# Connect Four Pico 2W Embedded Connect Four game with AI, running on a Raspberry Pi Pico 2W with a PicoResTouch-LCD-2.8 touchscreen (2.8" TFT + resistive touch). ## Build & Upload ```bash # Build pio run # Upload to board pio run --target upload # Monitor serial output pio device monitor ``` Requires PlatformIO CLI. The project uses the Arduino framework (earlephilhower core). ## Project Structure ``` src/ config.h — Pin definitions, layout constants, colors, game defaults game.h / .cpp — State enum, shared globals, board helpers, AI (minimax), game logic touch.h / .cpp — XPT2046 raw reads, touch events, calibration storage.h / .cpp — EEPROM persistence (calibration, settings, game log) display.h / .cpp — All TFT drawing (board, menu, status, settings UI, game log UI) main.cpp — setup(), loop(), state dispatch ``` Other files: - `platformio.ini` — Build configuration and tunable parameters - `connect_four.js` / `connect_four.html` — Browser edition (standalone, identical AI) - `README.md` — Technical and practical documentation - `Background information.md` — AI strategy explanation (accessible to all ages) ## Key Technical Details - **Hardware**: Raspberry Pi Pico 2W (RP2350), PicoResTouch-LCD-2.8 (ST7789 TFT 320x240, XPT2046 resistive touch) - **AI**: Minimax with alpha-beta pruning, three-phase move strategy (instant win/block, blunder, deep search) - **Display**: Adafruit_ST7789 + Adafruit_GFX via SPI1, portrait mode (240x320), dark theme matching the JS canvas implementation - **Touch**: Raw XPT2046 SPI reads (shared SPI1 bus with display). Calibration on first boot, stored in EEPROM. Hold touch during boot to recalibrate. - **Persistence**: Settings and game log stored in EEPROM (flash-backed). Survives reboots. - **Build flags**: Tunable game parameters defined as `-D` flags in `platformio.ini` - **Dependencies**: Adafruit ST7735/ST7789 Library, Adafruit GFX Library, EEPROM + SPI (built-in) ## Module Responsibilities - **config.h**: Constants only. No state, no functions. All pin defs, layout, colors, defaults. - **game.h/cpp**: Owns all shared globals (`board`, `gameState`, `tft`, etc.) as extern/definitions. Board helpers, scanBoard, evaluateBoard, minimax, computeAiMove. - **touch.h/cpp**: Owns touch calibration globals. readRawTouch, getTouchDown, colFromTouch, menuItemFromTouch, calibrateTouch. - **storage.h/cpp**: EEPROM layout defines. save/load for calibration, settings, game log. logGame, clearGameLog. - **display.h/cpp**: All drawing. drawCell, drawBoardFull, drawMenu, drawSettings, drawGameLogScreen, animateDrop. Settings/game log touch handlers. - **main.cpp**: setup, loop, state handlers (startGame, returnToMenu, startDemo, handleAiTurn, handleDemoStep, handleFlash). ## Conventions - **Naming**: camelCase for all variables and functions - **Game states**: Use enum names (`MENU`, `PLAYING`, `AI_TURN`, `FINISHED_WIN`, `FINISHED_DRAW`, `DEMO`, `SETTINGS`, `GAME_LOG`), never magic numbers - **Player colors**: Use `playerColor(player)` helper, never inline color constants directly - **Board reset**: Use `resetBoard()`, never bare `memset(board, 0, sizeof(board))` - **Column priority**: Use the shared `colOrder[]` constant, never duplicate `{3, 2, 4, 1, 5, 0, 6}` - **Duplicate logic**: The win/draw/log check is handled by `checkGameEnd()` — do not duplicate this pattern - **Colors**: RGB565 constants prefixed with `C_`, derived from the JS canvas palette via the `C565(r,g,b)` macro ## Display Layout (portrait 240x320) - Cell size: 32px, disc radius: 13px - Board origin: (8, 56), board size: 224x192 - Column numbers at y=44, status text at y=254, sub-status at y=278 - Board background with rounded corners, grid lines between cells, circular discs in cells ## Demo Mode Demo uses asymmetric ply depths (`demoPly[0]` and `demoPly[1]`) randomized at each demo game start via `randomizeDemoPlies()`. This ensures games produce winners rather than draws while still looking strategic. ## Game Log - Stored as `GameEntry` structs (type, level, winner, moves), not as formatted strings - Persisted to EEPROM after each game via `saveGameLog()` / `loadGameLog()` - Viewable on-device via Settings > View Game Log (paginated, newest first) - Max entries configurable via `MAX_GAME_LOG` build flag - Player wins highlighted in red ## Settings Menu Accessible from the main menu (4th item). Allows adjusting: - AI Ply depth (1-10) - Blunder mode ON/OFF - Blunder chance (5-100%, step 5) - View Game Log (paginated, with clear option) - Recalibrate touch screen Settings are persisted to EEPROM on exit. ## EEPROM Layout - Offset 0: Touch calibration magic + data (9 bytes) - Offset 9: Settings magic + lookAhead, blunderEnabled, blunderChance, gameLogCount (5+1 bytes) - Offset 16+: Game log entries (46 bytes each) ## Commit Style Follow the existing pattern: `[type] Description.` where type is `fix`, `update`, `add`, or `refactor`.