summary refs log tree commit diff stats
path: root/randomizer
diff options
context:
space:
mode:
Diffstat (limited to 'randomizer')
-rw-r--r--randomizer/generator.gd748
-rw-r--r--randomizer/load.gd18
-rw-r--r--randomizer/panelEnd.gd7
-rw-r--r--randomizer/panelInput.gd5
-rw-r--r--randomizer/panelLevelSwitch.gd7
-rw-r--r--randomizer/randomizer.gd26
-rw-r--r--randomizer/settings_buttons.gd16
-rw-r--r--randomizer/settings_screen.gd78
-rw-r--r--randomizer/worldTransporter.gd6
9 files changed, 911 insertions, 0 deletions
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 @@
1extends Node
2
3var panel_mapping = []
4var gen_seed
5
6var _generated_puzzles
7var _answer_by_id
8var _answers_by_type
9var _answers_by_length
10var _puzzle_by_id
11var _rng
12var _flags = 0
13var _total_generated = 0
14
15var _unique_pool = ""
16var _answers_by_unique_pool = {}
17var _needs_reuse = []
18var _possible_reuse = []
19
20const kWhiteMiddle = -1
21const kWhiteTop = 0
22const kWhiteBottom = 1
23const kYellowTop = 2
24const kYellowMiddle = 3
25const kBlackTop = 4
26const kBlackMiddle = 5
27const kBlackBottom = 6
28const kDoubleBlackBottom = 7
29const kRedTop = 8
30const kRedMiddle = 9
31const kRedBottom = 10
32const kBlueTop = 11
33const kBlueMiddle = 12
34const kBlueBottom = 13
35const kPurpleTop = 14
36const kPurpleMiddle = 15
37
38const kPuzzleTypes = [
39 kWhiteMiddle,
40 kWhiteTop,
41 kWhiteBottom,
42 kYellowTop,
43 kYellowMiddle,
44 kBlackTop,
45 kBlackMiddle,
46 kBlackBottom,
47 kDoubleBlackBottom,
48 kRedTop,
49 kRedMiddle,
50 kRedBottom,
51 kBlueTop,
52 kBlueMiddle,
53 kBlueBottom,
54 kPurpleTop,
55 kPurpleMiddle
56]
57
58const kMustReuseAnswer = 1 >> 0
59const kObscureHint = 1 >> 1
60const kShortAnswer = 1 >> 2
61
62signal generator_status
63
64
65func _init(gen_puzzles):
66 _generated_puzzles = gen_puzzles
67
68
69func generate(chosen_seed):
70 emit_signal("generator_status", "Generating puzzles...")
71
72 _flags = 0
73 _total_generated = 0
74
75 # Seed the random number generator.
76 if chosen_seed == "":
77 var seed_rng = RandomNumberGenerator.new()
78 seed_rng.randomize()
79 gen_seed = seed_rng.randi_range(0, 999999)
80 else:
81 gen_seed = int(chosen_seed)
82
83 _rng = RandomNumberGenerator.new()
84 _rng.seed = gen_seed
85
86 # Create some helpful indexes.
87 _answer_by_id = []
88 _answers_by_type = {}
89 _answers_by_length = {}
90 _puzzle_by_id = []
91 var openable_answers = []
92
93 for puzzle_type in kPuzzleTypes:
94 _answers_by_type[puzzle_type] = []
95
96 var puzzle_id = 0
97 for puzzle in _generated_puzzles.forms:
98 _answers_by_type[kWhiteMiddle].append(puzzle_id)
99
100 match typeof(puzzle):
101 TYPE_ARRAY:
102 _answer_by_id.append(puzzle[0])
103 if not _answers_by_length.has(puzzle[0].length()):
104 _answers_by_length[puzzle[0].length()] = []
105 _answers_by_length[puzzle[0].length()].append(puzzle_id)
106 _puzzle_by_id.append(puzzle)
107
108 for puzzle_type in puzzle[1].keys():
109 _answers_by_type[puzzle_type].append(puzzle_id)
110
111 if (
112 puzzle[1].has(kYellowMiddle)
113 and puzzle[1].has(kBlackBottom)
114 and puzzle[1].has(kRedMiddle)
115 and puzzle[1].has(kBlueMiddle)
116 and puzzle[1].has(kPurpleMiddle)
117 ):
118 openable_answers.append(puzzle_id)
119 TYPE_STRING:
120 _answer_by_id.append(puzzle)
121 if not _answers_by_length.has(puzzle.length()):
122 _answers_by_length[puzzle.length()] = []
123 _answers_by_length[puzzle.length()].append(puzzle_id)
124 _puzzle_by_id.append([puzzle, []])
125
126 puzzle_id += 1
127
128 # Choose the answer for the OPEN panels.
129 # There is a hedge maze OPEN but we can't randomize those yet.
130 var open_answer_id = _pickRandom(openable_answers)
131
132 _setUniquePool("agreeable")
133 _setPanel(
134 "Antonym Room/Panel_close_open",
135 _pickRandom(_puzzle_by_id[open_answer_id][1][kBlackBottom]),
136 open_answer_id
137 )
138
139 _setUniquePool("seeker")
140 _setPanel("Heteronym Room/Panel_entrance_entrance", open_answer_id, open_answer_id)
141
142 _setUniquePool("traveled")
143 _setPanel("Synonym Room/Panel_open_open", open_answer_id, open_answer_id)
144
145 _setUniquePool("discerning")
146 _setPanel(
147 "Sun Room/Panel_nope_open",
148 _pickRandom(_puzzle_by_id[open_answer_id][1][kYellowMiddle]),
149 open_answer_id
150 )
151
152 _setUniquePool("bold")
153 _setPanel(
154 "Truncate Room/Panel_unopened_open",
155 _pickRandom(_puzzle_by_id[open_answer_id][1][kRedMiddle]),
156 open_answer_id
157 )
158
159 _setUniquePool("undeterred")
160 _setPanel(
161 "Blue Room/Panel_pen_open",
162 _pickRandom(_puzzle_by_id[open_answer_id][1][kBlueMiddle]),
163 open_answer_id
164 )
165
166 _setUniquePool("initiated")
167 _setPanel(
168 "Rhyme Room/Panel_locked_knocked",
169 _pickRandom(_puzzle_by_id[open_answer_id][1][kPurpleMiddle]),
170 open_answer_id
171 )
172
173 # Start generating puzzles that need to have reused solutions.
174 _setFlag(kMustReuseAnswer)
175
176 _setUniquePool("agreeable")
177 _gSingle("Antonym Room/Panel_read_write", kBlackBottom)
178 _gSingle("Antonym Room/Panel_different_same", kBlackBottom)
179 _gSingle("Antonym Room/Panel_bye_hi", kBlackBottom)
180 _gSingle("Antonym Room/Panel_low_high", kBlackBottom)
181 _gSingle("Antonym Room/Panel_alive_dead", kBlackBottom)
182 _gSingle("Antonym Room/Panel_that_this", kBlackBottom)
183 _gSingle("Doorways Room/Panel_found_lost", kBlackBottom)
184
185 _setUniquePool("bold")
186 _gDouble("Truncate Room/Panel_face_eye", "Truncate Room/Panel_needle_eye", kRedBottom)
187 _gDouble("Truncate Room/Panel_mouth_teeth", "Truncate Room/Panel_saw_teeth", kRedBottom)
188 _gSingle("Truncate Room/Panel_foot_toe", kRedBottom)
189 _gSingle("Truncate Room/Panel_hand_finger", kRedBottom)
190 _gSingle("Doorways Room/Panel_loaf_crust", kRedBottom)
191
192 _setUniquePool("undeterred")
193 _gSingle("Blue Room/Panel_two_toucan", kBlueTop)
194 _gDouble("Blue Room/Panel_ice_eyesight", "Blue Room/Panel_height_eyesight", kBlueTop)
195 _gSingle("Blue Room/Panel_eye_hi", kBlueTop)
196 _gSingle("Blue Room/Panel_not_notice", kBlueMiddle)
197 _gDouble("Blue Room/Panel_just_readjust", "Blue Room/Panel_read_readjust", kBlueMiddle)
198 _gSingle("Blue Room/Panel_ate_primate", kBlueMiddle)
199 _gSingle("Blue Room/Panel_bone_skeleton", kBlueBottom)
200 _gDouble("Blue Room/Panel_mouth_face", "Blue Room/Panel_eye_face", kBlueBottom)
201 _gSingle("Blue Room/Panel_toucan_bird", kBlueBottom)
202 _gSingle("Blue Room/Panel_primate_mammal", kBlueBottom)
203 _gDouble("Blue Room/Panel_continent_planet", "Blue Room/Panel_ocean_planet", kBlueBottom)
204 _gSingle("Blue Room/Panel_wall_room", kBlueBottom)
205 _gSingle("Doorways Room/Panel_sun_sky", kBlueBottom)
206
207 _setUniquePool("traveled")
208 _gSingle("Synonym Room/Panel_close_near", kWhiteBottom)
209 _gSingle("Synonym Room/Panel_category_type", kWhiteBottom)
210 _gSingle("Synonym Room/Panel_distant_far", kWhiteBottom)
211 _gSingle("Synonym Room/Panel_hay_straw", kWhiteBottom)
212 _gSingle("Synonym Room/Panel_snitch_rat", kWhiteBottom)
213 _gSingle("Synonym Room/Panel_concealed_hidden", kWhiteBottom)
214 _gSingle("Synonym Room/Panel_growths_warts", kWhiteBottom)
215 _gSingle("Synonym Room/Panel_hello_hi", kWhiteBottom)
216 _gDouble("Synonym Room/Panel_compose_write", "Synonym Room/Panel_record_write", kWhiteBottom)
217 _gDouble("Synonym Room/Panel_duplicate_same", "Synonym Room/Panel_identical_same", kWhiteBottom)
218 _gDouble("Synonym Room/Panel_giggle_laugh", "Synonym Room/Panel_chuckle_laugh", kWhiteBottom)
219 _gDouble("Synonym Room/Panel_plunge_fall", "Synonym Room/Panel_autumn_fall", kWhiteBottom)
220 _gSingle("Doorways Room/Panel_begin_start", kWhiteBottom)
221
222 _setUniquePool("initiated")
223 _gSingle("Rhyme Room/Panel_daughter_laughter", kPurpleMiddle)
224 _gSingle("Rhyme Room/Panel_scope_type", kPurpleMiddle)
225 _gSingle("Rhyme Room/Panel_abyss_this", kPurpleMiddle)
226 _gSingle("Rhyme Room/Panel_wrath_path", kPurpleMiddle)
227 _gSingle("Rhyme Room/Panel_bed_dead", kPurpleMiddle)
228 _gSingle("Rhyme Room/Panel_alumni_hi", kPurpleTop)
229 _gSingle("Rhyme Room/Panel_maim_same", kPurpleTop)
230 _gSingle("Rhyme Room/Panel_bare_bear", kPurpleTop)
231 _gDouble("Rhyme Room/Panel_move_love", "Rhyme Room/Panel_stove_love", kPurpleMiddle)
232 _gDouble("Rhyme Room/Panel_sweat_great", "Rhyme Room/Panel_beat_great", kPurpleMiddle)
233 _gDouble("Rhyme Room/Panel_knight_write", "Rhyme Room/Panel_byte_write", kPurpleTop)
234 # Panel_chair_bear, Panel_cost_most (cyborg)
235
236 _setUniquePool("fearless")
237 _gSingle("Naps Room/Panel_easy_soft", kDoubleBlackBottom)
238 _gSingle("Naps Room/Panel_sometimes_always", kDoubleBlackBottom)
239 _gSingle("Naps Room/Panel_dark_extinguish", kDoubleBlackBottom)
240 _gSingle("Naps Room/Panel_impatient_doctor", kDoubleBlackBottom)
241 _gSingle("Naps Room/Panel_even_ordinary", kDoubleBlackBottom)
242
243 _setUniquePool("unchallenged")
244 _gSingle("Challenge Room/Panel_nevertrusted_maladjusted", kPurpleMiddle)
245 _gSingle("Challenge Room/Panel_writer_songwriter", kBlueMiddle)
246 _gSingle("Challenge Room/Panel_lobs_lobster", kBlueMiddle)
247
248 _setUniquePool("red")
249 _gSingle("Hangry Room/Panel_red_bot_1", kRedBottom)
250 _gSingle("Hangry Room/Panel_red_bot_2", kRedBottom)
251 _gSingle("Hangry Room/Panel_red_bot_3", kRedBottom)
252 _gSingle("Hangry Room/Panel_red_bot_6", kRedBottom)
253
254 # Do must-reuse panels with no unique pool last so that we can reuse already chosen answers.
255 _clearUniquePool()
256 _gSingle("Symmetry Room/Panel_left_wrong", kDoubleBlackBottom)
257 _gSingle("Symmetry Room/Panel_black_white", kBlackBottom)
258
259 _gSingle("Shuffle Room/Panel_lost_found", kBlackBottom)
260 _gSingle("Shuffle Room/Panel_clockwise_counterclockwise", kBlackBottom)
261 _gSingle("Shuffle Room/Panel_order_chaos", kBlackBottom)
262
263 _gSingle("Maze Room/Panel_down_up", kBlackBottom)
264 _gSingle("Maze Room/Panel_strays_maze", kPurpleTop)
265 _gSingle("Maze Room/Panel_daze_maze", kPurpleMiddle)
266 _gSingle("Maze Room/Panel_hide_seek", kBlackBottom)
267 _gSingle("Maze Room/Panel_hide_seek_2", kBlackBottom)
268 _gSingle("Maze Room/Panel_hide_seek_3", kBlackBottom)
269 _gSingle("Maze Room/Panel_hide_seek_4", kBlackBottom)
270 _gSingle("Maze Room/Panel_leap_jump", kWhiteBottom)
271 _gSingle("Maze Room/Panel_look_look", kWhiteBottom)
272
273 _gSingle("Appendix Room/Panel_discover_recover", kPurpleMiddle)
274 _gSingle("Appendix Room/Panel_warner_corner", kPurpleTop)
275 _gSingle("Appendix Room/Panel_adjust_readjusted", kBlueMiddle)
276 _gSingle("Appendix Room/Panel_trust_crust", kPurpleMiddle)
277 _gCopy("Appendix Room/Panel_trust_crust", "Appendix Room/Panel_trust_crust_2")
278 _gSingle("Appendix Room/Panel_trusted_readjusted", kPurpleMiddle)
279
280 _gSingle("Painting Room/Panel_free_three", kPurpleMiddle)
281 _gSingle("Painting Room/Panel_our_four", kBlueMiddle)
282 _gSingle("Painting Room/Panel_house_neighborhood", kBlueBottom)
283 # Panel_path_road
284 _gSingle("Painting Room/Panel_park_drive", kBlackBottom)
285 _gSingle("Painting Room/Panel_carriage_horse", kRedBottom)
286 _gSingle("Painting Room/Panel_learns_turns", kPurpleMiddle)
287 _gSingle("Painting Room/Panel_urns_turns", kBlueMiddle)
288
289 _gSingle("Backside Room/Panel_ward_forward", kBlueMiddle)
290 _gSingle("Backside Room/Panel_hind_behind", kBlueMiddle)
291 _gSingle("Backside Room/Panel_rig_right", kBlueMiddle)
292 _gSingle("Backside Room/Panel_turn_return", kBlueMiddle)
293 _gSingle("Backside Room/Panel_windward_forward", kPurpleMiddle)
294 _gSingle("Backside Room/Panel_light_right", kPurpleMiddle)
295 _gSingle("Backside Room/Panel_rewind_behind", kPurpleMiddle)
296 _gSingle("Backside Room/Panel_learn_return", kPurpleMiddle)
297
298 _gSingle("Color Arrow Room/Panel_hues_colors", kWhiteBottom)
299
300 # Now we'll generate puzzles that don't need to be reused, and hopefully cover
301 # all previously generated answers.
302 _clearFlag(kMustReuseAnswer)
303
304 _setUniquePool("agreeable")
305 _gSingle("Antonym Room/Panel_retool_looter", kBlackMiddle)
306 _gSingle("Antonym Room/Panel_drawer_reward", kBlackMiddle)
307 _gSingle("Antonym Room/Panel_stressed_desserts", kBlackMiddle)
308 _gSingle("Antonym Room/Panel_star_rats", kBlackMiddle)
309 _gSingle("Antonym Room/Panel_tame_mate", kBlackTop)
310 _gSingle("Antonym Room/Panel_cat_tack", kBlackTop)
311
312 _setUniquePool("seeker")
313 _setFlag(kObscureHint)
314 _gSingle("Heteronym Room/Panel_bear_bear", kWhiteMiddle)
315 _gSingle("Heteronym Room/Panel_bow_bow", kWhiteMiddle)
316 _gSingle("Heteronym Room/Panel_does_does", kWhiteMiddle)
317 _gDouble("Heteronym Room/Panel_mine_mine", "Heteronym Room/Panel_mine_mine_2", kWhiteMiddle)
318 _gDouble(
319 "Heteronym Room/Panel_mobile_mobile", "Heteronym Room/Panel_mobile_mobile_2", kWhiteMiddle
320 )
321 _gStack2(
322 "Heteronym Room/Panel_desert_dessert",
323 kWhiteTop,
324 "Heteronym Room/Panel_desert_desert",
325 kWhiteMiddle
326 )
327 _gStack2("Heteronym Room/Panel_sow_so", kWhiteTop, "Heteronym Room/Panel_sow_sow", kWhiteMiddle)
328 _gDouble("Heteronym Room/Panel_two_to", "Heteronym Room/Panel_two_too", kWhiteTop)
329 _gDouble("Heteronym Room/Panel_not_knot", "Heteronym Room/Panel_not_naught", kWhiteTop)
330 _gSingle("Heteronym Room/Panel_write_right", kWhiteTop)
331 _gSingle("Heteronym Room/Panel_you_ewe", kWhiteTop)
332 _gSingle("Heteronym Room/Panel_bear_bare", kWhiteTop)
333 _clearFlag(kObscureHint)
334
335 _setUniquePool("tenacious")
336 _gSingle("Palindrome Room/Panel_slaughter_laughter", kRedMiddle)
337 _gSingle("Palindrome Room/Panel_dread_dead", kRedMiddle)
338 _gSingle("Palindrome Room/Panel_massacred_sacred", kRedMiddle)
339 _gSingle("Palindrome Room/Panel_decay_day", kRedMiddle)
340 # do palindromes
341
342 _setUniquePool("discerning")
343 _gSingle("Sun Room/Panel_hits_this", kYellowMiddle)
344 _gSingle("Sun Room/Panel_adder_dread", kYellowMiddle)
345 _gSingle("Sun Room/Panel_laughters_slaughter", kYellowMiddle)
346 _gSingle("Sun Room/Panel_rat_art", kYellowMiddle)
347 _gSingle("Sun Room/Panel_dusty_study", kYellowMiddle)
348 _gSingle("Sun Room/Panel_state_taste", kYellowMiddle)
349 _gSingle("Sun Room/Panel_react_trace", kYellowMiddle)
350 _gSingle("Sun Room/Panel_seam_same", kYellowMiddle)
351 _gDouble("Sun Room/Panel_warred_drawer", "Sun Room/Panel_redraw_drawer", kYellowMiddle)
352 _gDouble("Sun Room/Panel_stone_notes", "Sun Room/Panel_onset_notes", kYellowMiddle)
353 _gDouble("Sun Room/Panel_arts_star", "Sun Room/Panel_tsar_star", kYellowMiddle)
354 _gDouble("Sun Room/Panel_dear_read", "Sun Room/Panel_dare_read", kYellowMiddle)
355
356 _setUniquePool("bold")
357 _gSingle("Truncate Room/Panel_sushi_hi", kRedMiddle)
358 _gSingle("Truncate Room/Panel_thistle_this", kRedMiddle)
359 _gSingle("Truncate Room/Panel_heartbreak_brake", kRedTop)
360 _gSingle("Truncate Room/Panel_airplane_plain", kRedTop)
361 _gSingle("Truncate Room/Panel_nightmare_knight", kRedTop)
362 _gSingle("Truncate Room/Panel_sign_sigh", kRedTop)
363 _gDouble("Truncate Room/Panel_undead_dead", "Truncate Room/Panel_deadline_dead", kRedMiddle)
364 _gDouble("Truncate Room/Panel_landmass_mass", "Truncate Room/Panel_massacred_mass", kRedMiddle)
365
366 _setUniquePool("rhyme")
367 _gStack2(
368 "Double Room/Panel_ascend_rhyme", kPurpleTop, "Double Room/Panel_ascend_syn", kWhiteBottom
369 )
370 _gStack2(
371 "Double Room/Panel_double_rhyme", kPurpleTop, "Double Room/Panel_double_syn", kWhiteBottom
372 )
373 _gStack2(
374 "Double Room/Panel_blocked_rhyme", kPurpleTop, "Double Room/Panel_blocked_syn", kWhiteBottom
375 )
376 _gStack2("Double Room/Panel_rise_rhyme", kPurpleTop, "Double Room/Panel_rise_syn", kWhiteBottom)
377 _gStack2(
378 "Double Room/Panel_crystal_rhyme", kPurpleTop, "Double Room/Panel_crystal_syn", kWhiteBottom
379 )
380 _gStack2(
381 "Double Room/Panel_creative_rhyme",
382 kPurpleTop,
383 "Double Room/Panel_creative_syn",
384 kWhiteBottom
385 )
386 _gStack2(
387 "Double Room/Panel_child_rhyme", kPurpleTop, "Double Room/Panel_child_syn", kWhiteBottom
388 )
389 _gStack2(
390 "Double Room/Panel_hidden_rhyme", kPurpleTop, "Double Room/Panel_hidden_syn", kWhiteBottom
391 )
392 _gStack2(
393 "Double Room/Panel_word_rhyme", kPurpleTop, "Double Room/Panel_word_whole", kBlueBottom
394 )
395 _gStack2(
396 "Double Room/Panel_silent_rhyme", kPurpleTop, "Double Room/Panel_silent_syn", kWhiteBottom
397 )
398 _gStack2(
399 "Double Room/Panel_bones_rhyme", kPurpleTop, "Double Room/Panel_bones_syn", kWhiteBottom
400 )
401 _gStack2(
402 "Double Room/Panel_sentence_rhyme",
403 kPurpleTop,
404 "Double Room/Panel_sentence_whole",
405 kBlueBottom
406 )
407 _gStack2(
408 "Double Room/Panel_dream_rhyme", kPurpleTop, "Double Room/Panel_dream_syn", kWhiteBottom
409 )
410 _gStack2(
411 "Double Room/Panel_mystery_rhyme", kPurpleTop, "Double Room/Panel_mystery_syn", kWhiteBottom
412 )
413 _gStack2("Double Room/Panel_jump_rhyme", kPurpleTop, "Double Room/Panel_jump_syn", kWhiteBottom)
414 _gStack2("Double Room/Panel_fall_rhyme", kPurpleTop, "Double Room/Panel_fall_syn", kWhiteBottom)
415 _gStack2(
416 "Double Room/Panel_return_rhyme", kPurpleTop, "Double Room/Panel_return_ant", kBlackBottom
417 )
418 _gStack2(
419 "Double Room/Panel_descend_rhyme", kPurpleTop, "Double Room/Panel_descend_ant", kBlackBottom
420 )
421
422 _clearUniquePool()
423 _gSingle("Entry Room/Panel_hidden_hidden", kWhiteMiddle)
424
425 _gPaired("Shuffle Room/Panel_sword_words", "Shuffle Room/Panel_words_sword", kYellowMiddle)
426 _gPaired("Shuffle Room/Panel_turn_runt", "Shuffle Room/Panel_turn_runt2", kYellowMiddle)
427 _gCohinted("Shuffle Room/Panel_lost_lots", "Shuffle Room/Panel_lost_slot", kYellowMiddle)
428 _gDouble("Shuffle Room/Panel_amen_mean", "Shuffle Room/Panel_name_mean", kYellowMiddle)
429 _gSingle("Shuffle Room/Panel_corner", kYellowTop)
430 _gSingle("Shuffle Room/Panel_gel", kYellowTop)
431 _gSingle("Shuffle Room/Panel_though", kYellowTop)
432 _gSingle("Shuffle Room/Panel_swap_wasp", kYellowMiddle)
433 _gSingle("Shuffle Room/Panel_eyes_see_shuffle", kYellowMiddle)
434 _gSingle("Shuffle Room/Panel_behind", kYellowMiddle)
435 _gPaired("Shuffle Room/Panel_left_left", "Shuffle Room/Panel_right_right", kWhiteMiddle)
436 _gSingle("Shuffle Room/Panel_middle_middle", kWhiteMiddle)
437 _gCopy("Shuffle Room/Panel_left_left", "Shuffle Room/Panel_left_left_2")
438 _gCopy("Shuffle Room/Panel_right_right", "Shuffle Room/Panel_right_right_2")
439 _gCopy("Shuffle Room/Panel_middle_middle", "Shuffle Room/Panel_middle_middle_2")
440 _gSingle("Shuffle Room/Panel_shortcuts", kWhiteMiddle)
441 _gSingle("Shuffle Room/Panel_tower", kWhiteMiddle)
442
443 _gSingle("Maze Room/Panel_reflow_flower", kYellowMiddle)
444
445 _gSingle("Appendix Room/Panel_rat_tar", kBlackMiddle)
446 _gSingle("Appendix Room/Panel_deadend_deadened", kWhiteTop)
447 _gPaired("Appendix Room/Panel_night_knight", "Appendix Room/Panel_knight_night", kBlueMiddle)
448 _gPaired("Appendix Room/Panel_bee_be", "Appendix Room/Panel_new_knew", kRedMiddle)
449 _gSingle("Appendix Room/Panel_fore_for", kRedMiddle)
450 _gCohinted(
451 "Appendix Room/Panel_trusted_trust", "Appendix Room/Panel_trusted_rusted", kRedMiddle
452 )
453 _gCohinted("Appendix Room/Panel_rust_trust", "Appendix Room/Panel_rust_crust", kBlueMiddle)
454 _gSingle("Appendix Room/Panel_encrusted_rust", kRedMiddle)
455 _gCohinted(
456 "Appendix Room/Panel_adjust_readjust", "Appendix Room/Panel_adjust_adjusted", kBlueMiddle
457 )
458
459 _gSingle("Painting Room/Panel_eon_one", kYellowMiddle)
460 _gSingle("Painting Room/Panel_to_two", kRedMiddle)
461 _setFlag(kShortAnswer)
462 _gSingle("Painting Room/Panel_an_many", kBlueMiddle)
463 _gSingle("Painting Room/Panel_may_many", kBlueMiddle)
464 _gSingle("Painting Room/Panel_any_many", kBlueMiddle)
465 _gSingle("Painting Room/Panel_man_many", kBlueMiddle)
466 _clearFlag(kShortAnswer)
467
468 _gExactLength("Backside Room/Panel_one_one", kWhiteMiddle, 1)
469 _gExactLength("Backside Room/Panel_two_two", kWhiteMiddle, 2)
470 _gExactLength("Backside Room/Panel_two_two_2", kWhiteMiddle, 2)
471 _gExactLength("Backside Room/Panel_three_three", kWhiteMiddle, 3)
472 _gExactLength("Backside Room/Panel_three_three_2", kWhiteMiddle, 3)
473 _gExactLength("Backside Room/Panel_three_three_3", kWhiteMiddle, 3)
474
475 _setFlag(kObscureHint)
476 _gSingle("Entry Room/Panel_forward_forward", kWhiteMiddle)
477 _gSingle("Entry Room/Panel_between_between", kWhiteMiddle)
478 _gSingle("Entry Room/Panel_backward_backward", kWhiteMiddle)
479 _gSingle("Entry Room/Panel_secret_secret", kWhiteMiddle)
480
481 _gPaired("Symmetry Room/Panel_leaf_feel", "Symmetry Room/Panel_feel_leaf", kBlackTop)
482 _gPaired("Symmetry Room/Panel_warts_straw", "Symmetry Room/Panel_straw_warts", kBlackMiddle)
483 _gPaired("Symmetry Room/Panel_near_far", "Symmetry Room/Panel_far_near", kBlackBottom)
484 _gPaired("Symmetry Room/Panel_left_right", "Symmetry Room/Panel_right_left", kBlackBottom)
485
486 _gSingle("Shuffle Room/Panel_theeyes_theeyes", kWhiteMiddle)
487 _gSingle("Shuffle Room/Panel_crossroads_crossroads", kWhiteMiddle)
488 _gSingle("Shuffle Room/Panel_corner_corner", kWhiteMiddle)
489 _gSingle("Shuffle Room/Panel_hollow_hollow", kWhiteMiddle)
490 _gPaired("Shuffle Room/Panel_far_far", "Shuffle Room/Panel_near_near", kWhiteMiddle)
491
492 _gSingle("Maze Room/Panel_trace_trace", kWhiteMiddle)
493
494 _gSingle("Appendix Room/Panel_deadend_deadend", kWhiteMiddle)
495 _gSingle("Appendix Room/Panel_lies_lies", kWhiteMiddle)
496
497 _gSingle("Cross Room/Panel_shortcut_shortcut", kWhiteMiddle)
498
499 _gSingle("Double Room/Panel_leap_leap", kWhiteMiddle)
500
501 _gSingle("Backside Room/Panel_backside_1", kWhiteMiddle)
502 _gSingle("Backside Room/Panel_backside_2", kWhiteMiddle)
503 _gSingle("Backside Room/Panel_backside_3", kWhiteMiddle)
504 _gSingle("Backside Room/Panel_backside_4", kWhiteMiddle)
505 _gSingle("Backside Room/Panel_backside_5", kWhiteMiddle)
506 _gSingle("Backside Room/Panel_farther_far", kRedMiddle)
507 _gSingle("Backside Room/Panel_first_first", kWhiteMiddle)
508 _gSingle("Backside Room/Panel_second_second", kWhiteMiddle)
509 _gSingle("Backside Room/Panel_third_third", kWhiteMiddle)
510 _gSingle("Backside Room/Panel_fourth_fourth", kWhiteMiddle)
511
512 _gExactLength("Backside Room/Panel_four_four", kWhiteMiddle, 4)
513 _gExactLength("Backside Room/Panel_four_four_2", kWhiteMiddle, 4)
514 _gExactLength("Backside Room/Panel_four_four_3", kWhiteMiddle, 4)
515 _gExactLength("Backside Room/Panel_four_four_4", kWhiteMiddle, 4)
516 _gExactLength("Backside Room/Panel_five_five", kWhiteMiddle, 5)
517 _gExactLength("Backside Room/Panel_five_five_2", kWhiteMiddle, 5)
518 _gExactLength("Backside Room/Panel_five_five_3", kWhiteMiddle, 5)
519 _gExactLength("Backside Room/Panel_five_five_4", kWhiteMiddle, 5)
520 _gExactLength("Backside Room/Panel_five_five_5", kWhiteMiddle, 5)
521 _gExactLength("Backside Room/Panel_six_six", kWhiteMiddle, 6)
522 _gExactLength("Backside Room/Panel_six_six_2", kWhiteMiddle, 6)
523 _gExactLength("Backside Room/Panel_six_six_3", kWhiteMiddle, 6)
524 _gExactLength("Backside Room/Panel_six_six_4", kWhiteMiddle, 6)
525 _gExactLength("Backside Room/Panel_six_six_5", kWhiteMiddle, 6)
526 _gExactLength("Backside Room/Panel_six_six_6", kWhiteMiddle, 6)
527 _gExactLength("Backside Room/Panel_seven_seven", kWhiteMiddle, 7)
528 _gExactLength("Backside Room/Panel_seven_seven_2", kWhiteMiddle, 7)
529 _gExactLength("Backside Room/Panel_seven_seven_3", kWhiteMiddle, 7)
530 _gExactLength("Backside Room/Panel_seven_seven_4", kWhiteMiddle, 7)
531 _gExactLength("Backside Room/Panel_seven_seven_5", kWhiteMiddle, 7)
532 _gExactLength("Backside Room/Panel_seven_seven_6", kWhiteMiddle, 7)
533 _gExactLength("Backside Room/Panel_seven_seven_7", kWhiteMiddle, 7)
534 _gExactLength("Backside Room/Panel_eight_eight", kWhiteMiddle, 8)
535 _gExactLength("Backside Room/Panel_eight_eight_2", kWhiteMiddle, 8)
536 _gExactLength("Backside Room/Panel_eight_eight_3", kWhiteMiddle, 8)
537 _gExactLength("Backside Room/Panel_eight_eight_4", kWhiteMiddle, 8)
538 _gExactLength("Backside Room/Panel_eight_eight_5", kWhiteMiddle, 8)
539 _gExactLength("Backside Room/Panel_eight_eight_6", kWhiteMiddle, 8)
540 _gExactLength("Backside Room/Panel_eight_eight_7", kWhiteMiddle, 8)
541 _gExactLength("Backside Room/Panel_eight_eight_8", kWhiteMiddle, 8)
542 _gExactLength("Backside Room/Panel_nine_nine", kWhiteMiddle, 9)
543 _gExactLength("Backside Room/Panel_nine_nine_2", kWhiteMiddle, 9)
544 _gExactLength("Backside Room/Panel_nine_nine_3", kWhiteMiddle, 9)
545 _gExactLength("Backside Room/Panel_nine_nine_4", kWhiteMiddle, 9)
546 _gExactLength("Backside Room/Panel_nine_nine_5", kWhiteMiddle, 9)
547 _gExactLength("Backside Room/Panel_nine_nine_6", kWhiteMiddle, 9)
548 _gExactLength("Backside Room/Panel_nine_nine_7", kWhiteMiddle, 9)
549 _gExactLength("Backside Room/Panel_nine_nine_8", kWhiteMiddle, 9)
550 _gExactLength("Backside Room/Panel_nine_nine_9", kWhiteMiddle, 9)
551
552 _clearFlag(kObscureHint)
553
554 if _needs_reuse.size() > 0:
555 print("Generation failed; the following words need to be reused:")
556 for word_id in _needs_reuse:
557 print(_answer_by_id[word_id])
558
559 print("Generated!")
560 for puzzle in panel_mapping:
561 print("%s: %s? %s!" % puzzle)
562
563
564func _pickRandom(set):
565 var id = _rng.randi_range(0, set.size() - 1)
566 return set[id]
567
568
569func _setFlag(flag):
570 _flags |= flag
571
572
573func _clearFlag(flag):
574 _flags &= ~flag
575
576
577func _isFlag(flag):
578 return (_flags & flag) > 0
579
580
581func _setUniquePool(pool):
582 _unique_pool = pool
583 if not _answers_by_unique_pool.has(_unique_pool):
584 _answers_by_unique_pool[_unique_pool] = []
585
586
587func _clearUniquePool():
588 _unique_pool = ""
589
590
591func _gSingle(panel_path, puzzle_type):
592 if puzzle_type == kWhiteMiddle:
593 var word_choices = _filterBestPuzzles(_answers_by_type[kWhiteMiddle])
594 var answer_id = _pickRandom(word_choices)
595 _setPanel(panel_path, answer_id, answer_id)
596 else:
597 var puzzle_choices = _filterBestPuzzles(_answers_by_type[puzzle_type])
598 if puzzle_choices.empty():
599 print("No possible puzzles for panel %s" % panel_path)
600 else:
601 var answer_id = _pickRandom(puzzle_choices)
602 var hint_choices = _puzzle_by_id[answer_id][1][puzzle_type]
603 var hint_id = _pickRandom(hint_choices)
604 _setPanel(panel_path, hint_id, answer_id)
605
606
607func _gDouble(panel1_path, panel2_path, puzzle_type):
608 if puzzle_type == kWhiteMiddle:
609 var word_choices = _filterBestPuzzles(_answers_by_type[kWhiteMiddle])
610 var answer_id = _pickRandom(word_choices)
611 _setPanel(panel1_path, answer_id, answer_id)
612 _setPanel(panel2_path, answer_id, answer_id)
613 else:
614 var pre_choices = _filterBestPuzzles(_answers_by_type[puzzle_type])
615 var puzzle_choices = []
616 for word_id in pre_choices:
617 if _puzzle_by_id[word_id][1][puzzle_type].size() > 1:
618 puzzle_choices.append(word_id)
619 if puzzle_choices.empty():
620 print("No possible puzzles for panel %s" % panel1_path)
621 else:
622 var answer_id = _pickRandom(puzzle_choices)
623 var hint_choices = _puzzle_by_id[answer_id][1][puzzle_type].duplicate()
624 var hint1_id = _pickRandom(hint_choices)
625 hint_choices.erase(hint1_id)
626 var hint2_id = _pickRandom(hint_choices)
627 _setPanel(panel1_path, hint1_id, answer_id)
628 _setPanel(panel2_path, hint2_id, answer_id)
629
630
631func _gPaired(panel1_path, panel2_path, puzzle_type):
632 var needed_type = puzzle_type
633 if puzzle_type == kWhiteMiddle:
634 needed_type = kBlackMiddle
635 var puzzle_choices = _filterBestPuzzles(_answers_by_type[needed_type])
636 if puzzle_choices.empty():
637 print("No possible puzzles for panel %s" % panel1_path)
638 else:
639 var answer_id = _pickRandom(puzzle_choices)
640 var hint_choices = _puzzle_by_id[answer_id][1][needed_type]
641 var hint_id = _pickRandom(hint_choices)
642 if puzzle_type == kWhiteMiddle:
643 _setPanel(panel1_path, hint_id, hint_id)
644 _setPanel(panel2_path, answer_id, answer_id)
645 else:
646 _setPanel(panel1_path, hint_id, answer_id)
647 _setPanel(panel2_path, answer_id, hint_id)
648
649
650func _gCohinted(panel1_path, panel2_path, puzzle_type):
651 pass
652
653
654func _gStack2(panel1_path, puzzle_type1, panel2_path, puzzle_type2):
655 if puzzle_type1 == kWhiteMiddle or puzzle_type2 == kWhiteMiddle:
656 if puzzle_type1 == kWhiteMiddle:
657 _gSingle(panel2_path, puzzle_type2)
658 _gCopyAnswer(panel2_path, panel1_path)
659 else:
660 _gSingle(panel1_path, puzzle_type1)
661 _gCopyAnswer(panel1_path, panel2_path)
662 else:
663 var pre_choices = _filterBestPuzzles(_answers_by_type[puzzle_type1])
664 var puzzle_choices = []
665 for word_id in pre_choices:
666 if _puzzle_by_id[word_id][1].has(puzzle_type2):
667 puzzle_choices.append(word_id)
668 if puzzle_choices.empty():
669 print("No possible puzzles for panel %s" % panel1_path)
670 else:
671 var answer_id = _pickRandom(puzzle_choices)
672 var hint1_choices = _puzzle_by_id[answer_id][1][puzzle_type1]
673 var hint1_id = _pickRandom(hint1_choices)
674 var hint2_choices = _puzzle_by_id[answer_id][1][puzzle_type2]
675 var hint2_id = _pickRandom(hint2_choices)
676 _setPanel(panel1_path, hint1_id, answer_id)
677 _setPanel(panel2_path, hint2_id, answer_id)
678
679
680func _gCopy(panel1_path, panel2_path):
681 for thing in panel_mapping:
682 if thing[0] == panel1_path:
683 panel_mapping.append([panel2_path, thing[1], thing[2]])
684 return
685
686
687func _gCopyAnswer(panel1_path, panel2_path):
688 for thing in panel_mapping:
689 if thing[0] == panel1_path:
690 panel_mapping.append([panel2_path, thing[2], thing[2]])
691 return
692
693
694func _gExactLength(panel_path, puzzle_type, answer_length):
695 var puzzle_choices = _filterBestPuzzles(_answers_by_length[answer_length])
696 if puzzle_type != kWhiteMiddle:
697 # TODO: Do we even need this?
698 pass
699 if puzzle_choices.empty():
700 print("No possible puzzles for panel %s" % panel_path)
701 else:
702 var answer_id = _pickRandom(puzzle_choices)
703 if puzzle_type == kWhiteMiddle:
704 _setPanel(panel_path, answer_id, answer_id)
705 else:
706 var hint_choices = _puzzle_by_id[answer_id][1][puzzle_type]
707 var hint_id = _pickRandom(hint_choices)
708 _setPanel(panel_path, hint_id, answer_id)
709
710
711func _filterBestPuzzles(input):
712 var not_uniqued = []
713 if _unique_pool == "":
714 not_uniqued = input
715 elif _answers_by_unique_pool.has(_unique_pool):
716 for word_id in input:
717 if not _answers_by_unique_pool[_unique_pool].has(word_id):
718 not_uniqued.append(word_id)
719 else:
720 not_uniqued = input
721 #if _isFlag(kMustReuseAnswer):
722 # var possible = []
723 # for word_id in not_uniqued:
724 # if _puzzle_by_id[word_id][1].size() > 1:
725 # possible.append(word_id)
726 # not_uniqued = possible
727 var result = []
728 for word_id in not_uniqued:
729 if _needs_reuse.has(word_id):
730 result.append(word_id)
731 if result.empty():
732 for word_id in not_uniqued:
733 result.append(word_id)
734 if _possible_reuse.has(word_id):
735 result.append(word_id)
736 return result
737
738
739func _setPanel(panel_path, hint_id, answer_id):
740 if _unique_pool != "":
741 _answers_by_unique_pool[_unique_pool].append(answer_id)
742 panel_mapping.append([panel_path, _answer_by_id[hint_id], _answer_by_id[answer_id]])
743 if not _isFlag(kMustReuseAnswer):
744 if _needs_reuse.has(answer_id):
745 _needs_reuse.erase(answer_id)
746 _possible_reuse.append(answer_id)
747 _total_generated += 1
748 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 @@
1extends "res://scripts/load.gd"
2
3
4func _load():
5 global._print("Hooked Load Start")
6
7 var randomizer = global.get_node("Randomizer")
8
9 # Apply the randomized panels.
10 var panels_parent = $Panels
11 for puzzle in randomizer.generator.panel_mapping:
12 var panel = panels_parent.get_node(puzzle[0])
13 panel.text = puzzle[1]
14 panel.answer = puzzle[2]
15
16 # Proceed with the rest of the load.
17 global._print("Hooked Load End")
18 ._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 @@
1extends "res://scripts/panelEnd.gd"
2
3
4func handle_correct():
5 # We don't call the base method because we want to suppress the original
6 # behaviour.
7 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 @@
1extends "res://scripts/panelInput.gd"
2
3
4func uncomplete():
5 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 @@
1extends "res://scripts/panelLevelSwitch.gd"
2
3
4func handle_correct():
5 # We don't call the base method because we want to suppress the original
6 # behaviour.
7 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 @@
1extends Node
2
3const my_version = "0.1.0"
4
5var SCRIPT_generator
6
7var generator
8
9signal finished_randomizing
10signal randomizer_status
11
12
13func start(gen_seed = ""):
14 generator = SCRIPT_generator.new($GeneratedPuzzles)
15 generator.connect("generator_status", self, "statusUpdate")
16 generator.generate(gen_seed)
17
18 emit_signal("finished_randomizing")
19
20
21func statusUpdate(text):
22 emit_signal("randomizer_status", text)
23
24
25func getSaveFileName():
26 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 @@
1extends Button
2
3
4func _ready():
5 pass
6
7
8func _start_pressed():
9 self.disabled = true
10
11 var randomizer = global.get_node("Randomizer")
12 randomizer.start(self.get_parent().get_node("seed_box").text)
13
14
15func _back_pressed():
16 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 @@
1extends Spatial
2
3
4func _ready():
5 # Undo the load screen removing our cursor
6 get_tree().get_root().set_disable_input(false)
7 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
8
9 # Create the global Randomizer node, if it doesn't already exist.
10 if not global.has_node("Randomizer"):
11 var randomizer_script = ResourceLoader.load("user://maps/randomizer/randomizer.gd")
12 var randomizer_instance = randomizer_script.new()
13 randomizer_instance.name = "Randomizer"
14 global.add_child(randomizer_instance)
15
16 randomizer_instance.SCRIPT_generator = load("user://maps/randomizer/generator.gd")
17
18 var generated_puzzles = ResourceLoader.load("user://maps/randomizer/generated_puzzles.gd")
19 var generated_puzzles_instance = generated_puzzles.new()
20 generated_puzzles_instance.name = "GeneratedPuzzles"
21 randomizer_instance.add_child(generated_puzzles_instance)
22
23 # Let's also inject any scripts we need to inject now.
24 installScriptExtension(ResourceLoader.load("user://maps/randomizer/load.gd"))
25 installScriptExtension(ResourceLoader.load("user://maps/randomizer/panelEnd.gd"))
26 installScriptExtension(ResourceLoader.load("user://maps/randomizer/panelInput.gd"))
27 installScriptExtension(ResourceLoader.load("user://maps/randomizer/panelLevelSwitch.gd"))
28 installScriptExtension(ResourceLoader.load("user://maps/randomizer/worldTransporter.gd"))
29
30 var randomizer = global.get_node("Randomizer")
31 randomizer.connect("finished_randomizing", self, "randomizationSuccessful")
32 randomizer.connect("randomizer_status", self, "randomizationStatus")
33
34 # Show client version.
35 self.get_node("Panel/title").text = "RANDOMIZER (%s)" % randomizer.my_version
36
37 # Increase font size in text boxes.
38 var field_font = DynamicFont.new()
39 field_font.font_data = load("res://fonts/CutiveMono_Regular.ttf")
40 field_font.size = 36
41
42 self.get_node("Panel/seed_box").add_font_override("font", field_font)
43
44
45# Adapted from https://gitlab.com/Delta-V-Modding/Mods/-/blob/main/game/ModLoader.gd
46func installScriptExtension(childScript: Resource):
47 # Force Godot to compile the script now.
48 # We need to do this here to ensure that the inheritance chain is
49 # properly set up, and multiple mods can chain-extend the same
50 # class multiple times.
51 # This is also needed to make Godot instantiate the extended class
52 # when creating singletons.
53 # The actual instance is thrown away.
54 childScript.new()
55
56 var parentScript = childScript.get_base_script()
57 var parentScriptPath = parentScript.resource_path
58 global._print("ModLoader: Installing script extension over %s" % parentScriptPath)
59 childScript.take_over_path(parentScriptPath)
60
61
62func randomizationStatus(message):
63 var popup = self.get_node("Panel/AcceptDialog")
64 popup.window_title = "Randomizing..."
65 popup.dialog_text = message
66 popup.popup_exclusive = true
67 popup.get_ok().visible = false
68 popup.popup_centered()
69
70
71func randomizationSuccessful():
72 var randomizer = global.get_node("Randomizer")
73
74 # Switch to LL1
75 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
76 global.map = "level1"
77 global.save_file = randomizer.getSaveFileName()
78 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 @@
1extends "res://scripts/worldTransporter.gd"
2
3
4func _body_entered(_body):
5 # Do not transport the player.
6 pass