From f834267a75c873d143e1f7f56f73faaa5e15cf2f Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Mon, 9 Dec 2024 12:50:24 -0500 Subject: First pass at panel randomization --- Archipelago/client.gd | 2 + Archipelago/generator.gd | 1027 ++++++++++++++++++++++++++++++++++++++++ Archipelago/load.gd | 7 +- Archipelago/settings_screen.gd | 46 ++ 4 files changed, 1080 insertions(+), 2 deletions(-) create mode 100644 Archipelago/generator.gd diff --git a/Archipelago/client.gd b/Archipelago/client.gd index aa50069..78058ca 100644 --- a/Archipelago/client.gd +++ b/Archipelago/client.gd @@ -2,6 +2,7 @@ extends Node var SCRIPT_doorControl var SCRIPT_effects +var SCRIPT_generator var SCRIPT_location var SCRIPT_multiplayer var SCRIPT_mypainting @@ -43,6 +44,7 @@ const kPILGRIMAGE = 3 const kNO_PANEL_SHUFFLE = 0 const kREARRANGE_PANELS = 1 +const kEXPERIMENTAL_PANELS = 2 const kCLASSIFICATION_LOCAL_NORMAL = 1 const kCLASSIFICATION_LOCAL_REDUCED = 2 diff --git a/Archipelago/generator.gd b/Archipelago/generator.gd new file mode 100644 index 0000000..2aeca82 --- /dev/null +++ b/Archipelago/generator.gd @@ -0,0 +1,1027 @@ +extends Node + +var panel_mapping = [] +var painting_mapping = [] +var steady_mapping = [] +var gen_seed +var is_set_seed = false + +var _gen_forms +var _gen_paintings +var _gen_wanderlust +var _gen_addition +var _gen_walls +var _gen_combos + +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 _hint_by_path = {} +var _answer_by_path = {} +var _painting_puzzles = [] +var _chain_cache = {} +var _short_answer_length = 4 + +var _unique_pool = "" +var _answers_by_unique_pool = {} +var _needs_reuse = [] +var _possible_reuse = [] + +var _cur_panel = "" + +const kOrangeMiddle = -2 +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 kColorIs = 16 + +const kPuzzleTypes = [ + kWhiteMiddle, + kWhiteTop, + kWhiteBottom, + kYellowTop, + kYellowMiddle, + kBlackTop, + kBlackMiddle, + kBlackBottom, + kDoubleBlackBottom, + kRedTop, + kRedMiddle, + kRedBottom, + kBlueTop, + kBlueMiddle, + kBlueBottom, + kPurpleTop, + kPurpleMiddle, + kColorIs +] + +const kMustReuseAnswer = 1 +const kObscureHint = 2 +const kShortAnswer = 4 +const kForcePalindrome = 8 + +signal generator_status + + +func _init(gen_puzzles): + _gen_forms = gen_puzzles[0] + _gen_paintings = gen_puzzles[1] + _gen_wanderlust = gen_puzzles[2] + _gen_addition = gen_puzzles[3] + _gen_walls = gen_puzzles[4] + _gen_combos = gen_puzzles[5] + + +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) + is_set_seed = false + else: + gen_seed = int(chosen_seed) + is_set_seed = true + + _rng = RandomNumberGenerator.new() + _rng.seed = gen_seed + + # Create some helpful indexes. + _answer_by_id = [] + _answers_by_type = {} + _answers_by_length = {} + _puzzle_by_id = [] + _hint_by_path = {} + _answer_by_path = {} + _painting_puzzles = _gen_paintings + var openable_answers = [] + + for puzzle_type in kPuzzleTypes: + _answers_by_type[puzzle_type] = [] + + var puzzle_id = 0 + for puzzle in _gen_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") + _setFlag(kObscureHint) + _setPanel("Heteronym Room/Panel_entrance_entrance", open_answer_id, open_answer_id) + _clearFlag(kObscureHint) + + _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 + ) + + _setUniquePool("scientific") + _setPanel("Chemistry Room/Panel_open", open_answer_id, open_answer_id) + _setPanel( + "Chemistry Room/Panel_close", + _pickRandom(_puzzle_by_id[open_answer_id][1][kBlackBottom]), + open_answer_id + ) + + _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) + + _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) + #_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) + + _setFlag(kForcePalindrome) + _gSingle("Palindrome Room/Panel_solos_solos", kWhiteMiddle) + _gSingle("Palindrome Room/Panel_racecar_racecar", kWhiteMiddle) + _gSingle("Palindrome Room/Panel_level_level", kWhiteMiddle) + _gCopyHidden("Palindrome Room/Panel_solos_solos", "Palindrome Room/Panel_solos_solos_2") + _gCopyHidden("Palindrome Room/Panel_racecar_racecar", "Palindrome Room/Panel_racecar_racecar_2") + _gCopyHidden("Palindrome Room/Panel_level_level", "Palindrome Room/Panel_level_level_2") + _clearFlag(kForcePalindrome) + + _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("bearer") + _setFlag(kShortAnswer) + _short_answer_length = 6 + _gChain("Cross Room/Panel_part_rap", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_heart_tar", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_smile_lime", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_snow_won", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_warts_star", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_pots_top", [kYellowMiddle, kRedMiddle]) + _gChain("Cross Room/Panel_silent_list", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_silent_list_2", [kYellowMiddle, kRedMiddle]) + _gChain("Cross Room/Panel_tent_net", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_peace_ape", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_space_cape", [kRedMiddle, kYellowMiddle]) + _gChain("Cross Room/Panel_bowl_low", [kRedMiddle, kYellowMiddle]) + _clearFlag(kShortAnswer) + + _setUniquePool("bold") + _gSingle("Truncate Room/Panel_sushi_hi", kRedMiddle) + _gSingle("Truncate Room/Panel_thistle_this", kRedMiddle) + _gDouble("Truncate Room/Panel_undead_dead", "Truncate Room/Panel_deadline_dead", kRedMiddle) + _gDouble("Truncate Room/Panel_landmass_mass", "Truncate Room/Panel_massacred_mass", kRedMiddle) + + _gSingle("Challenge Room/Panel_welcome_welcome", kWhiteMiddle) + _writePanel("Entry Room/Panel_return_return", "%s back" % _answer_by_path["Challenge Room/Panel_welcome_welcome"], "%s back" % _answer_by_path["Challenge Room/Panel_welcome_welcome"]) + + _setUniquePool("steady") + _gSteady("Rock Room/Panel_limelight_lime", kRedMiddle) + _gSteady("Rock Room/Panel_blue_blueberry", kBlueMiddle) + _gSteady("Rock Room/Panel_lump_plum", kYellowMiddle) + _gSteady("Rock Room/Panel_hairy_cherry", kBlueTop) + _gSteady("Rock Room/Panel_blue_orange", kBlackBottom) + _gSteady("Rock Room/Panel_melon_lemon", kYellowMiddle) + _gSteady("Rock Room/Panel_herald_emerald", kPurpleMiddle) + _gSteady("Rock Room/Panel_sap_sapphire", kBlueMiddle) + _gSteady("Rock Room/Panel_thistle_amethyst", kPurpleTop) + _gSteady("Rock Room/Panel_bury_ruby", kYellowMiddle) + _gSteady("Rock Room/Panel_antechamber_amber", kRedMiddle) + _gSteady("Rock Room/Panel_top_topaz", kBlueMiddle) + _gSteady("Rock Room/Panel_lielack_lilac", kWhiteTop) + _gSteady("Rock Room/Panel_soar_rose", kBlackTop) + _gSteady("Rock Room/Panel_incarnation_carnation", kRedMiddle) + _gSteady("Rock Room/Panel_sun_sunflower", kBlueMiddle) + + _clearUniquePool() + + _gPaired("Shuffle Room/Panel_sword_words", "Shuffle Room/Panel_words_sword", kYellowMiddle) + _gPaired("Shuffle Room/Panel_turn_runt", "Shuffle Room/Panel_turn_runt2", kYellowMiddle) + _gPaired("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_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", kYellowMiddle) + _gSingle("Shuffle Room/Panel_tower", kYellowMiddle) + _gPaired("Shuffle Room/Panel_far_far", "Shuffle Room/Panel_near_near", kWhiteMiddle) + + _gSingle("Maze Room/Panel_reflow_flower", kYellowMiddle) + + _gSingle("Appendix Room/Panel_rat_tar", kBlackMiddle) + + _gSingle("Painting Room/Panel_eon_one", kYellowMiddle) + _gSingle("Painting Room/Panel_to_two", kRedMiddle) + _setFlag(kShortAnswer) + _short_answer_length = 4 + _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) + _gSingle("Painting Room/Panel_runts_turns", kYellowMiddle) + _gOrangeAddition("Painting Room/Panel_send_use_turns") + _gOrangeWord("Painting Room/Panel_trust_06890") + _gOrangeNumber("Painting Room/Panel_06890_trust") + _writePanel("Painting Room/Panel_order_onepathmanyturns", "order", "%s road %s %s" % [_answer_by_path["Painting Room/Panel_eon_one"], _answer_by_path["Painting Room/Panel_any_many"], _answer_by_path["Painting Room/Panel_send_use_turns"]]) + + _gStack2("Ceiling Room/Panel_blue_top_1", kBlueTop, "Ceiling Room/Panel_red_bot_1", kRedBottom) + _gStack2( + "Ceiling Room/Panel_red_mid_2", kRedMiddle, "Ceiling Room/Panel_blue_bot_2", kBlueBottom + ) + _gStack2( + "Ceiling Room/Panel_blue_mid_3", kBlueMiddle, "Ceiling Room/Panel_red_bot_3", kRedBottom + ) + _gStack2("Ceiling Room/Panel_red_top_4", kRedTop, "Ceiling Room/Panel_blue_mid_4", kBlueMiddle) + _gStack2( + "Ceiling Room/Panel_yellow_top_5", kYellowTop, "Ceiling Room/Panel_blue_bot_5", kBlueBottom + ) + _gStack2( + "Ceiling Room/Panel_blue_top_6", kBlueTop, "Ceiling Room/Panel_yellow_mid_6", kYellowMiddle + ) + # gen_.GeneratePanelStack("", {}, "Panel_blue_mid_7", kBlue, "Panel_yellow_bot_7", kYellow); + _gStack2( + "Ceiling Room/Panel_yellow_mid_8", + kYellowMiddle, + "Ceiling Room/Panel_black_bot_8", + kBlackBottom + ) + # gen_.GeneratePanelStack("Panel_black_top_9", kBlack, "", {}, "Panel_yellow_bot_9", kYellow); + _gStack2( + "Ceiling Room/Panel_yellow_top_10", + kYellowTop, + "Ceiling Room/Panel_black_bot_10", + kBlackBottom + ) + _gStack2( + "Ceiling Room/Panel_black_top_11", + kBlackTop, + "Ceiling Room/Panel_yellow_mid_11", + kYellowMiddle + ) + _gStack2( + "Ceiling Room/Panel_black_top_12", kBlackTop, "Ceiling Room/Panel_red_bot_12", kRedBottom + ) + _gStack2( + "Ceiling Room/Panel_red_top_13", kRedTop, "Ceiling Room/Panel_black_bot_13", kBlackBottom + ) + _gStack2( + "Ceiling Room/Panel_black_mid_14", kBlackMiddle, "Ceiling Room/Panel_red_bot_14", kRedBottom + ) + _gStack2( + "Ceiling Room/Panel_black_top_15", kBlackTop, "Ceiling Room/Panel_red_mid_15", kRedMiddle + ) + #gen_.GenerateSinglePanel("Panel_answer_1", kBottom, kRed); + #_gSingle("Ceiling Room/Panel_answer_2", kBlackTop) + _writePanel("Ceiling Room/Panel_answer_1", "article", "the") + _writePanel("Ceiling Room/Panel_answer_2", "paints", "art") + _setFlag(kShortAnswer) + _short_answer_length = 4 + _gSingle("Ceiling Room/Panel_answer_3", kBlueMiddle) + _clearFlag(kShortAnswer) + _gSingle("Ceiling Room/Panel_answer_4", kBlackTop) + _writePanel("Countdown Panels/Panel_artistic_artistic", "", "the art %s %s" % [_answer_by_path["Ceiling Room/Panel_answer_3"], _answer_by_path["Ceiling Room/Panel_answer_4"]]) + + _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) + + _gSingle("Color Arrow Room/Panel_red_near", kWhiteMiddle) + _gSingle("Color Arrow Room/Panel_blue_near", kWhiteMiddle) + _gSingle("Color Arrow Room/Panel_yellow_near", kWhiteMiddle) + _gSingle("Color Arrow Room/Panel_orange_near", kWhiteMiddle) + _gSingle("Color Arrow Room/Panel_purple_near", kWhiteMiddle) + _gSingle("Color Arrow Room/Panel_green_near", kWhiteMiddle) + _gCopy("Color Arrow Room/Panel_red_near", "Color Arrow Room/Panel_red_afar") + _gCopy("Color Arrow Room/Panel_blue_near", "Color Arrow Room/Panel_blue_afar") + _gCopy("Color Arrow Room/Panel_yellow_near", "Color Arrow Room/Panel_yellow_afar") + _gCopy("Color Arrow Room/Panel_orange_near", "Color Arrow Room/Panel_orange_afar") + _gCopy("Color Arrow Room/Panel_purple_near", "Color Arrow Room/Panel_purple_afar") + _gCopy("Color Arrow Room/Panel_green_near", "Color Arrow Room/Panel_green_afar") + #painting_mapping.append(["colors_painting", "hatkirby"]) + + _gOrangeNumber("Orange Room/Panel_lust") + _gOrangeNumber("Orange Room/Panel_read") + _gOrangeNumber("Orange Room/Panel_sew") + _gOrangeNumber("Orange Room/Panel_dead") + _gOrangeNumber("Tower Room/Panel_834283054_undaunted") + _gOrangeWord("Orange Room/Panel_learn") + _gOrangeWord("Orange Room/Panel_dust") + _gOrangeWord("Orange Room/Panel_star") + _gOrangeWord("Orange Room/Panel_wander") + _gOrangeWord("Tower Room/Panel_wanderlust_1234567890") + _gOrangeAddition("Tower Room/Panel_dads_ale_dead_1") + _gOrangeAddition("Tower Room/Panel_art_art_eat_2") + _gOrangeAddition("Tower Room/Panel_deer_wren_rats_3") + _gOrangeAddition("Tower Room/Panel_learns_unsew_unrest_4") + _gOrangeAddition("Tower Room/Panel_drawl_runs_enter_5") + _gOrangeAddition("Tower Room/Panel_reads_rust_lawns_6") + _gOrangeAddition("Tower Room/Panel_waded_wee_warts_7") + + _gPaintingPuzzle("Panel Room/Panel_painting_flower", "flower_painting_gray") + _gPaintingPuzzle("Panel Room/Panel_painting_eye", "eye_painting_gray") + _gPaintingPuzzle("Panel Room/Panel_painting_snowman", "snowman_painting_gray") + _gPaintingPuzzle("Panel Room/Panel_painting_owl", "owl_painting_gray") + _gPaintingPuzzle("Panel Room/Panel_painting_panda", "panda_painting_gray") + + _gStack2("Open Areas/Panel_angered_enraged", kYellowMiddle, "", kWhiteBottom) + _gStack2("Open Areas/Panel_vote_veto", kYellowMiddle, "", kBlackBottom) + + #_setFlag(kObscureHint) + _gSingle("Entry Room/Panel_forward_forward", kWhiteMiddle) + _gSingle("Entry Room/Panel_between_between", kWhiteMiddle) + _gSingle("Entry Room/Panel_backward_backward", 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) + + _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) + + _gPaired("Appendix Room/Panel_left_left", "Appendix Room/Panel_right_right", kWhiteMiddle) + + _gSingle("Hallway Room/Panel_hollow_hollow", kWhiteMiddle) + _gSingle("Hallway Room/Panel_out_out", kWhiteMiddle) + + _gSingle("Open Areas/Panel_staircase", kWhiteMiddle) + _gSingle("Open Areas/Panel_smile_smile", kWhiteMiddle) + _gSingle("Open Areas/Panel_undistracted", kWhiteMiddle) + _gSingle("Open Areas/Panel_stargazer_stargazer", 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) + _gSingle("Backside Room/Panel_paranoid_paranoid", kWhiteMiddle) + _gPaired("Backside Room/Panel_salt_pepper", "Backside Room/Panel_pepper_salt", kBlackBottom) + + _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 apply(scene): + var panels_parent = scene.get_node("Panels") + var found_panels = [] + for puzzle in panel_mapping: + var panel = panels_parent.get_node(puzzle[0]) + panel.text = puzzle[1] + panel.answer = puzzle[2] + found_panels.append(puzzle[0]) + + for panel_group in panels_parent.get_children(): + for panel_panel in panel_group.get_children(): + var relpath = String(panels_parent.get_path_to(panel_panel)) + if !found_panels.has(relpath): + print("Unrandomized: %s" % relpath) + + for mapping in painting_mapping: + var scene_path = "res://nodes/paintings/%s.tscn" % mapping[1] + var painting_scene = load(scene_path) + var new_painting = painting_scene.instance() + new_painting.set_name("%s_new" % mapping[0]) + + var old_painting = scene.get_node("Decorations/Paintings").get_node(mapping[0]) + new_painting.translation = old_painting.translation + new_painting.rotation = old_painting.rotation + + scene.get_node("Decorations/Paintings").add_child(new_painting) + old_painting.queue_free() + + # Randomize THE COLORFUL - WALLS + var gridmap = scene.get_node("GridMap") + var mesh_library = gridmap.mesh_library + var mapvec1 = gridmap.world_to_map(gridmap.to_local(Vector3(-14.5, 0, -95.5))) + var mapvec2 = gridmap.world_to_map(gridmap.to_local(Vector3(-9.5, 6.5, -84.5))) + var mapvec_ex = gridmap.world_to_map(gridmap.to_local(Vector3(-10.5, 0.5, -86.5))) + + var walls_puzzle = _pickRandom(_gen_walls) + var mesh_item = mesh_library.find_item_by_name(walls_puzzle[1]) + + for x in range(mapvec1.x, mapvec2.x + 1): + for y in range(mapvec1.y, mapvec2.y + 1): + for z in range(mapvec1.z, mapvec2.z + 1): + if gridmap.get_cell_item(x,y,z) != GridMap.INVALID_CELL_ITEM: + gridmap.set_cell_item(x, y, z, mesh_item) + + gridmap.set_cell_item(mapvec_ex.x, mapvec_ex.y, mapvec_ex.z, mesh_library.find_item_by_name("MeshInstance2")) + scene.get_node("Doors/Doorway Room Doors/Door_green/Hinge/MeshInstance").set_surface_material(0, mesh_library.get_item_mesh(mesh_item).surface_get_material(0)) + + var walls_puzzle_node = panels_parent.get_node("Doorways Room/Panel_path_i") + walls_puzzle_node.answer = walls_puzzle[0] + + # Randomize ceilings of The Steady + var ceilings = [ + [71.5, 98.5], [64.5, 98.5], [57.5, 98.5], [50.5, 98.5], [43.5, 98.5], [36.5, 98.5], + [71.5, 91.5], [64.5, 91.5], [57.5, 91.5], [50.5, 91.5], [43.5, 91.5], [36.5, 91.5], + [57.5, 84.5], [50.5, 84.5], [43.5, 84.5], [36.5, 84.5] + ] + for i in range(0, 16): + var color_mesh = mesh_library.find_item_by_name(steady_mapping[i]) + var ceilingvec1 = gridmap.world_to_map(gridmap.to_local(Vector3(ceilings[i][0], 5.5, ceilings[i][1]))) + for x in range(ceilingvec1.x - 4, ceilingvec1.x + 1): + for z in range(ceilingvec1.z - 4, ceilingvec1.z + 1): + gridmap.set_cell_item(x, ceilingvec1.y, z, color_mesh) + + +func _pickRandom(set): + if set.size() == 0: + print("This is a problem: %s" % _cur_panel) + 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): + _cur_panel = panel_path + 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): + _cur_panel = panel1_path + 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 _gQuadruple(panel1_path, panel2_path, panel3_path, panel4_path, puzzle_type): + _cur_panel = panel1_path + 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() > 3: + 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) + hint_choices.erase(hint2_id) + var hint3_id = _pickRandom(hint_choices) + hint_choices.erase(hint3_id) + var hint4_id = _pickRandom(hint_choices) + _setPanel(panel1_path, hint1_id, answer_id) + _setPanel(panel2_path, hint2_id, answer_id) + _setPanel(panel3_path, hint3_id, answer_id) + _setPanel(panel4_path, hint4_id, answer_id) + + +func _gPaired(panel1_path, panel2_path, puzzle_type): + _cur_panel = panel1_path + var needed_type = puzzle_type + if puzzle_type == kWhiteMiddle: + needed_type = kBlackBottom + 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 _gStack2(panel1_path, puzzle_type1, panel2_path, puzzle_type2): + _cur_panel = panel1_path + 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) + if panel2_path != "": + _setPanel(panel2_path, hint2_id, answer_id) + + +func _gChain(panel_path, puzzle_types): + _cur_panel = panel_path + var just_answers = [] + var hints_by_answer = {} + puzzle_types.invert() + + if _chain_cache.has(puzzle_types): + just_answers = _chain_cache[puzzle_types][0] + hints_by_answer = _chain_cache[puzzle_types][1] + else: + var remaining = [] + for ptype in puzzle_types: + if remaining.empty(): + for answer in _answers_by_type[ptype]: + for choice in _puzzle_by_id[answer][1][ptype]: + remaining.append([choice, answer]) + elif ptype == kOrangeMiddle: + var newrem = [] + for puzzle in remaining: + if _gen_wanderlust.has(puzzle[0]): + newrem.append(puzzle) + if newrem.empty(): + print("No possible puzzles for panel %s" % panel_path) + return + remaining = newrem + else: + var newrem = [] + for puzzle in remaining: + if _puzzle_by_id[puzzle[0]][1].has(ptype): + for choice in _puzzle_by_id[puzzle[0]][1][ptype]: + newrem.append([choice, puzzle[1]]) + if newrem.empty(): + print("No possible puzzles for panel %s" % panel_path) + return + remaining = newrem + for puzzle in remaining: + if !just_answers.has(puzzle[1]): + just_answers.append(puzzle[1]) + hints_by_answer[puzzle[1]] = [puzzle[0]] + else: + hints_by_answer[puzzle[1]].append(puzzle[0]) + _chain_cache[puzzle_types] = [just_answers, hints_by_answer] + var puzzle_choices = _filterBestPuzzles(just_answers) + if puzzle_choices.empty(): + print("No possible puzzles for panel %s" % panel_path) + else: + var answer_id = _pickRandom(puzzle_choices) + var hint_choices = hints_by_answer[answer_id] + var hint_id = _pickRandom(hint_choices) + if puzzle_types[puzzle_types.size()-1] == kOrangeMiddle: + var hint = _applyCipher(_answer_by_id[hint_id]) + _writePanel(panel_path, hint, _answer_by_id[answer_id]) + else: + _setPanel(panel_path, hint_id, answer_id) + + +func _gCopy(panel1_path, panel2_path): + _cur_panel = panel2_path + _writePanel(panel2_path, _hint_by_path[panel1_path], _answer_by_path[panel1_path]) + + +func _gCopyAnswer(panel1_path, panel2_path): + _cur_panel = panel2_path + _writePanel(panel2_path, _answer_by_path[panel1_path], _answer_by_path[panel1_path]) + + +func _gCopyHidden(panel1_path, panel2_path): + _cur_panel = panel2_path + _writePanel(panel2_path, "?".repeat(_answer_by_path[panel1_path].length()), _answer_by_path[panel1_path]) + + +func _gExactLength(panel_path, puzzle_type, answer_length): + _cur_panel = panel_path + 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 _gOrangeNumber(panel_path): + _cur_panel = panel_path + var word_id = _pickRandom(_gen_wanderlust) + var answer = _answer_by_id[word_id] + var hint = _applyCipher(answer) + _writePanel(panel_path, hint, answer) + + +func _gOrangeWord(panel_path): + _cur_panel = panel_path + var word_id = _pickRandom(_gen_wanderlust) + var hint = _answer_by_id[word_id] + var answer = _applyCipher(hint) + _writePanel(panel_path, hint, answer) + + +func _gOrangeAddition(panel_path): + _cur_panel = panel_path + var puzzle = _pickRandom(_gen_addition) + var word1 = _answer_by_id[puzzle[0]] + var word2 = _answer_by_id[puzzle[1]] + var solution = _answer_by_id[puzzle[2]] + _writePanel(panel_path, "%s + %s" % [word1, word2], solution) + + +func _gPaintingPuzzle(panel_path, painting_name): + _cur_panel = panel_path + var chosen = _pickRandom(_painting_puzzles) + _painting_puzzles.erase(chosen) + _writePanel(panel_path, "painting", chosen[1]) + painting_mapping.append([painting_name, chosen[0]]) + + +func _gCombo(panel_path, left_type, right_type): + _cur_panel = panel_path + var puzzles = _gen_combos[left_type][right_type] + var chosen = _pickRandom(puzzles) + var hint_text + if chosen[1] == -1: + hint_text = _answer_by_id[chosen[0]] + else: + hint_text = "%s %s" % [_answer_by_id[chosen[0]], _answer_by_id[chosen[1]]] + _writePanel(panel_path, hint_text, _answer_by_id[chosen[2]]) + + +func _gSteady(panel_path, puzzle_type): + _cur_panel = panel_path + var pre_choices = _filterBestPuzzles(_answers_by_type[kColorIs]) + var puzzle_choices = [] + for word_id in pre_choices: + if _puzzle_by_id[word_id][1].has(puzzle_type): + puzzle_choices.append(word_id) + 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) + var color_choices = _puzzle_by_id[answer_id][1][kColorIs] + var color_id = _pickRandom(color_choices) + var color_word = _answer_by_id[color_id] + _setPanel(panel_path, hint_id, answer_id) + + if color_word == "red": + steady_mapping.append("MeshInstance7") + elif color_word == "blue": + steady_mapping.append("MeshInstance4") + elif color_word == "green": + steady_mapping.append("MeshInstance2") + elif color_word == "black": + steady_mapping.append("MeshInstance6") + elif color_word == "white": + steady_mapping.append("MeshInstance5") + elif color_word == "brown": + steady_mapping.append("MeshInstance3") + elif color_word == "orange": + steady_mapping.append("MeshInstance10") + elif color_word == "yellow": + steady_mapping.append("MeshInstance9") + elif color_word == "purple": + steady_mapping.append("MeshInstance8") + + +func _applyCipher(text): + var result = text + for i in range(result.length()): + if result.substr(i,1) == "w": + result[i] = "1" + elif result.substr(i,1) == "a": + result[i] = "2" + elif result.substr(i,1) == "n": + result[i] = "3" + elif result.substr(i,1) == "d": + result[i] = "4" + elif result.substr(i,1) == "e": + result[i] = "5" + elif result.substr(i,1) == "r": + result[i] = "6" + elif result.substr(i,1) == "l": + result[i] = "7" + elif result.substr(i,1) == "u": + result[i] = "8" + elif result.substr(i,1) == "s": + result[i] = "9" + elif result.substr(i,1) == "t": + result[i] = "0" + return result + + +func _filterBestPuzzles(input): + var acceptable = [] + for word_id in input: + if ( + _unique_pool != "" + and _answers_by_unique_pool.has(_unique_pool) + and _answers_by_unique_pool[_unique_pool].has(word_id) + ): + continue + if _isFlag(kShortAnswer) and _answer_by_id[word_id].length() > _short_answer_length: + continue + if _isFlag(kForcePalindrome) and _answer_by_id[word_id] != _reverseString(_answer_by_id[word_id]): + continue + acceptable.append(word_id) + #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 acceptable: + if _needs_reuse.has(word_id): + result.append(word_id) + if result.empty(): + for word_id in acceptable: + 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) + + var hint_text = _answer_by_id[hint_id] + if _isFlag(kObscureHint): + var numToObscure = 1 + if hint_text.length()/3 > 0: + numToObscure = _rng.randi_range(1, hint_text.length()/3) + var iota = range(0, hint_text.length()) + var order = [] + while not iota.empty(): + var i = _rng.randi_range(0, iota.size() - 1) + order.append(iota[i]) + iota.remove(i) + for i in range(0, numToObscure): + if hint_text[order[i]] != " " and hint_text[order[i]] != "-": + hint_text[order[i]] = "?" + + _writePanel(panel_path, hint_text, _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) + + +func _writePanel(panel_path, hint, answer): + panel_mapping.append([panel_path, hint, answer]) + _hint_by_path[panel_path] = hint + _answer_by_path[panel_path] = answer + _total_generated += 1 + emit_signal("generator_status", "Generating puzzles... (%d/?)" % _total_generated) + global._print("%s : %s -> %s" % [panel_path, hint, answer]) + + +func _reverseString(s): + var r = "" + for i in range(s.length()-1, -1, -1): + r += s[i] + return r diff --git a/Archipelago/load.gd b/Archipelago/load.gd index 931dfde..be209c3 100644 --- a/Archipelago/load.gd +++ b/Archipelago/load.gd @@ -135,7 +135,7 @@ func _load(): new_another_cdp.maxlength = (apclient._level_2_requirement - 1) new_another_cdp.nested = true get_node("CountdownPanels").add_child(new_another_cdp) - another_cdp.replace_with = "" + another_cdp.replace_with = "../CountdownPanel_level2_0" another_cdp.queue_free() else: var another_replacement = another_cdp.get_node(another_cdp.replace_with) @@ -275,7 +275,7 @@ func _load(): clear_gridmap_tile(25.5, 1.5, 11.5) clear_gridmap_tile(47.5, 1.5, 11.5) - if apclient._panel_shuffle == apclient.kREARRANGE_PANELS: + if apclient._panel_shuffle == apclient.kREARRANGE_PANELS or apclient._panel_shuffle == apclient.kEXPERIMENTAL_PANELS: # Do the actual shuffling. var panel_pools = {} for panel in gamedata.panels: @@ -342,6 +342,9 @@ func _load(): new_answer += " " new_answer += panels_parent.get_node("Painting Room/Panel_send_use_turns").answer panels_parent.get_node("Painting Room/Panel_order_onepathmanyturns").answer = new_answer + + if apclient._panel_shuffle == apclient.kEXPERIMENTAL_PANELS: + apclient.get_node("Generator").apply(self) # Handle our other static panels after panel randomization, so that the old # values can enter the pool, if necessary. diff --git a/Archipelago/settings_screen.gd b/Archipelago/settings_screen.gd index 6c64b15..956d966 100644 --- a/Archipelago/settings_screen.gd +++ b/Archipelago/settings_screen.gd @@ -1,5 +1,10 @@ extends Spatial +var generator_thread = Thread.new() +var generator + +signal finished_randomizing + func _ready(): # Some helpful logging. @@ -25,6 +30,7 @@ func _ready(): apclient_instance.SCRIPT_doorControl = load("user://maps/Archipelago/doorControl.gd") apclient_instance.SCRIPT_effects = load("user://maps/Archipelago/effects.gd") + apclient_instance.SCRIPT_generator = load("user://maps/Archipelago/generator.gd") apclient_instance.SCRIPT_location = load("user://maps/Archipelago/location.gd") apclient_instance.SCRIPT_multiplayer = load("user://maps/Archipelago/multiplayer.gd") apclient_instance.SCRIPT_mypainting = load("user://maps/Archipelago/mypainting.gd") @@ -123,6 +129,16 @@ func installScriptExtension(childScript: Resource): childScript.take_over_path(parentScriptPath) +func getVariantFromFile(path): + var cbin = File.new() + var err = cbin.open_compressed( + "%s\\%s" % [filename.get_base_dir(), path], File.READ, File.COMPRESSION_ZSTD + ) + if err != OK: + global._print("Error: %d" % err) + return cbin.get_var() + + func connectionStatus(message): var popup = self.get_node("Panel/AcceptDialog") popup.window_title = "Connecting to Archipelago" @@ -135,6 +151,36 @@ func connectionStatus(message): func connectionSuccessful(): var apclient = global.get_node("Archipelago") + if apclient._panel_shuffle == apclient.kEXPERIMENTAL_PANELS: + #connect("finished_randomizing", self, "loadLevel") + + #generator_thread.start(self, "doGeneration", null, Thread.PRIORITY_HIGH) + #yield(self, "finished_randomizing") + #generator_thread.wait_to_finish() + doGeneration() + + loadLevel() + else: + loadLevel() + + +func doGeneration(): + var apclient = global.get_node("Archipelago") + var gpv = getVariantFromFile("generated_puzzles.bin") + global._print("Forms: %d" % gpv[0].size()) + generator = apclient.SCRIPT_generator.new(gpv) + generator.name = "Generator" + apclient.add_child(generator) + + generator.connect("generator_status", self, "connectionStatus") + generator.generate(str(apclient._slot_seed)) + + emit_signal("finished_randomizing") + + +func loadLevel(): + var apclient = global.get_node("Archipelago") + # Save connection details var connection_details = [apclient.ap_server, apclient.ap_user, apclient.ap_pass] if apclient.connection_history.has(connection_details): -- cgit 1.4.1