Smarter AI - Adjacent Priority
The AI builds connected territory by prioritising cells next to its existing claims.
Random moves work, but they don’t feel like playing against an opponent. The AI scatters claims across the board with no plan. This unit gives the AI its first strategic behaviour: prefer cells adjacent to existing territory.
The result is an AI that builds connected regions — clumps of blue cells that expand outward. It’s still beatable, but it feels more like a real opponent.
Run It
pasmonext --sna inkwar.asm inkwar.sna

Watch how the AI’s claims cluster together. Instead of random scattered cells, it builds from its first claim outward.
The Strategy
When humans play territory games, they instinctively expand from existing claims. Isolated cells are vulnerable; connected regions are stronger. The AI now does the same:
- Scan every empty cell on the board
- For each empty cell, count how many adjacent cells the AI owns
- Pick the cell with the highest count
- If no adjacent cells exist, fall back to random
This simple heuristic produces surprisingly natural-looking play.
Finding the Best Adjacent Cell
The core algorithm scans all 64 cells and tracks the best candidate:
This code sample could not be loaded. The file may be missing or the path may be incorrect.
We track two values: best_cell (the index of the best cell found so far) and best_score (how many AI neighbours it has). Each empty cell gets scored, and we keep the highest.
If no cell has any AI neighbours (score remains 0), we fall back to find_random_empty_cell — the same function from Unit 9.
Counting Adjacent Cells
For each candidate cell, we need to count how many neighbours belong to the AI:
This code sample could not be loaded. The file may be missing or the path may be incorrect.
This checks the four orthogonal neighbours (up, down, left, right). Edge detection prevents reading outside the board — row 0 has no up neighbour, column 7 has no right neighbour.
The helper function .caa_check_cell converts row/column to a board index and checks if that cell belongs to Player 2 (the AI).
Updating AI Move Selection
The change to ai_make_move is minimal — just call the new function instead of the random one:
This code sample could not be loaded. The file may be missing or the path may be incorrect.
Everything else stays the same: convert the cell index to row/column, claim the cell, switch players, update the display.
Why This Works
Adjacent priority creates emergent behaviour:
- Early game: The AI’s first move is random (no existing territory), but subsequent moves cluster around it
- Mid game: The AI expands its territory naturally, filling in gaps
- Late game: When surrounded by enemy cells, it still finds the best local option
The AI doesn’t think ahead or consider defence — it just prefers cells next to its own. Yet this simple rule produces play that looks intelligent.
The Complete Code
This code sample could not be loaded. The file may be missing or the path may be incorrect.
Try This: Diagonal Neighbours
The current code only checks orthogonal neighbours (up, down, left, right). You could also check diagonal neighbours:
; Check up-left (row-1, col-1)
ld a, b
or a
jr z, .skip_up_left
ld a, c
or a
jr z, .skip_up_left
; ... check cell at (row-1, col-1)
This would make the AI value corner positions differently.
What You’ve Learnt
- Cell scoring — Evaluating board positions numerically
- Neighbour counting — Checking adjacent cells with boundary detection
- Fallback strategies — Using random when heuristics don’t apply
- Emergent behaviour — Simple rules producing complex-looking play
What’s Next
In Unit 11, we’ll add defensive behaviour — the AI will recognise when the human is building territory and try to block them.