Compare commits

...

2 Commits

Author SHA1 Message Date
3b2f8957e4 p2s2 2026-04-10 12:19:28 -05:00
852939830c Namespace the steps 2026-04-10 11:14:15 -05:00
33 changed files with 569 additions and 303 deletions

View File

@ -26,8 +26,8 @@ enum class Button: uint8_t {
B3 = 2, B3 = 2,
B4 = 3, B4 = 3,
GREEN = 0, GREEN = 0,
YELLOW = 1, RED = 1,
RED = 2, YELLOW = 2,
BLUE = 3, BLUE = 3,
}; };

View File

@ -1,6 +1,7 @@
#ifndef SD_H #ifndef SD_H
#define SD_H #define SD_H
#include "main.h"
#include <string.h> #include <string.h>
#include <sys/unistd.h> #include <sys/unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -15,7 +16,6 @@ extern sdmmc_card_t *card;
#define SD_PIN_CLK GPIO_NUM_39 #define SD_PIN_CLK GPIO_NUM_39
#define SD_PIN_CMD GPIO_NUM_40 #define SD_PIN_CMD GPIO_NUM_40
#define SD_PIN_D0 GPIO_NUM_38 #define SD_PIN_D0 GPIO_NUM_38
#define SD_PIN_D1 GPIO_NUM_45
#define SD_PIN_D2 GPIO_NUM_42 #define SD_PIN_D2 GPIO_NUM_42
#define SD_PIN_D3 GPIO_NUM_41 #define SD_PIN_D3 GPIO_NUM_41

View File

@ -13,19 +13,102 @@
#include "helper.h" #include "helper.h"
#include "steps/step0.h" #include "steps/step0.h"
#include "steps/step1.h" #include "steps/p001_step1.h"
#include "steps/step2.h" #include "steps/p001_step2.h"
#include "steps/step3.h" #include "steps/p001_step3.h"
#include "steps/step4.h" #include "steps/p001_step4.h"
#include "steps/step5.h" #include "steps/p001_step5.h"
#include "steps/step6.h" #include "steps/p001_step6.h"
#include "steps/p002_step1.h"
#include "steps/p002_step2.h"
#include "steps/p002_step3.h"
#include "steps/p002_step4.h"
#include "steps/p002_step5.h"
#include "steps/p002_step6.h"
static const char *TAG = "main"; static const char *TAG = "main";
uint32_t initial_game_time = 90*60*1000 + 1000; uint32_t initial_game_time = 90*60*1000 + 1000;
uint32_t skip_to_step = 0; uint32_t skip_to_step = 0;
uint32_t current_step = 0; uint32_t current_step = 0;
uint32_t puzzle = 0;
extern uint32_t total_strikes; extern uint32_t total_strikes;
static void do_p001() {
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) p001_step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) p001_step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) p001_step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) p001_step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) p001_step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) p001_step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
}
static void do_p002() {
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) p002_step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) p002_step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) p002_step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) p002_step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) p002_step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) p002_step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
}
extern "C" void app_main(void) { extern "C" void app_main(void) {
printf("app_main\n"); printf("app_main\n");
@ -39,49 +122,9 @@ extern "C" void app_main(void) {
clean_bomb(); clean_bomb();
step0(); step0();
// set_recording_source(stdout, false); if (puzzle == 1) {
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "w"); do_p001();
if (record_file == nullptr) { } else {
ESP_LOGE("main", "failed to open record.txt"); do_p002();
} }
set_recording_source(record_file, true);
start_recording();
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
stop_recording();
} }

View File

@ -1,12 +1,18 @@
set(SOURCES set(SOURCES
"setup_wires.cpp" "setup_wires.cpp"
"step0.cpp" "step0.cpp"
"step1.cpp" "p001_step1.cpp"
"step2.cpp" "p001_step2.cpp"
"step3.cpp" "p001_step3.cpp"
"step4.cpp" "p001_step4.cpp"
"step5.cpp" "p001_step5.cpp"
"step6.cpp" "p001_step6.cpp"
"p002_step1.cpp"
"p002_step2.cpp"
"p002_step3.cpp"
"p002_step4.cpp"
"p002_step5.cpp"
"p002_step6.cpp"
"wires_puzzle.cpp" "wires_puzzle.cpp"
) )

View File

@ -1,4 +1,4 @@
#include "step1.h" #include "p001_step1.h"
__attribute__((unused)) __attribute__((unused))
static const char *TAG = "step1"; static const char *TAG = "step1";
@ -276,7 +276,7 @@ static bool play_part(uint32_t time) {
return true; return true;
} }
void step1(void) { void p001_step1(void) {
while (get_switch_flipped(nullptr)); while (get_switch_flipped(nullptr));
init_step(); init_step();

10
main/steps/p001_step1.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef P001_STEP_1_H
#define P001_STEP_1_H
#include <random>
#include "../drivers/all.h"
#include "../helper.h"
void p001_step1(void);
#endif /* P001_STEP_1_H */

View File

@ -1,4 +1,4 @@
#include "step2.h" #include "p001_step2.h"
__attribute__((unused)) __attribute__((unused))
static const char *TAG = "step2"; static const char *TAG = "step2";
@ -91,7 +91,7 @@ static void new_puzzle(void) {
set_module_sseg_raw(display_map); set_module_sseg_raw(display_map);
} }
void step2(void) { void p001_step2(void) {
KeypadKey key; KeypadKey key;
int solved_times = 0; int solved_times = 0;

View File

@ -1,5 +1,5 @@
#ifndef STEP_2_H #ifndef P001_STEP_2_H
#define STEP_2_H #define P001_STEP_2_H
#include "../drivers/bottom_half.h" #include "../drivers/bottom_half.h"
#include "../drivers/wires.h" #include "../drivers/wires.h"
@ -11,6 +11,6 @@
#include <random> #include <random>
#include <map> #include <map>
void step2(void); void p001_step2(void);
#endif /* STEP_2_H */ #endif /* P001_STEP_2_H */

View File

@ -1,4 +1,4 @@
#include "step3.h" #include "p001_step3.h"
#define ONE_SECOND_TIME 90'000 #define ONE_SECOND_TIME 90'000
#define THREE_SECOND_TIME 90'000 #define THREE_SECOND_TIME 90'000
@ -63,7 +63,7 @@ static bool one_second();
static bool three_second(); static bool three_second();
static bool six_second(); static bool six_second();
void step3(void) { void p001_step3(void) {
StarCodeHandler star_codes[] = { StarCodeHandler star_codes[] = {
{ {
.code = "*1642", .code = "*1642",

10
main/steps/p001_step3.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef P001_STEP_3_H
#define P001_STEP_3_H
#include <random>
#include "../drivers/all.h"
#include "../helper.h"
void p001_step3(void);
#endif /* P001_STEP_3_H */

View File

@ -1,4 +1,4 @@
#include "step4.h" #include "p001_step4.h"
__attribute__((unused)) __attribute__((unused))
static const char *TAG = "step4"; static const char *TAG = "step4";
@ -233,8 +233,8 @@ bool play_game(int time, int required_score) {
target_score = required_score; target_score = required_score;
score = 0; score = 0;
update_score(); update_score();
set_module_time(time); // set_module_time(time);
start_module_timer(); // start_module_timer();
clear_board(); clear_board();
@ -272,7 +272,7 @@ bool play_game(int time, int required_score) {
show_board(); show_board();
if (score >= required_score) { if (score >= required_score) {
stop_module_timer(); // stop_module_timer();
return true; return true;
} }
} }
@ -307,18 +307,19 @@ bool play_game(int time, int required_score) {
show_board(); show_board();
if (score >= required_score) { if (score >= required_score) {
stop_module_timer(); // stop_module_timer();
return true; return true;
} }
} }
} }
} }
if (get_module_time() <= 0) { // if (get_module_time() <= 0) {
stop_module_timer(); // stop_module_timer();
strike("Out of time"); // strike("Out of time");
return false; // return false;
} // }
// if (get_switch_flipped(&switch_)) { // if (get_switch_flipped(&switch_)) {
// printf("%d\n", piece); // printf("%d\n", piece);
// for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) { // for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
@ -333,7 +334,7 @@ bool play_game(int time, int required_score) {
// game over // game over
ESP_LOGI(TAG, "Game Over. Score: %d", score); ESP_LOGI(TAG, "Game Over. Score: %d", score);
stop_module_timer(); // stop_module_timer();
strike("Out of room"); strike("Out of room");
return false; return false;
} }
@ -379,7 +380,7 @@ static void fail() {
} }
} }
void step4() { void p001_step4() {
StarCodeHandler star_code = { StarCodeHandler star_code = {
.code = "*3850", .code = "*3850",
.display_text = "Starting...", .display_text = "Starting...",
@ -392,10 +393,10 @@ void step4() {
while (!play_game(4*60*1000, 2)) fail(); while (!play_game(4*60*1000, 2)) fail();
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0); play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
complete(); complete();
while (!play_game(4*60*1000, 4)) fail(); while (!play_game(4*60*1000, 5)) fail();
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0); play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
complete(); complete();
while (!play_game(7*60*1000, 8)) fail(); while (!play_game(7*60*1000, 12)) fail();
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0); play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
complete(); complete();

View File

@ -1,5 +1,5 @@
#ifndef STEP_4_H #ifndef P001_STEP_4_H
#define STEP_4_H #define P001_STEP_4_H
#include <random> #include <random>
#include "../drivers/tft.h" #include "../drivers/tft.h"
@ -13,6 +13,6 @@
#define TETRIS_USE_FLASH_IMG #define TETRIS_USE_FLASH_IMG
#define TETRIS_USE_FLASH_BG_IMG #define TETRIS_USE_FLASH_BG_IMG
void step4(void); void p001_step4(void);
#endif /* STEP_4_H */ #endif /* P001_STEP_4_H */

View File

@ -1,4 +1,4 @@
#include "step5.h" #include "p001_step5.h"
#define TIME_CLEAR 30'000 #define TIME_CLEAR 30'000
#define TIME_PLANK 40'000 #define TIME_PLANK 40'000
@ -7,7 +7,6 @@
#define TIME_BLINK 35'000 #define TIME_BLINK 35'000
#define TIME_UMMM 35'000 #define TIME_UMMM 35'000
#define TIME_BLANK 40'000 #define TIME_BLANK 40'000
#define TIME_WHAT 60'000
#define TIME_PLINK 40'000 #define TIME_PLINK 40'000
__attribute__((unused)) __attribute__((unused))
@ -178,7 +177,7 @@ bool submit_6(bool* buttons_cycling, bool button_turned_on, int led_off) {
return true; return true;
} }
void step5(void) { void p001_step5(void) {
StarCodeHandler star_codes[] = { StarCodeHandler star_codes[] = {
{ {
.code = "*2648", .code = "*2648",
@ -651,154 +650,6 @@ void step5(void) {
break; break;
} }
case 7: { case 7: {
lcd_print("What");
set_module_time(TIME_WHAT);
start_module_timer();
std::uniform_int_distribution<> math_number_dist(1, 9);
std::vector<float> math_numbers;
std::vector<int> math_operations;
std::map<int, char> operation_map = {
{0, '+'},
{1, '-'},
{2, '*'},
{3, '/'},
};
int expression_answer = -1;
std::string display_expression;
while (expression_answer < 0) {
math_numbers = {static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen))};
std::vector<int> possible_math_operations = {0, 1, 2, 3};
math_operations = unique_values(possible_math_operations, 3);
display_expression = std::to_string(static_cast<int>(math_numbers[0]));
for (int i = 0; i < 3; i++) {
display_expression += operation_map[math_operations[i]];
display_expression += std::to_string(static_cast<int>(math_numbers[i + 1]));
}
// Solve
for (int j = 0; j < 3; j++) {
bool found = false;
for (int i = 0; i < math_operations.size(); i++) {
if (math_operations[i] == 2) {
// ESP_LOGI(TAG, "i = %i, condensing %f * %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] * math_numbers[i+1]));
math_numbers[i] = math_numbers[i] * math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
} else if (math_operations[i] == 3) {
// ESP_LOGI(TAG, "i = %i, condensing %f / %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] / math_numbers[i+1]));
math_numbers[i] = math_numbers[i] / math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
}
}
if (found) continue;
for (int i = 0; i < math_operations.size(); i++) {
if (math_operations[i] == 0) {
// ESP_LOGI(TAG, "i = %i, condensing %f + %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] + math_numbers[i+1]));
math_numbers[i] = math_numbers[i] + math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
} else if (math_operations[i] == 1) {
// ESP_LOGI(TAG, "i = %i, condensing %f - %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] - math_numbers[i+1]));
math_numbers[i] = math_numbers[i] - math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
}
}
}
expression_answer = static_cast<int>(std::floor(math_numbers[0]));
}
// display expression
lcd_print(1, 2, display_expression.c_str());
// set LEDs
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
};
std::uniform_int_distribution<> add_sub_indicator_dist(1, 6);
std::uniform_int_distribution<> mult_div_indicator_dist(1, 3);
int modifier_indicators[4] = {add_sub_indicator_dist(gen), add_sub_indicator_dist(gen), mult_div_indicator_dist(gen), mult_div_indicator_dist(gen)};
while ((((expression_answer + (modifier_indicators[0] * 3) - modifier_indicators[1]) * std::pow(3, modifier_indicators[2])) / std::pow(2, modifier_indicators[3])) < 0) {
modifier_indicators[0] = add_sub_indicator_dist(gen);
modifier_indicators[1] = add_sub_indicator_dist(gen);
modifier_indicators[2] = mult_div_indicator_dist(gen);
modifier_indicators[3] = mult_div_indicator_dist(gen);
}
expression_answer += modifier_indicators[0] * 3;
expression_answer -= modifier_indicators[1];
expression_answer *= std::pow(3, modifier_indicators[2]);
expression_answer /= std::pow(2, modifier_indicators[3]);
std::vector<int> led_options = all_leds;
for (int i = 0; i < 4; i++) {
set_unique_leds(led_options, modifier_indicators[i], COLORS[i]);
}
leds_flush();
std::string answer_string = std::to_string(expression_answer);
std::string entered_string = "";
ESP_LOGI(TAG, "Solved full answer: %s", answer_string.c_str());
KeypadKey key;
while (1) {
if (get_keypad_pressed(&key)) {
if (key == KeypadKey::star) {
// clear
entered_string = "";
} else if (key == KeypadKey::pound) {
// submit
if (entered_string != answer_string) {
strike("Incorrect answer!");
} else {
solved_correctly = true;
}
break;
} else {
entered_string += char_of_keypad_key(key);
}
lcd_clear();
lcd_print(1, 1, "What");
lcd_print(1, 2, display_expression.c_str());
lcd_print(1, 3, entered_string.c_str());
}
if (get_module_time() <= 0) {
strike("Ran out of time!");
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
break;
}
case 8: {
lcd_print("Plink"); lcd_print("Plink");
set_module_time(TIME_PLINK); set_module_time(TIME_PLINK);
start_module_timer(); start_module_timer();
@ -893,9 +744,11 @@ void step5(void) {
if (!failed) { if (!failed) {
solved_correctly = true; solved_correctly = true;
} }
break;
}
default: {
ESP_LOGE(TAG, "Invalid puzzle number %d", puzzle);
} }
} }
stop_module_timer(); stop_module_timer();
if (solved_correctly) { if (solved_correctly) {

View File

@ -1,5 +1,5 @@
#ifndef STEP_5_H #ifndef P001_STEP_5_H
#define STEP_5_H #define P001_STEP_5_H
#include "../drivers/bottom_half.h" #include "../drivers/bottom_half.h"
#include "../drivers/game_timer.h" #include "../drivers/game_timer.h"
@ -15,6 +15,6 @@
#include <cmath> #include <cmath>
#include <array> #include <array>
void step5(void); void p001_step5(void);
#endif /* STEP_5_H */ #endif /* P001_STEP_5_H */

View File

@ -1,11 +1,11 @@
#include "step6.h" #include "p001_step6.h"
__attribute__((unused)) __attribute__((unused))
static const char *TAG = "step6"; static const char *TAG = "step6";
static uint8_t cut_wires = 0; static uint8_t cut_wires = 0;
void step6(void) { void p001_step6(void) {
get_cut_wires(); get_cut_wires();
clear_all_pressed_released(); clear_all_pressed_released();

10
main/steps/p001_step6.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef P001_STEP_6_H
#define P001_STEP_6_H
#include "wires_puzzle.h"
#include "../drivers/all.h"
#include "../helper.h"
void p001_step6(void);
#endif /* P001_STEP_6_H */

View File

@ -0,0 +1,8 @@
#include "p002_step1.h"
__attribute__((unused))
static const char *TAG = "step1";
void p002_step1(void) {
// TODO: implement step 1
}

8
main/steps/p002_step1.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_1_H
#define P002_STEP_1_H
#include "../drivers/all.h"
void p002_step1(void);
#endif /* P002_STEP_1_H */

272
main/steps/p002_step2.cpp Normal file
View File

@ -0,0 +1,272 @@
#include "p002_step2.h"
#include "helper.h"
#include <cstdio>
#include <cstring>
#include <random>
__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<int> 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();
}

8
main/steps/p002_step2.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_2_H
#define P002_STEP_2_H
#include "../drivers/all.h"
void p002_step2(void);
#endif /* P002_STEP_2_H */

View File

@ -0,0 +1,8 @@
#include "p002_step3.h"
__attribute__((unused))
static const char *TAG = "step3";
void p002_step3(void) {
// TODO: implement step 3
}

8
main/steps/p002_step3.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_3_H
#define P002_STEP_3_H
#include "../drivers/all.h"
void p002_step3(void);
#endif /* P002_STEP_3_H */

View File

@ -0,0 +1,8 @@
#include "p002_step4.h"
__attribute__((unused))
static const char *TAG = "step4";
void p002_step4(void) {
// TODO: implement step 4
}

8
main/steps/p002_step4.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_4_H
#define P002_STEP_4_H
#include "../drivers/all.h"
void p002_step4(void);
#endif /* P002_STEP_4_H */

View File

@ -0,0 +1,8 @@
#include "p002_step5.h"
__attribute__((unused))
static const char *TAG = "step5";
void p002_step5(void) {
// TODO: implement step 5
}

8
main/steps/p002_step5.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_5_H
#define P002_STEP_5_H
#include "../drivers/all.h"
void p002_step5(void);
#endif /* P002_STEP_5_H */

View File

@ -0,0 +1,8 @@
#include "p002_step6.h"
__attribute__((unused))
static const char *TAG = "step6";
void p002_step6(void) {
// TODO: implement step 6
}

8
main/steps/p002_step6.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_6_H
#define P002_STEP_6_H
#include "../drivers/all.h"
void p002_step6(void);
#endif /* P002_STEP_6_H */

View File

@ -5,6 +5,7 @@ static const char* TAG = "step0";
extern uint32_t initial_game_time; extern uint32_t initial_game_time;
extern uint32_t skip_to_step; extern uint32_t skip_to_step;
extern uint32_t puzzle;
static void set_game_time(); static void set_game_time();
static void skip_to_step1() { skip_to_step = 1; } static void skip_to_step1() { skip_to_step = 1; }
@ -13,12 +14,12 @@ static void skip_to_step3() { skip_to_step = 3; }
static void skip_to_step4() { skip_to_step = 4; } static void skip_to_step4() { skip_to_step = 4; }
static void skip_to_step5() { skip_to_step = 5; } static void skip_to_step5() { skip_to_step = 5; }
static void skip_to_step6() { skip_to_step = 6; } static void skip_to_step6() { skip_to_step = 6; }
static void try_step1() { clean_bomb(); step1(); } static void try_step1() { clean_bomb(); p001_step1(); }
static void try_step2() { clean_bomb(); step2(); } static void try_step2() { clean_bomb(); p001_step2(); }
static void try_step3() { clean_bomb(); step3(); } static void try_step3() { clean_bomb(); p001_step3(); }
static void try_step4() { clean_bomb(); step4(); } static void try_step4() { clean_bomb(); p001_step4(); }
static void try_step5() { clean_bomb(); step5(); } static void try_step5() { clean_bomb(); p001_step5(); }
static void try_step6() { clean_bomb(); step6(); } static void try_step6() { clean_bomb(); p001_step6(); }
static void issue_strike() { strike("Strike Issued"); } static void issue_strike() { strike("Strike Issued"); }
static void flashbang(); static void flashbang();
static void debug_switches(); static void debug_switches();
@ -45,6 +46,14 @@ static void replay_last() {
start_playback(); start_playback();
} }
static void do_p001() {
puzzle = 1;
}
static void do_p002() {
puzzle = 2;
}
/// Wait for "*9819" /// Wait for "*9819"
void step0() { void step0() {
led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE); led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE);
@ -53,13 +62,19 @@ void step0() {
StarCodeHandler star_codes[] = { StarCodeHandler star_codes[] = {
{ {
.code = "*9819", .code = "*9819",
.display_text = "Defusal Initiated", .display_text = "Start P001",
.should_exit = true, .should_exit = true,
.callback = nullptr, .callback = do_p001,
},
{
.code = "*3141",
.display_text = "Start P002",
.should_exit = true,
.callback = do_p002,
}, },
{ {
.code = "*59861", .code = "*59861",
.display_text = "Set Up Wires", .display_text = "Setup Wires",
.should_exit = false, .should_exit = false,
.callback = setup_wires, .callback = setup_wires,
}, },

View File

@ -8,12 +8,12 @@
#include "setup_wires.h" #include "setup_wires.h"
#include "../helper.h" #include "../helper.h"
#include "step1.h" #include "p001_step1.h"
#include "step2.h" #include "p001_step2.h"
#include "step3.h" #include "p001_step3.h"
#include "step4.h" #include "p001_step4.h"
#include "step5.h" #include "p001_step5.h"
#include "step6.h" #include "p001_step6.h"
/// Wait for "*9819" /// Wait for "*9819"
void step0(void); void step0(void);

View File

@ -1,15 +0,0 @@
#ifndef STEP_1_H
#define STEP_1_H
#include <random>
#include "../drivers/bottom_half.h"
#include "../drivers/tft.h"
#include "../drivers/leds.h"
#include "../drivers/wires.h"
#include "../drivers/speaker.h"
#include "../drivers/game_timer.h"
#include "../drivers/char_lcd.h"
void step1(void);
#endif /* STEP_1_H */

View File

@ -1,15 +0,0 @@
#ifndef STEP_3_H
#define STEP_3_H
#include <random>
#include "../drivers/bottom_half.h"
#include "../drivers/wires.h"
#include "../drivers/speaker.h"
#include "../drivers/leds.h"
#include "../drivers/char_lcd.h"
#include "../drivers/game_timer.h"
#include "../helper.h"
void step3(void);
#endif /* STEP_3_H */

View File

@ -1,12 +0,0 @@
#ifndef STEP_6_H
#define STEP_6_H
#include "wires_puzzle.h"
#include "drivers/wires.h"
#include "drivers/bottom_half.h"
#include "drivers/sd.h"
#include "drivers/speaker.h"
void step6(void);
#endif /* STEP_6_H */