
How the current Gomoku AI is built
The Gomoku AI has three parts.
- Qt app: a Gomoku engine and a local heuristic AI written in C++. It supports human vs AI, human vs VLM and AI vs VLM games.
- VLM server: Qwen3-VL looks at a board image and a text board and answers the coordinate of the next move.
- Web play: at [omook.mariago.kr](https://omook.mariago.kr/play) a person plays Black and chooses either the local AI or the VLM as the opponent.
Results against people
Counting only games played to the end, people won 39 of 43. On the web, people won 22 of 24, and in the Qt app against the VLM, 17 of 19. Two of the web games ended in 9 moves because the AI never blocked while Black played five stones.

Training games between AIs
For a week, the Qt app kept the local AI (Black) and the VLM (White) playing each other automatically. Of the 487 finished games, White won 457. Black won 29, and one game went to move 361 and was a draw.

The VLM gets coordinates wrong first
Of the 25,413 moves the VLM chose, 7,089 (28%) were unplayable, such as cells that already held a stone. In that case the server asks again, and if it is still wrong, moves the stone to the nearest empty cell. As the code comment says, this correction only rescues the coordinate; it does not guarantee a good move.

Automatic training was broken too
After every training game, LoRA was set to retrain on the winning side's moves. The data grew to 12,080 examples, but the last training log shows the loss falling from 248,414 to 0 with NaN gradients. That means training did not work. The server is currently running the base model Qwen3-VL-2B without LoRA.
Three training runs are on record. All ran on the fifth day of automatic play, each using only 200 examples for 25 steps. In all three, the loss exceeded 500 at step 10 and became 0 at step 20. All six gradient records are NaN. train_vlm.py treats a loss above 100 as divergence, and all three runs crossed that line.
The collected data is also lopsided. Of the 12,080 examples, 10,513 (87%) are White's moves. That is because White won 94% of the training games, and those White moves were played by the VLM but recorded as the local AI's moves. Only 1,291 moves come from games the local AI won as Black, and 276 from games won by people.

In short, the current Gomoku AI loses almost every game to people, and the VLM has not learned anything yet. The following posts go through the rules, the weaknesses and the plan to fix them in turn.
The actual code for this step
This is the part that moves the VLM's choice to a nearby empty cell when it picks an unplayable cell.
vlm_pva_server.py
if (
not illegal_adj_fallback
and board is not None
and not _is_legal_vlm_move(board, r, c, size)
):
if args.strict:
raise RuntimeError(f"모델이 부적절 칸을 반환: ({r},{c})")
why = _move_rejection_reason(board, r, c, size)
if _is_opening_board(board, size):
near = _opening_center(size)
else:
near = _nearest_empty(board, r, c, size=size)
if near is None:
raise RuntimeError("빈 칸 없음 (보드 가득 참)")
logging.warning(
"모델 좌표 (%d,%d) 부적절 — 사유: %s → 인접·근접 빈 칸 (%d,%d) 로 보정 "
"(보정은 좌표 복구용 휴리스틱이라 좋은 수를 보장하지 않음)",
r,
c,
why,
*near,
)
r, c = near
corrected = True
correct_reason = whyThe next post is "2. The renju rule made White invincible".
COMMENTS · CHAPTER 01
A Gomoku AI that loses to people 0 comments
No comments yet. Leave a question or anything you would like to add.
To post a comment, continue with Google and register a nickname and email address.
Continue with Google