<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Jim Wright</title>
		<link>https://jmwri.dev/</link>
		<description>Recent content on Jim Wright</description>
		<generator>Hugo</generator>
		<language>en-GB</language>
		
		
		
		
			<lastBuildDate>Mon, 07 Sep 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://jmwri.dev/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Snake with NEAT: benchmarking changes to an evolutionary algorithm</title>
				<link>https://jmwri.dev/posts/snake-neat-measuring/</link>
				<pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-neat-measuring/</guid>
				<description>&lt;p&gt;Every number in &lt;a href=&#34;https://jmwri.dev/posts/snake-neat-intro/&#34;&gt;the last five posts&lt;/a&gt; is a comparison, and comparisons on an evolutionary algorithm are much harder than they look. This post is about the experimental setup, which took me longer to get right than any of the code it was measuring.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake with NEAT: a hunger input to break stalemates</title>
				<link>https://jmwri.dev/posts/snake-neat-hunger/</link>
				<pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-neat-hunger/</guid>
				<description>&lt;p&gt;I had a network that scored 94.5 of 99 after thirty-five thousand generations, and it had stopped improving. More generations, bigger populations, more games per genome - nothing.&lt;/p&gt;&#xA;&lt;p&gt;So I stopped trying to make it better and went to find out what it was actually losing to.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake with NEAT: training runs and checkpoints</title>
				<link>https://jmwri.dev/posts/snake-neat-training/</link>
				<pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-neat-training/</guid>
				<description>&lt;p&gt;The network is &lt;a href=&#34;https://jmwri.dev/posts/snake-neat-senses/&#34;&gt;shown eighteen numbers&lt;/a&gt; and &lt;a href=&#34;https://jmwri.dev/posts/snake-neat-fitness/&#34;&gt;paid for eating&lt;/a&gt;. What is left is running the thing: how many networks, for how long, on what boards, and - the part I got wrong first - which one you keep at the end.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake with NEAT: designing the fitness function</title>
				<link>https://jmwri.dev/posts/snake-neat-fitness/</link>
				<pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-neat-fitness/</guid>
				<description>&lt;p&gt;Evolution keeps whatever scores highest, so the fitness function is not a scoring rule - it is the entire specification of the problem. Anything you leave out, you are asking for.&lt;/p&gt;&#xA;&lt;p&gt;Snake looks like it should be one line: fitness is the score. It is not, and the reasons are more interesting than the fix.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake with NEAT: designing the network&#39;s inputs</title>
				<link>https://jmwri.dev/posts/snake-neat-senses/</link>
				<pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-neat-senses/</guid>
				<description>&lt;p&gt;The board is a hundred tiles and a network takes a fixed number of floats, so something has to decide what to throw away. That decision is called the encoding, and on this problem it mattered more than anything I did to the algorithm.&lt;/p&gt;&#xA;&lt;p&gt;Eighteen numbers go in each move.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: evolving a neural network with NEAT</title>
				<link>https://jmwri.dev/posts/snake-neat-intro/</link>
				<pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-neat-intro/</guid>
				<description>&lt;p&gt;Every player so far is my idea of how to play snake, written down. The greedy one is &amp;ldquo;go towards the fruit&amp;rdquo;. The safe one is &amp;ldquo;keep your tail in sight&amp;rdquo;. They are as good as the rule I thought of.&lt;/p&gt;&#xA;&lt;p&gt;The last player in this series was given no rule at all. It is a small neural network, and its weights and its shape were arrived at by evolution: a population of near-empty networks, the ones that happen to play better kept and mutated, over and over.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: building a Hamiltonian cycle with search</title>
				<link>https://jmwri.dev/posts/snake-hamiltonian/</link>
				<pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-hamiltonian/</guid>
				<description>&lt;p&gt;The &lt;a href=&#34;https://jmwri.dev/posts/snake-zigzag/&#34;&gt;zig-zag tour&lt;/a&gt; is laid out by hand, which works because a rectangle is easy to walk. The other way to get a tour is to search for one on the board in front of you.&lt;/p&gt;&#xA;&lt;p&gt;This player is the most fragile thing in the series and the most instructive, because almost all of its score comes from two decisions that have nothing to do with the search.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: safe shortcuts along the tour</title>
				<link>https://jmwri.dev/posts/snake-shortcut/</link>
				<pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-shortcut/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://jmwri.dev/posts/snake-zigzag/&#34;&gt;The zig-zag tour&lt;/a&gt; wins every game and takes twenty-five moves per fruit doing it, because it walks past ninety-nine tiles it does not want to reach the one it does.&lt;/p&gt;&#xA;&lt;p&gt;Most of that is waste you can prove is waste. The snake is one tile long for the first fruit and the whole tour is empty behind it; there is no reason to walk all of it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: a fixed Hamiltonian tour</title>
				<link>https://jmwri.dev/posts/snake-zigzag/</link>
				<pubDate>Sun, 30 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-zigzag/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://jmwri.dev/posts/snake-safe/&#34;&gt;The safe player&lt;/a&gt; never dies but stalls in nearly every game, because working move by move it eventually cannot prove any route to the fruit is survivable.&lt;/p&gt;&#xA;&lt;p&gt;There is a way to win every single game, and it has been sitting there the whole time. Stop deciding, and follow a fixed route that covers every tile on the board.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: a tail-reachability safety check</title>
				<link>https://jmwri.dev/posts/snake-safe/</link>
				<pubDate>Sat, 29 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-safe/</guid>
				<description>&lt;p&gt;Everything so far dies. The search players die at about 28 of 99, and they die because a shortest route and a survivable route are different things.&lt;/p&gt;&#xA;&lt;p&gt;This one does not die. Not once in two thousand games, and it scores 90.8.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: stretching the longest path</title>
				<link>https://jmwri.dev/posts/snake-longest-path/</link>
				<pubDate>Fri, 28 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-longest-path/</guid>
				<description>&lt;p&gt;The two search players die because a short route leaves the snake coiled up next to itself. The obvious opposite idea is to take the &lt;em&gt;longest&lt;/em&gt; route you can, so that by the time you arrive the tail has had time to get out of the way.&lt;/p&gt;&#xA;&lt;p&gt;It scores worse than walking straight at the fruit. It is also the single most useful piece of machinery in this series, because it is how you grow a route into a tour of the whole board.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: A* search instead of BFS</title>
				<link>https://jmwri.dev/posts/snake-astar/</link>
				<pubDate>Thu, 27 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-astar/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://jmwri.dev/posts/snake-shortest-path/&#34;&gt;Breadth first search&lt;/a&gt; expands in rings, so by the time it reaches a fruit four tiles away it has also visited everything four tiles in the opposite direction. A* keeps the same guarantee and skips most of that.&lt;/p&gt;&#xA;&lt;p&gt;This post is not really about playing snake - the two players score the same - it is about the search.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: shortest path with breadth-first search</title>
				<link>https://jmwri.dev/posts/snake-shortest-path/</link>
				<pubDate>Wed, 26 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-shortest-path/</guid>
				<description>&lt;p&gt;The &lt;a href=&#34;https://jmwri.dev/posts/snake-greedy/&#34;&gt;greedy player&lt;/a&gt; measures the distance to the fruit in a straight line, which stops being true the moment there is a snake in the way. The fix is to stop guessing and search for a real route through the board as it actually is.&lt;/p&gt;&#xA;&lt;p&gt;This is the first player with a search in it, and the first one to share machinery with the rest of the series.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: a greedy player</title>
				<link>https://jmwri.dev/posts/snake-greedy/</link>
				<pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-greedy/</guid>
				<description>&lt;p&gt;The &lt;a href=&#34;https://jmwri.dev/posts/snake-random/&#34;&gt;random player&lt;/a&gt; scores six because it does not know where the fruit is. The obvious fix is to tell it: of the moves that do not kill me this tick, take the one that ends up nearest the fruit.&lt;/p&gt;&#xA;&lt;p&gt;That is the whole of the greedy player. There is no search and no lookahead, and it is worth three and a half times as much as random.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Snake in Go: a random-move baseline</title>
				<link>https://jmwri.dev/posts/snake-random/</link>
				<pubDate>Mon, 24 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-random/</guid>
				<description>&lt;p&gt;The first player I wrote does not know where the fruit is. It looks one tile ahead, throws away the moves that would kill it this tick, and picks from whatever is left at random.&lt;/p&gt;&#xA;&lt;p&gt;That sounds like a waste of a post, but it is the number every other player is measured against, and it turns out to be worth understanding &lt;em&gt;why&lt;/em&gt; it scores what it does.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Eleven ways to play snake in Go, from random to NEAT</title>
				<link>https://jmwri.dev/posts/snake-ai-intro/</link>
				<pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/snake-ai-intro/</guid>
				<description>&lt;p&gt;I wanted a problem small enough to hold in my head and awkward enough to stay interesting. Snake is that. The rules fit in a sentence, and playing it well turns out to be a problem about not building a wall out of yourself.&lt;/p&gt;&#xA;&lt;p&gt;So I wrote a snake, and then I wrote eleven different ways of playing it. This series is one post per player, starting with the one that moves at random and ending on a neural network that was evolved rather than written.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: the evolution loop and reproducible runs</title>
				<link>https://jmwri.dev/posts/neatgo-running/</link>
				<pubDate>Sat, 22 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-running/</guid>
				<description>&lt;p&gt;Every piece is built. This is the loop around them, the parallelism, and the thing that mattered more than any of it: making a stochastic algorithm repeat exactly.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: deterministic parallel reproduction with goroutines</title>
				<link>https://jmwri.dev/posts/neatgo-reproduction/</link>
				<pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-reproduction/</guid>
				<description>&lt;p&gt;Every species knows how many offspring it is owed. This is the part that produces them - which is where the expensive work is, and where the temptation to parallelise it runs straight into the requirement that a seeded run be reproducible.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: fitness sharing and culling</title>
				<link>https://jmwri.dev/posts/neatgo-selection/</link>
				<pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-selection/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://jmwri.dev/posts/neatgo-speciation/&#34;&gt;Species&lt;/a&gt; exist so that a genome competes mainly against genomes like itself. This is the part that cashes that in: deciding how many offspring each species gets, which members are allowed to produce them, and which species do not get to continue at all.&lt;/p&gt;&#xA;&lt;p&gt;It is five short functions and I got three of them subtly wrong first.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: speciation with compatibility distance</title>
				<link>https://jmwri.dev/posts/neatgo-speciation/</link>
				<pubDate>Sun, 16 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-speciation/</guid>
				<description>&lt;p&gt;A genome that has just grown a new node is worse than it was. It has an untuned bias, two untuned weights and no idea what the node is for, and in a straight fight with the rest of the population it loses and is gone.&lt;/p&gt;&#xA;&lt;p&gt;Speciation is the answer: genomes compete mainly against genomes like themselves, so new structure gets a few generations to prove itself.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: crossover aligned by innovation ID</title>
				<link>https://jmwri.dev/posts/neatgo-crossover/</link>
				<pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-crossover/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://jmwri.dev/posts/neatgo-innovation/&#34;&gt;Historical markings&lt;/a&gt; exist so that this post is short. Once both parents&amp;rsquo; genes carry stable IDs, combining them is bookkeeping.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: add-node and add-connection mutations</title>
				<link>https://jmwri.dev/posts/neatgo-mutation-structure/</link>
				<pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-mutation-structure/</guid>
				<description>&lt;p&gt;This is the half of mutation that NEAT is named after: the part that grows the topology. Four mutations, all of them rare.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Breeder&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;mutateStructure&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Genome&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Genome&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;mutateAddNode&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;mutateDeleteNode&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;mutateAddConnection&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;mutateDeleteConnection&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: mutating weights and other parameters</title>
				<link>https://jmwri.dev/posts/neatgo-mutation-parameters/</link>
				<pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-mutation-parameters/</guid>
				<description>&lt;p&gt;Mutation comes in two halves, and they are kept apart deliberately.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Breeder&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;mutateGenome&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Genome&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Genome&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;mutateStructure&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;mutateParameters&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;genome&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This post is the first half: the mutations that change existing genes without adding or removing any.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: innovation IDs and historical markings</title>
				<link>https://jmwri.dev/posts/neatgo-innovation/</link>
				<pubDate>Sat, 08 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-innovation/</guid>
				<description>&lt;p&gt;If you take one idea away from NEAT, take this one. It is a page of code and it is what makes everything else possible.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: the genome, starting minimal</title>
				<link>https://jmwri.dev/posts/neatgo-genome/</link>
				<pubDate>Thu, 06 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-genome/</guid>
				<description>&lt;p&gt;A genome is a description of a network that has not been built yet. It is what mutation edits, what crossover combines, and what gets written to disk when a run finds something worth keeping.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: compiling a network into a flat loop</title>
				<link>https://jmwri.dev/posts/neatgo-network/</link>
				<pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-network/</guid>
				<description>&lt;p&gt;Before there is anything to evolve there has to be something to run. The &lt;code&gt;network&lt;/code&gt; package takes a list of nodes and a list of connections and turns them into something that activates fast, and it knows nothing at all about evolution.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: seeded randomness and generic helpers</title>
				<link>https://jmwri.dev/posts/neatgo-util/</link>
				<pubDate>Mon, 03 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-util/</guid>
				<description>&lt;p&gt;Before any of the algorithm, a handful of helpers for drawing random numbers and poking at slices. They are eight short functions and it would be fair to skip them - except that two of them encode decisions that everything else in the series depends on.&lt;/p&gt;</description>
			</item>
			<item>
				<title>NEAT in Go: neuroevolution, built a piece at a time</title>
				<link>https://jmwri.dev/posts/neatgo-intro/</link>
				<pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/neatgo-intro/</guid>
				<description>&lt;p&gt;Most neural network training holds the shape of the network fixed and moves the weights. NEAT moves both. A run starts from the smallest network that could possibly answer the question - every input wired straight to every output, nothing in between - and grows hidden nodes and connections one at a time, keeping whatever happens to help.&lt;/p&gt;&#xA;&lt;p&gt;I have wanted to build one properly for years. This series is that: &lt;a href=&#34;https://github.com/jmwri/neatgo&#34;&gt;neatgo&lt;/a&gt;, a piece at a time.&lt;/p&gt;</description>
			</item>
			<item>
				<title>What is `this` in JavaScript? The binding rules explained</title>
				<link>https://jmwri.dev/posts/what-is-this/</link>
				<pubDate>Thu, 16 Mar 2017 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/posts/what-is-this/</guid>
				<description>&lt;p&gt;Working on Nodejs at work recently made me remember how confusing javascript can be. There are a lot of quirks that make it a powerful language, but for developers coming from a more strict OOP background they can seem broken. In this post I&amp;rsquo;m going to talk about &lt;code&gt;this&lt;/code&gt; in javascript.&lt;/p&gt;</description>
			</item>
			<item>
				<title>About me</title>
				<link>https://jmwri.dev/about/</link>
				<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
				<guid>https://jmwri.dev/about/</guid>
				<description>&lt;p&gt;I&amp;rsquo;m a senior/staff software engineer with a decade of experience building and operating the&#xA;infrastructure behind large-scale, real-time systems. I&amp;rsquo;ve led cloud migrations and platform teams at&#xA;Cisco ThousandEyes and SamKnows, and I independently design and ship complete products end to end,&#xA;from backend architecture through billing and release engineering.&lt;/p&gt;&#xA;&lt;p&gt;I started out making games in Flash and writing an IRC client to earn a Trials2 achievement, went on to&#xA;study Computing (BSc, 2:1) at Canterbury Christ Church University, and have worked across the stack ever since.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
