902 lines
38 KiB
C++
902 lines
38 KiB
C++
#include "step5.h"
|
|
|
|
#define TIME_CLEAR 30'000
|
|
#define TIME_PLANK 40'000
|
|
#define TIME_EMPTY 40'000
|
|
#define TIME_NOTHING 25'000
|
|
#define TIME_BLINK 35'000
|
|
#define TIME_UMMM 35'000
|
|
#define TIME_BLANK 40'000
|
|
#define TIME_WHAT 60'000
|
|
#define TIME_PLINK 40'000
|
|
|
|
__attribute__((unused))
|
|
static const char *TAG = "step5";
|
|
|
|
static const int TIMES_TO_SOLVE = 9;
|
|
|
|
static std::random_device rd;
|
|
static std::mt19937 gen(rd());
|
|
static std::uniform_int_distribution<> puzzle_dist(0, 7);
|
|
static std::uniform_int_distribution<> led_picker_dist(0, 20);
|
|
static std::uniform_int_distribution<> led_color_dist(0, 5);
|
|
|
|
void set_unique_leds(std::vector<int>& input_options, const int num, const int r, const int g, const int b) {
|
|
for (int i = 0; i < num; i++) {
|
|
std::uniform_int_distribution<> led_option_dist(0, input_options.size() - 1);
|
|
int led = led_option_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, input_options[led], r, g, b));
|
|
input_options.erase(input_options.begin() + led);
|
|
}
|
|
}
|
|
|
|
void set_unique_leds_random_color(std::vector<int>& input_options, const int num, const int* r, const int* g, const int* b) {
|
|
for (int i = 0; i < num; i++) {
|
|
std::uniform_int_distribution<> led_option_dist(0, input_options.size() - 1);
|
|
int led = led_option_dist(gen);
|
|
|
|
std::uniform_int_distribution<> led_color_dist(0, sizeof(r) - 1);
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, input_options[led], r[color], g[color], b[color]));
|
|
input_options.erase(input_options.begin() + led);
|
|
}
|
|
}
|
|
|
|
std::vector<int> unique_values(std::vector<int>& input_options, int num) {
|
|
std::vector<int> output_vec;
|
|
for (int i = 0; i < num; i++) {
|
|
std::uniform_int_distribution<> option_num_dist(0, input_options.size() - 1);
|
|
int option_num = option_num_dist(gen);
|
|
output_vec.push_back(input_options[option_num]);
|
|
input_options.erase(input_options.begin() + option_num);
|
|
}
|
|
return output_vec;
|
|
}
|
|
|
|
bool submit_0(int green_indicators) {
|
|
uint8_t state = get_switch_state();
|
|
uint8_t flipped_state = 0;
|
|
flipped_state |= (state & 0b1) << 3;
|
|
flipped_state |= (state & 0b10) << 1;
|
|
flipped_state |= (state & 0b100) >> 1;
|
|
flipped_state |= (state & 0b1000) >> 3;
|
|
|
|
if (flipped_state == green_indicators) {
|
|
return true;
|
|
} else {
|
|
strike("Incorrect Switches");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool submit_1(int num_indicators, std::string pressed_keys, uint8_t starting_switch_state) {
|
|
if (num_indicators < 18) {
|
|
if (get_switch_state() == 0b1111) {
|
|
if (pressed_keys == "") {
|
|
return true;
|
|
} else {
|
|
strike("Incorrect keypad!");
|
|
return false;
|
|
}
|
|
} else {
|
|
strike("Incorrect switches!");
|
|
return false;
|
|
}
|
|
} else {
|
|
if (starting_switch_state == get_switch_state()) {
|
|
if (pressed_keys == "ADCB") {
|
|
return true;
|
|
} else {
|
|
strike("Incorrect keypad!");
|
|
return false;
|
|
}
|
|
} else {
|
|
strike("Switches changed!");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool submit_2(bool* lit_leds, int green_pressed, int blue_pressed, int fingerprint_pressed, std::string keypad_string) {
|
|
uint8_t switch_state = get_switch_state() & 0b11;
|
|
|
|
bool rfid_correct = (lit_leds[0] && (green_pressed == 1)) || (!lit_leds[0] && (green_pressed == 0));
|
|
ESP_LOGI(TAG, "rfid_correct: %i", rfid_correct);
|
|
bool lcd_correct = (lit_leds[1] && (blue_pressed == 1)) || (!lit_leds[1] && (blue_pressed == 0));
|
|
ESP_LOGI(TAG, "lcd_correct: %i", lcd_correct);
|
|
bool speaker_correct = (lit_leds[2] && (fingerprint_pressed == 2)) || (!lit_leds[2] && (fingerprint_pressed == 0));
|
|
ESP_LOGI(TAG, "speaker_correct: %i", speaker_correct);
|
|
bool keypad_correct = (lit_leds[3] && (keypad_string == "12")) || (!lit_leds[3] && (keypad_string == ""));
|
|
ESP_LOGI(TAG, "keypad_correct: %i", keypad_correct);
|
|
bool tft_correct = (lit_leds[4] && (switch_state == 0b11)) || !lit_leds[4];
|
|
ESP_LOGI(TAG, "tft_correct: %i", tft_correct);
|
|
|
|
if (rfid_correct && lcd_correct && speaker_correct && keypad_correct && tft_correct) {
|
|
return true;
|
|
} else {
|
|
strike("Incorrect state!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool submit_4(int* button_colors, int* switch_colors, uint8_t initial_switch_state) {
|
|
if (button_colors[0] == 0 && button_colors[1] == 1 && button_colors[2] == 2 && button_colors[3] == 3) {
|
|
uint8_t switch_state = get_switch_state();
|
|
bool correct = true;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (switch_colors[i] == 2) {
|
|
if ((((switch_state ^ initial_switch_state) >> i) & 0b1) != 1) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
} else {
|
|
if (((switch_state >> i) & 0b1) != (switch_colors[i] & 0b1)) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (correct) {
|
|
return true;
|
|
}
|
|
strike("Incorrect switches!");
|
|
return false;
|
|
} else {
|
|
strike("Incorrect buttons!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool submit_5(std::array<int, 4> indicator_numbers, std::array<int, 4> buttons_pressed) {
|
|
if (buttons_pressed != indicator_numbers) {
|
|
ESP_LOGI(TAG, "Button State: %i, %i, %i, %i, Indicator Numbers: %i, %i, %i, %i", buttons_pressed[0], buttons_pressed[1], buttons_pressed[2], buttons_pressed[3], indicator_numbers[0], indicator_numbers[1], indicator_numbers[2], indicator_numbers[3]);
|
|
strike("Wrong button state!");
|
|
return false;
|
|
}
|
|
|
|
uint8_t switch_state = get_switch_state();
|
|
for (int i = 0; i < 4; i++) {
|
|
ESP_LOGI(TAG, "Switch State: %i, Indicator Number: %i", ((switch_state >> i) & 0b1), indicator_numbers[i]);
|
|
if (((switch_state >> i) & 0b1) == (indicator_numbers[i] & 0b1)) {
|
|
strike("Wrong switch state!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool submit_6(bool* buttons_cycling, bool button_turned_on, int led_off) {
|
|
for (int i = 0; i < sizeof(buttons_cycling); i++) {
|
|
if ((buttons_cycling[i] == true) || (button_turned_on == false && led_off != -1)) {
|
|
strike("Incorrect!");
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void step5(void) {
|
|
StarCodeHandler star_codes[] = {
|
|
{
|
|
.code = "*2648",
|
|
.display_text = "Starting...",
|
|
.should_exit = true,
|
|
.callback = nullptr,
|
|
},
|
|
};
|
|
int len = sizeof(star_codes)/sizeof(StarCodeHandler);
|
|
do_star_codes(star_codes, len);
|
|
|
|
std::vector<int> all_leds;
|
|
|
|
for (int i = 0; i < 21; i++) {
|
|
all_leds.push_back(i);
|
|
}
|
|
|
|
const int INDICATOR_RED[6] = {20, 0, 0, 10, 10, 5};
|
|
const int INDICATOR_GREEN[6] = {0, 0, 10, 5, 0, 7};
|
|
const int INDICATOR_BLUE[6] = {0, 10, 0, 0, 5, 5};
|
|
static std::uniform_int_distribution<> led_number_dist(0, 21);
|
|
|
|
int last_cycle_tick = xTaskGetTickCount();
|
|
int scrambled_times = 0;
|
|
while (scrambled_times < 5) {
|
|
if ((xTaskGetTickCount() - last_cycle_tick) > pdMS_TO_TICKS(100)) {
|
|
clean_bomb();
|
|
std::vector<int> led_options = all_leds;
|
|
set_unique_leds_random_color(led_options, led_number_dist(gen), INDICATOR_RED, INDICATOR_GREEN, INDICATOR_BLUE);
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
last_cycle_tick = xTaskGetTickCount();
|
|
scrambled_times++;
|
|
}
|
|
}
|
|
|
|
clean_bomb();
|
|
int solved_puzzles = 0;
|
|
while (solved_puzzles < TIMES_TO_SOLVE) {
|
|
lcd_set_cursor(&lcd, 1, 1);
|
|
bool solved_correctly = false;
|
|
|
|
int puzzle = puzzle_dist(gen);
|
|
// int puzzle = 2;
|
|
|
|
switch (puzzle) {
|
|
case 0: {
|
|
lcd_print(&lcd, "Clear");
|
|
set_module_time(TIME_CLEAR);
|
|
start_module_timer();
|
|
|
|
std::vector<int> indicator_options = all_leds;
|
|
|
|
// set green
|
|
std::uniform_int_distribution<> green_indicators_dist(1, 15);
|
|
uint8_t green_indicators = green_indicators_dist(gen);
|
|
set_unique_leds(indicator_options, green_indicators, 0, 10, 0);
|
|
|
|
// set non-green
|
|
const int NON_GREEN_INDICATOR_RED[3] = {20, 0, 10};
|
|
const int NON_GREEN_INDICATOR_GREEN[3] = {0, 0, 0};
|
|
const int NON_GREEN_INDICATOR_BLUE[3] = {0, 10, 5};
|
|
std::uniform_int_distribution<> non_green_indicators_dist(0, (20 - green_indicators));
|
|
set_unique_leds_random_color(indicator_options, non_green_indicators_dist(gen), NON_GREEN_INDICATOR_RED, NON_GREEN_INDICATOR_GREEN, NON_GREEN_INDICATOR_BLUE);
|
|
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
// wait for submit
|
|
KeypadKey key;
|
|
while (1) {
|
|
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
|
|
solved_correctly = submit_0(green_indicators);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 1: {
|
|
lcd_print(&lcd, "Blank");
|
|
set_module_time(TIME_BLANK);
|
|
start_module_timer();
|
|
|
|
std::uniform_int_distribution<> on_indicators_dist(16, 21);
|
|
uint8_t indicators_num = on_indicators_dist(gen);
|
|
|
|
std::vector<int> indicator_options = all_leds;
|
|
const int INDICATOR_RED[6] = {20, 0, 0, 10, 10, 5};
|
|
const int INDICATOR_GREEN[6] = {0, 0, 10, 5, 0, 7};
|
|
const int INDICATOR_BLUE[6] = {0, 10, 0, 0, 5, 5};
|
|
|
|
set_unique_leds_random_color(indicator_options, indicators_num, INDICATOR_RED, INDICATOR_BLUE, INDICATOR_GREEN);
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
uint8_t starting_switch_state = get_switch_state();
|
|
std::string pressed_keys;
|
|
|
|
KeypadKey key;
|
|
while (1) {
|
|
if (get_pressed_keypad(&key)) {
|
|
char keypad_char = char_of_keypad_key(key);
|
|
if (keypad_char == '#') {
|
|
solved_correctly = submit_1(indicators_num, pressed_keys, starting_switch_state);
|
|
break;
|
|
} else {
|
|
pressed_keys += char_of_keypad_key(key);
|
|
}
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
solved_correctly = submit_1(indicators_num, pressed_keys, starting_switch_state);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
set_module_time(TIME_EMPTY);
|
|
start_module_timer();
|
|
|
|
std::map<int, int> idx_to_led_map = {
|
|
{0, 10},
|
|
{1, 12},
|
|
{2, 9},
|
|
{3, 11},
|
|
{4, 6},
|
|
};
|
|
|
|
std::uniform_int_distribution<> lit_led_dist(0, 1);
|
|
|
|
// rfid, lcd, speaker, keypad, tft
|
|
bool lit_leds[5] = {static_cast<bool>(lit_led_dist(gen)), static_cast<bool>(lit_led_dist(gen)), static_cast<bool>(lit_led_dist(gen)), static_cast<bool>(lit_led_dist(gen)), static_cast<bool>(lit_led_dist(gen))};
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
if (lit_leds[i]) {
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, idx_to_led_map[i], INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
|
|
}
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
int green_button_pressed = 0;
|
|
int blue_button_pressed = 0;
|
|
int fingerprint_sensor_pressed = 0;
|
|
std::string keypad_string;
|
|
|
|
KeypadKey key;
|
|
ButtonKey button;
|
|
|
|
while (1) {
|
|
if (get_pressed_button(&button)) {
|
|
uint8_t button_state = get_button_state();
|
|
|
|
if ((button_state & 0b1) == 0b1) {
|
|
green_button_pressed++;
|
|
if ((green_button_pressed > 1) || !lit_leds[0]) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
if ((button_state & 0b1000) == 0b1000) {
|
|
blue_button_pressed++;
|
|
if ((blue_button_pressed > 1) || !lit_leds[1]) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (get_touch_pressed()) {
|
|
fingerprint_sensor_pressed++;
|
|
// ESP_LOGI(TAG, "touch sensor pressed");
|
|
if ((fingerprint_sensor_pressed > 2) || !lit_leds[2]) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
if (get_pressed_keypad(&key)) {
|
|
char keypad_char = char_of_keypad_key(key);
|
|
if (keypad_char == '#') {
|
|
solved_correctly = submit_2(lit_leds, green_button_pressed, blue_button_pressed, fingerprint_sensor_pressed, keypad_string);
|
|
break;
|
|
} else {
|
|
// ESP_LOGI(TAG, "pressed %c", char_of_keypad_key(key));
|
|
keypad_string += char_of_keypad_key(key);
|
|
}
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
solved_correctly = submit_2(lit_leds, green_button_pressed, blue_button_pressed, fingerprint_sensor_pressed, keypad_string);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 3: {
|
|
lcd_print(&lcd, "Nothing");
|
|
set_module_time(TIME_NOTHING);
|
|
start_module_timer();
|
|
|
|
const int COLOR_RED[5] = {0, 20, 10, 0};
|
|
const int COLOR_GREEN[5] = {20, 0, 10, 0};
|
|
const int COLOR_BLUE[5] = {0, 0, 0, 20};
|
|
|
|
static std::uniform_int_distribution<> color_dist(0, 3);
|
|
|
|
int tft_color = color_dist(gen);
|
|
int speaker_color = color_dist(gen);
|
|
int s3_color = color_dist(gen);
|
|
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 6, COLOR_RED[tft_color], COLOR_GREEN[tft_color], COLOR_BLUE[tft_color]));
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 9, COLOR_RED[speaker_color], COLOR_GREEN[speaker_color], COLOR_BLUE[speaker_color]));
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 14, COLOR_RED[s3_color], COLOR_GREEN[s3_color], COLOR_BLUE[s3_color]));
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
int buttons_pressed = 0;
|
|
|
|
ButtonKey button;
|
|
while (1) {
|
|
if (get_pressed_button(&button)) {
|
|
buttons_pressed++;
|
|
uint8_t button_state = get_button_state();
|
|
|
|
if (buttons_pressed == 1) {
|
|
if ((button_state >> tft_color) != 0b1) {
|
|
strike("Wrong button!");
|
|
break;
|
|
}
|
|
} else if (buttons_pressed == 2) {
|
|
if ((button_state >> speaker_color) != 0b1) {
|
|
strike("Wrong button!");
|
|
break;
|
|
}
|
|
} else if (buttons_pressed == 3) {
|
|
if ((button_state >> s3_color) != 0b1) {
|
|
strike("Wrong button!");
|
|
} else {
|
|
solved_correctly = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
strike("Ran out of time!");
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
lcd_print(&lcd, "Blink");
|
|
set_module_time(TIME_BLINK);
|
|
start_module_timer();
|
|
|
|
// buttons
|
|
const int BUTTON_COLOR_RED[4] = {0, 20, 10, 0};
|
|
const int BUTTON_COLOR_GREEN[4] = {10, 0, 5, 0};
|
|
const int BUTTON_COLOR_BLUE[4] = {0, 0, 0, 10};
|
|
|
|
static std::uniform_int_distribution<> button_color_dist(0, 3);
|
|
int button_colors[4] = {button_color_dist(gen), button_color_dist(gen), button_color_dist(gen), button_color_dist(gen)};
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), BUTTON_COLOR_RED[button_colors[i]], BUTTON_COLOR_GREEN[button_colors[i]], BUTTON_COLOR_BLUE[button_colors[i]]));
|
|
}
|
|
|
|
// switches
|
|
const int SWITCH_COLOR_RED[3] = {20, 0, 10};
|
|
const int SWITCH_COLOR_GREEN[3] = {0, 10, 5};
|
|
|
|
static std::uniform_int_distribution<> switch_color_dist(0, 2);
|
|
|
|
int switch_colors[4] = {switch_color_dist(gen), switch_color_dist(gen), switch_color_dist(gen), switch_color_dist(gen)};
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (16 - i), SWITCH_COLOR_RED[switch_colors[i]], SWITCH_COLOR_GREEN[switch_colors[i]], 0));
|
|
}
|
|
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
ButtonKey button;
|
|
KeypadKey key;
|
|
uint8_t starting_switch_state = get_switch_state();
|
|
|
|
while (1) {
|
|
if (get_pressed_button(&button)) {
|
|
uint8_t button_state = get_button_state();
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (((button_state >> i) & 0b1) == 0b1) {
|
|
button_colors[i]++;
|
|
if (button_colors[i] > 3) {
|
|
button_colors[i] = 0;
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), BUTTON_COLOR_RED[button_colors[i]], BUTTON_COLOR_GREEN[button_colors[i]], BUTTON_COLOR_BLUE[button_colors[i]]));
|
|
}
|
|
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
}
|
|
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
|
|
solved_correctly = submit_4(button_colors, switch_colors, starting_switch_state);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
break;
|
|
}
|
|
case 5: {
|
|
lcd_print(&lcd, "Ummm");
|
|
set_module_time(TIME_UMMM);
|
|
start_module_timer();
|
|
|
|
std::uniform_int_distribution<> indicator_number_dist(0, 5);
|
|
|
|
const int INDICATOR_RED[4] = {0, 20, 10, 0};
|
|
const int INDICATOR_GREEN[4] = {10, 0, 5, 0};
|
|
const int INDICATOR_BLUE[4] = {0, 0, 0, 10};
|
|
|
|
// green, red, yellow, blue
|
|
std::array<int, 4> indicator_numbers = {indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen)};
|
|
std::vector<int> indicator_options = all_leds;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
set_unique_leds(indicator_options, indicator_numbers[i], INDICATOR_RED[i], INDICATOR_GREEN[i], INDICATOR_BLUE[i]);
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
std::array<int, 4> buttons_pressed = {0, 0, 0, 0};
|
|
ButtonKey button;
|
|
KeypadKey key;
|
|
|
|
while (1) {
|
|
if (get_pressed_button(&button)) {
|
|
uint8_t button_state = get_button_state();
|
|
bool failed = false;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (((button_state >> i) & 0b1) == 0b1) {
|
|
buttons_pressed[i]++;
|
|
if (buttons_pressed[i] > indicator_numbers[i]) {
|
|
strike("Too many times!");
|
|
failed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (failed) {
|
|
break;
|
|
}
|
|
}
|
|
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
|
|
ESP_LOGI(TAG, "Keypad Char: %c, time: %lu", char_of_keypad_key(key), get_module_time());
|
|
solved_correctly = submit_5(indicator_numbers, buttons_pressed);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 6: {
|
|
lcd_print(&lcd, "Plank");
|
|
set_module_time(TIME_PLANK);
|
|
start_module_timer();
|
|
|
|
std::uniform_int_distribution<> led_color_dist(0, 5);
|
|
std::uniform_int_distribution<> led_off_dist(-1, 3);
|
|
|
|
// red, purple, blue, white, green, yellow
|
|
const uint8_t COLORS_RED[6] = {20, 10, 0, 5, 0, 10};
|
|
const uint8_t COLORS_GREEN[6] = {0, 0, 0, 7, 10, 5};
|
|
const uint8_t COLORS_BLUE[6] = {0, 10, 10, 5, 0, 0};
|
|
|
|
int button_colors[4];
|
|
bool buttons_cycling[4];
|
|
int led_off = led_off_dist(gen);
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (led_off != i) {
|
|
button_colors[i] = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), COLORS_RED[button_colors[i]], COLORS_GREEN[button_colors[i]], COLORS_BLUE[button_colors[i]]));
|
|
buttons_cycling[i] = true;
|
|
} else {
|
|
button_colors[i] = -1;
|
|
buttons_cycling[i] = false;
|
|
}
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
const uint8_t CORRECT_COLORS[4] = {4, 0, 5, 2};
|
|
TickType_t lastCycleTime = xTaskGetTickCount();
|
|
bool button_turned_on = false;
|
|
|
|
ButtonKey button;
|
|
KeypadKey key;
|
|
|
|
std::uniform_int_distribution<> led_turn_on_dist(0, 3);
|
|
while (1) {
|
|
if (get_pressed_button(&button)) {
|
|
uint8_t button_state = get_button_state();
|
|
bool failed = false;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (((button_state >> i) & 0b1) == 0b1) {
|
|
if (button_colors[i] == -1) {
|
|
if (button_turned_on) {
|
|
strike("Pressed after on!");
|
|
failed = true;
|
|
break;
|
|
} else if (led_turn_on_dist(gen) == 0) {
|
|
button_turned_on = true;
|
|
led_strip_set_pixel(leds, (20 - i), COLORS_RED[CORRECT_COLORS[i]], COLORS_GREEN[CORRECT_COLORS[i]], COLORS_BLUE[CORRECT_COLORS[i]]);
|
|
led_strip_refresh(leds);
|
|
}
|
|
} else if (button_colors[i] != CORRECT_COLORS[i]) {
|
|
strike("Wrong time!");
|
|
failed = true;
|
|
break;
|
|
} else {
|
|
buttons_cycling[i] = false;
|
|
}
|
|
}
|
|
}
|
|
if (failed) {
|
|
break;
|
|
}
|
|
}
|
|
if ((xTaskGetTickCount() - lastCycleTime) >= pdMS_TO_TICKS(500)) {
|
|
for (int i = 0; i < 4; i++) {
|
|
if (buttons_cycling[i]) {
|
|
button_colors[i]++;
|
|
if (button_colors[i] > 5) {
|
|
button_colors[i] = 0;
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), COLORS_RED[button_colors[i]], COLORS_GREEN[button_colors[i]], COLORS_BLUE[button_colors[i]]));
|
|
}
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
lastCycleTime = xTaskGetTickCount();
|
|
}
|
|
get_pressed_keypad(&key);
|
|
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
|
|
solved_correctly = submit_6(buttons_cycling, button_turned_on, led_off);
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
break;
|
|
}
|
|
case 7: {
|
|
lcd_print(&lcd, "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_set_cursor(&lcd, 1, 2);
|
|
lcd_print(&lcd, display_expression.c_str());
|
|
|
|
// set LEDs
|
|
|
|
// blue, red, green, yellow
|
|
const int INDICATOR_RED[4] = {0, 20, 0, 10};
|
|
const int INDICATOR_GREEN[4] = {0, 0, 10, 5};
|
|
const int INDICATOR_BLUE[4] = {10, 0, 0, 0};
|
|
|
|
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], INDICATOR_RED[i], INDICATOR_GREEN[i], INDICATOR_BLUE[i]);
|
|
}
|
|
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
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_pressed_keypad(&key)) {
|
|
if (key == KeypadKey::star) {
|
|
// clear
|
|
entered_string = "";
|
|
} else if (key == KeypadKey::pound) {
|
|
// submit
|
|
if (entered_string != answer_string) {
|
|
strike("Incorrect answer!");
|
|
break;
|
|
} else {
|
|
solved_correctly = true;
|
|
}
|
|
break;
|
|
} else {
|
|
entered_string += char_of_keypad_key(key);
|
|
}
|
|
|
|
lcd_clear(&lcd);
|
|
lcd_set_cursor(&lcd, 1, 1);
|
|
lcd_print(&lcd, "What");
|
|
lcd_set_cursor(&lcd, 1, 2);
|
|
lcd_print(&lcd, display_expression.c_str());
|
|
lcd_set_cursor(&lcd, 1, 3);
|
|
lcd_print(&lcd, 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(&lcd, "Plink");
|
|
set_module_time(TIME_PLINK);
|
|
start_module_timer();
|
|
|
|
std::uniform_int_distribution<> indicator_number_dist(0, 4);
|
|
|
|
// ESP_LOGI(TAG, "Green: %i, Red: %i, Yellow: %i, Blue: %i", green_indicators, red_indicators, yellow_indicators, blue_indicators);
|
|
|
|
// green, red, yellow, blue, purple
|
|
const int INDICATOR_RED[5] = {0, 20, 10, 0, 10};
|
|
const int INDICATOR_GREEN[5] = {10, 0, 5, 0, 0};
|
|
const int INDICATOR_BLUE[5] = {0, 0, 0, 10, 5};
|
|
|
|
int solved_times = 0;
|
|
bool failed = false;
|
|
while (solved_times < 3 && !failed) {
|
|
int indicator_numbers[5] = {indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen)};
|
|
|
|
std::vector<int> led_options = all_leds;
|
|
for (int i = 0; i < 5; i++) {
|
|
set_unique_leds(led_options, indicator_numbers[i], INDICATOR_RED[i], INDICATOR_GREEN[i], INDICATOR_BLUE[i]);
|
|
}
|
|
|
|
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
std::uniform_int_distribution<> answer_color_dist(0, 4);
|
|
|
|
std::map<int, std::string> color_name_map = {
|
|
{0, "Green"},
|
|
{1, "Red"},
|
|
{2, "Yellow"},
|
|
{3, "Blue"},
|
|
{4, "Purple"},
|
|
};
|
|
|
|
int answer_color = answer_color_dist(gen);
|
|
|
|
std::string color_string = color_name_map[answer_color];
|
|
std::string answer_num = std::to_string(indicator_numbers[answer_color]);
|
|
|
|
// ESP_LOGI(TAG, "color string: %s", color_string.c_str());
|
|
|
|
lcd_set_cursor(&lcd, 1, 2);
|
|
lcd_print(&lcd, color_string.c_str());
|
|
|
|
std::string entered_string;
|
|
|
|
KeypadKey key;
|
|
while (1) {
|
|
if (get_pressed_keypad(&key)) {
|
|
bool failed = false;
|
|
|
|
if (key == KeypadKey::star) {
|
|
// clear
|
|
entered_string = "";
|
|
} else if (key == KeypadKey::pound) {
|
|
// submit
|
|
if (entered_string != answer_num) {
|
|
strike("Incorrect answer!");
|
|
failed = true;
|
|
} else {
|
|
solved_correctly = true;;
|
|
}
|
|
break;
|
|
} else {
|
|
entered_string += char_of_keypad_key(key);
|
|
}
|
|
|
|
if (failed) {
|
|
break;
|
|
}
|
|
|
|
lcd_clear(&lcd);
|
|
lcd_set_cursor(&lcd, 1, 1);
|
|
lcd_print(&lcd, "Plink");
|
|
lcd_set_cursor(&lcd, 1, 2);
|
|
lcd_print(&lcd, color_string.c_str());
|
|
lcd_set_cursor(&lcd, 1, 3);
|
|
lcd_print(&lcd, entered_string.c_str());
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
strike("Ran out of time!");
|
|
break;
|
|
}
|
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
if (!failed) {
|
|
solved_correctly = true;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
stop_module_timer();
|
|
if (solved_correctly) {
|
|
solved_puzzles++;
|
|
play_raw(MOUNT_POINT "/correct.pcm");
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
solved_correctly = false;
|
|
} else {
|
|
vTaskDelay(pdMS_TO_TICKS(3000));
|
|
}
|
|
clear_all_pressed_released();
|
|
clean_bomb();
|
|
}
|
|
}
|