Inspired by some other works on the same line, I made the regex engine play Connect Four.

The regexes don't do the work all by itself, although it spend most of it's time matching, it uses the negascout algorithm to transverse the game tree.

To evaluate the game state, I store the board as a string:
my $table = <<EOT 0000000 0000000 0000000 0000000 0001000 0002000 0021000 EOT
Then, to check if anyone won, for example:
$table =~/(?| (?: ([12]) (?= \1 \1 \1) ) | # (1) (?: ([12]) (?= .{7} \1 .{7} \1 .{7} \1) ) | # (2) (?: ([12]) (?= .{6} \1 .{6} \1 .{6} \1) ) | # (3) (?: ([12]) (?= .{8} \1 .{8} \1 .{8} \1) ) # (4) )/xs
It will first match 1|2 (1 and 2 are the players stones), and then look ahead for either horizontal match (1) or 3 stones vertically under it (2), or in either diagonals (3) and (4). If match, the winner will be in $1.

Adding a stone on the table is a s/// operation:
$table =~ s/^ .{4} (?: .{7} . )* \K 0/1/xs
Will add a '1' stone on the (zero-based) column 4. Match fails if column is full.

Finally, the meat of the script is the table evaluation, which is a auto-generated version of the win pattern, except instead of matching 4 equal stones, it matches all imperfect combinations and attribute points depending on how good is the combination (See the setup() sub).


You can run the script like this:
./c4player [--depth=9] [--width=7] [--height=7] [--cpu=1]
I choosed the 7x7 board because it has been proven you can't force a win but the script will accept any reasonable dimension.

Overall, the script turned out to be faster than I had thought, spending between 1 ~ 10 seconds to make a move at depth 9, although it's still 1 or 2 orders of magnitude slower than a "vanilla" C implementation.

Looking forward to hear how can I make this faster ;)