Every time a new piece appears, the AI tries every place it could put it, scores the board each one would leave, and goes with the best. Then it plays that placement with the same key presses you have, one frame at a time.
The rules are a straight port of Mike's 2020 pygame Tetris: a 7-piece bag, hold, three next pieces, SRS rotation with wall kicks, half a second of lock delay, and gravity that speeds up every level. The game advances in frames, 60 per second. Each frame it reads which keys are held, the way a console does, and holding left or right starts repeating after 16 frames, then moves every 6.
Searching over key presses doesn't work. There are 60 frames a second, and almost every frame's choice changes nothing. So the AI thinks one level up: a move is a placement, a pair of how many columns to shift (−5 to 5) and how many quarter turns to rotate (0 to 3). That's 44 moves per piece, and several of them land in the same spot when the piece hits a wall.
To make a move, it presses the rotation keys, taps left or right once per column (with a released frame between taps, so the key repeat never kicks in), then hard drops. While searching it plays those same presses on a copy of the game, so what it imagines is exactly what will happen.
It doesn't score boards by game points. Points mostly come from line clears, and a clear takes several pieces to set up, so a short search sees almost none. Instead it looks at the shape of what's left, using four numbers and weights from Yiyuan Lee's Tetris AI:
| height: the column heights added up | −0.510 |
| lines this placement cleared | +0.761 |
| holes: empty cells with a block right above | −0.357 |
| bumpiness: height jumps between neighbors | −0.184 |
The score is the weighted sum. A low, flat board with no covered gaps scores best. Mike's version measures a column's height as the row index of its top block, so a block sitting on the floor counts as 0, and a hole is only the cell directly under a block.
The next pieces are on screen, so the AI can plan for them too. With 2 pieces it tries every placement of the current piece, then every placement of the next one after it, and gives each first move the score of its best follow-up: 44 × 44 = 1,936 boards per piece. It's called minimax in the code, but with one player there's nothing to minimize, so it's a plain search for the best sequence. Ties go to a random one.
Because every move ends in a hard drop from above, it never slides a piece under an overhang or spins a T into a slot. What it does well is play quickly and cleanly, using few inputs per piece. That's how it survives gravity of a row or more per frame (level 18 and up), where a piece hits the stack almost as soon as it appears. Around level 25, with about six rows per frame, a piece can't slide past a tall column any more and the AI tops out within a few dozen lines. The game also pauses while the AI thinks, as the Python version did.