PrimLagic

Porting an AI from Python to JavaScript and testing it with 200 games

By Ali Abdolahi · · 2 min read

Porting an AI from Python to JavaScript and testing it with 200 games

The TekTacTok online demo has no server; everything runs in the browser. But the AI was written in Python, so the logic had to be ported, and every port raises the same worry: is the behaviour really identical?

Only a table was needed

Inference is simple: a precomputed table (about 43 thousand states, roughly 1.1 MB of JSON, around 155 KB over the wire when compressed) plus a few small functions: legal moves, applying a move, detecting a winner and mapping a state to its canonical form under symmetry. The heavy solver stays in Python; only its result ships to the browser.

Dangerous details

Symmetry: all 8 board symmetries must be tried in the same order as Python and the smallest representation kept; array comparison must behave like Python's tuple comparison. Table keys: a string of piece positions plus turn and two counters; a tiny formatting difference means "state not found". Random tie-breaks: the order in which random numbers are consumed must not differ between languages.

The parity test

Instead of reading the code and hoping, I wrote two scripts, one per language, using the same simple LCG random generator and the same selection rules. Each plays 200 games and records the winner; then the outputs are compared.

Two lessons: first, my first comparison showed differences, but the cause was the test itself: Python consumed a random number every turn while JavaScript's && short-circuited in perfect mode. After fixing the test the move sequences matched. Second, even with a correct test, exact moves sometimes differed among equally good moves, yet all 200 winners were identical. The right criterion was "the move is optimal", not byte-for-byte equality.

Result: 0 differences in the winners of 200 games.

When porting an algorithm: define what must be equal, write the test, then write the port.

JavaScriptPythontesting