<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: IdleCultivation</title>
    <description>The latest articles on DEV Community by IdleCultivation (@idlecultivation).</description>
    <link>https://dev.to/idlecultivation</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4111642%2F0e8ad04e-ec8e-4c51-adff-f897bf8ec2ba.jpeg</url>
      <title>DEV Community: IdleCultivation</title>
      <link>https://dev.to/idlecultivation</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idlecultivation"/>
    <language>en</language>
    <item>
      <title>Four rounds of review on my own work, and what each caught</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Sun, 18 Oct 2026 04:30:10 +0000</pubDate>
      <link>https://dev.to/idlecultivation/four-rounds-of-review-on-my-own-work-and-what-each-caught-ki2</link>
      <guid>https://dev.to/idlecultivation/four-rounds-of-review-on-my-own-work-and-what-each-caught-ki2</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;4 Sep 2026 to 6 Sep 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Working alone means nobody hands your change back. Review is not something that happens to you, it is something you schedule, and if you schedule it badly it turns into rereading your own diff and nodding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the last few weeks I have settled into running several rounds on anything non trivial, and this stretch produced enough data to say what each round is actually for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round one finds the obvious, and that is not the point
&lt;/h2&gt;

&lt;p&gt;The first pass catches the things you already half knew: the case you did not handle, the message you left in developer language, the value you meant to make configurable.&lt;/p&gt;

&lt;p&gt;If review stopped there it would still be worth doing, and it would also be roughly what a careful person catches while writing. The rounds that pay for themselves are the later ones, and what they find is a different category entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The valuable category is damage you just caused
&lt;/h2&gt;

&lt;p&gt;The single most productive rule I have: after applying a batch of fixes, review the batch, not the original problem.&lt;/p&gt;

&lt;p&gt;One night this week that produced seven separate issues, all introduced by that same evening's fixes. Not regressions in old code. New problems created by the repairs, in the hour after they were written, by someone who was concentrating.&lt;/p&gt;

&lt;p&gt;The sharpest one: a fix I had recorded as landed had not landed at all. The edit was matching a piece of text that an earlier reformatting had changed, so it quietly applied nothing, and the commit message went on describing behaviour that did not exist. Everything downstream then reasoned from that description. A later round only caught it because the reviewer went to the running code instead of reading the note.&lt;/p&gt;

&lt;p&gt;Another was two thresholds that were supposed to be the same number and were not. One value decided when a cooldown was considered finished, another decided when the button lit up. They differed slightly, so when a cooldown hit zero, roughly half the buttons stayed dim, which reads to a player as an input that did not register. Those duties are how a disciple climbs towards an &lt;a href="https://idlecultivation.com/article/entity-artifact-elder-seal-elder-s-seal-artifact-guide" rel="noopener noreferrer"&gt;Elder's Seal&lt;/a&gt;, one rank at a time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsiseqtmp3arlv2ehwpk2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsiseqtmp3arlv2ehwpk2.jpg" alt="Mission Hall board where duties and their buttons wait on cooldowns" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change the reader, not just the day
&lt;/h2&gt;

&lt;p&gt;The thing that makes a later round productive is that the reader is different. The same person, on the same day, with the same idea of how the change works, finds the same things they found the first time.&lt;/p&gt;

&lt;p&gt;I get this by varying who reads: a different model with different habits, or myself after enough time to have lost the mental model. A reviewer who has to reconstruct how it works will question things the author never thought to state, and the questions are the value. Half of what these rounds turn up starts as "why does this compare against that?" rather than as a found defect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Silent no-ops are the recurring shape
&lt;/h2&gt;

&lt;p&gt;Almost everything the later rounds catch fails quietly. The fix that did not apply. The two thresholds that nearly matched. A configuration override read before the thing it overrides exists, so the override never takes. A guard whose suite was already failing for an unrelated reason, so the checking process skipped the whole file and nobody saw the guard go dark.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flw0l4sgk3netn05slpmx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flw0l4sgk3netn05slpmx.jpg" alt="Profile settings screen whose options should take effect the moment they change" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;None of these produce an error. All of them produce a system that behaves slightly differently from every description of it, including the ones you wrote yourself an hour ago.&lt;/p&gt;

&lt;p&gt;If I had to compress the whole practice into one habit, it would be this: before you believe a fix, look at the running thing rather than the record of the change. The record is a claim about the past. The behaviour is the only evidence. What they pay is counted in &lt;a href="https://idlecultivation.com/article/entity-material-contribution-token-contribution-token-material-guide" rel="noopener noreferrer"&gt;Contribution Tokens&lt;/a&gt;, which is why a dim button matters.&lt;/p&gt;

&lt;p&gt;Sect duties are waiting: &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;take one on in your browser&lt;/a&gt;. Older posts are collected at &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Cultivation Game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>gamedev</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Hiding what a player cannot use yet, without hiding the quest</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Sat, 17 Oct 2026 04:30:09 +0000</pubDate>
      <link>https://dev.to/idlecultivation/hiding-what-a-player-cannot-use-yet-without-hiding-the-quest-2025</link>
      <guid>https://dev.to/idlecultivation/hiding-what-a-player-cannot-use-yet-without-hiding-the-quest-2025</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;30 Aug 2026 to 4 Sep 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Progression games accumulate lists. As Myriad Immortal Sect filled out, the market, the sect exchange, the formation board, the treasure racks and the alchemy bench all became long, and most of what was in them belonged to a stage of the game the player would not reach for weeks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is not richness. It is a wall of things you cannot buy, cannot make and cannot use, with the three you can somewhere in the middle of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering is the obvious answer and it is wrong
&lt;/h2&gt;

&lt;p&gt;My first instinct was to show only what fits your current realm.&lt;/p&gt;

&lt;p&gt;Two things break. You lose the view of what is ahead, and looking at what is ahead is a large part of why anyone plays this kind of game. And you cannot see the good stuff arriving, which is a real reward in itself.&lt;/p&gt;

&lt;p&gt;So the shape is not a filter, it is a fold. Items far above your realm collapse into a single card that says how many there are, and the horizon is a setting rather than something baked in, currently two realms ahead. Near-future items stay visible, because they are the ones you are working towards. Distant ones become a number you can open when you are curious. What counts as two realms ahead depends on &lt;a href="https://idlecultivation.com/article/cultivation-realms-explained" rel="noopener noreferrer"&gt;how the realm ladder works&lt;/a&gt;, if you are new to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffarm4d8lljolkufr0mns.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffarm4d8lljolkufr0mns.jpg" alt="Recipe shelf folding far-off items into one card that asks for Mahayana first" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One component does this for all five lists. That matters more than the rule itself, because if each screen implements its own version, the sixth screen will get a slightly different one and the game will feel arbitrary. The bench is the one deliberate variation: it folds, but it does not reorder, because the order of recipes there carries meaning that sorting would destroy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyx08j36ss57659t8m4ry.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyx08j36ss57659t8m4ry.jpg" alt="Alchemy bench keeping recipes in order and explaining which herbs are missing" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The exemption that makes it safe
&lt;/h2&gt;

&lt;p&gt;Then the obvious hazard, which I want to state plainly because I nearly shipped it.&lt;/p&gt;

&lt;p&gt;A quest tells you to obtain a particular item. The item belongs to a realm above your horizon. The list folds it away. The game has now told you to find something and then hidden it from you, and the player is not wrong to conclude the game is broken.&lt;/p&gt;

&lt;p&gt;So anything named by a quest you currently have open is never folded, whatever realm it belongs to. Objective or reward, it stays visible, in every list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fob6gathhsokzcsgc17ma.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fob6gathhsokzcsgc17ma.jpg" alt="Quest card naming its target, which stays visible in every list while active" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The general rule I would give anyone building progressive disclosure: your hiding rule needs an escape valve keyed to what the product is currently asking the user to do. Static rules about relevance are always wrong for the user who has just been given a task. The formation board is one of the five lists, and &lt;a href="https://idlecultivation.com/article/formations-arrays" rel="noopener noreferrer"&gt;the formations and arrays guide&lt;/a&gt; shows what lives on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small language trap on the way out
&lt;/h2&gt;

&lt;p&gt;The fold card says how many items are hidden. In English, with one item, it read "1 more items."&lt;/p&gt;

&lt;p&gt;Plurals are a real grammar feature and not a string with an s on the end. English needs one extra form here, and the other ten languages the game speaks each need their own rules, some with more forms than English has. Every list in the game now goes through that, which took an afternoon and removes a whole category of small embarrassments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also this week
&lt;/h2&gt;

&lt;p&gt;A round of work on refusals, prompted by watching real sessions. A Sell button was pressable on a row whose price could not be worked out, and pressing it went through, so the player learned what they had sold by reading their own history afterwards. Another panel kept the balance it had before a refusal rather than the one the refusal reported, so every later message about being short of funds was quoting a number that was not true.&lt;/p&gt;

&lt;p&gt;A refusal is a message. If you throw away the information it arrives with, everything you say after it is guesswork delivered with confidence.&lt;/p&gt;

&lt;p&gt;Free to start, no install: &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;see the folded lists in your browser&lt;/a&gt;, with more notes at &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Myriad Immortal Sect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedesign</category>
      <category>ux</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Width is not the viewport, and 800x600 is not a desktop</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Fri, 16 Oct 2026 04:30:10 +0000</pubDate>
      <link>https://dev.to/idlecultivation/width-is-not-the-viewport-and-800x600-is-not-a-desktop-3bo</link>
      <guid>https://dev.to/idlecultivation/width-is-not-the-viewport-and-800x600-is-not-a-desktop-3bo</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;29 Aug 2026 to 2 Sep 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Myriad Immortal Sect runs in a browser, and browsers are not one shape. It runs full screen on a laptop, portrait on a phone, landscape on a tablet, and embedded in a small frame on portals that host browser games. That last one is where my layout rules turned out to be built on an assumption I had never said out loud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The assumption
&lt;/h2&gt;

&lt;p&gt;Every breakpoint I had written asked one question: how wide is this?&lt;/p&gt;

&lt;p&gt;That works for the usual cases, because on real devices width and height travel together. A narrow viewport is a phone and a phone is also short. So width alone is a decent proxy for the whole shape, right up until it is not.&lt;/p&gt;

&lt;p&gt;The frame on a game portal is around eight hundred pixels wide and not very tall. Width says desktop, comfortably. Height says something closer to a phone. My code believed the width, so the embedded build got the full desktop treatment: a minimap at its full size covering a sizeable share of the visible area, and, on the first screen, a start button that sat below the fold. The first thing a visitor saw was a game they could not begin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbsxvf8mci79w820jhah.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbsxvf8mci79w820jhah.jpg" alt="Map view with the minimap, player card and quest panel competing for screen space" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Both directions, every time
&lt;/h2&gt;

&lt;p&gt;The rule now is that layered elements are decided against both dimensions. Not a second set of breakpoints, just an honest question: is there room for this, given how much space there actually is, rather than how wide it is.&lt;/p&gt;

&lt;p&gt;The practical version, if you want one line to take away: write down the real frames your thing runs in, including the embedded ones, and test the smallest total area rather than the smallest width. I had a phone in my test list and no small landscape frame, so a whole class of layout went unchecked in a place where real people arrive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other half of a viewport nobody reads
&lt;/h2&gt;

&lt;p&gt;A related one on phones with a notch or a home indicator. The document declares that it wants to draw into the full screen, edge to edge, which is the modern default and looks better.&lt;/p&gt;

&lt;p&gt;Declaring that is half the job. The other half is reading the safe area the device reports and keeping interactive controls out of it. I had done the first half only, so on those phones the bottom row of controls sat exactly in the strip the system reserves for its own gestures. Pressing them was a coin flip between the game and the operating system.&lt;/p&gt;

&lt;p&gt;The lesson generalises past this specific property. Anything that opts you into more space is also opting you into responsibility for the parts of that space that are not yours. The places that fill that frame, from cities to sect grounds, are named in the &lt;a href="https://idlecultivation.com/article/glossary-world-terms" rel="noopener noreferrer"&gt;glossary of world terms&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small thing, disproportionate effect
&lt;/h2&gt;

&lt;p&gt;The change I did not expect to matter: the minimap now folds itself away after ten seconds of no input, on a desktop or in landscape. A portrait phone keeps it, since the space it takes there is not contested.&lt;/p&gt;

&lt;p&gt;It is a small animation on a timer. It made the map feel meaningfully less cluttered, because the clutter was mostly a thing you needed for four seconds and then stopped looking at. A surprising amount of interface design is working out which elements are answers to a question rather than permanent furniture, and letting the answers leave once they have been read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Friu3lhkg0nqvr42vvctu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Friu3lhkg0nqvr42vvctu.jpg" alt="World map near a sect gate with the minimap in the corner" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Also this week
&lt;/h2&gt;

&lt;p&gt;A pass over the English text as a native reader would meet it, which meant removing transliterations that had survived in dialogue, replacing Chinese units of distance and weight, and fixing one quest line where all four names were wrong at once. Item names went through the same pass, and the &lt;a href="https://idlecultivation.com/article/glossary-item-terms" rel="noopener noreferrer"&gt;glossary of item terms&lt;/a&gt; collects their English forms. Our English text is authored rather than translated, so no reader should be able to tell which language a given sentence began life in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9noj7mb3nohmki1w53tc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9noj7mb3nohmki1w53tc.jpg" alt="Merchant dialogue on the map, English written as original text" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything here ships in &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Xianxia idle incremental game&lt;/a&gt;, and you can &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;check the layout on any screen you own&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>gamedev</category>
      <category>css</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Putting a 520-chapter serial inside the game itself</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Thu, 15 Oct 2026 04:30:07 +0000</pubDate>
      <link>https://dev.to/idlecultivation/putting-a-520-chapter-serial-inside-the-game-itself-21a9</link>
      <guid>https://dev.to/idlecultivation/putting-a-520-chapter-serial-inside-the-game-itself-21a9</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;23 Aug 2026 to 29 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;The novel that shares a world with Myriad Immortal Sect became part of the game this week rather than a thing beside it. There is a reader in the game, chapters arrive through their own channel, and somebody who finds a chapter on the web can be playing a few seconds later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing the chapters was the smaller half of that sentence. The story runs through ten acts, from the first realm to &lt;a href="https://idlecultivation.com/article/chapter-10-ascension" rel="noopener noreferrer"&gt;the Ascension finale&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is written is not what is published
&lt;/h2&gt;

&lt;p&gt;The first rule I had to make explicit is that having the text does not mean the text is available. Those are two different states and they need two different sources of truth: the writing, and a published index that says what a reader may actually open.&lt;/p&gt;

&lt;p&gt;Without that split, turning the feature on shows a reader an empty shelf, and the shelf looks like a bug rather than like a book that is still being written. With the split, the feature can be on while the index is honest about carrying three volumes.&lt;/p&gt;

&lt;p&gt;I got the inverse wrong once too. The index briefly advertised two volumes that were not there. An index that promises less than exists costs you nothing. An index that promises more produces a reader tapping a title and receiving nothing, which is the single worst outcome in the whole feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kpo0lscr3zvxrxdruz8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kpo0lscr3zvxrxdruz8.jpg" alt="Reader built into the game, opening a published chapter of the novel" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The states that are not chapters
&lt;/h2&gt;

&lt;p&gt;Most of the reader's real work is in the cases where there is no chapter to show.&lt;/p&gt;

&lt;p&gt;You can be offline, in which case previously read chapters should still open and unread ones should say so plainly rather than spin. A volume can be planned and unwritten, which is a real answer and deserves its own presentation, not an error. A chapter can be listed and fail to load, which is different again.&lt;/p&gt;

&lt;p&gt;I would guess two thirds of the reader's behaviour is these three states. That ratio is normal for anything that fetches content and always surprises me anyway when I count it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The screen that could trap you
&lt;/h2&gt;

&lt;p&gt;The interesting bug is worth the whole article.&lt;/p&gt;

&lt;p&gt;A visitor arriving from a chapter page should land in the reader, not in character creation. So the reader renders in front of the new player flow. That is deliberate and it is the right call: someone who came to read should read.&lt;/p&gt;

&lt;p&gt;Anything you place in front of an onboarding flow needs its own way out, and mine did not have one in every path. The close control lived in the reader's header, and the early return that runs before the chapter index arrives never rendered that header. So a visitor whose index failed to load got a screen with no chapters, no close control, no tabs, and no route into the game. Trapped on arrival, on their first visit, which is the exact moment you can least afford it.&lt;/p&gt;

&lt;p&gt;The general rule I wrote down after: any screen that renders ahead of the normal flow needs an exit that does not depend on the thing that might have failed. Put the way out in the branch that runs when nothing loaded, not in the branch that runs when everything worked. A reader arriving at a late chapter such as &lt;a href="https://idlecultivation.com/article/chapter-8-mahayana" rel="noopener noreferrer"&gt;Mahayana&lt;/a&gt; should never be trapped there, whatever loaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzqqk26yksy92rq8v508.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzqqk26yksy92rq8v508.jpg" alt="Out on the world map moments after leaving the reader" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  And the paperwork
&lt;/h2&gt;

&lt;p&gt;The rest of the week went to reading my own design set beside the running game. Working through it in order, the tally came out unpleasant: nine contradicted claims in one file, eleven in another, ten in a third, spread over some fifteen files.&lt;/p&gt;

&lt;p&gt;An automatic check now covers the cheapest third of that, refusing any document that cites a name or a file the project does not actually contain. The remaining two thirds still need a human with both open side by side. I have looked for a way around that and no longer expect to find one.&lt;/p&gt;

&lt;p&gt;The live build is &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Idle Cultivation RPG&lt;/a&gt;, and the reader is inside it: &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;open a chapter and the game in your browser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>writing</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Designing an item that exists because players get lost</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Wed, 14 Oct 2026 04:30:05 +0000</pubDate>
      <link>https://dev.to/idlecultivation/designing-an-item-that-exists-because-players-get-lost-3cgg</link>
      <guid>https://dev.to/idlecultivation/designing-an-item-that-exists-because-players-get-lost-3cgg</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;18 Aug 2026 to 23 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;The continent in Myriad Immortal Sect is big enough to be lost in, which is mostly a feature. Walking somewhere should cost you something, and reading the land should be a skill you develop. But there is a difference between not knowing the way and standing in a valley with no idea which direction anything is in, and the second one is not fun, it is just friction with a nice sky.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So there is an item for it, and building it properly took the whole week.&lt;/p&gt;

&lt;h2&gt;
  
  
  An aid has to work where the problem happens
&lt;/h2&gt;

&lt;p&gt;The first version could only be used from your bag. Read that back and the flaw is obvious: to use the thing that tells you where you are, you leave the view that shows you where you are, open a menu, find an item, and come back.&lt;/p&gt;

&lt;p&gt;It lights from the map now, in the place and at the moment being lost actually occurs. This sounds trivial and it changed how the item feels entirely. An aid used at the point of need is a tool. The same aid two menus away is homework. The &lt;a href="https://idlecultivation.com/article/discerning-eye-minigame" rel="noopener noreferrer"&gt;Discerning Eye sorting game&lt;/a&gt; hands these out too, which matters for what comes next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbsxvf8mci79w820jhah.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbsxvf8mci79w820jhah.jpg" alt="Quick-use item bar on the world map, where an aid can be lit on the spot" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The related failure came from a sorting minigame that also hands these out. Its assistance tray had been sized for the opening stage and never grew, while the boards tripled in size behind it. The help was still there. It had quietly become help for a problem three times smaller than the one in front of you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbt9up7vblbawo3q40z0d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbt9up7vblbawo3q40z0d.jpg" alt="Discerning Eye stage with a heap of relics, the tray and three helper aids" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reachable by the people who need it
&lt;/h2&gt;

&lt;p&gt;Two things were making the aid unavailable to exactly the players most likely to be lost, which is to say new ones.&lt;/p&gt;

&lt;p&gt;One rung of assistance was meant for people playing without an account, and it could never be reached, because a player on a device that remembers them looked signed in to the check. The other was physical: the three assistance buttons were a thirty five pixel target on a phone, in a project that already had a solution for that and had simply not applied it here.&lt;/p&gt;

&lt;p&gt;Neither of these is a design decision. Both of them silently overrode the design decision, which is a thing I have learned to look for specifically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing a thing you also give away
&lt;/h2&gt;

&lt;p&gt;The item is sold, and it is also granted: some for confirming your email, some for each cleared stage of the sorting game.&lt;/p&gt;

&lt;p&gt;That combination is where an economy can quietly spring a leak, and the fix is unglamorous. Buy price and sell payout are set independently rather than one being derived from the other, so no arrangement of buying and selling comes out ahead. The sell payout is deliberately low, and that low number is the brake.&lt;/p&gt;

&lt;p&gt;I could have made the item untradeable instead. I did not, because untradeable items pile up in a bag as a category of thing you cannot do anything with, and because a low resale value is honest: it says this is a consumable convenience, not treasure. Players understand that immediately.&lt;/p&gt;

&lt;p&gt;One consequence worth knowing if you build the same thing: every source has to deliver the identical item, or your bag ends up with three stacks of the same lamp from three places. Sameness here is a design requirement, not an implementation detail. The settlements you are most likely to be walking between are listed in the guide to &lt;a href="https://idlecultivation.com/article/cities-towns-villages" rel="noopener noreferrer"&gt;cities, towns and villages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ir52b4u6wkcevv88ib7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ir52b4u6wkcevv88ib7.jpg" alt="Bag with tabs and item cards, where every source must stack into one slot" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Elsewhere
&lt;/h2&gt;

&lt;p&gt;The other half of the week went to the tie in novel's checking gates, where I measured the false alarm rate at roughly seventy to eighty percent over three rounds. The useful move was not better filtering. It was giving the checker the context it was missing, since a large share of its bad calls came from reading chapter numbers that were local to a section rather than to the book. Fix the input, and a whole class of wrong answers stops being generated.&lt;/p&gt;

&lt;p&gt;Try it in your browser: &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Idle Cultivation Game&lt;/a&gt;, or &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;light a lamp yourself, free and with no install&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedesign</category>
      <category>gamedev</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Adding a rule to a project that already breaks it</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Tue, 13 Oct 2026 04:30:07 +0000</pubDate>
      <link>https://dev.to/idlecultivation/adding-a-rule-to-a-project-that-already-breaks-it-2lpg</link>
      <guid>https://dev.to/idlecultivation/adding-a-rule-to-a-project-that-already-breaks-it-2lpg</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;18 Aug 2026 to 22 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Most rules worth having arrive after the thing they govern. You decide that every tunable value must be readable by the code that needs it, or that every craft key sold in a shop must open something, and then you discover the project breaks that rule in forty places, some of which will take a week to unpick.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are three things you can do, and two of them do not work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two that do not work
&lt;/h2&gt;

&lt;p&gt;Fix everything now and only then turn the rule on. This sounds principled and it means the rule ships in a month, or never, because the forty fixes touch systems you were not planning to open. In the meantime nothing stops violation forty one.&lt;/p&gt;

&lt;p&gt;Make it a warning. A warning that appears on every run stops being read by the second week. I have done this to myself more than once and I no longer pretend otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The third one
&lt;/h2&gt;

&lt;p&gt;Enumerate the violations you have, by name, and assert that the set only ever shrinks. Anything not on the list fails immediately. Anything on the list is a to-do with a test attached, and removing an entry is a small satisfying commit rather than a project.&lt;/p&gt;

&lt;p&gt;The rule is live from day one against all new code, which is where most violations would otherwise come from, and the existing debt becomes visible and countable instead of implied. This week that shape closed three separate things: config keys with no reader, craft keys sold in a shop that opened nothing, and a formatting rule. The sellers in question include the &lt;a href="https://idlecultivation.com/article/wandering-merchant-offers" rel="noopener noreferrer"&gt;wandering merchant's stall&lt;/a&gt;, which stocks recipes among its goods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq2cpvasa31i6jmmzidp2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq2cpvasa31i6jmmzidp2.jpg" alt="Recipes tab in the bag holding five pill recipes that must each unlock a brew" width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistake that makes it useless
&lt;/h2&gt;

&lt;p&gt;I had the formatting one wrong for weeks and did not know it.&lt;/p&gt;

&lt;p&gt;Instead of naming the violating files, I had exempted them with a pattern. A pattern does not just cover the files that existed when you wrote it. It covers every file that matches it from then on, including the ones I wrote that same night, which were red, and which nothing told me about because the exemption swallowed them along with the old ones.&lt;/p&gt;

&lt;p&gt;That is the whole difference between an exemption and a ratchet. An exemption describes a shape and keeps forgiving it. A ratchet lists specific items and forgives exactly those. The list is uglier to read and it is the only version that works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two smaller ways a guard can be theatre
&lt;/h2&gt;

&lt;p&gt;Both of these were live in this project and both survived review, because a guard that never fires looks exactly like a guard that passes.&lt;/p&gt;

&lt;p&gt;One matched a mention rather than a use. It was checking whether a certain thing appeared in the file, so an unused import at the top satisfied it forever, long after the real usage had gone.&lt;/p&gt;

&lt;p&gt;One had been written inside a comment. It never ran at all. Nobody noticed because its suite was green, which it would have been either way.&lt;/p&gt;

&lt;p&gt;The habit I have taken from this: when I write a guard, I break the thing it guards on purpose and watch it go red before I commit. Sixty seconds, and it is the only evidence that the guard is connected to anything. A craft key such as the &lt;a href="https://idlecultivation.com/article/entity-recipe-pill-deity-recipe-deity-pill-recipe-guide" rel="noopener noreferrer"&gt;Deity Pill recipe&lt;/a&gt; is the kind of item the shop check now covers.&lt;/p&gt;

&lt;h2&gt;
  
  
  And check the artifact, not the description
&lt;/h2&gt;

&lt;p&gt;The last variation is subtler. Several checks here were asserting against prose in a document, or against a value in the file that authors it, rather than against the payload that actually ships to players.&lt;/p&gt;

&lt;p&gt;Those pass while the shipped thing is wrong, which is the worst outcome available: a green signal proving something adjacent to the thing you care about. The checks now read the exported payload. Two of them went red the moment they were pointed at it, which is exactly what you hope for and never enjoy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.idlecultivation.com%2Fdevlog%2Fi%2F960b57734d1e1011b801.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.idlecultivation.com%2Fdevlog%2Fi%2F960b57734d1e1011b801.jpg" alt="Contribution Exchange pill hall, the goods players actually receive" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;Open the game free in a browser tab&lt;/a&gt; to see the rules at work; the devlog archive sits at &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Incremental RPG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>gamedev</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>The rename that changed nothing, and why 43 names had drifted</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Mon, 12 Oct 2026 04:30:07 +0000</pubDate>
      <link>https://dev.to/idlecultivation/the-rename-that-changed-nothing-and-why-43-names-had-drifted-1c9j</link>
      <guid>https://dev.to/idlecultivation/the-rename-that-changed-nothing-and-why-43-names-had-drifted-1c9j</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;16 Aug 2026 to 18 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;I spent part of this week renaming thirteen named characters in Myriad Immortal Sect. The English edition is written as an original rather than as a translation, so a character who reads naturally in Chinese gets an English name that reads naturally in English, not a transliteration a reader has to decode. Characters now carry names like &lt;a href="https://idlecultivation.com/article/entity-character-mojinghao-sabrina-character-guide" rel="noopener noreferrer"&gt;Sabrina&lt;/a&gt;, whose codex page shows the name players actually see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made the renames in the place where the game's entity data is authored and curated. Then I opened the game and every character still had the old name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two sources, one fallback, opposite winners
&lt;/h2&gt;

&lt;p&gt;Names in this game live in two places.&lt;/p&gt;

&lt;p&gt;There is the curated entity data, which is authored, reviewed and exported to the client. And there is the display catalogue that the interface reads for the player's language.&lt;/p&gt;

&lt;p&gt;The lookup tries the catalogue first and falls back to the entity data when the catalogue has no key. That is a completely reasonable design, and it produces two quiet no-ops that point in opposite directions.&lt;/p&gt;

&lt;p&gt;Rename in the entity data, and nothing changes for any name the catalogue already knows. The export runs, the payload updates, the game shows what it always showed.&lt;/p&gt;

&lt;p&gt;Rename in the catalogue, and the entity data stays wrong forever. It is not reachable from any export, so a later reader of that data sees a name that no player has ever seen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9noj7mb3nohmki1w53tc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9noj7mb3nohmki1w53tc.jpg" alt="A named merchant from Azuresun City speaking to the player on the map" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the drift accumulates rather than settling
&lt;/h2&gt;

&lt;p&gt;There is a tool that seeds missing catalogue entries from the entity data, and it is additive and safe to re-run on purpose, which is the right call for a tool that runs often.&lt;/p&gt;

&lt;p&gt;Additive means it can add a key that is absent. It cannot carry a change to a key that is present. So every repair made in the catalogue leaves the entity data one step behind, permanently, and the tool that exists to keep them together can never close that particular gap.&lt;/p&gt;

&lt;p&gt;By the time I looked, forty three rows had drifted. The curated data said "Alchemy" where the game had been saying "Alchemy Pavilion" for months. The good name was the one nobody had written down in the place that looks authoritative. The hall in question is &lt;a href="https://idlecultivation.com/article/entity-building-alchemy-room-alchemy-pavilion-building-guide" rel="noopener noreferrer"&gt;the Alchemy Pavilion&lt;/a&gt;, which is what its codex page calls it too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fds8vs8rjj76cumfhikgk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fds8vs8rjj76cumfhikgk.jpg" alt="The Alchemy Pavilion, the name players saw while the data still said Alchemy" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually changed
&lt;/h2&gt;

&lt;p&gt;A single tool now moves both layers together, and the rule is written down where the next person will trip on it, which in practice means where I will trip on it.&lt;/p&gt;

&lt;p&gt;The wider lesson is the part worth carrying to another project. If you have two sources with a fallback between them, ask two questions before you edit either. Which one wins for the reader, and can your synchronisation carry a change or only an addition? A sync that is additive and safe to re-run is a guarantee about safety, not about convergence. Those get confused constantly, including by the person who wrote the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elsewhere this week
&lt;/h2&gt;

&lt;p&gt;The same week produced a matching lesson at the data layer: a repair applied to the authored rows is not finished until every mirror of those rows carries it, because a fresh environment is rebuilt from the mirror rather than from the repair. And a check now runs over the design documents themselves, failing when a document names an identifier or a path the project does not have. Six of those were live, including two constants documented in a file they had moved out of.&lt;/p&gt;

&lt;p&gt;None of these are interesting bugs. They are all the same shape: a fact stored twice, agreeing at the moment it was written, with nothing watching the gap afterwards.&lt;/p&gt;

&lt;p&gt;The cast answers to its English names now: &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;meet them in your browser&lt;/a&gt;, or read the rest at &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Cultivation Game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>i18n</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>1,826 draw calls to put 61 objects on the screen</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Sun, 11 Oct 2026 04:30:08 +0000</pubDate>
      <link>https://dev.to/idlecultivation/1826-draw-calls-to-put-61-objects-on-the-screen-47ll</link>
      <guid>https://dev.to/idlecultivation/1826-draw-calls-to-put-61-objects-on-the-screen-47ll</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;15 Aug 2026 to 17 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Players of Myriad Immortal Sect walk a continent that streams in around them as they go. It had felt slightly rough for weeks, in the way that is easy to live with and impossible to un-notice, and I had two confident theories about why.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both were wrong. I finally measured, and the number that came back was 1,826 draw calls to put 61 objects on the screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading and showing are different units
&lt;/h2&gt;

&lt;p&gt;The map loads in chunks. A chunk is a sensible unit for loading, because it is a sensible unit for unloading: when you walk far enough away, the whole chunk goes.&lt;/p&gt;

&lt;p&gt;The problem is that the renderer does not skip a plain image just because it sits outside the view. Every loaded thing gets submitted, every frame, whether it is in front of you or twenty eight thousand pixels behind you. And chunks stay loaded for a long distance around the player, deliberately, so that walking back does not stutter.&lt;/p&gt;

&lt;p&gt;That is where the ratio comes from. Sixty one objects were visible. Everything else being drawn was correct to keep loaded and pointless to draw.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6sr7vjlgmn3dxm2j6s52.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6sr7vjlgmn3dxm2j6s52.jpg" alt="Flying over a streaming continent where only a handful of objects are on screen" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fix is to keep the unit of loading as the chunk and make the unit of visibility the object. Those cannot be the same unit here, because a sect compound's buildings all belong to one chunk while the world is dozens of chunks across, so chunk level visibility would either draw the whole compound or none of it. A compound holds a dozen or so halls, such as &lt;a href="https://idlecultivation.com/article/entity-building-azure-cloud-pagoda-pagoda-building-guide" rel="noopener noreferrer"&gt;Azure Cloud's pagoda&lt;/a&gt;, all owned by that one chunk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flamdy2sfobqangc74ze2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flamdy2sfobqangc74ze2.jpg" alt="Medicine King Valley compound, whose buildings all load together as one chunk" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The trigger you will forget
&lt;/h2&gt;

&lt;p&gt;Visibility gets recomputed when the camera moves, which is the obvious trigger and the one everybody writes.&lt;/p&gt;

&lt;p&gt;It also has to be recomputed when new chunks finish streaming in. Without that second trigger, anything that arrives while the player is standing still is never considered, so it is drawn forever regardless of where it is. Standing still is extremely common in an idle game. That trigger is doing more work than the obvious one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then the opposite problem
&lt;/h2&gt;

&lt;p&gt;Building a chunk means scattering its props, and that work is synchronous. Measured, it is about seven milliseconds at the median, thirty six at the ninety fifth, and one hundred and forty two at its worst.&lt;/p&gt;

&lt;p&gt;When you reveal a large area at once, the box being revealed can be twenty five chunks. Doing twenty five of those in a single frame is a freeze, and a freeze while the page is meant to stay responsive is exactly the thing I care most about avoiding.&lt;/p&gt;

&lt;p&gt;So chunk assembly now runs against a per frame budget, nearest chunks first. Terrain loading is deliberately not budgeted, because ground appearing late is much worse than a tree appearing late. Population trails the ground by a frame or two and nobody notices. The land being streamed is laid out in this &lt;a href="https://idlecultivation.com/article/mortal-world-map" rel="noopener noreferrer"&gt;overview of the whole continent&lt;/a&gt;, if you want to see how far it goes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Friu3lhkg0nqvr42vvctu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Friu3lhkg0nqvr42vvctu.jpg" alt="World map filling in around a sect gate with the minimap and item belt" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I want to remember
&lt;/h2&gt;

&lt;p&gt;I had two explanations for the roughness before I measured. One was about how the game hands work to the browser. The other was about a piece of the world I had recently changed and felt guilty about. Both were the kind of theory you can hold with real confidence, because both described mechanisms that genuinely exist and genuinely cost something.&lt;/p&gt;

&lt;p&gt;Neither was the reason. The reason was a ratio nobody would guess, sitting in a system I considered finished, and it took a count of draw calls to find.&lt;/p&gt;

&lt;p&gt;I now treat a performance hunch as a hypothesis with a required measurement attached, and I write the measurement down next to the fix. Not for discipline points. Because the next person to touch this code will be me in four months, holding a fresh confident theory, and the number in the comment is the only thing that will stop me.&lt;/p&gt;

&lt;p&gt;More devlogs and the game: &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Myriad Immortal Sect&lt;/a&gt;, where you can &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;roam the streamed world for free&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>performance</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>You cannot eyeball a tap target, so I measured all of them</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Sat, 10 Oct 2026 04:30:06 +0000</pubDate>
      <link>https://dev.to/idlecultivation/you-cannot-eyeball-a-tap-target-so-i-measured-all-of-them-2l46</link>
      <guid>https://dev.to/idlecultivation/you-cannot-eyeball-a-tap-target-so-i-measured-all-of-them-2l46</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;10 Aug 2026 to 15 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Myriad Immortal Sect runs in a browser, which means it runs on phones, which means for months it had a whole half that nobody was testing. I had looked at it on a phone plenty of times. Looking is not the same as testing, and for this particular class of problem, looking is close to useless.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a phone pass is dimensional, not visual
&lt;/h2&gt;

&lt;p&gt;The defects here are numbers. A control is 17 pixels tall. A grid is 40 pixels wider than the screen. A description has one line of room and two lines of text, so it does not wrap, it disappears.&lt;/p&gt;

&lt;p&gt;None of those announce themselves when you glance at a screenshot. The screen looks like the screen. You find out when you try to press something with a thumb and press the thing beside it instead, and even then you are inclined to blame your thumb.&lt;/p&gt;

&lt;p&gt;So the first real change was not a fix. I taught the machine that plays the game overnight to switch to a phone viewport, and suddenly the mobile half was under the same treatment as everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first measurement pass lied to me
&lt;/h2&gt;

&lt;p&gt;Asking a page how big each control is sounds like the easy part. It is where I lost the most time.&lt;/p&gt;

&lt;p&gt;The game already gives many buttons an invisible halo that extends the pressable area past the visible edge. That halo is drawn separately from the button. If you measure the button's own box, you get the visible size and you conclude the control is too small, including for every control you already fixed. My first sweep confidently re-reported a batch of buttons that were fine.&lt;/p&gt;

&lt;p&gt;The lesson generalises past this project: when you automate a measurement, check it against a case you know the answer to before you trust the list it produces. I had a list of forty problems, some fraction of which were the measurement's problems rather than the game's.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix the class, not the instances
&lt;/h2&gt;

&lt;p&gt;Once the list was honest, the temptation was to walk it. Four controls at 13 to 28 pixels here, a pager arrow there, tabs on the market at 28, a duel button at 24.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvf73gyluhm7mfvphuyb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvf73gyluhm7mfvphuyb.jpg" alt="Market counter with its row of tabs and pill listings, sized for thumbs" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Walking a list like that is how you fix forty and miss four hundred. The controls came from one shared button definition, so the minimum pressable size went there, once, and most of the list closed by itself. What was left was genuinely per screen: a grid that had to stop assuming a desktop width, a header that had to wrap so its action stayed visible, a bottom bar that now scrolls to the tab you are actually on.&lt;/p&gt;

&lt;p&gt;One fix I want to call out because it is invisible on desktop and obvious on a phone: an item menu used to open below the point you touched, which is exactly where your finger already is. It opens above now. Nothing about that is discoverable from a mouse. Every screen got the same treatment, down to the &lt;a href="https://idlecultivation.com/article/cultivation-skill-tree" rel="noopener noreferrer"&gt;skill tree page&lt;/a&gt;, one of the busiest screens on a small display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fizw29e8av19p2tk5htcz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fizw29e8av19p2tk5htcz.jpg" alt="Pills tab of the bag with stack counts and Use buttons on each item" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The other half of the week
&lt;/h2&gt;

&lt;p&gt;Away from the phone, this stretch was the tribulation curve. Breakthroughs used to be uniformly tense, which reads as uniformly flat. They are now loose at the front and tight at the back, so the early ones teach you the rhythm and the last two are meant to frighten you, with the panel telling you plainly what would raise your odds. There is always a way through. Difficulty that can trap you is not difficulty, it is a dead end with a health bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6cjn5b1ueb82r7ui022u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6cjn5b1ueb82r7ui022u.jpg" alt="Survived tribulation summary: the cost paid, the realm reached, a sudden epiphany" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The connection to the phone work is real, if you squint. Both are about the game answering the player honestly about a physical fact: how big this is, and how likely that is. Preparations for a tribulation include items like the &lt;a href="https://idlecultivation.com/article/entity-material-tribulation-warding-talisman-tribulation-warding-talisman-material-guide" rel="noopener noreferrer"&gt;Tribulation-Warding Talisman&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have a phone handy, &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;test the game on it straight from the browser&lt;/a&gt;; the full series is on &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Xianxia idle incremental game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>webdev</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>The writing pipeline kept eating the state it depended on</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Fri, 09 Oct 2026 04:30:07 +0000</pubDate>
      <link>https://dev.to/idlecultivation/the-writing-pipeline-kept-eating-the-state-it-depended-on-3nnd</link>
      <guid>https://dev.to/idlecultivation/the-writing-pipeline-kept-eating-the-state-it-depended-on-3nnd</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;11 Aug 2026 to 15 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;This stretch was almost entirely the tie in novel rather than the game. The series covers a book per realm, and volume one alone is long enough that nobody is holding it in their head. So the writing runs as a pipeline, unattended, for hours at a time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A pipeline like that has two products, and I had only been watching one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The output is not the state
&lt;/h2&gt;

&lt;p&gt;The obvious product is chapters. The other one is everything the pipeline remembers between chapters: which threads are open, who knows what, which promises the book has made and not yet kept. That running record is what makes chapter 300 agree with chapter 40. It is not delivered to anyone. It exists so the next run is not starting from nothing.&lt;/p&gt;

&lt;p&gt;I found out that my revision step rewrites that record every time it runs. Not corrupts, rewrites: it reconstructs the state from its own reading and puts that back. Measured on one book, the record of open threads came back missing about four fifths of its entries. A separate step could truncate it to nothing at all.&lt;/p&gt;

&lt;p&gt;None of this showed up in the chapters. The prose was fine. It would have kept being fine for a while, and then, thirty chapters later, the book would have quietly stopped honouring a promise it made in the second volume, and I would have gone looking for that in the writing. The story it has to keep straight is the game's story too, down to single quests such as &lt;a href="https://idlecultivation.com/article/quests-mortal-b8-t2-settling-karma-walkthrough" rel="noopener noreferrer"&gt;Settling Karma&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kpo0lscr3zvxrxdruz8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kpo0lscr3zvxrxdruz8.jpg" alt="The novel reader in game, showing chapters produced by the writing workflow" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What made it findable
&lt;/h2&gt;

&lt;p&gt;I only caught it because I started checking the state before and after a run instead of reading the output. That sounds like something you would obviously do. In practice it is not obvious at all, because the state is intermediate, it has no reader, and every instinct says the thing to inspect is the thing you are shipping.&lt;/p&gt;

&lt;p&gt;The rule I now work by: if a long job carries state between steps, that state is a first class artifact. Snapshot it before a destructive step, compare after, restore when the comparison fails, and assert on it in its own right. Do not infer its health from the output, because output quality degrades far later and far more gradually than state does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmi8acmt3g8yt4kimkped.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmi8acmt3g8yt4kimkped.jpg" alt="Chronicle page keeping a running record of quests, merit and dated events" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A related trap, in the checking layer
&lt;/h2&gt;

&lt;p&gt;The same week produced a version of this in the repair path. I had a step that takes an identified problem, edits the text, and reports success. Reporting success is not evidence, so I added two assertions: the thing you were asked to remove must be gone, and everything you were not asked to touch must still be there.&lt;/p&gt;

&lt;p&gt;The first assertion had a flaw that made it always pass. Its pattern was allowed to end on whitespace, which meant it could never match what it was looking for, which meant it never fired. An assertion that cannot fail is worse than no assertion, because it makes a report of success look checked.&lt;/p&gt;

&lt;p&gt;The second assertion, the one about not touching anything else, turned out to be the more valuable half. A repair step will happily fix the sentence you named and rewrite the paragraph around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parallel version of every bug
&lt;/h2&gt;

&lt;p&gt;The last thing I did here was let several arcs be written at once. That surfaced five separate defects that simply do not exist in a single stream, the most instructive being two runs racing for the same write with no single instance check between them.&lt;/p&gt;

&lt;p&gt;Concurrency did not create those bugs. It removed the accidental serialization that had been hiding them, which is roughly what it always does. The people whose knowledge that running record tracks include figures like &lt;a href="https://idlecultivation.com/article/entity-character-zhou-ming-zhou-ming-character-guide" rel="noopener noreferrer"&gt;Zhou Ming&lt;/a&gt;, who also appear in the game.&lt;/p&gt;

&lt;p&gt;Everything here ships in &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Idle Cultivation RPG&lt;/a&gt;; &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;read the story and play it free in the browser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>writing</category>
      <category>gamedev</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>How big is that tree? Sizing a world drawn at every scale</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Thu, 08 Oct 2026 04:30:07 +0000</pubDate>
      <link>https://dev.to/idlecultivation/how-big-is-that-tree-sizing-a-world-drawn-at-every-scale-5h31</link>
      <guid>https://dev.to/idlecultivation/how-big-is-that-tree-sizing-a-world-drawn-at-every-scale-5h31</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;9 Aug 2026 to 11 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;The world map in Myriad Immortal Sect is made of hand drawn pieces: halls, pines, herbs, beasts, mountain ranges, people. They were drawn at whatever size suited the drawing. A pine came in enormous. A herb came in nearly as tall as a person. A wild beast was being shown at one fixed height whether it was a rat or a tiger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You do not notice this as a sizing problem. You notice it as the world feeling wrong, which is a much harder thing to act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The player is the ruler
&lt;/h2&gt;

&lt;p&gt;The fix started by naming the unit. The player figure is the reference height for every drawn thing in the world, and whatever decides how large to render a piece asks a single place for that answer. A gatherable herb is about half a person. A pine is a tree, meaning several people tall. A beast is sized by what it is, and when the beast happens to be a person, it is sized like a person.&lt;/p&gt;

&lt;p&gt;Having one answer sounds like tidiness. It is really about the failure it prevents. Three separate places were deciding size, and they had drifted, so the same object could be one height in the world and another in a panel. There is now a test whose only job is to fail if a fourth place starts deciding this on its own. The halls that rule now sizes are catalogued in the &lt;a href="https://idlecultivation.com/article/buildings-codex" rel="noopener noreferrer"&gt;codex of buildings&lt;/a&gt;, each drawn against the same human ruler.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flamdy2sfobqangc74ze2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flamdy2sfobqangc74ze2.jpg" alt="Sect gate, hall and paved road drawn to scale against the player figure" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A ceiling flattens the thing you care about
&lt;/h2&gt;

&lt;p&gt;My first version capped drawn height. Anything above the cap became the cap.&lt;/p&gt;

&lt;p&gt;That is wrong in a way that took a day to see. A cap does not just shrink the giants. It makes all the giants the same. A mountain range, a great hall and an overgrown pine all hit the ceiling and arrive at identical height, so the world loses its ordering exactly where the ordering is most dramatic. The player cannot tell that the mountain is the biggest thing on screen, because everything tall is now equally tall.&lt;/p&gt;

&lt;p&gt;So oversized things are compressed along a curve instead. Big things get noticeably smaller, enormous things get much smaller, and the ordering between them survives the squeeze. A mountain range is also allowed out of the system entirely, because a skyline that respects a height budget is not a skyline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs7j9virauiu39kw0ifxe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs7j9virauiu39kw0ifxe.jpg" alt="Mountain range towering over a sect dome, allowed to stay taller than everything" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The bugs this class of change produces
&lt;/h2&gt;

&lt;p&gt;Two are worth repeating because they are the same mistake wearing different clothes.&lt;/p&gt;

&lt;p&gt;A gentle breathing animation on standing figures was written as a scale, so it multiplied whatever size the new system had chosen and pushed some villagers to twice the player's height on the inhale. An animation that adjusts a value has to adjust it, not replace it.&lt;/p&gt;

&lt;p&gt;The ground had a similar story. I wanted a hairline seam between tiles so the surface reads as tiles rather than as paint, and I first added it by shrinking each tile. That opens gaps you can walk into, and in one spot could not walk out of. The seam belongs in the spacing between tiles, not in the tiles. You can judge the result in any stretch of wilderness, for example around &lt;a href="https://idlecultivation.com/article/dragon-vein-eye" rel="noopener noreferrer"&gt;the Dragon Vein Eye&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9noj7mb3nohmki1w53tc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9noj7mb3nohmki1w53tc.jpg" alt="Azuresun City merchant standing at person height while talking to the player" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Walking got the same treatment
&lt;/h2&gt;

&lt;p&gt;Click to move used to plan one route to the destination and give up if the whole thing was blocked. It now plans leg by leg, measures progress against the current leg instead of the final goal, and slides along a wall it bumps into while keeping the heading it was travelling on. It cancels only when the destination itself is unreachable, not when some point along the way is.&lt;/p&gt;

&lt;p&gt;The common thread across all of it: the first version of each rule was a single global answer, and the world is not uniform enough for a single global answer. What worked was a rule that keeps relative order intact, plus one place that owns it, plus a test that notices when a second place appears.&lt;/p&gt;

&lt;p&gt;Sizes now follow the player everywhere. &lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;Walk that continent free in the browser&lt;/a&gt;, or see the other devlogs on &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Idle Cultivation Game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>gamedesign</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>The spec was unbuildable, and only building it showed that</title>
      <dc:creator>IdleCultivation</dc:creator>
      <pubDate>Wed, 07 Oct 2026 04:30:09 +0000</pubDate>
      <link>https://dev.to/idlecultivation/the-spec-was-unbuildable-and-only-building-it-showed-that-2i18</link>
      <guid>https://dev.to/idlecultivation/the-spec-was-unbuildable-and-only-building-it-showed-that-2i18</guid>
      <description>&lt;p&gt;Development covered &lt;strong&gt;6 Aug 2026 to 9 Aug 2026&lt;/strong&gt; (commit dates).&lt;/p&gt;

&lt;p&gt;Myriad Immortal Sect has a design document per system, and I write the document before I write the system. This week I finally built one of the oldest ones and discovered it described something that cannot exist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading your own spec like a stranger
&lt;/h2&gt;

&lt;p&gt;The system is a slow-earning currency. The document said, in effect, that you earn it while you are in the game, at a rate set against a balance, with the earning gated on a condition. I had read that paragraph perhaps thirty times over several months and understood it every time.&lt;/p&gt;

&lt;p&gt;Then I sat down to implement it exactly as written, and the gate could never be satisfied. The condition the document set was one the game reaches only after the currency already exists. Read literally, the faucet never opens on a new account, which is the only kind of account that matters for a currency meant to accumulate slowly.&lt;/p&gt;

&lt;p&gt;I want to be clear that this is not a typo I could have caught by proofreading. The sentence is grammatical and it names real things. It is wrong in the way a plan for a bridge is wrong when the two banks are at different heights and nobody drew the elevation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "an hour is worth an hour" means when you write it down
&lt;/h2&gt;

&lt;p&gt;Settling it meant answering a question the document had been quietly avoiding: what is one hour of play actually worth here?&lt;/p&gt;

&lt;p&gt;An idle game has to answer that in a currency, not in a feeling. Once the number exists, everything downstream stops being an argument. The production rate became plain arithmetic that a test can assert, which sounds obvious and was not obvious for months, because the rate had been living inside a paragraph as a description rather than inside the game as a value.&lt;/p&gt;

&lt;p&gt;The moment it was arithmetic, a second problem showed itself: a faucet with no relationship to a balance is just a number going up. So the rate now reads from the same balance the rest of the economy reads, and the two move together. If I change what an hour is worth, one number changes and the whole system follows. Each attribute that rate eventually feeds is described in the guide to &lt;a href="https://idlecultivation.com/article/cultivation-attributes" rel="noopener noreferrer"&gt;what your cultivation attributes do&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgulz52sg9gypt5v2eeme.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgulz52sg9gypt5v2eeme.jpg" alt="Cultivate screen where every multiplier on the hourly rate is spelled out" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The rest of the week was the same lesson at smaller scale
&lt;/h2&gt;

&lt;p&gt;I spent most of this stretch checking documents against the game that shipped, one document at a time, and the pattern repeated in miniature everywhere.&lt;/p&gt;

&lt;p&gt;A file promised a discount that scales with your realm. Built version: a flat one, and the document had claimed the scaled version superseded it. A card advertised perks that were compiled into the build, while an operator was supposed to be able to change them. An index named the wrong starting sect. A guidance table ranked two actions it had never actually ranked. In one document three separate claims described behaviour the code does not have.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9d8xlltb83kutni0xdee.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9d8xlltb83kutni0xdee.jpg" alt="Market Isles General Store listing pills and their prices" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;None of these were caught by reading. They were caught by holding one document open and one game open and going line by line, which took a full day per batch and turned up something almost every time. Several of those documents describe trade, such as the &lt;a href="https://idlecultivation.com/article/grand-auction" rel="noopener noreferrer"&gt;weekly sealed-bid sale&lt;/a&gt; and its pricing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpl6bxvof8upzka4gdg14.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpl6bxvof8upzka4gdg14.jpg" alt="Sect rank and contribution panel above the Mission Hall board" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway I would give a past version of myself
&lt;/h2&gt;

&lt;p&gt;Write the document first, still. It remains the reason the game has a shape. But treat it as a hypothesis with an expiry date rather than a record of what is true. A spec that has never been built is not verified, however many times you have read it, and rereading is the exact activity that will not verify it. The only reader who finds the missing elevation drawing is the one holding a shovel.&lt;/p&gt;

&lt;p&gt;I now finish a system by going back and rewriting its document to describe what shipped, including the places where I decided the original was wrong. That is not bookkeeping. It is the only way the next thing I build starts from something true.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;Go straight to the game and play for free&lt;/a&gt;, or browse the design notes at &lt;a href="https://idlecultivation.com/" rel="noopener noreferrer"&gt;Incremental RPG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://idlecultivation.com/immortal-sect?src=devto" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ry5ba73ahswb860ofof.png" alt="Myriad Immortal Sect, the game this devlog is about. Play it free in the browser" width="798" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>idlegame</category>
      <category>indiedev</category>
      <category>devlog</category>
    </item>
  </channel>
</rss>
