<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:wfw="http://wellformedweb.org/CommentAPI/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:atom="http://www.w3.org/2005/Atom"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
 xmlns:georss="http://www.georss.org/georss"
 xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
 xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<atom:link href="joegame.xyz/rss.xml" rel="self" type="application/rss+xml" />
<title>joegame.xyz Posts</title>
<link>joegame.xyz</link>
<description><![CDATA[Writeups from Joegame studios.]]></description>
<language>en</language>
<lastBuildDate>Sun, 24 May 2026 20:12:52 -0600</lastBuildDate>
<generator>Emacs 30.2 org-publish-rss.el 0.8</generator>
<item>
<title>Porting joegame to Hoot (I)</title>
<link>joegame.xyz/blog/porting-joegame-hoot.html</link>
<pubDate>Sat, 16 May 2026 01:14:02 -0600</pubDate>
<guid>joegame.xyz/blog/porting-joegame-hoot.html</guid>
<description>
<![CDATA[<p>
This is an introduction to the ongoing efforts in the joegame universe.  Due to various budget cuts and red tape, development has been at a halt for the better part of the last year, but recently some funds have been released for completely rewriting joegame in Hoot, such that it can be deployed almost completely client side.  In this, it's probably best to start with a review of joegame as it stands.
</p>
<div id="outline-container-org7559e7a" class="outline-2">
<h2 id="org7559e7a"><span class="section-number-2">1.</span> Current joegame tile server and client</h2>
<div class="outline-text-2" id="text-1">
<p>
joegame has two high level components
</p>
<ul class="org-ul">
<li>A full world tile generator and server, written in Common Lisp and only tested with sbcl.</li>
<li>A javascript-based client which creates a seamless interface to explore the world.</li>
</ul>

<p>
The task we will be taking up for this series will concern mostly the first bit here.  Currently, image data is generated at the server and sent over to the client as needed. While, as we will see, there has been some effort taken to optimize the relevant endpoints here, much of the current stagnation in development rests on the unsustainability of the model as a whole.
</p>

<p>
We can cache images liberally, and optimize paths at the server level, but this doesn't escape the fact that the world we are sustaining is <b>big</b>.
</p>


<div id="orgd34f9bd" class="figure">
<p><img src="joegame.xyz/blog/../images/joegame-demo.gif" alt="Zooming out in joegame, currently." class="figure" />
</p>
<p><span class="figure-number">Figure 1: </span>Zooming out in joegame, currently.</p>
</div>

<p>
<i>"How big is it?"</i> First of all, as you can see above, we can distinguish a granular <i>tilemap</i> level from a <i>world</i> one. A tilemap is requested at a certain address: <code>"/worldmap/:x/:y/:file/:rank"</code> ; while at a world level we simply request "tiles" at x,y,z(oom) coordinates, <code>"/worldtile/:z/:x/:y"</code> . Tilemaps are a data structure which includes tile data and world features like trees and billboards.  Tiles are images, returned from the server as 256x256 <code>png</code> images, and coordinated into the grid at a client level. Between these two is a relatively hard seperation, like moving from the map to the "street view." In this, and as a general note of focus for now, we can say that we are consider only the server, and only the tile images returned from the <code>worldtile</code> endpoint which is used at our world layer.
</p>

<p>
World tiles are at least inspired from (what we understand) other "real" tile servers <a href="https:TODO">do</a>, where the <code>z</code> dimension scales things exponentially.
</p>

<div class="org-src-container">
<pre class="src src-lisp">(<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">world-tile</span> (x y z)
  (<span style="font-weight: bold;">declare</span> (type integer x y z))
  (<span style="font-weight: bold;">let*</span> ((tz (expt 2 z))
         (tz-scale (* 1/256 tz)))
    (<span style="font-weight: bold;">if</span> (&lt;= tz-scale 1)
        (worldconf:make-world-image-scaled worldconf:*worldconf* 256 256 tz-scale
                                           (* 256 (mod x tz))
                                           (* 256 (mod y tz)))
        *test-image*)))
</pre>
</div>

<p>
The "natural" scale for is is 1/256, so z=8 gives us a scale of one, and z=0 is 1/256.  At 0th zoom level, the entire world is represented as one 256x256 image, then 4, and so on, where zoom level 8 is a grid of 256x256 images.
</p>


<p>
In this, we can derive multiple answers to the "how big?" question.  First of all, while remaining at a world tile level, a fully zoomed in picture of the world would need each dimension to be <code>(2^8)*256</code>, or 65536 (2<sup>16</sup>) pixels big, that is, 256 pictures at 256 size.  But the total amount of pictures is a function of each zoom level's scale (256<sup>2</sup>)+(128)+&#x2026;+(A/n<sup>2</sup>)
</p>

<div class="org-src-container">
<pre class="src src-elisp">
(<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">bb/jgsize</span> (n)
  (+ (expt n 2)
     (<span style="font-weight: bold;">if</span> (not (eql n 1))
         (bb/jgsize (/ n 2))
       0)))

(<span style="font-weight: bold;">setq</span> bb-jgsize
      (bb/jgsize 256))

(format  <span style="font-style: italic;">"There are %d distinct 256x256 pictures, for a total of %d pixels squared that must be calculated to generate it all"</span> bb-jgsize (* bb-jgsize 256))
</pre>
</div>

<p>
There are 87,381 distinct 256x256 pictures, for a total of 22,369,536 pixels squared (roughly 500 trillion) that must be theoretically calculated to generate it all.
</p>

<p>
It should also be noted that the amount of compute required for each tile is not the same, the empty ocean is quicker to figure our than a busy land area.  But in general computation is evenly distributed across zoom levels.  We said earlier that the "natural" scale for us is 8 (1/256).  This means that the tiles for zoom levels above are generated by sampling the pixels returned at zoom level 8, where each pixel can be one to one:
</p>

<div class="org-src-container">
<pre class="src src-lisp">  (<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">get-top-color-sampled</span> (conf x y n amount)
    (<span style="font-weight: bold;">progn</span>
      (<span style="font-weight: bold;">let*</span> ((resolved
               (resolve-sampled-terrains conf x y n amount))
             (c (render:parse-rgb-color
                 (<span style="font-weight: bold;">if</span> resolved
                     (color (car (last resolved)))
                     #xeeeeee))))
        (list
         (getf c <span style="font-weight: bold;">:r</span>)
         (getf c <span style="font-weight: bold;">:g</span>)
         (getf c <span style="font-weight: bold;">:b</span>)))))

  ...

(<span style="font-weight: bold;">defmethod</span> <span style="font-weight: bold;">sample-val</span> ((v value) (p point) n amount)
  (<span style="font-weight: bold;">let</span>
      ((pointmin p)
       (pointmax (++p p n)))
    (<span style="font-weight: bold;">let</span> ((vals (map 'list #'(<span style="font-weight: bold;">lambda</span> (thisp) (get-val v thisp))
                     (get-random-points pointmin pointmax amount))))
      (mean vals))))

</pre>
</div>
</div>
</div>
<div id="outline-container-orge7b6d49" class="outline-2">
<h2 id="orge7b6d49"><span class="section-number-2">2.</span> What a world</h2>
<div class="outline-text-2" id="text-2">
<p>
Going back to our current project, we are aiming to reimplement everything needed to generate the world tile images.  Currently they are transported as png images, but really raw pixel data is what is most important, and in fact there is only so many colors we know, so even using png data and absolute colors is currently probably a big point of inefficiency.
</p>

<div class="org-src-container">
<pre class="src src-lisp">(setf *area-set*
       '((<span style="font-weight: bold;">:deep-ocean</span> . (<span style="font-weight: bold;">:name</span> <span style="font-style: italic;">"deep-ocean"</span>
                         <span style="font-weight: bold;">:color</span> <span style="font-style: italic;">"#265272"</span>
                         <span style="font-weight: bold;">:animals</span> (:|seaturtle|)
                         <span style="font-weight: bold;">:objects</span> ()
                         <span style="font-weight: bold;">:image</span> <span style="font-style: italic;">"images/terr_trench.png"</span>
                         <span style="font-weight: bold;">:wang-set</span> <span style="font-weight: bold;">:default</span>))

         (<span style="font-weight: bold;">:ocean</span> . (<span style="font-weight: bold;">:name</span> <span style="font-style: italic;">"ocean"</span>
                    <span style="font-weight: bold;">:color</span> <span style="font-style: italic;">"#4aa0df"</span>
                    <span style="font-weight: bold;">:animals</span> (:|seaturtle|)
                    <span style="font-weight: bold;">:image</span> <span style="font-style: italic;">"images/terr_ocean.png"</span>
                    <span style="font-weight: bold;">:wang-set</span> <span style="font-weight: bold;">:default</span>
                    <span style="font-weight: bold;">:objects</span> ()))


         <span style="font-weight: bold; font-style: italic;">;;  </span><span style="font-weight: bold; font-style: italic;">a lot more...
</span>
         (<span style="font-weight: bold;">:sand</span> . (<span style="font-weight: bold;">:name</span> <span style="font-style: italic;">"sand"</span>
                   <span style="font-weight: bold;">:color</span> <span style="font-style: italic;">"#ead2bd"</span>
                   <span style="font-weight: bold;">:image</span> <span style="font-style: italic;">"images/terr_sand.png"</span>
                   <span style="font-weight: bold;">:wang-set</span> <span style="font-weight: bold;">:default</span>)))))

</pre>
</div>

<p>
There is some other things here, but the important thing to remember is that each pixel of a tile corresponds to a color defined here. With this though we can't delay any longer the real meat of the thing here, which is how the world is defined such that we can place pixels where we want them.
</p>

<p>
Inspired by shader languages, the world can be considered always one pixel at a time.  We implement a very simple kind of DSL in lisp macros which creates a data structure that directs what to do to get pixels.
</p>

<p>
In a word, joegame is also <i>this</i> big:
</p>

<div class="org-src-container">
<pre class="src src-lisp">(<span style="font-weight: bold;">let</span> ((size (expt 2 16)))
  (setf *worldconf*
        (__ <span style="font-weight: bold;">:ocean</span>
            (&lt;&gt;

             (circle&amp;
              (circle&amp;
               (not-circle&amp;
                (in-circle&amp;
                 (perlin~ 0.000028 208 '())
                  )

                 (point (/ size 2) (/ size 2))
                 (* (/ size 2) 2/3) 1.2)
                (point (* size 1/3) (* size 2/3))
                (/ size 3) 0.5)
               (point (* size 1/3) (* size 3/4))
               (* size 1/5) 1.3)
              (point (* size 2/3) (* size 1/2))
              (* size 1/3) 0.6)

             0.0 (__ <span style="font-weight: bold;">:deep-ocean</span>)
             7/16 (__ <span style="font-weight: bold;">:ocean</span>)
             8/16 (0 (__ <span style="font-weight: bold;">:sand</span>)
                     1/64 ( 0.0 (__ <span style="font-weight: bold;">:grass</span>)
                                1/8 (__ <span style="font-weight: bold;">:dirt</span>
                                        (&lt;&gt; (lat&amp; (perlin~ 0.000128 218 '()) size )
                                            0.0 (&lt;&gt; (lon&amp; (perlin~ 0.000128 218 '()) size)
                                                    0.0 (&lt;&gt; (perlin~ 0.000128 108 '())
                                                            0.0 (__ <span style="font-weight: bold;">:grass</span>)
                                                            4/9 (__ <span style="font-weight: bold;">:forest</span>))

  <span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">etc etc ( about 14 lines abbreviated here for space)
</span>                                            (+ 3/5 1/32) (__ <span style="font-weight: bold;">:forest</span>)))))))))

</pre>
</div>

<p>
But in order to start unpacking this, we can look at a simpler example.
</p>

<div class="org-src-container">
<pre class="src src-lisp">
(in-circle&amp; <span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">a signal filter
</span> (filler~ '((1/2 (__ <span style="font-weight: bold;">:ocean</span>)) <span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">a "fill" (always 1) signal, with two terrain children
</span>             (1 (__ <span style="font-weight: bold;">:sand</span>))))
 '(<span style="font-weight: bold;">:x</span> 500 <span style="font-weight: bold;">:y</span> 500) <span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">the filters coordinate param
</span> 300) <span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">the filters radius param
</span>
</pre>
</div>

<p>
In our little language here, there are three kinds of entities: signals (for example <code>filler~</code>), terrains (sand and ocean here), and filters (<code>in-circle&amp;</code>).  Signals and terrains can have children, filters can have its "source" which is a signal or another filter.  The basic procedure is as follows:
</p>

<ol class="org-ol">
<li>Enter at the top level.</li>
<li>If the current entity is a terrain, add it to the current stack</li>
<li>If the current entity has no children, return the stack.</li>
<li>If the current entity is a terrain, add it to the stack and move to step 5. If a signal, move to step 6.</li>
<li>Iterate through each child of the terrain, making it the current entity and moving to step 2.  Return the resulting stack.</li>
<li>Get the value of the signal at the current x and y coordinates and use it to pick a child.  A signal's value is always between 0.0-1.0 inclusive, and the value is mapped to the child based on its offset number.  Make the decided upon child the current entity and move back to step 2.</li>
</ol>

<p>
In the above example, we have only one level to consider, we query the signal and return a stack with a single <code>:ocean</code> or <code>:sand</code> back.  The filler always returns 1, but then we check if the coordinate in question is in the circle with a center at 500x500 and a radius of 300.  If it is, the final value is a 1 and we get the highest child (sand), if it isn't the final value is "filtered out" and we get back 0.
</p>

<p>
In practice, we want some layering of the world.  Grass grows ontop of soil, the shore springs out of the depths.  This explains the rule around terrains having children, because otherwise terrains would always be leafs, and stacks would always be 1.  In this way, we make things like this:
</p>

<div class="org-src-container">
<pre class="src src-lisp">(__ <span style="font-weight: bold;">:deep-ocean</span>
    (perlin~ 102 0.3
             '((0.0 nil)
               (0.2 (__ <span style="font-weight: bold;">:ocean</span>)
                (0.7 (__ <span style="font-weight: bold;">:shore</span>
                      (perlin~ 123 0.8
                       '((0.3 (__ <span style="font-weight: bold;">:grass</span>))
                         (1.0 (__ <span style="font-weight: bold;">:sand</span>)))))))))

    (resolve-terrains *world* 123 123) <span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">-&gt; (:deep-ocean :shore :grass)
</span>
</pre>
</div>

<p>
There is always deep ocean, if the first signal is over 0.2 its also regular ocean, if &gt; 0.7, we add the shore and then see if there is grass or sand on it.
</p>

<p>
Finally, because we are only considered for now with our world tiles, we are not actually concerned about the full stack, only the "last" terrain (which above would be either deep-ocean, ocean, grass, or sand).
</p>

<p>
And that is pretty much it! We should have at least everything we need to get hootin.  We need to recreate
</p>
</div>
</div>
<div id="outline-container-orgce8089a" class="outline-2">
<h2 id="orgce8089a"><span class="section-number-2">3.</span> hoot dev log</h2>
<div class="outline-text-2" id="text-3">
<p>
To be continued&#x2026;
</p>
<div class="org-src-container">
<pre class="src src-bash">guix shell guile-next guile-hoot
</pre>
</div>
</div>
</div>
]]>
</description></item>
<item>
<title>Joegame does the Spring Lisp Game Jam 2026</title>
<link>joegame.xyz/blog/spring-lisp-game-jam-2026.html</link>
<pubDate>Sun, 24 May 2026 20:12:48 -0600</pubDate>
<guid>joegame.xyz/blog/spring-lisp-game-jam-2026.html</guid>
<description>
<![CDATA[<p>
As we are hard at work on <i>the next big thing</i>, Joegame studios thought it wise to do a little bit of professional development and take part in our first ever "game jam."  For those who don't know, a game jam is when actual pieces of fruit are used, as opposed to a <i>game jelly</i>, which just uses juice, and has a smoother, thinner texture.
</p>

<p>
The jam we are taking part in is the <a href="https://itch.io/jam/spring-lisp-game-jam-2026">Spring Lisp Game Jam 2026</a>.  The forthcoming Solitaire RPG epic from Joegame studios has us working in the static, compiled world of <a href="https://ziglang.org/">zig</a>, which has been great, but taking a break to come back to our old friend in lisp languages.  While there are already <a href="joegame.xyz/blog/porting-joegame-hoot.html">plans</a> here at joegame to work with <a href="https://spritely.institute/hoot/">Hoot</a>, which appears to be a kind of sponsor of the jam itself, what is more on our mind at the moment is lua, so we decided to go with <a href="https://fennel-lang.org/">fennel</a> and <a href="https://love2d.org/">love2d</a>, and specifically this lovely <a href="https://itch.io/jam/love2d-jam-2026/topic/6082771/how-to-get-started-with-love2d-and-fennel">template</a>.
</p>

<p>
What follows aims to be some pretty extensive rubber ducking of the whole process.
</p>
<div id="outline-container-orgdf66080" class="outline-2">
<h2 id="orgdf66080"><span class="section-number-2">1.</span> Day 1</h2>
<div class="outline-text-2" id="text-1">
<p>
Our addition to the template is just to assure our dependencies through a simple nix flake:
</p>

<div class="org-src-container">
<pre class="src src-nix">{
  description = "slotaire";

  inputs = {
    nixpkgs.url =
      "github:NixOS/nixpkgs/fad271db9413e9ea187306aa67b26405a818449d";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let pkgs = nixpkgs.legacyPackages.${system};
      in {
        devShells.default = pkgs.mkShell {

          buildInputs = with pkgs; [
            love
            (lua.withPackages (l: with l; [ busted love fennel ]))
            fennel-ls
            fnlfmt
            # just in case we are looking at lua libs
            emmylua-ls
          ];

        };
      });
}
</pre>
</div>

<p>
And then per the instructions for fennel-ls, download the love docset and add a flsproject.fnl file:
</p>

<div class="org-src-container">
<pre class="src src-fennel">{:fennel-path "./?.fnl;./?/init.fnl;"
 :lua-version "lua5.1"
 :libraries {:love2d true}
 :extra-globals "love.handlers pp"
 }
</pre>
</div>

<p>
Because I hate prefix arguments, I set the dir local for the project to default to love when running <code>fennel-repl</code>:
</p>

<div class="org-src-container">
<pre class="src src-elisp"><span style="font-weight: bold; font-style: italic;">;;; </span><span style="font-weight: bold; font-style: italic;">Directory Local Variables            -*- no-byte-compile: t -*-
</span><span style="font-weight: bold; font-style: italic;">;;; </span><span style="font-weight: bold; font-style: italic;">For more information see (info "(emacs) Directory Variables")
</span>
((fennel-mode . ((fennel-program . <span style="font-style: italic;">"love ."</span>))))
</pre>
</div>

<p>
&#x2026; and we are off to the races!
</p>


<div id="orgf40b1d1" class="figure">
<p><img src="joegame.xyz/blog/../images/love-fennel-setup.png" alt="Love,emacs,fennel all set up" class="figure" />
</p>
</div>
</div>
<div id="outline-container-org04bc563" class="outline-3">
<h3 id="org04bc563"><span class="section-number-3">1.1.</span> What's the game?</h3>
<div class="outline-text-3" id="text-1-1">
<p>
I have been in deep meditation on solitaire.  This comes from a larger project for joegame, which will be announced soon.  On perusing the various pieces of literature on the subject (directed by the wonderful <a href="https://www.solitairelaboratory.com/biblio/SolitaireBibliography.html">resources</a> at Solitaire Labratory), one particularly caught my eye, even though it is not applicable to the aforementioned project.  The book <a href="https://chambers.co.uk/book/chambers-card-games-one/">Chambers Card Games for One</a> introduces the game "Accordion" like so:
</p>

<blockquote>
<p>
Accordion is the simplest of all patience games, so simple that it probably wasn’t invented consciously but just evolved, or —- more accurately — just happened. It has acquired the name Accordion because it takes place in one line of cards that during the game tends to get longer and shorter, rather like the way an accordion does when it is being played.
</p>
</blockquote>

<p>
Perhaps the biggest reason why I became attracted to the game is specifically because it requires no set up playing by hand.  You have a deck, you start playing.  In this, it becomes an ideal idle activity: sitting on the couch, I have the deck in my hands, I can just start to do it.  There are two possible moves: place a card down from the deck and increasing the size of the stack, or moving an existing card to an appropriate spot. Chambers describes the valid moves of the second type like so: "A card that is played to the right of a card that it matches in either suit or rank can be packed upon it. Similarly, if a card matches in suit or rank a card third to its left, it can be packed upon it (ie the card will have to jump over two other
cards)" (3).  These are the only two moves, but one move may lead to another. As you place cards with these moves, cards
</p>

<p>
For our purposes now we will define some terms: a "stack" is a pile of cards, whose valid moves are determined by the top card; the "line" is the line of card stacks we are adding to our manipulating; a "deal" is when a card is drawn and pushed onto the line, creating a new stack of one card; a "move" is moving one stack ontop of the other.
</p>

<p>
Now, already I would argue that while we are just reading from a book, this is a worthwhile game to try and make video.  But there is something that has come organically out of pen and paper iterations of Accordion.  In the real world, you only have so much space to play, so as you add cards to the right, increasing the line, you eventually have to continue the line somewhere else.  This organically starts to make a grid of cards.  Chambers indeed notes this point: "If the line gets so long that there is no space for further cards then a second line is started below the first, but the two lines <i>must be considered as one continuous line</i>" (ibid. emphasis mine).
</p>

<p>
In this, with a flash of inspiration, our whole pitch for the game becomes this: the solitaire game of Accordion, except played on an explicit grid, where vertical moves are available; plus, time permitting, creating roguelike/balatro elements where there is scoring/combos and power up items like, e.g., "clear a column", "delete a card".  We shall call <i>gridthuselah</i>, as another name for Accordion (according to Chambers) is <a href="https://en.wikipedia.org/wiki/Methuselah">Methuselah</a>.
</p>


<div id="orge863256" class="figure">
<p><img src="joegame.xyz/blog/../images/HarrowingBermejo.jpg" alt="&quot;By Bartolomé Bermejo - Source: Web Gallery of art http://www.kfki.hu/~arthp/html/b/bermejo/index.html, Public Domain, https://commons.wikimedia.org/w/index.php?curid=3170425&quot;" class="figure" />
</p>
<p><span class="figure-number">Figure 1: </span>By Bartolomé Bermejo - Source: Web Gallery of art <a href="http://www.kfki.hu/~arthp/html/b/bermejo/index.html">http://www.kfki.hu/~arthp/html/b/bermejo/index.html</a>, Public Domain, <a href="https://commons.wikimedia.org/w/index.php?curid=3170425">https://commons.wikimedia.org/w/index.php?curid=3170425</a></p>
</div>
</div>
</div>
<div id="outline-container-org57024ff" class="outline-3">
<h3 id="org57024ff"><span class="section-number-3">1.2.</span> Getting something on paper</h3>
<div class="outline-text-3" id="text-1-2">
<p>
We will be happy today if we can render a grid of cards, and perhaps have some minimal kind of interactivity.  Following the structure of our inherited template, I will make a "game scene". But first, I need something to draw.  I will take <a href="https://elvgames.itch.io/playing-cards-pixelart-asset-pack">this lovely asset</a> Elv Games which I have used before, and set up some scaffolding to draw arbritrary cards (note, I have done a lot of this logic before in vanilla lua, so this work was more me transliterating it to fennel).
</p>

<div class="org-src-container">
<pre class="src src-fennel" id="org944b8c9">(local u (require :utils))

(local image-path "elv_Playing_Cards.png")
(fn load-asset []
  (love.graphics.newImage image-path))

(local pad {:x 12 :y 15})
(local dimensions {:width 40 :height 66})
(local image-dimensions {:width 832 :height 576})

(fn make-quad-row [row-num]
  "row num arg is 0-indexed!"
  (icollect [_ col-num (ipairs (u.make-range 0 12))]
    (love.graphics.newQuad
     ;; x
     (+
      pad.x
      (* col-num dimensions.width)
      (* col-num pad.x 2))
     ;; y
     (+
      pad.y
      (* row-num dimensions.height)
      (* row-num pad.y 2))
     dimensions.width
     dimensions.height
     image-dimensions.width
     image-dimensions.height)))



(fn make-raw-quads []
  (icollect [_ row-num (ipairs (u.make-range 0 5))]
    (make-quad-row row-num)))

(local all-quads (make-raw-quads))

;; elv asset row order is heart, spade, club, diamond
;; our convention is heart, diamond, club, spade

(local card-quads (u.flatten [(. all-quads 1)
                    (. all-quads 4)
                    (. all-quads 3)
                    (. all-quads 2)]))

(local back-quad (. all-quads 6 1))

{
 : load-asset
 : card-quads
 : back-quad
 }

</pre>
</div>

<p>
Our convention going forward is this: every card in a 52 card deck has an integer ID derived from a deck in <i>our</i> particular order (that is, not <i>NDO</i>), hearts (A-K), diamonds, clubs, spades. These ids are called <code>cid</code>, and given our convention we can make some helper functions already:
</p>

<div class="org-src-container">
<pre class="src src-fennel">(local card-suits {:hearts 1 :diamonds 2 :clubs 3 :spades 4})
(local card-ranks {:ace 1 :two 2 :three 3 :four 4 :five 5 :six 6 :seven 7 :eight 8 :nine 9 :ten 10 :jack 11 :queen 12 :king 13})
(local card-suits-amount (length (u.tkeys card-suits)))
(local card-ranks-amount (length (u.tkeys card-ranks)))

(fn to-cid [rank suit]
  (+ (. card-ranks rank)
     (* card-ranks-amount (- (. card-suits suit) 1))))

(fn card-suit [cid]
  (. (u.tkeys card-suits)
     (+ (if (= (math.fmod cid card-ranks-amount) 0) 0 1)
        (math.floor (/ cid card-ranks-amount)))))

(fn card-rank [cid]
  (let [raw-mod (math.fmod cid card-ranks-amount)]
  (. (u.tkeys card-ranks)
     (if (= raw-mod 0) card-ranks-amount raw-mod))))
</pre>
</div>

<p>
Oh.. I missed lisp. I try not to be a big complainer about things made by very smart people, always chalking it up to my own inability to understand something, but here, to me, shows a few places where 0-indexing would produce something even cleaner, basically anyplace where math determines an index we then need to look up.  We should note also that we have our first of realistically many bits of dreaded <i>premature optimization</i> here: settings things up such that decks might be non-standard by having the helper functions refer to our global enum thingys for suit/rank, even though our asset hard codes a standard 52 card deck.
</p>
</div>
</div>
<div id="outline-container-org3425c22" class="outline-3">
<h3 id="org3425c22"><span class="section-number-3">1.3.</span> First bit of a game</h3>
<div class="outline-text-3" id="text-1-3">
<p>
Based on our working model so far, we can represent much of our game by a few simple data structure: our <code>line</code> of <code>stacks</code>. There also needs to be some kind of <code>deck</code>, which is essentially a stack <i>not</i> on the line, prepopulated with cards.  An early POC could be our grid and ability to move stacks ontop of each other. In this, we need some kind of interface to move among the stacks.  Solitaire is usually pretty mouse centric&#x2026; but for now we are going to use a keyboard driven mechanic, so we will need to keep track of a <code>target-cursor</code> and <code>source-cursor</code>.
</p>

<div class="org-src-container">
<pre class="src src-fennel">(local *game-line* (make-line))
(local *deck* (u.knuth-shuffle (u.make-range 1 52)))
(local *source-cursor* {:x 1 :y 1})
(local *target-cursor* {:x 1 :y 1})
</pre>
</div>

<p>
The way I have learned to think about video game software, which like most things for me has just been felt out over the years, is to create a pretty strong seperation between the "game" (state and possible manipulations of state) and everything else (view and ui/interaction).  In a way, it's just <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">model-view-controller</a>.  But the important thing here is simply the idea that there should be portion of your code that is as decoupled as possible from the framework and precise visual representation of the game, which exposes some kind of interface.  Then another part of your program is something that reads the state and shows it, as well as captures input and decides if that will manipulate the state.
</p>

<p>
So, we have our state.  What is our interface for it? Well, we need to be able to <code>deal</code> from the <code>*deck*</code>, we need to be able to set the source and target cursors, we need to be able to merge stacks, pushing cards over on the line in consequence.  Probably tonight we can get the first two..
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn deal [line deck]
  (let [next-pos (next-empty-stack-pos line)]
    (if next-pos
        (tset line
              next-pos.y
              next-pos.x
              (+ 1 (length (. line next-pos.y next-pos.x)))
              ;; val
              (table.remove deck))
        false)))
(fn move-cursor-down [cursor ?n]
  (set (. cursor :y) (math.min grid-info.height (+ (. cursor :y) (or ?n 1)))))
(fn move-cursor-up [cursor ?n]
  (set (. cursor :y) (math.max 1 (- (. cursor :y) (or ?n 1)))))

(fn move-cursor-right [cursor ?n]
  (set (. cursor :x) (math.min grid-info.width (+ (. cursor :x) (or ?n 1)))))
(fn move-cursor-left [cursor ?n]
  (set (. cursor :x) (math.max 1 (- (. cursor :x) (or ?n 1)))))

</pre>
</div>

<p>
Further, on the other end of our mental model, we need some "draw" functions for our state.  Or we wouldn't be able to see anything!
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn draw-grid [line]
  (for [y 1 grid-info.height 1]
    (for [x 1 grid-info.width]
      (let [this-stack (. line y x)]
        (if (stack-emptyp this-stack)
            (cards.drawVEmpty state (get-grid-pos x y))
            (cards.drawV state (top this-stack) (get-grid-pos x y)))))))

(local cursor-pad 5)
(fn draw-cursor [pos ?color]
  (let [cpos (get-grid-pos pos.x pos.y)
        [r g b] (or ?color [0 0 1])]
    (love.graphics.setColor r g b)
    (love.graphics.rectangle "fill" (- cpos.x cursor-pad) (- cpos.y cursor-pad)
                           (+ (* cards.default-scale cards.dimensions.width)
                              (* cursor-pad 2))
                           (+ (* cards.default-scale cards.dimensions.height)
                              (* cursor-pad 2)))))

</pre>
</div>

<p>
Thinking it like this, suddenly everything comes together at the very end:
</p>

<div class="org-src-container">
<pre class="src src-fennel">{:activate (fn activate [])
 :enter (fn enter [])
 :leave (fn leave [])
 :draw (fn draw [message]
         (draw-cursor *source-cursor*)
         (draw-cursor *target-cursor* [0 1 0])
         (draw-grid *game-line*))
 :update (fn update [dt set-mode])
 :keyreleased (fn keyreleased [key _ _]
                (if (= key "d")
                    (deal *game-line* *deck*))
                (when (= key "space")
                  (set *source-cursor*.x *target-cursor*.x)
                  (set *source-cursor*.y *target-cursor*.y))
                (if
                 (= key "down") (move-cursor-down *target-cursor*)
                 (= key "up") (move-cursor-up *target-cursor*)
                 (= key "right") (move-cursor-right *target-cursor*)
                 (= key "left") (move-cursor-left *target-cursor*)))}

</pre>
</div>

<p>
We have our <code>*state*</code>, our various interfaces into it (<code>deal</code>, <code>move-cursor-..</code>), and we draw it.  Seems alright for day 1!
</p>



<div id="org6479051" class="figure">
<p><img src="joegame.xyz/blog/../images/slgj-day1-end.png" alt="The game at the end of day 1. The source cursor is blue and the target one is green" class="figure" />
</p>
<p><span class="figure-number">Figure 2: </span>The game at the end of day 1. The source cursor is blue and the target one is green</p>
</div>
</div>
</div>
</div>
<div id="outline-container-orgdb9ad58" class="outline-2">
<h2 id="orgdb9ad58"><span class="section-number-2">2.</span> Day 2-3</h2>
<div class="outline-text-2" id="text-2">
<p>
Busy&#x2026;
</p>
</div>
</div>
<div id="outline-container-orgc9dc678" class="outline-2">
<h2 id="orgc9dc678"><span class="section-number-2">3.</span> Day 4</h2>
<div class="outline-text-2" id="text-3">
<p>
Ok following from where we left off, the next step is allowing the user to move stacks around.  I already know this is going to immediately launch us into a bulk of the complexity, even given that I am choosing to start with <i>no rules</i>.  What we want to get done is this (still kinda abbreviated day): the user can move any stack to any other stack <i>and</i> when spaces are made, cards will fill in from the bottom
</p>

<div class="org-src-container">
<pre class="src src-nil">;; one move

      v--------&lt;
1. A--B--C--D--E--F

2. A--E--C--D-- --F

3  A--E--C--D--F

</pre>
</div>

<p>
Visualizing what we want here, I want to notice two things: what is originally the <code>B</code> stack in time 1, becomes a stack with two cards, <code>E</code> ontop of <code>B</code>, and its probably a good idea to track this, rather than just deleting the <code>B</code>; there is a difference between 2 and 3, but not because of user input.  It <i>could</i> be the case that we start with 1 and move directly on to 3, where the stack combination and filling in are one move, but I have this intuition that we should consider the filling in as a kind of move.  Not only will this make it easier, I think, to eventually animate these card movements, making what happens at each step clear, but it means that the filling in behavior itself needs to be parameterized in a way, a kind of rule to follow that we could eventually decide to to play with.  What if.. things only fill within a row for example? Or there was a kind of time freeze mode where a user can make a column move in the hole left from the last move?  This is either way an important fork in the road: the time cost here is, er, pretty critical because its like a game jam and we did kinda miss 1/5 of it this weekend (although I thought about it a lot!).  But either way, I just have this sense that doing it the harder way will pay off here.
</p>

<p>
So, mr rubber duck, what is next?  We already have our cursors, and I also was thinking about the cursors. Or the whole source/target cursor thing.  If we had just a dpad and a single button, what would we do? Lets instead imagine there is just <i>one</i> cursor, and the idea of a selected stack.  If the user presses the button, we check if a stack is already selected; if a stack is, and it is not currently where the cursor is, then move the selected stack ontop of the cursor; if there is not a selected stack, select the stack under cursor; if the stack selected and the cursor are the same, deselect the stack.  Make sense? does to me, more intuitive than it sounds I think but we will see!
</p>

<p>
This is what we will get done today.
</p>
</div>
</div>
<div id="outline-container-orgeb49910" class="outline-2">
<h2 id="orgeb49910"><span class="section-number-2">4.</span> Day 5</h2>
<div class="outline-text-2" id="text-4">
<p>
OK feelin the pressure now, its halway and we have next to nothing!  To update, all the things discussed yesterday were seen to, left today with at first finishing up mouse controls, using the same "one button" DWIM approach. Does one discuss DWIM for video games?
</p>
</div>
<div id="outline-container-org38e98fc" class="outline-3">
<h3 id="org38e98fc"><span class="section-number-3">4.1.</span> A note on conventions</h3>
<div class="outline-text-3" id="text-4-1">
<div class="org-src-container">
<pre class="src src-fennel">;; game actions, closely tied to user input and the ongoing progression of the game are `functions!`:

(fn deal! [line deck]
  (let [next-pos (next-empty-stack-pos line)]
    (if next-pos
        (tset line
              next-pos.y
              next-pos.x
              (+ 1 (length (. line next-pos.y next-pos.x)))
              ;; val
              (table.remove deck))
        false)))

(fn combine-stacks! [line source target]
  ...)

(fn move-cursor-down! [cursor ?n]
  ...)
;; etc

;; game state itself is formatted with %, `%variable`
(local %game-state {
                    :line (make-line)
                    :counters (make-grid {:fill-in-wait 0.0})
                    :deck (u.knuth-shuffle (u.make-range 1 52))
                    :source-cursor {:x 0 :y 0}
                    :target-cursor {:x 1 :y 1}
                    })

;; global constants are like `*var`
(local *grid-info {:width 5 :height 5 :pad {:x 10 :y 5}})

</pre>
</div>

<p>
I am not sure what's more fennel idiomatic.  The reason I didn't just go with full on common lisp patterns like <code>*constant*</code>, <code>+variable+</code> is because fennel allows for dot access and something like <code>*constant*.field</code> looks odd (but seems to be valid fennel).
</p>
</div>
</div>
<div id="outline-container-org63620f9" class="outline-3">
<h3 id="org63620f9"><span class="section-number-3">4.2.</span> dwim</h3>
<div class="outline-text-3" id="text-4-2">
<p>
Following through with the reflection on controls, we have a game action like so:
</p>
<div class="org-src-container">
<pre class="src src-fennel">(fn select-or-move! [line source target]
  (when *settings.debug-print
    (print (: "source %d,%d, target %d,%d, deselected %s"
              :format source.x source.y target.x target.y (if (cursor-deselected-p source) "true" "false"))))
  (if (cursor-deselected-p source)
      (do
        (set source.x target.x)
        (set source.y target.y))
      (do
        (combine-stacks! line source target)
        (deselect-cursor! source))))

</pre>
</div>

<p>
That is, if nothing is selected, select (think "set as source cursor"); if source cursor is around, make the move and deselect.
</p>
</div>
</div>
<div id="outline-container-org632e052" class="outline-3">
<h3 id="org632e052"><span class="section-number-3">4.3.</span> rules</h3>
<div class="outline-text-3" id="text-4-3">
<p>
Ok, so we are at a good point, new things can come quickly now.  <i>Now</i> we should make only valid moves playable.  A move is made by referencing a line object (a 2d array of stacks) source and target cursor positions (positions into the line object).  Given this information, we should be able to create something that checks for a moves validity.  <a href="#org57024ff">As discussed</a>, cards are represented by integer ids, given a deck with a certain overall order (in rank and suit). We already have those helper functions made, so as specified in Accordion's rules, the two things that make a move valid is the two cards rank/suit, and their relative positions.  Both should be straightforward, but we should treat them as separate rules and then compose:
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn position-right [{: x : y}]
  (if (= x *grid-info.width)
      {:x 1 :y (+ 1 y)}
      {:x (+ 1 x) : y}))
(fn position-right-n [pos n]
  (if (= n 0)
      pos
      (position-right-n (position-right pos) (- n 1))))

(fn position-left [{: x : y}]
  (if (= x 1)
      {:x 5 :y (- y 1)}
      {:x (- x 1) : y}))

(fn position-left-n [pos n]
  (if (= n 0)
      pos
      (position-left-n (position-left pos) (- n 1))))

;; game rules
(local *rules  {
                :valid-cards (fn [line source target]
                               (let [source-card (top (. line source.y source.x))
                                     target-card (top (. line target.y target.x))]
                                 (and
                                  source-card
                                  target-card
                                  (or
                                   (=
                                    (cards.card-rank source-card)
                                    (cards.card-rank target-card))
                                   (=
                                    (cards.card-suit source-card)
                                    (cards.card-suit target-card))))))
                :valid-positions (fn [_ source target]
                                   (or
                                    (u.v= target (position-left-n source 1))
                                    (u.v= target (position-left-n source 3))))
                })


</pre>
</div>

<p>
Ok, we still do not have our one little innovation here, but this completes implementing the original rules of accordion: same suit or rank, either one to the left, or three (adjacent cards, or cards separated by two).  Importantly, the grid is both a continuous line to us and a grid, which is why we need our special <code>position-left/right</code>.  <code>position-up</code> is even easier:
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn position-up [{: x : y}]
  {: x :y (- y 1)})
(fn position-up-n [pos n]
  (if (= n 0)
      pos
      (position-up-n (position-up pos) (- n 1))))

;; then add to the rule
{
 ;; ...
 :valid-positions (fn [_ source target]
                    (or
                     (u.v= target (position-left-n source 1))
                     (u.v= target (position-left-n source 3))
                     (u.v= target (position-up-n source 1)))) ;; here
 ;; ..
 }
</pre>
</div>

<p>
To round this up we need a win state I guess, or rather, just game end situation.  The game ends when there are no more moves left, which means the deck needs to be empty and there are no possible moves left.  The last bit seems a little tricky&#x2026; but I think it will be fine to just brute force it and check for every possible valid move. Assuming we can skip self stack moves, that means (* 24 25) at most.  Which is fine.
</p>
</div>
</div>
</div>
<div id="outline-container-orge4ec2d8" class="outline-2">
<h2 id="orge4ec2d8"><span class="section-number-2">5.</span> Day 6-7</h2>
<div class="outline-text-2" id="text-5">
</div>
<div id="outline-container-org2b95a2a" class="outline-3">
<h3 id="org2b95a2a"><span class="section-number-3">5.1.</span> Polish</h3>
<div class="outline-text-3" id="text-5-1">
<blockquote>
<p>
Polish is any effect that creates artificial cues about the physical
properties of objects through interaction. In this case, artificial
means “not simulated.” When two objects collide and the code tells
them that they’re each solid and so should rebound with a certain
force in a certain direction, this is not polish. This is part of the
simulation, part of the game’s response to input. Instead of
“artificial,” the terms “nonessential” or “layered on” could also be
used. &#x2013; Swink, <i><a href="http://www.game-feel.com/">Game Feel: A Game Designer's Guide to Virtual Sensation</a></i>, Chapter 9
</p>
</blockquote>

<p>
Looking through this book, it's clear the author would not consider <i>Gridthuselah</i> a game which should worry much about "feel," but either way, I am interested in this divide between the simulation and the polish, the essential and the nonessential.  What is "essential" in a video game, why would you ever include anything that <i>isn't</i> essential?  It is the kind of question that is easy for other kinds of "games."  For the author of <i>Game Feel</i> (Steve Swink), games have feel only when they have "real time control" in some kind of "simulated space," so the stuff that is "nonessential" becomes everything that doesn't contribute to that.
</p>

<p>
Does classic Windows Solitaire/Klondike have game feel?  The game
purports to be a simulation of the world, your cursor is a hand, picking up and dropping cards onto stacks, time moves in <i>real</i> time, as it tells how long the game was in minutes and seconds at the end&#x2026; Still, according to the framework of <i>Game Feel</i>, real time control seems only to exist where there is an "ongoing correction cycle" (Chapter 2) of the player/input to the action on the screen. Asteroids has real time control, but Guitar Hero does not: "the whole loop of input and response happens in less than 100 ms, but once it’s done it’s done. There is no continuous flow of input and response, no correction cycle" (Chapter 4).  What Guitar Hero does definitely have is polish, it is noted though.
</p>

<p>
Not to get too hung up on this, <i>Game Feel</i> is quite open about its somewhat narrow definition and system it sets up.  The reason I am thinking about it is that this is where we are at with our little game jam game here that we are still unsure we will be able to finish.  By shamelessly borrowing some rules from an old solitaire book, we have (purposefully) made everything that isn't polish quite easy for ourselves.  But now that we 3/4 of the way through, the continual problem of what to prioritize gains a lot more traction.  And here I am reading books.
</p>

<p>
What are we polishing?
</p>


<div id="org71a1802" class="figure">
<p><img src="joegame.xyz/blog/../images/day6-lispgamejam.gif" alt="The game as it stands as a blurry gif.  While cards 'fill in' in a kind of interactive, 'real time' way, everything else is discrete, cards appear and disappear" class="figure" />
</p>
<p><span class="figure-number">Figure 3: </span>The game as it stands as a blurry gif.  While cards 'fill in' in a kind of interactive, 'real time' way, everything else is discrete, cards appear and disappear</p>
</div>

<p>
I think.. our filling-in intuition was good.  It is already barely understandable what is going on when a stack on the line is left empty and cards start to cascade back/to-the-left to fill in, but making it not immediate helps, and also already suggests our next move: cards should not jump from discrete spots, they should move/float to them.  I believe we glossed over the actual implementation of this before, better look at it now.
</p>

<p>
Following a kind of hybrid "structure-of-arrays" situation, we store values for each stack on the line in a separate table, where the <code>:counters</code> table here matches up exactly with the <code>:line</code> one.
</p>


<div class="org-src-container">
<pre class="src src-fennel">(local %game-state {
                    :line (make-line)
                    :counters (make-grid {:fill-in-wait 0.0 ;; here
                                          :target-pop 0.0
                                          })
                    :deck (u.knuth-shuffle (u.make-range 1 52))
                    :source-cursor {:x 0 :y 0}
                    :target-cursor {:x 1 :y 1}
                    :active-rules [:valid-cards :valid-positions]
                    :game-done false
                    })
</pre>
</div>

<p>
With just this simple idea, we can control any arbritrary thing that might deal with a given stack across time.  So, to implement the delay of filling in, we are always checking if something <i>should</i> be filled in, and if a delay is already not in progress, one is set.  At the same time, any delay in progress (any stack with <code>:fill-in-wait &gt; 0</code>) is updated by decrementing that value by <code>dt</code>.
</p>

<div class="org-src-container">
<pre class="src src-fennel">{
:update (fn [dt _set-mode]
          (iter-grid %game-state.counters
                     (fn [val]
                       (let [{: x : y : it} val]
                         (if
                          ;; fill in wait check
                          (&gt; it.fill-in-wait 0)
                          (let [new-val (- it.fill-in-wait dt)]
                            ;; decrement by new-val
                            (tset %game-state.counters y x :fill-in-wait (math.max 0 new-val))
                            ;; the wait is over
                            (when (&lt; new-val 0)
                              (combine-stacks! %game-state.line (position-right val) val)
                              (check-finish-game! %game-state)))

                          ;; check fill in
                          (and
                           (should-fill-in-p %game-state.line val)
                           (&lt;= it.fill-in-wait 0))
                          (tset %game-state.counters y x :fill-in-wait (u.bpm-secs 150))))))))
}

</pre>
</div>

<p>
The plan of attack here is simple (I think).  The same value we are using to simply delay the call to <code>combine-stacks!</code> can become the progress of the card the next stack over moving to this space.  This will clearly play out in <code>draw</code>, which right now displays cards only based on the <code>line</code> state.
</p>

<div class="org-src-container">
<pre class="src src-fennel"> (fn get-grid-pos [x y]
"Given grid position, return coordinates of that card"
{:x (+ *grid-info.pad.x (* cards.dimensions.width cards.default-scale (- x 1))
       (* *grid-info.pad.x x 2))
 :y (+ *grid-info.pad.y
       (* cards.dimensions.height cards.default-scale (- y 1))
       (* *grid-info.pad.y y 2))})


 (fn draw-grid [line]
   (for [y 1 *grid-info.height 1]
     (for [x 1 *grid-info.width]
       (let [this-stack (. line y x)]
         (if (stack-emptyp this-stack)
             (cards.drawVEmpty state (get-grid-pos x y))
             (cards.drawV state (top this-stack) (get-grid-pos x y)))))))


</pre>
</div>

<p>
<code>draw-grid</code> needs to know about <code>:fill-in-wait</code>, but in fact that value for the stack to the "left" of it.  Then its just about interpolating between the two positions using the value of <code>wait/wait-total-duration</code>.
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn draw-grid [game-state]
  (for [y 1 *grid-info.height 1]
    (for [x 1 *grid-info.width]
      (let [this-stack (. game-state.line y x)
            this-pos (get-grid-pos x y)]
        (cards.drawVEmpty %state this-pos)
        (if (not (stack-emptyp this-stack))
            (let [pos-left (position-left-n {: x : y} 1)
                  neighbor-fill-in-wait (and pos-left (. game-state :counters pos-left.y pos-left.x :fill-in-wait))]
              ;; for filling in movement
              (if (and neighbor-fill-in-wait (&gt; neighbor-fill-in-wait 0))
                  (cards.drawV %state (top this-stack) (u.v-lerp  (get-grid-pos pos-left.x pos-left.y) this-pos (/ neighbor-fill-in-wait *settings.fill-in-duration)))
                  (cards.drawV %state (top this-stack) (get-grid-pos x y)))))))))
</pre>
</div>

<p>
Just like that, it all works:
</p>



<div id="orgd21407c" class="figure">
<p><img src="joegame.xyz/blog/../images/lispgamejam-basic-fill-in.gif" alt="Basic fill in implemented." class="figure" />
</p>
<p><span class="figure-number">Figure 4: </span>Basic fill in implemented.</p>
</div>
</div>
</div>
</div>
<div id="outline-container-org444a91e" class="outline-2">
<h2 id="org444a91e"><span class="section-number-2">6.</span> Day 8</h2>
<div class="outline-text-2" id="text-6">
</div>
<div id="outline-container-org8064a38" class="outline-3">
<h3 id="org8064a38"><span class="section-number-3">6.1.</span> springs</h3>
<div class="outline-text-3" id="text-6-1">
<p>
We can do better.
</p>

<p>
Our basic vector2 lerp looks like this (relying on the <a href="https://github.com/rxi/lume">lume library</a> that came with our love2d+fennel template):
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn v-lerp [a b amount]
  {:x (lume.lerp a.x b.x amount)
   :y (lume.lerp a.y b.y amount)})
</pre>
</div>

<p>
Now, <code>amount</code> for us is linear right now, it changes at the rate of frame times, but I know (just because I have done stuff like this before), we can get big "polish" gains by messing with the rate of change proportional to its progress.  I first learned about this as a frontend web developer working with libraries like <a href="https://www.react-spring.dev/">react-spring</a>.  How does react spring work?
</p>

<p>
As an aside, I am not a big AI guy, but if I was allowed to in this game jam, I would be probably paying a few cents towards my openrouter api key to ask something about this.  Not "give me fennel function which simulates a spring-based tween/lerp?" but more "how can I adjust my lerp to by more 'spring like'?".  Still, I respect and very much appreciate the rules for the jam.  While my skills and intuitions may not show it, I <i>have</i> been doing stuff like this a while.  I know we are lerping, linear interpolating, and I know there are other kinds of interpolation, that is kinda what we want, right?
</p>


<div id="org04afa38" class="figure">
<p><img src="joegame.xyz/blog/../images/wiki-see-also.png" alt="Other kidns of interpolation" class="figure" />
</p>
<p><span class="figure-number">Figure 5: </span>Other kidns of interpolation</p>
</div>

<p>
Ok lets look at Bezier.
</p>


<div id="org6085961" class="figure">
<p><img src="joegame.xyz/blog/../images/QuadraticBèziercurvesinstringart.svg" alt="Cmglee, CC BY-SA 3.0 &lt;https://creativecommons.org/licenses/by-sa/3.0&gt;, via Wikimedia Commons" class="figure small-image" />
</p>
<p><span class="figure-number">Figure 6: </span>Cmglee, CC BY-SA 3.0 <a href="https://creativecommons.org/licenses/by-sa/3.0">https://creativecommons.org/licenses/by-sa/3.0</a>, via Wikimedia Commons</p>
</div>

<p>
Looks good to me, but we need to imagine it temporally, not spatially.  Well but that doesnt work, because we don't have another dimension here&#x2026; Ok lets think in "first principles" here.. What we have is the movement of an object over time.  What we are imagining is that the change is relative to the progress, it moves slower at the beginning, and then speeds up at the end.  We just want it to be exponential is all, but not adjust the underlying state of time. Duh, this is so much simpler.
</p>

<div class="org-src-container">
<pre class="src src-fennel">;; where the lerp happens
(cards.drawV
 %state
 (top this-stack)
 (u.v-lerp
  (get-grid-pos pos-left.x pos-left.y)
  this-pos
  (math.pow (/ neighbor-fill-in-wait *settings.fill-in-duration) 2))) ;; here

</pre>
</div>


<div id="org8392c4a" class="figure">
<p><img src="joegame.xyz/blog/../images/lispgamejam-exponential-fill-in.gif" alt="Filling in exponentially" class="figure" />
</p>
<p><span class="figure-number">Figure 7: </span>Filling in exponentially</p>
</div>

<p>
Ok, the movement is (imo) notably more "natural," the polish of the simulation has been increased.  One thought for me, is that there is the progress of each card filling in, but like the last gif there, we want there to be the overall progress of filling in, the total cascade.  Wouldn't it be great for the filling in to speed up near the end of the total cascade?  We could keep track of a single cascade, but our code currently doesn't have a sense of a cascade.  It's just checking for fill ins.  Lets put that to the side.
</p>

<p>
We are using our crude blue/green cursors to keep track of target and sources.  Let us use the same principles we have so far to scale the cards as we target them. Just following intuition here.
</p>


<div id="org8697047" class="figure">
<p><img src="joegame.xyz/blog/../images/lispgamejam-pop-target-bug.gif" alt="A bug with our popping" class="figure" />
</p>
<p><span class="figure-number">Figure 8: </span>A bug with our popping</p>
</div>

<p>
Now, what is happening here?
</p>

<div class="org-src-container">
<pre class="src src-fennel">(fn [dt _set-mode]
  (iter-grid %game-state.counters
             (fn [val]
                 ;; ...
                 ;; ...
                 ;; ...
                 ;; check target pop HERE
                 (if (u.v= %game-state.target-cursor val)
                     (when (not (= it.target-pop *settings.pop-duration))
                       (tset %game-state.counters y x :target-pop (math.min *settings.pop-duration (+ it.target-pop dt))))
                     (when (not (= it.target-pop 0))
                       (tset %game-state.counters y x :target-pop (math.max 0 (- it.target-pop dt))))))))
</pre>
</div>


<p>
If the current card is the current target, increment the value at least to pop-duration&#x2026;
</p>

<p>
&#x2026; &#x2026; ..
</p>

<p>
Ok, well, it was just a bug with our mouse logic.
</p>

<p>
We have polished both the fill-in and the target actions in the game.  We need to now have some kind polish/reactivity arount setting a source.  How about a little wiggle?  This can be done the same way as the the time stuff, where it is just the question of the right function interpreting the underlying counter.
</p>

<p>
In a weird way, I am more prepared for this than the movement thing.  My heuristic: a wiggle is something that starts in one state, undergoes something, and ends up back where it started; this means we will almost definitely use trigonometry.  A sin wave starts at 0 and ends at 0 every period.  While a wiggle is also going to be a rotation, it wouldn't need to be to make use of a sin wave.  All that is important is the nature of the transformation over time. Here is the simplest, doing a <code>wiggle-times</code> oscillations linearly.
</p>

<div class="org-src-container">
<pre class="src src-fennel">(* *settings.wiggle-amount
   (math.sin  (*
               math.pi
               2
               (/
                (. game-state.counters y x :source-wiggle)
                *settings.wiggle-duration))))]

</pre>
</div>


<div id="org51b42e3" class="figure">
<p><img src="joegame.xyz/blog/../images/lispgamejam-wiggle-v1.gif" alt="Wiggling the source selection, v1" class="figure" />
</p>
<p><span class="figure-number">Figure 9: </span>Wiggling the source selection, v1</p>
</div>
</div>
</div>
<div id="outline-container-org915139b" class="outline-3">
<h3 id="org915139b"><span class="section-number-3">6.2.</span> <span class="todo TODO">TODO</span> qol</h3>
<div class="outline-text-3" id="text-6-2">
<p>
Polish is one thing, and we will be doing more today, but there is another "thing" here I think about: making all the small things not as frustrating.  Right now, our "DWIM" logic has a small annoyance.  When you click, it first checks if there is a source set, and then checks for validity.  If there is no source, one is set.  If it is not valid, the source is deselected.  But when playing the game, sometimes I just
</p>
</div>
</div>
</div>
<div id="outline-container-org4eefb30" class="outline-2">
<h2 id="org4eefb30"><span class="section-number-2">7.</span> <span class="todo TODO">TODO</span> Day 9-10</h2>
<div class="outline-text-2" id="text-7">
<p>
Well you could say yesterday I was really in-the-zone and got a lot done&#x2026;
</p>

<p>
TODO
</p>
</div>
<div id="outline-container-org56bc7c3" class="outline-3">
<h3 id="org56bc7c3"><span class="section-number-3">7.1.</span> update on polish</h3>
<div class="outline-text-3" id="text-7-1">

<div id="org73d6107" class="figure">
<p><img src="joegame.xyz/blog/../images/lispgamejam-desmos-waverv1.gif" alt="Simple waver which will dip from 1 to s" class="figure" />
</p>
<p><span class="figure-number">Figure 10: </span>Simple waver which will dip from 1 to s</p>
</div>
</div>
<div id="outline-container-org41b25a9" class="outline-4">
<h4 id="org41b25a9"><span class="section-number-4">7.1.1.</span> rubber ducking multi card movement</h4>
<div class="outline-text-4" id="text-7-1-1">
<p>
What we want is for cards to return to the deck when a stack gets to a certain size, see <a href="#org8b8ff4b">new mechanics</a>.  How I want to do this is like all our other "tweens," where a counter refers to a certain stack, and the progress of that counter to 0, over some predefined duration.  For this specific effect, the idea is to have a stream of cards flow one by one to the deck, ideally speeding up/looking organic as they do. My initial thought is that each card moving over is delayed based on its index (always 1..amount-traveling), but then its speed is adjusted to compensate for the delay.  Starting out just linearly and playing around in the calculator, I get <code>y=x+dx-d</code> as a suitable function, where <code>d</code> is some delay amount.  From there, its easy to use <code>sin((x*pi)/2)</code> in place of x in the original function.
</p>


<div id="orgd905867" class="figure">
<p><img src="joegame.xyz/blog/../images/lispgame-jamdelaying-functions.png" alt="functions for multi card movement" class="figure" />
</p>
<p><span class="figure-number">Figure 11: </span>functions for multi card movement</p>
</div>

<p>
These functions can stay as is and
</p>
</div>
</div>
</div>
<div id="outline-container-org4196cc9" class="outline-3">
<h3 id="org4196cc9"><span class="section-number-3">7.2.</span> on using lisp</h3>
</div>
<div id="outline-container-orgca0e74c" class="outline-3">
<h3 id="orgca0e74c"><span class="section-number-3">7.3.</span> assets used</h3>
</div>
<div id="outline-container-org8b8ff4b" class="outline-3">
<h3 id="org8b8ff4b"><span class="section-number-3">7.4.</span> new mechanics</h3>
<div class="outline-text-3" id="text-7-4">
</div>
<div id="outline-container-orgb7ddf45" class="outline-4">
<h4 id="orgb7ddf45"><span class="section-number-4">7.4.1.</span> countdown</h4>
</div>
<div id="outline-container-org07e0e21" class="outline-4">
<h4 id="org07e0e21"><span class="section-number-4">7.4.2.</span> stack completion</h4>
</div>
</div>
<div id="outline-container-orgc8f3349" class="outline-3">
<h3 id="orgc8f3349"><span class="section-number-3">7.5.</span> release</h3>
</div>
</div>
]]>
</description></item>
<item>
<title>Bootstrapping the joegame blog</title>
<link>joegame.xyz/blog/bootstrapping-joegame-blog.html</link>
<pubDate>Fri, 15 May 2026 23:31:15 -0600</pubDate>
<guid>joegame.xyz/blog/bootstrapping-joegame-blog.html</guid>
<description>
<![CDATA[<p>
Some things can just be simple. I don't know about you, but my eyes glaze over when I peruse through <a href="https://themes.gohugo.io/">this</a>. The current blog is built like this
</p>

<div class="org-src-container">
<pre class="src src-elisp">(<span style="font-weight: bold;">require</span> '<span style="font-weight: bold; text-decoration: underline;">org</span>)

(<span style="font-weight: bold;">setq</span>
 org-confirm-babel-evaluate nil
 org-publish-use-timestamps-flag nil
 org-publish-timestamp-directory <span style="font-style: italic;">"./.org-timestamps/"</span>)

<span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">rss feed
</span>(add-to-list 'load-path (expand-file-name <span style="font-style: italic;">"./org-publish-rss/"</span>))
(<span style="font-weight: bold;">require</span> '<span style="font-weight: bold; text-decoration: underline;">org-publish-rss</span>)
(<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">joegame-site-filter-from-rss</span> (filename)
  (<span style="font-weight: bold;">and</span>
   (not (bb/org-is-draft (bb/org-get-keywords filename)))
   (not (equal (file-name-nondirectory filename) <span style="font-style: italic;">"index.org"</span>))))



<span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">shared utilities
</span>(<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">bb/org-get-keywords</span> (blog-file)
  (<span style="font-weight: bold;">with-temp-buffer</span>
    (insert-file blog-file)
    (append (list (cons <span style="font-style: italic;">"PATH"</span> (format <span style="font-style: italic;">"./%s"</span> (file-relative-name blog-file))))
            (org-element-map (org-element-parse-buffer)
                'keyword
              (<span style="font-weight: bold;">lambda</span> (it)
                (cons
                 (org-element-property <span style="font-weight: bold;">:key</span> it)
                 (org-element-property <span style="font-weight: bold;">:value</span> it)))))))

(<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">bb/org-is-draft</span> (keywords)
  (equal <span style="font-style: italic;">"t"</span> (alist-get <span style="font-style: italic;">"DRAFT"</span> keywords <span style="font-style: italic;">"t"</span> nil #'equal)))
(<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">bb/org-keyword-value</span> (keywords key)
  (alist-get key keywords nil nil #'equal))


<span style="font-weight: bold; font-style: italic;">;; </span><span style="font-weight: bold; font-style: italic;">projects
</span>(<span style="font-weight: bold;">setq</span>
 org-publish-project-alist '((<span style="font-style: italic;">"orgfiles"</span>
                              <span style="font-weight: bold;">:base-directory</span> <span style="font-style: italic;">"./src"</span>
                              <span style="font-weight: bold;">:recursive</span> t
                              <span style="font-weight: bold;">:publishing-directory</span> <span style="font-style: italic;">"./public"</span>
                              <span style="font-weight: bold;">:html-head</span> <span style="font-style: italic;">"&lt;link rel=\"stylesheet\" href=\"/style.css\" type=\"text/css\"/&gt;"</span>
                              <span style="font-weight: bold;">:html-postamble</span> t
                              <span style="font-weight: bold;">:auto-sitemap</span> nil
                              <span style="font-weight: bold;">:html-postamble-format</span> (( <span style="font-style: italic;">"en"</span> <span style="font-style: italic;">"&lt;footer&gt; &lt;p&gt;&amp;copy; 2026 Your Company. All rights reserved.&lt;/p&gt;&lt;/footer&gt;"</span>))
                              <span style="font-weight: bold;">:html-preamble-format</span> ((<span style="font-style: italic;">"en"</span> <span style="font-style: italic;">"&lt;header&gt; &lt;h2 style=\"flex-grow:1 \"&gt;&lt;a href=\"/\"&gt;joegame&lt;/a&gt;&lt;/h2&gt; &lt;img class=\"gif-image\" src=\"/images/kangaroo_east.gif\"&lt;/img&gt; &lt;h4&gt;&lt;a href=\"/rss.xml\"&gt;rss&lt;/a&gt;&lt;/h4&gt;&lt;/header&gt;"</span>))
                              <span style="font-weight: bold;">:html-home/up-format</span> <span style="font-style: italic;">""</span>
                              <span style="font-weight: bold;">:base-extension</span> <span style="font-style: italic;">"org"</span>
                              <span style="font-weight: bold;">:headline-levels</span> 3
                              <span style="font-weight: bold;">:section-numbers</span> nil
                              <span style="font-weight: bold;">:with-toc</span> nil
                              <span style="font-weight: bold;">:with-todo-keywords</span> nil
                              <span style="font-weight: bold;">:org-html-html5-fancy</span> t
                              <span style="font-weight: bold;">:org-html-head-include-default-style</span> nil
                              <span style="font-weight: bold;">:auto-rss</span> t
                              <span style="font-weight: bold;">:rss-title</span> <span style="font-style: italic;">"joegame.xyz Posts"</span>
                              <span style="font-weight: bold;">:rss-description</span> <span style="font-style: italic;">"Writeups from Joegame studios."</span>
                              <span style="font-weight: bold;">:rss-with-content</span> all
                              <span style="font-weight: bold;">:html-link-home</span> <span style="font-style: italic;">"joegame.xyz"</span>
                              <span style="font-weight: bold;">:completion-function</span> org-publish-rss
                              <span style="font-weight: bold;">:rss-filter-function</span> joegame-site-filter-from-rss
                              )

                             (<span style="font-style: italic;">"static"</span>
                              <span style="font-weight: bold;">:base-directory</span> <span style="font-style: italic;">"./src"</span>
                              <span style="font-weight: bold;">:recursive</span> t
                              <span style="font-weight: bold;">:base-extension</span> <span style="font-style: italic;">"jpg</span><span style="font-weight: bold; font-style: italic;">\\</span><span style="font-weight: bold; font-style: italic;">|</span><span style="font-style: italic;">gif</span><span style="font-weight: bold; font-style: italic;">\\</span><span style="font-weight: bold; font-style: italic;">|</span><span style="font-style: italic;">png</span><span style="font-weight: bold; font-style: italic;">\\</span><span style="font-weight: bold; font-style: italic;">|</span><span style="font-style: italic;">css</span><span style="font-weight: bold; font-style: italic;">\\</span><span style="font-weight: bold; font-style: italic;">|</span><span style="font-style: italic;">svg</span><span style="font-weight: bold; font-style: italic;">\\</span><span style="font-weight: bold; font-style: italic;">|</span><span style="font-style: italic;">webp</span><span style="font-weight: bold; font-style: italic;">\\</span><span style="font-weight: bold; font-style: italic;">|</span><span style="font-style: italic;">html"</span>
                              <span style="font-weight: bold;">:include</span> (<span style="font-style: italic;">"rss.xml"</span>)
                              <span style="font-weight: bold;">:publishing-directory</span> <span style="font-style: italic;">"./public"</span>
                              <span style="font-weight: bold;">:publishing-function</span> org-publish-attachment)

                             (<span style="font-style: italic;">"site"</span> <span style="font-weight: bold;">:components</span> (<span style="font-style: italic;">"orgfiles"</span> <span style="font-style: italic;">"static"</span>))))

</pre>
</div>

<p>
Most of this is just using org-mode's <a href="https://orgmode.org/manual/Publishing.html">publish feature</a>, along with our one external dependency in <a href="https://git.sr.ht/~taingram/org-publish-rss/tree/master/item/org-publish-rss.el">org-publish-rss</a>, and finally a few extra things we will get to.  This is saved in a <code>site.el</code> file at the root of the website repo, and we can build the site with a makefile rule:
</p>

<div class="org-src-container">
<pre class="src src-makefile"><span style="font-weight: bold;">build</span>:
        emacs -q --script ./site.el --eval <span style="font-style: italic;">'(org-publish "site")'</span>
</pre>
</div>

<p>
So far, the extra stuff we are doing is just related to generating a list of posts.  Also in the basedir of the site is a <code>lib.org</code> file, acting as our own personal <a href="https://orgmode.org/manual/Library-of-Babel.html">library of babel</a>.  It contains helper functions like this:
</p>

<div class="org-src-container">
<pre class="src src-org"><span style="font-weight: bold;">* gen post list</span>
<span style="font-weight: bold; font-style: italic;">#+name: gen-post-list</span>
<span style="font-weight: bold; font-style: italic;">#+begin_src elisp :results output raw :exports results
</span>  (<span style="font-weight: bold;">defun</span> <span style="font-weight: bold;">joegame-site-gen-blog-entries</span> ()
    (<span style="font-weight: bold;">dolist</span> (to-pub
             (sort (cl-remove-if #'bb/org-is-draft
                                 (cl-map 'list #'bb/org-get-keywords
                                         (directory-files <span style="font-style: italic;">"./blog/"</span> t <span style="font-style: italic;">"\\.*.org"</span>)))
                   (<span style="font-weight: bold;">lambda</span> (a b)
                     (string&gt; (<span style="font-weight: bold;">or</span> (bb/org-keyword-value a <span style="font-style: italic;">"DATE"</span>) <span style="font-style: italic;">""</span>)
                              (<span style="font-weight: bold;">or</span> (bb/org-keyword-value b <span style="font-style: italic;">"DATE"</span>) <span style="font-style: italic;">""</span>)))))
      (princ (format <span style="font-style: italic;">"- ,[,[%s][%s]] %s\n"</span>
                     (bb/org-keyword-value to-pub <span style="font-style: italic;">"PATH"</span>)
                     (bb/org-keyword-value to-pub <span style="font-style: italic;">"TITLE"</span>)
                     (bb/org-keyword-value to-pub <span style="font-style: italic;">"DATE"</span>)))))

    (joegame-site-gen-blog-entries)

<span style="font-weight: bold; font-style: italic;">#+end_src
</span>

</pre>
</div>

<p>
Note especially how we are generating raw org markdown (<code>:results output raw</code>), which is then turned into html by the actual publishing process.
</p>

<p>
We use it like so (on the homepage):
</p>

<div class="org-src-container">
<pre class="src src-org"><span style="font-weight: bold; font-style: italic;">#+call: ../lib.org:gen-post-list()</span>
</pre>
</div>

<p>
Another helper function looks like this, for images
</p>

<div class="org-src-container">
<pre class="src src-org"><span style="font-weight: bold; font-style: italic;">#+name: image</span>
<span style="font-weight: bold; font-style: italic;">#+begin_src elisp :results output raw :exports results :var image="slgj-day1-end.png" caption="A caption"
</span>  (princ (format <span style="font-style: italic;">"#+CAPTION: %s\n"</span> caption))
  (princ (format <span style="font-style: italic;">"#+ATTR_HTML: :alt %s :class figure\n"</span> caption))
  (princ (format <span style="font-style: italic;">"<a href="file:%s\n">file:%s\n</a>"</span> image))
<span style="font-weight: bold; font-style: italic;">#+end_src</span>
</pre>
</div>

<p>
Which we can call like so
</p>

<div class="org-src-container">
<pre class="src src-org"><span style="font-weight: bold; font-style: italic;">#+call: ../../lib.org:image("../images/slgj-day1-end.png", "The game at the end of day 1. The source cursor is blue and the target one is green" )</span>
</pre>
</div>
]]>
</description></item>
</channel>
</rss>
