NOMIC.py — Non-Ontic Methodology for Improvisational Constitutions In Python
Introducing NOMIC.py, a basic self-executing computational implementation of the game of self-amendment in the python programming language
In the last article in this series, I introduced the game of Nomic and chronicled my first major attempt at playing it. That game, which survived only seven turns1, was in retrospect, ended by a natural pattern of gameplay: in order to outmanoeuvre their opponents, players would take advantage of increasingly insignificant amgibuities or loose language in the rules, leading to an exponential escalation of the players’ expectations of gameplay rigour. The game was simply never allowed to continue long enough to catch up with this expectation, grinding to a halt as we eventually became unable to resolve any judgment. In this article, I will present my not-in-the-slightest-bit-overkill solution to this problem (which also completely sidesteps the need for Judges): a complete implementation of a Nomic in Python. I present to you, NOMIC.py
Basic Scheme
The basic system of gameplay I envisioned was the following. There exists a single nomic.py (or perhaps a game.py from which the nomic is imported) containing some initial setup code (the structures for turns and creating rules), and a player’s turn consists of adding a few lines of code to the file, which can then be executed to evaluate the gamestate. There are three constructs to be aware of: gamestate, the action and the hooks, detailed in the next sections.
Of course, making everything run law-as-code style still does not solve the problems of IRL player interaction surrounding the editing of the code, which will need its own set of rules2. Such a system clearly benefits from version control and would appear to be easiest to play on an online git service. It does, however, (superficially) appear to solve the original problem of undefined and unrigorous gameplay.
I should also say that a nonzero amount of this structure was inspired by many hours playing around with GNU Emacs and losing at Balatro.
Gamestate
The gamestate is the easiest component; it consists of a dictionary which encodes the current game state, easily extensible with additional information, as required. This is what the example below uses.
Actions
Actions, taking them or creating them, are the main ways that players affect the game. The initial nomic.py comes with a basic structure for creating actions, allowing players to package functions into objects that integrate well with the rest of the game. The code for defining an action uses a series of nested decorators, which we will see later. For now, here is an example of a “point adding” action.
Hooks
A hook is essentially a gameplay trigger that other effects can hang off. They are how effects that trigger on “end of turn” or similar conditions are met. Suppose we wanted to have the game end when a player accumulates 1000 points. One way to do this is by adding a point-checkin hook to the addpt action, so that every time a player’s points change (using this particular function), it triggers a check of the win condition. The syntax for such a hook is below.
Hooks additionally have access to all mandatory and optional arguments passed to the action that triggers them. All hooks also have a “speed”, the hook above being added at speed 1. Hooks with a negative speed are executed before the action they are attached to, positive speeds trigger after. The hooks with the largest magnitudes of negative/positive speed are executed first/last. And before you wonder, yes, you can add full gameplay actions as hooks. Hooks within hooks within hooks within hooks…
The Constructor
The creation of new gameplay is achieved using the @newaction decorator
which uses the actionbuilder function to create a new instance of createaction (see code below) which already contains a link to the gamestate (to avoid passing it each time)
To actually execute a defined game action, the class provides the gameAction.o() method.
Future Work
Currently, accessing the *args and **kwargs from inside hooks is a little cumbersome, involving some duplicate preprocessing. An example of this is given below in an addpt action with additional “commentary”.
This can probably be solved by an additional decorator which wraps the hooks and action function a little differently; however, as it stands, the game is eminently somewhat playable. Now all I need are some victims friends to pay with.
If you feel like you have too many friends, you can access the code for nomic.py here
Depending on your perspective, this is an extremely successful or unsuccessful Nomic.
A meta-Nomic, if you will







