[add] Autoplay demo, web config, and WiFi AP.

This commit is contained in:
2026-03-06 09:53:53 +01:00
parent cea3cdad37
commit 8a776dfae5
7 changed files with 542 additions and 231 deletions
+85 -28
View File
@@ -1,38 +1,95 @@
# Connect Four
# Connect Four: ESP32-C3 LED Edition
Connect Four is a two player game played on a 7 by 6 grid. Each player has a color: one player is red, and the other player is yellow. The first player starts Connect Four by dropping one of their yellow discs into the (center) column of an empty game board. The two players then alternate turns dropping one of their discs at a time into an unfilled column, until the second player, with red discs, achieves a diagonal four in a row, and wins the game. If the board fills up before either player achieves four in a row, then the game is a draw.
A hardware-based Connect Four game featuring an 8x8 NeoPixel matrix, a strategic Minimax AI, and a dynamic "Attract Mode" for public display.
## Technical specifications
## How the Program Works
The game board is an 8 x 8 NeoPixel grid. To mark the limits of the board, the top row is off, in the row below the pixels are blue, and in the rightmost column's pixels are blue from the row below the empty row until the bottom row.
The game consists of a rotary encoder, using the Encoder.h library connected to pins:
```c++
#define ENCODER_A 2
#define ENCODER_B 3
#define ENCODER_SW 4
```
The program is built as a **Finite State Machine (FSM)**.
It manages the game flow by transitioning between distinct states based on user input, game outcomes, or inactivity timers.
The grid is managed using the FastLED.h library and is connected to:
```c++
#define LED_PIN 6
#define LED_WIDTH 8
#define LED_HEIGHT 8
#define NUM_LEDS (LED_WIDTH * LED_HEIGHT)
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
```
### 1. Game States
Players play by turning the rotary encoder to choose a column by rotating the encoder. When they press the button, the disc is dropped and falls to the lowest free position in the grid. If a column is full and a player tries to drop a disc, the disc at the top (column selection row) blinks, indicating that no disc can be dropped. If the player rotates the encoder to a non-full column, a disc can be played.
- **Menu**: Displays stylized Roman numerals (**I** or **II**) to select between Single Player or Two Player modes.
- **Game Play**: The main loop handles the real-time gravity of falling discs, encoder tracking for column selection, and the hand-off between the human and the AI.
- **Game Over**: Triggered when a win or draw is detected. It "locks" the board, dims the background discs to 15% intensity, and flashes the winning line.
- **Demo Mode**: Triggered after 60 seconds of inactivity. The AI plays against itself to act as a visual "attract mode."
A win is when one of the players achieves four connecting discs of the same color: horizontal, vertical, or diagonal. If a player wins, all the discs on the board a dimmed to 15% intensity, and the winning four discs are blinking at high intensity.
### 2. Win Detection Logic
If the board is full and none of the players win, a draw, then all the discs on the board are dimmed, and a blinking animation indicates a draw.
To ensure 100% accuracy, the program performs a synchronous, multi-directional scan of the 7x6 grid after every single move.
It checks for four matching non-zero values in the following patterns:
The game has four states:
1. Menu: Here the players choose the type of game they want to play, 1 or 2 player. This is indicated on the board by a single yellow vertical bar in the center column (single player versus computer) or two vertical bars: two player game. Rotating the encoder switches between game modes, and pressing the button selects the game mode.
2. Game play: Players are playing the game until one of the players connects four or they achieve a draw.
3. Game over: One of the players connects four, or they achieve a draw. If the rotary encoder button is pressed, this state switches to the Menu state.
4. Demo mode: The computer plays against itself. This mode is automatically triggered if there is no input for 60 seconds. If the rotary encoder is turned or pushed, the demo mode exits and the game returns to the menu state.
- **Horizontal**: `[column] [row]` to `[column + 3] [row]`
- **Vertical**: `[column] [row]` to `[column] [row + 3]`
- **Diagonal Up**: `[column] [row]` to `[column + 3] [row + 3]`
- **Diagonal Down**: `[column] [row]` to `[column + 3] [row - 3]`
The program initializes the SerialPrint output (baud 115200) and outputs useful (debugging) information regarding the game state and selections.
---
## The AI: Strategic Minimax
The computer opponent uses the **Minimax Algorithm**, a classic artificial intelligence method for zero-sum games.
### 1. Look-Ahead (Depth Search)
The AI does not just look at the current board; it simulates the game **6 to 8 moves into the future**.
It explores a "tree" of possibilities: _"If I play here, and the player plays there, then I can play here..."_
### 2. Alpha-Beta Pruning
Because searching millions of possibilities would be too slow for a microcontroller, we use **Alpha-Beta Pruning**.
This allows the AI to "prune" (ignore) branches of the game tree that are mathematically
guaranteed to be worse than moves it has already found, significantly speeding up the calculation.
### 3. Immediate Threat Reaction
To prevent the AI from being "distracted" by deep strategies while missing a simple win or loss,
we implemented a high-priority **Reaction Scanner**:
- **Kill Move**: If the AI can win in exactly one move, it takes it immediately.
- **Block Move**: If the player is one move away from winning (3-in-a-row), the AI identifies the threat and blocks it regardless of the Minimax score.
### 4. Controlled Randomness (Demo Mode)
To keep the Demo Mode interesting for spectators, the AI has a 25% chance to ignore the "perfect" move and pick a random column.
This ensures that every demo game is unique and not a repetitive loop of the same strategy.
---
## Technical Specifications
### Hardware Pins (Lolin C3 Mini)
| Component | Pin | Function |
| :---------- | :-- | :--------------------------------------- |
| **LED_PIN** | 4 | WS2812B NeoPixel Data |
| **ENC_A** | 0 | Rotary Encoder Phase A |
| **ENC_B** | 1 | Rotary Encoder Phase B |
| **ENC_SW** | 2 | Switch (Includes 50ms Software Debounce) |
### NeoPixel Grid Layout
The 8x8 matrix is mapped as follows:
- **Play Area**: 7 columns (0-6) by 6 rows (0-5).
- **Boundaries**: Row 1 and Column 7 are lit in **Blue** to mark the board limits.
- **Indicators**: The top-right pixel (7,0) pulses in the computer's color while it is "thinking."
- **Glowing Frame**: During Demo mode, the blue borders pulse with a white "glow" effect using a `beat8` sine wave to indicate autonomous play.
---
## Controls & Interaction
- **Rotate Encoder**: Move the cursor (top row) to select a column.
- **Press Encoder Button**: Drop a disc.
- **Full Column Warning**: If you attempt to play in a full column, the selection disc will blink rapidly, and the move will be ignored.
- **Reset**: After a game ends, press the button once to return to the Menu.
## Build Flags (platformio.ini)
Tweak the game performance without changing the source code:
- `IDLE_TIMEOUT`: Time (ms) before Demo Mode starts.
- `DEMO_RESET_PAUSE`: Delay (ms) between games in Demo Mode.
- `DEBOUNCE_DELAY`: Sensitivity of the encoder button.
- `BRIGHTNESS`: Global brightness of the NeoPixels.