#include "step3.h" static const char *TAG = "step3"; 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); static const int INDICATOR_RED[6] = {30, 0, 0, 25, 15, 10}; static const int INDICATOR_GREEN[6] = {0, 0, 30, 5, 0, 10}; static const int INDICATOR_BLUE[6] = {0, 30, 0, 0, 15, 10}; void step3(void) { int solved_puzzles = 0; while (solved_puzzles < 3) { // int puzzle = puzzle_dist(gen); int puzzle = 2; switch (puzzle) { case 0: { lcd_print(&lcd, "Clear"); set_module_time(10000); start_module_timer(); std::uniform_int_distribution<> green_indicators_dist(2, 15); // create all green indicators uint8_t green_indicators = green_indicators_dist(gen); std::set indicators; // ESP_LOGI(TAG, "green indicators: %i", green_indicators); while (indicators.size() < green_indicators) { int led = led_picker_dist(gen); indicators.insert(led); // ESP_LOGI(TAG, "added green led at %i", led); } for (std::set::iterator it = indicators.begin(); it != indicators.end(); it++) { ESP_ERROR_CHECK(led_strip_set_pixel(leds, *it, 0, 10, 0)); } // add non-green indicators const int NON_GREEN_INDICATOR_RED[3] = {30, 0, 15}; const int NON_GREEN_INDICATOR_BLUE[3] = {0, 30, 15}; std::uniform_int_distribution<> non_green_indicator_color_dist(0, 2); std::uniform_int_distribution<> remaining_indicators_dist(0, 20 - green_indicators); int non_green_indicators = remaining_indicators_dist(gen); std::set remaining_indicators; // ESP_LOGI(TAG, "non-green indicators: %i", non_green_indicators); while (remaining_indicators.size() < non_green_indicators) { int led_attempt = led_picker_dist(gen); if (indicators.find(led_attempt) == indicators.end()) { remaining_indicators.insert(led_attempt); // ESP_LOGI(TAG, "added non-green led at %i", led_attempt); } } for (std::set::iterator it = remaining_indicators.begin(); it != remaining_indicators.end(); it++) { int color = non_green_indicator_color_dist(gen); ESP_ERROR_CHECK(led_strip_set_pixel(leds, *it, NON_GREEN_INDICATOR_RED[color], 0, NON_GREEN_INDICATOR_BLUE[color])); } 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 switch combination! (step 3, puzzle 0)"); } break; } vTaskDelay(pdMS_TO_TICKS(10)); } break; } case 1: { lcd_print(&lcd, "Blank"); set_module_time(10000); start_module_timer(); std::uniform_int_distribution<> on_indicators_dist(16, 21); uint8_t indicators_num = on_indicators_dist(gen); std::set indicators; while (indicators.size() < indicators_num) { indicators.insert(led_picker_dist(gen)); } for (std::set::iterator it = indicators.begin(); it != indicators.end(); it++) { int color = led_color_dist(gen); ESP_ERROR_CHECK(led_strip_set_pixel(leds, *it, INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color])); } 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 was changed! (step 3, puzzle 1)"); } 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++; // ESP_LOGI(TAG, "puzzle 1 solved (keypad)!"); } } else { strike("Switch state was changed! (step 3, puzzle 1)"); } break; } vTaskDelay(pdMS_TO_TICKS(10)); } } break; } case 2: { set_module_time(10000); start_module_timer(); std::uniform_int_distribution<> lit_led_dist(0, 1); bool rfid_lit = lit_led_dist(gen); // ESP_LOGI(TAG, "rfid lit: %i", rfid_lit); 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); Led rfid_led = rfid; Led lcd_led = char_lcd; Led speaker_led = speaker; Led keypad_led = keypad; Led tft_led = tft; if (rfid_lit) { int color = led_color_dist(gen); ESP_ERROR_CHECK(led_strip_set_pixel(leds, rfid_led, 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, lcd_led, 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, speaker_led, 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, keypad_led, 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, tft_led, 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("Green button pressed too many times! (step 3, puzzle 2)"); break; } } if ((button_state & 0b1000) == 0b1000) { blue_button_pressed++; if ((blue_button_pressed > 1) || !lcd_lit) { strike("Blue button pressed too many times! (step 3, puzzle 2)"); break; } } } if (get_touch_pressed()) { fingerprint_sensor_pressed++; if ((fingerprint_sensor_pressed > 2) || !speaker_lit) { strike("Fingerprint sensor pressed too many times! (step 3, puzzle 2)"); 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("1 was not pressed on Keypad! (step 3, puzzle 2)"); wrong = true; } break; } case 2: { if (keypad_string != "12") { strike("12 was not pressed on Keypad! (step 3, puzzle 2)"); wrong = true; } break; } default: { strike("keypad length was more than 2! (step 3, puzzle 2)"); wrong = true; break; } } if (wrong) { break; } } if (get_flipped_up_switch(&switch1) || get_flipped_up_switch(&switch2)) { if (!tft_lit) { strike("Switch 1 or 2 were flipped up! (step 3, puzzle 2)"); 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++; } else { strike("Final state was not correct! (step 3, puzzle 2)"); } break; } vTaskDelay(pdMS_TO_TICKS(10)); } break; } case 3: { lcd_print(&lcd, "Nothing"); set_module_time(10000); start_module_timer(); break; } case 4: { lcd_print(&lcd, "Blink"); set_module_time(10000); start_module_timer(); break; } case 5: { lcd_print(&lcd, "Ummm"); set_module_time(10000); start_module_timer(); break; } case 6: { lcd_print(&lcd, "Plank"); set_module_time(10000); start_module_timer(); break; } case 7: { lcd_print(&lcd, "What"); set_module_time(10000); start_module_timer(); break; } case 8: { lcd_print(&lcd, "Plink"); set_module_time(10000); start_module_timer(); break; } } clean_bomb(); } }