◈ ALGORITHM DEEP DIVE ◈

TRAPGRID

Theory · Algorithms · Formulas · Strategy

BFS Minimax Alpha-Beta Pruning Move Ordering Adaptive Depth Heuristic Design Game Theory
↓ Scroll to explore ↓
Contents
SECTION 01
Game Overview & Rules
The isolation game on a 7×7 grid

TrapGrid is a two-player combinatorial strategy game based on the classic Isolation concept. Players move on a 7×7 grid. Every cell a player leaves behind becomes permanently blocked. The player who cannot make a valid move loses.

Grid Size
7×7
49 cells total
Move Directions
4
Up Down Left Right
Starting Cells
(0,0)
P1 top-left
Starting Cells
(6,6)
P2 bottom-right
Win Condition
Trap
Opponent 0 moves
Objective
Force your opponent into a position where they have zero valid adjacent moves. The last player to move wins.
Trail of Blocks
Every cell you leave becomes a permanent blocker (✕). You can never revisit it — the board shrinks every turn.
Legal Moves
From position (r,c) you may move to (r-1,c), (r+1,c), (r,c-1), or (r,c+1) — only if that cell is empty (value = 0).
Game End
When the current player has no valid moves after refreshing from their position, the previous mover is declared winner.
Board State Encoding
CELL_EMPTY = 0 // free cell — can be moved into CELL_P1 = 1 // Player 1 is currently here CELL_P2 = 2 // Player 2 / AI is currently here CELL_BLOCKED = -1 // permanently blocked trail cell
SECTION 02
BFS — Breadth-First Search
Measuring territory & breathing room

BFS is the backbone of the heuristic. It performs a flood-fill from a player's current position and counts every empty cell reachable without crossing blocked or occupied cells. This count equals the player's territory — how much of the board they still own. A player with large territory has more room to manoeuvre; a player cornered into a small pocket is losing.

BFS guarantees the correct count even for irregular board shapes and isolated pockets — unlike a naive "count empty neighbors" approach which would miss cells behind corners.
1
Initialise
Create a visited[7][7] boolean grid, all false. Push the player's position onto a queue. Mark it visited. Set count = 0.
2
Dequeue & Count
Pop a cell from the front of the queue. Increment count. For each of 4 neighbours: skip if out-of-bounds, already visited, or not CELL_EMPTY.
3
Enqueue Valid Neighbours
Mark each valid neighbour as visited and push to the queue. This prevents double-counting and infinite loops.
4
Repeat Until Empty
Continue until the queue is empty. The final count equals the number of reachable cells — the player's territory score.
BFS Pseudocode
function countReachable(board, startRow, startCol): visited false[7][7] queue [(startRow, startCol)] visited[startRow][startCol] = true count 0 while queue not empty: (r, c) dequeue(queue) count++ for (dr, dc) in [(-1,0),(1,0),(0,-1),(0,1)]: (nr, nc) (r+dr, c+dc) if inBounds(nr,nc) and not visited[nr][nc] and board[nr][nc] == 0: visited[nr][nc] = true enqueue(queue, (nr,nc)) return count // territory size

Territory Map: Running BFS from both players simultaneously produces a coloured zone map. Cells reachable only by P1 are green, only by P2 are blue, and cells reachable by both (contested) are purple.

P1 exclusive territory
P2 exclusive territory
Contested (both can reach)
P1 position
P2 position
Blocked
Time complexity: O(R × C) = O(49) per BFS call. In the worst case we call BFS at every node in the Minimax tree — but with alpha-beta pruning this stays tractable.
SECTION 03
Minimax Search
Recursive adversarial game tree search

Minimax is a recursive algorithm for two-player zero-sum games. The AI (maximiser) tries to pick the move that leads to the highest heuristic score. The opponent (minimiser) is assumed to play perfectly and will always choose the move that is worst for the AI. The algorithm explores all possible futures up to a given depth, then evaluates leaf nodes with the heuristic function.

Maximiser (AI, P2)
At MAX nodes the AI picks the child with the highest score. It wants to find a move that leaves it in the best position.
Minimiser (P1)
At MIN nodes the opponent picks the child with the lowest score. They are assumed to play optimally against the AI.
Terminal / Leaf Nodes
If a player is trapped (no moves), return +100,000 (AI wins) or -100,000 (AI loses). At depth 0, call the heuristic.
Value Propagation
Scores bubble up: MIN takes the minimum of its children, MAX takes the maximum. The root returns the best move found.
MINIMAX TREE — SIMPLIFIED 2-PLY EXAMPLE
MAX (AI)12ROOT
MIN12move A
MIN7move B
MIN4move C
MAX12← best
MAX7
MAX4
MAX15not chosen
MAX9
Minimax Core Logic
function minimax(board, depth, α, β, isMax, p1, p2): // Terminal: someone is trapped if isMax and moves(p2).length == 0: return -100000 // AI trapped if not isMax and moves(p1).length == 0: return +100000 // P1 trapped // Leaf: depth exhausted → evaluate if depth == 0: return heuristic(board, p1, p2) best isMax ? -∞ : +∞ for move in orderMoves(board, isMax ? moves(p2) : moves(p1)): applyMove(board, move) score minimax(board, depth-1, α, β, not isMax, ...) undoMove(board, move) if isMax: best = max(best, score); α = max(α, score) else: best = min(best, score); β = min(β, score) if β α: break // α-β cut return best
SECTION 04
Alpha-Beta Pruning
Cutting impossible branches to search deeper faster

Alpha-Beta pruning is an optimisation layered on top of Minimax. It maintains two values — alpha and beta — which represent the best already-explored options for the maximiser and minimiser respectively. When β ≤ α, the current branch cannot influence the final decision and is cut (pruned). This can reduce the number of nodes from O(b^d) to O(b^(d/2)), effectively doubling the searchable depth.

Alpha — MAX bound
The best guaranteed score the maximiser has found so far along this path. Starts at -∞. Updated when MAX finds a better move. If a MIN node's value drops below alpha, MAX already has something better — prune remaining siblings.
Beta — MIN bound
The best guaranteed score the minimiser has found so far along this path. Starts at +∞. Updated when MIN finds a worse move for MAX. If a MAX node's value exceeds beta, MIN already has something better — prune remaining siblings.
ALPHA-BETA PRUNING EXAMPLE
MAXα=5root
MINβ=5
MIN ✂prunedβ<α
MAX5
MAX3
MAX?
MAX?
Cut Condition
// β-cutoff (at MAX node): MIN parent won't allow this path if score β: nodesPruned += remaining_siblings break // prune all remaining siblings // α-cutoff (at MIN node): MAX parent won't allow this path if score α: nodesPruned += remaining_siblings break // Efficiency metric tracked in real-time pruningEfficiency = nodesPruned / (nodesVisited + nodesPruned) × 100%
PropertyPlain MinimaxMinimax + Alpha-Beta
Time complexityO(b^d)O(b^(d/2)) best case
Nodes at depth 5 (b≈4)~1024~32 best case
Depth at same cost3–45–8 with move ordering
Move ordering benefitNoneCritical — sorts to maximise cuts
CorrectnessExactExact (same result)
SECTION 05
Move Ordering
Searching best moves first to maximise pruning

Alpha-Beta pruning works best when the strongest moves are searched first. If the first move examined is already close to optimal, subsequent branches are quickly cut. TrapGrid uses a quick pre-sort of all legal moves using a lightweight BFS evaluation before calling the full Minimax tree.

Move Ordering Score (quick eval, O(N) per move)
// For maximiser (AI) evaluating move m → new_p2: quickScore = BFS(new_p2) × 2 - BFS(p1_pos) // maximise AI room, minimise P1 room + CENTER_BONUS[m.row][m.col] × 0.2 // prefer central moves // For minimiser (P1) evaluating move m → new_p1: quickScore = -BFS(new_p1) + BFS(p2_pos) × 2 // minimise P1 room, keep AI breathing + CENTER_BONUS[m.row][m.col] × 0.2 // Sort moves descending for MAX, ascending for MIN orderedMoves sort(moves, by quickScore)
In practice, move ordering combined with alpha-beta pruning saves 40–70% of node evaluations compared to searching in an unordered fashion. The AI panel's "Efficiency %" stat directly measures this.
SECTION 06
Heuristic Function
The multi-component board evaluation formula

At depth-0 leaf nodes (and for logging/display), the game state is evaluated by a weighted multi-component heuristic. A positive result means the AI is winning; negative means the human is ahead. The formula balances long-term territory ownership with immediate tactical pressure.

Master Heuristic Formula
score = (aiTerritory - oppTerritory) × 2.5 // territory weight + (aiImmediate - oppImmediate) × 3.0 // immediate mobility + manhattanDist(p1, p2) × 0.3 // separation bonus + (aiCenter - oppCenter) // center control + (oppWallDanger - aiWallDanger) × 1.5 // wall safety - isolationPenalty(aiMobility, aiImmediate) // AI low-mobility penalty + isolationBonus (oppMobility, oppImmediate) // Opp low-mobility bonus // Terminals override heuristic entirely: SCORE_WIN = +100000 // P1 has no moves → AI wins SCORE_LOSE = -100000 // AI has no moves → AI loses
×2.5
Territory Score
BFS reachable cells for AI minus BFS reachable cells for P1. The most important long-term factor.
(aiTerritory − oppTerritory) × 2.5
×3.0
Immediate Mobility
Count of direct adjacent empty cells — the most urgent tactical measure. Higher weight than territory.
(aiImmediate − oppImmediate) × 3.0
×0.3
Distance Bonus
Manhattan distance between players. Larger gap = AI not yet cornered and has time to manoeuvre.
|r1−r2| + |c1−c2|) × 0.3
×0.4
Center Control
Precomputed bonus table — centre cells score 6, edges score ~1. Central positions have more escape routes.
(6 − |r−3| − |c−3|) × 0.4
×1.5
Wall Danger
Penalises being near corners/edges. Corner = +4 danger, edge = +2 danger, plus low immediate moves penalty.
(oppWallDanger − aiWallDanger) × 1.5
Var
Isolation Penalty
Non-linear penalty/bonus for critically low mobility. Trapping the opponent yields huge bonuses; being trapped yourself is heavily penalised.
imm=0:±200/300, mob<4:±80, <8:±35
Wall Danger Detail
function getWallDanger(board, pos): moves getValidMoves(board, pos) isEdge pos.row {0,6} OR pos.col {0,6} isCorner pos.row {0,6} AND pos.col {0,6} danger 0 if isCorner: danger += 4 elif isEdge: danger += 2 danger += max(0, 2 - moves.length) × 3 // very few moves = extra danger return danger
Center Bonus Lookup Table (precomputed)
// For cell at (r, c) on 7×7 grid, centre = (3,3) CENTER_BONUS[r][c] = 6 - (|r-3| + |c-3|) // Result grid (visualised): // 0 1 2 3 2 1 0 // 1 2 3 4 3 2 1 // 2 3 4 5 4 3 2 // 3 4 5 6 5 4 3 ← centre (3,3) = 6 // 2 3 4 5 4 3 2 // 1 2 3 4 3 2 1 // 0 1 2 3 2 1 0
SECTION 07
Adaptive Depth
Searching deeper when it matters most

A fixed depth is wasteful — in the endgame when very few moves are available, a depth-5 search may explore only a handful of nodes. Conversely, branching is high mid-game. TrapGrid uses adaptive depth: the base depth is 5 but automatically scales up to 8 when both players have few remaining moves, making the AI near-perfect in critical endgame situations.

Adaptive Depth Logic
function getAdaptiveDepth(board, p1, p2): ai getValidMoves(board, p2).length opp getValidMoves(board, p1).length minMoves min(ai, opp) if minMoves 2: return min(8, BASE_DEPTH + 3) // critical endgame if minMoves 4: return min(8, BASE_DEPTH + 2) // late endgame if minMoves 6: return min(8, BASE_DEPTH + 1) // early endgame return BASE_DEPTH // = 5 (mid-game default)
Min Available MovesPhaseSearch DepthWhy
> 6Mid-game5High branching factor — depth 5 is already expensive
5–6Early Endgame6Fewer branches — can afford to look one ply deeper
3–4Late Endgame7Very few branches — two extra plies come cheap
≤ 2Critical8Near-terminal — near-perfect play possible, small tree
SECTION 08
Wall Danger & Isolation Mechanics
Non-linear penalties that model real tactical danger

Linear scoring misses critical positions. A player with 1 immediate move vs 2 is not just "1 unit worse" — they are on the edge of defeat. TrapGrid uses non-linear step functions for isolation to ensure the AI treats near-trapped states as nearly catastrophic.

Isolation Penalty (applied to AI)
function getIsolationPenalty(mobility, immediate): if immediate == 0: return 200 // one move from losing → massive penalty if mobility < 4: return 80 // very small pocket if mobility < 8: return 40 // restricted pocket if mobility < 12: return 15 // somewhat constrained return 0 // comfortable space — no penalty function getIsolationBonus(oppMobility, oppImmediate): if oppImmediate == 0: return 300 // opponent about to be trapped → huge bonus if oppMobility < 4: return 80 if oppMobility < 8: return 35 return 0
Consider a position where the AI has territory = 12 and immediate = 0. The territory score looks fine, but the AI is one turn from losing. A flat score would miss this. The immediate == 0 → -200 penalty ensures the AI treats these near-death states with extreme caution.

Wall Danger models the danger of being trapped in a corner or edge. Corners have only 2 neighbours (maximum), making them the easiest places to seal someone. Edges have 3. The danger score penalises being in these locations and having few immediate moves simultaneously.

Corner Position
Base danger +4. Only 2 adjacent cells. One blocked neighbour = only 1 escape. Two blocked = trapped. Avoid corners at all cost — or use them to trap the opponent!
Edge Position
Base danger +2. Three adjacent cells. Less dangerous than corners but still restricts movement. The AI avoids edges unless tactically forced.
Low Immediate Moves
Each move below 2 adds +3 wall danger. Combined with corner/edge position this compounds quickly. danger = 4 + (2-0)×3 = 10 for a trapped corner.
Centre Safe Zone
Centre cells (3,3) have 4 neighbours and score 0 wall danger. The AI actively steers toward the centre to maintain maximum flexibility.
SECTION 09
Strategy Guide
How to think and beat the AI

TrapGrid has deep strategy despite simple rules. The key insight is that territory matters more than position — a player who secures a large pocket of cells will outlast one who chases the opponent. Understanding the AI's priorities lets you exploit its blind spots.

Control the Centre
Move toward (3,3) early. Central cells give you 4 possible moves at all times and maximum BFS territory. The AI knows this — contest the centre immediately or you'll be squeezed into a corner.
Divide the Board
Try to cut off a large chunk of the board for yourself and a small chunk for the AI. Once separated, the territory disparity rapidly becomes decisive. Look at the BFS zone overlay to see if you've achieved separation.
Compress the AI
Don't run away — chase the AI toward walls and corners. A player compressed into the bottom-right quarter of the board with few cells will run out of moves quickly. Aggressive containment beats passive survival.
Avoid Corners
Corners at (0,0), (0,6), (6,0), (6,6) have only 2 exits. Even one blocked neighbour halves your options. Stay away from corners unless you're deliberately trapping the opponent in one.
Think Parity
If you're isolated from the AI in a pocket, count the available cells. Odd cells = last mover wins (usually you). Even cells = last mover loses (usually you). You can sometimes "waste" a move to flip parity.
Beat the AI
The AI searches depth 5–8 but evaluates using a heuristic. In truly unusual board shapes, the heuristic can be wrong. Create strange, irregular pockets. The AI expects the opponent to play near-optimally — unpredictable moves can throw it off.

Parity Rule (critical endgame concept):

Parity Strategy
// If players are separated into isolated pockets: yourCells = BFS(your_position) // cells in your pocket their_cells = BFS(their_position) // cells in their pocket if yourCells % 2 == 1: // ODD → you will make the LAST move in your pocket → you WIN if isolated else: // EVEN → opponent makes the last move in your region → you LOSE if isolated // Strategy: waste a move (move then come back) to flip parity!
SECTION 10
Complexity Analysis
Theoretical bounds and practical performance
OperationTime ComplexitySpaceNotes
Single BFSO(R×C) = O(49)O(49)Constant on 7×7 board
getValidMovesO(4) = O(1)O(1)4 directions only
orderMovesO(m × 49)O(m)m = number of legal moves
Minimax (no pruning)O(b^d)O(d)b ≈ 4, d = 5 → ~1024 nodes
Minimax + Alpha-BetaO(b^(d/2))O(d)Best case ≈ 32 nodes at depth 5
Full AI turn (typical)O(b^d × 49)O(d × 49)Sub-second in practice
Territory mapO(2 × 49) = O(98)O(49)Two BFS runs per update
Danger/heatmapO(49)O(49)Manhattan distance per cell
Base Search Depth
5
mid-game
Max Search Depth
8
endgame adaptive
Win Score
100k
terminal
Board Cells
49
7×7 grid
Max Legal Moves
4
per position
In practice: With alpha-beta pruning and move ordering, the typical AI turn evaluates 80–400 nodes (not 1024), completes in under 50ms on a modern device, and plays at near-perfect strength. The AI panel's "Nodes Visited" and "Pruned" stats reflect this in real-time.

Game State Space: The total number of distinct TrapGrid positions is bounded by the number of ways to choose which cells are blocked, which are occupied, and who moves next — a massive combinatorial space. Minimax doesn't enumerate all of it; it only searches the sub-tree reachable from the current position, pruning aggressively. This is what makes depth-5 search practical in real-time.

Two-player zero-sum game Perfect information Combinatorial Deterministic NP-hard in general case PSPACE-complete (unbounded)