
    <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
      <title>graham's blog (#video games)</title>
      <subtitle>to distract from existential dread</subtitle>
      <link href="https://graham.build/s/a-blog/about/video games/feed.xml"/>
      <link href="https://graham.build/"/>
      <updated>2026-07-10T06:30:00.000Z</updated>
      <id>https://graham.build/</id>
      <author>
        <name>graham</name>
      </author>
      
        <entry>
          <title>I'm Working On A Game</title>
          <link href="https://graham.build/s/a-blog/039-im-working-on-a-game/" />
          <id>https://graham.build/s/a-blog/039-im-working-on-a-game/</id>
          <published>2026-07-10T06:30:00.000Z</published>
          <updated>2026-07-10T06:30:00.000Z</updated>
          <category>pokemon</category>
<category>video games</category>
<category>game development</category>
<category>puzzles</category>
<category>art</category>
<category>digital art</category>
          <content type="html">
            &lt;p&gt;Ever since I first read about &lt;a href=&quot;https://celia14.itch.io/my-friends-the-monster-trainers&quot;&gt;My Friends the Monster Trainers&lt;/a&gt; by &lt;a href=&quot;https://jamwitch.itch.io/&quot;&gt;Jamwitch&lt;/a&gt; via &lt;a href=&quot;https://blog.lauramichet.com/cute-little-pokemon-esque-roottrees-alike/&quot;&gt;Laura Michet&#039;s blogpost about it&lt;/a&gt;, I&#039;ve been completely enamored by that game. I love the not-technically-pokemon designs about it. I love the believable-in-fiction setup for the game&#039;s premise. I love how toyetic the design of the whole webpage where you play the game is. And what I found was that I also craved more: more not-pokemon to try to determine from clues, more detailed typings and how those types overlap with the real world, more keeping track of which creatures turn into which other creatures, among many more notes I wrote down to try to come back come development-time.&lt;/p&gt;
&lt;p&gt;Since roughly June 1st of this year, I have been working on putting together a list of 50 names of not-pokemon followed by illustrating simple contour drawings of them by hand on my phone. Here are the names in alphabetical order.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Aboara
Arcupine
Blaazé
Bluega
Boarealis
Boouoy
Bowvine
Brewelée
Buffalloy
Bullbil
Calvine
Canaro
Capyterra
Chinchiller
Coltage
Cragmite
Dextsnail
Dragonet
Ducktile
Fincho
Flambébé
Gumchu
Hogtide
Hogwash
Hydromedary
Icebis
Joltergeist
Koalala
Llamina
Magmoo
Malleabard
Ossilot
Pneumatoad
Psycculent
Ratarot
Rockoon
Sanguin
Scorchion
Scorchling
Serindigo
Shrewdinger
Silverant
Sinisnail
Smolten
Snowflee
Spoonswill
Stingrazor
Tamanoir
Tsooienami
Ziprunner
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As of tonight, (and the reason for this blogpost) I have also now completed the 50th hand-made drawing on my phone of each of the names above, which marks a sort of milestone for this game. I&#039;ve included the drawings below in a random order to try to prevent any accidental spoilers for the eventual game, since presumably a major goal of the game will be to figure out which name goes with which picture.&lt;/p&gt;
&lt;div class=&quot;image-flex-grid&quot;&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/0.png&quot; alt=&quot;a kneeling sheep with one burning fist out&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/1.png&quot; alt=&quot;a rodent with faint contour lines offset horizontally&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/2.png&quot; alt=&quot;a plant person with roots as feet and plants as hands and eyes&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/3.png&quot; alt=&quot;a fat rodent laying on its back with a big tail&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/4.png&quot; alt=&quot;a pig with a water lasso&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/5.png&quot; alt=&quot;an anteater wearing a cap and looking pensive&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/6.png&quot; alt=&quot;a small bird kind of in the shape of an egg&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/7.png&quot; alt=&quot;a bull with long lines drawn down its body and a weird squiggly tail&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/8.png&quot; alt=&quot;a penguin whose shadow is going the wrong way&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/9.png&quot; alt=&quot;a scorpion with a weird face mask and metal tubes instead of claws&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/10.png&quot; alt=&quot;a camel with water encircling its head&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/11.png&quot; alt=&quot;a sassy sheep holding up a hand with a flame just above it&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/12.png&quot; alt=&quot;a bug featuring many copies of its contour drawing with varying opacity leading up to the darkest, closest one&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/13.png&quot; alt=&quot;a capybara with particularly geometric line patterns around its body&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/14.png&quot; alt=&quot;a small blob obscured by a leaning metal structure&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/15.png&quot; alt=&quot;a horse with a lightning bolt tail&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/16.png&quot; alt=&quot;a raccoon with particularly geometric line patterns around its body&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/17.png&quot; alt=&quot;a fish with some very large and ornate fins&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/18.png&quot; alt=&quot;a sheep sitting down holding a fireball in one hand&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/19.png&quot; alt=&quot;a bug with particularly geometric line patterns around its body&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/20.png&quot; alt=&quot;a buffalo with riveted plating on its back&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/21.png&quot; alt=&quot;a beluga whale with a bubble stream coming out of its blowhole&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/22.png&quot; alt=&quot;a duck with a neck that is doing a loop-de-loop&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/23.png&quot; alt=&quot;a porcupine with lots of zig zag patterning in its fur and quills&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/24.png&quot; alt=&quot;an abstract zig-zagging shape with two legs and a face&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/25.png&quot; alt=&quot;a large pig looking intimidating with a large ocean wave in the background&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/26.png&quot; alt=&quot;a pig flying upwards with ribbon-like wings&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/27.png&quot; alt=&quot;a stingray with an odd silhouette&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/28.png&quot; alt=&quot;a koala shape sticking up out of a pile of rocks and dirt&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/29.png&quot; alt=&quot;a young cow holding a small rope or vine&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/30.png&quot; alt=&quot;a bug with a long face and a pair of forelimbs that end apruptly with something rounded off&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/31.png&quot; alt=&quot;a snail with a red stripe and arrow on its shell&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/32.png&quot; alt=&quot;a rodent with a card attached to its tail&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/33.png&quot; alt=&quot;a duck with a long neck laying down&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/34.png&quot; alt=&quot;a frog with a tubular apparatus on its back and connected to its back thighs&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/35.png&quot; alt=&quot;a pig with ribbon-like wings standing on the ground&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/36.png&quot; alt=&quot;a bird with its wings elongated and spoons hovering around its head&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/37.png&quot; alt=&quot;a rotund bird with some decorations around its eyes&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/38.png&quot; alt=&quot;a bird with something liquid or icy about its head and back&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/39.png&quot; alt=&quot;a cat with leopard-spots and particularly jagged-corner features&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/40.png&quot; alt=&quot;a bug with metal forelimbs and a large plume of fire coming from around midway down its back&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/41.png&quot; alt=&quot;a bug with some snow on its back&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/42.png&quot; alt=&quot;a cow with melting goop all over it&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/43.png&quot; alt=&quot;a llama with many horizontal lines that aren&#039;t always straight but also never cross&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/44.png&quot; alt=&quot;a cow with ribbon-like patterns all over its body and a knotted ribbon atop its head&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/45.png&quot; alt=&quot;a bird looking over its shoulder with energy crackling at its feet&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/46.png&quot; alt=&quot;an anteater wearing a hat and holding a magnifying glass&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/47.png&quot; alt=&quot;a pig with a stream of water hovering above it&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/48.png&quot; alt=&quot;a very large looking bird with many decorations across its face and belly&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;span&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/039-im-working-on-a-game/49.png&quot; alt=&quot;a snail with a blue stripe and arrow on its shell&quot;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;There&#039;s still a lot of work to do on this game. There&#039;s a whole story that contains logical clues to deduce the various not-pokemon, their names, their types, what they&#039;ll become, and where they live. I&#039;ve never had to do much writing for any game I&#039;ve worked on, so I imagine that will take a lot of effort.&lt;/p&gt;
&lt;p&gt;Then there&#039;s all the coding. I don&#039;t want to just copy the UX from MFtMT, as much as I like that game, since that feels lazy. However, there are parts that I imagine will get reused: some of the game being organized around jotting down clues and facts while the other part is organized around analyzing info for new logical conclusions, for instance.&lt;/p&gt;
&lt;p&gt;I&#039;m excited about this milestone and I am hopeful to continue to use this momentum to make something fun.&lt;/p&gt;

          </content>
        </entry>
      

        <entry>
          <title>Phonetic Pangram Tool</title>
          <link href="https://graham.build/s/a-blog/036-phonetic-pangram-tool/" />
          <id>https://graham.build/s/a-blog/036-phonetic-pangram-tool/</id>
          <published>2026-01-03T06:30:00.000Z</published>
          <updated>2026-01-03T06:30:00.000Z</updated>
          <category>wordplay</category>
<category>phonetic pangrams</category>
<category>pokemon</category>
<category>video games</category>
          <content type="html">
            &lt;p&gt;After spending last night writing that blog post about &lt;a href=&quot;/s/a-blog/035-pokemon-phonetic-pangram&quot;&gt;pokemon phonetic pangrams&lt;/a&gt;, I felt like I was done with this hyperfixation and could move onto other things&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. This morning proved me wrong when I had the thought&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey isn&#039;t making a pangram kind of just a very specific case of that &lt;a href=&quot;/s/a-blog/017-crowdpleaser-words&quot;&gt;daily word game&lt;/a&gt; you made last year?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Suffice it to say that that inkling was correct, and it &lt;em&gt;only&lt;/em&gt; took me &lt;em&gt;all day&lt;/em&gt; to remember how that all worked, copy it into a new project, modify that into working for phonetic pangrams, set that project up with Render&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; for hosting, upload the iframe pointed there from &lt;a href=&quot;http://itch.io&quot;&gt;itch.io&lt;/a&gt;, and build out a new &lt;a href=&quot;http://itch.io&quot;&gt;itch.io&lt;/a&gt; page for the project. Take a look below:&lt;/p&gt;
&lt;iframe title=&quot;Phonetic Pangrams itch.io embed&quot; frameborder=&quot;0&quot; src=&quot;https://itch.io/embed/4167222?bg_color=262215&amp;amp;fg_color=ebe3cc&amp;amp;link_color=b57f00&amp;amp;border_color=ebe3cc&quot; width=&quot;552&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https://anvilfood.itch.io/phonetic-pangrams&quot;&gt;Phonetic Pangrams by graham&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;It works with pokemon and the CMU phonetic dictionary, which covers a bunch of English words and names. It only supports General American English&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; for now, but I think there are ways to extend that to other dialects going forward, with enough data about how the phonemes change.&lt;/p&gt;
&lt;p&gt;Anyway, in the interest of keeping it short, that&#039;s it! Enjoy, and please share your phonetic pangrams with each other and me on there. As far as I know, there does not yet exist a solved solution for phonetic pangrams in English the way that there are now for pokemon names.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Like finishing up the hxh fanart, or reading, or touching grass between rainstorms in the Bay, that sort of thing. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I once again really wanted to be able to rely on websockets for checking whether a given word matched the corpus on the server. Otherwise, everyone using the tool would have to download a big file of all possible words and names and their pronunciations. Shout-outs to Render! &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;And if you want a bonus difficulty level, I recommend using the &lt;code&gt;/x/&lt;/code&gt; phoneme of &lt;code&gt;loch /lɑx/&lt;/code&gt;. &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Pokemon Phonetic Pangram</title>
          <link href="https://graham.build/s/a-blog/035-pokemon-phonetic-pangram/" />
          <id>https://graham.build/s/a-blog/035-pokemon-phonetic-pangram/</id>
          <published>2026-01-02T16:00:00.000Z</published>
          <updated>2026-01-02T16:00:00.000Z</updated>
          <category>pokemon</category>
<category>video games</category>
<category>wordplay</category>
<category>phonetic pangrams</category>
          <content type="html">
            &lt;p&gt;As a follow-up to &lt;a href=&quot;/s/a-blog/034-pokemon-gen-1-phonetic-pangram&quot;&gt;my previous post&lt;/a&gt;, I have uploaded the data and my previous solution to &lt;a href=&quot;https://codeberg.org/anvilfood/pokemon-phonetic-pangrams&quot;&gt;codeberg&lt;/a&gt;. Last time, I learned that &lt;code&gt;Slither Wing&lt;/code&gt; is the only pokemon across all current generations to contain the &lt;code&gt;ð&lt;/code&gt; phoneme, which meant that only datasets that included gen-9 could form &lt;em&gt;true&lt;/em&gt; phonetic pangrams for General American English. With this in mind, I scraped the rest of the generations and compiled them into one unified dataset for all pokemon. As expected, I was able to find several 11-pokemon pangrams&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; by simply using the new dataset, but it made me wonder if there existed any pangrams with even fewer pokemon. I tried running the 10-mon pangram attempt across all gens and found that nothing happened for a while, even with the caching I had explained in the previous post.&lt;/p&gt;
&lt;h3&gt;Technical Hurdles&lt;/h3&gt;
&lt;p&gt;After discussing this with some of my friends on Discord, it became clear that the size of the problem-space being explored had grown very quickly with the size of the dataset of pokemon, just as predicted. For gen-1, there were at most (151 &lt;a href=&quot;https://en.wikipedia.org/wiki/Combination#Number_of_k-combinations&quot;&gt;choose&lt;/a&gt; 10) combinations of pokemon to find a set that covered all 37 represented phonemes in that set. For all gens, it was more like (1025 choose 10) combinations, which is roughly 269 million times more. Despite this, I tried to simply run the program and wait. I was rewarded with a new problem:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;$ bun run main.ts
136 |           if (!cache.has(cacheKey)) {
137 |             if (solution.names.size &amp;lt; SetCoverSizeToBeat - 1) {
138 |               const idx = queue.findIndex(s =&amp;gt; s.phones.size &amp;lt;= solution.phones.size)
139 |               queue.splice(idx, 0, solution)
140 |             }
141 |             cache.add(cacheKey)
                        ^
RangeError: Out of memory
      at &amp;lt;anonymous&amp;gt; (/Users/g/Documents/programming/pokemon/phonetic_pangram/main.ts:141:19)
      at forEach (1:11)
      at &amp;lt;anonymous&amp;gt; (/Users/g/Documents/programming/pokemon/phonetic_pangram/main.ts:133:17)
      at forEach (1:11)
      at main (/Users/g/Documents/programming/pokemon/phonetic_pangram/main.ts:132:22)
      at /Users/g/Documents/programming/pokemon/phonetic_pangram/main.ts:153:1
      at loadAndEvaluateModule (2:1)

Bun v1.3.3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It makes sense that this program would run out of memory because the cache is adding new paths that have been visited constantly until the program finishes. In the past, this was a small enough problem space to avoid memory issues, but now the problem space had simply ballooned too much for the cache to handle. I looked into how I could make the size of what I was storing smaller. For one, I was storing the cache key as a set of strings that contained all the letters of the pokemon being represented in the path. By &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode&quot;&gt;replacing a given pokemon with a single character&lt;/a&gt;, I was able to shorten this from an average of 7.6 characters per pokemon name to 1, which reduced the cache size by a factor of ~7x. This did not solve my out of memory issue.&lt;/p&gt;
&lt;p&gt;Googling around, I learned that Typescript &lt;a href=&quot;https://stackoverflow.com/questions/58674238/did-my-javascript-run-out-of-asyncids-rangeerror-in-inspector-async-hook-js&quot;&gt;has a hard-limit on the number of members in a set or a map&lt;/a&gt;. It turns out that this limit is far below the number of possible solutions to explore, even with the reduced dataset size. Similar to one of the suggestions on stackoverflow, I implemented a &lt;code&gt;BigSet&lt;/code&gt; class that just created a new set every time the old one was about to be full. This allowed the program to run without hitting javascript memory limits. But it meant that it quickly used up 13GB of RAM on my computer, even when no other programs were running.&lt;/p&gt;
&lt;p&gt;Next, I tried seeing if any of the pokemon I was considering had phonemes that were a subset of any other pokemon pronunciations. For example &lt;code&gt;Kadabra&lt;/code&gt; clearly contains all the phonemes that &lt;code&gt;Abra&lt;/code&gt; does. It&#039;s reasonable to skip &lt;code&gt;Abra&lt;/code&gt; if the goal is just to find the existence of any phonetic pangram, since any one that would use Abra could instead use Kadabra. Continuing this pattern reduced the number of pokemon from 1025 down to 789, which reduced the problem space by a factor of about 13x. This also did not solve my out of memory issue.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;To try to limit the remaining unknowns about the full pokemon dataset, I separately tried looking up pangrams for 1, 2, ..., 7, and 8 pokemon. I knew from size-10 and size-11 ones that even a single answer could come in much faster than my computer hitting its memory limits. I found that I was successfully able to exhaust the problem space for all 1-to-8-sized phonetic pangrams. This left just 9 and its memory issues as the only remaining hurdle.&lt;/p&gt;
&lt;p&gt;It was clear I needed to try something else. My friends suggested a &lt;a href=&quot;https://en.wikipedia.org/wiki/Bloom_filter&quot;&gt;bloom filter&lt;/a&gt;, since those are really good at telling if a given thing (list of pokemon) is either &amp;quot;definitely not&amp;quot; or &amp;quot;maybe is&amp;quot; in a given collect. For a problem like this that has a lot of &amp;quot;wrong answers&amp;quot; relative to the number of &amp;quot;correct answers,&amp;quot; it seemed like a well-tuned bloom filter could work great. That said, I had plans for New Years Eve, so I uploaded what I had to codeberg and let my friends try to nerdsnipe anybody else into solving it a different way.&lt;/p&gt;
&lt;h3&gt;The Same Sort of Algorithm, but in Rust&lt;/h3&gt;
&lt;p&gt;Micolous was able to make a number of &lt;a href=&quot;https://github.com/micolous/mon-pangrams&quot;&gt;algorithmic optimizations&lt;/a&gt; to what I had contributed so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instead of storing sets of names in the cache as letters representing pokemon, and instead of storing the phonemes represented by those pokemon names as a set, liberal usage of &lt;a href=&quot;https://en.wikipedia.org/wiki/Mask_(computing)&quot;&gt;bitmasking&lt;/a&gt; allowed for much smaller amounts of memory used&lt;/li&gt;
&lt;li&gt;Instead of exhaustively searching for every solution to the problem, focus on finding even a single solution at the current desired length&lt;/li&gt;
&lt;li&gt;While looking for a solution, throw out any path that would be worse (i.e. necessarily have more pokemon names) than the current best solution&lt;/li&gt;
&lt;li&gt;Keep all previous optimizations like the limited data-set with pokemon like &lt;code&gt;Abra&lt;/code&gt; removed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these and a little fine-tuning for data-labelling issues from the pokemonlp wiki, it was finally possible to find the first valid 9-pokemon phonetic pangram for General American English:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Heatmor
Typhlosion
Noibat
Vulpix
Growlithe
Poochyena
Shedinja
Illumise
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As expected, it had &lt;code&gt;Slither Wing&lt;/code&gt;. Unlike the previous post, &lt;code&gt;Typhlosion&lt;/code&gt; took the place of &lt;code&gt;Persian&lt;/code&gt;, undoubtedly because of how many more phonemes it contains (8 total versus 5). I was excited to see this news and have a new, clearer goal to work towards. Surely implementing all of the same optimizations in my own code would allow me to get similar results.&lt;/p&gt;
&lt;h3&gt;Hoisted by my Own Petard&lt;/h3&gt;
&lt;p&gt;I spent the better part of New Year&#039;s Day rewriting the set logic I used for determining which phonemes a given solution had so far to instead use bitmasking like Micolous&#039;s. It took some time, but I was happy once it was working. I had the thought that I could stop writing code on my laptop and instead practice with my new split keyboard&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; on my desktop by pushing what I had to codeberg again and then pulling it down from the cloud.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Upon pulling the latest from main and getting the script set up to run, I ran my version on the 9-gram, and found that I got an answer too! This was exhilarating compared to my machine turning on its fans and maxing out RAM for hours with no results. But of course, this had to be because of the optimizations I had spent all day implementing, right?&lt;/p&gt;
&lt;p&gt;I tried rewinding the code to what I had days prior when I had been trying to overcome the technical hurdles on my own. That also ran flawlessly on my desktop computer. It turns out that having similar but not exactly the same specs across a laptop and a desktop can lead to wildly different experiences when it comes to problems like this one. I&#039;m embarrassed that I didn&#039;t try this sooner.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I have yet to get &lt;em&gt;every&lt;/em&gt; 9-pokeon phonetic pangram across all generations, because I did eventually run into memory-hog issues and didn&#039;t want to keep working on optimizations for a problem with so many solutions.&lt;/p&gt;
&lt;p&gt;Below are the first 20&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt; that my algorithm found:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Basculegion
Shaymin
Charizard
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Exeggcute
Shaymin
Jirachi
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Chi-Yu
Aegislash
Blaziken
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Chi-Yu
Aegislash
Rayquaza
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Chi-Yu
Shedinja
Blaziken
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Chi-Yu
Shedinja
Rayquaza
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Poochyena
Aegislash
Blaziken
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Poochyena
Aegislash
Rayquaza
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Poochyena
Shedinja
Blaziken
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Poochyena
Shedinja
Rayquaza
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Charmeleon
Aegislash
Blaziken
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Charmeleon
Aegislash
Rayquaza
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Charmeleon
Shedinja
Blaziken
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Houndoom
Charmeleon
Shedinja
Rayquaza
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Gouging Fire
Exeggcute
Hawlucha
Shaymin
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Gouging Fire
Exeggcute
Honchkrow
Shaymin
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Gouging Fire
Exeggcute
Hitmonchan
Shaymin
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Gouging Fire
Exeggcute
Shaymin
Hitmonchan
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Gouging Fire
Exeggcute
Shaymin
Honchkrow
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Dragapult
Venomoth
Gouging Fire
Exeggcute
Shaymin
Hawlucha
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously, as mentioned before, every answer necessarily had to have &lt;code&gt;Slither Wing&lt;/code&gt;. Additionally, every answer my program found contained &lt;code&gt;Typhlosion&lt;/code&gt; and &lt;code&gt;Noibat&lt;/code&gt;. While these 20 above all included &lt;code&gt;Dragapult&lt;/code&gt;, there were eventually others like these following two that broke that pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Clobbopus
Meowth
Hariyama
Shedinja
Ninetales
Galvantula
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Slither Wing
Typhlosion
Noibat
Rookidee
Venomoth
Gouging Fire
Poochyena
Iron Hands
Shaymin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that every pokemon generation has been included, now that the minimum-length phonetic pangram for General American English has been discovered, and now that we know &lt;em&gt;several&lt;/em&gt; of the minimum-length one in particular, it seems like this problem is ready to be put away for a little while. Maybe when one of those things changes in the future, I&#039;ll unearth this problem again.&lt;/p&gt;
&lt;p&gt;After all, when it comes to the world of pokemon pronunciation set-covering optimization problems:&lt;/p&gt;
&lt;p&gt;I want to be the very best.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Any of the sets from gen 1 listed at the end of the previous post, plus Slither Wing, for example. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;However, I did learn that the phonemes in &lt;code&gt;Arceus&lt;/code&gt; are a subset of the phonemes contained within &lt;code&gt;Cofagrigous&lt;/code&gt;, which was surprising to me! &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;A &lt;a href=&quot;https://www.zsa.io/moonlander&quot;&gt;Moonlander&lt;/a&gt; that my job paid for, which I have yet to bring into the office because I&#039;m still getting used to the layout. &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Decades ago, it used to be the case that transferring files between computers was most quickly done over USBs. These days, that feels like so much effort compared to pushing to a git repo, at least for small code repos like this that are already being stored in the cloud. &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;By the time I stopped the program, I had found 933 9-pokemon pangrams. While this technically only represents a lower-limit, it seemed good enough to stop searching/optimizing for now. &lt;a href=&quot;#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Pokemon Gen 1 Phonetic Pangram</title>
          <link href="https://graham.build/s/a-blog/034-pokemon-gen-1-phonetic-pangram/" />
          <id>https://graham.build/s/a-blog/034-pokemon-gen-1-phonetic-pangram/</id>
          <published>2025-12-28T21:40:00.000Z</published>
          <updated>2025-12-28T21:40:00.000Z</updated>
          <category>pokemon</category>
<category>video games</category>
<category>wordplay</category>
<category>phonetic pangrams</category>
<category>longposts</category>
          <content type="html">
            &lt;p&gt;As I mentioned in my &lt;a href=&quot;/s/a-blog/033-phonetic-pangrams&quot;&gt;previous post&lt;/a&gt;, a phonetic pangram is a sentence or phrase that covers every one of the sounds in a given dialect of a language. Since proper nouns can form a phrase, a phonetic pangram could potentially be made from any sufficiently large collection of names.&lt;/p&gt;
&lt;p&gt;This led me to the question: &amp;quot;Is it possible to make a phonetic pangram from pokemon names?&amp;quot; and more specifically, &amp;quot;Can we do so using only the 151 from the first generation of pokemon?&amp;quot;&lt;/p&gt;
&lt;h3&gt;Phonetics&lt;/h3&gt;
&lt;p&gt;For General American English, &lt;a href=&quot;https://en.wikipedia.org/wiki/English_phonology&quot;&gt;wikipedia&lt;/a&gt; lists the following sounds that comprise every commonly spoken word:&lt;/p&gt;
&lt;h4&gt;Consonants (24&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;)&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;m, n, ŋ, p, b, t, d, k, ɡ, tʃ, dʒ, f, v, θ, ð, s, z, ʃ, ʒ, h, l, r, j, w&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;Vowels (14)&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;ɪ, i, ʊ, u, ɛ, eɪ, ə, oʊ, æ, ɑ, aɪ, ɔɪ, aʊ, ɚ&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To make a pangram, I simply needed pokemon names that encompassed each of these 38 phonemes. You could imagine a worst case of 38, where each pokemon is picked for having exactly on phoneme represented in its name, though I figured there was probably more overlap than that.&lt;/p&gt;
&lt;h3&gt;Pokemon name pronunciations&lt;/h3&gt;
&lt;p&gt;I was able to find &lt;a href=&quot;https://pokemonlp.antifandom.com/wiki/Pok%C3%A9mon_Pronunciation_Guide/Generation_I&quot;&gt;the pronunciations of all 151 gen 1 pokemon&lt;/a&gt;. I copied the table and kept only the name and IPA pronunciation columns. A given pokemon name contains many phonemes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ekans &lt;code&gt;ɛkənz&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First, I had to figure out whether the set of these pokemon match the 48 phonemes labeled above. To do this, I iterated over every row and added the phonemes for that pokemon&#039;s pronunciation to an ever-growing set. Once I reached the end, I found that there were more than 48 phonemes represented, which meant I needed to do some data cleanup.&lt;/p&gt;
&lt;h3&gt;Data Cleanup&lt;/h3&gt;
&lt;p&gt;There are four different kinds of cleanup that were necessary for this dataset:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Two-character phonemes:&lt;/strong&gt; for diphthongs and dual-character phonemes like &lt;code&gt;dʒ&lt;/code&gt;, I needed to replace these combos with single-character variants instead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Americanized phonemes:&lt;/strong&gt; because of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cot%E2%80%93caught_merger&quot;&gt;cot/caught merger&lt;/a&gt; and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hurry%E2%80%93furry_merger&quot;&gt;hurry/furry merger&lt;/a&gt;, among others, it was necessary to map all present phonemes that other dialects used onto General American English.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incorrect phonemes:&lt;/strong&gt; There were a couple of places like Victreebel where phones like &lt;code&gt;/r/&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; which seemed like a mistake, to my ears.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ambiguous phonemes:&lt;/strong&gt; In the case of Nidoran♂ and Nidoran♀, it is unclear whether the names are supposed to include &amp;quot;male&amp;quot; and &amp;quot;female&amp;quot; in the pronunciations. Even canonical anime pronunciations differ depending on episode.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; For the purposes of this challenge, it seemed best to omit them.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After cleanup, I continued to work on the problem.&lt;/p&gt;
&lt;h3&gt;Set Cover&lt;/h3&gt;
&lt;p&gt;I got an old familiar feeling while doing this problem. I thought maybe it was from a previous &lt;a href=&quot;https://adventofcode.com&quot;&gt;advent of code&lt;/a&gt; or something. I couldn&#039;t remember what the problem I was thinking of was formally called -- only previous times that I had encountered it.&lt;/p&gt;
&lt;p&gt;In designing levels for &lt;a href=&quot;https://anvilfood.itch.io/snails-and-sorcery&quot;&gt;Snails and Sorcery&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;, I mapped out every single mechanic for every single level into a big spreadsheet so that I could tell at a glance whether a given level was introducing too many mechanics at once. Later, I wanted to see which levels would make the smallest set while representing every mechanic.&lt;/p&gt;
&lt;p&gt;Another place this has come up is in Magic: the Gathering combos. There&#039;s a silver-bordered&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt; card that lets you win the game if you make a pangram with card names.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cards.scryfall.io/large/front/9/5/95c790e6-340f-42c2-af88-e458b7b9690c.jpg&quot; alt=&quot;Now I Know My ABCs, a card that checks if you control cards whose names span the English alphabet&quot;&gt;&lt;/p&gt;
&lt;p&gt;Trying to find the smallest combo of card names to achieve this pangram is the same problem, just put in a slightly different context.&lt;/p&gt;
&lt;p&gt;When I asked around, my friends told me that this was a &lt;a href=&quot;https://en.wikipedia.org/wiki/Set_cover_problem&quot;&gt;classic Set Cover problem&lt;/a&gt; and that it&#039;s a notoriously difficult problem once the problem size grows big enough.&lt;/p&gt;
&lt;p&gt;Here I was, once again wondering if there was some collection of things (i.e. pokemon names) that would cover all of a set (i.e. General American English phonemes). Thankfully this problem has the benefit that the set of all pokemon (especially just gen 1) is plenty small compared to the set of all MTG cards and is also very small compared to the limit where solving this problem would take too long to complete.&lt;/p&gt;
&lt;h3&gt;A greedy approximation&lt;/h3&gt;
&lt;p&gt;Generally with Set Cover, it&#039;s a lot easier to get a solution that&#039;s pretty good than a solution that&#039;s provably the best. Instead of worrying about the best next step, a heuristic like &amp;quot;start by adding the item which has the fewest overlaps with other items&amp;quot; can get close enough. In this case, that&#039;d be a pokemon whose names contain a phoneme or phonemes that are shared least by the other pokemons&#039; names in the set.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Persian &lt;code&gt;pɝʒən&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Persian is the only gen one pokemon with the &lt;code&gt;ʒ&lt;/code&gt; sound. This means that Persian must be included in every gen 1 phonetic pangram. It also means that &lt;code&gt;p&lt;/code&gt;,&lt;code&gt;ɝ&lt;/code&gt;,&lt;code&gt;ə&lt;/code&gt;, and &lt;code&gt;n&lt;/code&gt; get covered automatically.&lt;/p&gt;
&lt;p&gt;For all other &amp;quot;least common remaining phonemes&amp;quot;, there would be more than one pokemon which contained that phoneme in its name. For instance:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vulpix &lt;code&gt;vʊlpɪks&lt;/code&gt;, Bulbasaur &lt;code&gt;bʊlbəsɑɹ&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Blastoise &lt;code&gt;blæstɔɪs&lt;/code&gt;, Cloyster &lt;code&gt;klɔɪstɚ&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which of the pokemon names in these pairs is better to add? Is it better to add a pokemon from the first pair or the second one? For this greedy approximation, I went with &amp;quot;the one from the first-looked-at-phoneme that will cause the most phonemes to be added to the covering set, or go with the last pokemon if there&#039;s a tie.&amp;quot; In this case, that&#039;s &lt;code&gt;Bulbasaur&lt;/code&gt; because &lt;code&gt;b ʊ l ə s ɑ ɹ&lt;/code&gt; is seven more phonemes covered, as compared with &lt;code&gt;v ʊ l ɪ k s&lt;/code&gt; the six from &lt;code&gt;Vulpix&lt;/code&gt; when you account for &lt;code&gt;p&lt;/code&gt; already being covered by &lt;code&gt;Persian&lt;/code&gt;. From here it&#039;s possible to continue and get an answer, but remember that that&#039;s still a heuristic (good enough) approximation rather than a provably best answer.&lt;/p&gt;
&lt;p&gt;From here, there was a bunch of trial and error to discover and fix the points mentioned in the data cleanup. Originally, the next to choose from was Nidoran♀ because it contained an empty space &lt;code&gt; &lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn6&quot; id=&quot;fnref6&quot;&gt;[6]&lt;/a&gt;&lt;/sup&gt;. Next, every answer included Victreebel because it was the only one containing &lt;code&gt;/r/&lt;/code&gt;. Then, every answer contained Omanyte or Arcanine because they contained &lt;code&gt;ɑɪ&lt;/code&gt; instead of &lt;code&gt;aɪ&lt;/code&gt;. This continued for a while.&lt;/p&gt;
&lt;p&gt;After working through cleaning up all of these edge cases, there was finally a reasonable approximate answer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-csv&quot;&gt;Persian 
Bulbasaur
Blastoise
Meowth
Sandshrew
Hypno
Exeggcute
Koffing
Squirtle
Ivysaur
Charmander
Pidgey
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These 12 pokemon names looked to form a nice phonetic pangram. But could the same be achieved with 11? 10?&lt;/p&gt;
&lt;h3&gt;Minmaxing with Recursion™&lt;/h3&gt;
&lt;p&gt;I noticed while writing the greedy heuristic algorithm that one aspect (number of pokemon names which contain this next phoneme)was minimized while another aspect (the number of phonemes that would get added to the covering set) was maximized. By thinking of these steps as a two-player game, it&#039;s possible to reframe this problem as a version of &lt;a href=&quot;https://en.wikipedia.org/wiki/Minimax&quot;&gt;Minimax&lt;/a&gt;. Similar to how humans and computers &amp;quot;think ahead&amp;quot; a number of moves in a game like chess, perhaps the best move (pokemon to choose) at a given step could be dependent on thinking X-many moves ahead?&lt;/p&gt;
&lt;p&gt;I wrote a recursive algorithm in Typescript for solving this problem. If there were no phonemes that still needed to be added to the set, then the program could stop and return the solution. A given solution could be rated by its number of pokemon names. The best solution would be one that minimized the number of pokemon, which could be filtered for after exploring all of the possible solutions.&lt;/p&gt;
&lt;h3&gt;Searching without Recursion™&lt;/h3&gt;
&lt;p&gt;Javascript, which Typescript runs under the hood, has a max number of times that a recursive function can call itself (i.e. &amp;quot;max depth&amp;quot;) of 10 times. I immediately ran into this limit. I should have known better when I selected this language for writing the algorithm in the first place, but I forgot. There are ways around the max depth restriction, but I find it&#039;s always good practice for code maintainability to unwind the recursion. Generally recursion asks the person reading the code to maintain the state of the program in their head, whereas other approaches can make that state much clearer and easier to inspect when things go wrong.&lt;/p&gt;
&lt;p&gt;I rewrote the algorithm to be more like searching an N-dimensional grid, where each pokemon chosen was like a new direction through a maze, and the set of pokemon names at the end was like the path taken to get to the finish. The goal was to minimize the path length, and at each step along the way, I kept track of &amp;quot;the path so far&amp;quot; for every possible &amp;quot;next step to take&amp;quot;. As I got to a branching point in the maze, I just added each of the &amp;quot;potential next steps to take&amp;quot; to a list. When the list was empty, I knew that all possible paths had been exhausted.&lt;/p&gt;
&lt;p&gt;This time, when I ran the program, it didn&#039;t immediately error out. In fact, it didn&#039;t do much of anything for a very long time, and I got bored.&lt;/p&gt;
&lt;h3&gt;Speeding up the search with pruning&lt;/h3&gt;
&lt;p&gt;Given that the greedy heuristic solution found a way through the &amp;quot;maze&amp;quot; in 12 steps, I knew that I could get rid of any potential next step that would be greater than or equal to 12 steps long. This is sort of like a simple version of &lt;a href=&quot;https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning&quot;&gt;alpha-beta pruning&lt;/a&gt;, in that I was pruning out solutions that were known to be worse than the greedy approximation solution of 12. This optimization may have helped, but not enough for me to notice.&lt;/p&gt;
&lt;p&gt;Next, I tried to keep the list ordered by how long the path had been so far. This helped avoid looking at bad solutions before good ones, but I found that the program still took a very long time.&lt;/p&gt;
&lt;p&gt;When I looked at what was happening step by step towards the beginning of the search, I noticed that there were ways for the same list of pokemon to show up in a solution, just in a different order. Going back to the greedy algorithm example from before:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vulpix &lt;code&gt;vʊlpɪks&lt;/code&gt;, Bulbasaur &lt;code&gt;bʊlbəsɑɹ&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Blastoise &lt;code&gt;blæstɔɪs&lt;/code&gt;, Cloyster &lt;code&gt;klɔɪstɚ&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In exploring each of these possibilities, there would be one that would look like &lt;code&gt;Persian, Vulpix, Blastoise&lt;/code&gt; and another that would look like &lt;code&gt;Persian, Blastoise, Vulpix&lt;/code&gt;. These two states are equivalent in terms of how much they cover the set of phonemes, but the paths to get to each were different-looking enough that my code was treating them as independent solutions.&lt;/p&gt;
&lt;p&gt;I decided to make an in-memory cache that would tell me whether I had &amp;quot;been to this part of the maze&amp;quot; before. All I had to do was name each spot in the maze in a way that would give the same name every time I asked for the same spot. For instance, the first spot in the maze could be called &lt;code&gt;Persian&lt;/code&gt; since the algorithm only had one choice. Then when I added new names, I could sort them all alphabetically, and then join them together into a single name like &lt;code&gt;Persian|Vulpix&lt;/code&gt; or &lt;code&gt;Blastoise|Persian|Vulpix&lt;/code&gt;. By storing each place name I had already been, I could avoid accidentally back-tracking through parts of the maze. This greatly sped up how long the search took to solve.&lt;/p&gt;
&lt;h3&gt;The final results&lt;/h3&gt;
&lt;p&gt;After running and re-running to find the best solutions, these were the solutions I found. Note that Persian, Blastoise, and Vulpix are in all of them:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Shellder
Hitmonchan
Ninetales
Cubone
Jigglypuff
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Shellder
Hitmonchan
Ninetales
Cubone
Jynx
Wigglytuff
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Shellder
Hitmonchan
Primeape
Cubone
Jigglypuff
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Shellder
Rhyhorn
Clefable
Charmeleon
Geodude
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Oddish
Clefable
Rhyhorn
Charmeleon
Geodude
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Sandshrew
Rhyhorn
Clefable
Charmeleon
Geodude
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Sandshrew
Rhyhorn
Clefable
Charmeleon
Pidgeotto
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Rapidash
Rhyhorn
Clefable
Charmeleon
Geodude
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Growlithe
Sandslash
Rhyhorn
Clefable
Charmeleon
Geodude
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Persian
Blastoise
Vulpix
Meowth
Shellder
Hitmonchan
Primeape
Cubone
Jigglypuff
Weezing
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;While writing this post, I had to go back through and double check everything. After all, who would ever want to be wrong on the internet?&lt;/p&gt;
&lt;p&gt;I took one of the sets of phonemes from these final results and checked each phoneme against the list at the beginning. There was one missing. Apparently, throughout my process cleaning, running, readjusting, etc I had thought that there were 38 phonemes present, but it was just an errant &lt;code&gt;ˌ&lt;/code&gt; in &lt;code&gt;/ˌpɪdʒiːˈoʊɾoʊ/&lt;/code&gt; and a few others that had caused the number to look right when it wasn&#039;t. Upon cleaning that final non-phoneme up, my solutions all read 37. The missing phoneme throughout all of this has been &lt;code&gt;ð&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Sure, there&#039;s some &lt;a href=&quot;https://en.wikipedia.org/wiki/Sunk_cost&quot;&gt;sunk cost&lt;/a&gt; aspect to have written all of this only to have the answers to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Is it possible to make a phonetic pangram from pokemon names?&amp;quot; and more specifically, &amp;quot;Can we do so using only the 151 from the first generation of pokemon?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;be &amp;quot;no.&amp;quot; I double-checked that I hadn&#039;t missed any pronunciations. Was Growlithe maybe actually pronounced like &amp;quot;tithe&amp;quot;? No, it definitely used &lt;code&gt;θ&lt;/code&gt; in the pronunciation guide.&lt;/p&gt;
&lt;p&gt;Ok, so the above solutions are sufficient for 37/38 phonemes, which seems like as good as could be done for gen 1. What generation of pokemon does &lt;code&gt;ð&lt;/code&gt; first show up in? According to the same dataset I got these gen 1 pronunciations from, it wasn&#039;t until &lt;a href=&quot;https://antifandom.com/pokemonlp/wiki/Pok%C3%A9mon_Pronunciation_Guide/Generation_IX&quot;&gt;Gen IX&lt;/a&gt; that there finally was a pokemon whose english pronunciation contained &lt;code&gt;ð&lt;/code&gt;. It was &lt;a href=&quot;https://bulbapedia.bulbagarden.net/wiki/Slither_Wing_(Pok%C3%A9mon)&quot;&gt;Slither Wing&lt;/a&gt;. The only other pokemon to ever have &lt;code&gt;ithe&lt;/code&gt; in its name was Growlithe.&lt;/p&gt;
&lt;p&gt;To get a phonetic pangram with pokemon, it&#039;s possible to add Slither Wing to any of the above solutions and have 11 names cover it. I&#039;ll postpone looking into phonetic pangrams across all gens for &lt;a href=&quot;/s/a-blog/035-pokemon-phonetic-pangram&quot;&gt;a future post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As for gen 1 specifically, maybe I&#039;ll try to start saying Growlithe with a &lt;code&gt;ð&lt;/code&gt; from now on, and say it&#039;s 11 pokemon for gen 1 to make a phonetic pangram. You might say &amp;quot;but if Growlithe uses &lt;code&gt;ð&lt;/code&gt;, then how will you get the &lt;code&gt;θ&lt;/code&gt; you previously used it to cover?&amp;quot; and I would reply simply:&lt;/p&gt;
&lt;p&gt;Meowth &lt;code&gt;/miːˈaʊθ/&lt;/code&gt;, that&#039;s right.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Note that while my previous pangrams included the &lt;code&gt;/x/&lt;/code&gt; sound of &amp;quot;loch&amp;quot; and &amp;quot;chutzpah&amp;quot;, this is a rare and often excluded phoneme for General American English. I included it in those because it was a fun constraint to work around, but I&#039;m ignoring it here because no pokemon in any gen have that sound at all, and it&#039;d be a kind of boring exercise. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This is the rolled r trill that gets used in Spanish and Scottish English, among other places. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Gen 1 didn&#039;t have the concept of pokemon gender outside of these two names. Gen 2 added gender for every pokemon, but never consolidated Nidoran into a single entry for legacy pokedex numbering reasons. The anime includes &lt;a href=&quot;https://youtu.be/EJHqzKQ3guQ&quot;&gt;a pokedex entry that does say the gender&lt;/a&gt; but also includes &lt;a href=&quot;https://youtu.be/xMk8wuw7nek&quot;&gt;the pokerap, which does not say the gender&lt;/a&gt;. Human characters in the anime tend not to say the gender, and I imagine this would be the case in real life too: you wouldn&#039;t say the gender unless specifically asked or unless you had to disambiguate. &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;You may remember this as &lt;a href=&quot;/s/a-blog/001-wizard-sokoban&quot;&gt;Wizard Sokoban&lt;/a&gt; prior to the name change last year. &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Silver-bordered in that game means &amp;quot;don&#039;t take this too seriously&amp;quot; and tends to involve meta-mechanics and humor. &lt;a href=&quot;#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;A space character in the pronunciation was treated as a distinct phoneme, and then &lt;code&gt;/ˈniːdoʊɹæn (ˈfiːmeɪl)/&lt;/code&gt; added a bunch more phonemes to the set, so it was always selected &lt;a href=&quot;#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Unfair Flips World Record Strategy</title>
          <link href="https://graham.build/s/a-blog/028-unfair-flips-world-record-strategy/" />
          <id>https://graham.build/s/a-blog/028-unfair-flips-world-record-strategy/</id>
          <published>2025-10-14T06:00:00.000Z</published>
          <updated>2025-10-14T06:00:00.000Z</updated>
          <category>unfair flips</category>
<category>video games</category>
<category>speedrunning</category>
          <content type="html">
            &lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game about flipping a coin to get 10 Heads flips in a row.&lt;/p&gt;
&lt;iframe src=&quot;https://store.steampowered.com/widget/3925760/?t=Unfair%20Flips%20is%20a%20non-idle%20clicker%20game%20about%20flipping%20a%20coin%20that%20hates%20you.%20Starting%20with%20just%20a%2020%25%20chance%20of%20getting%20heads%2C%20can%20you%20get%20ten%20heads%20in%20a%20row%3F%20&quot; frameborder=&quot;0&quot; width=&quot;646&quot; height=&quot;190&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game about how humans interact with variable probability.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game about how people interpret the information presented to them, relative to the seemingly random outcomes they experience.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game about why people play games at all, when there&#039;s only a finite amount of time to experience them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game with &lt;a href=&quot;https://www.speedrun.com/unfairflips&quot;&gt;a speedrunning community&lt;/a&gt;. The rules of the speedrun say that time starts when the first coin is flipped and ends when one of the various endings occurs and then number of total flips is displayed. The current world-record strategy routeing seems like an optimal series of upgrades to minimize time played, along with a lot of luck. Statistically speaking, the variance in flips will eventally produce a relatively fast run. The minimum required number of flips per run is 10 Heads and no Tails. With enough time across enough runners, it&#039;s possible that someone will even get &lt;em&gt;this&lt;/em&gt; lucky. Other speedruns tend to rely on memorization, dexterity, and endurance. While the orders of upgrades could land in those former categories, the repeated flipping of the coin lies squarely in the lattermost category.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game made by Heather Flowers in Unity. Using &lt;a href=&quot;https://www.jetbrains.com/decompiler/&quot;&gt;JetBrains&#039;s dotPeek decompiler&lt;/a&gt;, I read through the &lt;code&gt;CoinFlip.cs&lt;/code&gt; file, verifyng that the code for whether a coin lands Heads or Tails is solely&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; based on Heads flip percentage and Unity&#039;s pseudorandom number generator:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cs&quot;&gt;// CoinFlip.cs
bool heads = (double) UnityEngine.Random.Range(0.0f, 1f) &amp;lt; (double) coinFlip.flipHeadsChance;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game made in &lt;a href=&quot;https://unity.com/releases/editor/whats-new/2022.3.62f2&quot;&gt;Unity 2022.3.62.f2&lt;/a&gt;, which relies on &lt;a href=&quot;https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Random.html&quot;&gt;the default pseudorandom number generator&lt;/a&gt;, which is further reliant on an &lt;a href=&quot;https://en.wikipedia.org/wiki/Xorshift&quot;&gt;XORshift128&lt;/a&gt;-style algorithm. The seed of this pRNG algorithm is determined on app start:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is statically initialized with a high-entropy seed from the operating system, and stored in native memory where it will survive domain reloads. This means that the generator is seeded exactly once on process start, and after that is left entirely under script control.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;An approximate implementation of Unity&#039;s &lt;code&gt;Random.Range&lt;/code&gt; function can be found &lt;a href=&quot;https://gist.github.com/macklinb/a00be6b616cbf20fa95e4227575fe50b&quot;&gt;here&lt;/a&gt;. Because XORshift128 is not cryptographically secure, it is possible to determine the seed of an XORshift128-style pRNG by observation of outputs alone. This could be done in &lt;a href=&quot;https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f&quot;&gt;as few as three sequential random numbers&lt;/a&gt;, if all of the bits of the number were revealed. By determining the seed, it would be possible to know whether the next number accessed from this generator would correspond to a Heads or a Tails. In fact, it would be possible to look arbitrarily far ahead and figure out when a sequence of numbers would produce 10 Heads and a game win. In addition to the &lt;code&gt;Random.Range&lt;/code&gt; call for determining Heads or Tails, the code for flipping the coin includes a random call for number of turns of the coin in the flip animation, a random call for the sound to play during the flip, a random call on the 9th Heads flip to determine the ending, and - if the ending is Tails - another random call to determine the sound of the coin landing. This means that each flip could reveal about a half-dozen bits if all these parts were well-observed. However, according to the rules of the speedrun, time starts at first flip, which means time would be ticking while the flips are being performed to reverse engineer the seed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game with one non-player character: Gar, the mongoose-mask-wearing milk-drinking bar patron. Gar drinks this milk throughout the course of play. Gar&#039;s drink function is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cs&quot;&gt;// Gar.cs
private IEnumerator Drink()
  {
    while (true)
    {
      if (this.ableToDrink)
      {
        yield return (object) new WaitForSeconds(Random.Range(30f, 60f));
        if (this.ableToDrink)
          this.img.sprite = this.drink1;
        yield return (object) new WaitForSeconds(1f);
        if (this.ableToDrink)
          this.img.sprite = this.drink2;
        yield return (object) new WaitForSeconds(Random.Range(2f, 5f));
        if (this.ableToDrink)
          this.img.sprite = this.drink1;
        yield return (object) new WaitForSeconds(1f);
        if (this.ableToDrink)
          this.img.sprite = this.baseSprite;
      }
      yield return (object) null;
    }
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Gar&#039;s drinking is completely independent of the player&#039;s actions and continues even in the main menu, on start-up, just after the random seed is initialized. A &amp;quot;&lt;a href=&quot;https://en.wikipedia.org/wiki/Computer_vision&quot;&gt;diligent observer&lt;/a&gt;&amp;quot; could note how many seconds it takes Gar to begin drinking, as well as how long it takes Gar to put down the milk glass, and those seconds could be used to reveal bits about the random seed, which could then be reverse engineered through the same mechanisms above. After enough careful observation, it could be possible to determine that a given seed would produce the right random numbers for exactly 10 Heads flips in a row at some future point.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game that runs at 60fps. By observing frames of Gar&#039;s drinking habits, an &amp;quot;&lt;a href=&quot;https://opencv.org/&quot;&gt;extraordinarily diligent observer&lt;/a&gt;&amp;quot; could note how many frames it takes Gar to begin drinking, thereby how many seconds, and also thereby gaining additional decimal places - meaning extra bits - of precision on what the &lt;code&gt;Random.Range&lt;/code&gt; number is. The same is true for how many frames it takes Gar to put down the milk after drinking, though the total number of bits leaking through would be fewer, due to the smaller range bounds.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game with a theoretical optimal strategy: use tools to determine the random seed over the course of days or weeks of the game running and Gar drinking milk, begin a timer and the first flip at exactly the moment when the tool says that there&#039;s a 100% chance, and then complete 10 Heads flips in a row. As of the timer starting, no tools would be necessary&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;. The runner would flip Heads 8 times, gain access to the upgrades, mash the &lt;code&gt;-0.2 seconds flip time&lt;/code&gt; button, flip a 9th Heads and have the upgrade menu disappear, and then flip the 10th Heads and stop the timer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game that will someday have a glitchless, tool-unassisted World Record of around ~19.6 seconds from start to finish of the recording. It will take days or weeks of observations&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;, followed by some random amount of time having to wait for the right opening, and then about 20 seconds of flipping. To me, this amount of work to get the World Record run is just barely too much to be worthwhile. I have loved the process of digging into how a run like this could be done,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; but I don&#039;t have plans on trying it myself.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; is a game about why people play games at all, when there&#039;s only a finite amount of time to experience them.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;My apologies to &lt;a href=&quot;/s/a-blog/026-unfair-flips-fatt-playthrough&quot;&gt;The Red Duke and The Blue Baron&lt;/a&gt; for this existential threat to their existence. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In fact, the recording instructions for the speedrun specifically state that the runner needs only submit a recording of the first flip through the 10th Heads, along with the total number of flips. This recording, if done according to the rules, could be impossible to differentiate from a recording of someone just happening to get extraordinarily lucky. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Unless it&#039;s possible to speed up the framerate to compress the time that an automated tool takes to reverse-engineer the random seed. &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Shoutouts to both &lt;a href=&quot;http://gameboat.org/&quot;&gt;Colin&lt;/a&gt; and &lt;a href=&quot;https://www.witchoflight.com/&quot;&gt;Cassie&lt;/a&gt; for helping me bounce ideas off of them while going through this process. &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Working on a game called Nimnim</title>
          <link href="https://graham.build/s/a-blog/027-working-on-a-game-called-nimnim/" />
          <id>https://graham.build/s/a-blog/027-working-on-a-game-called-nimnim/</id>
          <published>2025-10-13T20:00:00.000Z</published>
          <updated>2025-10-13T20:00:00.000Z</updated>
          <category>game development</category>
<category>mtg</category>
<category>nim</category>
<category>video games</category>
          <content type="html">
            &lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;Every game of Magic: the Gathering can technically be won by making another player try to draw a card when there are no cards left in their deck, a strategy called &amp;quot;milling.&amp;quot;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; In custom fan formats like &lt;a href=&quot;https://breezewiki.pussthecat.com/mtg/wiki/Forgetful_Fish&quot;&gt;Dandân&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;, there is a single deck shared between the two players, which encourages milling as a more serious backup strategy if the whole &amp;quot;making your opponent lose life&amp;quot; thing doesn&#039;t work out. Recently, I became curious what a custom format might look like if milling was not only a backup but the only strategy? Constraints breed creativity, after all.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Nim&quot;&gt;Nim&lt;/a&gt; is a much older game than MTG about trying not to be the last player to remove an object from a central pile. Every turn, each player can choose to pick up one object, pick up two objects, or pick up half of the remaining objects. It&#039;s often used as an example game with easy rules to implement in introductory computer-science classes, since the game strategy is solved and coding that strategy is simple to do. Part of what makes the strategy so simple is that both players always have the same actions they can take each turn, and the information of what a player can do and how it&#039;ll affect the game is publicly known.&lt;/p&gt;
&lt;p&gt;The more I thought about a milling format in MTG, the more it reminded me of Nim: there&#039;s a central pile of objects which each player can affect each turn&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; and when the pile runs out, a player loses. If you look deep enough into the history of MTG, you can even find cards that sort of do the same things as each of the actions in Nim:&lt;/p&gt;
&lt;div class=&quot;image-flex-grid&quot;&gt;
&lt;a class=&quot;big&quot; href=&quot;https://scryfall.com/card/stx/255/excavated-wall&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https://cards.scryfall.io/normal/front/f/e/fed54d00-b11f-4529-864c-63a114617b36.jpg&quot; alt=&quot;Excavated Wall: {1}, {T}: Mill a card.&quot;&gt;&lt;/p&gt;
&lt;/a&gt;
&lt;a class=&quot;big&quot; href=&quot;https://scryfall.com/card/brr/32/millstone&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https://cards.scryfall.io/large/front/4/6/46097ab2-bfa7-4f36-a523-2522810da3ab.jpg&quot; alt=&quot;Millstone: {2}, {T}: Target player mills 2 cards&quot;&gt;&lt;/p&gt;
&lt;/a&gt;
&lt;a class=&quot;big&quot; href=&quot;https://scryfall.com/card/m14/77/traumatize&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https://cards.scryfall.io/large/front/9/b/9b8784dd-83f9-41f8-aedc-f0f81073ffcb.jpg&quot; alt=&quot;Traumatize: target player mills half their library, rounded down.&quot;&gt;&lt;/p&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The cards constraining the actions in MTG tend to be mostly hidden information, and player access to those actions is all dependent on card-drawing. Each player can only hold so many cards in their hand at the end of their turn, and having more cards tends to be better. Ultimately, a game of MTG like Nim boils down to &amp;quot;What happens to the last couple of cards left in the deck?&amp;quot; The rest of the time playing is just about trying to set up for that moment. Nim is turn-based with each player taking only one action. In contrast, MTG has &amp;quot;instants&amp;quot; and &amp;quot;activated abilities&amp;quot; which can be played outside that turn structure, and which follow MTG&#039;s &amp;quot;spells and abilities on the stack&amp;quot; rules for resolution.&lt;/p&gt;
&lt;p&gt;From these two ideas, I set out to make a Nim-flavored format of MTG, which I&#039;ve been calling &lt;a href=&quot;https://cubecobra.com/cube/list/nimnim&quot;&gt;Nimnim&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;. Because Blue is the most draw-focused and mill-focused &lt;a href=&quot;https://breezewiki.pussthecat.com/wiki/mtg/Color_identity&quot;&gt;color identity&lt;/a&gt;, I decided to ignore all other color identities. I searched through hundreds of Blue and/or Colorless cards on scryfall, removing anything that relied on loss of life or other alternate win conditions, and collecting anything that felt similar in spirit to the goals of Nim. Because I was looking for individual cards that looked like they would fit in a format like this, I wound up with a singleton set of a few hundred.&lt;/p&gt;
&lt;p&gt;Next, I began to think about what the end of the game would look like. If I wanted the stack to grow to 4-to-5 spells back and forth on the last turn of the game, then the vast majority of cards would have to be very cheap to play. It became difficult to continue to cull cards somewhere around 150 because there were so many that felt like great fits for the format, but eventually I decided that 114 should be the cut-off. The opening hand in magic contains 7 cards, so once the two people comprising a 1v1 match drew their starting hands, that would leave a nice round 100 to work with as the remaining colleciton for Nimnim.&lt;/p&gt;
&lt;h3&gt;Blue Herrings&lt;/h3&gt;
&lt;p&gt;When designing a 1v1 Blue mirror format, it was really tempting to throw in a bunch of &lt;a href=&quot;https://scryfall.com/card/dsc/114/counterspell&quot;&gt;counterspells&lt;/a&gt;, since that&#039;s such a core part of the Blue identity in MTG. However, I found that these tended to be too harsh of a play experience. When a counterspell is played, at least one player tends to wind up not getting to play MTG. I wanted Nimnim to have this momentum of inevitability behind it. No matter what you did, the end of the game would arrive and you had to plan for it rather than just planning to thwart your opponent&#039;s plans and win by default. I wound up removed every spell that outright countered&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt;. Instead, I only kept ones like &lt;a href=&quot;https://scryfall.com/card/rvr/59/remand&quot;&gt;Remand&lt;/a&gt;, &lt;a href=&quot;https://scryfall.com/card/2xm/54/hinder&quot;&gt;Hinder&lt;/a&gt;, and &lt;a href=&quot;https://scryfall.com/card/ema/60/memory-lapse&quot;&gt;Memory Lapse&lt;/a&gt;. The latter of these are particularly nice because they allow for continued battling over the top card of the deck, and they can disrupt the math around the total remaining number of cards in the deck.&lt;/p&gt;
&lt;p&gt;Another natural Blue identity to lean on is manipulation of handsize. Things like &lt;a href=&quot;https://scryfall.com/card/m10/220/spellbook&quot;&gt;Spellbook&lt;/a&gt; and &lt;a href=&quot;https://scryfall.com/card/vis/141/anvil-of-bogardan&quot;&gt;Anvil of Bogardan&lt;/a&gt; were considered because they meant more actions per player, which meant more agency, and -- hopefully -- more fun and faster games. In practice, being able to keep more than 7 cards in your hand at the end of your turn absolutely exploded the possibility space to consider, and with the fact that there were no repeat cards except Islands, this led to extremely long turns and even longer games to weigh the many branching options. Those handsize effect cards were all cut. Obviously, drawing is still a hugely important part of the game, but now you simply have to balance between &amp;quot;getting the card you &lt;em&gt;really&lt;/em&gt; want via casting extra draw spells&amp;quot; and &amp;quot;ending the turn with too many good cards in your hand and having to discard to hand-size.&amp;quot;&lt;/p&gt;
&lt;p&gt;In certain sets, Blue tends to have lots of artifacts and enchantments with abilities. I wanted to find some that generally provided a big benefit to both players and also ideally a little benefit to one of them, like &lt;a href=&quot;https://scryfall.com/card/5dn/135/lantern-of-insight&quot;&gt;Lantern of Insight&lt;/a&gt;. This proved difficult, though! &lt;a href=&quot;https://scryfall.com/card/wth/162/well-of-knowledge&quot;&gt;Well of Knowledge&lt;/a&gt; allowed the player with a mana advantage to convert it into a card advantage, in addition to having an ability that could be performed many times in the final turn pretty cheaply. Cards like &lt;a href=&quot;https://scryfall.com/card/cn2/211/horn-of-greed&quot;&gt;Horn of Greed&lt;/a&gt; and &lt;a href=&quot;https://scryfall.com/card/kld/216/ghirapur-orrery&quot;&gt;Ghirapur Orrey&lt;/a&gt; have symmetrically beneficial abilities, but with how much access to instant-speed bounce effects there are in this cube, the player who usually benefitted the most from the card tended to be the one who didn&#039;t play it.&lt;/p&gt;
&lt;p&gt;While I wanted to include some permanents with one-sided abilities, after trying out &lt;a href=&quot;https://scryfall.com/card/mkc/119/teferis-ageless-insight&quot;&gt;Teferi&#039;s Ageless Insight&lt;/a&gt; and &lt;a href=&quot;https://scryfall.com/card/2x2/303/crucible-of-worlds&quot;&gt;Crucible of Worlds&lt;/a&gt;, I realized that there were certain abilities that were simply too strong to be worth keeping in. Teferi&#039;s Ageless insight provided such a huge advantage for one player that the downside of potentially causing your own demise was heavily mitigated by sifting through for the best answers. Lands can be among the most valuable cards early on, with the player who gets ahead on them often being able to access more cards over the length of the game. This mean that more often, Crucible of Worlds wound up being a &amp;quot;win more&amp;quot; card rather than a means to get back into a game. With such little in terms of downsides, these one-sided benefit permanents were too much and I removed them and others like them from the set.&lt;/p&gt;
&lt;h3&gt;What&#039;s going well, so far?&lt;/h3&gt;
&lt;p&gt;With the aforementioned goal of inevitable momentum, I&#039;ve found that heavily restraining cards that can recycle from the graveyard in any way has been extremely effective. The only ones currently which pull cards out of the graveyard are &lt;a href=&quot;https://scryfall.com/card/5dn/112/conjurers-bauble&quot;&gt;Conjurer&#039;s Bauble&lt;/a&gt;, &lt;a href=&quot;https://scryfall.com/card/mkc/277/mystic-sanctuary&quot;&gt;Mystic Sanctuary&lt;/a&gt;, and &lt;a href=&quot;https://scryfall.com/card/ody/323/petrified-field&quot;&gt;Petrified Field&lt;/a&gt;, and only two of them return the recycled card to the deck. Because of this, we avoid situations where it feels like the number of remaining cards is ever increasing, and in the bauble&#039;s case, the drawn card makes up for the recycled card, so the endgame still arrives on-time.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://breezewiki.pussthecat.com/mtg/wiki/flashback&quot;&gt;Flashback&lt;/a&gt; is a wonderful mechanic for milling-centric decks in regular MTG, and it is absolutely at home in Nimnim as well. There are times where a powerful effect from a card has to be weighed against the ability for the opponent to cast the same card for its flashback cost soon after. On the other hand, flashback cards can create interesting emergent gameplay when the randomly milled cards from the deck include some of these flashback cards, which then generates new options.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://breezewiki.pussthecat.com/mtg/wiki/delve&quot;&gt;Delve&lt;/a&gt; is another mechanic that balances flashback out well and makes use of the fact that there are going to be dozens of cards in the graveyard in every game of Nimnim at some point. Cards like &lt;a href=&quot;https://scryfall.com/card/tdc/169/treasure-cruise&quot;&gt;Treasure Cruise&lt;/a&gt; and &lt;a href=&quot;https://scryfall.com/card/dsc/115/dig-through-time&quot;&gt;Dig Through Time&lt;/a&gt; were strong in their own right when they came out, but with the shared graveyard, and especially with cards with Flashback or &lt;a href=&quot;https://breezewiki.pussthecat.com/mtg/wiki/retrace&quot;&gt;Retrace&lt;/a&gt; or &lt;a href=&quot;https://breezewiki.pussthecat.com/mtg/wiki/escape&quot;&gt;Escape&lt;/a&gt; being so valuable in Nimnim, these delve cards become some of the strongest in the whole format because of how much graveyard disruption they can manage.&lt;/p&gt;
&lt;p&gt;Many of the cards are deceptively simple. Mental Note, for example, is a card I used to play in Nimnim whenever I saw it because it was cheap and was a cantrip.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn6&quot; id=&quot;fnref6&quot;&gt;[6]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;image-flex-grid&quot;&gt;
&lt;a class=&quot;big&quot; href=&quot;https://scryfall.com/card/jud/46/mental-note&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https://cards.scryfall.io/large/front/1/f/1f343724-6ecd-494f-8bfc-93676af4e173.jpg&quot; alt=&quot;Mental Note - Instant: Mill two cards. Draw a card.&quot;&gt;&lt;/p&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;However, with the cost being so low, it being at instant speed, and it disrupting 3 cards in the deck all make it a useful card in the late game. If your opponent began their turn with 3 cards left in the deck, you could play this just before their draw step and they would have to do something at instant speed to avoid losing the game. Meanwhile, you&#039;ve only expended one mana, so there&#039;s still plenty of room to follow it up even if they do have an answer.&lt;/p&gt;
&lt;p&gt;Finally, I&#039;ve really enjoyed &lt;a href=&quot;https://breezewiki.pussthecat.org/mtg/wiki/scry&quot;&gt;scry&lt;/a&gt;, &lt;a href=&quot;https://breezewiki.pussthecat.org/mtg/wiki/surveil&quot;&gt;surveil&lt;/a&gt;, and cards like &lt;a href=&quot;https://scryfall.com/card/m13/55/index&quot;&gt;Index&lt;/a&gt;, which all let you affect what&#039;s coming up next in the deck. There&#039;s this back-and-forth meta-game about how to order the cards that I find captivating. If left in order, each player will draw each card during their turn. This means the person sorting through the cards should give themselves the best cards and their opponent the worst ones. However, since neither players knows what cards are in the other&#039;s hand, it can be difficult to play around what instant-speed effects the opponent may have, even if you have a few of your own. I&#039;ve seen cases during playtesting where both players know the top card is powerful and then several spells get played to try to fight over trying to draw it first. This sort of metagame of locking your opponent into bad cards encourages interesting play in the early-to-mid-game, from my experience, and it makes the skill ceiling and replayability of the format increase as well.&lt;/p&gt;
&lt;h3&gt;What&#039;s next?&lt;/h3&gt;
&lt;p&gt;I&#039;ve played Nimnim a handful of times with my buddy, 2Blave, to playtest it, and I have yet to outright win.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn7&quot; id=&quot;fnref7&quot;&gt;[7]&lt;/a&gt;&lt;/sup&gt; Playtesting has all been done on TableTopSimulator thus far, since the &amp;quot;only one deck&amp;quot;, &amp;quot;shared graveyard&amp;quot;, and &amp;quot;no keeping track of lifetotals&amp;quot; all deviate pretty significantly from the more commonly supported online MTG formats. There continues to be a set of mechanics that are a little bit awkward in TTS, like searching the deck for anything or putting the card on the bottom during a Scry ability, but we&#039;re able to make do for now. As we continue to refine, I&#039;ll probably eventually get to a point where I set up a mod in the workshop for playing it, though I can&#039;t promise I&#039;ll do any scripting.&lt;/p&gt;
&lt;p&gt;As of writing this, &lt;a href=&quot;https://cubecobra.com/cube/list/nimnim&quot;&gt;Nimnim&lt;/a&gt; has 80+ unique cards that aren&#039;t basic Islands, and that complexity alone means it continues to be a game for absolute sickos with a bunch of time on their hands. It has been difficult to find people to test it with, even among various groups of MTG fans I&#039;m connected to online. I&#039;m hopeful that future iterations will be a lower time commitment. Ideally, something like 60-90 minutes per game would be nice.&lt;/p&gt;
&lt;p&gt;These last few points have another solution: remove MTG altogether, create new and simplified cards that fit exactly what I&#039;m looking for with this format, remove mana in favor of some easier to explain action economy, and then ideally start playtesting with folks who aren&#039;t familiar with MTG at all. It&#039;d be a ton of work, but it&#039;d be just as easy to playtest in TTS, and if it did wind up being fun, I could see there being two different style versions of the game based on difficulty, just like how &lt;a href=&quot;https://en.wikipedia.org/wiki/Spiel_des_Jahres&quot;&gt;Spiel des Jahres&lt;/a&gt; has different tiers for family-style games and connossieur-style games.&lt;/p&gt;
&lt;p&gt;In the meantime, feel free to reach out if you have questions or anything, and hopefully I&#039;ll have more progress soon.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Because of &lt;a href=&quot;https://scryfall.com/card/atq/56/millstone&quot;&gt;https://scryfall.com/card/atq/56/millstone&lt;/a&gt; &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Named after the card &lt;a href=&quot;https://scryfall.com/card/arn/12/dand%C3%A2n&quot;&gt;Dandân&lt;/a&gt;, originally named after the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dandan&quot;&gt;mythical Arabian fish&lt;/a&gt; &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;With a minimum of one card that must be drawn by default during their &amp;quot;draw step&amp;quot; each turn. &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;From Nim + Dandân, though it could also have been called &amp;quot;Nimnîm&amp;quot; &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Meaning any spell that, once resolved, puts the countered spell into the graveyard with no upside for that spell&#039;s owner. &lt;a href=&quot;#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;A card which when played draws a new card, thereby replenishing the possible actions the player could take, as though they had spent nothing. &lt;a href=&quot;#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn7&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Most recently, I won but as we looked closer at the end of the game, it became clear that he had me beat a couple of times over and it was more a fault of the way the deck number was being reported in-game than anything good I did. I&#039;m counting it as a draw. &lt;a href=&quot;#fnref7&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Unfair Flips Friends at the Table Playthrough</title>
          <link href="https://graham.build/s/a-blog/026-unfair-flips-fatt-playthrough/" />
          <id>https://graham.build/s/a-blog/026-unfair-flips-fatt-playthrough/</id>
          <published>2025-09-28T06:55:00.000Z</published>
          <updated>2025-09-28T06:55:00.000Z</updated>
          <category>video games</category>
<category>unfair flips</category>
<category>friends at the table</category>
<category>art</category>
<category>digital art</category>
          <content type="html">
            &lt;p&gt;This weekend, I was overcome by the urge to make this extremely specific fanart.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/026-unfair-flips-fatt-playthrough/unfair_flips_red_duke_blue_baron.png&quot; alt=&quot;The Red Duke and The Blue Baron clinking their goblets of wine and milk respectively, with Jack and Austin flipping unfair coins in the foreground&quot;&gt;&lt;/p&gt;
&lt;p&gt;I recently watched Austin and Jack from &lt;a href=&quot;https://friendsatthetable.net&quot;&gt;Friends at the Table&lt;/a&gt; play &lt;a href=&quot;https://buttondown.com/HTHR&quot;&gt;Hthrflwrs&lt;/a&gt;&#039;s extremely good new video game &lt;a href=&quot;https://store.steampowered.com/app/3925760/Unfair_Flips/&quot;&gt;Unfair Flips&lt;/a&gt; by &lt;a href=&quot;https://www.twitch.tv/videos/2575439457&quot;&gt;streaming it on Twitch&lt;/a&gt;&lt;/p&gt;
&lt;script src= &quot;https://player.twitch.tv/js/embed/v1.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;twitch_video_player&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
  var options = {
    width: 800,
    height: 450,
    video: &quot;2575439457&quot;,
    autoplay: false,
    muted: true,
    parent: [&quot;graham.build&quot;]
  };
  var player = new Twitch.Player(&quot;twitch_video_player&quot;, options);
  player.setVolume(0.5);
&lt;/script&gt;
&lt;p&gt;Over the course of the roughly three hour stream, Austin and Jack -- among other things&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; -- invented a pair of delightfully frustrating fictional oligarchs named The Red Duke and The Blue Baron, who alternated between jabs at their subjects (the streamers) and talking to each other about the rousing match of coin flips the were playing vicariously through them.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Austin also read a long excerpt about how wine and milk are two ends of a spectrum among drinks. I forget which book excerpt it came from, but it was a great time. In my headcannon, The Blue Baron is a milk-drinker, while The Red Duke drinks wine. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Poliwhirl's Mouth</title>
          <link href="https://graham.build/s/a-blog/020-poliwhirls-mouth/" />
          <id>https://graham.build/s/a-blog/020-poliwhirls-mouth/</id>
          <published>2025-05-03T18:30:00.000Z</published>
          <updated>2025-05-03T18:30:00.000Z</updated>
          <category>pokemon</category>
<category>video games</category>
<category>art</category>
<category>digital art</category>
          <content type="html">
            &lt;p&gt;I spent some time this morning thinking about Pokémon. Specifically, I considered how the poliwag, poliwhirl, poliwrath evolution line mimics poliwogs, frogs, and frog-themed wrestlers. While considering this, I noticed that poliwag&#039;s mouth is separate from the hypnotic spiral on its front:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/020-poliwhirl&#039;s-mouth/poliwag.png&quot; alt=&quot;the default photo of poliwag, the tadpole pokemon showing its mouth above the spiral&quot;&gt;&lt;/p&gt;
&lt;p&gt;This led me to consider how poliwhirl&#039;s mouth must work. I came up with the following two options, which I illustrated by hand on my phone:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/020-poliwhirl&#039;s-mouth/poliwhirl_mouth.png&quot; alt=&quot;normal poliwhirl at the top, an arrow down to the left of poliwhirl illustrated in all blue with a thin black mouth line, and an arrow down to the right of poliwhirl illustrated to open a mouth that sort of peels away the spiral to open&quot;&gt;&lt;/p&gt;
&lt;p&gt;I think the one on the right is technically more frog-like, while the left just looks like a blue Dot Gobbler.&lt;/p&gt;

          </content>
        </entry>
      

        <entry>
          <title>Crowdpleaser Words</title>
          <link href="https://graham.build/s/a-blog/017-crowdpleaser-words/" />
          <id>https://graham.build/s/a-blog/017-crowdpleaser-words/</id>
          <published>2025-01-12T23:30:00.000Z</published>
          <updated>2025-01-12T23:30:00.000Z</updated>
          <category>video games</category>
<category>game development</category>
<category>puzzles</category>
          <content type="html">
            &lt;p&gt;As part of the &lt;a href=&quot;https://discord.gg/ZkV2zdb&quot;&gt;thinky puzzle games discord&lt;/a&gt;, some folks began running the &lt;a href=&quot;https://confoundingcalendar.itch.io/&quot;&gt;Confounding Calendar&lt;/a&gt; project, which I got to experience for the first time this past year (2024). My favorite entry from those was a game called &amp;quot;Alphabet Soup for Picky Eaters&amp;quot; which is a combination of a code-breaking word-guessing game and a bunch of absolutely delightful little guys of different colors to make use of the yearly Confounding Calendar chosen color palette. If you haven&#039;t played it, I highly recommend doing so.&lt;/p&gt;
&lt;iframe title=&quot;Alphabet Soup for Picky Eaters itch.io embed&quot; frameborder=&quot;0&quot; src=&quot;https://itch.io/embed/3086189&quot; width=&quot;552&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https://managore.itch.io/alphabet-soup-for-picky-eaters&quot;&gt;Alphabet Soup for Picky Eaters by Daniel Linssen&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;After playing it, I felt a similar feeling to how I felt when I first played Wordle. Here was a game that was a delightful 10-15 minute puzzle, it didn&#039;t overstay its welcome, and it also happened to have a handful of solutions that could all suffice. I began imagining trying to make a version that could handle the &amp;quot;new word every day&amp;quot; and more importantly &amp;quot;new set of rules every day.&amp;quot;&lt;/p&gt;
&lt;p&gt;This weekend, I had some free time and needed a distraction for a handful of reasons, and so I finally decided to dive into making a prototype. I&#039;ve been building UI-heavy browser-focused games in React lately as a way to avoid having to learn the arcane and cursed UI programming behind more conventional game engines.&lt;/p&gt;
&lt;p&gt;It took the better part of an afternoon, but I was able to set up a list of popular English words and various rules to clue them so that the game could provide a countdown and automatically choose a new word every day at midnight pacific and the rules could vary each day, as well. I aimed to have at least 5 words that appeased all the judges per day so that it&#039;s not too difficult. I also have made sure that it plays pretty smoothly on both mobile and desktop. You can play it on my &lt;a href=&quot;http://itch.io&quot;&gt;itch.io&lt;/a&gt; page.&lt;/p&gt;
&lt;iframe title=&quot;Crowdpleaser Words itch.io embed&quot; frameborder=&quot;0&quot; src=&quot;https://itch.io/embed/3237987?linkback=true&amp;amp;bg_color=222&amp;amp;fg_color=FFF&amp;amp;link_color=327345&amp;amp;border_color=333333&quot; width=&quot;552&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https://anvilfood.itch.io/crowdpleaser-words&quot;&gt;Crowdpleaser Words by graham&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;After getting some feedback from friends and a few discord servers I&#039;m in, I added the ability to write down notes as you go along, and I&#039;ve also added a way to get hints in the form of the game telling you what kind of rule a given judge is particular about. It won&#039;t give you all the info you need to solve the puzzle, but hopefully it&#039;s enough to be a stepping stone towards the solution. Additionally, if you finish the game with a guess unexpectedly, you can refresh to see what the rules were that you unintentionally satisfied.&lt;/p&gt;
&lt;p&gt;Making this game was a lot of fun, and it was a much quicker feedback loop to prototype than other games I&#039;ve tried to make this year like &lt;a href=&quot;/s/a-blog/001-wizard-sokoban&quot;&gt;Wizard Sokoban&lt;/a&gt; or even UI games I haven&#039;t written about here. Here&#039;s hoping that I&#039;ll have more energy to throw some new ones together in the near future.&lt;/p&gt;

          </content>
        </entry>
      

        <entry>
          <title>Slay the Spire Online</title>
          <link href="https://graham.build/s/a-blog/016-slay-the-spire-online/" />
          <id>https://graham.build/s/a-blog/016-slay-the-spire-online/</id>
          <published>2025-01-11T05:00:00.000Z</published>
          <updated>2025-01-11T05:00:00.000Z</updated>
          <category>video games</category>
<category>slay the spire</category>
<category>mods</category>
          <content type="html">
            &lt;p&gt;&lt;img src=&quot;/post-assets/016-slay-the-spire-online/slay_the_spire_example.jpg&quot; alt=&quot;A screenshot of Slay the Spire showing a handful of cards for the Defect character and a Zap+ card being played&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slay the Spire is the best roguelike deckbuilder of all time. I remember seeing it released in early access in 2017 and it took over all sorts of Twitch streams that I watched at the time. Despite loving card games and despite having enjoyed playing other hybrid-roguelikes&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; of the era&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;, I didn&#039;t buy and play Slay the Spire until it officially launched on the Nintendo Switch in June of 2019 as a game for plane rides across the country for work and visiting friends.&lt;/p&gt;
&lt;p&gt;Ever since, Slay the Spire has been a game that I play almost exclusively while traveling, whether while in transit or at my destination. I play each character&#039;s new ascension level in order before I move onto the next level. I have not beaten A20 on any character yet, but I&#039;m at A10 on all of them, and the game hasn&#039;t lost its magic for me. In 2024, I began a completely different relationship with the game: one where I play it for hours at home and with friends.&lt;/p&gt;
&lt;h3&gt;Modded Slay the Spire&lt;/h3&gt;
&lt;p&gt;Over the years since its launch, I had learned about &lt;a href=&quot;https://store.steampowered.com/app/1865780/Downfall__A_Slay_the_Spire_Fan_Expansion/&quot;&gt;the Downfall mod&lt;/a&gt; from &lt;a href=&quot;https://www.youtube.com/watch?v=vYthsh8a1Dc&quot;&gt;its original trailer&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=MK2Zayb2Alo&quot;&gt;its updated version&lt;/a&gt;, and I&#039;d also learned of &lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=1997053791&quot;&gt;the mod that Jorbs worked on&lt;/a&gt;, but I wasn&#039;t interested in trying either of them, since I wanted to get through A20 first before augmenting the 1-player experience.&lt;/p&gt;
&lt;p&gt;Then, last year, my friend who I worked with on &lt;a href=&quot;/s/a-blog/001-wizard-sokoban&quot;&gt;Wizard Sokoban&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; introduced me to another set of mods. He and I had previously played &lt;a href=&quot;https://yellowafterlife.itch.io/nuclear-throne-together&quot;&gt;Nuclear Throne together&lt;/a&gt; and been blown away at how well the mod community could execute multiplayer in a game like that. We took a look at &lt;a href=&quot;https://steamcommunity.com/workshop/filedetails/?id=2395241968&quot;&gt;Spire With Friends&lt;/a&gt;, but ultimately found it lacking.&lt;/p&gt;
&lt;p&gt;While it does offer a free way to play an online game of Slay the Spire semi-cooperatively, Spire With Friends has you each battling your own regular enemy individually, as though you were just playing the one-player game at the same time, with minor changes to make it feel like you can have an effect on each other&#039;s progress. There are new nodes on the map called &amp;quot;Couriers&amp;quot; that allow for trading between players, but because the mod is all designed around asynchronous play, you don&#039;t need to both be at the Courier to trade: one of you can leave cards for the other to pick up (or ignore!) when they get to that node. Because of this, we found it was a little bit too easy to &amp;quot;cheese&amp;quot; the game by taking bad cards out of your deck to put in the courier&#039;s send slot, and having the other player simply not take them from that slot when they arrive.&lt;/p&gt;
&lt;p&gt;After a few tries of Spire With Friends, we tried out a different mod, which we&#039;ve now been happily going back to for months.&lt;/p&gt;
&lt;h3&gt;Together in Spire&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/016-slay-the-spire-online/together_in_spire_example.jpg&quot; alt=&quot;A screenshot of the Together in Spire mod that shows three players in the same room at once fighting a jaw worm&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://steamcommunity.com/workshop/filedetails/?id=2384072973&quot;&gt;Together in Spire&lt;/a&gt; is another cooperative mod, but you actually play the game simultaneously and next to each other. Everyone in the game enters into the same room against the same enemy -- whose max health is scaled with the number of players -- and then the enemy only takes their turn once everyone in the room has clicked the End Turn button. Play continues like this, synchronized depending on who is in the room at a given time. While this can be a little grueling in parts of the late game if your friend is going infinite and you&#039;re just hanging on, we found that the difficulty and playstyle far better matched what we were looking for out of cooperative Slay the Spire than any of the alternatives.&lt;/p&gt;
&lt;p&gt;Each battle, there&#039;s usually a little bit of discussion about who will be able to apply negative effects like vulnerable or weak to the enemy, then everyone plays their damage in mostly whatever order, and sometimes we have some discussion about trying to end a given fight on a certain turn for relic or card reasons. The early fights, especially against elites can be difficult, while most of the rest of the game becomes trivially easy with more players. With two people, we find that ascension levels up to around 15 are pretty straightforward without having to do a lot of math or double-checking. With four, there&#039;s usually only one or two times in a run where anyone is in any serious danger of dying.&lt;/p&gt;
&lt;p&gt;At every campfire, there&#039;s a new free (optional) action for trading and another new action called &amp;quot;Resurrect.&amp;quot; Resurrect allows you to bring a dead teammate back to life. If they died far from a campfire, then you have to figure out a path to get to a campfire safely with whoever you have left. Trade allows any two people on the team to trade up to one relic, three potions, and three cards at a time. You both have to lock in the trade to make it take place, and unlike the Courier in Spire With Friends, you must take anything you agree to be traded. I really like that they made a way for the coop game to continue going even if one person dies, but also because Resurrect takes up the action that a person would normally do at the campfire, there&#039;s a real cost to having to do it. I find it makes the rest of the run feel earned, even if there&#039;s a death.&lt;/p&gt;
&lt;p&gt;At shops, you can trade gold with any other player as much as you like, which is a nice quality of life thing without being game-breaking.&lt;/p&gt;
&lt;p&gt;The game also autosaves, which means that even internet trouble or having to take a break doesn&#039;t get in the way of a good run.&lt;/p&gt;
&lt;h3&gt;Setup Instructions&lt;/h3&gt;
&lt;p&gt;Getting mods to work with Slay the Spire doesn&#039;t &lt;em&gt;require&lt;/em&gt; Steam, but the workshop items tend to make it easy enough for non-technical people who can follow directions to be able to do. For Together in Spire, you need to own Slay the Spire and download the following mods, which you can do by clicking the subscribe button in the workshop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=1605833019&quot;&gt;BaseMod&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=1605060445&quot;&gt;ModTheSpire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=1609158507&quot;&gt;StSLib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=2384072973&quot;&gt;Steam Multiplayer - Together in Spire&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once all of these are installed properly, you&#039;ll have an option to start Slay the Spire with mods active. Depending on the operating system, we saw this fail the first attempt on Mac, followed by it working just fine every time after that. Make sure all of these mods are enabled, and then the game should boot up, and you should be able to see &amp;quot;Multiplayer&amp;quot; as an option in your starting menu.&lt;/p&gt;
&lt;p&gt;One player can host a room for you all to play in, and they can set the settings they want to use in terms of both difficulty of the game once it&#039;s started and also who is allowed into the room. I&#039;d highly recommend &amp;quot;Friends Only&amp;quot; so that only people you&#039;re friends with on Steam can access. One time, we had a troll try to join our game and use cheats to win faster than we could.&lt;/p&gt;
&lt;p&gt;Joining a game can be done through the steam friends menu, and technically doesn&#039;t have to be at the very beginning of the game, though that&#039;s what we&#039;ve always done so that we can play through everything together.&lt;/p&gt;
&lt;p&gt;Note that A20 has had a bug for us where only 2/4 people wind up fighting the second boss of Act 3. Otherwise, there have been no bugs that have gotten in the way of a game, thankfully.&lt;/p&gt;
&lt;h3&gt;Future Considerations&lt;/h3&gt;
&lt;p&gt;As a way to play a cooperative card game with low stakes and interesting challenges, Together in Spire has absolutely delivered for us. There have been runs where we all roll random characters, runs where we each take one of the four main characters, and runs where we&#039;ve all chosen the same character.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;We find that as we all get comfortable playing, the game gets easier, so we look for harder challenges to impose. There&#039;s a &amp;quot;Hell&amp;quot; difficulty that&#039;s separate from the ascension levels that we&#039;d like to try out. We&#039;ve also talked about trying to do 2v2 races where you have to try to take different paths from one another and the first team to beat the heart wins.&lt;/p&gt;
&lt;p&gt;At the very least, having a game that has very little timing-specific gameplay, only requires a mouse and a pretty unsubstantial computer and internet connection to play, and whose runs can be an interesting way to spend a few hours in a given evening hanging out on a voice call, I imagine my friends and I will continue to play this for a while going forward.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In conversation, I&#039;d probably just use the shorthand &amp;quot;roguelikes&amp;quot; and let context clues do their thing, but I figure being extra intentional with word choice can help avoid &amp;quot;rogue/-like/-lite/etc&amp;quot; discourse. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The ones I played were mostly Nuclear Throne, Enter the Gungeon, Dungeon of the Endless, and Don&#039;t Starve. I was also very familiar with Spelunkey, Binding of Isaac, and Crypt of the Necrodancer at that point, but had either bounced off of them or had never given them a fair shot. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Now rebranded as &lt;a href=&quot;https://anvilfood.itch.io/snails-and-sorcery&quot;&gt;Snails and Sorcery&lt;/a&gt; &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;We all did Ironclad and realized that we could use the campfire trades to ensure one player had a deck that could go infinite on turn one every fight. It was goofy as hell, but it was also this person&#039;s first time playing online with the mods, so what better way to get acclimated, I suppose? &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      

        <entry>
          <title>Some Interesting Links From October</title>
          <link href="https://graham.build/s/a-blog/006-some-interesting-links/" />
          <id>https://graham.build/s/a-blog/006-some-interesting-links/</id>
          <published>2024-11-01T09:45:00.000Z</published>
          <updated>2024-11-01T09:45:00.000Z</updated>
          <category>links</category>
<category>video games</category>
<category>pokemon</category>
<category>fashion</category>
<category>politics</category>
<category>color theory</category>
          <content type="html">
            &lt;p&gt;I like reading about what other folks find interesting, but I often forget to write down what I myself have found. I&#039;ve been meaning to talk about this first link ever since I came across it, but I kept forgetting to make time until now. I figure a new month is a good a time as any to make a link-retrospective post.&lt;/p&gt;
&lt;h3&gt;Video Games&lt;/h3&gt;
&lt;p&gt;This video is not only impressive on a technical level for being able to accomplish what it set out to do, but the animations and ways that the information is conveyed is on par with a pannenkoek video in terms of making complex ideas become understable.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/jNMWkD5VsZ8&quot; title=&quot;Beating every possible game of Pokemon Platinum at the same time&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jNMWkD5VsZ8&quot;&gt;Beating every possible game of Pokemon Platinum at the same time&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Movies&lt;/h3&gt;
&lt;p&gt;I had never heard of this and it became the first RSS feed post that I&#039;ve bookmarked since making the transition over from cohost to inoreader as my means of internet browsing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.lauramichet.com/you-should-watch-these-fan-edited-movie-documentaries/&quot;&gt;Laura linked to a well-creafted treasure trove of (especially Lucasfilm) behind-the-scenes info&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Fashion&lt;/h3&gt;
&lt;p&gt;I had meant to share this CJ video because I think it does an incredible job of explaining fashion through the lens of &amp;quot;conversation with community identity,&amp;quot; and I was reminded that I wanted to share it when I saw Dante&#039;s post here. I don&#039;t know if Dante meant to be in conversation with this video, but I found watching the latter made me appreciate the former more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.dante.cool/in-defense-of-the-great-male-renunciation-sort-of/&quot;&gt;Dante in defense of the Great Male Renunciation (sort of)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/LpHFcylNGqg&quot; title=&quot;CJ the X talking about the longer historical context of fashion&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=LpHFcylNGqg&quot;&gt;CJ the X talking about the longer historical context of fashion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Color Theory&lt;/h3&gt;
&lt;p&gt;One of my special interests is color theory. I think this video does a great job of explaining how color works across a number of different disciplines, but I wish it spent more time talking about refraction, polarization, and rayleigh scattering. That being said, this whole channel is full of interesting videos that are worth checking out, and even without that stuff, this one on color theory is still good:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/6xgBSQwqAuE&quot; title=&quot;Reactions on color theory&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6xgBSQwqAuE&quot;&gt;Reactions on color theory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;XOXO 2024 Festival Talks:&lt;/h3&gt;
&lt;p&gt;I didn&#039;t get to attend this year, but I really appreciated and resonated with these three talks moreso than the others, even though I enjoyed many more.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/ddy5uMdzZB8&quot; title=&quot;Ed Yong at XOXO 2024&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ddy5uMdzZB8&quot;&gt;Ed Yong&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=H2Mb-0QrYw0&quot;&gt;Dan Olson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=MTaeVVAvk-c&quot;&gt;Molly White&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Politics&lt;/h3&gt;
&lt;p&gt;I found this retrospective of what working conditions were like under the Nevada State Democratic Party to be both insightful and harrowing. Regardless of your exact politics, I think there&#039;s a lot of stuff to think about, especially with respect to how campaigns are organized, where and how money is spent, and what the overall longterm goals are. I found reading it went by very quickly for me, and I also found that I kept thinking about it afterwards for a handful of days. Who could say why?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://post-goldfish.ghost.io/i-became-an-anarchist-while-working-for-the-nevada-state-democratic-party/&quot;&gt;i became an anarchist while working for the nevada state democratic party&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

          </content>
        </entry>
      

        <entry>
          <title>How my friend and I became Lords of Oblivion</title>
          <link href="https://graham.build/s/a-blog/005-how-my-friend-and-i-became-lords/" />
          <id>https://graham.build/s/a-blog/005-how-my-friend-and-i-became-lords/</id>
          <published>2024-10-11T10:00:00.000Z</published>
          <updated>2022-09-04T07:36:15.000Z</updated>
          <category>video games</category>
<category>elder scrolls</category>
<category>glitches</category>
<category>longposts</category>
          <content type="html">
            &lt;p&gt;The Elder Scrolls IV: Oblivion came out for the Xbox 360 on March 20, 2006 -- almost two decades ago. It launched during an era when there weren&#039;t really game wikis to google, which meant that most of the bugs and strange discoveries in the game for me came from word of mouth in my social circle.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/View_Frostcrag_Spire.webp&quot; alt=&quot;A view of Frostcrag spire from above, pulled from the Oblivion wiki&quot;&gt;&lt;/p&gt;
&lt;p&gt;Beyond the more widely-known &amp;quot;horse-armor&amp;quot; DLC launched in April of 2006, there was a number of other DLC items. The only relevant one to this story was the Frostcrag Spire quest for the &amp;quot;Wizard&#039;s Tower&amp;quot;. I did not buy it, but my friend did and we would regularly hang out. We found that if my friend logged in while he was at my house, then I was able to download and play the DLC on my console. However, either because of limitation in the storage of our hard-drives or because you could only associate your Xbox Live account with so many Xbox 360s at once, we got into this mess where I kept having to re-download the DLC every time he visited if I wanted to play it.&lt;/p&gt;
&lt;p&gt;This went on for a few weeks until one of us accidentally tried to load a save from inside the DLC even though it was not downloaded. What we found was likely not supposed to be accessible except for the developers of the game.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/test_village.jpg&quot; alt=&quot;Oblivion developer test village featuring some houses in a circle and some flat texture-less ground that comes to an abrupt end well before the skybox&quot;&gt;&lt;/p&gt;
&lt;p&gt;This demo area existed outside of the bounds of the main game, and the underlying method for how we got to it seemed to be exploiting a memory pointer. Our best guess was that the DLC overwrote some &amp;quot;unused&amp;quot; (aka only used for developer testing) memory when it was installed, so removing it points the save state at that memory location.&lt;/p&gt;
&lt;p&gt;I was spurred to undergo all of this work to reproduce the glitch because of a combination of wanting to port over the summarized version of this story from Twitter and from a Steam sale where Oblivion with all the DLC was bundled for $6. After making my way through the tutorial and going directly towards the DLC objective indicator, I summited some nearby mountains and entered the tower.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/frostcrag_spire_interior.jpg&quot; alt=&quot;Picture of the interior of Frostcrag Spire, where a giant hand made of ice is coming out of the floor in front of a tall doorway into the inner sanctum&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once I saw the ice hand on the floor, my memories of this glitch came flooding back to me. This was the room in which we first found the glitch. I saved, exited the game, and then restarted -- this time making sure to uncheck the tower DLC on startup so that it wouldn&#039;t be loaded. I ignored the warning that my save was loading from a version of the game that had different content from the one I had running.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/uncheck_frostcrag.png&quot; alt=&quot;Settings screen for Oblivion on PC where there are options to check or uncheck various DLC bundles&quot;&gt;&lt;/p&gt;
&lt;p&gt;My character loaded into a black zone outside of a house looking in through one-way walls. It was impossible to travel through these walls by default, but by carefully jumping around the edges of the house, the front door became accessible, and it happened to be functional even through the invisible wall. This door led to the outside of the house, labeled &amp;quot;Wilderness&amp;quot;, which was the village screenshot from before.&lt;/p&gt;
&lt;p&gt;The village contained a number of empty houses that could not be entered -- they each had a &amp;quot;Door&amp;quot; that did not budge when interacted with. There were also a few houses which had functional doors labeled things like &amp;quot;Wooden Door to Bruma House Test&amp;quot; and &amp;quot;Wooden Door to TesterHouseBrumaMid&amp;quot;.&lt;/p&gt;
&lt;p&gt;While all of the exteriors of the houses matched those of homes and buildings in Bruma, there was one house whose insides did not match the exterior at all. Upon entering, it looked almost pitch black. Picking khajiit for this verification run wound up being a good choice because of access to night vision at level 1.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/oblivion_gate_interior.jpg&quot; alt=&quot;The interior room of the end of an Oblivion Gate with a sigil stone suspended in midair two stories above. All of this picture has a blue hue to it because of Night Vision&quot;&gt;&lt;/p&gt;
&lt;p&gt;With night vision active, it was clear that the interior of this house was the final room of an Oblivion Gate. Following the ramps up to the top, a sigil stone sat just out of reach. If you have not played Oblivion in 16+ years, you can &lt;a href=&quot;https://en.uesp.net/wiki/Oblivion:Sigil_Stone&quot;&gt;read up on what a sigil stone is here&lt;/a&gt;. The important parts to note for this are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sigil stones were extremely rare with only 70 total in the entire game.&lt;/li&gt;
&lt;li&gt;Sigil stones could be used to enchant armor and weapons with magical effects that were randomly selected from a set of possible options upon collection.&lt;/li&gt;
&lt;li&gt;For what seemed like balancing purposes, the strength of the magical effects from the sigil stones were dependent on the level of the character collecting them at collection time. At level 3, this meant they were &amp;quot;Descendent Sigil Stones&amp;quot; (the weakest), while my friend and I originally found this glitch as characters that were at least level 13, which meant &amp;quot;Ascendent Sigil Stones&amp;quot;.
Interacting with the stone at the top added the sigil stone into the inventory and the only exit was through the floating wooden door that also served as the entrance two floors below.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Trying to get this sigil stone at level 3 proved difficult. Despite a few ranks up in the acrobatics skill, falling from this height was an instant death upon impact due to fall damage. I spent a few minutes wedged under the ramp to the sigil stone platform so that I could jump repeatedly in rapid succession. These ranks allowed me to level up, so I could increase my endurance, which would increase my health and help me live through a fall. I went back to the other Bruma houses and one of them had a bed I could sleep in to level up. Between the health increase from endurance going up and the higher and longer jumps from acrobatics going up, it was finally possible to jump across the gap and land only one level below, immediately pause and heal, and then drop again to land directly next to the door.&lt;/p&gt;
&lt;p&gt;This house wasn&#039;t just a test to refine the design of an Oblivion Gate final room. It also may have been a way to practice generating all of the different sigil stone types and potentially load testing as well. Being able to access the door was an essential part of this because part of grabbing the sigil stone was that it effectively became impossible to move after about a second or two of game-time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/sigil_stones_in_inventory.jpg&quot; alt=&quot;The inventory now that sigil stones have begun spawning rapidly inside the inventory pocket. Each of a dozen of the stones has about 100 quantity, which has led to carrying 2955/200 pounds of items&quot;&gt;&lt;/p&gt;
&lt;p&gt;It has been impossible for me to ever play an Elder Scrolls Game without having to deal with becoming over-encumbered. 16+ years ago, my friend and I learned that we could make our way through doors while over-encumbered. And it turned out that exiting the room back into the Wilderness would stop the sigil stones from replicating in the inventory. At this point, in the Xbox 360 version, removing sigil stones from the player&#039;s inventory would drop individual orbs one by one. Unpausing after removing all the excess sigil stones from the inventory would lead to the game freezing up or crashing on that console from having to render the collision physics of all of those great many orbs. On PC, they were dropped in large-quantity bunches. Either way, dropping sigil stones was required, and we could drop just about all types of them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/chameleon_armor_full.jpg&quot; alt=&quot;My character wearing four pieces of armor, each enchanted with a sigil stone to provide chameleon&quot;&gt;&lt;/p&gt;
&lt;p&gt;The most important sigil stone for us the one that provided chameleon on self. chameleon was a form of &amp;quot;soft invisibility&amp;quot; that usually rendered a user less-than-fully invisible. However, in a crucial difference from the invisibility spell, chameleon would not dispel after making an attack or doing an action. At the &amp;quot;ascendant&amp;quot; strength for a level 13+ character, these sigil stones would have magic effects of 25% chameleon per piece of clothing enchanted. This meant that with only 4/5 pieces of armor enchanted, we could get passive 100% chameleon. No one could see us no matter how many items we stole or people we attacked.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/005-how-my-friend-and-i-became-lords/fast_travel_to_bravil.jpg&quot; alt=&quot;Overworld map showing that I could fast travel to Bravil&quot;&gt;&lt;/p&gt;
&lt;p&gt;After no longer being over-encumbered, it was possible to fast travel out to any other city, which returned the game memory to the regular range in case any of the DLC areas continued to be important to access.&lt;/p&gt;
&lt;p&gt;From here on, hardly any characters in the game would interact with us without trying to speak to them first. Finally, we had transcended combat or laws. We had become Lords.&lt;/p&gt;

          </content>
        </entry>
      

        <entry>
          <title>Wizard Sokoban</title>
          <link href="https://graham.build/s/a-blog/001-wizard-sokoban/" />
          <id>https://graham.build/s/a-blog/001-wizard-sokoban/</id>
          <published>2024-09-30T19:00:00.000Z</published>
          <updated>2024-09-30T19:00:00.000Z</updated>
          <category>video games</category>
<category>game development</category>
<category>puzzles</category>
          <content type="html">
            &lt;p&gt;Today, my friend and I launched another new version of our puzzle game named Wizard Sokoban (working title). You can play it on &lt;a href=&quot;http://itch.io&quot;&gt;itch.io&lt;/a&gt; for free, though it works best on a computer using firefox:&lt;/p&gt;
&lt;iframe title=&quot;Wizard Sokoban itch.io embed&quot; frameborder=&quot;0&quot; src=&quot;https://itch.io/embed/2906186?bg_color=242f45&amp;amp;fg_color=ffffff&amp;amp;link_color=3269d4&amp;amp;border_color=4c525f&quot; width=&quot;552&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https://anvilfood.itch.io/wizard-sokoban&quot;&gt;Wizard Sokoban by graham&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;I wanted to take some time to discuss the journey we&#039;ve been through getting here because I&#039;m proud of what we&#039;ve made so far and I&#039;m excited for what it&#039;ll be after we&#039;ve applied another few rounds of polish.&lt;/p&gt;
&lt;h3&gt;Our second time game developing&lt;/h3&gt;
&lt;p&gt;In May of 2024, my friend Jules and I found ourselves simultaneously unemployed for the first time in our professional careers. With no structure to our days, we talked about some side projects that we&#039;d been meaning to try out when we had more time. He mentioned wanting to try out Godot, and I mentioned that I had an idea for a puzzle game that could be pretty fun and simple to make.&lt;/p&gt;
&lt;p&gt;We&#039;ve been playing video games together for over a decade, and we most recently took on the idea of making our own when we went on a vacation to take part in &lt;a href=&quot;https://itch.io/jam/train-jam-2017&quot;&gt;Indie Train Jam 2017&lt;/a&gt; from Chicago to Emeryville.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; Surrounded by professionals and friendly hobbiest game developers, we realized just how out of our depth we were when we discovered that we hadn&#039;t even both installed git on our computers before we lost wifi (my bad!). Train Jam was absolutely a once-in-a-lifetime experience for me, and I&#039;m glad we managed to partake in it before it shut down. I&#039;ve never been surrounded by so many talented people, and the excitement and beauty of the whole trip far outweighed the intense imposter syndrome feelings throughout.&lt;/p&gt;
&lt;p&gt;So back in May, I sent over a simplified drawing I had done on my phone to describe a sort of box-pushing sokoban game where the user was a wizard&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; who could cast spells to affect its surroundings. I scribbled a grid puzzle that would require a spell to complete on my phone and sent it over:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/001-wizard-sokoban/box_barrier_with_burn_spell.png&quot; alt=&quot;Phone art of a level showing a pile of boxes blocking a wizard&#039;s path towards a raised flag, along with a bar at the top for magic and a spell called BURN at the bottom.&quot;&gt;&lt;/p&gt;
&lt;p&gt;The crux was to have the difficulty of the puzzles come from both:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the regular diffculty of manipulating your surroundings in particular orders that a sokoban game tends to have&lt;/li&gt;
&lt;li&gt;an added layer of which spells you had access to in a given level, which orders and targets to perform those spell casts, and how each of those affected the level manipulation aspect&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My hope was that being a turn-based grid-based puzzle for one player, we&#039;d be able to avoid a lot of the difficulties people have around the complexity of the systems, the interactions between players and each other or players and the game, etc. We talked about project setup and then met up for some IRL game jamming at his house across the bay. We quickly learned that despite shaving off a lot of the more complex things to do in a game, we were starting from scratch so we still had a plenty steep learning curve to overcome.&lt;/p&gt;
&lt;p&gt;We&#039;ve both grown a lot as developers since Train Jam 2017. It was cool to see how we approached this game versus our previous attempt. Back then, we made a list of features that we wanted and then tried to make them all work without necessarily having a broader vision, nor any idea how to program an engine to get the game to work like we wanted to. This time around, we talked about various architecture designs and weighed their pros and cons with plenty of experience from our day jobs. We settled on responding to player input with a queue of actions and generally modeled the game loop after board games and the ways that players are instructed to modify the game state in those after they take their turn. Where we ran into difficulty with art assets previously, I now knew how to sketch some art on my phone while I took BART over.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/001-wizard-sokoban/original_wizard.png&quot; alt=&quot;Phone art of a wizard with a gray hat covering their face, a blobby blue robe, and one white-gloved hand with a finger stuck out to one side&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/001-wizard-sokoban/original_crate.png&quot; alt=&quot;Phone art of a pale yellow wooden crate viewed from the side&quot;&gt;&lt;/p&gt;
&lt;p&gt;From my time on cohost, I had learned that a key part to making any video game is having a &amp;quot;little guy.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/001-wizard-sokoban/original_little_guy.png&quot; alt=&quot;Black and white phone art of a blobby dude with a round head and pointy ears with one arm slightly raised&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once we needed more than just a character, a little guy, and a box, I downloaded some free assets from itch. By the end of a week of off-and-on work, we had a game that was playable. It had a level that could be completed, it supported undo, and I was just about ready to start making levels.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/001-wizard-sokoban/original_default_level.png&quot; alt=&quot;Screenshot of a level with a plain gray background, where walls are made of fences, and there are new aasets for a few crates, a few little guys, a red button, a red and green flag, and a blue triangular player&quot;&gt;&lt;/p&gt;
&lt;p&gt;As things progressed over the months since then, we&#039;ve done a lot of designing and redesigning. I 100%-ed &lt;a href=&quot;https://www.patricksparabox.com/&quot;&gt;Patrick&#039;s Parabox&lt;/a&gt; and most of &lt;a href=&quot;https://store.steampowered.com/app/497780/Recursed/&quot;&gt;Recursed&lt;/a&gt; for some puzzle and systems design inspiration. We booted up levels of &lt;a href=&quot;https://hempuli.com/baba/&quot;&gt;Baba is You&lt;/a&gt;, &lt;a href=&quot;https://www.stephenssausageroll.com/&quot;&gt;Stephen&#039;s Sausage Roll&lt;/a&gt;, and even some Zelda games to understand their ways of teaching and exploring interactions. We talked about how the various spells should work and the ways they should modify each game object.&lt;/p&gt;
&lt;p&gt;Time passed and each of us took breaks from thinking about or working on this game, but here and there, I&#039;d make some progress on spells or the UI side, or Jules would have some refactor to the engine that would make adding new stuff a lot easier or cleaned up a bunch of bugs all at once. We also added our friend Brendan to help with art and sound. (He composed the main menu theme!)&lt;/p&gt;
&lt;p&gt;By the end of August Jules had constructed a Level Editor that made level creation and revision much easier. It supported loading any level straight from the pause menu in debug mode. It allowed us to create new levels to test out buggy behaviors. It prevented me from setting up levels with the buttons on the same layer as the player by accident. And it allowed users to save and load each others&#039; levels.&lt;/p&gt;
&lt;p&gt;We released the &lt;a href=&quot;http://itch.io&quot;&gt;itch.io&lt;/a&gt; alpha on cohost shortly after it was announced that cohost would be shutting down. We got a bunch of great feedback from folks in DMs and on Discord. Today marks another alpha release with a lot of that feedback being addressed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/post-assets/001-wizard-sokoban/a_current_level.png&quot; alt=&quot;A screenshot of a current level of the game, which includes both Freeze and Burn as spells, along with multiple little guys, a green door and matching button, a red button, stairs to be activated rather than a flag, and nicely tiled wall segments instead of fenceposts&quot;&gt;&lt;/p&gt;
&lt;p&gt;There&#039;s still a ton of stuff to be done, art assets to swap out, sounds to add, etc. But I&#039;m already really happy with how far we&#039;ve come. This is a game that I feel like better shows off what a great game development team Jules and I are, and I&#039;m excited for the future.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Rip to Indie Train Jam. Someday, I hope that we have sufficient health precautions that &amp;quot;spending 52 hours encased in a train with a bunch of other game devs&amp;quot; can be a safe thing to do for everyone again. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It&#039;s the year of the wizard, after all. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

          </content>
        </entry>
      
    </feed>
  