Nomic Coding Game April 5th, 2026
Patrick Stein

About 30 years ago, I had an idea for a coding game inspired by Nomic. It occurred to me last month that all of the tools I need are readily available now.

Pen-and-paper Nomic

The pen-and-paper game of Nomic (by Peter Suber) has an initial ruleset which describes how one proposes changes to the rules, how one gets those changes ratified, a way to award points when someone’s rule change is ratified, and a rule declaring that the winner is the first player to amass 100 points. Some of the rules are mutable and some are immutable and there are rules about turning mutable rules into immutable ones and vice-versa.

The game was meant to show some of the paradoxes of self-amendment. It was meant to lead people into situations where it was clear that certain actions were both legal (or even mandatory) and illegal.

A drastically simplified starting set of rules might look like:

  • There are these players: Alice, Bob, Carol, David, and Mel.
  • Any of the players can propose a change to these rules at any time when there is not already an outstanding proposal.
  • When a player makes a proposal, all players (including the player making the proposal) must immediately vote: Yay or Nay.
  • If a proposal garners more Yay than Nay votes, it takes effect immediately. Otherwise, the proposal is rejected.
  • The winner is the first person to score 100 points.

Nomic in Code

So, 30 years ago, I had the idea that it would be fabulous to write some code to referee a Nomic game. However, because interpretation of the rules is so horrendously human, it felt impossible. Today, in 2026, it seems one could maybe get Claude, Gemini, or some other LLM to referee. But, this doesn’t much interest me, either, really. I cannot get any of them to keep track of something that I made them write down. I cannot imagine that I would be happy with their interpretation of whether my move is legal given the current state of the rules nor to amend the rules appropriately if my move is legal.

What felt slightly more attainable 30 years ago would be to make it a battle in code:

  • The players propose deltas to the current code.
  • The players vote on which deltas to approve.
  • If the resulting code declares you the winner, you win.

This was nice and all, but it was also too static. The rules about who can vote and how votes are tallied and such wouldn’t be subject to change.

Nomic in Code in 2026

Fast-forward to last month. Last month, I realized that with the GitHub API interface, I could implement a very Nomic-ish pull request battle game. I can:

  • Gather information about all of the open pull requests on a repository,
  • Checkout a copy of the current main branch of that same repository,
  • Run the code on the main branch of that repository and give it the information that I collected about the open pull requests, and
  • Have the code on the main branch tell me which open pull requests (if any) to accept or reject.

To be truly in Nomic’s full spirit, it would be nice to allow the code in the repository to interact with the GitHub API on its own. Alas, that would immediately let the players vote in changes that expose my GitHub tokens, so it would be a gaping security hole—not only because it would let users impersonate me but because it would let them end-around the actual code in the repository to make changes to the main branch in the repository.

So, as it is, I have a supervisor written in Common Lisp which handles all of the interaction with GitHub and various game repositories (one to play in Common Lisp, one to play in JavaScript, and one to play in Python). The supervisor:

  • fetches all of the open pull requests;
  • annotates each pull request with:
    • all of the reviews on the pull request,
    • all of the comments on the pull request, and
    • all of the commits on the pull request;
  • clones the main branch of the game repository;
  • runs the game code from that main branch giving it the annotated list of open pull requests encoded as JSON on standard input;
  • reads the JSON-encoded output from the game code; and
  • acts accordingly.

The game code, given a list of open pull requests can reply with one of the following messages:

{
  "decision": "winner",
  "name": name-of-winner,
  "message": optional-reason-for-decision
}
{
  "decision": "accept",
  "id": id-number-of-pull-request-to-accept,
  "message": optional-reason-for-decision
}
{
  "decision": "reject",
  "id": id-number-of-pull-request-to-reject,
  "message": optional-reason-for-decision
}
{
  "decision": "defer"
}

The "defer" decision means that there is not enough information at the moment. Maybe, in the future, with other pull requests or other comments or reviews we will be able to make some move.

If the game code replies with anything that isn’t one of the four types of replies shown above, the supervisor assumes the latest merge broke the code and reverts the change.

The Ask

I haven’t been able to drum up enough players for a game in any of my regular haunts. So, I am looking for tolerant players who will help me give it a test run or two to work out the kinks in the supervisor. Some areas where I forsee potential issues:

  • There may be scenarios that cause the game to reach an impasse.
  • There are probably some GitHub responses that the supervisor doesn’t do the right thing with (in fact, I think I just thought of a situation that a malicious player could do if they are a collaborator rather than doing this through forked repos).
  • There might be special issues related to pull requests coming in from forks rather than within the repo which I cannot test without making myself a second GitHub account.
  • Who can say what the optimal number of players is, at this point?

So, if you’re tolerant of some bumps in the process, have a GitHub account (or will make one), and are interested in a Common Lisp battle of pull requests, let me know so we can get a game going.

HTML + JS + LISP. Oh My. March 20th, 2012
Patrick Stein

I started a Javascript + HTML application some time back. I decided that I wanted to get some Lisp on. So, it was time to pull out Hunchentoot, CL-WHO, and Parenscript.

It’s been awkward slogging so far. I still don’t have a good user-model of when exactly I need to wrap something in a (cl-who:str ...) or when Parenscript will expand my macro rather than convert it into a function call or how I managed to get the cl-who:*attribute-quote-char* to finally stick for a few REPLs.

The other half of the awkwardness is that I started writing the application in idiomatic javascript with prototype-based objects.

function MyClass () {
  this.myfirst = undefined;
  this.myarray = [ ];
}

MyClass.prototype.mymethod = function (arg1, arg2) {
  this.myfirst = arg1;
  this.myarray.push(arg2);
};

This makes for some awkward javascript when converted directly into Parenscript because:

  • The method mymethod() will try to return the result of Array.push() (which, technically, is fine, but not really the intent of the method).
  • Almost every statement on the Lisp side ends up wrapping just about everything in (parenscript:chain ...). (Edit: Of course, I discovered right after posting this that the dot is left untouched in the Parenscript symbol conversion, so I can do (this.myarray.push arg2) instead of (parenscript:chain this my array (push arg2)). I’m certainly pleased with the brevity, but it pegs my something’s fishy here, Batman meter.)
  • I have an aversion to using any package other than COMMON-LISP, so everything is way clunkier than all of the tutorials and examples online.

I think that I’m going to scratch all of the Javascript and Parenscript code that I have right now and start over with a mindset of How would I do this if it were just in Lisp? Now, what extra hoops do I need to get Parenscript to make usable Javascript? rather than How would I do this in Javascript? Oh, and then, how can I make Parenscript say exactly that? And, I may bite the bullet and (use-package ...) both CL-WHO and Parenscript.

Blur and Edge Detect your Fourier Transforms September 21st, 2009
Patrick Stein

I have now added convolutions to my FFT Paint application. Here, I started with the following image (again, magnitude on the left and phase on the right):

conv_orig_m  conv_orig_p

From there, I took the Fourier Transform:

conv_pre_m  conv_pre_p

Then, I did a horizontal Sobel operator on it to get this:

conv_post_m  conv_post_p

From there, I did the Inverse Fourier Transform to obtain this:

conv_final_m  conv_final_p

Enjoy!

Simple Function Plotting in Javascript September 15th, 2009
Patrick Stein

graphRather than work more on my FFT Paint program yesterday, I took a break to make a simple function plotter. There are lots of useful Java applets out there that do more than what I’ve done here. And, certainly, gnuplot is much more complete and useful.

On the other hand, if you just want to quickly plot something that you can save as an image, you either have to re-learn gnuplot (every time I use it, I have to sift through the help to figure out how to set up my tics and labels and output size and output filename) or you have to do screen grabs from one of the Java applets.

With the plotter that I wrote yesterday, you click on the Snapshot button, then right-click to save the image or copy it to your clipboard.

Enjoy.

Better Examples of Fourier Transform Painting September 10th, 2009
Patrick Stein

I have now added symmetry options to my Fourier Transform painting application. As PC pointed out in a comment to my previous post, examples with higher frequency information are more interesting. Here are some images of the background tile of this website. The magnitude is on the left and the phase is on the right. You can click them for the full-sized images.

This is the original:

squares_m  squares_p

This is the Fourier transform of the original:

squares_mf  squares_pf

This is my edited version of that transform. I wiped out lots of the off-axis frequencies. I tinted the center red. And, I added some green blotches along the diagonals.

squares_mfe  squares_pfe

And, here is the inverse transform of my edited data.

squares_mfei  squares_pfei

l