3 Commits
Author SHA1 Message Date
mitchell 5ffc2b609b add support for modifed game 2026-04-10 13:38:14 -05:00
mitchell 3b2f8957e4 p2s2 2026-04-10 12:19:28 -05:00
mitchell 852939830c Namespace the steps 2026-04-10 11:14:15 -05:00
50 changed files with 773 additions and 330 deletions
+2 -2
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,
}; };
+1 -1
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
+95 -50
View File
@@ -13,19 +13,104 @@
#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"
bool play_modified;
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 +124,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();
} }
+2
View File
@@ -6,6 +6,8 @@
#include <cstddef> #include <cstddef>
extern bool play_modified;
constexpr size_t N_STEPS = 6; constexpr size_t N_STEPS = 6;
#endif /* MAIN_H */ #endif /* MAIN_H */
+12 -6
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"
) )
@@ -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
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 */
@@ -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;
@@ -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 */
@@ -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
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 */
@@ -1,4 +1,5 @@
#include "step4.h" #include "p001_step4.h"
#include "main.h"
__attribute__((unused)) __attribute__((unused))
static const char *TAG = "step4"; static const char *TAG = "step4";
@@ -233,8 +234,11 @@ bool play_game(int time, int required_score) {
target_score = required_score; target_score = required_score;
score = 0; score = 0;
update_score(); update_score();
if (!play_modified) {
set_module_time(time); set_module_time(time);
start_module_timer(); start_module_timer();
}
clear_board(); clear_board();
@@ -272,6 +276,7 @@ bool play_game(int time, int required_score) {
show_board(); show_board();
if (score >= required_score) { if (score >= required_score) {
if (!play_modified)
stop_module_timer(); stop_module_timer();
return true; return true;
} }
@@ -307,6 +312,7 @@ bool play_game(int time, int required_score) {
show_board(); show_board();
if (score >= required_score) { if (score >= required_score) {
if (!play_modified)
stop_module_timer(); stop_module_timer();
return true; return true;
} }
@@ -314,11 +320,12 @@ bool play_game(int time, int required_score) {
} }
} }
if (get_module_time() <= 0) { if ((!play_modified) && 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,6 +340,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);
if (!play_modified)
stop_module_timer(); stop_module_timer();
strike("Out of room"); strike("Out of room");
return false; return false;
@@ -379,7 +387,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...",
@@ -389,13 +397,16 @@ void step4() {
do_star_codes(&star_code, 1); do_star_codes(&star_code, 1);
init_screen(); init_screen();
while (!play_game(4*60*1000, 2)) fail(); int lines_1 = play_modified ? 2 : 2;
int lines_2 = play_modified ? 5 : 4;
int lines_3 = play_modified ? 12 : 8;
while (!play_game(4*60*1000, lines_1)) 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, lines_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(7*60*1000, 8)) fail(); while (!play_game(6*60*1000, lines_3)) 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();
@@ -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 */
+154 -150
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
@@ -178,7 +178,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 +651,8 @@ void step5(void) {
break; break;
} }
case 7: { case 7: {
lcd_print("What"); if (play_modified) {
set_module_time(TIME_WHAT); // do PLINK
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 +747,159 @@ void step5(void) {
if (!failed) { if (!failed) {
solved_correctly = true; solved_correctly = true;
} }
} else {
// do WHAT
lcd_print(1, 1, "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(2, 1, 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(2, 1, display_expression.c_str());
lcd_print(3, 1, entered_string.c_str());
}
if (get_module_time() <= 0) {
strike("Ran out of time!");
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
break;
}
default: {
ESP_LOGE(TAG, "Invalid puzzle number %d", puzzle);
}
} }
stop_module_timer(); stop_module_timer();
if (solved_correctly) { if (solved_correctly) {
@@ -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 */
@@ -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
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 */
+8
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
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
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
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 */
+8
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
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 */
+8
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
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 */
+8
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
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 */
+8
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
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 */
+36 -9
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,20 @@ static void replay_last() {
start_playback(); start_playback();
} }
static void do_p001() {
play_modified = false;
puzzle = 1;
}
static void do_p001_modified() {
play_modified = true;
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 +68,25 @@ void step0() {
StarCodeHandler star_codes[] = { StarCodeHandler star_codes[] = {
{ {
.code = "*9819", .code = "*9819",
.display_text = "Defusal Initiated", .display_text = "Start P001DH",
.should_exit = true, .should_exit = true,
.callback = nullptr, .callback = do_p001,
},
{
.code = "*9818",
.display_text = "Start P001DM",
.should_exit = true,
.callback = do_p001_modified,
},
{
.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,
}, },
+6 -6
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);
-15
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 */
-15
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 */
-12
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 */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.