<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.petervanonselen.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.petervanonselen.com/" rel="alternate" type="text/html" /><updated>2026-03-05T21:58:17+00:00</updated><id>https://www.petervanonselen.com/feed.xml</id><title type="html">Peter van Onselen</title><subtitle>Personal website and portfolio of Peter van Onselen
</subtitle><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><entry><title type="html">How I Learnt to Stop Worrying and Love Agentic Katas</title><link href="https://www.petervanonselen.com/2026/03/05/learn-to-love-agentic-coding/" rel="alternate" type="text/html" title="How I Learnt to Stop Worrying and Love Agentic Katas" /><published>2026-03-05T08:00:00+00:00</published><updated>2026-03-05T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2026/03/05/learn-to-love-agentic-coding</id><content type="html" xml:base="https://www.petervanonselen.com/2026/03/05/learn-to-love-agentic-coding/"><![CDATA[<p><em>I don’t know how to teach this. But I think I’ve figured out how to practice it…</em></p>

<hr />

<p>Have you ever struggled to get started with something new, not because the thing itself is hard, but because the <em>shape</em> of how to learn it isn’t clear? That’s where I’ve been stuck with agentic coding. Not the doing of it. I’ve been doing it for months. The teaching of it. The “how do I help someone else get started” of it.</p>

<p>And then I remembered code retreats. And katas. And the way I actually learned TDD all those years ago, not from a book, but from structured practice with low stakes and room to play.</p>

<p>So I built a set of agentic katas: structured coding exercises designed specifically for practising AI-assisted development. Not traditional katas, those are too small and the AI already knows all the answers. These are bigger, meatier problems in unfamiliar domains that force you to engage with the full process of working alongside an agent.</p>

<p>Let me explain how I got here.</p>

<h2 id="a-brief-history-of-practising-on-purpose">A Brief History of Practising on Purpose</h2>

<p>Early in my career, code retreats were the thing that taught me test-driven development. Not a book. Not a course. A structured, all-day event where you solve Conway’s Game of Life over and over again, each time with different constraints. Maybe your pair is actively trying to <em>not</em> solve the problem. Maybe you’re strictly ping-ponging. Maybe you delete your code every 45 minutes.</p>

<p>The point was never to solve Conway’s Game of Life. The point was to internalise the patterns and practices of TDD by giving yourself a safe space to experiment. No production pressure. No deadlines. Just play.</p>

<p>Code katas grew out of the same ethos, small self-contained problems that shouldn’t take more than an hour or two. The algorithm doesn’t matter. How you choose to solve it does. They’re bite-sized by design. They’re not supposed to be hard. They’re supposed to be <em>practice</em>.</p>

<h2 id="the-problem-with-katas-and-ai">The Problem with Katas and AI</h2>

<p>Here’s the thing I’ve been struggling with: traditional code katas don’t work for learning agentic development. They’re too small. The LLM has already seen every solution to FizzBuzz and Roman Numerals in its training data. You’re not practising a workflow, you’re watching an AI regurgitate a known answer. There’s nothing to explore, nothing to plan, no decisions to make about approach or tooling.</p>

<p>And that matters, because the skill you need to develop with agentic coding isn’t “how to prompt an AI to write code.” It’s how to <em>think alongside one</em>. How to explore a problem space together. How to write a plan that gives an agent enough context to be useful. How to verify that what came back is actually what you wanted. How to set up your workspace so the AI has the right guardrails.</p>

<p>None of that shows up in a 30-minute kata where the AI already knows the answer.</p>

<h2 id="the-accidental-discovery">The Accidental Discovery</h2>

<p>What’s funny is that I’ve kind of been doing agentic katas already, almost by accident. I just didn’t realise it at the time.</p>

<p><img src="/assets/agentic-kata/kata1.png" alt="The first kata" /></p>

<p>A few weeks ago I wrote about <a href="https://www.petervanonselen.com/2026/02/10/agentic-play/">deleting code on purpose as a way to recover from burnout</a>. I’d been experimenting with the Ralph Wingum loop, throwing PRDs at an agentic coding workflow, seeing what came out, then deliberately throwing the code away. The output I was chasing wasn’t a codebase. It was understanding. How big can a PRD get before the loop breaks? How much do agent files matter? What’s the minimum setup to get something useful?</p>

<p>Each run was a contained experiment. Fresh repo, clear problem, focused practice, delete the code, do it again. I was varying one thing at a time, adding a CLAUDE.md file, scaling up the PRD size, trying a different domain, and learning from each iteration.</p>

<p>I was doing agentic katas. I just hadn’t named them yet.</p>

<p>Looking back, the whole arc has been building toward this. My game project was the first rough version, months of cycling through spec-driven development and making mistakes. The “delete the code” experiments compressed that into focused sessions. And now, formalising the structure into something other people can pick up feels like the obvious next step.</p>

<h2 id="building-the-thing">Building the Thing</h2>

<p>So I’ve put together a set of agentic katas. The idea is that each one should require somewhere in the region of four to eight hours of focused hand crafted work to do <em>well</em>. And by “well” I mean the full golden plate: test-driven, 100% coverage, clean README, proper git history, the works. Not because the output matters, but because doing that level of work with an AI agent forces you to actually engage with the process.</p>

<p>The loop for every kata is the same:</p>

<p><strong>Explore</strong> → <strong>Plan</strong> → <strong>Set Up Context</strong> → <strong>Build</strong> → <strong>Verify</strong></p>

<p>And there’s one key rule that makes the whole thing work: <em>you are not allowed to choose a programming language or framework until you’ve had a conversation with your AI tool about what the best approach is.</em></p>

<p>This is the rule that forces the shift. Instead of jumping straight to “build me X in TypeScript,” you have to start with “I need to solve this problem, what are my options?” You explore the problem space. You figure out what tools exist. You have the AI challenge your assumptions. <em>Then</em> you decide on an approach.</p>

<p>From there, you write a detailed plan, acceptance criteria, example data, use cases, a breakdown into small chunks of work. You set up your workspace with an agent file and think about what context to include. You build incrementally. And you verify everything: read the plan, read the code, run it, test it, confirm it does what you intended.</p>

<p><img src="/assets/agentic-kata/agentic-kata-loop.svg" alt="the loop" /></p>

<h2 id="the-katas-themselves">The Katas Themselves</h2>

<p>I’ve started with four problems, each chosen because they sit in a domain most developers haven’t worked in before:</p>

<p>An <strong>audio transcriber</strong> that handles speech-to-text with timestamps and speaker diarisation. A <strong>background remover</strong> for image segmentation. A <strong>meme generator</strong> that deals with text rendering and positioning on arbitrary images. And a <strong>thumbnail ranker</strong> that scores images for visual appeal.</p>

<p>Each kata has deliberate ambiguity baked in, because real problems are ambiguous, and part of the skill is figuring out what questions to ask. They also have a privacy constraint (everything runs locally, no cloud APIs for processing) and an extra credit extension for when you want to push further.</p>

<h2 id="why-this-matters-right-now">Why This Matters Right Now</h2>

<p>I’ll be honest: the reason I’m putting this together is partly selfish. I want to run a workshop with my colleagues, and I need structured material to do it. But there’s a bigger motivation too.</p>

<p>Right now, everything about AI and software development feels incredibly intense. Fear of being made obsolete. AI layoff discourse everywhere. The pressure to have strong opinions about tools you’ve barely had time to evaluate. It’s all very stressful, and stress is the enemy of learning.</p>

<p>What people actually need, what <em>I</em> needed, and what I accidentally created for myself, is a safe space to play. A contained environment where you can try things, make mistakes, and build intuition without the stakes of production code or career anxiety hanging over you.</p>

<p>Code retreats gave us that for TDD. I’m hoping agentic katas can do the same for working with AI.</p>

<h2 id="the-repo">The Repo</h2>

<p>I’ve put everything together in a repo: <a href="https://github.com/vanonselenp/agentic-katas">github.com/vanonselenp/agentic-katas</a></p>

<p>It includes the kata briefs, a participant guide covering the rules and process, and a facilitator guide for anyone who wants to run this as a structured session with their team. A session takes about 90 minutes.</p>

<p>I haven’t run this with anyone else yet. I only put it together today, and I’m planning to trial it with my team in the coming weeks. It might be brilliant. It might be terrible. Either way, I’ll write about how it goes.</p>

<p>But the core idea, that you need bigger, unfamiliar problems to practise AI-assisted development, and that the process matters more than the output, that I’m confident about. Because I’ve been living it, accidentally, for months.</p>

<p>If you try it, I’d love to hear how it goes. And if you’re doing something different to build these skills, I’d love to hear about that too.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="claudecode" /><category term="specdrivendevelopment" /><category term="katas" /><category term="softwarecraftsmanship" /><summary type="html"><![CDATA[I don’t know how to teach this. But I think I’ve figured out how to practice it…]]></summary></entry><entry><title type="html">14 PRs, 6 Repos, 1 Button: A Tale of Tumbling Down the Rabbit Hole</title><link href="https://www.petervanonselen.com/2026/02/12/rabbit-holes/" rel="alternate" type="text/html" title="14 PRs, 6 Repos, 1 Button: A Tale of Tumbling Down the Rabbit Hole" /><published>2026-02-12T08:00:00+00:00</published><updated>2026-02-12T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2026/02/12/rabbit-holes</id><content type="html" xml:base="https://www.petervanonselen.com/2026/02/12/rabbit-holes/"><![CDATA[<p><em>True stories from the front lines of the internet…</em></p>

<hr />

<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Down_the_Rabbit_Hole_%28311526846%29.jpg/960px-Down_the_Rabbit_Hole_%28311526846%29.jpg" alt="Alice falling down the rabbit hole" />
<em>Alice in Wonderland by <a href="https://commons.wikimedia.org/wiki/File:Down_the_Rabbit_Hole_(311526846).jpg">Valerie Hinojosa</a> / <a href="https://creativecommons.org/licenses/by-sa/2.0/">Creative Commons Attribution-Share Alike 2.0
</a></em></p>

<p>Now this is a story all about how one button link got my codebase flipped turned upside down. And I’d like to take a minute, just sit right there, and I’ll tell you how I shipped 14 PRs without pulling out my hair.</p>

<p>It started with a Monday morning meeting. I’d been off for three weeks. The meeting was dense with context about decisions made months ago, documented across scattered specs and design docs. Systems I don’t own. Plans originally speced out almost a year prior. SEO requirements. Legacy middleware behaviour. And somewhere in all of this, a single task: change where a subscribe button points.</p>

<p>The old flow routed users through a legacy auth endpoint which was a piece of middleware handling user state and return-to-site functionality. The new flow should skip that layer and go direct. Simple, right?</p>

<p>Three repos. 3 small PRs. That was the original scope.</p>

<p>It became six repos and one or two more PRs…</p>

<h2 id="the-context-problem">The Context Problem</h2>

<p>Here’s what made this tricky: I didn’t have the context. Not the institutional knowledge of why things were built this way. Not the codebase familiarity to know where all the tendrils reached. Not the cross-system visibility to see how changes would ripple.</p>

<p>Normally, this is where you’d involve other teams. Schedule alignment meetings. Negotiate architecture choices. Coordinate timed releases. The org chart becomes the constraint.</p>

<p>Instead, I threw five AI tools at the problem.</p>

<p>I used internal knowledge search to surface half a dozen docs from a year ago about what a potential migration might look like. Copilot and Codex scanned repos I’d never opened, outputting high-level analysis of what would need to change. NotebookLM synthesised a dozen-plus sources into actionable Jira tickets with acceptance criteria and testing plans. And Claude handled the actual implementation across all six repositories.</p>

<p>Each tool for what it does best. None of them sufficient alone.</p>

<h2 id="the-shape-of-the-change">The Shape of the Change</h2>

<p>What was supposed to be three repos became six because the AI tooling kept finding rabbit holes worth going down.</p>

<p>The approach was backwards compatibility first. I updated the auth service to forward requests to the new endpoint, so existing systems would keep working. Only after that was stable did I remove the old code paths and switch the calls to point directly to the new flow.</p>

<p>Along the way, I hit a referrer bug that only revealed itself mid-implementation. One of the components lived in a shared library, not a full application, which meant handling referral data differently than expected. This meant that I had to change how it was reading from window referrer data rather than relying on direct redirect URLs.</p>

<p>And then there was a shared header component in another team’s repo. Hardcoded to the old endpoint. In code I couldn’t easily modify. The rabbit holes kept cropping up every time I thought I dived down them all.</p>

<p>Fourteen PRs. Six repositories. Backwards compatible throughout. Zero downtime.</p>

<p>The old flow had an extra hop through legacy middleware that handled state management. The new flow removes that layer entirely. Which makes for a faster time to checkout, same user experience, one less thing to maintain.</p>

<h2 id="the-point">The Point</h2>

<p>This would have been a multi-team effort. Alignment meetings across three teams, at minimum. Negotiated timelines. Architectural discussions. Coordinated releases.</p>

<p>Instead, it was one developer holding context that used to require an org chart.</p>

<p>I’m not saying AI tooling makes you a better engineer. I’m saying it lets you hold more context. And sometimes that’s the difference between “we’ll need to schedule a meeting with the other teams” and “I’ll have a PR up by Thursday.”</p>

<p>The context ceiling just got a lot higher.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><category term="codex" /><summary type="html"><![CDATA[True stories from the front lines of the internet…]]></summary></entry><entry><title type="html">This Is the Way: Delete the Code</title><link href="https://www.petervanonselen.com/2026/02/10/agentic-play/" rel="alternate" type="text/html" title="This Is the Way: Delete the Code" /><published>2026-02-10T08:00:00+00:00</published><updated>2026-02-10T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2026/02/10/agentic-play</id><content type="html" xml:base="https://www.petervanonselen.com/2026/02/10/agentic-play/"><![CDATA[<p><em>How I learned to do AI Katas and make disposable code helped me recover from burnout</em></p>

<hr />

<p>Burnout is real, and it takes time to work its way out.</p>

<p>I spent the last couple of months trying to work up the will to tackle game projects again. Every attempt fizzled. After a 3+ month slog on a project that <a href="https://www.petervanonselen.com/2025/11/20/scope-creep/">refused to reach an end state</a>. I had nothing left.</p>

<p>So instead of committing to another massive project, I started playing.</p>

<p>I came across the Ralph Wingum loop (<a href="https://www.youtube.com/watch?v=RpvQH0r0ecM">30-min video if you’re curious</a>) and decided to experiment. The premise is simple: use two Claude skills and a bash script to let an AI go full agent mode. The first skill, <code class="language-plaintext highlighter-rouge">/prd</code>, takes a spec and generates user stories with verifiable acceptance criteria. The second, <code class="language-plaintext highlighter-rouge">/ralph</code>, converts that PRD into JSON. Then you loop over the JSON until done. This is basic agentic coding, but AI-agnostic and surprisingly effective.</p>

<p><img src="/assets/agentic-play/image.png" alt="the wiggam loop" /></p>

<p>I needed a project to test this on, so I picked <a href="https://boardgamegeek.com/boardgame/163474/v-sabotage">V-Sabotage</a>. It’s a board game I enjoy but rarely get to play (toddler life), and more importantly, it’s simple enough to define a clear MVP: rooms, a player, guards, sneaking mechanics, a win condition. I’d learned my lesson about scope.</p>

<p>The real experiment wasn’t building the game. That was just the head fake. It actually was figuring out how to break down the work. How big should each PRD be? Do you treat each milestone as its own PRD? Do you throw the whole spec at it and see what happens?</p>

<p>I had to find out.</p>

<p><strong>First run:</strong> I threw a PRD at the skills, ralphed it, and looped on a fresh repo. What came out was very familiar from the last time I was building a game in Godot with AI. Bascially something that worked, but buggy, clunky, no tests, poor signal architecture, tightly coupled code.</p>

<p><strong>Second run:</strong> Same PRD, same loop, but this time I initialised the repo with a CLAUDE.md file first. Just basics: test-drive the code, use Godot 4.x best practices, that sort of thing.</p>

<p>The difference was dramatic. The AI wrote its own test runner. It test-drove everything, achieved high coverage, produced cleaner interfaces, used signals properly, and kept things decoupled. Twenty minutes of compute, and the output was genuinely good. Honestly the thing that blew my mind on this was <strong>it wrote it’s own TEST RUNNER!?!?</strong>. Are you kidding me?</p>

<p>So … key lesson: agent files matter. A lot.</p>

<p><strong>Third run:</strong> I embedded full milestones into the PRDs—a dozen user stories each, multiple acceptance criteria. The loop churned through it and produced a testable MVP in surprisingly little time.</p>

<p><img src="/assets/agentic-play/tactics.png" alt="stealth game" /></p>

<p><strong>Fourth run:</strong> I got distracted by an app idea. Spent a couple of hours refining it with AI, generated a chunky PRD, threw the whole thing at the <code class="language-plaintext highlighter-rouge">/prd</code> skill. It produced 40 stories. I looped it. An hour later, with 5% of my usage allowance remaining, I had a working prototype.</p>

<p><img src="/assets/agentic-play/mobile-app.png" alt="random app" /></p>

<p>It didn’t do exactly what I wanted. But it did most of what I’d asked. This was surprisingly more than enough to immediately change my thinking about what I actually needed in a meaningful way.</p>

<p>And here’s the thing that made all of this feel like play instead of work: <strong>I deleted the code.</strong>. I went full <a href="https://www.coderetreat.org/">code retreat conways game of life</a> delete the code.</p>

<p>Multiple times. Deliberately. The output I was chasing wasn’t a codebase. It was understanding. How big can a PRD get before the loop breaks? (Bigger than I expected.) How much do agent files matter? (More than I expected.) What’s the minimum setup to get something useful? (Less than I expected.)</p>

<p>Disposable code meant low stakes. Low stakes meant I could experiment freely. And experimenting freely, it turns out, is how I recover from burnout.</p>

<p>This play has fundamentally changed how I work at The Economist. But that’s a story for next time.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><category term="codex" /><summary type="html"><![CDATA[How I learned to do AI Katas and make disposable code helped me recover from burnout]]></summary></entry><entry><title type="html">Why You Shouldn’t Speedrun a Production Refactor</title><link href="https://www.petervanonselen.com/2025/12/12/speedrunning-prod-refactors/" rel="alternate" type="text/html" title="Why You Shouldn’t Speedrun a Production Refactor" /><published>2025-12-12T08:00:00+00:00</published><updated>2025-12-12T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/12/12/speedrunning-prod-refactors</id><content type="html" xml:base="https://www.petervanonselen.com/2025/12/12/speedrunning-prod-refactors/"><![CDATA[<p><em>Learning the hard way that AI makes discipline more important, not less…</em></p>

<hr />

<p>This week has been a mess. I’ve been ill since last Thursday with a cough that’s been both productive and dizzying, which in a rare moment of clarity made me realize that maybe doing personal dev in the evenings is… not ideal. So no game dev tales this week.</p>

<p>Instead, I want to talk about how I nearly torpedoed a production refactor at The Economist a month ago by forgetting the most important lesson I’ve been learning over the past few months: <strong>AI makes discipline more important, not less.</strong></p>

<h2 id="the-spectacular-failure">The spectacular failure</h2>

<p>I’m currently on the e-comm-funnel team working on the checkout pipeline. One of my first projects has been tackling Commerce Services. This is a Go monolith (a language I’d never used before recently) that started as a POC and got productionized. Naturally, it’s a beautiful mess with conflicting APIs doing all sorts of non-cohesive domain things.</p>

<p>My goal: break it into microservices.</p>

<p>So naturally I did what I’ve been practicing with Horizons Edge and started with a spec. I had a very long conversation with Codex, analyzed the repo structure, identified the domains, mapped dependencies. From this chat we produced a solid 10 page high-level plan.</p>

<p>And the first step of that plan was <em>Phase 1: extract common code into a shared library</em>.</p>

<p>And somewhat predictably, here’s where I got clever.</p>

<p>I thought: “I’ve got a detailed spec. Codex knows Go. Let’s just… do the whole thing! Whats the worst that could happen?”</p>

<p>So I did. One massive refactor. Codex happily obliged.</p>

<p>Then I looked at the pull request: <strong>200 files changed in the monolith. 80 files in the new library.</strong></p>

<p><img src="/assets/speedrun-refactor/this-is-fine.png" alt="this is fine, right?" /></p>

<p>And I just stared at it, completely overwhelmed by the obvious question: <em>How the hell am I going to verify this actually works?</em></p>

<p>There was no way I could meaningfully review 280 files of changes. No way I could ask another engineer to do it. No way to be confident this wouldn’t break something subtle in production. I’d just created an unshippable monster.</p>

<h2 id="starting-over-properly-this-time">Starting over, properly this time</h2>

<p>I scrapped the entire thing and started again with an “I need this to be incremental” mindset.</p>

<p>Not just because I wanted to be able to review it, though that’s critical, but because I genuinely believe small releases into production are the right way to work. It should have been my default starting point. Instead, I’m still learning just how disciplined I need to be when working with AI tooling.</p>

<p>The new approach:</p>

<p><strong>First</strong>, I wrote a much more detailed spec for Phase 1 that lived in the new repo. Not just “extract shared library” but an 8-step plan where each step could go to production independently. Start with the absolute minimum: just one joint service with no dependencies. This would validate the CI/CD pipeline, the integration points, everything, with the smallest possible change.</p>

<p><strong>Then</strong>, one step at a time:</p>
<ul>
  <li>Extracted and deploy leaf utilities (logging, validation, middleware)</li>
  <li>Migrated HTTP routing abstractions</li>
  <li>Moved observability and AWS helpers</li>
  <li>Extracted infrastructure components like health checks</li>
  <li>Finally, the component registry</li>
</ul>

<p>At each step: tested, improved coverage, deployed to production, monitored. The existing systems kept running exactly as before.</p>

<p>I followed the same hyper-methodical approach I’ve been using with the game project. Focusing on small scoped MVP slices and incremental delivery. For the actual development, I loaded Codex into a workspace with both repos and had it follow the spec file for each migration. Then validated with Claude in GitHub Copilot, extensive personal review, and eventually team review before each production deployment.</p>

<p>The result: A refactor of a core system touching ~200 files, in a programming language I’m just learning, in a domain I’d just joined, completed over a couple of weeks with zero downtime. No one on the team was blocked or impacted. It just happened quietly in the background.</p>

<h2 id="what-im-taking-away">What I’m taking away</h2>

<p>Two things keep reinforcing themselves across contexts:</p>

<p><strong>First</strong>: AI amplifies your need for discipline. The easier it becomes to generate large amounts of code, the more critical it is to think carefully about scope, verification, and deployment strategy. One-shotting 280 files feels productive in the moment. It’s not. It’s just creating an unshippable mess you’ll have to undo.</p>

<p><strong>Second</strong>: The “what’s the smallest increment that adds value?” mindset pays off everywhere. It saved Horizons Edge when I was drowning in scope creep. It made this refactor safe and reviewable. It’s not just a nice-to-have for side projects … it’s how you de-risk production changes in unfamiliar territory.</p>

<p>Next up is breaking out actual domains into microservices, starting with Identity &amp; User. But that’s a plan for next year, when I’m hopefully no longer coughing my lungs out.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><category term="codex" /><summary type="html"><![CDATA[Learning the hard way that AI makes discipline more important, not less…]]></summary></entry><entry><title type="html">Finally… A Wild MVP Appears</title><link href="https://www.petervanonselen.com/2025/12/04/finally-a-wild-mvp-appears/" rel="alternate" type="text/html" title="Finally… A Wild MVP Appears" /><published>2025-12-04T08:00:00+00:00</published><updated>2025-12-04T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/12/04/finally-a-wild-mvp-appears</id><content type="html" xml:base="https://www.petervanonselen.com/2025/12/04/finally-a-wild-mvp-appears/"><![CDATA[<p><em>Three Months to MVP: What I Learned Building a Tactical Card Game with AI…</em></p>

<hr />

<p><img src="/assets/mvp/banner.png" alt="banner" /></p>

<p>It’s been three months since I started trying to make Horizon’s Edge, a tactical turn-based wargame in the sky. And honestly, I’m completely stunned that I even have something that actually … kinda … works.</p>

<h2 id="from-vibe-to-spec">From Vibe to Spec</h2>

<p>When I started this project, I was pure vibe coding. But somewhere in the middle, when I was trying to refactor the UI from a classic RTS/turn-based strategy with a mass of buttons to something entirely driven by card play, vibe coding hit a wall. I couldn’t get AI tooling to cooperate with my loose intuitions. That’s when I started working with specs and it changed my life…. metaphorical life …. but life!</p>

<p><img src="/assets/mvp/cards.png" alt="card driven" /></p>

<p>Writing a clear specification before diving head first into a vibe changed everything. Suddenly the AI had guardrails. It stopped looping in circles. If you want to go deeper on this, I wrote about starting to figure out specs in <a href="https://claude.ai/2025/10/03/chaos-cards-and-claude-copy/">Chaos, Cards, and Claude</a>.</p>

<h2 id="months-of-education">Months of Education</h2>

<p>What I’ve learned so far is this: it’s entirely possible to make working software with AI tools. You can keep momentum even when you’re completely out of energy or time. But the most important thing … the thing that actually matters … is that you have to always verify what the AI outputs. Automated unit tests are your best friend here. A Quality first mindset and thinking about edge cases is fundamental.</p>

<p><img src="/assets/mvp/waveform.gif" alt="waveform generation" /></p>

<p>I’ve done major refactors. I’ve rethought how the game works multiple times. I added procedural generation because it was fun. I figured out how to make the game work with just card play mechanics that… mostly work (much to my surprise). Some refactors were vibe-coded disasters; others were spec-driven and clean. But every single one taught me something about how to work with AI as a tool rather than a replacement.</p>

<h2 id="the-mvp-what-it-took">The MVP: What It Took</h2>

<p>Two days ago I finished the final major system needed to validate the MVP: the victory system. Islands needed to change ownership. Every existing system needed to integrate with that. Core island nodes needed to be targetable from creatures, spells, and abilities. Getting the targeting code to work meant hitting more touch points than I anticipated. A lot of different abilities needed specific ways to target islands, not just creatures. It was more entertaining than expected, but I had a spec, and that spec kept me honest.</p>

<p>I now have two thematic decks that are actually unique. 10 creatures. Infrastructure cards that terraform and change the world. A spell that destroys the world. Card play mechanics that mostly work. A whole horde of nuanced and detailed rules about damage and combat that work.</p>

<p><strong>Prototype done. Well, mostly.</strong></p>

<p>The mechanics are all there. What’s left is UI feedback. Cards need to show their play cost clearly, what they do when discarded, what abilities they have before you play them. I know all this because I’ve spent three months building it. Others won’t. So I’m going to tackle those UI gaps this week, then put this in front of a few people to get real feedback.</p>

<h2 id="now-its-your-turn">Now It’s Your Turn</h2>

<p>I’ve spent the past five months working on this. It started with a Magic the Gathering Pauper Jumpstart cube that just wouldn’t get out of my head, went running headlong into a board game prototype that was way too complicated and barrelled straight into this game. I’ve learned a ridiculous amount. <strong>But here’s what actually matters:</strong></p>

<p>It is possible to make working software with AI. You can make some amazing things with these tools. You can learn as you go. You can ship those crazy ideas you never thought you could.</p>

<p><strong>So here’s what I want:</strong></p>

<p>I want <em>you</em> go out and make your own mistakes. Build something weird. Use AI as a tool, verify everything it does, and then make something great. Make art. Because making art, well, that’s the most human thing we can do.</p>

<p>Tell me what you build. I want to hear about it.</p>

<p>Till then, keep learning.</p>

<div style="position: relative; width: 100%; padding-bottom: 56.25%; height: 0; overflow: hidden;">
  <iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" src="https://www.youtube.com/embed/NdQgOLlt8QQ?si=F2rdwci0GcDvNm9R" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>
</div>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="godot" /><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><summary type="html"><![CDATA[Three Months to MVP: What I Learned Building a Tactical Card Game with AI…]]></summary></entry><entry><title type="html">The Long Road to MVP</title><link href="https://www.petervanonselen.com/2025/11/27/long-road-to-mvp/" rel="alternate" type="text/html" title="The Long Road to MVP" /><published>2025-11-27T08:00:00+00:00</published><updated>2025-11-27T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/11/27/long-road-to-mvp</id><content type="html" xml:base="https://www.petervanonselen.com/2025/11/27/long-road-to-mvp/"><![CDATA[<p><em>How I learned to stop overthinking and ship the damn thing…</em></p>

<hr />

<p><img src="/assets/long-road/banner.png" alt="banner" /></p>

<p><a href="https://www.petervanonselen.com/2025/11/20/scope-creep/">Last week I had a sudden but inevitable realisation</a>. Basically my MVP was completely not an MVP but rather a bloated over-built system that I should have been moving to release sooner. Which in hindsight I should have realised… 4 weeks ago. Lesson learned.</p>

<p>So, this week I started with yet another plan where I detailed out a new spec that broke down the exact things I needed to do. And then… I did just that! Everything else is deferred.</p>

<p><strong>Broad plan for MVP:</strong></p>
<ul>
  <li>1 Spell: Meteor - DONE</li>
  <li>1 Victory condition: own all the islands - IN PROGRESS</li>
  <li>2 Unique Decks - TODO</li>
</ul>

<p>The spell was easy. Just another ability, and make it bigger, cost more and have an animation that then removes a massive amount of real estate. Big, flashy, simple.</p>

<p><img src="/assets/long-road/meteor.gif" alt="meteor" /></p>

<p>The victory condition, however, has turned into a far more crunchy problem. Turns out wiring up ownership, health tracking, and win conditions across multiple systems was messier than I thought. I’ve built:</p>
<ul>
  <li>A <strong>game over</strong> screen to start a new game</li>
  <li>Health on the core island node</li>
  <li>A UI display to see that health</li>
  <li>A manager to track who owns the islands and a way to change ownership</li>
  <li>A victory condition that checks each round if someone’s actually won</li>
</ul>

<p>Almost there! The missing piece is creatures targeting the core island and dealing damage to it. Once I wire up that damage pathway, the whole system clicks. That’s what I’m grinding through at the moment.</p>

<p>All that will be left is two decks. Which should be as simple as updating two config files, and I’ll have a playable MVP. Finally.</p>

<p><img src="https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExOG05YndpM2NxbWIxaDE5N2t0ODg2NDRia29tdWd0OXhoaXViMTFhaSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/dyw4fuAhPaIh0japgg/giphy.gif" alt="light" /></p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="godot" /><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><summary type="html"><![CDATA[How I learned to stop overthinking and ship the damn thing…]]></summary></entry><entry><title type="html">How Many Times Do You Have to Build Too Much to Learn Scope Creep?</title><link href="https://www.petervanonselen.com/2025/11/20/scope-creep/" rel="alternate" type="text/html" title="How Many Times Do You Have to Build Too Much to Learn Scope Creep?" /><published>2025-11-20T08:00:00+00:00</published><updated>2025-11-20T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/11/20/scope-creep</id><content type="html" xml:base="https://www.petervanonselen.com/2025/11/20/scope-creep/"><![CDATA[<p><em>Scope Creep Keeps Teaching Me…</em></p>

<hr />

<p><img src="/assets/scope-creep-november/banner.png" alt="banner" /></p>

<h1 id="scope-creep-keeps-teaching-me">Scope Creep Keeps Teaching Me</h1>

<p>Have you ever had one of those weeks where you suddenly have to be traveling a lot and don’t really have any time for personal projects? This has been my week. I still managed to get two creatures and six abilities created.</p>

<p>The Flux Chaos controls the board by moving creatures into and out of position, swapping them from behind enemy lines or randomly teleporting them somewhere (maybe even off into the void). The Flux Storm does massive area damage while locking down the area preventing anyone from teleporting in and out. Watching these creatures interact with the existing systems is delightful. The abilities are beginning to feel like they synergize and interact together nicely.</p>

<p><img src="/assets/scope-creep-november/chaos-storm.png" alt="chaos and storm" /></p>

<p>I’ve been on a mission to prototype this strange game idea for a while now. I started the repo on September 4th. Three months later, I’m watching a prototype that’s actually starting to feel like a game with interesting systems.</p>

<h2 id="but-heres-what-i-should-have-learnt-sooner-i-didnt-cut-far-enough">But here’s what I should have learnt sooner: I didn’t cut far enough.</h2>

<p>When I started, I aggressively removed things. All 8 envisioned factions. The single-player campaign, stories, and lore. AI players. Multiplayer. Different form factors like mobile. Complex models and animations. I thought I’d solved the scoping problem. Oh how innocent I was.</p>

<p>I then built ten creatures with twenty-nine abilities. I added procedural island generation and dynamic road construction. I went down tangents and rabbit holes as I iterated from RTS-style UI to pure card-driven gameplay.</p>

<p>Looking at that list now, that should have been a warning sign. And it gets worse: my remaining feature list for MVP includes five more buildings, five more spells, multiple win conditions, fog of war, proper turn behavior, UI polish.</p>

<p>It’s only now that I am looking at my remaining feature list (I wrote up the list for this very blog post), that I realize the entirely obvious thing. I am <em>still</em> overscoping. Scope creep doesn’t stop after one round of cuts. It’s persistent. Even when you’re actively trying to think in MVP terms, there’s a pull to add one more building, one more spell, one more system. Each one feels necessary. But they compound.</p>

<p>I should have picked this up sooner: that grinding feeling I’ve been having with the creatures and abilities. It has felt like motivation leeching away in the never ending drudgery. It was a clear warning sign I was off the path.</p>

<p>So here’s my actual MVP: one spell (meteor), Fog of War, one win condition, UI, and two decks. That’s it. Just the core systems missing, playable, shippable. This is what I should have built from the start, the smallest thing that proves the concept works.</p>

<p><img src="/assets/scope-creep-november/simple.webp" alt="simple" /></p>

<h2 id="the-lesson-keeps-teaching-itself">The lesson keeps teaching itself</h2>

<p>I keep learning the same lesson over and over. I thought I’d solved scope creep when I cut factions and campaigns. Three months later, with ten creatures and twenty-nine abilities built, I realized I’d just learned the lesson at a different scale. Every time I ship something, I understand a little better what actually mattered. And every time, I realize I could have cut further.</p>

<p>The game is starting to have shape because I’ve been building and learning. But I’m also learning, again, that shipping something small and real beats shipping something comprehensive and theoretical. Time to cut deeper. This time, I’m shipping the prototype before I convince myself I need more.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="godot" /><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><summary type="html"><![CDATA[Scope Creep Keeps Teaching Me…]]></summary></entry><entry><title type="html">How to Get Things Done When You Have Nothing but Process</title><link href="https://www.petervanonselen.com/2025/11/13/the-no-good-low-energy-week/" rel="alternate" type="text/html" title="How to Get Things Done When You Have Nothing but Process" /><published>2025-11-13T08:00:00+00:00</published><updated>2025-11-13T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/11/13/the-no-good-low-energy-week</id><content type="html" xml:base="https://www.petervanonselen.com/2025/11/13/the-no-good-low-energy-week/"><![CDATA[<p><em>The tale of how a good System can carry you through the dark times…</em></p>

<hr />

<p><img src="/assets/no-energy-week/banner.png" alt="banner" /></p>

<p>This week I had zero motivation. Motivation tank completely empty.</p>

<p>My goal was 4 creatures and all of the remaining abilities. I only manage to build 2 creatures and 7 abilities instead.</p>

<p>That happening was astonishing to me.</p>

<p>But it did. And the reason isn’t hard work or willpower, it’s process. The structure on how to work with AI that I follow is robust enough to produce good work even when I have nothing left. That’s the real story.</p>

<h2 id="how-the-structure-holds-up">How the structure holds up</h2>

<p>My process is straightforward: compact the conversation, use the spec to guide the next iteration, verify the implementation, have the AI explain what it did, then manually test each ability. Rinse and repeat.</p>

<p>The spec-driven approach kept context alive, for me <em>and</em> the AI. While my motivation was completely drained, the AI kept building. I basically did the bare minimum each day before switching to Marvel Spider-Man, but the structure meant I never lost the thread. I was running on <a href="https://www.youtube.com/shorts/mVQ1bzd816I">Seinfeld method</a> momentum: just keep the chain unbroken.</p>

<p>But here’s the critical bit: <strong>verify everything the AI makes</strong>. The AI will confidently insist “Everything works perfectly!” and update your docs without being asked. Then you test it. Nothing works. You point it out and it turns out half the feature wasn’t there to start with. Point it out again, and more unfinished work is found. The AI is capable and also will miss the obvious. Trust but verify.</p>

<p><strong>Pro tip</strong>: never ever let the AI update the docs without being directly asked to.</p>

<p>This verification habit isn’t just bug-catching. It is the key habit that keeps the process from collapsing. Without it, you’re just building on sand. With it, even a low-energy week produces solid work.</p>

<h2 id="where-designs-actually-get-good">Where designs actually get good</h2>

<p>The most valuable phase in my workflow is when the AI explains what it just built. That’s where I stop and think: does this ability actually do what I want? Should it shift? Should it do something different?</p>

<p>That’s where the magic happens.</p>

<p><img src="/assets/no-energy-week/tank.png" alt="tank" /></p>

<p>The Biomass Tank’s parasitic bond is a perfect example. It started as a triggered ability, shifted into an activated passive that heals the Tank whenever <em>any</em> nearby enemy creature takes damage. That single design decision cascaded: upkeep suddenly mattered. Rounds had weight. Generator buildings became far more valuable, and vulnerable. The creature went from decent to a potential powerhouse with two different healing methods and the ability to stay safe at range.</p>

<p>The design got better not because I worked harder on it, but because I paused to think about what it <em>was</em> and what it <em>could be</em>.</p>

<p><img src="/assets/no-energy-week/defender.png" alt="defender" /></p>

<p>Same with the Voltage Defender. Its pull mechanic started simple—nudging creatures around the battlefield. But when I stopped to think about it, it shifted: what if it could move creatures <em>off islands entirely</em>? Suddenly it’s a broad control tool, shutting down buildings and repositioning the entire battlefield. That cascaded too—every ability needed rework. The EMP got bigger, affected every building including the player’s, made positioning critical.</p>

<p>This reflection loop, building something, stopping to think about it and then nudging the design. It keeps creating moments where the game gets better. It’s where iteration actually matters.</p>

<h2 id="the-real-lesson">The real lesson</h2>

<p>Turns out the structure matters more than the fuel. Low-energy weeks aren’t failures. They’re tests of process.</p>

<p>When you have nothing left, you find out what actually works. This week proved that good structure, spec-driven development, verification habits, and the discipline to reflect, can carry you through. The creatures got better not because I pushed harder, but because the process was solid enough to ship good work anyway.</p>

<p>I might not have had the energy. But the system did.</p>

<h2 id="next-week">Next week</h2>

<p>Fingers crossed, I will hopefully be finished the creature cards and start working on spells like Meteor and Lightning and getting some more buildings working correctly.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="godot" /><category term="vibecoding" /><category term="claudecode" /><category term="specdrivendevelopment" /><summary type="html"><![CDATA[The tale of how a good System can carry you through the dark times…]]></summary></entry><entry><title type="html">The Beautiful Boring: How I Refactored a Game Without Breaking it</title><link href="https://www.petervanonselen.com/2025/11/06/a-chill-refactor/" rel="alternate" type="text/html" title="The Beautiful Boring: How I Refactored a Game Without Breaking it" /><published>2025-11-06T08:00:00+00:00</published><updated>2025-11-06T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/11/06/a-chill-refactor</id><content type="html" xml:base="https://www.petervanonselen.com/2025/11/06/a-chill-refactor/"><![CDATA[<p><em>Can an AI Do a Boring Refactor? A Case Study in Systematic Code Cleanup</em></p>

<hr />

<p><img src="/assets/chill-refactor/banner.png" alt="banner" /></p>

<p>This week, my carefully-laid plans for rapid progress on <strong>Horizons Edge</strong>, a tactical wargame with card-driven combat on floating islands, collided headfirst with 2,255 lines of code and 94 functions living in a single file. Whoops. Just what I always wanted. I’d let a god class slowly brew and percolate while I focused on shipping features. Now it was time to pay the inevitable technical debt.</p>

<p>The wonderful file in question: <code class="language-plaintext highlighter-rouge">game_manager.gd</code>. It was managing twelve distinct functional areas: turn management, combat, creatures, cards, abilities, territory, players, and more. The result was tight coupling and maintenance friction of epic proportions.</p>

<h2 id="the-question-that-drove-me">The Question that drove me</h2>

<p>I’ve spent the last month learning how to work productively with AI on complex coding tasks. And I had a nagging question: <strong>Can an AI do a massive refactor productively? Can you have a boring refactor—a by-the-numbers, tick-the-boxes, super easy, chill refactor?</strong></p>

<p>This wasn’t just idle curiosity. When I last <a href="https://www.petervanonselen.com/2025/09/29/the-grand-refactor/">attempted a refactor of similar scope, it was an spectacular disaster</a>. I spent two evenings fighting with Claude about types, going in circles while the AI and I kept insisting the other was wrong. The game broke for days. It was a hair-pulling nightmare that never ended. It was painful, demoralizing, and left me deeply skeptical about whether AI could handle large-scale refactoring productively. That experience shaped everything about how I approached this week.</p>

<p>But this time felt different. <a href="https://www.petervanonselen.com/2025/10/30/exert-of-what-i-learnt/">I had a plan</a>.</p>

<p><img src="/assets/chill-refactor/plan.png" alt="a plan" /></p>

<h2 id="setting-the-constraints">Setting the Constraints</h2>

<p>Before diving in, I wanted to be intentional. I asked Claude to analyze the file and create a refactoring plan, but with strict requirements:</p>

<p><strong>Functional Requirements:</strong></p>
<ul>
  <li>Maintain existing behavior. No new code, no feature creep—same behavior, different structure.</li>
  <li>All key systems had to keep working: card play, creature combat, energy systems, turn management, terrain creation and destruction. Everything.</li>
</ul>

<p><strong>Technical Requirements:</strong></p>
<ul>
  <li>Files should be less than 400 lines each</li>
  <li>Absolutely no circular dependencies (this still haunts my nightmares)</li>
  <li>Follow good Godot practices using signal-based architecture and node-based composition</li>
</ul>

<p><strong>Methodology:</strong></p>
<ul>
  <li>Everything had to be incremental. No big bang refactors. Incremental changes mean incremental testing, which means catching bugs early.</li>
</ul>

<p>Claude produced a 1,091-line planning document comprising 11 phases, complete with a testing strategy, regression testing plan, and a high-level architecture with 8 new manager classes. It was exactly what I needed: a detailed roadmap to follow rather than a free-form creative challenge.</p>

<h2 id="the-method-that-worked">The Method That Worked</h2>

<p>Here’s the systematic approach I followed for every phase:</p>

<ol>
  <li><strong>Clean context</strong>: Open a new terminal window with a fresh Claude context (no conversation history creep)</li>
  <li><strong>Implement one phase</strong>: Ask Claude to implement just that single phase from the planning document</li>
  <li><strong>Verify no regressions</strong>: Get Claude to check to verify its work</li>
  <li><strong>Create a manual test plan</strong>: Have Claude outline a manual testing plan</li>
  <li><strong>Hand test and fix</strong>: Switch back to vibe coding; find bugs, fix them one at a time</li>
  <li><strong>Commit with clarity</strong>: Once working, commit to the branch with a descriptive message</li>
</ol>

<p>This rhythm was key. It prevented the cognitive overload of trying to refactor everything at once while still making steady progress.</p>

<h2 id="the-results">The Results</h2>

<p><img src="/assets/chill-refactor/gitcommit.png" alt="commit history" /></p>

<p>I started Friday evening and finished Tuesday evening. Seven hours total—an hour Friday night, four hours scattered across the weekend, another hour or two on Monday and Tuesday combined.</p>

<p>And here’s what shocked me: <strong>the game never broke</strong>. Not once. This was the easiest refactor of such a complicated system I’ve done in my career.</p>

<p>The difference was night and day compared to last month. That first refactor had been a hair-pulling nightmare. The game was down for days, I was fighting with the AI in circles, nothing felt under control. This time? The game was working the entire time. Every phase landed in manageable doses. I could test incrementally. I could fix bugs before they cascaded into system-wide failures.</p>

<p>It’s a quintessential example of risk mitigation in action. Small, verifiable steps beat big, catastrophic swings every time.</p>

<p>Unlike that previous disaster, this one was systematic. Methodical. Boring, even. It felt like just a matter of following good habits and executing. No dramatic debugging sessions. No circular reasoning about types. No late-night frustration.</p>

<p>There was something almost boring about how well it worked. And that was the point.</p>

<h2 id="what-this-taught-me">What This Taught Me</h2>

<p>The breakthrough wasn’t a better AI. It was a better process. By being intentional about constraints, breaking work into small phases, maintaining a testing regimen, and keeping context clean, I transformed a refactoring task from a high-risk, high-stress nightmare into a predictable, manageable project.</p>

<p>That first refactor failed because I was vibe-coding with the AI. It was reactive, unfocused, trying to solve the whole problem at once. This one succeeded because I treated it like a spec-driven project with a plan, clear objectives, and systematic execution.</p>

<p>The lesson: AI isn’t magic. It’s a tool. And like any tool, it works best when you know exactly what you’re trying to build and you approach it methodically.</p>

<h2 id="whats-next">What’s Next</h2>

<p>Now I can finally get back to what I actually want to be doing: making <strong>Horizons Edge</strong> a better game.</p>

<p><img src="/assets/chill-refactor/voltage-defender.png" alt="voltage defender" /></p>

<p>This coming week: three new creatures with three abilities each. <strong>Voltage Defender</strong> (exactly what it sounds like), <strong>Biomass Tank</strong> (a tanky presence), and <strong>Flux Chaos</strong> (honestly, even I don’t know what this one is yet. That’s kinda the fun of discovery). More abilities. More discipline. More checkboxes to tick.</p>

<p>Until next time, may your refactors be as boring, and your code as stable, as this one turned out to be.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="vibecoding" /><summary type="html"><![CDATA[Can an AI Do a Boring Refactor? A Case Study in Systematic Code Cleanup]]></summary></entry><entry><title type="html">The Boring Path to Actually Shipping with AI</title><link href="https://www.petervanonselen.com/2025/10/31/boring-path-to-shipping/" rel="alternate" type="text/html" title="The Boring Path to Actually Shipping with AI" /><published>2025-10-31T08:00:00+00:00</published><updated>2025-10-31T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/31/boring-path-to-shipping</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/31/boring-path-to-shipping/"><![CDATA[<p><em>Or: How I Learned to Stop Vibing and Love the Spec”</em></p>

<hr />

<p>OMG. This <a href="https://www.petervanonselen.com/2025/10/30/exert-of-what-i-learnt/">spec driven development</a> process is BORING!</p>

<p>Okay okay, for reals though, following this process of using a spec and a clear breakdown of tasks is tangibly yielding results and making remarkable progress forward in the game.</p>

<p><img src="/assets/boring/3-heroes.png" alt="3 heroes" /></p>

<p><strong>In the past week I have:</strong></p>
<ul>
  <li>Created 3 new creatures: one that moves fast, hits hard and stuns enemies; another that spawns minions and multiplies when it dies; and one that shoots a bolt that blows things up and destroys land all over the place</li>
  <li>Around 9 new abilities created and working</li>
  <li>Got the AI to hack some terrible models together so they would be unique enough to be playable</li>
  <li>Made the islands generate more interestingly</li>
  <li>Completed a horde of UI cleanups</li>
  <li>Handled some general refactorings and got a bunch of systems working</li>
  <li><strong>Total changes:</strong> 52 files modified, +3,718 lines, -474 lines across 34 commits all for about 10 hours effort.</li>
</ul>

<p>By basically all metrics… productive?</p>

<h2 id="so-where-did-the-boring-comment-come-from">So Where Did the “Boring” Comment Come From?</h2>

<p>It comes down to what following the spec driven development process has actually become. Now that I’m being militant about making AI follow a todo list, what I’ve functionally done is put on multiple hats:</p>

<p><strong>Product Manager hat:</strong> Created a complete game design doc. High-level, aspirational, covering combat systems, creatures, abilities, victory conditions — the whole vision thing.</p>

<p><strong>Delivery/Feature Lead hat:</strong> Took one section (the combat system) and broke it down into actual features. Not just “build combat” but “what does combat <em>need</em>? Movement? Attacks? Status effects? Death?” The unglamorous work of turning vibes into verbs.</p>

<p><strong>3 Amigos hat:</strong> Turned those features into a massive todo task list. Every checkbox a micro-commitment. “Add blink ability.” “Implement stun on hit.” “Make multiplying enemy spawn minions.” The kind of granular breakdown that makes you feel like you’re doing corporate sprint planning for your hobby project.</p>

<p><strong>Engineer hat:</strong> Actioning the tasks one at a time. No wandering off to make prettier models. No “oh but what if the islands had weather systems?” Just: checkbox, code, commit, next checkbox.</p>

<p><strong>QA hat:</strong> Testing behavior. Does the stun actually stun? Does the explosion destroy terrain properly? Do the spawned minions inherit the right stats? The tedious-but-essential validation loop.</p>

<p><strong>The realization:</strong> I’ve become …. an entire agile team.</p>

<p>And what that practically means is that I’ve made gamedev into <em>work</em>. My day job. God damn it.</p>

<p>Spent a lifetime developing habits on how to do engineering, and then you get a newfangled tool and you just… follow the process. Good job me. Yay! Right? …Right?!</p>

<h2 id="the-tangents-i-didnt-follow-and-why-that-hurts-a-little">The Tangents I Didn’t Follow (And Why That Hurts a Little)</h2>

<p>I’ll be honest: getting lost in tangents and running away with the vibes is a whole hell of a lot of fun.</p>

<p>In past weeks, I would have absolutely gone off on any of these:</p>

<p><strong>Visual polish:</strong> Using all the gorgeous tiles from Kenney’s asset packs to make everything look beautiful instead of just functional. Making each creature feel distinct and characterful instead of “placeholder cube with stats.”</p>

<p><strong>Procedural generation rabbit hole:</strong> Diving deeper into Wave Function Collapse algorithms to generate more dynamic, interesting terrain. Making islands that feel hand-crafted even though they’re algorithmic.</p>

<p><strong>Creature personality:</strong> Actually modeling unique designs for each bot. Giving them visual identity, animations, character beyond their mechanical function.</p>

<p><strong>Worldbuilding:</strong> Fleshing out the lore of the different factions. Their motivations, their aesthetics, their place in this weird sky-island world I’m building.</p>

<p>These are the <em>fun</em> parts. The parts where you lose track of time because you’re following curiosity instead of a checklist. The parts that make gamedev feel like <em>play</em> instead of <em>work</em>.</p>

<p>But here’s the thing: <strong>none of them get me closer to a playable game.</strong></p>

<p>They’re all polish on a foundation that doesn’t exist yet. They’re the dessert when I haven’t finished the vegetables. So the spec says: not now. Stay focused. Ship the MVP first.</p>

<p>It’s the right call. I know it’s the right call. Oh heavens please let this be the right call …</p>

<p>And I hate how boring the right call is.</p>

<h2 id="the-discipline-vs-fun-paradox">The Discipline vs. Fun Paradox</h2>

<p>Being strictly disciplined with myself about how to dev with this tool is <em>super productive</em>. Lots of forward momentum in an actual direction is really fantastic.</p>

<p>And also… boring.</p>

<p>There’s something deeply satisfying about seeing the commit graph fill up. About checking off todo items. About watching the line count grow in a structured, intentional way. It feels <em>professional</em>. It feels like I’m actually building something instead of just playing around.</p>

<p>But it’s missing that chaotic energy that made the early weeks of this project so intoxicating. The “what if I just try this wild thing?” moments. The tangents that turned into features I didn’t know I needed.</p>

<p>The spec process works. It’s just not romantic.</p>

<h2 id="where-im-headed">Where I’m Headed</h2>

<p>My plan is to stay disciplined until I hit what I’m calling an “exit point” — a milestone where the game is functioning <em>just enough</em> to validate the gameplay and experience. Right now, that means:</p>

<ul>
  <li><strong>2 unique decks</strong> that feel different to play</li>
  <li><strong>Basic strategy cards</strong> that offer meaningful choices</li>
  <li><strong>Fog of war</strong> (because exploration matters in a tactics game)</li>
  <li><strong>A simple victory condition</strong></li>
</ul>

<p>It won’t be <em>done</em>. But it will be <strong>playable</strong>. And <strong>testable</strong>. A real artifact I can put in front of someone and ask: “Is this fun?”</p>

<p>Following this process is giving me something I’ve never had before in side projects: <strong>predictable, consistent progress</strong>.</p>

<p>Not explosive bursts of inspiration followed by month-long abandonments. Not chasing vibes until I hit a wall and lose interest. Not 10,000-line notebooks that collapse under their own weight.</p>

<p>Actual, measurable forward motion toward a concrete goal.</p>

<p><img src="/assets/boring/chaos.png" alt="current" /></p>

<h2 id="the-bottom-line">The Bottom Line</h2>

<p>Is it boring? Yes.</p>

<p>Is it working? Also yes.</p>

<p>And maybe that’s the trade I need to make right now. There’s a time for tangents and vibes — I spent weeks in that mode and learned a ton. But there’s also a time to put your head down, follow the checklist, and <em>actually finish something</em>.</p>

<p>The irony isn’t lost on me: I spent four months learning how to use AI as a collaborator, only to discover that the real unlock was bringing back all the boring engineering discipline I use at my day job.</p>

<p>Turns out “vibe coding” still requires structure. Who knew?</p>

<p>Next week: More abilities. More discipline. More checkboxes. And hopefully, one step closer to knowing if this game is worth making at all.</p>

<hr />

<p><strong>P.S.</strong> If you’re following along with this devlog and thinking “wow, this sounds like he’s sucked all the joy out of his hobby” — yeah, a little bit. But also: I’m actually <em>building</em> something now instead of just dreaming about it. So maybe boring is the price of shipping.</p>

<p>We’ll see how I feel when I hit that exit point.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="vibecoding" /><summary type="html"><![CDATA[Or: How I Learned to Stop Vibing and Love the Spec”]]></summary></entry><entry><title type="html">AI Spec Driven Development</title><link href="https://www.petervanonselen.com/2025/10/30/exert-of-what-i-learnt/" rel="alternate" type="text/html" title="AI Spec Driven Development" /><published>2025-10-30T08:00:00+00:00</published><updated>2025-10-30T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/30/exert-of-what-i-learnt</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/30/exert-of-what-i-learnt/"><![CDATA[<p><em>A brief summary of what I have learnt</em></p>

<hr />

<p>This is an exert of <a href="https://www.petervanonselen.com/2025/10/20/what-i-have-learnt/">From AI Skeptic to Constant Collaborator: What I Learned Vibe Coding</a>.</p>

<h2 id="practical-workflows">Practical Workflows</h2>

<p>Through trial and error, I developed specific patterns to manage AI’s weaknesses:</p>

<p><strong>1. The Planning Folder Pattern</strong>
Keep numbered specs (1-initial-feature.md, 2-pay-by-discard.md, etc.) that document feature discussions. These become persistent context across sessions.</p>

<p><strong>2. The Todo Accountability System</strong>
Break specs into granular checkbox lists. Use them to hold the AI accountable during implementation.</p>

<p><strong>3. The Git Save-Scumming Strategy</strong>
Commit frequently. AI will overwrite working solutions without memory of what worked before.</p>

<p><strong>4. The Role-Based AI Selection</strong></p>
<ul>
  <li>ChatGPT: Brainstorming, exploration, asking “what’s wrong with this design?”</li>
  <li>Claude: Implementation, code review, pair programming</li>
  <li>Copilot/Codex: Ticket-style work where you hand off and come back later</li>
</ul>

<p><strong>5. The Discipline Override</strong>
Set hard rules to counter AI’s momentum:</p>
<ul>
  <li>Force refactor cycles</li>
  <li>Write tests even when AI makes it feel unnecessary</li>
  <li>Question every tangent: “Is this the MVP?”</li>
</ul>

<h2 id="minimum-viable-prompt-literacy">Minimum Viable Prompt Literacy</h2>

<p>I have no idea what a “perfect prompt” looks like. But I know one rule that consistently works:</p>

<p><strong>No matter what you ask the AI to make, the last sentence should be: “Ask me questions.”</strong></p>

<p>Get the AI to ask <em>you</em> questions. Ask it “what am I missing?” type questions. This back-and-forth is where the real value emerges, not in the first response, but in the dialogue.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="claudecode" /><category term="vibecoding" /><summary type="html"><![CDATA[A brief summary of what I have learnt]]></summary></entry><entry><title type="html">I Actually Stayed On Task (For Once): A Dev Miracle</title><link href="https://www.petervanonselen.com/2025/10/24/i-stayed-on-task/" rel="alternate" type="text/html" title="I Actually Stayed On Task (For Once): A Dev Miracle" /><published>2025-10-24T08:00:00+00:00</published><updated>2025-10-24T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/24/i-stayed-on-task</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/24/i-stayed-on-task/"><![CDATA[<p><em>Breaking news: Developer completes planned features … who would have thought?</em></p>

<hr />

<p>Remember all those high-minded ideas I had about <a href="https://www.petervanonselen.com/2025/10/20/what-i-have-learnt/">staying on task with AI-assisted development</a>? All that big game I’ve been talking about “this is how you do dev with an AI and keep it on task” and “this is the way you got to do it”?</p>

<p>Yeah, about that.</p>

<p>If you’ve been reading the wonderful adventures of the tangent king over here, I know what you’re thinking. He can’t do that.</p>

<p><strong>For context:</strong> I’m building Horizon’s Edge: a turn-based tactical wargame inspired by NetStorm where floating islands battle for control of the skies. I’ve been developing it with AI assistance in Godot, and staying focused has been… a journey. Previous highlights include: diving into Wave Function Collapse procedural generation instead of finishing game rules, and a grand refactor that ate five entire evenings because I accidentally committed the <code class="language-plaintext highlighter-rouge">.godot</code> cache folder.</p>

<p>Well, I will have you know… that this week I set out to get a bunch of combat systems up and running. Working tip top. No funny business with wave function algorithms or hexes or anything! And I managed, for the first time in almost 4 months, to stay on task and not meander (too much) and actually get some things <em>completed</em>.</p>

<p><img src="/assets/stay-on-target/mage.png" alt="mage!" /></p>

<p>I now have 3 creatures, each with at least 1 or more special abilities and those abilities actually work. I know! I am surprised too. I’m meandering my way through my todo list and this week I have a test mage with 5 abilities actually working:</p>

<ul>
  <li><strong>Blink</strong> - Teleportation ability</li>
  <li><strong>Ethereal Phase</strong> - Phasing ability</li>
  <li><strong>Arcane Missile</strong> - Ranged magic projectile</li>
  <li><strong>Divination</strong> - Detection/reveal ability</li>
  <li><strong>Mana Drain</strong> - Resource manipulation ability</li>
</ul>

<p>I might have wandered off and made one of the spells do terrain destruction too. Arcane Missile is the first ability in the game that actually destroys terrain rather than just building it. I just love the idea of the battlefield being dynamic and changing under the players’ feet. Right now it wipes out the hex the target was standing on, plus a 50% chance on each of the 6 surrounding hexes. The idea is that if a creature is no longer standing on anything, even if it has a lot of health, it will plummet to its death. It should create tension around expansion and positioning. Do you risk getting close for that attack if one wrong spell could drop you into the void?</p>

<p><img src="/assets/stay-on-target/destruction.png" alt="Island destruction" /></p>

<p>I also figured out how to get rounds and turns working together (this was needed for Ethereal Phase). And I might have spent some silly time hacking in a few animations to make the effects a bit more obvious when they happen.</p>

<p>Admittedly none of this is “let other people play with it” yet. And it doesn’t yet have a win condition. But it is meandering in a direction.</p>

<p>See? Like I told you. Todo list! Let’s see if I can do it again?</p>

<p><strong>Next up on the todo list:</strong> Three more creature archetypes, each with their own special abilities.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">test_voltage_bot</code> with Overcharge and Turbo Boost abilities.</li>
  <li><code class="language-plaintext highlighter-rouge">test_biomass_spawn</code> with Regenerate and Spawn Swarmlings.</li>
  <li><code class="language-plaintext highlighter-rouge">test_flux_walker</code> with Chaos Bolt and Lucky Strike.</li>
</ul>

<p>…assuming I don’t get distracted tweaking that wave function collapse algorithm again.</p>

<p><img src="/assets/stay-on-target/Distracted-Boyfriend.jpg" alt="tangent king" /></p>

<p><strong>Incidentally, the stats for the week:</strong></p>
<ul>
  <li>32 files changed</li>
  <li>3,029 additions</li>
  <li>508 deletions</li>
  <li>Net addition of ~2,500 lines of code</li>
</ul>

<p>For an hour and a bit each night, the progress here is just down right fierce!</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="board-game" /><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="codex" /><category term="vibecoding" /><summary type="html"><![CDATA[Breaking news: Developer completes planned features … who would have thought?]]></summary></entry><entry><title type="html">From AI Skeptic to Constant Collaborator: What I Learned Vibe Coding</title><link href="https://www.petervanonselen.com/2025/10/20/what-i-have-learnt/" rel="alternate" type="text/html" title="From AI Skeptic to Constant Collaborator: What I Learned Vibe Coding" /><published>2025-10-20T08:00:00+00:00</published><updated>2025-10-20T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/20/what-i-have-learnt</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/20/what-i-have-learnt/"><![CDATA[<p><em>The Question That Started Everything… am I going to lose my job?</em></p>

<hr />

<h2 id="the-question-that-started-everything">The Question That Started Everything</h2>

<p>How does one actually vibe code? And the follow-on questions that kept me up at night: Is it any good? Can I actually generate real code with this? Is this going to take my job? Am I running out of career runway?</p>

<p>Around the start of June this year, I was an AI optimist while not really engaging with it. I used ChatGPT, DeepSeek, and Anthropic’s Claude, ran some thinking through them, maybe did basic searches. Honestly, I wasn’t using it in any meaningful way. Functionally, I was just playing with it. Nothing more.</p>

<p>Then I got stuck on a problem. By simply following my curiosity, I went from not having a clear idea of what I wanted to accomplish with AI to actively using it as a constant collaborator across multiple domains of my life. My approach to AI has fundamentally changed over the past four months, and it continues to evolve.</p>

<h2 id="the-catalyst-magic-the-gathering-naturally">The Catalyst: Magic the Gathering (Naturally)</h2>

<p><strong>TLDR</strong>: I tried to make a <a href="https://www.petervanonselen.com/2025/08/04/jumpstart-cube-catastrophication/">Jumpstart cube</a>. ChatGPT couldn’t solve it. Co-pilot couldn’t solve it. Co-pilot vibe coded a solution that kinda worked. I vibe coded a new solution that actually worked.</p>

<p>I couldn’t get the damn thing out of my mind, so I vibe coded this <a href="https://github.com/vanonselenp/vanonselenp.github.io">portfolio site</a> to document what happened. Then, while working on the cube, a <a href="https://www.petervanonselen.com/2025/08/21/sky-islands/">board game idea struck</a>, and I couldn’t get it out any other way except by building it with AI. That board game has somehow <a href="https://www.petervanonselen.com/2025/09/07/boardgame-to-digital/">morphed into a video game</a> that’s far too complicated for the “get an MVP into prod fast” approach I keep trying to follow.</p>

<p><strong>The time investment</strong>: 1-2 hours a day, either in the morning before work or while watching TV with my wife in the evening. This became an all-consuming obsession for four months. I sacrificed learning urban sketching, which I’d spent the first half of the year actively pursuing.</p>

<p><strong>The cost</strong>: I’m paying £16/month for Claude Pro and £20/month for ChatGPT Pro. I use Claude as my primary coding assistant and switch between ChatGPT and Claude for thinking through problems. It’s worth it, without AI, none of these projects would exist.</p>

<p>Pre-AI, my side projects were timeboxed to a couple of days and small, achievable problems. Anything more would rapidly collapse under its own weight, too much code, too little time. Basically I didn’t do tech side projects. AI changed that equation entirely.</p>

<p><img src="/assets/github.png" alt="pre ai assisted tooling" /></p>

<h2 id="what-ive-learned-the-core-insights">What I’ve Learned: The Core Insights</h2>

<h3 id="ai-is-a-tool-and-a-multiplier">AI is a Tool and a Multiplier</h3>

<p>You have to treat AI not as a magic box that will automatically solve whatever you hope it does, but rather as another person you’re working with over Slack. If you tell a coworker “make me a feature!” you can’t be upset when they return junk.</p>

<p>The best way to use this tool is to assume it doesn’t actually know what you want. I’ve found the most effective approach is to start conversations with lots of negative validation questions: What am I missing? What could be improved? Be critical. Be objective. Get the AI to shoot holes through your ideas.</p>

<p>Once you’ve had this conversation, write that plan to file. Congrats, you now have a high-level plan. This becomes useful context for future chats. However, this alone won’t give you consistent, reasonable, progressive progress. Because basically, AIs like to write code, and they write an awful lot of it.</p>

<p>So get it to make a todo list with a painful amount of tick boxes.</p>

<p><img src="/assets/checklist.png" alt="checklists!" /></p>

<p>When building, use that todo document to hold the AI accountable. It makes testing and building more predictable and manageable.</p>

<h3 id="the-junior-engineer-mental-model-goes-deeper-than-you-think">The “Junior Engineer” Mental Model Goes Deeper Than You Think</h3>

<p>Treating AI like a junior engineer isn’t just about tone, it’s about workflow. Through my projects, I discovered I needed to:</p>

<ul>
  <li><strong>Use different AIs for different roles</strong>: ChatGPT for exploration and brainstorming, Claude for implementation and code review</li>
  <li><strong>Create specs as “shared memory”</strong>: Documentation that gets committed to the repo so the AI can reference it across sessions</li>
  <li><strong>Break work into granular todos</strong>: Not just for you, for holding the AI accountable to what actually matters</li>
  <li><strong>Pair with it through code review</strong>: Not just generation</li>
</ul>

<p>This evolved from my Magic cube project where I had specs numbered 1 through 15, each documenting a feature discussion. These weren’t outputs, they were context that survived beyond individual chat sessions.</p>

<h2 id="the-dangerous-patterns-what-they-dont-tell-you">The Dangerous Patterns: What They Don’t Tell You</h2>

<h3 id="the-refactor-paradox">The Refactor Paradox</h3>

<p>Here’s something crucial I learned the hard way: <strong>AI accelerates the “green” phase so much that you skip “refactor,” leading to massive technical debt.</strong></p>

<p>During my Magic cube project, I went from manually patching decks to having a 10,000-line IPython notebook that was completely impossible to understand. I had hit cognitive overload.</p>

<p>As an ardent TDD advocate in my day job, I realized I was missing two critical pieces of the red-green-refactor cycle: I was just writing code. No tests. No cleanups. Rookie mistake.</p>

<p>I had to start from scratch, consciously embracing a build-and-refactor loop, following the code smell patterns that years of clean code practices had drilled into me. AI doesn’t just multiply your output, <strong>it multiplies your technical debt if you’re not careful.</strong></p>

<p>The game dev project repeated this pattern. I’d run <code class="language-plaintext highlighter-rouge">git ls-files | grep '\.gd$' | xargs wc -l</code> and see files well over 2k lines. I’d missed refactor cycles again.</p>

<h3 id="the-tangent-amplification-problem">The Tangent Amplification Problem</h3>

<p>AI doesn’t just enable scope creep, <strong>it actively encourages it by making every side quest feel achievable.</strong></p>

<p>My board game project is the perfect example. I set out one week to work on creature combat. By the end of the week, I had:</p>
<ul>
  <li>Created test creatures</li>
  <li>Built movement and attack systems</li>
  <li>Added height-based defense</li>
  <li>Implemented dice roll combat</li>
  <li>Created a radial menu for unit actions</li>
  <li>Downloaded 3D models from Kenney.nl</li>
  <li>Rebuilt roads with proper models and rotations</li>
  <li>Added a blink ability</li>
</ul>

<p>One feature became an ecosystem. And here’s the thing: <strong>it is beyond exceedingly simple to wander off on completely unrelated tangents</strong> when the AI makes everything feel possible.</p>

<p>I kept telling myself “get an MVP to prod fast” while simultaneously building procedural island generation with Wave Function Collapse algorithms.</p>

<p>But here’s why I didn’t stop: <strong>AI provides so much momentum that even when it’s frustrating, you can think about the problem slightly differently and feel like you’re making progress.</strong> When direct AI generation hits a wall, I switch to having it build the broad structure while I manually tweak settings. This makes working on side projects genuinely fun in a way they haven’t been before.</p>

<p>The momentum AI provides is a double-edged sword. It keeps you engaged through the frustration, but it also keeps you building when you should be stepping back and asking “is this the right thing?”</p>

<h3 id="the-direction-problem-ais-spatial-blindness">The Direction Problem: AI’s Spatial Blindness</h3>

<p>Some tasks reveal AI’s sharp limitations. During my road system implementation, I discovered that <strong>AI spatial reasoning is terrible.</strong></p>

<p>When work involves orientation, rotation, or physical space, the AI’s sense of direction doesn’t match how the world is rendered. Trying to explain rotations in a way that makes sense to both of us is like teaching a goldfish to drive.</p>

<p>And if the AI ever accidentally gets something right, it will immediately overwrite it in the next change.</p>

<p>My eventual workflow:</p>
<ol>
  <li>Get the AI to build the big stuff, toggles, switches, base structure</li>
  <li>Manually go through and tweak everything myself</li>
</ol>

<p>This led me to develop what I call “Git <a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/SaveScumming">save-scumming</a>”, treating Git like a video game save system because AI will thoughtlessly overwrite correct solutions without remembering what worked.</p>

<h2 id="the-momentum-trap">The Momentum Trap</h2>

<p>AI gives me the same benefit I get from using Audible for reading books: <strong>momentum</strong>. It’s a lot easier to keep working on a side project with AI than without, especially when you have no time at all to do the work.</p>

<p>But here’s the tension my blog posts reveal: momentum without direction leads nowhere useful.</p>

<p>I built 24,000 lines of Python code for a board game that probably should have been paper prototyped first. I kept reminding myself to “get an MVP to prod fast and learn lessons,” but the AI made it so easy to keep building that I kept following the fun instead of following the plan.</p>

<p>The momentum is addictive even when it’s pulling you away from your goal. You have to be disciplined about direction, or you’ll end up with beautiful code for the wrong thing.</p>

<h2 id="the-transformation-four-months-everything-changed">The Transformation: Four Months, Everything Changed</h2>

<p>The most remarkable thing about this journey isn’t what I built, it’s the speed of transformation.</p>

<p><strong>June 2025</strong>: AI optimist, barely engaging
<strong>October 2025</strong>: 24k lines of game code, active collaborator across multiple projects, writing blog posts documenting the journey in real-time</p>

<p>Getting to the “treat AI like a junior engineer” mindset took about 2-3 weeks. I had to unlearn the “AI is magic” assumption and figure out how to actually use it.</p>

<p>This wasn’t gradual learning, it was catalytic. Each success made the next leap feel possible:</p>
<ul>
  <li>Magic cube problem → vibe coding solution</li>
  <li>Couldn’t stop thinking about it → portfolio site</li>
  <li>One blog post → entire blog series</li>
  <li>Board game idea → 24k lines of video game code</li>
  <li>Video game reimplementation → another 24k lines of video game code</li>
</ul>

<p>The cascading confidence is real. Once you see AI help you solve one “impossible” problem, you start seeing possibilities everywhere.</p>

<h2 id="bringing-it-back-to-the-day-job">Bringing It Back to the Day Job</h2>

<p>The spec-driven workflow I developed through these side projects has now become how I work professionally. I take tickets and reframe them into specs with task breakdowns. I use AI to analyze complex codebases I’m barely familiar with.</p>

<p>Right now I’m refactoring a monolith written in Go into a commons library with five microservices, using the AI spec-driven workflow with AI-assisted code development, working in small increments. Everything I’m doing, I learned from these side projects.</p>

<p>The irony: The Economist (where I work) has embraced AI tooling internally, while engineers in general remain reticent. I get it, I was there four months ago.</p>

<p>But here’s what changed for me: <strong>I still do traditional hand-crafted coding in my day job. I regularly work through code katas, which are fun and enjoyable in and of themselves.</strong> AI hasn’t replaced my coding skills, it’s multiplied what I can accomplish when I need to move fast or explore unfamiliar territory.</p>

<h2 id="practical-workflows-that-emerged">Practical Workflows That Emerged</h2>

<p>Through trial and error, I developed specific patterns to manage AI’s weaknesses:</p>

<p><strong>1. The Planning Folder Pattern</strong>
Keep numbered specs (1-initial-feature.md, 2-pay-by-discard.md, etc.) that document feature discussions. These become persistent context across sessions.</p>

<p><strong>2. The Todo Accountability System</strong>
Break specs into granular checkbox lists. Use them to hold the AI accountable during implementation.</p>

<p><strong>3. The Git Save-Scumming Strategy</strong>
Commit frequently. AI will overwrite working solutions without memory of what worked before.</p>

<p><strong>4. The Role-Based AI Selection</strong></p>
<ul>
  <li>ChatGPT: Brainstorming, exploration, asking “what’s wrong with this design?”</li>
  <li>Claude: Implementation, code review, pair programming</li>
  <li>Copilot/Codex: Ticket-style work where you hand off and come back later</li>
</ul>

<p><strong>5. The Discipline Override</strong>
Set hard rules to counter AI’s momentum:</p>
<ul>
  <li>Force refactor cycles</li>
  <li>Write tests even when AI makes it feel unnecessary</li>
  <li>Question every tangent: “Is this the MVP?”</li>
</ul>

<h2 id="what-about-the-code-quality">What About the Code Quality?</h2>

<p>Let’s be honest: the code AI generates can be good, can be overly verbose, tends toward duplication. But it can be nudged in the right direction quite easily.</p>

<p>The game currently works. It’s not feature complete, not even a pared-down, super-trimmed version. But it’s playable, testable, and iterating forward.</p>

<p>That’s the trade-off: you get speed and momentum in exchange for code that needs shepherding. You’re not writing every line, but you’re still responsible for the architecture, the patterns, and the quality.</p>

<h2 id="minimum-viable-prompt-literacy">Minimum Viable Prompt Literacy</h2>

<p>I have no idea what a “perfect prompt” looks like. But I know one rule that consistently works:</p>

<p><strong>No matter what you ask the AI to make, the last sentence should be: “Ask me questions.”</strong></p>

<p>Get the AI to ask <em>you</em> questions. Ask it “what am I missing?” type questions. This back-and-forth is where the real value emerges, not in the first response, but in the dialogue.</p>

<p>It took me 2-3 weeks to figure this out, but once I did, everything clicked.</p>

<h2 id="the-bottom-line">The Bottom Line</h2>

<p>AI hasn’t replaced my thinking, it’s changed how I work. The best analogy I’ve found: it’s like pairing with a junior engineer who:</p>
<ul>
  <li>Never gets tired</li>
  <li>Has read everything</li>
  <li>Has no memory between sessions</li>
  <li>Will confidently suggest terrible ideas alongside brilliant ones</li>
  <li>Makes everything feel achievable (which is both blessing and curse)</li>
</ul>

<p>You have to bring the discipline, direction, and judgment. The AI brings speed, exploration, and momentum.</p>

<p>After four months of solo exploration,watching YouTube videos, AI Engineer conference talks, and lots of trial and error,I’m not worried about my career ending. I’m worried about not learning these tools fast enough.</p>

<h2 id="why-this-matters-and-why-im-writing-this">Why This Matters (and Why I’m Writing This)</h2>

<p>I’m writing this for two audiences:</p>

<p><strong>Future me</strong>: So I can succinctly explain “this is what I learned” when the details fade.</p>

<p><strong>You</strong>: To give you an idea of how to approach AI development that’s more than the nebulous “what the hell do I do here” feeling I had in June.</p>

<p>This is an invitation. Not a tutorial, not a manifesto,an invitation to experiment, to treat side projects with these tools as “learn how to AI” projects, and to discover your own patterns through building.</p>

<p>Because here’s what I know now: the developers who learn to work effectively with AI aren’t going to replace the ones who don’t. They’re going to outpace them by an order of magnitude.</p>

<p>The question isn’t “will AI take my job?”</p>

<p>The question is: “Am I learning to multiply my effectiveness, or am I just playing with shiny tools?”</p>

<p>For me, the answer finally became clear somewhere between a Magic the Gathering cube and a procedurally generated sky island wargame.</p>

<p>I’m building the plane while flying it. And documenting the journey as I go.</p>

<p>Because maybe, just maybe, someone else is standing where I was in June, wondering “how does one actually vibe code?”</p>

<p>And maybe this helps them take the first step.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="board-game" /><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="codex" /><category term="vibecoding" /><summary type="html"><![CDATA[The Question That Started Everything… am I going to lose my job?]]></summary></entry><entry><title type="html">The Road to Combat Is Paved with Tangents: A Devlog</title><link href="https://www.petervanonselen.com/2025/10/17/road-to-combat-paved-with-blink/" rel="alternate" type="text/html" title="The Road to Combat Is Paved with Tangents: A Devlog" /><published>2025-10-17T08:00:00+00:00</published><updated>2025-10-17T08:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/17/road-to-combat-paved-with-blink</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/17/road-to-combat-paved-with-blink/"><![CDATA[<p><em>I set out to make a combat system. I returned with roads, models, and a blink ability…</em></p>

<hr />

<h1 id="tangents-roads-and-blinking-archers">Tangents, Roads, and Blinking Archers</h1>

<p>okay okay okay, so I <em>know</em> last time I was all:</p>

<blockquote>
  <p>“I am going to work on the combat system.”</p>
</blockquote>

<p>and I meant it. I really did.</p>

<p>I started the week’s development figuring out how to get a second creature working — this time one that could <em>shoot</em>! and it shot! with animation! and a lovely red number floating overhead when it hit.</p>

<p>Then I spent some time trying to convince the AI to make an archer… which came out as a cylinder and a torus mashed together like some long-lost relic from <em>Lord of the Rings</em>.</p>

<p><img src="/assets/road-to-combat/archer.png" alt="archer" /></p>

<p>Somewhere between the floating numbers and cursed geometry, I ran into a movement bug where the creature could only move <em>upwards</em> but never <em>downwards</em> — so, you know, just another normal day working on a game with a super-powered AI as a pair.</p>

<p>And that’s the problem with having a super-powered AI as a pair: it is <em>beyond</em> exceedingly simple to wander off on completely unrelated tangents. Which is, of course, what I did.</p>

<hr />

<h2 id="the-tangent-shiny-hexes-">The Tangent: Shiny Hexes ✨</h2>

<p>When I was working through a game dev course on <a href="https://www.udemy.com/course/jumpstart-to-2d-game-development-godot-4-for-beginners/">Jumpstart to 2D Game Development: Godot 4.4+ for Beginners</a> last year, I came across a really cool site: <a href="https://kenney.nl/">kenney.nl</a>.</p>

<p>They’ve got models, textures, and all sorts of game assets. And wouldn’t you know it, I found a bunch of hex models that perfectly matched the vibe in my head.</p>

<p>And just like that, all thoughts of combat systems and specs and rational planning <em>evaporated</em>.</p>

<p>No, now was <em>obviously</em> the perfect time to get models and textures in. So I immediately downloaded the GLB files and started plugging them into my wave function collapse algorithms.</p>

<p><img src="/assets/road-to-combat/current.png" alt="current" /></p>

<p>Instant vibe shift. The world suddenly <em>looked</em> like something. I’m not using all the models yet… but give me time 😄.</p>

<hr />

<h2 id="the-roads-to-madness-️">The Roads to Madness 🛣️</h2>

<p>With proper models in hand, I finally turned to something that’s been quietly tormenting me for weeks: roads.</p>

<p>Now that I had actual path models to work with, I thought this was going to be a cinch.</p>

<p>Nope. No. Oh hell no.</p>

<p>This is the kind of task that is <em>inherently infuriating</em> to get an AI to handle. Its sense of direction doesn’t match the way the world is rendered, and trying to explain rotations in a way that makes sense to both of us is like trying to teach a goldfish to drive.</p>

<p><img src="/assets/road-to-combat/roads.png" alt="roads roads roads" /></p>

<p>And if the AI ever <em>accidentally</em> gets something right, it will immediately overwrite it in the next change. Because of course it will.</p>

<p>My eventual workflow:</p>

<ul>
  <li>Get the AI to build the big stuff — toggles, switches, base structure.</li>
  <li>Then manually go through and tweak everything myself.</li>
</ul>

<p>Thank god for Git and my obsession with <a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/SaveScumming">save scumming</a> my way back to a sensible state.</p>

<hr />

<h2 id="meanwhile-combat-system-">Meanwhile… Combat System? 🫣</h2>

<p>Hang on though.
Wasn’t I working on a <em>combat system</em>?
Damn it.</p>

<p>Okay, where was I?</p>

<p>Ah yes — my ever-growing planning folder to the rescue.</p>

<p>I’ve developed a habit of getting the AI to output the result of any long feature discussion into a spec or planning file that gets committed into the repo.</p>

<p>Which is how I ended up with… about a dozen specs.</p>

<p>Some were implemented, some were “I realized this was a tangent and saved myself,” and some were very much still alive. After some reorganizing, I was down to a high level planning doc and a solid todo list that was a solid active plan.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜  horizons-edge git:(main) ✗ ls planning/6-
6-implementation-todo.md
6-test-deck-archetypes-energy-abilities.md
</code></pre></div></div>

<p>Then came the fun part: getting the AI to validate how accurate my current TODO list was against the plan — and then, obviously, not trusting it at all and just starting to build anyway 😄.</p>

<hr />

<h2 id="back-on-track-blink-">Back on Track: Blink ✨</h2>

<p>At last, <em>finally</em>, I was back on combat system track.
And the first order of business: give my test creature a <strong>blink ability</strong>.</p>

<p><img src="/assets/road-to-combat/radial.png" alt="blink ability!" /></p>

<p>Let’s see how far I get next week.</p>

<p>Until then, I hope you’re enjoying whatever tangent is currently distracting you from your side project. I salute you, fellow tangent adventurers. 🫡</p>

<hr />

<h2 id="-progress-summary-since-last-time">📝 Progress Summary Since last time.</h2>

<ul>
  <li>🚧 <strong>Road System:</strong> Added straight roads, corners, intersections, and 3–5-way connections. Complex rotation logic, road-to-hex connectivity.</li>
  <li>🧱 <strong>3D Asset Library:</strong> Integrated Kenney Hexagon Kit (180+ models, textures, documentation).</li>
  <li>🏹 <strong>Combat &amp; Abilities:</strong> Projectile system, Archer &amp; Scout cards, ability system improvements, radial menu, energy planning.</li>
  <li>🖱 <strong>Input &amp; UI:</strong> New input controller with hex highlighting, better radial menu, multiplayer safeguards, grid visualization.</li>
  <li>🧭 <strong>3D Model Integration:</strong> <code class="language-plaintext highlighter-rouge">hex_tile_model_config.gd</code>, updated rendering, road path visualization.</li>
  <li>🗂 <strong>Documentation:</strong> New spec for energy payment (spec 7), reorganized planning docs.</li>
</ul>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="board-game" /><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="codex" /><category term="vibecoding" /><summary type="html"><![CDATA[I set out to make a combat system. I returned with roads, models, and a blink ability…]]></summary></entry><entry><title type="html">Scope Creep Chronicles: Creature Combat Devlog</title><link href="https://www.petervanonselen.com/2025/10/10/scope-creep-chronicles/" rel="alternate" type="text/html" title="Scope Creep Chronicles: Creature Combat Devlog" /><published>2025-10-10T11:00:00+00:00</published><updated>2025-10-10T11:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/10/scope-creep-chronicles</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/10/scope-creep-chronicles/"><![CDATA[<p><em>Crouching Creature Combat, hidden tangents…</em></p>

<hr />

<p>Combat is a cornerstone of the game’s core loop — it’s a wargame after all. If the creatures can’t attack or move, nothing else really works. So it felt like the perfect place to focus on getting one thing working at a time.</p>

<p>You know that feeling when you promise yourself to build <em>just one simple feature</em>… and then accidentally end up building half a combat system?
Yeah. That happened.</p>

<p><img src="/assets/scope-creep/current.png" alt="current wip" /></p>

<p>I set out to make creature movement and attack work. Just that. And technically… I did.</p>

<p>But also…</p>

<hr />

<h2 id="so-what-happened-since-last-time">So What Happened Since Last Time?</h2>

<ul>
  <li>Created a <strong>test creature</strong></li>
  <li>Added <strong>stubs for abilities</strong> and creatures</li>
  <li>Can <strong>play the creature onto the world</strong></li>
  <li>Creature can <strong>move</strong></li>
  <li>Creature can <strong>attack</strong> (with a cheeky little “nudge” animation!)</li>
  <li>Creature is <strong>persistent</strong> in the world</li>
  <li>First version of a <strong>combat system</strong> is in place</li>
  <li>Height contributes to <strong>defence</strong></li>
  <li>Combat uses <strong>dice rolls</strong></li>
  <li>Added a <strong>UI element</strong> showing active units</li>
</ul>

<p>Somewhere between “just movement and attack” and the inevitable barrage of scope creep that is this list… I may have overshot my initial scope a tiny bit.</p>

<hr />

<h2 id="the-big-question-i-didnt-think-through">The Big Question I Didn’t Think Through</h2>

<p>When I first added creature cards, I realised something obvious but important:</p>

<blockquote>
  <p>“What happens to the card once the creature is played?”</p>
</blockquote>

<p>Does it:</p>

<ul>
  <li>🃏 Get discarded like a one-off spell?</li>
  <li>🏗️ Stay permanently on the battlefield, RTS-style?</li>
  <li>🧍 Act more like an ally in <a href="https://boardgamegeek.com/boardgame/285774/marvel-champions-the-card-game">Marvel Champions</a>?</li>
  <li>❄️ Or a unique character like in <a href="https://boardgamegeek.com/boardgame/268864/undaunted-normandy">Undaunted</a>?</li>
</ul>

<p>I wasn’t sure which direction would be more fun, so I had a long chat with the AI to explore the implications of each — and in classic not-thinking-it-through fashion, this has the feeling of being a dramatic question that might shift the whole damn game all over again. Hello scope creep, my old friend. I’m trying to keep you in check this time, I promise — setting clearer boundaries for what belongs in the MVP and what gets kicked down the road for future me to deal with.</p>

<p>The key takeaway:
I want players to <strong>get cards out fast</strong>, <strong>keep them on the board</strong>, and <strong>have those creatures feel unique</strong>. So the “remove from deck” idea (like Undaunted) felt too punishing. RTS swarm spam didn’t fit either.</p>

<p>The sweet spot seems to be something like <strong>Marvel Champions</strong>: unique characters with meaningful impact.</p>

<hr />

<h2 id="a-fun-rabbit-hole-rewarding-combat">A Fun Rabbit Hole: Rewarding Combat</h2>

<p>This led me to thinking: what happens when you <strong>win</strong> a combat?</p>

<p>That’s when <a href="https://store.steampowered.com/app/1025600/Battle_Realms_Zen_Edition/">Battle Realms</a> came to mind — an underrated, vibey-as-hell RTS from way back, with samurai, werewolves, vampires, and mystical Eastern weirdness. It used combat to <strong>generate resources for upgrades</strong>.</p>

<p>I love that idea. It adds stakes and momentum to battles without punishing players for losing units. And in yet another stunning moment of self-realisation, I promptly undid all my changes related to this feature — because it was scope creep of the highest order!</p>

<hr />

<h2 id="ui-tangents-and-side-quests">UI Tangents and Side Quests</h2>

<p>UI clarity is what really shapes how the game <em>feels</em> to play, so making it intuitive is critical. When the interface gets in the way, the whole experience slows down, so I’ve been extra sensitive about how these elements work.</p>

<p><img src="/assets/scope-creep/movement.png" alt="creature movement" /></p>

<p>Of course, I also got distracted by UI.</p>

<p>Playing a card and then having it <strong>disappear so you can see where to place it</strong> just makes sense. So I ended up tinkering with creature display windows and UX polish far beyond what I planned. I also found myself wrestling with the active unit display — trying (and failing repeatedly) to get Claude and Codex to understand exactly what I wanted changed. It turns out it’s surprisingly difficult to use plain English to precisely specify how a UI element should behave.</p>

<p>But I did get a shiny radial menu for unit actions out of it…</p>

<p><img src="/assets/scope-creep/radial.png" alt="radial" /></p>

<hr />

<h2 id="the-actual-goal-achieved">The Actual Goal? Achieved.</h2>

<p>At the end of the day, I really did achieve what I set out to do:</p>

<p>✅ <strong>Creature movement and attack</strong> — working (ish)
🌀 Plus a whole lot of unexpected side questing, because game dev is never a straight line.</p>

<hr />

<h2 id="next-steps">Next Steps</h2>

<p>Onward to the next rabbit hole.</p>

<p>This sprint was messy but productive — a reminder that even the tangents feed back into making the game feel more alive.</p>

<ul>
  <li>Refine creature persistence and combat flow</li>
  <li>Continue working through the massive creature card spec doc — I barely made it through the first two abilities, and I still want to explore resource generation and upgrades from combat wins</li>
  <li>Keep iterating without accidentally building a full-blown RTS 😅</li>
</ul>

<hr />

<p><strong>TL;DR:</strong>
I aimed for one thing. I built a small ecosystem. I’m proud, a little tired, and very excited about where this is going. And I’ve learned more about using AI tooling than I ever imagined.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="board-game" /><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="codex" /><category term="vibecoding" /><summary type="html"><![CDATA[Crouching Creature Combat, hidden tangents…]]></summary></entry><entry><title type="html">Cards, Chaos and the subtle art of Claude Code</title><link href="https://www.petervanonselen.com/2025/10/03/chaos-cards-and-claude-copy/" rel="alternate" type="text/html" title="Cards, Chaos and the subtle art of Claude Code" /><published>2025-10-03T11:00:00+00:00</published><updated>2025-10-03T11:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/10/03/chaos-cards-and-claude%20copy</id><content type="html" xml:base="https://www.petervanonselen.com/2025/10/03/chaos-cards-and-claude-copy/"><![CDATA[<p><em>Last Time on Madness Boulevard…</em></p>

<hr />

<p>Last time on the wonderful adventures of a random walk down the boulevard of madness in making a <del>board</del> video game, I was busy <a href="https://www.petervanonselen.com/2025/09/29/the-grand-refactor/">refactoring cards and trying to get them to actually work</a>.</p>

<p><img src="/assets/cards-chaos-claude/cards.png" alt="Cards Cards CARDS!" /></p>

<p>Now I have working CARDS! They discard! They look devy! They click! They discard! The UI is janky, but hey—it works. I’ve got… 3 cards. Three. OMG. Only 3 cards. :mindblown: This is going to be harder than I thought (obviously).</p>

<h2 id="factions-of-madness">Factions of Madness</h2>

<p>When I nudged Claude toward “cards instead of buttons” as a way to unify the gameplay, I immediately got ahead of myself. Naturally, I dreamed up two factions, a bit of lore, some shiny card concepts, and before I knew it… two half-baked 20-card decks <em>plus</em> a half-baked strategy deck. It was going to be over 9000!</p>

<p>The concepts were fun:</p>

<p><img src="/assets/cards-chaos-claude/nezumi.png" alt="Nezumi Swarm" /></p>

<p><strong>Nezumi Swarm:</strong> Honorable rat samurai + endless undead swarm tactics. Weak but unstoppable. Multiplying and spawning more and more. For the SWARM!</p>

<p><img src="/assets/cards-chaos-claude/aetheric.png" alt="Aetheric Empire" /></p>

<p><strong>Aetheric Empire:</strong> Victorian British Empire × Girl Genius mad science romance. Cyborgs, mechs, airship supremacy, love and madness.</p>

<p>The Romance. The Swarm. It was glorious.</p>

<h2 id="overload-incoming">Overload Incoming</h2>

<p>Then reality hit: instead of my usual TDD-style “one thing at a time, working confidently,” I was doing <em>everything, everywhere, all at once.</em> Unsurprisingly: overloaded. Cue the <a href="https://www.youtube.com/watch?v=sYOUFGfK4bU">“who’s on first, what’s on second, I don’t knows on third”</a> situation.</p>

<p>So, the <em>logical</em> next step was to pause the chaos and implement turn/round structure. Makes sense, right? …Except instead I doubled back to cards. Because of course I did.</p>

<h2 id="planning-docs-or-madness-in-writing">Planning Docs, or Madness in Writing</h2>

<p>Here’s the interesting part: working with Claude (and Codex) has led me to generate deep planning docs for features. I’ll spend hours iterating back and forth, treating them like living documents. Each doc builds context for the next, and since I’m writing them <em>inside</em> the codebase, they get deeply grounded in the actual work. It’s been a surprisingly useful feedback loop.</p>

<p>If you’re bored, you can peek at the <a href="/articles/horizons-edge/5-command-token-bag-system">planning doc for Turn and Round Structure</a>.  But spoiler: instead of building turns/rounds like a sane person, I realized maybe… just maybe… I should start small. Like, <em>test cards first.</em> Lego pieces before Royal Albert Hall.</p>

<p>Small steps. Right?</p>

<h2 id="next-steps">Next Steps</h2>

<p>So the plan now: get a test deck with basic cards sketched up and playable.</p>

<p><strong>Next steps: MORE CARDS!</strong></p>

<p>I’m focusing on functional requirements like:</p>

<ul>
  <li><strong>Complete archetype coverage:</strong> Territory, creatures, spells, interaction, combos</li>
  <li><strong>Energy-gated abilities:</strong> Powers tied to energy types</li>
  <li><strong>Ability framework:</strong> Up to 4 abilities per creature</li>
  <li><strong>Energy-scaling bonuses:</strong> Special effects if fueled by the right energy</li>
</ul>

<p>And covering these card types:</p>

<ul>
  <li>✅ Territorial Claim – Place core nodes</li>
  <li>✅ Terraforming Push – Expand island</li>
  <li>✅ Road Network – Connect islands</li>
  <li>✅ Build Generator – Energy production</li>
  <li>❌ Creatures with abilities</li>
  <li>❌ Combat mechanics</li>
  <li>❌ Opponent interaction</li>
  <li>❌ Energy-specific bonuses</li>
</ul>

<p>You’d think I’d take it easier this time, right? Nope. My card planning doc is 1,299 lines long. But this time, I’m getting Claude to implement <em>one card at a time.</em></p>

<p>Let’s see how that goes.</p>

<p>Will I actually build a turn structure next time? Or just make <em>even more cards</em>? Until then, may your rats be honorable and your airships only slightly on fire.</p>

<p>Also, if you are counting, I am now up to using Claude Code, Claude, Codex, ChatGPT and Gemini to do this project ….</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="board-game" /><category term="godot" /><category term="video-game" /><category term="claudecode" /><category term="codex" /><category term="vibecoding" /><summary type="html"><![CDATA[Last Time on Madness Boulevard…]]></summary></entry><entry><title type="html">When Refactors Eat Your Game (and Your Evenings)</title><link href="https://www.petervanonselen.com/2025/09/29/the-grand-refactor/" rel="alternate" type="text/html" title="When Refactors Eat Your Game (and Your Evenings)" /><published>2025-09-29T11:00:00+00:00</published><updated>2025-09-29T11:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/09/29/the-grand-refactor</id><content type="html" xml:base="https://www.petervanonselen.com/2025/09/29/the-grand-refactor/"><![CDATA[<p><em>From Buttons to Cards: A Sideways Journey</em></p>

<hr />

<h1 id="the-grand-refactor">The Grand Refactor!</h1>

<p><img src="/assets/grand-refactor/current.png" alt="current look" /></p>

<p><a href="https://www.petervanonselen.com/2025/09/07/boardgame-to-digital/">Last time we chatted</a> I was making excellent progress with the video game implementation of a board game I’m randomly working on. I had island placement, roads, chunking, waveform-collapse procedural generation. It was smoking. I was learning how to get Claude to code well. The way of the Force was strong.</p>

<p>And then I ran a little terminal command:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git ls-files | <span class="nb">grep</span> <span class="s1">'\.gd$'</span> | xargs <span class="nb">wc</span> <span class="nt">-l</span>
</code></pre></div></div>

<p>…and what I saw was a bunch of files well over 2k lines. Clearly I’d missed a refactor cycle (or three).</p>

<p>Meanwhile, I’d spun up a Claude sub-agent to do research on tech topics. Naturally, one of the first queries was: <em>“best practices for Godot.”</em></p>

<p>The results:</p>

<ul>
  <li>Use a signal-based architecture (which matched my half-remembered notes from a Godot course last year).</li>
  <li>Use singletons for global access and cross-cutting concerns like game managers and event buses.</li>
  <li>And, buried near the bottom as a tiny afterthought: <em>“Do not include the <code class="language-plaintext highlighter-rouge">.godot</code> directory in your repo.”</em></li>
</ul>

<p>Guess what I had in my repo.</p>

<p><img src="/assets/grand-refactor/betrayal.png" alt="the inevitable betrayl" /></p>

<p>I deleted the folder… and unleashed a week of refactor drama. Turns out the AI had written multiple cyclic dependencies that only “worked” because the cache made it look fine.</p>

<p>Cue the AI loop:</p>

<ul>
  <li><em>“To fix cyclic deps, remove types.”</em></li>
  <li><em>“No wait, add types.”</em></li>
  <li><em>“Think harder.”</em></li>
  <li><em>“Ultra-think.”</em></li>
</ul>

<p>This went on for hours until I forced a combo:</p>

<ul>
  <li>do ultrathink,</li>
  <li>do not remove types,</li>
  <li>change the dependency pattern,</li>
  <li>refactor large files into smaller files.</li>
</ul>

<p>That finally got things moving. Between Claude and Codex, the refactor slogged forward. But it cost me five evenings of work.</p>

<p>When the dust cleared, I… immediately rethought the UI.</p>

<p>Up to now, core gameplay actions (building islands, adding chunks, placing roads and buildings) were just buttons. Cards existed, but only for creatures and spells. Then I thought: <em>what if everything was a card?</em></p>

<p><img src="/assets/grand-refactor/wireframe.jpeg" alt="wrieframes" /></p>

<p>That would unify the control system: play a road, play an island, play a creature — all from cards. It lays the groundwork for an MVP, and it leans into what I love about games like <a href="https://boardgamegeek.com/boardgame/268864/undaunted-normandy">Undaunted</a> and <a href="https://boardgamegeek.com/boardgame/10630/memoir-44">Memoir ’44</a>, where your options each turn come from your hand.</p>

<p>So naturally, I dove straight into a UI refactor.</p>

<p>At least this time I started with wireframes in my sketchbook, thinking mobile-first. Right now the UI shows:</p>

<ul>
  <li>your resources,</li>
  <li>your current hand of cards,</li>
  <li>a test deck with only the working cards,</li>
  <li>and the ability to create islands by playing cards and paying with other cards.</li>
</ul>

<p>To call this “progress” would be… generous. It’s more of a profound sideways move. But that’s coding sometimes — discovery through chaos.</p>

<p>The one genuinely new thing I’ve started doing is <strong>feature planning with Claude</strong>. Basically it goes like:</p>

<ul>
  <li>I describe the feature</li>
  <li>Claude grills me with clarifying questions</li>
  <li>I save that Q&amp;A as documentation</li>
  <li>then Codex implements</li>
  <li>Claude reviews.</li>
</ul>

<p>Complete aside: I also started playing with OpenAI’s Codex to see what it’s like. Codex feels like an agent you hand a ticket to and then 30 minutes later it drops a PR on your desk. Claude, on the other hand, is more like a junior dev you pair with — lots of back-and-forth, explaining, nudging, but it stays with you in the problem.</p>

<p>This flow has meant:</p>

<ul>
  <li>less back-and-forth,</li>
  <li>better documentation,</li>
  <li>and an easier way to track what I’m actually building.</li>
</ul>

<p>Which is good, because this project has been the wildest, flux-crazed coding ride I’ve ever been on.</p>

<p><img src="/assets/grand-refactor/cards.png" alt="cards cards cards" /></p>

<hr />

<h2 id="whats-next">What’s next</h2>

<p>Honestly? No idea. Probably “make more cards actually work.” and “make them look more informative than tiny text you got to squint at to figure out what you are trying to do!”</p>

<p>Right now I’m wrestling the <strong>road network</strong> into the card system. The “play a card → build roads” flow keeps fighting me. It <em>works</em> as a button; it <em>sulks</em> as a card.</p>

<p>Near-term plan (aka cope notes):</p>

<ul>
  <li><strong>Make roads a first-class action.</strong> Card triggers a <code class="language-plaintext highlighter-rouge">BuildRoadNetwork</code> action with inputs (start, end, cost), not a kitchen-sink utility.</li>
  <li><strong>Signals over reach-ins.</strong> Card emits “build-road-requested”; the road system owns the how.</li>
  <li><strong>Pay-before-play.</strong> Validate cost and constraints first, then build; if it fails, no state touched.</li>
  <li><strong>Isolate the graph.</strong> Get road-graph ops (connectivity, loops, costs) tested in isolation so I’m not debugging UI + rules at once.</li>
  <li><strong>Tiny wins.</strong> One card → one road segment → then chains → then networks.</li>
</ul>

<p>If that behaves, I’ll circle back and keep converting the old button-y stuff into cards until the whole game flows from a hand. If it doesn’t… I will perform ritual sacrifices to the debug gods and try the other other thing.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="python" /><category term="board-game" /><category term="godot" /><category term="video-game" /><summary type="html"><![CDATA[From Buttons to Cards: A Sideways Journey]]></summary></entry><entry><title type="html">Building AI Before Building the Game: A Cautionary Tale</title><link href="https://www.petervanonselen.com/2025/09/07/building-ai-before-you-have-a-game/" rel="alternate" type="text/html" title="Building AI Before Building the Game: A Cautionary Tale" /><published>2025-09-07T11:00:00+00:00</published><updated>2025-09-07T11:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/09/07/building-ai-before-you-have-a-game</id><content type="html" xml:base="https://www.petervanonselen.com/2025/09/07/building-ai-before-you-have-a-game/"><![CDATA[<p><em>The curious case of Sky Islands and the Endless Roads leading nowhere ….</em></p>

<hr />

<h3 id="lost-in-the-sky-islands-my-first-attempt-at-ai-for-a-board-game">Lost in the Sky Islands: My First Attempt at AI for a Board Game</h3>

<p><img src="/assets/agentic_gone_wrong.png" alt="When Agentic programs go wrong" /></p>

<p>I’ve been on a mission to design a board game — <a href="https://www.petervanonselen.com/2025/08/21/sky-islands/"><em>Sky Islands</em></a> — and build a simulation of it in Pygame so I can playtest it digitally.</p>

<p>As a seasoned engineer with 14+ years of experience, you’d think I’d take a well-organized, disciplined approach to building my game: a clear Trello board, carefully prioritized tasks, and a smooth, methodical path from prototype to polish.</p>

<p>Except… no.</p>

<p>Instead, I’ve been wandering from random idea to random idea, in a meandering creative hike with zero map and no water bottle.</p>

<p>Lately, I’ve been closing in on a pretty complete rules implementation: combat is figured out, island control works, magic buffs and damage systems are in place, and the Pygame simulation is <em>almost</em> bug-free.</p>

<p>Which naturally meant it was the <strong>perfect time</strong> to… add AI.</p>

<hr />

<h3 id="enter-the-llm-ai-player">Enter the LLM AI Player</h3>

<p>Traditional game AI is this slow, careful, deeply technical craft. It takes months — sometimes years — to tune and polish.</p>

<p>So in my infinite wisdom, I skipped all that and said: <em>“Nah. Let’s just use an LLM as the AI.”</em></p>

<p>Better yet, let’s make it <strong>fully agentic</strong>. Surely if I give it a prompt and some game state data, it’ll play like a pro.</p>

<p>Here’s part of what I gave it:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You are an AI player in Sky Islands, a strategic card game. 
You control {self.faction_name} with {self.strategy_name} strategy.

Core principles:
- Maintain resource economy
- Protect your base
- Control valuable islands
- Use command points efficiently

Always respond in this exact format:
ACTION: [action_name]
TARGET: [target_if_needed]
REASONING: [brief explanation]

CRITICAL: Only use actions from the "AVAILABLE ACTIONS" section.
</code></pre></div></div>

<p>It seemed foolproof.
Even better, I didn’t have to pay for every token — I hooked the OpenAI API up to a local LLM and got free AI gameplay. Perfect, right?</p>

<hr />

<h3 id="the-dream-and-the-reality">The Dream… and the Reality</h3>

<p>The AI did <strong>exactly one thing well</strong>: write extremely <em>convincing</em> reasoning for its moves.</p>

<p>Like this:</p>

<blockquote>
  <p>“I’ll acquire the Roads island to improve connectivity and expand my territory, while also gaining a foothold on the board. Since it’s a low-cost island and cannot have generators built, it won’t disrupt my resource economy. This action will also give me more options for future expansion and defense.”</p>
</blockquote>

<p>Sounds smart, right? A master strategist!</p>

<p><img src="/assets/road_to_nowhere.png" alt="road to nowhere" /></p>

<p>Except in practice, it did this for 20 turns straight — acquiring road after road, until it had a glorious chain of roads leading absolutely nowhere.</p>

<p>My digital empire was basically a medieval fantasy version of the UK’s motorway network.</p>

<p>Turns out, <strong>getting AI to work right is hard</strong>. Who knew?</p>

<hr />

<h3 id="what-went-wrong">What Went Wrong</h3>

<p>I had made two big mistakes:</p>

<ol>
  <li>
    <p><strong>No actual game tools.</strong>
I was giving the AI text descriptions and asking it to pick actions, but it had no real way to <em>interact</em> with the game world. I should have built proper <a href="https://modelcontextprotocol.io/">MCP</a> tools so the AI could <em>act</em>, not just talk.</p>
  </li>
  <li>
    <p><strong>Building before understanding.</strong>
I jumped into AI development before I had a clear idea of what I was even making. It was scope creep disguised as “innovation.”</p>
  </li>
</ol>

<p>Basically, I was trying to build a self-driving car while still figuring out how to assemble a bicycle.</p>

<hr />

<h3 id="takeaways">Takeaways</h3>

<ol>
  <li>
    <p><strong>If you’re going agentic, build tools first.</strong>
Don’t just toss prompts at an LLM and hope for intelligence. Give it structured ways to interact with the game world.</p>
  </li>
  <li>
    <p><strong>Figure out what you’re building before adding AI.</strong>
AI shouldn’t be a replacement for clarity — it should come after you understand the game design itself.</p>
  </li>
</ol>

<p>For now, my AI dreams are on pause. Back to the basics: fixing my Pygame simulation and actually finishing the game rules.</p>

<p>Because the real Sky Islands challenge wasn’t the enemy factions, or the balance issues, or even the road spam.</p>

<p>It was me.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="python" /><category term="board-game" /><summary type="html"><![CDATA[The curious case of Sky Islands and the Endless Roads leading nowhere ….]]></summary></entry><entry><title type="html">I Just Wanted to Make a Board Game and Now There Are Procedural Islands</title><link href="https://www.petervanonselen.com/2025/09/07/boardgame-to-digital/" rel="alternate" type="text/html" title="I Just Wanted to Make a Board Game and Now There Are Procedural Islands" /><published>2025-09-07T11:00:00+00:00</published><updated>2025-09-07T11:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/09/07/boardgame-to-digital</id><content type="html" xml:base="https://www.petervanonselen.com/2025/09/07/boardgame-to-digital/"><![CDATA[<p><em>Why I Stopped Worrying and Learned to Love Chaos ….</em></p>

<hr />

<p>So… I’m supposed to be making a <strong>board game</strong>. At least, I think I am. Probably? Maybe?</p>

<p>What started as a simple idea about floating islands locked in war has slowly mutated into something far stranger.</p>

<hr />

<h3 id="where-we-left-off">Where We Left Off</h3>

<p>If you caught my last post, <a href="https://www.petervanonselen.com/2025/09/07/building-ai-before-you-have-a-game/">Building AI Before Building the Game: A Cautionary Tale</a>, you’ll know I’d been trying to simulate <em>Sky Islands</em> in Pygame. The goal was to playtest the rules, track combat and control, and maybe get some balance insights. Then I got ambitious and plugged an LLM in to act as an AI player.</p>

<p><img src="/assets/road_to_nowhere.png" alt="silly ai" /></p>

<p>That went… poorly. The AI spent twenty straight turns building roads that went nowhere, while writing deeply convincing justifications for every decision. It was like watching a medieval city planner gone mad. Funny? Absolutely. Useful? Not so much.</p>

<hr />

<h3 id="the-escalation-from-boring-to-beautiful-to-wild">The Escalation: From Boring to Beautiful to Wild</h3>

<p>After that fiasco, I stepped back and looked at my simulation. It worked, technically—but visually, it was about as inspiring as a spreadsheet. Dry. Functional. Boring.</p>

<p>I thought: <em>It just needs a little something …</em></p>

<p>So naturally I did the completely logical thing of iterating on the base concept, creating some physical components and playtesting the hell out of this… right? No.</p>

<p>Instead I:</p>

<ul>
  <li>Downloaded Godot.</li>
  <li>Built a basic isometric grid.</li>
  <li>Added hexes stacked on other hexes.</li>
  <li>Added colours and a cloud-like background.</li>
  <li>Added roads.</li>
</ul>

<p><img src="/assets/boardgame-to-digital/color2.png" alt="i might have a problem" /></p>

<p>And, then naturally, decided to throw in <a href="https://www.youtube.com/watch?v=zE1Jbh8b0BM"><strong>Wave Function Collapse</strong></a> for procedurally generated islands.</p>

<p>(Wave Function Collapse, for the unfamiliar: you feed an algorithm a set of tiles and rules for which tiles can sit next to which. It then generates new maps that look organic but still follow those constraints. Think Sudoku meets Minecraft.)</p>

<p><img src="/assets/boardgame-to-digital/waveform.png" alt="waveform collapsing the hell out of this" /></p>

<p>Each new step felt like a tiny, harmless addition—until I looked up and realized I was knee-deep in procedural generation instead of working on my board game.</p>

<hr />

<h3 id="the-identity-crisis">The Identity Crisis</h3>

<p>At this point, I had to stop and ask myself … what the hell am i doing?</p>

<ul>
  <li>Am I still making a <strong>board game</strong>?</li>
  <li>Or is this now a <strong>video game prototype</strong> masquerading as a board game?</li>
</ul>

<p>Because here’s where I stood:</p>

<ul>
  <li>A physical prototype with real pieces, great for fast iteration.</li>
  <li>A digital build with pretty visuals, dynamic maps, and increasingly complex systems.</li>
</ul>

<p>Two games. One idea. Total confusion.</p>

<hr />

<h3 id="what-im-learning-about-chaos">What I’m Learning About Chaos</h3>

<p>Yes, there’s a certain logic to focusing purely on a physical prototype first. But this is a side project meant to be fun, and I honestly have no idea where it’s heading. So instead of forcing order, I’m leaning into the fun and seeing where it takes me.</p>

<p>Right now, chaos is bubbling everywhere because I’m basically doing both at the same time—tinkering with a paper version and iterating on a digital one.</p>

<p>And that’s not entirely unprecedented. Building a paper version of a game before implementing it digitally is a time‑honored tradition. One of the best tactics games I’ve played in years (Mario + Rabbids Kingdom Battle) was built this way, and it worked beautifully.</p>

<p>Here’s what I’m starting to realize:</p>

<ul>
  <li>Building flashy visuals and complex systems is fun, but they’re <em>add-ons</em>, not the core of the game.</li>
  <li>Chaos is part of the creative process. The trick is knowing which parts to hold onto and which to let drift away.</li>
  <li>Having two prototypes isn’t inherently bad—as long as you know why each exists and what you’re testing with it.</li>
</ul>

<hr />

<h3 id="the-plan-for-now">The Plan (For Now)</h3>

<p>For now, I’m planning on following the fun—playing with procedural generation and trying to make this into a video game that can be played quickly.</p>

<p>And I might still be making a physical version because drawing is fun and making physical things is entertaining from time to time.</p>

<p>…yes, I know I just went, “I am going to do everything everywhere all at once…”</p>

<hr />

<h3 id="embracing-the-weirdness">Embracing the Weirdness</h3>

<p><img src="/assets/boardgame-to-digital/final.png" alt="where i am so far" /></p>

<p>Maybe this project was never going to stay neat and tidy. Maybe my creative process just looks like a cloud of floating hexes.</p>

<p>And maybe that’s okay.</p>

<p>So, here’s to embracing chaos, even when you’re not entirely sure what the hell you’re building.</p>

<iframe width="100%" height="315" src="https://www.youtube.com/embed/Xo7D7lnq_zQ?si=70eiCuDIwS0SaNHG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" style="max-width: 100%;"></iframe>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="python" /><category term="board-game" /><summary type="html"><![CDATA[Why I Stopped Worrying and Learned to Love Chaos ….]]></summary></entry><entry><title type="html">Islands at War: Designing a Board Game with AI</title><link href="https://www.petervanonselen.com/2025/08/21/sky-islands/" rel="alternate" type="text/html" title="Islands at War: Designing a Board Game with AI" /><published>2025-08-21T11:00:00+00:00</published><updated>2025-08-21T11:00:00+00:00</updated><id>https://www.petervanonselen.com/2025/08/21/sky-islands</id><content type="html" xml:base="https://www.petervanonselen.com/2025/08/21/sky-islands/"><![CDATA[<p>Or my on going adventures in playing with AI development tools …</p>

<hr />

<h3 id="inspiration-rediscovering-netstorm">Inspiration: Rediscovering NetStorm</h3>

<p>Sometimes the strangest of projects begin with a simple question: <strong>do you remember NetStorm?</strong></p>

<p><img src="/assets/netstorm.png" alt="Netstorm in action" /></p>

<p>For most people, the answer is no. <a href="https://www.netstormhq.net/">NetStorm</a> was a quirky real-time strategy game from the late 90s where players built chains of bridges to connect floating islands, deployed priests to capture enemy units, and unleashed elemental spells to control the battlefield. Matches were fast, tactical, and strange in a way that made it unforgettable, even if few played it at the time.;</p>

<p>But for me, it triggered an itch that just couldn’t be scratched. For the past year it’s been popping into my head like a song that gets stuck on repeat — especially the memory of floating islands, the roads stretching between them, and the chaos that ensued once those bridges connected. And since it’s impossible to play on modern tech without resorting to figuring out complicated emulation for a legacy Windows game on a modern Mac, I found myself wondering: what if I could capture that vibe from a board game instead?</p>

<p>It was a ridiculous idea in some ways, rooted in nostalgia for something obscure. But it stuck. And once the cube project was done, I found myself diving headfirst into a new design challenge. This time, though, I wasn’t working alone.</p>

<hr />

<h3 id="lessons-from-the-cube-project">Lessons from the Cube Project</h3>

<p>The <a href="https://www.petervanonselen.com/2025/08/04/jumpstart-cube-catastrophication/">Jumpstart cube project</a> had taught me something important: <strong>AI could be a collaborator, not just a tool.</strong></p>

<p>The breakthrough wasn’t about the right prompt or the cleverest model hack. It was about treating the AI like a <strong>junior engineer</strong> — someone who could help generate ideas, point out problems, and accelerate iteration, but who still needed guidance, context, and decisions.</p>

<p>I learned to:</p>

<ul>
  <li>Ask AI to critique ideas, not just produce them.</li>
  <li>Frame questions in terms of gaps, edge cases, and “what doesn’t make sense.”</li>
  <li>Use the back-and-forth to sharpen my own intent.</li>
</ul>

<p>That mindset became the foundation for the new board game project.</p>

<hr />

<h3 id="from-digital-to-tabletop-goals-and-challenges">From Digital to Tabletop: Goals and Challenges</h3>

<p>The initial vision that drove me was the feeling of <strong>islands floating in the sky at war</strong> — a mashup of inspirations:</p>

<ul>
  <li>Magic: The Gathering’s <strong>Jumpstart</strong> ease of deck building and fun with interesting themed decks,</li>
  <li>Marvel Champions’ <strong>card management</strong>,</li>
  <li>and Star Wars: The Deckbuilding Game’s <strong>capital ships</strong> — which at first felt like they could fit the vibe I was imagining, but in my version, those ships were islands.</li>
</ul>

<p>I started with a speculative chat that led to a rough design doc — high-level, but with enough of a skeleton to start iterating toward a solution. Then I followed it up with discussions about resource management, card flow, and how creatures might interact with the islands.</p>

<p>At each stage I translated these prompts ithrough Claude Code into a sprawling Python codebase, building rough but tangible systems so I could test how the mechanics meshed and influenced each other.</p>

<p>And then came the breakthrough …. or perhaps it was a bombshell. This was the small decision that went on to change every other single decision, as the consequences kept cascading out from it.</p>

<hr />

<h3 id="the-sky-island-moment">The Sky Island Moment</h3>

<p>The question that changed everything was deceptively simple: <strong>what exactly are the islands, thematically?</strong></p>

<p>Somewhere in that back-and-forth, the idea of <strong>sky islands</strong> emerged. The idea went from an abstract hand wave of “there is a thing” to grappling with how to tie them into gameplay — what does it mean to interact with them, and why does that even matter? Suddenly the game wasn’t just a dueling card game. It shifted into something closer to a <strong>dueling wargame</strong> — a clash of floating fortresses, each vying for control of the skies.</p>

<p>That one shift cascaded into every corner of the design:</p>

<ul>
  <li><strong>Creatures</strong> became more than just units — they had roles tied to the islands themselves.</li>
  <li><strong>Resources</strong> weren’t just mana, they were generated through interactions between creatures, cards, and island abilities.</li>
  <li>The <strong>turn structure</strong> morphed to resemble wargames like <strong>Bolt Action</strong> or even the action phases of <strong>Terraforming Mars</strong>.</li>
  <li>The definition of the <strong>“player” avatar</strong> in the game changed, along with how victory was determined.</li>
</ul>

<p>It was dramatic. The feel of the entire game had transformed. And it had all come out of a collaborative conversation with the AI.</p>

<hr />

<h3 id="how-collaboration-looked-in-practice">How Collaboration Looked in Practice</h3>

<p>One of the things I’ve been experimenting with is using <strong>different AIs for different roles</strong>. For this project:</p>

<ul>
  <li>I’d often workshop prompts and do deep exploratory discussions in <strong>ChatGPT</strong>, digging into mechanics and edge cases.</li>
  <li>Then I’d switch to <strong>Claude</strong> when it came time to pair on writing code or fleshing out structured text.</li>
</ul>

<p>I’ve been leaning into a spec‑driven design philosophy: writing in‑depth specification files that dive into each game system, then keeping them directly in the codebase alongside the code itself. This way they act as living documents the AI can reference when implementing features or validating correctness.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
~ ls ~/workspace/sky-islands/specs
1-initial-feature.md              14-streamline-resources.md        5-creatrure-combat.md
10-resource-management.md         15-streamline-upkeep.md           6-turn-structure.md
11-indepth-turn-structure.md      2-pay-by-discard.md               7-leader-homebase.md
12-upkeep-payment-supply-lines.md 3-sky-islands.md                  8-victory-conditions.md
13-deck-composition.md            4-ui.md                           9-hand-size-and-draw-mechanics.md
</code></pre></div></div>

<p>The rhythm became clear: spend more time up front in detailed conversation about a single feature or mechanic, then move to execution.</p>

<p>The most valuable questions I asked were:</p>

<ul>
  <li>
    <p><strong>Where are the gaps?</strong></p>
  </li>
  <li>
    <p><strong>What doesn’t make sense?</strong></p>
  </li>
  <li>
    <p><strong>What’s wrong with this design?</strong></p>
  </li>
</ul>

<p>Those questions made the AI less of an idea generator and more of a <strong>critical partner</strong>. And that’s when the collaboration felt most real.</p>

<hr />

<h3 id="where-i-am-now">Where I Am Now</h3>

<p>At this point, I have a <strong>partially refined board game</strong> with a comprehensive set of rules that cover deck design, map interaction and play, resources, hand management, combat, magic, and more. I also have a <strong>partially implemented working Pygame simulation</strong> of the board game. It’s still very much a developer interface and only kind of works, but it’s there. It’s already over 24k lines of Python code.</p>

<p><img src="/assets/skyisland2.png" alt="Sky islands in action!" /></p>

<p>What’s exciting is how the different systems impact each other in ways that feel earned and interesting — at least from my high-level thinking so far. I don’t yet have a fully functional version of the game, but the foundations are solid and interconnected. Every new rule or mechanic ripples through the system in a way that makes the design feel alive.</p>

<hr />

<h3 id="looking-back">Looking Back</h3>

<p>AI didn’t design this game. But it helped me test ideas faster, spot flaws earlier, and push through creative blocks.</p>

<p>What surprised me most wasn’t the cleverness of any single AI output. It was how much momentum I got from the <strong>dialogue itself</strong>. The interaction between my intent and the AI’s output was where the creativity lived.</p>

<p>I started this whole thing chasing a nostalgic itch for a half-forgotten 90s RTS. I ended up building the foundations of a brand new board game.</p>

<p>And I don’t think I would have got there without treating the AI as a collaborator.</p>]]></content><author><name>Peter van Onselen</name><email>augury_upsurge.17@icloud.com</email><uri>https://www.petervanonselen.com</uri></author><category term="personal" /><category term="python" /><category term="board-game" /><summary type="html"><![CDATA[Or my on going adventures in playing with AI development tools …]]></summary></entry></feed>