#include "p002_step2.h" #include "helper.h" #include #include #include __attribute__((unused)) static const char *TAG = "step2"; 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(); }