4.9 KiB
4.9 KiB
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
# 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 parametersconnect_four.js/connect_four.html— Browser edition (standalone, identical AI)README.md— Technical and practical documentationBackground 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
-Dflags inplatformio.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 barememset(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 theC565(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
GameEntrystructs (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_LOGbuild 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.