From f0555579cd462b27c71c486bd7456265cc827937 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 9 Dec 2023 13:14:25 -0500 Subject: Starting to work --- randomizer/generator.gd | 748 +++++++++++++++++++++++++++++++++++++++++ randomizer/load.gd | 18 + randomizer/panelEnd.gd | 7 + randomizer/panelInput.gd | 5 + randomizer/panelLevelSwitch.gd | 7 + randomizer/randomizer.gd | 26 ++ randomizer/settings_buttons.gd | 16 + randomizer/settings_screen.gd | 78 +++++ randomizer/worldTransporter.gd | 6 + 9 files changed, 911 insertions(+) create mode 100644 randomizer/generator.gd create mode 100644 randomizer/load.gd create mode 100644 randomizer/panelEnd.gd create mode 100644 randomizer/panelInput.gd create mode 100644 randomizer/panelLevelSwitch.gd create mode 100644 randomizer/randomizer.gd create mode 100644 randomizer/settings_buttons.gd create mode 100644 randomizer/settings_screen.gd create mode 100644 randomizer/worldTransporter.gd (limited to 'randomizer') diff --git a/randomizer/generator.gd b/randomizer/generator.gd new file mode 100644 index 0000000..22ab178 --- /dev/null +++ b/randomizer/generator.gd @@ -0,0 +1,748 @@ +extends Node + +var panel_mapping = [] +var gen_seed + +var _generated_puzzles +var _answer_by_id +var _answers_by_type +var _answers_by_length +var _puzzle_by_id +var _rng +var _flags = 0 +var _total_generated = 0 + +var _unique_pool = "" +var _answers_by_unique_pool = {} +var _needs_reuse = [] +var _possible_reuse = [] + +const kWhiteMiddle = -1 +const kWhiteTop = 0 +const kWhiteBottom = 1 +const kYellowTop = 2 +const kYellowMiddle = 3 +const kBlackTop = 4 +const kBlackMiddle = 5 +const kBlackBottom = 6 +const kDoubleBlackBottom = 7 +const kRedTop = 8 +const kRedMiddle = 9 +const kRedBottom = 10 +const kBlueTop = 11 +const kBlueMiddle = 12 +const kBlueBottom = 13 +const kPurpleTop = 14 +const kPurpleMiddle = 15 + +const kPuzzleTypes = [ + kWhiteMiddle, + kWhiteTop, + kWhiteBottom, + kYellowTop, + kYellowMiddle, + kBlackTop, + kBlackMiddle, + kBlackBottom, + kDoubleBlackBottom, + kRedTop, + kRedMiddle, + kRedBottom, + kBlueTop, + kBlueMiddle, + kBlueBottom, + kPurpleTop, + kPurpleMiddle +] + +const kMustReuseAnswer = 1 >> 0 +const kObscureHint = 1 >> 1 +const kShortAnswer = 1 >> 2 + +signal generator_status + + +func _init(gen_puzzles): + _generated_puzzles = gen_puzzles + + +func generate(chosen_seed): + emit_signal("generator_status", "Generating puzzles...") + + _flags = 0 + _total_generated = 0 + + # Seed the random number generator. + if chosen_seed == "": + var seed_rng = RandomNumberGenerator.new() + seed_rng.randomize() + gen_seed = seed_rng.randi_range(0, 999999) + else: + gen_seed = int(chosen_seed) + + _rng = RandomNumberGenerator.new() + _rng.seed = gen_seed + + # Create some helpful indexes. + _answer_by_id = [] + _answers_by_type = {} + _answers_by_length = {} + _puzzle_by_id = [] + var openable_answers = [] + + for puzzle_type in kPuzzleTypes: + _answers_by_type[puzzle_type] = [] + + var puzzle_id = 0 + for puzzle in _generated_puzzles.forms: + _answers_by_type[kWhiteMiddle].append(puzzle_id) + + match typeof(puzzle): + TYPE_ARRAY: + _answer_by_id.append(puzzle[0]) + if not _answers_by_length.has(puzzle[0].length()): + _answers_by_length[puzzle[0].length()] = [] + _answers_by_length[puzzle[0].length()].append(puzzle_id) + _puzzle_by_id.append(puzzle) + + for puzzle_type in puzzle[1].keys(): + _answers_by_type[puzzle_type].append(puzzle_id) + + if ( + puzzle[1].has(kYellowMiddle) + and puzzle[1].has(kBlackBottom) + and puzzle[1].has(kRedMiddle) + and puzzle[1].has(kBlueMiddle) + and puzzle[1].has(kPurpleMiddle) + ): + openable_answers.append(puzzle_id) + TYPE_STRING: + _answer_by_id.append(puzzle) + if not _answers_by_length.has(puzzle.length()): + _answers_by_length[puzzle.length()] = [] + _answers_by_length[puzzle.length()].append(puzzle_id) + _puzzle_by_id.append([puzzle, []]) + + puzzle_id += 1 + + # Choose the answer for the OPEN panels. + # There is a hedge maze OPEN but we can't randomize those yet. + var open_answer_id = _pickRandom(openable_answers) + + _setUniquePool("agreeable") + _setPanel( + "Antonym Room/Panel_close_open", + _pickRandom(_puzzle_by_id[open_answer_id][1][kBlackBottom]), + open_answer_id + ) + + _setUniquePool("seeker") + _setPanel("Heteronym Room/Panel_entrance_entrance", open_answer_id, open_answer_id) + + _setUniquePool("traveled") + _setPanel("Synonym Room/Panel_open_open", open_answer_id, open_answer_id) + + _setUniquePool("discerning") + _setPanel( + "Sun Room/Panel_nope_open", + _pickRandom(_puzzle_by_id[open_answer_id][1][kYellowMiddle]), + open_answer_id + ) + + _setUniquePool("bold") + _setPanel( + "Truncate Room/Panel_unopened_open", + _pickRandom(_puzzle_by_id[open_answer_id][1][kRedMiddle]), + open_answer_id + ) + + _setUniquePool("undeterred") + _setPanel( + "Blue Room/Panel_pen_open", + _pickRandom(_puzzle_by_id[open_answer_id][1][kBlueMiddle]), + open_answer_id + ) + + _setUniquePool("initiated") + _setPanel( + "Rhyme Room/Panel_locked_knocked", + _pickRandom(_puzzle_by_id[open_answer_id][1][kPurpleMiddle]), + open_answer_id + ) + + # Start generating puzzles that need to have reused solutions. + _setFlag(kMustReuseAnswer) + + _setUniquePool("agreeable") + _gSingle("Antonym Room/Panel_read_write", kBlackBottom) + _gSingle("Antonym Room/Panel_different_same", kBlackBottom) + _gSingle("Antonym Room/Panel_bye_hi", kBlackBottom) + _gSingle("Antonym Room/Panel_low_high", kBlackBottom) + _gSingle("Antonym Room/Panel_alive_dead", kBlackBottom) + _gSingle("Antonym Room/Panel_that_this", kBlackBottom) + _gSingle("Doorways Room/Panel_found_lost", kBlackBottom) + + _setUniquePool("bold") + _gDouble("Truncate Room/Panel_face_eye", "Truncate Room/Panel_needle_eye", kRedBottom) + _gDouble("Truncate Room/Panel_mouth_teeth", "Truncate Room/Panel_saw_teeth", kRedBottom) + _gSingle("Truncate Room/Panel_foot_toe", kRedBottom) + _gSingle("Truncate Room/Panel_hand_finger", kRedBottom) + _gSingle("Doorways Room/Panel_loaf_crust", kRedBottom) + + _setUniquePool("undeterred") + _gSingle("Blue Room/Panel_two_toucan", kBlueTop) + _gDouble("Blue Room/Panel_ice_eyesight", "Blue Room/Panel_height_eyesight", kBlueTop) + _gSingle("Blue Room/Panel_eye_hi", kBlueTop) + _gSingle("Blue Room/Panel_not_notice", kBlueMiddle) + _gDouble("Blue Room/Panel_just_readjust", "Blue Room/Panel_read_readjust", kBlueMiddle) + _gSingle("Blue Room/Panel_ate_primate", kBlueMiddle) + _gSingle("Blue Room/Panel_bone_skeleton", kBlueBottom) + _gDouble("Blue Room/Panel_mouth_face", "Blue Room/Panel_eye_face", kBlueBottom) + _gSingle("Blue Room/Panel_toucan_bird", kBlueBottom) + _gSingle("Blue Room/Panel_primate_mammal", kBlueBottom) + _gDouble("Blue Room/Panel_continent_planet", "Blue Room/Panel_ocean_planet", kBlueBottom) + _gSingle("Blue Room/Panel_wall_room", kBlueBottom) + _gSingle("Doorways Room/Panel_sun_sky", kBlueBottom) + + _setUniquePool("traveled") + _gSingle("Synonym Room/Panel_close_near", kWhiteBottom) + _gSingle("Synonym Room/Panel_category_type", kWhiteBottom) + _gSingle("Synonym Room/Panel_distant_far", kWhiteBottom) + _gSingle("Synonym Room/Panel_hay_straw", kWhiteBottom) + _gSingle("Synonym Room/Panel_snitch_rat", kWhiteBottom) + _gSingle("Synonym Room/Panel_concealed_hidden", kWhiteBottom) + _gSingle("Synonym Room/Panel_growths_warts", kWhiteBottom) + _gSingle("Synonym Room/Panel_hello_hi", kWhiteBottom) + _gDouble("Synonym Room/Panel_compose_write", "Synonym Room/Panel_record_write", kWhiteBottom) + _gDouble("Synonym Room/Panel_duplicate_same", "Synonym Room/Panel_identical_same", kWhiteBottom) + _gDouble("Synonym Room/Panel_giggle_laugh", "Synonym Room/Panel_chuckle_laugh", kWhiteBottom) + _gDouble("Synonym Room/Panel_plunge_fall", "Synonym Room/Panel_autumn_fall", kWhiteBottom) + _gSingle("Doorways Room/Panel_begin_start", kWhiteBottom) + + _setUniquePool("initiated") + _gSingle("Rhyme Room/Panel_daughter_laughter", kPurpleMiddle) + _gSingle("Rhyme Room/Panel_scope_type", kPurpleMiddle) + _gSingle("Rhyme Room/Panel_abyss_this", kPurpleMiddle) + _gSingle("Rhyme Room/Panel_wrath_path", kPurpleMiddle) + _gSingle("Rhyme Room/Panel_bed_dead", kPurpleMiddle) + _gSingle("Rhyme Room/Panel_alumni_hi", kPurpleTop) + _gSingle("Rhyme Room/Panel_maim_same", kPurpleTop) + _gSingle("Rhyme Room/Panel_bare_bear", kPurpleTop) + _gDouble("Rhyme Room/Panel_move_love", "Rhyme Room/Panel_stove_love", kPurpleMiddle) + _gDouble("Rhyme Room/Panel_sweat_great", "Rhyme Room/Panel_beat_great", kPurpleMiddle) + _gDouble("Rhyme Room/Panel_knight_write", "Rhyme Room/Panel_byte_write", kPurpleTop) + # Panel_chair_bear, Panel_cost_most (cyborg) + + _setUniquePool("fearless") + _gSingle("Naps Room/Panel_easy_soft", kDoubleBlackBottom) + _gSingle("Naps Room/Panel_sometimes_always", kDoubleBlackBottom) + _gSingle("Naps Room/Panel_dark_extinguish", kDoubleBlackBottom) + _gSingle("Naps Room/Panel_impatient_doctor", kDoubleBlackBottom) + _gSingle("Naps Room/Panel_even_ordinary", kDoubleBlackBottom) + + _setUniquePool("unchallenged") + _gSingle("Challenge Room/Panel_nevertrusted_maladjusted", kPurpleMiddle) + _gSingle("Challenge Room/Panel_writer_songwriter", kBlueMiddle) + _gSingle("Challenge Room/Panel_lobs_lobster", kBlueMiddle) + + _setUniquePool("red") + _gSingle("Hangry Room/Panel_red_bot_1", kRedBottom) + _gSingle("Hangry Room/Panel_red_bot_2", kRedBottom) + _gSingle("Hangry Room/Panel_red_bot_3", kRedBottom) + _gSingle("Hangry Room/Panel_red_bot_6", kRedBottom) + + # Do must-reuse panels with no unique pool last so that we can reuse already chosen answers. + _clearUniquePool() + _gSingle("Symmetry Room/Panel_left_wrong", kDoubleBlackBottom) + _gSingle("Symmetry Room/Panel_black_white", kBlackBottom) + + _gSingle("Shuffle Room/Panel_lost_found", kBlackBottom) + _gSingle("Shuffle Room/Panel_clockwise_counterclockwise", kBlackBottom) + _gSingle("Shuffle Room/Panel_order_chaos", kBlackBottom) + + _gSingle("Maze Room/Panel_down_up", kBlackBottom) + _gSingle("Maze Room/Panel_strays_maze", kPurpleTop) + _gSingle("Maze Room/Panel_daze_maze", kPurpleMiddle) + _gSingle("Maze Room/Panel_hide_seek", kBlackBottom) + _gSingle("Maze Room/Panel_hide_seek_2", kBlackBottom) + _gSingle("Maze Room/Panel_hide_seek_3", kBlackBottom) + _gSingle("Maze Room/Panel_hide_seek_4", kBlackBottom) + _gSingle("Maze Room/Panel_leap_jump", kWhiteBottom) + _gSingle("Maze Room/Panel_look_look", kWhiteBottom) + + _gSingle("Appendix Room/Panel_discover_recover", kPurpleMiddle) + _gSingle("Appendix Room/Panel_warner_corner", kPurpleTop) + _gSingle("Appendix Room/Panel_adjust_readjusted", kBlueMiddle) + _gSingle("Appendix Room/Panel_trust_crust", kPurpleMiddle) + _gCopy("Appendix Room/Panel_trust_crust", "Appendix Room/Panel_trust_crust_2") + _gSingle("Appendix Room/Panel_trusted_readjusted", kPurpleMiddle) + + _gSingle("Painting Room/Panel_free_three", kPurpleMiddle) + _gSingle("Painting Room/Panel_our_four", kBlueMiddle) + _gSingle("Painting Room/Panel_house_neighborhood", kBlueBottom) + # Panel_path_road + _gSingle("Painting Room/Panel_park_drive", kBlackBottom) + _gSingle("Painting Room/Panel_carriage_horse", kRedBottom) + _gSingle("Painting Room/Panel_learns_turns", kPurpleMiddle) + _gSingle("Painting Room/Panel_urns_turns", kBlueMiddle) + + _gSingle("Backside Room/Panel_ward_forward", kBlueMiddle) + _gSingle("Backside Room/Panel_hind_behind", kBlueMiddle) + _gSingle("Backside Room/Panel_rig_right", kBlueMiddle) + _gSingle("Backside Room/Panel_turn_return", kBlueMiddle) + _gSingle("Backside Room/Panel_windward_forward", kPurpleMiddle) + _gSingle("Backside Room/Panel_light_right", kPurpleMiddle) + _gSingle("Backside Room/Panel_rewind_behind", kPurpleMiddle) + _gSingle("Backside Room/Panel_learn_return", kPurpleMiddle) + + _gSingle("Color Arrow Room/Panel_hues_colors", kWhiteBottom) + + # Now we'll generate puzzles that don't need to be reused, and hopefully cover + # all previously generated answers. + _clearFlag(kMustReuseAnswer) + + _setUniquePool("agreeable") + _gSingle("Antonym Room/Panel_retool_looter", kBlackMiddle) + _gSingle("Antonym Room/Panel_drawer_reward", kBlackMiddle) + _gSingle("Antonym Room/Panel_stressed_desserts", kBlackMiddle) + _gSingle("Antonym Room/Panel_star_rats", kBlackMiddle) + _gSingle("Antonym Room/Panel_tame_mate", kBlackTop) + _gSingle("Antonym Room/Panel_cat_tack", kBlackTop) + + _setUniquePool("seeker") + _setFlag(kObscureHint) + _gSingle("Heteronym Room/Panel_bear_bear", kWhiteMiddle) + _gSingle("Heteronym Room/Panel_bow_bow", kWhiteMiddle) + _gSingle("Heteronym Room/Panel_does_does", kWhiteMiddle) + _gDouble("Heteronym Room/Panel_mine_mine", "Heteronym Room/Panel_mine_mine_2", kWhiteMiddle) + _gDouble( + "Heteronym Room/Panel_mobile_mobile", "Heteronym Room/Panel_mobile_mobile_2", kWhiteMiddle + ) + _gStack2( + "Heteronym Room/Panel_desert_dessert", + kWhiteTop, + "Heteronym Room/Panel_desert_desert", + kWhiteMiddle + ) + _gStack2("Heteronym Room/Panel_sow_so", kWhiteTop, "Heteronym Room/Panel_sow_sow", kWhiteMiddle) + _gDouble("Heteronym Room/Panel_two_to", "Heteronym Room/Panel_two_too", kWhiteTop) + _gDouble("Heteronym Room/Panel_not_knot", "Heteronym Room/Panel_not_naught", kWhiteTop) + _gSingle("Heteronym Room/Panel_write_right", kWhiteTop) + _gSingle("Heteronym Room/Panel_you_ewe", kWhiteTop) + _gSingle("Heteronym Room/Panel_bear_bare", kWhiteTop) + _clearFlag(kObscureHint) + + _setUniquePool("tenacious") + _gSingle("Palindrome Room/Panel_slaughter_laughter", kRedMiddle) + _gSingle("Palindrome Room/Panel_dread_dead", kRedMiddle) + _gSingle("Palindrome Room/Panel_massacred_sacred", kRedMiddle) + _gSingle("Palindrome Room/Panel_decay_day", kRedMiddle) + # do palindromes + + _setUniquePool("discerning") + _gSingle("Sun Room/Panel_hits_this", kYellowMiddle) + _gSingle("Sun Room/Panel_adder_dread", kYellowMiddle) + _gSingle("Sun Room/Panel_laughters_slaughter", kYellowMiddle) + _gSingle("Sun Room/Panel_rat_art", kYellowMiddle) + _gSingle("Sun Room/Panel_dusty_study", kYellowMiddle) + _gSingle("Sun Room/Panel_state_taste", kYellowMiddle) + _gSingle("Sun Room/Panel_react_trace", kYellowMiddle) + _gSingle("Sun Room/Panel_seam_same", kYellowMiddle) + _gDouble("Sun Room/Panel_warred_drawer", "Sun Room/Panel_redraw_drawer", kYellowMiddle) + _gDouble("Sun Room/Panel_stone_notes", "Sun Room/Panel_onset_notes", kYellowMiddle) + _gDouble("Sun Room/Panel_arts_star", "Sun Room/Panel_tsar_star", kYellowMiddle) + _gDouble("Sun Room/Panel_dear_read", "Sun Room/Panel_dare_read", kYellowMiddle) + + _setUniquePool("bold") + _gSingle("Truncate Room/Panel_sushi_hi", kRedMiddle) + _gSingle("Truncate Room/Panel_thistle_this", kRedMiddle) + _gSingle("Truncate Room/Panel_heartbreak_brake", kRedTop) + _gSingle("Truncate Room/Panel_airplane_plain", kRedTop) + _gSingle("Truncate Room/Panel_nightmare_knight", kRedTop) + _gSingle("Truncate Room/Panel_sign_sigh", kRedTop) + _gDouble("Truncate Room/Panel_undead_dead", "Truncate Room/Panel_deadline_dead", kRedMiddle) + _gDouble("Truncate Room/Panel_landmass_mass", "Truncate Room/Panel_massacred_mass", kRedMiddle) + + _setUniquePool("rhyme") + _gStack2( + "Double Room/Panel_ascend_rhyme", kPurpleTop, "Double Room/Panel_ascend_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_double_rhyme", kPurpleTop, "Double Room/Panel_double_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_blocked_rhyme", kPurpleTop, "Double Room/Panel_blocked_syn", kWhiteBottom + ) + _gStack2("Double Room/Panel_rise_rhyme", kPurpleTop, "Double Room/Panel_rise_syn", kWhiteBottom) + _gStack2( + "Double Room/Panel_crystal_rhyme", kPurpleTop, "Double Room/Panel_crystal_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_creative_rhyme", + kPurpleTop, + "Double Room/Panel_creative_syn", + kWhiteBottom + ) + _gStack2( + "Double Room/Panel_child_rhyme", kPurpleTop, "Double Room/Panel_child_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_hidden_rhyme", kPurpleTop, "Double Room/Panel_hidden_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_word_rhyme", kPurpleTop, "Double Room/Panel_word_whole", kBlueBottom + ) + _gStack2( + "Double Room/Panel_silent_rhyme", kPurpleTop, "Double Room/Panel_silent_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_bones_rhyme", kPurpleTop, "Double Room/Panel_bones_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_sentence_rhyme", + kPurpleTop, + "Double Room/Panel_sentence_whole", + kBlueBottom + ) + _gStack2( + "Double Room/Panel_dream_rhyme", kPurpleTop, "Double Room/Panel_dream_syn", kWhiteBottom + ) + _gStack2( + "Double Room/Panel_mystery_rhyme", kPurpleTop, "Double Room/Panel_mystery_syn", kWhiteBottom + ) + _gStack2("Double Room/Panel_jump_rhyme", kPurpleTop, "Double Room/Panel_jump_syn", kWhiteBottom) + _gStack2("Double Room/Panel_fall_rhyme", kPurpleTop, "Double Room/Panel_fall_syn", kWhiteBottom) + _gStack2( + "Double Room/Panel_return_rhyme", kPurpleTop, "Double Room/Panel_return_ant", kBlackBottom + ) + _gStack2( + "Double Room/Panel_descend_rhyme", kPurpleTop, "Double Room/Panel_descend_ant", kBlackBottom + ) + + _clearUniquePool() + _gSingle("Entry Room/Panel_hidden_hidden", kWhiteMiddle) + + _gPaired("Shuffle Room/Panel_sword_words", "Shuffle Room/Panel_words_sword", kYellowMiddle) + _gPaired("Shuffle Room/Panel_turn_runt", "Shuffle Room/Panel_turn_runt2", kYellowMiddle) + _gCohinted("Shuffle Room/Panel_lost_lots", "Shuffle Room/Panel_lost_slot", kYellowMiddle) + _gDouble("Shuffle Room/Panel_amen_mean", "Shuffle Room/Panel_name_mean", kYellowMiddle) + _gSingle("Shuffle Room/Panel_corner", kYellowTop) + _gSingle("Shuffle Room/Panel_gel", kYellowTop) + _gSingle("Shuffle Room/Panel_though", kYellowTop) + _gSingle("Shuffle Room/Panel_swap_wasp", kYellowMiddle) + _gSingle("Shuffle Room/Panel_eyes_see_shuffle", kYellowMiddle) + _gSingle("Shuffle Room/Panel_behind", kYellowMiddle) + _gPaired("Shuffle Room/Panel_left_left", "Shuffle Room/Panel_right_right", kWhiteMiddle) + _gSingle("Shuffle Room/Panel_middle_middle", kWhiteMiddle) + _gCopy("Shuffle Room/Panel_left_left", "Shuffle Room/Panel_left_left_2") + _gCopy("Shuffle Room/Panel_right_right", "Shuffle Room/Panel_right_right_2") + _gCopy("Shuffle Room/Panel_middle_middle", "Shuffle Room/Panel_middle_middle_2") + _gSingle("Shuffle Room/Panel_shortcuts", kWhiteMiddle) + _gSingle("Shuffle Room/Panel_tower", kWhiteMiddle) + + _gSingle("Maze Room/Panel_reflow_flower", kYellowMiddle) + + _gSingle("Appendix Room/Panel_rat_tar", kBlackMiddle) + _gSingle("Appendix Room/Panel_deadend_deadened", kWhiteTop) + _gPaired("Appendix Room/Panel_night_knight", "Appendix Room/Panel_knight_night", kBlueMiddle) + _gPaired("Appendix Room/Panel_bee_be", "Appendix Room/Panel_new_knew", kRedMiddle) + _gSingle("Appendix Room/Panel_fore_for", kRedMiddle) + _gCohinted( + "Appendix Room/Panel_trusted_trust", "Appendix Room/Panel_trusted_rusted", kRedMiddle + ) + _gCohinted("Appendix Room/Panel_rust_trust", "Appendix Room/Panel_rust_crust", kBlueMiddle) + _gSingle("Appendix Room/Panel_encrusted_rust", kRedMiddle) + _gCohinted( + "Appendix Room/Panel_adjust_readjust", "Appendix Room/Panel_adjust_adjusted", kBlueMiddle + ) + + _gSingle("Painting Room/Panel_eon_one", kYellowMiddle) + _gSingle("Painting Room/Panel_to_two", kRedMiddle) + _setFlag(kShortAnswer) + _gSingle("Painting Room/Panel_an_many", kBlueMiddle) + _gSingle("Painting Room/Panel_may_many", kBlueMiddle) + _gSingle("Painting Room/Panel_any_many", kBlueMiddle) + _gSingle("Painting Room/Panel_man_many", kBlueMiddle) + _clearFlag(kShortAnswer) + + _gExactLength("Backside Room/Panel_one_one", kWhiteMiddle, 1) + _gExactLength("Backside Room/Panel_two_two", kWhiteMiddle, 2) + _gExactLength("Backside Room/Panel_two_two_2", kWhiteMiddle, 2) + _gExactLength("Backside Room/Panel_three_three", kWhiteMiddle, 3) + _gExactLength("Backside Room/Panel_three_three_2", kWhiteMiddle, 3) + _gExactLength("Backside Room/Panel_three_three_3", kWhiteMiddle, 3) + + _setFlag(kObscureHint) + _gSingle("Entry Room/Panel_forward_forward", kWhiteMiddle) + _gSingle("Entry Room/Panel_between_between", kWhiteMiddle) + _gSingle("Entry Room/Panel_backward_backward", kWhiteMiddle) + _gSingle("Entry Room/Panel_secret_secret", kWhiteMiddle) + + _gPaired("Symmetry Room/Panel_leaf_feel", "Symmetry Room/Panel_feel_leaf", kBlackTop) + _gPaired("Symmetry Room/Panel_warts_straw", "Symmetry Room/Panel_straw_warts", kBlackMiddle) + _gPaired("Symmetry Room/Panel_near_far", "Symmetry Room/Panel_far_near", kBlackBottom) + _gPaired("Symmetry Room/Panel_left_right", "Symmetry Room/Panel_right_left", kBlackBottom) + + _gSingle("Shuffle Room/Panel_theeyes_theeyes", kWhiteMiddle) + _gSingle("Shuffle Room/Panel_crossroads_crossroads", kWhiteMiddle) + _gSingle("Shuffle Room/Panel_corner_corner", kWhiteMiddle) + _gSingle("Shuffle Room/Panel_hollow_hollow", kWhiteMiddle) + _gPaired("Shuffle Room/Panel_far_far", "Shuffle Room/Panel_near_near", kWhiteMiddle) + + _gSingle("Maze Room/Panel_trace_trace", kWhiteMiddle) + + _gSingle("Appendix Room/Panel_deadend_deadend", kWhiteMiddle) + _gSingle("Appendix Room/Panel_lies_lies", kWhiteMiddle) + + _gSingle("Cross Room/Panel_shortcut_shortcut", kWhiteMiddle) + + _gSingle("Double Room/Panel_leap_leap", kWhiteMiddle) + + _gSingle("Backside Room/Panel_backside_1", kWhiteMiddle) + _gSingle("Backside Room/Panel_backside_2", kWhiteMiddle) + _gSingle("Backside Room/Panel_backside_3", kWhiteMiddle) + _gSingle("Backside Room/Panel_backside_4", kWhiteMiddle) + _gSingle("Backside Room/Panel_backside_5", kWhiteMiddle) + _gSingle("Backside Room/Panel_farther_far", kRedMiddle) + _gSingle("Backside Room/Panel_first_first", kWhiteMiddle) + _gSingle("Backside Room/Panel_second_second", kWhiteMiddle) + _gSingle("Backside Room/Panel_third_third", kWhiteMiddle) + _gSingle("Backside Room/Panel_fourth_fourth", kWhiteMiddle) + + _gExactLength("Backside Room/Panel_four_four", kWhiteMiddle, 4) + _gExactLength("Backside Room/Panel_four_four_2", kWhiteMiddle, 4) + _gExactLength("Backside Room/Panel_four_four_3", kWhiteMiddle, 4) + _gExactLength("Backside Room/Panel_four_four_4", kWhiteMiddle, 4) + _gExactLength("Backside Room/Panel_five_five", kWhiteMiddle, 5) + _gExactLength("Backside Room/Panel_five_five_2", kWhiteMiddle, 5) + _gExactLength("Backside Room/Panel_five_five_3", kWhiteMiddle, 5) + _gExactLength("Backside Room/Panel_five_five_4", kWhiteMiddle, 5) + _gExactLength("Backside Room/Panel_five_five_5", kWhiteMiddle, 5) + _gExactLength("Backside Room/Panel_six_six", kWhiteMiddle, 6) + _gExactLength("Backside Room/Panel_six_six_2", kWhiteMiddle, 6) + _gExactLength("Backside Room/Panel_six_six_3", kWhiteMiddle, 6) + _gExactLength("Backside Room/Panel_six_six_4", kWhiteMiddle, 6) + _gExactLength("Backside Room/Panel_six_six_5", kWhiteMiddle, 6) + _gExactLength("Backside Room/Panel_six_six_6", kWhiteMiddle, 6) + _gExactLength("Backside Room/Panel_seven_seven", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_seven_seven_2", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_seven_seven_3", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_seven_seven_4", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_seven_seven_5", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_seven_seven_6", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_seven_seven_7", kWhiteMiddle, 7) + _gExactLength("Backside Room/Panel_eight_eight", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_2", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_3", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_4", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_5", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_6", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_7", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_eight_eight_8", kWhiteMiddle, 8) + _gExactLength("Backside Room/Panel_nine_nine", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_2", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_3", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_4", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_5", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_6", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_7", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_8", kWhiteMiddle, 9) + _gExactLength("Backside Room/Panel_nine_nine_9", kWhiteMiddle, 9) + + _clearFlag(kObscureHint) + + if _needs_reuse.size() > 0: + print("Generation failed; the following words need to be reused:") + for word_id in _needs_reuse: + print(_answer_by_id[word_id]) + + print("Generated!") + for puzzle in panel_mapping: + print("%s: %s? %s!" % puzzle) + + +func _pickRandom(set): + var id = _rng.randi_range(0, set.size() - 1) + return set[id] + + +func _setFlag(flag): + _flags |= flag + + +func _clearFlag(flag): + _flags &= ~flag + + +func _isFlag(flag): + return (_flags & flag) > 0 + + +func _setUniquePool(pool): + _unique_pool = pool + if not _answers_by_unique_pool.has(_unique_pool): + _answers_by_unique_pool[_unique_pool] = [] + + +func _clearUniquePool(): + _unique_pool = "" + + +func _gSingle(panel_path, puzzle_type): + if puzzle_type == kWhiteMiddle: + var word_choices = _filterBestPuzzles(_answers_by_type[kWhiteMiddle]) + var answer_id = _pickRandom(word_choices) + _setPanel(panel_path, answer_id, answer_id) + else: + var puzzle_choices = _filterBestPuzzles(_answers_by_type[puzzle_type]) + if puzzle_choices.empty(): + print("No possible puzzles for panel %s" % panel_path) + else: + var answer_id = _pickRandom(puzzle_choices) + var hint_choices = _puzzle_by_id[answer_id][1][puzzle_type] + var hint_id = _pickRandom(hint_choices) + _setPanel(panel_path, hint_id, answer_id) + + +func _gDouble(panel1_path, panel2_path, puzzle_type): + if puzzle_type == kWhiteMiddle: + var word_choices = _filterBestPuzzles(_answers_by_type[kWhiteMiddle]) + var answer_id = _pickRandom(word_choices) + _setPanel(panel1_path, answer_id, answer_id) + _setPanel(panel2_path, answer_id, answer_id) + else: + var pre_choices = _filterBestPuzzles(_answers_by_type[puzzle_type]) + var puzzle_choices = [] + for word_id in pre_choices: + if _puzzle_by_id[word_id][1][puzzle_type].size() > 1: + puzzle_choices.append(word_id) + if puzzle_choices.empty(): + print("No possible puzzles for panel %s" % panel1_path) + else: + var answer_id = _pickRandom(puzzle_choices) + var hint_choices = _puzzle_by_id[answer_id][1][puzzle_type].duplicate() + var hint1_id = _pickRandom(hint_choices) + hint_choices.erase(hint1_id) + var hint2_id = _pickRandom(hint_choices) + _setPanel(panel1_path, hint1_id, answer_id) + _setPanel(panel2_path, hint2_id, answer_id) + + +func _gPaired(panel1_path, panel2_path, puzzle_type): + var needed_type = puzzle_type + if puzzle_type == kWhiteMiddle: + needed_type = kBlackMiddle + var puzzle_choices = _filterBestPuzzles(_answers_by_type[needed_type]) + if puzzle_choices.empty(): + print("No possible puzzles for panel %s" % panel1_path) + else: + var answer_id = _pickRandom(puzzle_choices) + var hint_choices = _puzzle_by_id[answer_id][1][needed_type] + var hint_id = _pickRandom(hint_choices) + if puzzle_type == kWhiteMiddle: + _setPanel(panel1_path, hint_id, hint_id) + _setPanel(panel2_path, answer_id, answer_id) + else: + _setPanel(panel1_path, hint_id, answer_id) + _setPanel(panel2_path, answer_id, hint_id) + + +func _gCohinted(panel1_path, panel2_path, puzzle_type): + pass + + +func _gStack2(panel1_path, puzzle_type1, panel2_path, puzzle_type2): + if puzzle_type1 == kWhiteMiddle or puzzle_type2 == kWhiteMiddle: + if puzzle_type1 == kWhiteMiddle: + _gSingle(panel2_path, puzzle_type2) + _gCopyAnswer(panel2_path, panel1_path) + else: + _gSingle(panel1_path, puzzle_type1) + _gCopyAnswer(panel1_path, panel2_path) + else: + var pre_choices = _filterBestPuzzles(_answers_by_type[puzzle_type1]) + var puzzle_choices = [] + for word_id in pre_choices: + if _puzzle_by_id[word_id][1].has(puzzle_type2): + puzzle_choices.append(word_id) + if puzzle_choices.empty(): + print("No possible puzzles for panel %s" % panel1_path) + else: + var answer_id = _pickRandom(puzzle_choices) + var hint1_choices = _puzzle_by_id[answer_id][1][puzzle_type1] + var hint1_id = _pickRandom(hint1_choices) + var hint2_choices = _puzzle_by_id[answer_id][1][puzzle_type2] + var hint2_id = _pickRandom(hint2_choices) + _setPanel(panel1_path, hint1_id, answer_id) + _setPanel(panel2_path, hint2_id, answer_id) + + +func _gCopy(panel1_path, panel2_path): + for thing in panel_mapping: + if thing[0] == panel1_path: + panel_mapping.append([panel2_path, thing[1], thing[2]]) + return + + +func _gCopyAnswer(panel1_path, panel2_path): + for thing in panel_mapping: + if thing[0] == panel1_path: + panel_mapping.append([panel2_path, thing[2], thing[2]]) + return + + +func _gExactLength(panel_path, puzzle_type, answer_length): + var puzzle_choices = _filterBestPuzzles(_answers_by_length[answer_length]) + if puzzle_type != kWhiteMiddle: + # TODO: Do we even need this? + pass + if puzzle_choices.empty(): + print("No possible puzzles for panel %s" % panel_path) + else: + var answer_id = _pickRandom(puzzle_choices) + if puzzle_type == kWhiteMiddle: + _setPanel(panel_path, answer_id, answer_id) + else: + var hint_choices = _puzzle_by_id[answer_id][1][puzzle_type] + var hint_id = _pickRandom(hint_choices) + _setPanel(panel_path, hint_id, answer_id) + + +func _filterBestPuzzles(input): + var not_uniqued = [] + if _unique_pool == "": + not_uniqued = input + elif _answers_by_unique_pool.has(_unique_pool): + for word_id in input: + if not _answers_by_unique_pool[_unique_pool].has(word_id): + not_uniqued.append(word_id) + else: + not_uniqued = input + #if _isFlag(kMustReuseAnswer): + # var possible = [] + # for word_id in not_uniqued: + # if _puzzle_by_id[word_id][1].size() > 1: + # possible.append(word_id) + # not_uniqued = possible + var result = [] + for word_id in not_uniqued: + if _needs_reuse.has(word_id): + result.append(word_id) + if result.empty(): + for word_id in not_uniqued: + result.append(word_id) + if _possible_reuse.has(word_id): + result.append(word_id) + return result + + +func _setPanel(panel_path, hint_id, answer_id): + if _unique_pool != "": + _answers_by_unique_pool[_unique_pool].append(answer_id) + panel_mapping.append([panel_path, _answer_by_id[hint_id], _answer_by_id[answer_id]]) + if not _isFlag(kMustReuseAnswer): + if _needs_reuse.has(answer_id): + _needs_reuse.erase(answer_id) + _possible_reuse.append(answer_id) + _total_generated += 1 + emit_signal("generator_status", "Generating puzzles... (%d/?)" % _total_generated) diff --git a/randomizer/load.gd b/randomizer/load.gd new file mode 100644 index 0000000..727e368 --- /dev/null +++ b/randomizer/load.gd @@ -0,0 +1,18 @@ +extends "res://scripts/load.gd" + + +func _load(): + global._print("Hooked Load Start") + + var randomizer = global.get_node("Randomizer") + + # Apply the randomized panels. + var panels_parent = $Panels + for puzzle in randomizer.generator.panel_mapping: + var panel = panels_parent.get_node(puzzle[0]) + panel.text = puzzle[1] + panel.answer = puzzle[2] + + # Proceed with the rest of the load. + global._print("Hooked Load End") + ._load() diff --git a/randomizer/panelEnd.gd b/randomizer/panelEnd.gd new file mode 100644 index 0000000..81f07d6 --- /dev/null +++ b/randomizer/panelEnd.gd @@ -0,0 +1,7 @@ +extends "res://scripts/panelEnd.gd" + + +func handle_correct(): + # We don't call the base method because we want to suppress the original + # behaviour. + global.solved -= 1 diff --git a/randomizer/panelInput.gd b/randomizer/panelInput.gd new file mode 100644 index 0000000..48d6324 --- /dev/null +++ b/randomizer/panelInput.gd @@ -0,0 +1,5 @@ +extends "res://scripts/panelInput.gd" + + +func uncomplete(): + global._print("Filtered out panel uncompletion") diff --git a/randomizer/panelLevelSwitch.gd b/randomizer/panelLevelSwitch.gd new file mode 100644 index 0000000..06df02b --- /dev/null +++ b/randomizer/panelLevelSwitch.gd @@ -0,0 +1,7 @@ +extends "res://scripts/panelLevelSwitch.gd" + + +func handle_correct(): + # We don't call the base method because we want to suppress the original + # behaviour. + global.solved -= 1 diff --git a/randomizer/randomizer.gd b/randomizer/randomizer.gd new file mode 100644 index 0000000..ff558a3 --- /dev/null +++ b/randomizer/randomizer.gd @@ -0,0 +1,26 @@ +extends Node + +const my_version = "0.1.0" + +var SCRIPT_generator + +var generator + +signal finished_randomizing +signal randomizer_status + + +func start(gen_seed = ""): + generator = SCRIPT_generator.new($GeneratedPuzzles) + generator.connect("generator_status", self, "statusUpdate") + generator.generate(gen_seed) + + emit_signal("finished_randomizing") + + +func statusUpdate(text): + emit_signal("randomizer_status", text) + + +func getSaveFileName(): + return "zzRN_%d" % generator.gen_seed diff --git a/randomizer/settings_buttons.gd b/randomizer/settings_buttons.gd new file mode 100644 index 0000000..4e656b0 --- /dev/null +++ b/randomizer/settings_buttons.gd @@ -0,0 +1,16 @@ +extends Button + + +func _ready(): + pass + + +func _start_pressed(): + self.disabled = true + + var randomizer = global.get_node("Randomizer") + randomizer.start(self.get_parent().get_node("seed_box").text) + + +func _back_pressed(): + fader._fade_start("main_menu") diff --git a/randomizer/settings_screen.gd b/randomizer/settings_screen.gd new file mode 100644 index 0000000..708b4ef --- /dev/null +++ b/randomizer/settings_screen.gd @@ -0,0 +1,78 @@ +extends Spatial + + +func _ready(): + # Undo the load screen removing our cursor + get_tree().get_root().set_disable_input(false) + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + + # Create the global Randomizer node, if it doesn't already exist. + if not global.has_node("Randomizer"): + var randomizer_script = ResourceLoader.load("user://maps/randomizer/randomizer.gd") + var randomizer_instance = randomizer_script.new() + randomizer_instance.name = "Randomizer" + global.add_child(randomizer_instance) + + randomizer_instance.SCRIPT_generator = load("user://maps/randomizer/generator.gd") + + var generated_puzzles = ResourceLoader.load("user://maps/randomizer/generated_puzzles.gd") + var generated_puzzles_instance = generated_puzzles.new() + generated_puzzles_instance.name = "GeneratedPuzzles" + randomizer_instance.add_child(generated_puzzles_instance) + + # Let's also inject any scripts we need to inject now. + installScriptExtension(ResourceLoader.load("user://maps/randomizer/load.gd")) + installScriptExtension(ResourceLoader.load("user://maps/randomizer/panelEnd.gd")) + installScriptExtension(ResourceLoader.load("user://maps/randomizer/panelInput.gd")) + installScriptExtension(ResourceLoader.load("user://maps/randomizer/panelLevelSwitch.gd")) + installScriptExtension(ResourceLoader.load("user://maps/randomizer/worldTransporter.gd")) + + var randomizer = global.get_node("Randomizer") + randomizer.connect("finished_randomizing", self, "randomizationSuccessful") + randomizer.connect("randomizer_status", self, "randomizationStatus") + + # Show client version. + self.get_node("Panel/title").text = "RANDOMIZER (%s)" % randomizer.my_version + + # Increase font size in text boxes. + var field_font = DynamicFont.new() + field_font.font_data = load("res://fonts/CutiveMono_Regular.ttf") + field_font.size = 36 + + self.get_node("Panel/seed_box").add_font_override("font", field_font) + + +# Adapted from https://gitlab.com/Delta-V-Modding/Mods/-/blob/main/game/ModLoader.gd +func installScriptExtension(childScript: Resource): + # Force Godot to compile the script now. + # We need to do this here to ensure that the inheritance chain is + # properly set up, and multiple mods can chain-extend the same + # class multiple times. + # This is also needed to make Godot instantiate the extended class + # when creating singletons. + # The actual instance is thrown away. + childScript.new() + + var parentScript = childScript.get_base_script() + var parentScriptPath = parentScript.resource_path + global._print("ModLoader: Installing script extension over %s" % parentScriptPath) + childScript.take_over_path(parentScriptPath) + + +func randomizationStatus(message): + var popup = self.get_node("Panel/AcceptDialog") + popup.window_title = "Randomizing..." + popup.dialog_text = message + popup.popup_exclusive = true + popup.get_ok().visible = false + popup.popup_centered() + + +func randomizationSuccessful(): + var randomizer = global.get_node("Randomizer") + + # Switch to LL1 + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + global.map = "level1" + global.save_file = randomizer.getSaveFileName() + var _discard = get_tree().change_scene("res://scenes/load_screen.tscn") diff --git a/randomizer/worldTransporter.gd b/randomizer/worldTransporter.gd new file mode 100644 index 0000000..1488907 --- /dev/null +++ b/randomizer/worldTransporter.gd @@ -0,0 +1,6 @@ +extends "res://scripts/worldTransporter.gd" + + +func _body_entered(_body): + # Do not transport the player. + pass -- cgit 1.4.1