Home

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

Home