Play Connect 4 in your terminal
nc cqql.site 1234
I just really wanted to make Connect 4 playable in the terminal from anywhere in the world without any installations (assuming you have netcat installed and using a linux terminal because who else would be the target demographic for this :3).
AI
I didn't want to code the AI myself so I decided to look for a ready made algorithm. Very fortunately, I stumbled on Arjun Balakrishnan's article Exploring Board Game AI Algorithms: Minimax. You can play with his AI (compiled to WASM) interactively in the browser at balkarjun.github.io/ConnectFourAI. The code had beautiful little tricks, like representing the whole game state with just two 64-bit integers
/*
6 13 20 27 34 41 48 55 62
---------------------
| 5 12 19 26 33 40 47 | 54 61
| 4 11 18 25 32 39 46 | 53 60
| 3 10 17 24 31 38 45 | 52 59
| 2 9 16 23 30 37 44 | 51 58
| 1 8 15 22 29 36 43 | 50 57
| 0 7 14 21 28 35 42 | 49 56 63
---------------------
Bitboard Representation
*/
// [...]
struct GameState {
u64 bitboards[2] = {0, 0};
// [...]
}
Which enables checking win conditions with just a couple with shifts
int check_win() {
for (int idx = 0; idx <= 1; idx++) {
u64 board = bitboards[idx];
if ((board & (board >> 7) & (board >> 14) & (board >> 21)) != 0) return idx; // horizontal
if ((board & (board >> 1) & (board >> 2) & (board >> 3)) != 0) return idx; // vertical
if ((board & (board >> 8) & (board >> 16) & (board >> 24)) != 0) return idx; // positive diagonal
if ((board & (board >> 6) & (board >> 12) & (board >> 18)) != 0) return idx; // negative diagonal
}
return -1;
}
Very elegant.
Interface
I wanted to make this as barebones and low level as possible, so I decided to just go with a TCP socket. To be able to implement it in Rust, I rewrote Arjun's AI (with his permission - as long as it stays open source), then implemented a socket interface, and later added logging.
The code is available in this git repo: tcp-connect4.
The interface looks like this
Connect 4
Choose your difficulty [1-9]: 3
Move 0:
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · · · · ·
1 2 3 4 5 6 7
Choose column: 5
[AI thinking]
Move 2:
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · ○ ● · ·
1 2 3 4 5 6 7
Choose column: 5
[AI thinking]
Move 4:
· · · · · · ·
· · · · · · ·
· · · · · · ·
· · · · ○ · ·
· · · · ● · ·
· · · ○ ● · ·
1 2 3 4 5 6 7
The difficulty choice is just the depth up to which the min max algorithm will look before choosing a heuristic. It's fun to experiment with that and seeing how the AI behaves!
Then I added logging because I wanted to practice Rust's tracing crate. If you want to see a leaner version of the code, without the logging, take a look at this commit.
Now you can just type
nc cqql.site 1234
in your terminal and play Connect 4 from anywhere in the world!
Hosting
If you'd like to host it like I did on cqql.site, then you can use this dockerfile
FROM ubuntu:latest
COPY ./connect4 /connect4
EXPOSE 1234
CMD ["/connect4"]
Then build it with
docker build . -t "connect4"
And run with
docker run -i -p 1234:1234 -v ./logs:/logs --name connect4 connect4