Case Study · Reinforcement Learning

Hybrid AI for Pac-Man
Capture the Flag

Symbolic PDDL planning on top, feature-based Q-learning underneath: an agent that beat UC Berkeley's baseline 8 out of 10 games.

80%Win rate vs Berkeley baseline
100%Win rate vs Staff team
2-layerPlanning + learning architecture
Pac-Man Capture the Flag gameplay

UC Berkeley Pac-Man Capture the Flag: two-vs-two, partial observability.

Download the full report (PDF)
Note on code. The contest framework carries an educational license that prohibits publishing solutions, so the agent code is kept in a private repository rather than posted publicly. It's available directly to employers on request. This page documents the design, iterations, and results.

The problem

Capture the Flag is a two-vs-two adversarial game: each team simultaneously raids the opponent's food and defends its own, under partial observability (exact enemy positions are only known when they're close; otherwise distances are noisy) and a hard per-move compute budget. A single fixed strategy loses. A strong agent has to keep re-deciding what it should be doing (grab food, bank it, chase an invader, grab a capsule, flee a ghost) and then execute that decision well. I wanted a design that cleanly separated high-level intent from low-level control so each could be improved on its own.

The approach: a two-layer hybrid

        ┌─────────────────────────────────────────────┐
        │  HIGH LEVEL - Symbolic PDDL planner           │
        │  game state → predicates → goal → plan         │
        │  attack · defend · go-home · patrol · flank    │
        └───────────────────────┬───────────────────────┘
                                │  chosen high-level action
        ┌───────────────────────▼───────────────────────┐
        │  LOW LEVEL - feature-based Q-learning          │
        │  Q(s,a) = Σ wᵢ·fᵢ(s,a), pick the best move      │
        │  offensive · escape · capsule · defensive       │
        └───────────────────────┬───────────────────────┘
                                │  concrete move (N/S/E/W/Stop)
                                ▼
                         Pac-Man game engine

High level: a PDDL planner decides what to do

Each tick, the raw game state is translated into logical predicates (a custom pacman_bool STRIPS domain) and planned over. The planner chooses among high-level actions:

Low level: Q-learning decides how to do it

Once a high-level action is chosen, a feature-based Q-learning controller picks the concrete move by scoring candidates as a linear combination of engineered features and learned weights, choosing the highest Q-value. Separate behaviours (offensive, escape, capsule, defensive, move-away) each have their own features and reward shaping.

Reinforcement learning details

Trained offensive weights (learned, not hand-set):

successorScore:           +26.2      # push up the score
chance-return-food:       +25.5      # carry food toward home
#-of-ghosts-1-step-away:   -3.7      # avoid stepping next to a ghost
closest-food:             -11.8      # don't dawdle near food without progressing
bias:                    -486        # baseline

These are interpretable and sensible: the agent learned to value scoring and safe food-return while avoiding ghosts.

Iterating on strategy

Approach 1: fixed roles

The first version hard-assigned one attack agent and one defense agent. It worked, but had real weaknesses: fixed roles caused idle downtime (an attacker with no nearby food, or a defender with no threat, wasted turns), and when both agents were eaten they respawned with no adaptive recovery, and the Berkeley baseline exploited those gaps to bank points.

Approach 2: a semi-defensive, "Kabaddi-inspired" strategy

To fix that, both agents default to a defensive stance in their own half, forming a hard-to-breach line, then opportunistically dart out to grab reachable food when it's safe before falling back, much like the raid-and-retreat rhythm of Kabaddi. This kept both agents useful at all times and reduced the downtime the baseline had been punishing.

Results

MatchupRecordWin rateNotes
vs Berkeley baseline8 / 1080%Consistent wins, narrow 1–4 pt margins
vs Staff team10 / 10100%Dominant, winning by 7–11 pts per game

Honest drawbacks

The biggest limitation was side-dependence: because I trained and tuned primarily on the red side under time constraints, the agent played noticeably better there (≈6/10) than when switched to blue (≈4/10). The learned weights didn't fully generalize across map orientations, a clear signal that the training regimen, not the architecture, was the bottleneck. Some later, more aggressive weight configurations also became numerically unstable during training, which reinforced the value of the stable, interpretable Approach-1 weights above.

What I'd do next

What I took away

Separating what from how was the design decision that made everything else tractable. I could change a strategic decision (fixed roles → semi-defensive) without retraining, and improve execution without touching the planning logic. And measuring against real opponents, not just intuition, is what surfaced the side-dependence problem and pointed clearly at what to fix next.

Tech

Python · PDDL (STRIPS planning) · Feature-based Q-learning (linear function approximation, TD updates, ε-greedy) · UC Berkeley Pac-Man Capture the Flag framework

Attribution. Built on the Pac-Man AI projects developed at UC Berkeley by John DeNero and Dan Klein (ai.berkeley.edu). Used for educational purposes; per the framework's license, solution code is not published. All agent design, the PDDL planning model, features, reward shaping, and strategy described here are my own work.