962 lines
42 KiB
C++
962 lines
42 KiB
C++
#include "step5.h"
|
|
|
|
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;
|
|
}
|
|
|
|
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 < ) {
|
|
lcd_set_cursor(&lcd, 1, 1);
|
|
|
|
int puzzle = puzzle_dist(gen);
|
|
// int puzzle = 6;
|
|
|
|
bool solved_correctly = false;
|
|
switch (puzzle) {
|
|
case 0: {
|
|
lcd_print(&lcd, "Clear");
|
|
set_module_time(30000);
|
|
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] = {30, 0, 15};
|
|
const int NON_GREEN_INDICATOR_GREEN[3] = {0, 0, 0};
|
|
const int NON_GREEN_INDICATOR_BLUE[3] = {0, 30, 15};
|
|
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 time
|
|
while (1) {
|
|
if (get_module_time() <= 0) {
|
|
uint8_t state = get_switch_state();
|
|
uint8_t flipped_state = 0;
|
|
flipped_state |= (state & 0x01) << 3;
|
|
flipped_state |= (state & 0x02) << 1;
|
|
flipped_state |= (state & 0x04) >> 1;
|
|
flipped_state |= (state & 0x08) >> 3;
|
|
|
|
if (flipped_state == green_indicators) {
|
|
solved_puzzles++;
|
|
} else {
|
|
strike("Incorrect Switches");
|
|
}
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 1: {
|
|
lcd_print(&lcd, "Blank");
|
|
set_module_time(40000);
|
|
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));
|
|
// ESP_LOGI(TAG, "puzzle 1 LEDs set (%i leds)", indicators_num);
|
|
|
|
if (indicators_num < 18) {
|
|
while (1) {
|
|
if (get_module_time() <= 0) {
|
|
if (get_switch_state() == 0b1111) {
|
|
solved_puzzles++;
|
|
// ESP_LOGI(TAG, "puzzle 1 solved (switches)!");
|
|
} else {
|
|
strike("Switch State Changed");
|
|
}
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
} else {
|
|
uint8_t starting_switch_state = get_switch_state();
|
|
KeypadKey key;
|
|
std::string pressed_keys;
|
|
while (1) {
|
|
if (get_pressed_keypad(&key)) {
|
|
pressed_keys += char_of_keypad_key(key);
|
|
// ESP_LOGI(TAG, "key %c pressed", char_of_keypad_key(key));
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
if (starting_switch_state == get_switch_state()) {
|
|
if (pressed_keys == "ADCB") {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
// ESP_LOGI(TAG, "puzzle 1 solved (keypad)!");
|
|
}
|
|
} else {
|
|
strike("Switches Changed!");
|
|
}
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
}
|
|
case 2: {
|
|
set_module_time(25000);
|
|
start_module_timer();
|
|
|
|
std::uniform_int_distribution<> lit_led_dist(0, 1);
|
|
bool rfid_lit = lit_led_dist(gen);
|
|
bool lcd_lit = lit_led_dist(gen);
|
|
bool speaker_lit = lit_led_dist(gen);
|
|
bool keypad_lit = lit_led_dist(gen);
|
|
bool tft_lit = lit_led_dist(gen);
|
|
|
|
if (rfid_lit) {
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 10, INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
|
|
}
|
|
if (lcd_lit) {
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 12, INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
|
|
}
|
|
if (speaker_lit) {
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 9, INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
|
|
}
|
|
if (keypad_lit) {
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 11, INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
|
|
}
|
|
if (tft_lit) {
|
|
int color = led_color_dist(gen);
|
|
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 6, INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
|
|
}
|
|
ESP_ERROR_CHECK(led_strip_refresh(leds));
|
|
|
|
int green_button_pressed = 0;
|
|
// ESP_LOGI(TAG, "green pressed: %i", green_button_pressed);
|
|
int blue_button_pressed = 0;
|
|
int fingerprint_sensor_pressed = 0;
|
|
std::string keypad_string;
|
|
|
|
ButtonKey button;
|
|
KeypadKey key;
|
|
SwitchKey switch1 = s1;
|
|
SwitchKey switch2 = s2;
|
|
|
|
while (1) {
|
|
if (get_pressed_button(&button)) {
|
|
uint8_t button_state = get_button_state();
|
|
// ESP_LOGI(TAG, "Button pressed! (%i)", button_state());
|
|
|
|
if ((button_state & 0b1) == 0b1) {
|
|
green_button_pressed++;
|
|
if ((green_button_pressed > 1) || !rfid_lit) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
if ((button_state & 0b1000) == 0b1000) {
|
|
blue_button_pressed++;
|
|
if ((blue_button_pressed > 1) || !lcd_lit) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (get_touch_pressed()) {
|
|
fingerprint_sensor_pressed++;
|
|
if ((fingerprint_sensor_pressed > 2) || !speaker_lit) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
if (get_pressed_keypad(&key)) {
|
|
bool wrong = false;
|
|
keypad_string += char_of_keypad_key(key);
|
|
switch (keypad_string.length()) {
|
|
case 1: {
|
|
if (keypad_string != "1") {
|
|
strike("Incorrect Keypad!");
|
|
wrong = true;
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
if (keypad_string != "12") {
|
|
strike("Incorrect Keypad!");
|
|
wrong = true;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
strike("Incorrect Keypad!");
|
|
wrong = true;
|
|
break;
|
|
}
|
|
}
|
|
if (wrong) {
|
|
break;
|
|
}
|
|
}
|
|
if (get_flipped_up_switch(&switch1) || get_flipped_up_switch(&switch2)) {
|
|
if (!tft_lit) {
|
|
strike("Incorrect Switches");
|
|
break;
|
|
}
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
bool rfid_correct = !(rfid_lit && (green_button_pressed != 1));
|
|
bool lcd_correct = !(lcd_lit && (blue_button_pressed != 1));
|
|
bool speaker_correct = !(speaker_lit && (fingerprint_sensor_pressed != 2));
|
|
bool keypad_correct = !(keypad_lit && (keypad_string != "12"));
|
|
bool tft_correct = !(tft_lit && ((get_switch_state() & 0b11) != 0b11));
|
|
|
|
if (rfid_correct && lcd_correct && speaker_correct && keypad_correct && tft_correct) {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
} else {
|
|
strike("Incorrect state!");
|
|
}
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 3: {
|
|
lcd_print(&lcd, "Nothing");
|
|
set_module_time(25000);
|
|
start_module_timer();
|
|
|
|
const int COLOR_RED[5] = {0, 20, 10, 0, 0};
|
|
const int COLOR_GREEN[5] = {20, 0, 10, 0, 0};
|
|
const int COLOR_BLUE[5] = {0, 0, 0, 20, 0};
|
|
|
|
static std::uniform_int_distribution<> color_dist(0, 4);
|
|
|
|
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_puzzles++;
|
|
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(35000);
|
|
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;
|
|
SwitchKey switch_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 (button_colors[0] == 0 && button_colors[1] == 1 && button_colors[2] == 2 && button_colors[3] == 3) {
|
|
// check switch state
|
|
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 ^ starting_switch_state) >> i) & 0b1) != 1) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
} else {
|
|
if (((switch_state >> i) & 0b1) != (switch_colors[i] & 0b1)) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (correct) {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (get_flipped_switch(&switch_key)) {
|
|
if (button_colors[0] == 0 && button_colors[1] == 1 && button_colors[2] == 2 && button_colors[3] == 3) {
|
|
// check switch state
|
|
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 ^ starting_switch_state) >> i) & 0b1) != 1) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
} else {
|
|
if (((switch_state >> i) & 0b1) != (switch_colors[i] & 0b1)) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (correct) {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
// check button state
|
|
if (button_colors[0] == 0 && button_colors[1] == 1 && button_colors[2] == 2 && button_colors[3] == 3) {
|
|
// check switch state
|
|
uint8_t switch_state = get_switch_state();
|
|
bool correct = true;
|
|
// ESP_LOGI(TAG, "starting switch state: %i, current switch state: %i", starting_switch_state, switch_state);
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (switch_colors[i] == 2) {
|
|
// ESP_LOGI(TAG, "color yellow triggered: %i", (((switch_state ^ starting_switch_state) >> i) & 0b1));
|
|
if ((((switch_state ^ starting_switch_state) >> i) & 0b1) != 1) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
} else {
|
|
// ESP_LOGI(TAG, "color green or red triggered: %i != %i", ((switch_state >> i) & 0b1), (switch_colors[i] & 0b1));
|
|
if (((switch_state >> i) & 0b1) != (switch_colors[i] & 0b1)) {
|
|
correct = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (correct) {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
} else {
|
|
strike("Wrong switch state!");
|
|
}
|
|
} else {
|
|
strike("Wrong button state!");
|
|
}
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
case 5: {
|
|
lcd_print(&lcd, "Ummm");
|
|
set_module_time(35000);
|
|
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;
|
|
|
|
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) {
|
|
buttons_pressed[i]++;
|
|
if (buttons_pressed[i] > indicator_numbers[i]) {
|
|
strike("Too many times!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
// check for correct button presses
|
|
for (int i = 0; i < 4; i++) {
|
|
if (buttons_pressed == indicator_numbers) {
|
|
strike("Wrong button state!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint8_t switch_state = get_switch_state();
|
|
|
|
// check for correct switch states
|
|
for (int i = 0; i < 4; i++) {
|
|
if (((switch_state >> i) & 0b1) == (indicator_numbers[i] & 0b1)) {
|
|
strike("Wrong switch state!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
}
|
|
case 6: {
|
|
lcd_print(&lcd, "Plank");
|
|
set_module_time(40000);
|
|
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;
|
|
|
|
std::uniform_int_distribution<> led_turn_on_dist(0, 3);
|
|
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) {
|
|
if (button_colors[i] == -1) {
|
|
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!");
|
|
break;
|
|
} else {
|
|
buttons_cycling[i] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool success = true;
|
|
for (int i = 0; i < sizeof(buttons_cycling); i++) {
|
|
if ((buttons_cycling[i] == true) || (button_turned_on == false && led_off != -1)) {
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
if (success) {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
break;
|
|
}
|
|
}
|
|
if ((xTaskGetTickCount() - lastCycleTime) >= pdMS_TO_TICKS(500)) {
|
|
ESP_LOGI(TAG, "Cycling LEDs");
|
|
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();
|
|
}
|
|
if (get_module_time() <= 0) {
|
|
bool success = true;
|
|
for (int i = 0; i < sizeof(buttons_cycling); i++) {
|
|
if ((buttons_cycling[i] == true) || (button_turned_on == false && led_off != -1)) {
|
|
strike("Ran out of time!");
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
if (success) {
|
|
solved_puzzles++;
|
|
solved_correctly = true;
|
|
}
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
break;
|
|
}
|
|
case 7: {
|
|
lcd_print(&lcd, "What");
|
|
set_module_time(50000);
|
|
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());
|
|
|
|
// ESP_LOGI(TAG, "Display expression: %s", display_expression.c_str());
|
|
// ESP_LOGI(TAG, "Solved expression answer: %i", static_cast<int>(expression_answer));
|
|
|
|
// 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]) * (3 ^ modifier_indicators[2])) / (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 *= 3 ^ modifier_indicators[2];
|
|
expression_answer /= 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!");
|
|
} else {
|
|
solved_puzzles++;
|
|
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(40000);
|
|
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)) {
|
|
if (key == KeypadKey::star) {
|
|
// clear
|
|
entered_string = "";
|
|
} else if (key == KeypadKey::pound) {
|
|
// submit
|
|
if (entered_string != answer_num) {
|
|
strike("Incorrect answer!");
|
|
} else {
|
|
solved_times++;
|
|
}
|
|
break;
|
|
} else {
|
|
entered_string += char_of_keypad_key(key);
|
|
}
|
|
|
|
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_puzzles++;
|
|
solved_correctly = true;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
stop_module_timer();
|
|
if (solved_correctly) {
|
|
play_raw(MOUNT_POINT "/correct.pcm");
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
solved_correctly = false;
|
|
} else {
|
|
vTaskDelay(pdMS_TO_TICKS(3000));
|
|
}
|
|
clean_bomb();
|
|
}
|
|
}
|