A minimax chess engine in regular expressions
102 comments
·January 7, 2025basementcat
wodenokoto
> demonstrated that printf() is Turing complete and wrote a first person shooter in ...
Not gonna lie, I thought that sentence would end with the FPS being done in printf.
teleforce
This guy wrote tic-tac-toe in a single call to printf for IOCCC 2020 competition:
paulddraper
That is quite literally a work of art.
tubs
It’s very fun and impressive but it’s absolutely not a single call.
albertzeyer
The development writeup for the Doom is interesting, with many details. https://nicholas.carlini.com/writing/2019/javascript-doom-cl...
There was one month time to complete the competition. But it seems you were allowed to reuse any existing other code.
Looks like this was quite fun to work on.
(I feel a bit sad that I would never be able to get one month of free time to work on this now, due to family and job...)
mock-possum
Wow that’s a fascinating read, thanks for linking it!!
kookamamie
> a first person shooter in 13kB of Javascript
I was somewhat disappointed to realize they used WebGL for rendering the graphics.
klibertp
There was an earlier version of the underlying 3d engine that used only Canvas. WebGL use is justified like this:
> Once I actually got that working doing all of the math by hand in JavaScript I decided that using WebGL would probably be worth it, and actually probably wasn't cheating all that much. WebGL exposes access to the GPU-enabled rendering engine through JavaScript. While it does abstract away some of the rendering, it's less than I thought---it just supports the ability to do the necessary math efficiently---so I decided this wouldn't be cheating. And fortunately, it didn't take long to reproduce the initial renderer, but this time supporting much better (and more efficient) graphics.
From: https://nicholas.carlini.com/writing/2019/3d-renderer-javasc...
lxgr
That makes sense: As far as I understand, OpenGL 2.0 and beyond don’t really provide much fixed-function/predefined logic anymore, e.g. I believe you need to provide your own vertex and pixel shaders.
You could argue that rasterization itself is being taken care by the implementation, though.
pmarreck
Why is this disappointing?
ThrowawayTestr
[flagged]
vintagedave
This point was where this changed from crazy/fun to absolutely extraordinary, where calculations of multiple possible positions all occurred in parallel, running a regex over an increasing series of state & variable sets, aka threads:
> And now for my absolute favorite part of the language we've developed. By the magic of regular expressions (and the fact that they perform substitution globally over the entire string), we can run multiple threads simultaneously!
Also:
> What do you want out of a conclusion to a blog post like this? I don't really have much to conclude. I guess I'll just say that I think more people should do entirely pointless things like this. It's a lot of fun, no one cares how long it takes you to finish, no one cares if it works or not, and incidentally, it teaches you more than you wanted to know about dozens of areas of computer science outside your field.
What a wonderful ethos.
ricardo81
This makes me wonder whether I could achieve such a thing if I removed all my preoccupations of other stuff.
For me what I take out of it is the power to sit down, focus your mind on something then who knows the lengths of what is possible. That, and the author is clearly very talented/skilled and creative.
larodi
Apparently it takes more than skill but also persistence and concentration. Not many schools of thought explain this well .
PaulHoule
No, it takes (1) knowing what you learn in a compilers class (or upper level math classes) and (2) putting it to work. He didn't write 80,000 regular expressions, he wrote a compiler that wrote those expressions. Commercial-quality compilers are hard to write but simple compilers are straightforward if you know the fundamentals.
It's like the problem of solving the Rubik's cube. If you look at it in terms of geometry and spatial intuition it's intractable. If you treat it as an abstract algebra problem and break it down into "solve the top of the cube, solve the middle row of the cube, solve the bottom of the cube" and then develop a set of operators that will let you permute certain parts of the cube it takes a moderate amount of skill, persistence and concentration.
CS students do exercises such as writing moderately complex programs for a Turing machine and it's an exercise like what he did.
====
Funny my project last month was a chess engine. For a long time I'd wondered if I could make a decent MCTS chess engine but someone close to me has been getting serious about chess (usually wins against the random person, usually loses at the chess club, is fighting hard to get up the bracket) so writing a program that was a match for him seemed like a fun and meaningful project and I decided to try the conventional route of alpha-beta search.
If you tried to write a chess engine from zero you'd probably struggle, but the lifetime value you get out of education (CS or otherwise) is looking things up the literature, learning from other people's experiences, and putting it to work. So this has been my guide
https://www.chessprogramming.org/Main_Page
I started out with Python with the goal of making something tiny and stylish and started out with a move generator from
https://python-chess.readthedocs.io/en/latest/
and once I got the signs right in alpha-beta negamax (when I had them wrong it discovered https://en.wikipedia.org/wiki/Fool%27s_mate) it beat my tester several times before he regrouped, traded a knight for a good pawn structure, and got his first win.
The next goal is to take it to the chess club which means it has to respect time control. I switched to Java because its faster and because it is easy to have a comms thread interrupt a think thread. The first try wasn't faster because my move ordering was terrible. I was much faster implementing it though because I could cut and paste the test cases I had in Python and if I knew anything at this point it was the signs in negamax.
https://en.wikipedia.org/wiki/Iterative_deepening_depth-firs... is not only good for time control but gets better move ordering and I'm in the middle of implementing that. It would take me years to find out that Iterative Deepening works a lot better than you might expect, the Killer Heuristic, etc. Reading is my superpower.
null
reader9274
There's a bug somewhere it seems like, as it ends the following game with "Illegal move, you lose", even though it's not an illegal move:
1. e2e4, e7e5 2. d2d4, e5d4 3. d1d4, a7a5 4. g1f3, b7b5 5. b1c3, a5a4 6. c3b5, a4a3 7. b5a3, a8a3 8. b2a3 --> Illegal Move You Lose. Game over.
FEN of game above: 1nbqkbnr/2pp1ppp/8/8/3QP3/P4N2/P1P2PPP/R1B1KB1R b KQk - 0 8
oah
a2a3 on the first move or on the second move after e2e4 outputs that you have played an illegal move.
But this is a bug as these are legal moves.
foxglacier
Simply using a2a4 as the first move does that too.
reader9274
ah interesting, a2a3 does the same. May be a bug with moves on the a file by white
comonoid
I fear not the man who plays chess with 84,688 regular expressions, but I fear the man who plays chess with one regular expression.
pmarreck
If there was a general heuristic to make sequentially-applied regexes linear (combine any 2 into 1), it could be applied to this
help, I'm being nerd-sniped
right away I see backreferences as a potential problem
it would be a VERY long regex, but you're basically encoding a chess engine, so...
TZubiri
"help, I'm being nerd-sniped"
Just breathe
Close your eyes
Picture an algebraic representation of the higher order function that represents your real life utility and minimizes the use of resources including your cognitive energy.
Focus on optimizing that function.
Ohmmmmm
anal_reactor
I fear people in general because I have social anxiety
thot_experiment
When I see this sort of thing I just I want to take my hat off and stand in solemn appreciation for the true heroes among men.
DylanSp
The bug with a-file moves has been fixed: https://github.com/carlini/regex-chess/issues/1.
lifthrasiir
Previously: Chess written in sed https://news.ycombinator.com/item?id=6261314
Of course, the sed version does make use of control flow commands in sed and only probes 1ply (I think) so this version is significantly different in that regard.
z3t4
This is not only a chess engine, it's a computer and an assembly language, built in only using Regexp
dstrek
I normally don’t lose so quickly opening with a2a4 !
NooneAtAll3
oh, cool
I encountered similar bug in the a-column via e2e4-d2d4-d1d4-g1f3-f1b5-d4e5-e5c5-e1g1-b2a3
eru
Compare also https://codegolf.stackexchange.com/q/3503/32575
lifthrasiir
That shouldn't be really surprising, as all divisibility rules are necessarily regular because anything more complex wouldn't be human-executable "rules".
eru
Humans are able to check whether a string of parens, like ()(()()), is matched but finite state machines can't.
In any case, if you know how the regex is constructed, it's not surprising. But I found it fun to actually do the construction, instead of just being theoretically aware of the possibility.
lifthrasiir
Is this balanced or not: ((((((((((((((((((((())))))))))))))))))))? Humans can check only so many parentheses before losing track of them, so it is still an FSM in my opinion.
Also, those regexes are directly translated from the equivalent and much smaller FSM. Regexes are necessarily complex only because they have Kleene stars and nothing else; it's like representing every Boolean circuits with NAND, which is of course possible and a little fun fact but the process itself isn't exactly fun to me.
QuentinCh
The idea of doing something without a defined "productive" goal might help to do things differently, discover new ways, and in the end stumble on an innovation?
Tried it, 2 comments:
1) Engine gives a piece early with: 1. b3 b6 2. Bb2 Bb7 3. e4 ??Bxg2
2) when you enter an uppercase letter it says illegal move
Edit: and here I am trying to "stumble" on an innovation and be productive again. Erh... Humans
plank
Well, winning with checkmate in just a few moves is also possible (d4 d5 - c4 dxc4 - e4 d8xd4 and after d1xd4, d4c4, c4xc7 and c7xc8 won by checkmate).
I guess playing 'good' chess is not the point, the point is that you can play at all using regexp. (The 'move a2a3 and lose as not considered legal' is more serious then it not actually playing well).
o999
One good way some people learned programming is by building replacements for Python builtin/standard modules functions in Python
magnusisapuxxy
As it's already been reported in this comment section, at a seemingly random stage of the game when it's the player to move, an error caused by an illegal move is triggered. Happened to me twice already in the opening. Once for a King's knight move to f3 and once for a simple pawn move as follows: 1.Nc3(b1c3) Nc6(b8c6) 2.g3(g2g3) g6(g7g6) 3.Bg2(f1g2) Bg7(f8g7) 4.e3(e2e3) Bxc3(g7c3) 5.bxc3(b2c3) a6(a7a6) 6.c4(c3c4) a5(a6a5) 7.Ne2(g1e2) a4(a5a4) 5.a3(a2a3) saying a2a3 is illegal.
Creative approach. Very impressive if it'd work, but you cannot finish the game, because it doesn't recognize the moves properly. The program understanding and strength is poor, but it was to be expected and it's beyond the point of this intellectual exercise, I guess.
This is from the same gentleman who (among other things) demonstrated that printf() is Turing complete and wrote a first person shooter in 13kB of Javascript.
https://github.com/HexHive/printbf
https://github.com/carlini/js13k2019-yet-another-doom-clone