By dkl9, written 2025-134, revised 2025-134 (0 revisions)
Go is a game of two players, black and white:
This leaves out a few details, which you may learn by actually playing a game.
Desmos graphing calculator is Turing-complete, so one could make Go in it. One tuesday night, I got bored enough to start exactly that. The finished game is public, and what follows is how it works.
This was the easy part. I modelled the game-state as a W·H-element list B and a turn-variable T. In both, black was represented as +1, white as -1, and neutral as 0.
To give the state any real meaning, I had to also display it. That arose as a list of lattice-points, formed by iterating over columns and rows. Their form and colour was mapped from B. Where B held 0, the point was shown as a clickable black dot. Where B held 1 (resp., -1), the point was shown as a larger black (resp., white) circle. A few other plotted equations served to show more clearly the structure of the board, as one would see in real life.
A click on one of those empty black dots would mean that you place a stone there. From such a click, the index into B tells the "code" where to place it, and the current turn T tells which stone — black or white, +1 or -1 — should be marked anew in B. Thus did I write the action P(i), to modify B just like that. It also changed T, as turns alternate, but that was later moved to the end of the turn.
To find captures in Go:
A "liberty", here, is an empty grid-spot next to a given stone or group. A function L(x, y) counts the liberties of the stone at (x, y), if treated separate from its group. Ls(l) gives the total liberties of the stones listed in l. The proper view says that liberties are only defined on groups, and that Ls double-counts many of them, but these definitions agree on what has zero liberties, which suffices here.
Any one move can only affect those groups that include stones adjacent to the newly-placed stone. Thus does P(i), as a stone is placed, set a small queue Q of stones to consider. V(p), used for Q, lists five positions — p and its four immediate neighbours.
"Connected group" is any fixed point of that function on a set of positions that inserts to the set all alike neighbours of items in the set. E(l) takes a list of positions l and gives another list, which holds also some of the four immediate neighbours of each. In particular, the new list adds only those neighbours which "hold the same colour stone" (have the same value in B) as the original positions. E uses D(l) to remove duplicates, and so make the list work more like a set.
That comes together in Sgg, which gathers groups in G as started from positions in Q:
K(l) sets all positions in l to hold 0 in B.
When checking which groups get captured, first look at the opponent's groups, and only afterward at those of the colour just placed. I enforced that by using Vs to build Q which, instead of mere V, sorts the neighbours by whether their position's state in B matches the current turn. Every move should cause at most one capture, so K also clears Q, leaving zero more positions to process.
Sith scoring a Go game is even harder than checking for captures, and sith there are multiple common ways to score games, I leave the score to the humans, instead of implementing it in Desmos.
But to end the game, the players must pass. So Pp immediately moves to the next turn, and is affixed to the clickable edge of the board. Such a pass is recorded in the inscrutable state-variable Sp. A second pass ends the game, to prohibit more moves and show the game in a scoring-friendly form.
It's also useful to know how many stones were captured, so Zb and Zw keep track of those, as updated by K. To help one recreate a game, Bo records the ply-number when each stone was placed, as updated by S — the main calculation step — using the ply-number C.
Via some minor hacking which, it seems, Desmos users silently agree to keep secret, I saved the finished game to the custom URL https://desmos.com/calculator/weiqiboard — "weiqi", or "围棋" is the Chinese name for Go.