From 3b2f8957e479cb9f1c299c0d0bcb1563f0692d84 Mon Sep 17 00:00:00 2001 From: Mitchell M Date: Fri, 10 Apr 2026 12:19:28 -0500 Subject: [PATCH] p2s2 --- main/drivers/inputs.hpp | 4 +- main/drivers/sd.h | 2 +- main/steps/p002_step2.cpp | 268 +++++++++++++++++++++++++++++++++++++- 3 files changed, 269 insertions(+), 5 deletions(-) diff --git a/main/drivers/inputs.hpp b/main/drivers/inputs.hpp index 5d4306a..231f694 100644 --- a/main/drivers/inputs.hpp +++ b/main/drivers/inputs.hpp @@ -26,8 +26,8 @@ enum class Button: uint8_t { B3 = 2, B4 = 3, GREEN = 0, - YELLOW = 1, - RED = 2, + RED = 1, + YELLOW = 2, BLUE = 3, }; diff --git a/main/drivers/sd.h b/main/drivers/sd.h index ea2b706..cfd89fe 100644 --- a/main/drivers/sd.h +++ b/main/drivers/sd.h @@ -1,6 +1,7 @@ #ifndef SD_H #define SD_H +#include "main.h" #include #include #include @@ -15,7 +16,6 @@ extern sdmmc_card_t *card; #define SD_PIN_CLK GPIO_NUM_39 #define SD_PIN_CMD GPIO_NUM_40 #define SD_PIN_D0 GPIO_NUM_38 -#define SD_PIN_D1 GPIO_NUM_45 #define SD_PIN_D2 GPIO_NUM_42 #define SD_PIN_D3 GPIO_NUM_41 diff --git a/main/steps/p002_step2.cpp b/main/steps/p002_step2.cpp index 523d9bb..fdcc109 100644 --- a/main/steps/p002_step2.cpp +++ b/main/steps/p002_step2.cpp @@ -1,8 +1,272 @@ #include "p002_step2.h" +#include "helper.h" +#include +#include +#include __attribute__((unused)) static const char *TAG = "step2"; -void p002_step2(void) { - // TODO: implement step 2 +static const uint8_t BOARD_COUNT = 9; +static const uint8_t BOARD_SIZE = 6; +static const uint8_t PART_SHOTS[3] = {20, 15, 12}; +static const char *PART_LABELS[3] = {"Alpha", "Bravo", "Charlie"}; +static const char ROW_LABELS[BOARD_SIZE] = {'A', 'B', 'C', 'D', 'E', 'F'}; + +static std::random_device random_device; +static std::mt19937 random_engine(random_device()); +static std::uniform_int_distribution random_board(0, BOARD_COUNT - 1); + +static const uint8_t ALL_BOARDS[BOARD_COUNT][BOARD_SIZE][BOARD_SIZE] = { + { + {0,0,0,0,0,0}, + {0,0,1,1,1,1}, + {0,1,0,0,0,0}, + {0,1,0,1,1,0}, + {0,1,0,0,0,0}, + {0,0,0,1,0,0}, + }, + { + {0,1,0,0,0,0}, + {0,1,0,1,1,0}, + {0,1,0,0,0,0}, + {0,0,0,1,0,0}, + {0,0,0,0,0,0}, + {1,1,1,1,0,0}, + }, + { + {0,0,1,1,1,1}, + {0,1,0,0,0,0}, + {0,1,0,0,0,0}, + {0,1,0,0,0,0}, + {0,0,1,0,0,0}, + {1,0,1,0,0,0}, + }, + { + {1,0,0,0,0,0}, + {1,0,0,0,0,0}, + {1,0,0,0,0,1}, + {1,0,0,0,0,1}, + {0,0,0,0,1,0}, + {0,1,1,1,0,0}, + }, + { + {1,1,0,1,0,0}, + {0,0,0,1,0,0}, + {0,1,0,1,0,0}, + {0,0,0,0,0,0}, + {0,1,1,1,1,0}, + {0,0,0,0,0,0}, + }, + { + {0,0,1,0,1,0}, + {1,0,1,0,1,0}, + {0,0,1,0,1,0}, + {0,0,1,0,0,0}, + {0,0,0,0,0,0}, + {1,1,0,0,0,0}, + }, + { + {0,0,0,0,0,1}, + {1,1,0,0,0,0}, + {0,0,0,0,1,0}, + {1,1,1,0,1,0}, + {0,0,0,0,1,0}, + {0,0,0,0,1,0}, + }, + { + {0,1,1,0,0,0}, + {0,0,0,0,1,0}, + {0,0,0,0,1,0}, + {0,0,1,0,1,0}, + {0,0,0,0,0,0}, + {1,1,1,1,0,0}, + }, + { + {0,0,0,0,0,0}, + {1,0,0,0,0,0}, + {0,1,0,0,1,1}, + {0,1,0,1,0,0}, + {0,1,0,1,0,0}, + {0,1,0,1,0,0}, + }, +}; + +static bool row_from_button_state(uint8_t state, uint8_t *row) { + switch (state) { + case 0b1100: *row = 0; return true; // B1 + B2 -> A + case 0b1010: *row = 1; return true; // B1 + B3 -> B + case 0b1001: *row = 2; return true; // B1 + B4 -> C + case 0b0110: *row = 3; return true; // B2 + B3 -> D + case 0b0101: *row = 4; return true; // B2 + B4 -> E + case 0b0011: *row = 5; return true; // B3 + B4 -> F + default: return false; + } +} + +static bool column_from_switch_state(uint8_t state, uint8_t *col) { + uint8_t value = state & 0xF; + if (value >= 1 && value <= 6) { + *col = value - 1; + return true; + } + return false; +} + +static int count_ship_segments(const uint8_t board[BOARD_SIZE][BOARD_SIZE]) { + int count = 0; + for (uint8_t row = 0; row < BOARD_SIZE; ++row) { + for (uint8_t col = 0; col < BOARD_SIZE; ++col) { + if (board[row][col] == 1) { + ++count; + } + } + } + return count; +} + +static void copy_board(uint8_t dest[BOARD_SIZE][BOARD_SIZE], const uint8_t src[BOARD_SIZE][BOARD_SIZE]) { + memcpy(dest, src, BOARD_SIZE * BOARD_SIZE); +} + +static void render_status(const char *part_name, + int shots_left, + int hits, + int misses, + int row, + int col, + const char *info) { + char line0[21] = {0}; + char line1[21] = {0}; + char line2[21] = {0}; + char line3[21] = {0}; + + snprintf(line0, sizeof(line0), "%s Shots:%2d", part_name, shots_left); + if (row >= 0 && col >= 0) { + snprintf(line1, sizeof(line1), "Row %c Col %d", ROW_LABELS[row], col + 1); + } else { + snprintf(line1, sizeof(line1), "Row - Col -"); + } + snprintf(line2, sizeof(line2), "Hits:%2d Misses:%2d", hits, misses); + snprintf(line3, sizeof(line3), "%s", info); + + lcd_clear(); + lcd_print(0, 0, line0); + lcd_print(0, 1, line1); + lcd_print(0, 2, line2); + lcd_print(0, 3, line3); +} + +void p002_step2(void) { + clean_bomb(); + + for (int part = 0; part < 3; ++part) { + const char *part_name = PART_LABELS[part]; + const int max_shots = PART_SHOTS[part]; + bool completed = false; + + while (!completed) { + uint8_t board[BOARD_SIZE][BOARD_SIZE]; + copy_board(board, ALL_BOARDS[random_board(random_engine)]); + + int shots_taken = 0; + int hits = 0; + int misses = 0; + int current_row = -1; + int current_col = -1; + const char *status = "Hold 2 buttons + set switches"; + + render_status(part_name, max_shots - shots_taken, hits, misses, -1, -1, status); + clean_bomb(); + + while (true) { + uint8_t button_state = get_button_state(); + uint8_t switch_state = get_switch_state(); + uint8_t row = 0; + uint8_t col = 0; + bool row_valid = row_from_button_state(button_state, &row); + bool col_valid = column_from_switch_state(switch_state, &col); + + if (row_valid) { + current_row = row; + } else { + current_row = -1; + } + if (col_valid) { + current_col = col; + } else { + current_col = -1; + } + + KeypadKey key; + if (get_keypad_pressed(&key)) { + if (key == KeypadKey::k5) { + if (!row_valid) { + status = "Invalid row selection"; + } else if (!col_valid) { + status = "Invalid column value"; + } else { + uint8_t cell = board[row][col]; + if (cell == 2 || cell == 3) { + status = "Already fired there"; + } else { + shots_taken += 1; + if (cell == 1) { + board[row][col] = 3; + hits += 1; + status = "Hit!"; + led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_RED); + } else { + board[row][col] = 2; + misses += 1; + status = "Miss!"; + led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_WHITE); + } + leds_flush(); + vTaskDelay(pdMS_TO_TICKS(250)); + led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_OFF); + leds_flush(); + } + } + } + } + + render_status(part_name, + max_shots - shots_taken, + hits, + misses, + current_row, + current_col, + status); + + if (count_ship_segments(board) == 0) { + completed = true; + break; + } + + if (shots_taken >= max_shots) { + strike("Out of shots!"); + status = "Out of shots! Retry"; + render_status(part_name, + 0, + hits, + misses, + current_row, + current_col, + status); + vTaskDelay(pdMS_TO_TICKS(2000)); + break; + } + + vTaskDelay(pdMS_TO_TICKS(50)); + } + } + + if (part < 2) + play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0); + clean_bomb(); + } + + play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0); + lcd_clear(); }