From d38684835b6276729652429ecf78ed26e57e0413 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Sun, 30 Jul 2023 15:05:33 +0200 Subject: [PATCH 01/18] Added blitz code for a faster playthrough. --- README | 1 + randomizer.py | 10 +++- tables/requirements_blitz.txt | 95 +++++++++++++++++++++++++++++++++++ tables/restrictions_blitz.txt | 17 +++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 tables/requirements_blitz.txt create mode 100644 tables/restrictions_blitz.txt diff --git a/README b/README index f03d946..7c2613a 100644 --- a/README +++ b/README @@ -38,6 +38,7 @@ Secret Codes: airship Start the game with the airship. bossy Very random bosses (unbalanced even with scaling) fourkeys Open World, but there are only four keys + blitz Allows a faster playthrough OPEN WORLD ENEMY SCALING scale Scale enemy status in open-world mode diff --git a/randomizer.py b/randomizer.py index 87ef49e..d9603bc 100644 --- a/randomizer.py +++ b/randomizer.py @@ -5912,6 +5912,8 @@ def extract_location_boss(findstr): for capsule_index in range(7): findstr = '. 81({0:0>2X})'.format(capsule_index) location, boss = extract_location_boss(findstr) + if location is None or boss is None: + continue s3 += CapsuleObject.get(capsule_index*5).name + '\n' s3 += right_justify(location) + '\n' s3 += right_justify(boss.boss.name) + '\n' @@ -6494,6 +6496,10 @@ def make_open_world(custom=None): path.join(tblpath, 'restrictions_fourkeys.txt'), linearity=0.8) make_four_keys() + elif 'blitz' in get_activated_codes(): + ir = ItemRouter(path.join(tblpath, 'requirements_blitz.txt'), + path.join(tblpath, 'restrictions_blitz.txt'), + linearity=0.4) else: ir = ItemRouter(path.join(tblpath, 'requirements.txt'), path.join(tblpath, 'restrictions.txt'), @@ -6518,7 +6524,8 @@ def make_open_world(custom=None): if loc.endswith('1'): other = loc[:-1] + '2' if other in ir.assignments: - assert not ir.assignments[other].endswith('_key') + print( "Not assigned: {}".format(loc) ) + #assert not ir.assignments[other].endswith('_key') MapEventObject.class_reseed('selecting_characters') if VERSION == '3.16' and 1682460000 <= get_seed() <= 1682460000 + 172800: @@ -7025,6 +7032,7 @@ def run_trials(): 'monstermash': ['monstermash'], 'nocap': ['nocap'], 'fourkeys': ['fourkeys'], + 'blitz': ['blitz'], } run_interface(ALL_OBJECTS, snes=True, codes=codes, custom_degree=True, custom_difficulty=True) diff --git a/tables/requirements_blitz.txt b/tables/requirements_blitz.txt new file mode 100644 index 0000000..798a017 --- /dev/null +++ b/tables/requirements_blitz.txt @@ -0,0 +1,95 @@ +.def breakable bomb|hammer +.def useless_keys door_key&shrine_key +.def all_keys sky_key&lake_key&ruby_key&wind_key&cloud_key&light_key&sword_key&tree_key&flower_key&magma_key&heart_key&ghost_key&trial_key&dankirk_key&basement_key&narcysus_key&truth_key +.def all_tools arrow&bomb&hook&hammer&fire_arrow +.def all_tools_or_keys all_tools|all_keys +.def arrowlike arrow|hook|fire_arrow + +.def all_capsules jelze&flash&gusto&zeppy&darbi&sully&blaze +.def some_capsules jelze|flash|gusto|zeppy|darbi|sully|blaze + +.def any_tool arrow|bomb|hook|hammer|fire_arrow +.def any_key sky_key|lake_key|ruby_key|wind_key|cloud_key|light_key|sword_key|tree_key|flower_key|magma_key|heart_key|ghost_key|trial_key|dankirk_key|basement_key|narcysus_key|truth_key +.def party0 any_tool&character0 + +.def party1 character1|character2|character3|character4 + +.def party2a character1&character2 +.def party2b character1&character3 +.def party2c character1&character4 +.def party2d character2&character3 +.def party2e character2&character4 +.def party2f character3&character4 +.def party2 party2a|party2b|party2c|party2d|party2e|party2f + +.def party3a character1&character2&character3 +.def party3b character1&character2&character4 +.def party3c character1&character3&character4 +.def party3d character2&character3&character4 +.def party3 party3a|party3b|party3c|party3d + +.def party4 character1&character2&character3&character4&all_capsules + +.def airship engine +.def submarine mermaid_jade +.def submarine_or_airship submarine|airship +.def victory victory + +.def dankirk hook&bomb&dankirk_key&party3 +.def gratze dankirk|submarine_or_airship + +starting_character * +starting_item * +hidden_item * +skill_cave arrowlike&party0 +foomy_woods party0 +darbi_shrine party0 +zeppy_cave submarine&party0 +sundletan_cave party0 +catfish_cave arrowlike&lake_key&party0 +alunze_cave breakable&party0 +alunze_basement breakable&party0 +tanbel_tower1 sky_key&party1 +tanbel_tower2 sky_key&party1 +ruby_cave ruby_key&party1 +ruby_capsule breakable&party0 +tsword_shrine1 bomb&sword_key&party1 +tsword_shrine2 bomb&sword_key&party1 +gordovan_tower1 hook&bomb&wind_key&party1 +gordovan_tower2 hook&bomb&wind_key&party1 +cave_bridge breakable&hook&party0 +north_dungeon hook&bomb&party1 +north_capsule hook&party1 +ancient_tower1 hook&bomb&cloud_key&party1 +ancient_tower2 hook&bomb&cloud_key&party1 +lighthouse1 light_key&party1 +lighthouse2 light_key&party1 +phantom_mountain hook&bomb&fire_arrow&tree_key&party2 +sacrifice_tower1 hook&bomb&narcysus_key&party2 +sacrifice_tower2 hook&bomb&narcysus_key&party2 +sacrifice_capsule hook&breakable&narcysus_key&party2 +karlloon_shrine1 hook&bomb&party2 +karlloon_shrine2 hook&bomb&party2 +lexis_lab party0 +flower_mountain hammer&flower_key&party2 +flower_capsule hammer&hook&party2 +dankirk_dungeon dankirk +northeast_tower1 hook&hammer&trial_key&party2 +northeast_tower2 hook&hammer&trial_key&party2 +no_return_mountain party0 +divine_shrine1 hook&hammer&heart_key&party2 +divine_shrine2 hook&hammer&heart_key&party2 +vengeance_shrine1 submarine&bomb&hammer&ghost_key&party2 +vengeance_shrine2 submarine&bomb&hammer&ghost_key&party2 +truth_tower1 breakable&hook&truth_key&party2 +truth_tower2 breakable&hook&truth_key&party2 +dragon_mountain submarine_or_airship&hook&hammer&fire_arrow&magma_key&party2 +underwater_shrine submarine&party0 +gratze_basement gratze&arrowlike&basement_key&party2 +shuman airship&party3 +stradha airship&party3 +kamirno airship&party3 +lisa arrowlike +marie breakable +clare party1 +daos_shrine lisa&marie&clare&any_key diff --git a/tables/restrictions_blitz.txt b/tables/restrictions_blitz.txt new file mode 100644 index 0000000..af3eef5 --- /dev/null +++ b/tables/restrictions_blitz.txt @@ -0,0 +1,17 @@ +.def keys sky_key,lake_key,ruby_key,wind_key,cloud_key,light_key,sword_key,tree_key,flower_key,magma_key,heart_key,ghost_key,trial_key,dankirk_key,basement_key,narcysus_key,truth_key + +starting_character character0 +starting_item arrow,bomb,hammer +hidden_item nothing +tanbel_tower1 keys +tsword_shrine1 keys +gordovan_tower1 keys +ancient_tower1 keys +lighthouse1 keys +sacrifice_tower1 keys +karlloon_shrine1 keys +northeast_tower1 keys +divine_shrine1 keys +vengeance_shrine1 keys +truth_tower1 keys +daos_shrine victory From e9928639c8bb4c8c1964da6ca26b6db19e7387d6 Mon Sep 17 00:00:00 2001 From: PhilAndChill <140955262+phku-hk@users.noreply.github.com> Date: Sun, 30 Jul 2023 21:28:55 +0200 Subject: [PATCH 02/18] Updated README --- README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README b/README index 7c2613a..dc370b3 100644 --- a/README +++ b/README @@ -1,3 +1,8 @@ + +Adds Blitz Mode to abyssonym's Lufia 2 Randomizer for a faster playthrough. + + + Lufia 2 Terror Wave Randomizer Version: 3 Date: April 1, 2023 From 0d47d894906278c428e2bdb81f19b8833030d3f8 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Mon, 31 Jul 2023 03:17:09 +0200 Subject: [PATCH 03/18] Revert "Updated README" This reverts commit e9928639c8bb4c8c1964da6ca26b6db19e7387d6. --- README | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README b/README index dc370b3..7c2613a 100644 --- a/README +++ b/README @@ -1,8 +1,3 @@ - -Adds Blitz Mode to abyssonym's Lufia 2 Randomizer for a faster playthrough. - - - Lufia 2 Terror Wave Randomizer Version: 3 Date: April 1, 2023 From d89d95071163a900217b79b815e29dc4f653f294 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Mon, 31 Jul 2023 12:59:39 +0200 Subject: [PATCH 04/18] Fixed not being able to fly to doom island without engine. Modified routing requirements. --- randomizer.py | 17 +- tables/requirements_blitz.txt | 11 +- tables/template_open_world_events_blitz.txt | 744 ++++++++++++++++++++ 3 files changed, 763 insertions(+), 9 deletions(-) create mode 100644 tables/template_open_world_events_blitz.txt diff --git a/randomizer.py b/randomizer.py index d9603bc..d31f822 100644 --- a/randomizer.py +++ b/randomizer.py @@ -164,8 +164,8 @@ def price_clean(self): price /= (10**power) price = price / 2 assert price <= 65500 - if price > 10 and price % 10 == 0 and int(VERSION[0]) % 2 == 1: - price = price - 1 + #if price > 10 and price % 10 == 0 and int(VERSION[0]) % 2 == 1: + #price = price - 1 self.price = int(round(price)) @@ -6752,7 +6752,10 @@ def make_open_world(custom=None): parameters['hidden_item'] = '' # Apply base patches BEFORE procedural modifications - patch_with_template('open_world_events', parameters) + if 'blitz' in get_activated_codes(): + patch_with_template('open_world_events_blitz', parameters) + else: + patch_with_template('open_world_events', parameters) boss_events = [] assert len(shuffled_bosses) == len(sorted_locations) @@ -6984,9 +6987,11 @@ def key_shop(): def run_trials(): LOGFILE = 'trial_log.txt' - NUM_TRIALS = 1000 + NUM_TRIALS = 100 victory_set = {'lisa', 'marie', 'clare', 'engine'} linearity = 0 + with open(LOGFILE, 'w') as f: + pass for n in range(NUM_TRIALS): MapEventObject.class_reseed('trial%s-%s' % (linearity, n+4000)) ir = ItemRouter(path.join(tblpath, 'requirements.txt'), @@ -6997,15 +7002,17 @@ def run_trials(): assert 'daos_shrine' not in ir.assignments ir.assignments['daos_shrine'] = 'victory' items = set() + noLocChecks = 0 for rank in sorted(ir.location_ranks): locations = ir.location_ranks[rank] for loc in sorted(locations): + noLocChecks = noLocChecks + 1 if loc in ir.assignments: items.add(ir.assignments[loc]) if items >= victory_set: break with open(LOGFILE, 'a+') as f: - s = '%s %s %s\n' % (linearity, rank, max(ir.location_ranks)) + s = '%s %s %s %s\n' % (linearity, rank, max(ir.location_ranks), noLocChecks) f.write(s) print(s.strip()) diff --git a/tables/requirements_blitz.txt b/tables/requirements_blitz.txt index 798a017..cc2589f 100644 --- a/tables/requirements_blitz.txt +++ b/tables/requirements_blitz.txt @@ -10,6 +10,12 @@ .def any_tool arrow|bomb|hook|hammer|fire_arrow .def any_key sky_key|lake_key|ruby_key|wind_key|cloud_key|light_key|sword_key|tree_key|flower_key|magma_key|heart_key|ghost_key|trial_key|dankirk_key|basement_key|narcysus_key|truth_key +.def any_dungeon_key lake_key|ruby_key|dankirk_key|basement_key +.def any_shrine_key sword_key|heart_key|ghost_key +.def any_mountain_key tree_key|magma_key|flower_key +.def any_tower_key cloud_key|light_key|narcysus_key|sky_key|trial_key|truth_key|wind_key +.def some_key any_dungeon_key&any_shrine_key&any_mountain_key&any_tower_key + .def party0 any_tool&character0 .def party1 character1|character2|character3|character4 @@ -89,7 +95,4 @@ gratze_basement gratze&arrowlike&basement_key&party2 shuman airship&party3 stradha airship&party3 kamirno airship&party3 -lisa arrowlike -marie breakable -clare party1 -daos_shrine lisa&marie&clare&any_key +daos_shrine lisa&marie&clare&some_key diff --git a/tables/template_open_world_events_blitz.txt b/tables/template_open_world_events_blitz.txt new file mode 100644 index 0000000..a3e8931 --- /dev/null +++ b/tables/template_open_world_events_blitz.txt @@ -0,0 +1,744 @@ +EVENT A0-X-XX # $3a428:3a428 +0000. 6A(0A-@7B) +0001. 15(BF-@1E) # Branch on Flag BF ($0795:80) +0004. 15(BC-@18) # Branch on Flag BC ($0795:10) +0008. 15(BB-@12) # Branch on Flag BB ($0795:08) +000C. 4B(15) # Preload Music +000E. 1C(@24) # Jump +# LABEL @11 $3a439 +0011. 00() # End Event +# LABEL @12 $3a43a +0012. 4B(16) # Preload Music +0014. 1C(@24) # Jump +0017. 00() # End Event +# LABEL @18 $3a440 +0018. 4B(32) # Preload Music +001A. 1C(@24) # Jump +001D. 00() # End Event +# LABEL @1E $3a446 +001E. 4B(11) # Preload Music +0020. 1C(@24) # Jump +0023. 00() # End Event +# LABEL @24 $3a44c +0024. 69(90) +002F. 68(50-0C) # Load NPC (1e,0b) 50: 0c Blue Man +0032. 68(51-0B) # Load NPC (15,1d) 51: 0b Green Girl +0035. 68(52-1A) # Load NPC (14,24) 52: 1a Sailor +0038. 68(53-1A) # Load NPC (22,25) 53: 1a Sailor +003B. 68(54-0A) # Load NPC (27,1e) 54: 0a Red Boy +003E. 68(55-11) # Load NPC (27,11) 55: 11 Gray Old Woman +0041. 68(56-10) # Load NPC (10,17) 56: 10 Bald Old Man +0044. 68(57-49) # Load NPC (16,28) 57: 49 Big Boat +0047. 68(58-49) # Load NPC (21,29) 58: 49 Big Boat +004A. 68(5B-71) # Load NPC (1c,2f) 5b: 71 Little Boat +004D. 68(68-70) # Load NPC (17,14) 68: 70 Nothing +007B. 00() # End Event + +EVENT A0-B-0F +#0000. 1A(1A) +#0001. 1A(1B) +#0002. 1A(1C) +1010. 70() +1020. 2B({{starting_character_index}}) +1030. 2C(00) +1040. 16(A2-0A-04) +1050. 00() + +EVENT 68-B-02 + 0000. 2B({{starting_character_index}}) + 0010. 2C(00) + 0020. 1A({{starting_character_flag}}) + 1000. 59(11) # Luminosity + 1002. 33(09-53) # Move Character to Location + 1005. 13: Amazing you got this far! + You can play this + {Bonus Game} only + in the Ancient Cave. + 103D. 13: You should go to the + Cafe before you go to + the cave. Good luck! + 1069. 1A(C4) # Set Event Flag C4 ($0796:10) + 106B. 00() # End Event + +EVENT 68-B-03 # $56796:56b0d +1000. 2C(00) +1002. 2C(01) # Character Leaves party +1004. 2C(02) # Character Leaves party +1006. 2C(03) # Character Leaves party +1008. 2C(04) # Character Leaves party +100A. 2C(05) # Character Leaves party +100C. 2C(06) # Character Leaves party +1080. 2B({{starting_character_index}}) +2000. 2C(06) +2002. 2C(05) # Character Leaves party +2004. 2C(04) # Character Leaves party +2006. 2C(03) # Character Leaves party +2008. 2C(02) # Character Leaves party +200A. 2C(01) # Character Leaves party +200C. 2C(00) # Character Leaves party +2800. 2B({{starting_character_index}}) +300C. 59(11) # Luminosity +300E. 00() # End Event + +!npc 04 (00) 69:04,04 +!npc 1d (00) 69:09,06 +!npc 1e (05) 69:02,10 +EVENT 69-X-XX # $39d83:39d83 +0002. 69(90) +0100. 15(C4-@1800) +0110. 68(6D-6D) +1000. 14(C2-019C-0001-40-C8-30-@1800-FF) +1010. 14(C2-019D-0001-40-C9-30-@1800-FF) +1020. 14(C2-019E-0001-40-CA-30-@1800-FF) +1030. 14(C2-019F-0001-40-CB-30-@1800-FF) +1040. 14(C2-01A0-0001-40-CC-30-@1800-FF) +1050. 14(C2-01A1-0001-40-CD-30-@1800-FF) +1060. 14(C2-01A2-0001-40-CE-30-@1800-FF) +1070. 14(C2-01A3-0001-40-CF-30-@1800-FF) +1080. 14(C2-01A4-0001-40-D0-30-@1800-FF) +1090. 14(C2-01A5-0001-40-D1-30-@1800-FF) +1700. 4B(09) +1710. 1C(@2006) +1800. 4B(15) +2006. 68(50-0E) # Load NPC (14,1c) 50: 0e Yellow Middle Man +2009. 68(51-32) # Load NPC (06,1b) 51: 32 Priest +200C. 68(52-0E) # Load NPC (14,0e) 52: 0e Yellow Middle Man +200F. 68(53-0E) # Load NPC (04,04) 53: 0e Yellow Middle Man +2012. 68(54-0C) # Load NPC (0a,05) 54: 0c Blue Man +2015. 68(55-0E) # Load NPC (16,04) 55: 0e Yellow Middle Man +2018. 68(56-1C) # Load NPC (12,07) 56: 1c Brown Woman +201B. 68(57-10) # Load NPC (13,06) 57: 10 Bald Old Man +201E. 68(58-0D) # Load NPC (17,07) 58: 0d Yellow Woman +2021. 68(59-1C) # Load NPC (05,11) 59: 1c Brown Woman +2024. 68(5A-0F) # Load NPC (20,12) 5a: 0f Green Middle Woman +2027. 68(5B-1A) # Load NPC (1f,05) 5b: 1a Sailor +202A. 68(5C-F1) # Load NPC (0b,11) 5c: f1 Sword +202D. 68(5D-F2) # Load NPC (0a,11) 5d: f2 Shield +2030. 68(5E-F3) # Load NPC (09,11) 5e: f3 Helm +2033. 68(5F-F4) # Load NPC (08,11) 5f: f4 Armor +2036. 68(60-F5) # Load NPC (07,11) 60: f5 Ring +2039. 68(61-F6) # Load NPC (0b,14) 61: f6 Gemstone +203C. 68(62-F7) # Load NPC (0a,14) 62: f7 Rod +203F. 68(63-F8) # Load NPC (09,14) 63: f8 Vase +2042. 68(64-F9) # Load NPC (08,14) 64: f9 Circlet +2045. 68(65-94) # Load NPC (07,14) 65: 94 Jelly +3000. 6A(C4-@7FFF) +3100. 15(02-@3200) +3110. 68(66-01) +3200. 15(03-@3300) +3210. 68(67-02) +3300. 15(04-@3400) +3310. 68(68-03) +3400. 15(05-@3500) +3410. 68(69-04) +3500. 15(06-@3600) +3510. 68(6A-05) +3600. 15(07-@3700) +3610. 68(6B-06) +3700. 15(01-@7FFF) +3710. 68(6C-00) +7FFF. 00() + +EVENT 69-A-02 +#0000. 21(9C-01) +#0001. 21(9D-01) +#0002. 21(9E-01) +#0003. 21(9F-01) +#0004. 21(A0-01) +#0005. 21(A1-01) +#0006. 21(A2-01) +#0007. 21(A3-01) +#0008. 21(A4-01) +#0009. 21(A5-01) +1000. 14(C2-019C-0001-30-@1020-FF) +1010. 1A(C8) +1020. 14(C2-019D-0001-30-@1040-FF) +1030. 1A(C9) +1040. 14(C2-019E-0001-30-@1060-FF) +1050. 1A(CA) +1060. 14(C2-019F-0001-30-@1080-FF) +1070. 1A(CB) +1080. 14(C2-01A0-0001-30-@10a0-FF) +1090. 1A(CC) +10a0. 14(C2-01A1-0001-30-@10c0-FF) +10b0. 1A(CD) +10c0. 14(C2-01A2-0001-30-@10e0-FF) +10d0. 1A(CE) +10e0. 14(C2-01A3-0001-30-@1100-FF) +10f0. 1A(CF) +1100. 14(C2-01A4-0001-30-@1120-FF) +1110. 1A(D0) +1120. 14(C2-01A5-0001-30-@1140-FF) +1130. 1A(D1) +1140. 2E(53) +7FFF. 00() + +EVENT 69-C-53 # $56b32:56cbc +0000. 15(C4-@3A) # Branch on Flag C4 ($0796:10) +0004. 08: You came here for the + Ancient Cave too, right? + There are so many like + you in the back. +# LABEL @3A $56cf6 +003A. 14(10-0B-00-20-@AE-FF) # If Variable 0B ($07a9) == 0 then jump to @AE +0042. 08: Are you going to + leave your party? +0058. 10(02-@6B-@A9) # Set Up Branching Event +005E. 08: Yes. + No. +0066. 08: Alright. +# LABEL @6B $56d27 +006B. 08: Alright. Would you step + outside? There are things + I have to do. +0092. 1D(0B-00) # Set Variable 0B ($07a9) +0094. 1B(01) # Clear Event Flag 01 ($077e:02) +0095. 1B(02) # Clear Event Flag 02 ($077e:04) +0097. 1B(03) # Clear Event Flag 03 ($077e:08) +0099. 1B(04) # Clear Event Flag 04 ($077e:10) +009B. 1B(05) # Clear Event Flag 05 ($077e:20) +009D. 1B(06) # Clear Event Flag 06 ($077e:40) +009F. 1B(07) # Clear Event Flag 07 ($077e:80) +00A0. 1A({{starting_character_flag}}) +00A1. 33(12-00) # Move Character to Location +00A4. 16(68-03-04) # Warp to Map & Event [68-B-03] (04) +00A8. 00() # End Event +# LABEL @A9 $56d65 +00A9. 08: Alright. +# LABEL @AE $56d6a +00AE. 08: Choose the party you're + going with to the cave. + Of course, you can + go by yourself. + +EVENT 69-C-6C +0000. 14(12-0B-03-20-@39-FF) # If Variable 0B ($07a9) >= 3 then jump to @39 +0008. 08: I'm the protagonist. +0028. 1E(0B-01) # Add Value to Variable 0B ($07a9) +0031. 3C() # Gather Behind Maxim +0032. 2B(00) # Character Joins Party +0034. 2E(6C) # Character Disappears +0036. 1A(01) # Set Event Flag 01 ($077e:02) +0038. 00() # End Event +# LABEL @39 $576b2 +0039. 08: ...I'm the protagonist. + +EVENT 69-C-6D +0000. 14(12-0E-0A-20-@2000-FF) +1000. 08: Hark, traveler, do you + tire of all the fighting? + There exists another + path to victory. +1010. 08: Gather all ten Iris + treasures hither this + hallowed tea shop + basement. +1020. 08: Then seek my counsel + yet once more, and + Doom Island shall + be yours. +1030. 00() +2000. 08: Hark... HARK!! + Doth mine eyes behold + a trickery? An ILLUSION?? +2010. 08: 'Tis not! Reunited at + last are the Iris + treasures of old! +2020. 08: Now go, adventurer, + and seize the prize + befitting your long + hunt! +2030. 4C(33) +2040. 95(FF-00-3C) +2050. 37(3C) +2070. 4C(33) +2080. 37(3C) +2090. 97() +2095. 37(1E) +20a0. 4C(32) +2100. A3({{starting_character_index}}-9B) +2110. 37(48) +2200. 1A({{final_boss_flag}}) +2210. 1A({{iris_ending_flag}}) +3010. 6A(01-@3030) +3020. 2C(00) +3030. 6A(02-@3050) +3040. 2C(01) +3050. 6A(03-@3070) +3060. 2C(02) +3070. 6A(04-@3090) +3080. 2C(03) +3090. 6A(05-@30B0) +30A0. 2C(04) +30B0. 6A(06-@30D0) +30C0. 2C(05) +30D0. 6A(07-@3100) +30E0. 2C(06) +3100. 1B(01) +3110. 1B(02) +3120. 1B(03) +3130. 1B(04) +3140. 1B(05) +3150. 1B(06) +3160. 1B(07) +7000. 16(E7-62-01) # Warp to Map & Event E7-B-62 (01) +7FFF. 00() + +!npc 0f (00) 80:0e,04 +EVENT 80-X-XX +0000. 74(01) # Set Battle BG +0002. 69(01) # Set Map Properties (escapable, etc.) +0004. 69(11) # Set Map Properties (escapable, etc.) +0006. 4B(13) # Play BGM +0008. 7B(50-AB) # Load Monster NPC (07,1c) 50: ab Necromancer +0100. 14(C2-0029-0001-20-@7FFF-FF) +0110. 14(C2-01a7-0001-20-@7FFF-FF) +0120. 68(5E-37) +7FFF. 00() # End Event + +EVENT 80-C-5E +0000. 14(C2-01AC-0001-30-@1000-FF) +0010. 08: What the heck?! + Why are you here + again? +0020. 1C(@3000) +1000. 08: Are you stuck? +1010. 10(02-@1040-@2000) +1020. 08: Yes. + No. +1030. 1C(@2000) +1040. 08: Boy, you've really + done it this time. +1050. 08: I can warp you + out, but you have + to do me a favor. +1060. 10(02-@1090-@2000) +1070. 08: Okay. + No way. +1080. 1C(@2000) +1090. 08: Great! Just hold + on to this item + for me. Bye! +10A0. 1C(@3000) +2000. 08: Suit yourself. +3000. A3({{starting_character_index}}-85) +3100. 16(A2-0B-04) +3110. 00() + +EVENT A2-B-0B +0000. 59(11) +0010. 14(C2-01AC-0001-20-@7FFF-FF) +1010. 4B(33) +1020. 8C(00-0A-0F) +1030. 86(00-40) +1040. 49(C8) +1050. 9E: Gets the + JADE OF SHAME. +1060. 89(00) +1070. 49(00) +1080. 21(AC-01) +1090. 70() +10A0. 4B(07) +7FFF. 00() + +!npc 1e (00) 87:07,1f +!npc 1f (00) 87:04,05 +EVENT 87-X-XX # $3a0e9:3a0e9 +0000. 69(90) # Set Map Properties (escapable, etc.) +0002. 4B(22) # Play BGM +0004. 68(50-1C) # Load NPC (1c,05) 50: 1c Brown Woman +0007. 68(51-1C) # Load NPC (1a,05) 51: 1c Brown Woman +000A. 68(52-58) # Load NPC (06,05) 52: 58 Formal Blue Dude +000D. 68(53-58) # Load NPC (11,0c) 53: 58 Formal Blue Dude +0010. 68(54-1C) # Load NPC (03,0e) 54: 1c Brown Woman +0013. 68(55-1C) # Load NPC (13,08) 55: 1c Brown Woman +0016. 68(56-10) # Load NPC (04,09) 56: 10 Bald Old Man +0019. 68(57-58) # Load NPC (0a,0c) 57: 58 Formal Blue Dude +001C. 68(58-0C) # Load NPC (06,11) 58: 0c Blue Man +001F. 68(59-58) # Load NPC (1d,1b) 59: 58 Formal Blue Dude +0022. 68(5A-17) # Load NPC (10,0e) 5a: 17 Maid +0025. 68(5B-11) # Load NPC (13,11) 5b: 11 Gray Old Woman +0028. 68(5C-1A) # Load NPC (0e,06) 5c: 1a Sailor +002B. 68(5D-1C) # Load NPC (1b,1b) 5d: 1c Brown Woman +002E. 68(5E-58) # Load NPC (12,1f) 5e: 58 Formal Blue Dude +0031. 68(63-58) # Load NPC (0d,1e) 63: 58 Formal Blue Dude +0034. 68(64-12) # Load NPC (0b,20) 64: 12 King +0037. 68(65-13) # Load NPC (0d,22) 65: 13 Queen +003A. 68(66-15) # Load NPC (0f,20) 66: 15 Princess +003D. 68(67-1C) # Load NPC (0d,0b) 67: 1c Brown Woman +0040. 68(68-1C) # Load NPC (13,0d) 68: 1c Brown Woman +0043. 68(69-35) # Load NPC (0c,0f) 69: 35 Elf Woman +0046. 68(6A-58) # Load NPC (07,0e) 6a: 58 Formal Blue Dude +0049. 68(6B-58) # Load NPC (05,0e) 6b: 58 Formal Blue Dude +004C. 68(6E-37) +0100. 68(6D-14) +7FFF. 00() # End Event + +EVENT 87-C-6D +0000. 08: I'm a placeholder. + +EVENT 87-C-6E +0000. 08: For your convenience, + get the hottest + consumable items + right here! +1000. 18(1A) +7FFF. 00() + +!npc 0f (05) a2:0d,21 +!npc 1a (00) a2:0b,19 +!npc 1b (00) a2:0c,19 +!npc 1c (00) a2:0d,19 +EVENT A2-X-XX # $3a5f1:3a5f1 +0000. 6A(0A-@1000) +0010. 14(00-1A-80-1B-80-1C-30-@80-FF) +0020. 4B(09) +0030. 1C(@1000) +0080. 4B(1F) +1000. 69(90) +1031. 68(56-6E) # Load NPC (06,09) 56: 6e Gray Lab Assistant +1034. 68(57-6F) # Load NPC (0d,08) 57: 6f Red Lab Assistant +1037. 68(58-6E) # Load NPC (0e,1a) 58: 6e Gray Lab Assistant +103A. 68(59-6E) # Load NPC (08,19) 59: 6e Gray Lab Assistant +103D. 68(5A-6F) # Load NPC (05,1f) 5a: 6f Red Lab Assistant +1040. 68(5B-6E) # Load NPC (12,1b) 5b: 6e Gray Lab Assistant +1043. 68(5C-0B) # Load NPC (12,21) 5c: 0b Green Girl +1046. 68(5D-40) # Load NPC (0c,1f) 5d: 40 Lab Assistant +1049. 68(5E-71) # Load NPC (0d,21) 5e: 71 Little Boat +2000. 6A(1A-@2020) +2010. 68(69-44) +2020. 6A(1B-@2040) +2030. 68(6A-44) +2040. 6A(1C-@7FFF) +2050. 68(6B-44) +7FFF. 00() # End Event + +EVENT A2-B-0A +0050. 76() +0140. 59(11) +0200. 23({{starting_character_index}}-26) # Learn Spell +0210. 23({{starting_character_index}}-24) # Learn Spell +0300. 7E(00) # Set Ship Exists/Unexists +0310. 7D(E0) # Relocate Ship +0320. 7C(00) # Change Ship Type +0330. 1D(0B-00) +0340. 1A(95) +0400. 22(0BB8) +0410. 21(AD-01) +0420. 21(AE-01) +0430. 25(A9-01) +{{hidden_item}} +{{starting_item_reward_event}} +7FE0. 4B(1F) +7FF0. 1A(0A) +7FFF. 00() + +EVENT A2-C-5D +0000. 14(00-1A-80-1B-80-1C-30-@1000-FF) +0020. 08: You've rescued all three + maidens! Board the Excerion + to fly to Doom Island! +0800. 08: You need an Engine to fly + to Doom Island. +1000. 08: Return here after rescuing + the three maidens to go to + Doom Island! + +EVENT A2-C-69 +0000. 08: I'm Lisa. + +EVENT A2-C-6A +0000. 08: I'm Marie. + +EVENT A2-C-6B +0000. 08: I'm Clare. + +!tile 0a a2:0d,20 2x1 +EVENT A2-D-0A +0000. 14(00-1A-80-1B-80-1C-30-@1000-FF) +0020. 9E: Fly to Doom Island? +0030. 10(02-@60-@1000) +0040. 08: Yes. + No. +0050. 1C(@1000) +0060. 5B(04-0D) +0070. 5B(04-0E) +0080. 16(E6-63-01) +0800. 00() +1000. 9E: Depart on the + Excerion? +1010. 10(02-@1040-@1030) +1020. 08: Yes. + No. +1030. 00() +1040. 7E(00) +1050. 7D(02) +1060. 7F(FF) +1100. 2E(00) +1110. 2E(01) +1120. 2E(02) +1130. 2E(03) +1140. 2E(04) +1150. 2E(05) +1160. 2E(06) +1170. 33(25-5E) +1200. 5E(03) +7FFF. 00() + +EVENT E6-B-63 # $701c2:701ce +0000. 2E(00) # Character Disappears +0001. 2E(01) # Character Disappears +0002. 2E(02) # Character Disappears +0003. 2E(03) # Character Disappears +0004. 2E(04) # Character Disappears +0005. 2E(05) # Character Disappears +0006. 2E(06) # Character Disappears +0007. 2D({{starting_character_index}}) +1006. 6C({{starting_character_index}}-F8-00) +100A. 34({{starting_character_index}}-FA) +100D. A3({{starting_character_index}}-9B) +1010. 59(11) # Luminosity +1012. 76() +1013. 89(00) +1015. 37(14) # Pause +1017. 16(E7-62-01) # Warp to Map & Event E7-B-62 (01) +101B. 00() # End Event + +!exit 01 (00) ea:0,0->ea:0,0 +!tile 0a ea:10,12 +EVENT EA-X-XX +0000. 74(08) # Set Battle BG +0002. 69(D9) # Set Map Properties (escapable, etc.) +7FFF. 00() # End Event + +EVENT EA-A-00 +0000. 15({{final_boss_flag}}-@30) +0010. 4B(0A) +0020. 00() +0030. 4B(38) +7FFF. 00() # End Event + +EVENT EA-A-01 +0000. 15({{final_boss_flag}}-@7FFF) +1007. 43(02-01) +7FFF. 00() + +EVENT EA-D-01 +0000. 15({{final_boss_flag}}-@7FFF) +1000. 9E: You may not cross. +1010. 16(E9-0A-01) +7FFF. 00() + +EVENT EA-D-0A +0000. A3({{starting_character_index}}-85) +1000. 16(EB-0A-07) +7FFF. 00() + +!tile 02 eb:00,00 +!npc 01 (05) eb:0f,1e +!npc 02 (05) eb:0f,1e +!npc 03 (05) eb:0f,1e +!npc 04 (05) eb:0d,0b +!npc 05 (05) eb:11,0b +EVENT EB-X-XX +0000. 69(D9) +0010. 4B(38) +1000. 68(50-70) +1010. 68(51-70) +1020. 68(52-70) +1030. 6A({{iris_ending_flag}}-@7FFF) +2000. 68(53-6D) +2010. 68(54-{{final_boss_sprite_index}}) +7FFF. 00() + +EVENT EB-A-00 +7FFF. 00() + +EVENT EB-A-01 +7FFF. 00() + +EVENT EB-B-0A +0000. 3B(07) +0010. 6A(01-@30) +0020. 2C(00) +0030. 6A(02-@50) +0040. 2C(01) +0050. 6A(03-@70) +0060. 2C(02) +0070. 6A(04-@90) +0080. 2C(03) +0090. 6A(05-@B0) +00A0. 2C(04) +00B0. 6A(06-@D0) +00C0. 2C(05) +00D0. 6A(07-@400) +00E0. 2C(06) +0400. 59(11) +0800. 41(11-12) + +1000. 33(06-{{starting_character_index}}) + +1010. 6A(01-@1030) +1015. 34({{ending_npc_a}}-00) +1020. 1B(01) +1025. 1C(@2010) +1030. 6A(02-@1050) +1035. 34({{ending_npc_a}}-01) +1040. 1B(02) +1045. 1C(@2010) +1050. 6A(03-@1070) +1055. 34({{ending_npc_a}}-02) +1060. 1B(03) +1065. 1C(@2010) +1070. 6A(04-@1090) +1075. 34({{ending_npc_a}}-03) +1080. 1B(04) +1085. 1C(@2010) +1090. 6A(05-@10B0) +1095. 34({{ending_npc_a}}-04) +10A0. 1B(05) +10A5. 1C(@2010) +10B0. 6A(06-@10D0) +10B5. 34({{ending_npc_a}}-05) +10C0. 1B(06) +10C5. 1C(@2010) +10D0. 6A(07-@2010) +10D5. 34({{ending_npc_a}}-06) +10E0. 1B(07) + +2010. 6A(01-@2030) +2015. 34({{ending_npc_b}}-00) +2020. 1B(01) +2025. 1C(@3010) +2030. 6A(02-@2050) +2035. 34({{ending_npc_b}}-01) +2040. 1B(02) +2045. 1C(@3010) +2050. 6A(03-@2070) +2055. 34({{ending_npc_b}}-02) +2060. 1B(03) +2065. 1C(@3010) +2070. 6A(04-@2090) +2075. 34({{ending_npc_b}}-03) +2080. 1B(04) +2085. 1C(@3010) +2090. 6A(05-@20B0) +2095. 34({{ending_npc_b}}-04) +20A0. 1B(05) +20A5. 1C(@3010) +20B0. 6A(06-@20D0) +20B5. 34({{ending_npc_b}}-05) +20C0. 1B(06) +20C5. 1C(@3010) +20D0. 6A(07-@3010) +20D5. 34({{ending_npc_b}}-06) +20E0. 1B(07) + +3010. 6A(01-@3030) +3015. 34({{ending_npc_c}}-00) +3020. 1B(01) +3025. 1C(@4010) +3030. 6A(02-@3050) +3035. 34({{ending_npc_c}}-01) +3040. 1B(02) +3045. 1C(@4010) +3050. 6A(03-@3070) +3055. 34({{ending_npc_c}}-02) +3060. 1B(03) +3065. 1C(@4010) +3070. 6A(04-@3090) +3075. 34({{ending_npc_c}}-03) +3080. 1B(04) +3085. 1C(@4010) +3090. 6A(05-@30B0) +3095. 34({{ending_npc_c}}-04) +30A0. 1B(05) +30A5. 1C(@4010) +30B0. 6A(06-@30D0) +30B5. 34({{ending_npc_c}}-05) +30C0. 1B(06) +30C5. 1C(@4010) +30D0. 6A(07-@4010) +30D5. 34({{ending_npc_c}}-06) +30E0. 1B(07) + +4010. 1A(0A) +4030. 33(03-51) +4040. 33(04-52) +4050. 33(05-50) +4060. 37(0f) +4070. 31(50-02) +4080. 31(51-02) +4090. 31(52-02) + +40A0. 9E: Congratulations!! + You are the {{ending_title}} + of Doom Island! +40B0. 58(18) +40C0. 57() +40D0. 4B(28) +40E0. 5B(05-00) +40F0. BB() +7FFF. 00() + +!tile 0a f0:0d,07 +EVENT F0-D-0A +0000. 15(93-@7FFF) +0010. A8(00) +0020. A8(01) +7FFF. 00() + +!npc 02 (00) f0:0c,0d +EVENT F0-C-51 +0000. 15(93-@1024) # Branch on Flag 93 ($0790:08) +0010. 08: I can hold your + items and levels for + safekeeping. +0020. 08: Otherwise, items you + use will be lost + permanently. Leave + your items with me? +0030. 10(02-@50-@1004) +0040. 08: No. + Yes. +0050. 08: As you wish. You + may keep your items. +0060. 1C(@101D) +1004. 08: I will keep your + items here. +1018. A8(00) # Ancient Cave Item Management +101A. 1A(93) # Set Event Flag 93 ($0790:08) +# LABEL @101D +101D. 33(01-51) # Move Character to Location +101F. 1A(FA) # Set Event Flag FA ($079d:04) +1021. 1B(FB) # Clear Event Flag FB ($079d:08) +1023. 00() # End Event +# LABEL @24 $72369 +1024. 08: I wish you good luck! + +EVENT F0-C-52 +0000. 15(FB-@143) # Branch on Flag FB ($079d:08) +0008. 6A(93-@72) # Branch on NOT Flag 93 ($0790:08) +000C. 08: Oh, it's you. You're + back safe and sound! + Let me return your + items to you. +003A. 08: You may now return to + the city with your + head held high! +0060. A8(01) # Ancient Cave Item Management +0062. 14(00-C3-30-@6C-FF) # If Flag C3 ($0796:08) set then DON'T jump to @6C +0069. 21(C2-01) # Get Item 1XX (Ancient key x1) +# LABEL @6C $723e4 +006C. 1B(93) # Clear Event Flag 93 ($0790:08) +006E. 33(02-52) # Move Character to Location +0071. 00() # End Event +# LABEL @72 $723ea +0072. 08: Want to watch me take + one step to the right? +0080. 33(02-52) # Move Character to Location +0090. 00() +# LABEL @143 $724bb +0143. 08: I have returned all the + items. Please come + again! From a3fb2533e069bfd5429107b16598c8f9f901e5a6 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Tue, 1 Aug 2023 09:37:47 +0200 Subject: [PATCH 05/18] Added. --- ideas.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 ideas.md diff --git a/ideas.md b/ideas.md new file mode 100644 index 0000000..7a83eba --- /dev/null +++ b/ideas.md @@ -0,0 +1,22 @@ + +A list of things that MAY be considered to be added in the future. + + +# Blitz Mode + - Warp is very powerful. It feels more rewarding if you get it from a boss. + - Learnable by all characters. + - Also remove buying warps. + + - Escape is very powerful. It feels more rewarding if you get it from a boss. + - Add an escape tile to boss rooms (not capsules), so you don't have to walk back. + - Learnable by all characters. + - Also remove buying escapes. + - Give 5 escape items at start. + + - Add defeating Gades, Amon and Erim as requirement for flying to doom island. + - Add hints to other boss locations where to find them. + - Also make Daos last boss on doom island. + + - Distribute keys sometimes to chests + - Make most chests empty in order to reduce number of checks + - Chests may contain warp/escape spell/items From d521c18f4a9f9e408f759902a13f9dcc80123dd7 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Tue, 1 Aug 2023 13:23:20 +0200 Subject: [PATCH 06/18] Updated --- ideas.md | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/ideas.md b/ideas.md index 7a83eba..e5d26d5 100644 --- a/ideas.md +++ b/ideas.md @@ -1,22 +1,36 @@ A list of things that MAY be considered to be added in the future. +# General + +### Correct translations +- She Viper => Sea Viper +- Asashin => Assassin +- Waiban => Wyvern +- Mad Gorem => Mud Golem +- Sand Gorem => Sand Golem (and all other versions) +- Hidora => Hydra (and all other versions) + +### Small Shrine to Treadool +Stop the guard from blocking the way after 5-15 seconds or give opportunity to *fight* your way free. # Blitz Mode - - Warp is very powerful. It feels more rewarding if you get it from a boss. - - Learnable by all characters. - - Also remove buying warps. - - - Escape is very powerful. It feels more rewarding if you get it from a boss. - - Add an escape tile to boss rooms (not capsules), so you don't have to walk back. - - Learnable by all characters. - - Also remove buying escapes. - - Give 5 escape items at start. - - - Add defeating Gades, Amon and Erim as requirement for flying to doom island. - - Add hints to other boss locations where to find them. - - Also make Daos last boss on doom island. - - - Distribute keys sometimes to chests - - Make most chests empty in order to reduce number of checks - - Chests may contain warp/escape spell/items +- Warp is very powerful. It feels more rewarding getting it from a boss. + - Learnable by all characters. + - Also remove buying warps. + - As soon as you learn it you can warp to all previously visited towns. Even if u didn't have warp at that time. + +- Escape is very powerful. It feels more rewarding getting it from a boss. + - Add an escape tile to boss rooms (not capsules), so you don't have to walk back. + - Learnable by all characters. + - Also remove buying escapes. + - Give 5 escape items at start. + +- Add defeating Gades, Amon and Erim as requirement for flying to doom island. + - Add hints to other boss locations where to find them. + - Also make Daos last boss on doom island. + +- Distribute keys sometimes to chests + - Make most chests empty in order to reduce number of checks + - Chests may contain warp/escape spell/items + From f823a06478b1ad75c6f2760767f472aaacc27508 Mon Sep 17 00:00:00 2001 From: PhilAndChill <140955262+phku-hk@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:40:48 +0200 Subject: [PATCH 07/18] Create python-packaging.yml --- .github/workflows/python-packaging.yml | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/python-packaging.yml diff --git a/.github/workflows/python-packaging.yml b/.github/workflows/python-packaging.yml new file mode 100644 index 0000000..f9aa8b4 --- /dev/null +++ b/.github/workflows/python-packaging.yml @@ -0,0 +1,32 @@ +name: Python Packaging + +on: [push] + +jobs: + build-windows: + runs-on: windows + strategy: + max-parallel: 5 + + steps: + - name: PyInstaller Build + # You may pin to the exact commit or the version. + # uses: eric2788/pyinstaller-build@28997858929e3dcf38a6d05018a2affc5b11383e + uses: eric2788/pyinstaller-build@0.1.3 + with: + # the main python file (without .py) + main: randomizer.py + # the dist path + dist: ./dist # optional, default is ./dist + # the version of python + python_version: 3.10.8 # optional, default is 3.9.7 + # the version of pyinstaller + pyinstaller_version: 4.7 # optional, default is 4.7 + # the output exe name + artifact: main # optional, default is main + # whether to install requirements.txt before build + use-dependencies: true # optional, default is true + # whether to disppear console terminal + no-console: false # optional + # add the icon mark into your executable, the file path of your ico + icon: NONE # optional, default is NONE From cb944badbc6efe7b62f589f3addee784c5205a4a Mon Sep 17 00:00:00 2001 From: PhilAndChill <140955262+phku-hk@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:43:07 +0200 Subject: [PATCH 08/18] Update python-packaging.yml --- .github/workflows/python-packaging.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-packaging.yml b/.github/workflows/python-packaging.yml index f9aa8b4..44426b6 100644 --- a/.github/workflows/python-packaging.yml +++ b/.github/workflows/python-packaging.yml @@ -3,8 +3,8 @@ name: Python Packaging on: [push] jobs: - build-windows: - runs-on: windows + build-linux: + runs-on: ubuntu-latest strategy: max-parallel: 5 From 32d9f648819af09eeb634746b299b2608d91c028 Mon Sep 17 00:00:00 2001 From: PhilAndChill <140955262+phku-hk@users.noreply.github.com> Date: Tue, 1 Aug 2023 17:31:08 +0200 Subject: [PATCH 09/18] Create python-build-exe.yml --- .github/workflows/python-build-exe.yml | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/python-build-exe.yml diff --git a/.github/workflows/python-build-exe.yml b/.github/workflows/python-build-exe.yml new file mode 100644 index 0000000..3e25e47 --- /dev/null +++ b/.github/workflows/python-build-exe.yml @@ -0,0 +1,76 @@ +name: Python Package using Conda + +on: [push] + +jobs: + build-linux: + runs-on: ubuntu-latest + strategy: + max-parallel: 5 + + steps: + - name: Build EXE from Python Script + # You may pin to the exact commit or the version. + # uses: Nuitka/Nuitka-Action@c6dcfbdc669bfb7006feeb1b6a9d29c963cb63ea + uses: Nuitka/Nuitka-Action@v0.5 + with: + # Version of nuitka to use + #nuitka-version: # optional, default is main + # name or path to python script that is to be built + script-name: randomizer.py + # Create an extension module executable instead of a program. Defaults to off. + #module: # optional + # Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "-- follow-imports" and "--python-flag=no_site". Defaults to true. + #standalone: # optional, default is true + # On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to true. + #onefile: # optional, default is true + # Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "' on this platform. .exe) + output-file: randomizer-blitz # optional + # github personal access token of an account authorized to access the Nuitka/Nuitka-commercial repo + #access-token: # optional + # When compiling for Windows or macOS, enable the console window and create a console application. This disables hints from certain modules, e.g. "PySide" that suggest to disable it. Defaults to true. + #enable-console: # optional, default is true + # When compiling for Windows or macOS, disable the console window and create a GUI application. Defaults to false. + #disable-console: # optional + # Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with \# where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored. + #windows-icon-from-ico: # optional + # Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off. + #windows-uac-admin: # optional + # Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off. + #windows-uac-uiaccess: # optional + # Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to GITHUB_REPOSITORY_OWNER. + #windows-company-name: # optional, default is ${{ github.repository_owner }} + # Name of the product to use in Windows Version information. Defaults to base filename of the binary. + #windows-product-name: # optional + # File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. + #windows-file-version: # optional + # Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. + #windows-product-version: # optional + # Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense. + #windows-file-description: # optional + # Use this as a temporary folder. Defaults to '%TEMP%\onefile_%PID%_%TIME%', i.e. system temporary directory. + #windows-onefile-tempdir-spec: # optional + # allows/enforces building with MinGW64 + #mingw64: # optional + # When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console. Defaults to false. + #macos-create-app-bundle: # optional From 4ee90fc3ead70d0df0c7b8959b18dc48ae438711 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Wed, 2 Aug 2023 00:38:40 +0200 Subject: [PATCH 10/18] Adjusted Blitz Mode Seed Generation Updated Ideas Updated Blitz Routing Requirements --- ideas.md | 8 +++ randomizer.py | 99 ++++++++++++++++++++++++++++++----- tables/requirements_blitz.txt | 4 +- 3 files changed, 95 insertions(+), 16 deletions(-) diff --git a/ideas.md b/ideas.md index e5d26d5..913ed2c 100644 --- a/ideas.md +++ b/ideas.md @@ -34,3 +34,11 @@ Stop the guard from blocking the way after 5-15 seconds or give opportunity to * - Make most chests empty in order to reduce number of checks - Chests may contain warp/escape spell/items + +# Hero Mode +- Open world +- Remove grinding entirely. + - Instead of grinding money for gear you find suitable in chests. (no junk) + - You also find suitable spells in chests. (no tier 1 spells) + - All characters are level 30 and monsters are scaled based on that. + - Monsters no longer give xp diff --git a/randomizer.py b/randomizer.py index d31f822..7bb819b 100644 --- a/randomizer.py +++ b/randomizer.py @@ -164,8 +164,8 @@ def price_clean(self): price /= (10**power) price = price / 2 assert price <= 65500 - #if price > 10 and price % 10 == 0 and int(VERSION[0]) % 2 == 1: - #price = price - 1 + if price > 10 and price % 10 == 0 and int(VERSION[0]) % 2 == 1: + price = price - 1 self.price = int(round(price)) @@ -5218,6 +5218,57 @@ def set_new_leader_for_events(new_character_index, old_character_index=0): script.script = new_script +class LocationTime: + def __init__(self): + self.location_time = { + 'starting_character': 0, + 'starting_item': 0, + 'hidden_item': 0, + 'daos_shrine': 0, + 'foomy_woods': 1, + 'darbi_shrine': 1, + 'zeppy_cave': 1, + 'lexis_lab': 1, + 'underwater_shrine': 1, + 'daos_shrine': 1, + 'no_return_mountain': 2, + 'skill_cave': 2, + 'sundletan_cave': 2, + 'ruby_cave': 2, + 'ruby_capsule': 2, + 'cave_bridge': 2, + 'north_dungeon': 4, + 'north_capsule': 4, + 'catfish_cave': 5, + 'alunze_cave': 5, + 'alunze_basement': 5, + 'sacrifice_tower': 5, + 'sacrifice_capsule': 5, + 'northeast_tower': 5, + 'flower_mountain': 7, + 'flower_capsule': 7, + 'tanbel_tower': 10, + 'ancient_tower': 10, + 'lighthouse': 10, + 'gratze_basement': 10, + 'shuman': 10, + 'stradha': 10, + 'kamirno': 10, + 'truth_tower': 10, + 'karlloon_shrine': 15, + 'divine_shrine': 15, + 'vengeance_shrine': 15, + 'dragon_mountain': 20, + 'tsword_shrine': 20, + 'gordovan_tower': 20, + 'phantom_mountain': 20, + 'dankirk_dungeon': 25, + } + + def get_time_of_location(self, loc): + key = loc.rstrip('1').rstrip('2') + return self.location_time[key] if key in self.location_time else 20 + def make_wild_jelly(jelly_flag): MapEventObject.class_reseed('make_wild_jelly') JELLY_SPRITE_INDEX = 0x94 @@ -6499,7 +6550,7 @@ def make_open_world(custom=None): elif 'blitz' in get_activated_codes(): ir = ItemRouter(path.join(tblpath, 'requirements_blitz.txt'), path.join(tblpath, 'restrictions_blitz.txt'), - linearity=0.4) + linearity=0.8) else: ir = ItemRouter(path.join(tblpath, 'requirements.txt'), path.join(tblpath, 'restrictions.txt'), @@ -6520,18 +6571,38 @@ def make_open_world(custom=None): assert 'daos_shrine' not in ir.assignments ir.assignments['daos_shrine'] = 'victory' - for loc in ir.unassigned_locations: - if loc.endswith('1'): - other = loc[:-1] + '2' - if other in ir.assignments: - print( "Not assigned: {}".format(loc) ) - #assert not ir.assignments[other].endswith('_key') + if 'blitz' in get_activated_codes(): + locTime = LocationTime() + for r in range(20): # Retry count for a good blitz seed + victory_set = {'lisa', 'marie', 'clare'} + items = set() + noLocChecks = 0 + for rank in sorted(ir.location_ranks): + locations = ir.location_ranks[rank] + for loc in sorted(locations, key=locTime.get_time_of_location): + noLocChecks = noLocChecks + 1 + if loc in ir.assignments: + items.add(ir.assignments[loc]) + if items >= victory_set: + break + if items >= victory_set: + break + if noLocChecks >= 20 and noLocChecks <= 30: + break + print( "{} checks are bad. Retrying.".format( noLocChecks ) ) + ir.clear_assignments() + ir.assign_everything() + ir.assignments['daos_shrine'] = 'victory' + + else: # Disallow non-key rewards for non-blitz + for loc in ir.unassigned_locations: + if loc.endswith('1'): + other = loc[:-1] + '2' + if other in ir.assignments: + assert not ir.assignments[other].endswith('_key') MapEventObject.class_reseed('selecting_characters') - if VERSION == '3.16' and 1682460000 <= get_seed() <= 1682460000 + 172800: - VALID_LEADERS = ['artea', 'lexis'] - else: - VALID_LEADERS = ['selan', 'guy', 'artea', 'tia', 'dekar', 'lexis'] + VALID_LEADERS = ['selan', 'guy', 'artea', 'tia', 'dekar', 'lexis'] assert ir.assignments['starting_character'] == 'character0' name = random.choice(VALID_LEADERS) character_recruitments = {'character0': name} @@ -6987,7 +7058,7 @@ def key_shop(): def run_trials(): LOGFILE = 'trial_log.txt' - NUM_TRIALS = 100 + NUM_TRIALS = 1000 victory_set = {'lisa', 'marie', 'clare', 'engine'} linearity = 0 with open(LOGFILE, 'w') as f: diff --git a/tables/requirements_blitz.txt b/tables/requirements_blitz.txt index cc2589f..ddc4746 100644 --- a/tables/requirements_blitz.txt +++ b/tables/requirements_blitz.txt @@ -14,7 +14,7 @@ .def any_shrine_key sword_key|heart_key|ghost_key .def any_mountain_key tree_key|magma_key|flower_key .def any_tower_key cloud_key|light_key|narcysus_key|sky_key|trial_key|truth_key|wind_key -.def some_key any_dungeon_key&any_shrine_key&any_mountain_key&any_tower_key +.def some_keys any_dungeon_key&any_shrine_key&any_mountain_key&any_tower_key .def party0 any_tool&character0 @@ -95,4 +95,4 @@ gratze_basement gratze&arrowlike&basement_key&party2 shuman airship&party3 stradha airship&party3 kamirno airship&party3 -daos_shrine lisa&marie&clare&some_key +daos_shrine lisa&marie&clare&some_keys&all_tools From 886461831af65c83d90097e1c85228752ec6dcd0 Mon Sep 17 00:00:00 2001 From: PhilAndChill <140955262+phku-hk@users.noreply.github.com> Date: Wed, 2 Aug 2023 10:45:27 +0200 Subject: [PATCH 11/18] Delete .github/workflows directory --- .github/workflows/python-build-exe.yml | 76 -------------------------- .github/workflows/python-packaging.yml | 32 ----------- 2 files changed, 108 deletions(-) delete mode 100644 .github/workflows/python-build-exe.yml delete mode 100644 .github/workflows/python-packaging.yml diff --git a/.github/workflows/python-build-exe.yml b/.github/workflows/python-build-exe.yml deleted file mode 100644 index 3e25e47..0000000 --- a/.github/workflows/python-build-exe.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Python Package using Conda - -on: [push] - -jobs: - build-linux: - runs-on: ubuntu-latest - strategy: - max-parallel: 5 - - steps: - - name: Build EXE from Python Script - # You may pin to the exact commit or the version. - # uses: Nuitka/Nuitka-Action@c6dcfbdc669bfb7006feeb1b6a9d29c963cb63ea - uses: Nuitka/Nuitka-Action@v0.5 - with: - # Version of nuitka to use - #nuitka-version: # optional, default is main - # name or path to python script that is to be built - script-name: randomizer.py - # Create an extension module executable instead of a program. Defaults to off. - #module: # optional - # Enable standalone mode for output. This allows you to transfer the created binary to other machines without it using an existing Python installation. This also means it will become big. It implies these option: "-- follow-imports" and "--python-flag=no_site". Defaults to true. - #standalone: # optional, default is true - # On top of standalone mode, enable onefile mode. This means not a folder, but a compressed executable is created and used. Defaults to true. - #onefile: # optional, default is true - # Allow Nuitka to download external code if necessary, e.g. dependency walker, ccache, and even gcc on Windows. To disable, redirect input from nul device, e.g. "' on this platform. .exe) - output-file: randomizer-blitz # optional - # github personal access token of an account authorized to access the Nuitka/Nuitka-commercial repo - #access-token: # optional - # When compiling for Windows or macOS, enable the console window and create a console application. This disables hints from certain modules, e.g. "PySide" that suggest to disable it. Defaults to true. - #enable-console: # optional, default is true - # When compiling for Windows or macOS, disable the console window and create a GUI application. Defaults to false. - #disable-console: # optional - # Add executable icon. Can be given multiple times for different resolutions or files with multiple icons inside. In the later case, you may also suffix with \# where n is an integer index starting from 1, specifying a specific icon to be included, and all others to be ignored. - #windows-icon-from-ico: # optional - # Request Windows User Control, to grant admin rights on execution. (Windows only). Defaults to off. - #windows-uac-admin: # optional - # Request Windows User Control, to enforce running from a few folders only, remote desktop access. (Windows only). Defaults to off. - #windows-uac-uiaccess: # optional - # Name of the company to use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to GITHUB_REPOSITORY_OWNER. - #windows-company-name: # optional, default is ${{ github.repository_owner }} - # Name of the product to use in Windows Version information. Defaults to base filename of the binary. - #windows-product-name: # optional - # File version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. - #windows-file-version: # optional - # Product version to use in Windows Version information. Must be a sequence of up to 4 numbers, e.g. 1.0.0.0, only this format is allowed. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to unused. - #windows-product-version: # optional - # Description of the file use in Windows Version information. One of file or product version is required, when a version resource needs to be added, e.g. to specify product name, or company name. Defaults to nonsense. - #windows-file-description: # optional - # Use this as a temporary folder. Defaults to '%TEMP%\onefile_%PID%_%TIME%', i.e. system temporary directory. - #windows-onefile-tempdir-spec: # optional - # allows/enforces building with MinGW64 - #mingw64: # optional - # When compiling for macOS, create a bundle rather than a plain binary application. Currently experimental and incomplete. Currently this is the only way to unlock disabling of console. Defaults to false. - #macos-create-app-bundle: # optional diff --git a/.github/workflows/python-packaging.yml b/.github/workflows/python-packaging.yml deleted file mode 100644 index 44426b6..0000000 --- a/.github/workflows/python-packaging.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Python Packaging - -on: [push] - -jobs: - build-linux: - runs-on: ubuntu-latest - strategy: - max-parallel: 5 - - steps: - - name: PyInstaller Build - # You may pin to the exact commit or the version. - # uses: eric2788/pyinstaller-build@28997858929e3dcf38a6d05018a2affc5b11383e - uses: eric2788/pyinstaller-build@0.1.3 - with: - # the main python file (without .py) - main: randomizer.py - # the dist path - dist: ./dist # optional, default is ./dist - # the version of python - python_version: 3.10.8 # optional, default is 3.9.7 - # the version of pyinstaller - pyinstaller_version: 4.7 # optional, default is 4.7 - # the output exe name - artifact: main # optional, default is main - # whether to install requirements.txt before build - use-dependencies: true # optional, default is true - # whether to disppear console terminal - no-console: false # optional - # add the icon mark into your executable, the file path of your ico - icon: NONE # optional, default is NONE From fda806cb3a4b4b4657f58aaeec90c5921bac6b1e Mon Sep 17 00:00:00 2001 From: phku-hk Date: Thu, 3 Aug 2023 10:18:28 +0200 Subject: [PATCH 12/18] Some corrections --- ideas.md | 14 ++------------ randomizer.py | 10 +++------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/ideas.md b/ideas.md index 913ed2c..c3ee0e8 100644 --- a/ideas.md +++ b/ideas.md @@ -3,17 +3,6 @@ A list of things that MAY be considered to be added in the future. # General -### Correct translations -- She Viper => Sea Viper -- Asashin => Assassin -- Waiban => Wyvern -- Mad Gorem => Mud Golem -- Sand Gorem => Sand Golem (and all other versions) -- Hidora => Hydra (and all other versions) - -### Small Shrine to Treadool -Stop the guard from blocking the way after 5-15 seconds or give opportunity to *fight* your way free. - # Blitz Mode - Warp is very powerful. It feels more rewarding getting it from a boss. - Learnable by all characters. @@ -21,7 +10,7 @@ Stop the guard from blocking the way after 5-15 seconds or give opportunity to * - As soon as you learn it you can warp to all previously visited towns. Even if u didn't have warp at that time. - Escape is very powerful. It feels more rewarding getting it from a boss. - - Add an escape tile to boss rooms (not capsules), so you don't have to walk back. + - Add an escape tile/npc to boss rooms (not capsules), so you don't have to walk back. - Learnable by all characters. - Also remove buying escapes. - Give 5 escape items at start. @@ -40,5 +29,6 @@ Stop the guard from blocking the way after 5-15 seconds or give opportunity to * - Remove grinding entirely. - Instead of grinding money for gear you find suitable in chests. (no junk) - You also find suitable spells in chests. (no tier 1 spells) + - Make most chests empty in order to reduce number of checks - All characters are level 30 and monsters are scaled based on that. - Monsters no longer give xp diff --git a/randomizer.py b/randomizer.py index 7bb819b..bd4ca14 100644 --- a/randomizer.py +++ b/randomizer.py @@ -45,7 +45,7 @@ def lange(low, high): def check_open_world(): if any(code in get_activated_codes() for code in - {'open', 'airship', 'custom', 'fourkeys'}) or 'w' in get_flags(): + {'open', 'airship', 'custom', 'fourkeys', 'blitz'}) or 'w' in get_flags(): return True return False @@ -6587,7 +6587,7 @@ def make_open_world(custom=None): break if items >= victory_set: break - if noLocChecks >= 20 and noLocChecks <= 30: + if 20 <= noLocChecks <= 30: break print( "{} checks are bad. Retrying.".format( noLocChecks ) ) ir.clear_assignments() @@ -7061,8 +7061,6 @@ def run_trials(): NUM_TRIALS = 1000 victory_set = {'lisa', 'marie', 'clare', 'engine'} linearity = 0 - with open(LOGFILE, 'w') as f: - pass for n in range(NUM_TRIALS): MapEventObject.class_reseed('trial%s-%s' % (linearity, n+4000)) ir = ItemRouter(path.join(tblpath, 'requirements.txt'), @@ -7073,17 +7071,15 @@ def run_trials(): assert 'daos_shrine' not in ir.assignments ir.assignments['daos_shrine'] = 'victory' items = set() - noLocChecks = 0 for rank in sorted(ir.location_ranks): locations = ir.location_ranks[rank] for loc in sorted(locations): - noLocChecks = noLocChecks + 1 if loc in ir.assignments: items.add(ir.assignments[loc]) if items >= victory_set: break with open(LOGFILE, 'a+') as f: - s = '%s %s %s %s\n' % (linearity, rank, max(ir.location_ranks), noLocChecks) + s = '%s %s %s\n' % (linearity, rank, max(ir.location_ranks)) f.write(s) print(s.strip()) From 845f871dc23187de61b1aae350bc32dd0ea37196 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Sun, 6 Aug 2023 13:30:41 +0200 Subject: [PATCH 13/18] Blitz seed now always have between 20 to 25 checks for a fast playthrough. Also changed requirements to add at least one capsule monster. --- randomizer.py | 11 ++++++----- tables/requirements_blitz.txt | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/randomizer.py b/randomizer.py index bd4ca14..e22d55c 100644 --- a/randomizer.py +++ b/randomizer.py @@ -6573,23 +6573,24 @@ def make_open_world(custom=None): if 'blitz' in get_activated_codes(): locTime = LocationTime() + victory_set = {'lisa', 'marie', 'clare'} for r in range(20): # Retry count for a good blitz seed - victory_set = {'lisa', 'marie', 'clare'} items = set() - noLocChecks = 0 + locsChecked = set() for rank in sorted(ir.location_ranks): locations = ir.location_ranks[rank] for loc in sorted(locations, key=locTime.get_time_of_location): - noLocChecks = noLocChecks + 1 + key = loc.rstrip('1').rstrip('2') + locsChecked.add(key) if loc in ir.assignments: items.add(ir.assignments[loc]) if items >= victory_set: break if items >= victory_set: break - if 20 <= noLocChecks <= 30: + if 20 <= len(locsChecked) <= 25: break - print( "{} checks are bad. Retrying.".format( noLocChecks ) ) + print( "{} checks are bad. Retrying.".format( len(locsChecked) ) ) ir.clear_assignments() ir.assign_everything() ir.assignments['daos_shrine'] = 'victory' diff --git a/tables/requirements_blitz.txt b/tables/requirements_blitz.txt index ddc4746..475e171 100644 --- a/tables/requirements_blitz.txt +++ b/tables/requirements_blitz.txt @@ -7,6 +7,7 @@ .def all_capsules jelze&flash&gusto&zeppy&darbi&sully&blaze .def some_capsules jelze|flash|gusto|zeppy|darbi|sully|blaze +.def less_capsules gusto|darbi|sully|blaze .def any_tool arrow|bomb|hook|hammer|fire_arrow .def any_key sky_key|lake_key|ruby_key|wind_key|cloud_key|light_key|sword_key|tree_key|flower_key|magma_key|heart_key|ghost_key|trial_key|dankirk_key|basement_key|narcysus_key|truth_key @@ -95,4 +96,4 @@ gratze_basement gratze&arrowlike&basement_key&party2 shuman airship&party3 stradha airship&party3 kamirno airship&party3 -daos_shrine lisa&marie&clare&some_keys&all_tools +daos_shrine lisa&marie&clare&some_keys&all_tools&less_capsules From 98fb3bfc05524b81514c6a378f53fc37e791c962 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Sun, 6 Aug 2023 14:02:47 +0200 Subject: [PATCH 14/18] Changed version string to show blitz. --- randomizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/randomizer.py b/randomizer.py index e22d55c..10e34c8 100644 --- a/randomizer.py +++ b/randomizer.py @@ -20,7 +20,7 @@ from traceback import format_exc -VERSION = '3.16' +VERSION = '3.16 blitz1.0.4' TEXT_VERSION = 'Three Sixteen' ALL_OBJECTS = None DEBUG_MODE = False From 9d5c3c5413772446db2997b182e396437ab11341 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Sun, 6 Aug 2023 14:04:21 +0200 Subject: [PATCH 15/18] Changed version string. --- randomizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/randomizer.py b/randomizer.py index 10e34c8..1cdbdc2 100644 --- a/randomizer.py +++ b/randomizer.py @@ -20,7 +20,7 @@ from traceback import format_exc -VERSION = '3.16 blitz1.0.4' +VERSION = '3.16 blitz1.0.3' TEXT_VERSION = 'Three Sixteen' ALL_OBJECTS = None DEBUG_MODE = False From b9f32b0a251e26d07025a0ea60b3967ccf9d4f3a Mon Sep 17 00:00:00 2001 From: phku-hk Date: Wed, 9 Aug 2023 13:28:29 +0200 Subject: [PATCH 16/18] Added secret code: 'sinistrals' Spoiler now shows bosses. --- README | 1 + randomizer.py | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README b/README index 7c2613a..c6ba23e 100644 --- a/README +++ b/README @@ -39,6 +39,7 @@ Secret Codes: bossy Very random bosses (unbalanced even with scaling) fourkeys Open World, but there are only four keys blitz Allows a faster playthrough + sinistrals Maidens are always guarded by sinistrals. Makes Daos last boss. OPEN WORLD ENEMY SCALING scale Scale enemy status in open-world mode diff --git a/randomizer.py b/randomizer.py index 1cdbdc2..5e9525b 100644 --- a/randomizer.py +++ b/randomizer.py @@ -20,7 +20,7 @@ from traceback import format_exc -VERSION = '3.16 blitz1.0.3' +VERSION = '3.16 blitz1.0.4' TEXT_VERSION = 'Three Sixteen' ALL_OBJECTS = None DEBUG_MODE = False @@ -6424,7 +6424,7 @@ def get_sorted_stats(m): m.scale_stats(scale_amount) -def make_spoiler(ir, character_recruitments): +def make_spoiler(ir, character_recruitments, location2BossMap={}): head, tail = path.split(get_outfile()) outfilename = path.join(head, 'spoiler.{0}.txt'.format(tail)) randomness = [o.random_degree for o in ALL_OBJECTS] @@ -6439,7 +6439,17 @@ def make_spoiler(ir, character_recruitments): 'difficulty: {}'.format(get_difficulty()), ) header = '\n'.join(s) - footer = ir.report + footer = [] + locTime = LocationTime() + for rank in sorted(ir.location_ranks): + locations = ir.location_ranks[rank] + for loc in sorted(locations, key=lambda k: (locTime.get_time_of_location(k), k) ): + if loc in ir.assignments: + item = ir.assignments[loc] + bossloc = loc.rstrip('2').rstrip('1') + boss = location2BossMap[bossloc] if bossloc in location2BossMap else '-' + footer.append( "{0:<20}{1:<20}{2}".format( loc, item, boss ) ) + footer = "\n".join(footer) for recruitment, character_name in character_recruitments.items(): while len(character_name) < len(recruitment): character_name += ' ' @@ -6784,7 +6794,6 @@ def make_open_world(custom=None): ir.assignments[location] = 'item_{0:0>3x}'.format(item.index) sorted_locations = [l for l in sorted_locations if l in used_locations] - make_spoiler(ir, character_recruitments) MapEventObject.class_reseed('boss_route2') random.shuffle(chosen_bosses) @@ -6830,6 +6839,8 @@ def make_open_world(custom=None): patch_with_template('open_world_events', parameters) boss_events = [] + sinistrals = {"Gades x1", "Amon x1", "Erim x1", "Daos x1"} + location2BossMap = {'starting_item': '', 'starting_character': '', 'hidden_item': ''} assert len(shuffled_bosses) == len(sorted_locations) for location, boss in sorted(location_bosses.items()): assert location not in NOBOSS_LOCATIONS @@ -6851,6 +6862,23 @@ def make_open_world(custom=None): reward1 = character_recruitments[reward1] if isinstance(reward2, str) and reward2.startswith('character'): reward2 = character_recruitments[reward2] + if 'sinistrals' in get_activated_codes(): + if reward1 == "lisa" or reward2 == "lisa": + boss = "gades2" + elif reward1 == "clare" or reward2 == "clare": + boss = "amon1" + elif reward1 == "marie" or reward2 == "marie": + boss = "erim" + elif reward1 == "victory": + boss = "daos" + elif boss.name in sinistrals: + for i in range(100): + boss.reseed("boss%s" % (i) ) + boss.become_random() + if boss.name not in sinistrals: + break + bossName = boss if isinstance(boss, str) else boss.name + location2BossMap[location.rstrip('1').rstrip('2')] = bossName.strip() result = OpenNPCGenerator.create_boss_npc(location, boss, reward1, reward2, parameters) location, boss, reward1, reward2, event = result @@ -6860,6 +6888,8 @@ def make_open_world(custom=None): assigned_item_indexes.append(int(reward.item_index, 0x10)) + make_spoiler(ir, character_recruitments, location2BossMap) + for location in sorted(OpenNPCGenerator.boss_location_properties): if location not in OpenNPCGenerator.done_locations: OpenNPCGenerator.create_prince(location) @@ -7108,6 +7138,7 @@ def run_trials(): 'nocap': ['nocap'], 'fourkeys': ['fourkeys'], 'blitz': ['blitz'], + 'sinistrals': ['sinistrals'], } run_interface(ALL_OBJECTS, snes=True, codes=codes, custom_degree=True, custom_difficulty=True) From 4c0d9ffb2ee9deb98806235dabee67f34d62a640 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Fri, 11 Aug 2023 11:14:56 +0200 Subject: [PATCH 17/18] Added 'last_sinistral' secret code --- README | 3 ++- randomizer.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README b/README index c6ba23e..b380583 100644 --- a/README +++ b/README @@ -38,8 +38,9 @@ Secret Codes: airship Start the game with the airship. bossy Very random bosses (unbalanced even with scaling) fourkeys Open World, but there are only four keys - blitz Allows a faster playthrough + blitz Allows a faster open world playthrough sinistrals Maidens are always guarded by sinistrals. Makes Daos last boss. + last_sinistral Last boss is always one of the sinistrals. Conflicts with 'sinistrals' code. OPEN WORLD ENEMY SCALING scale Scale enemy status in open-world mode diff --git a/randomizer.py b/randomizer.py index 5e9525b..cf1f646 100644 --- a/randomizer.py +++ b/randomizer.py @@ -20,7 +20,7 @@ from traceback import format_exc -VERSION = '3.16 blitz1.0.4' +VERSION = '3.16 blitz1.0.5' TEXT_VERSION = 'Three Sixteen' ALL_OBJECTS = None DEBUG_MODE = False @@ -6877,8 +6877,18 @@ def make_open_world(custom=None): boss.become_random() if boss.name not in sinistrals: break + elif 'last_sinistral' in get_activated_codes(): + if reward1 == "victory": + boss = random.choice(["gades4", "amon2", "erim", "daos"]) + elif boss.name in sinistrals: + for i in range(100): + boss.reseed("boss%s" % (i) ) + boss.become_random() + if boss.name not in sinistrals: + break + bossName = boss if isinstance(boss, str) else boss.name - location2BossMap[location.rstrip('1').rstrip('2')] = bossName.strip() + location2BossMap[location.rstrip('1').rstrip('2')] = bossName result = OpenNPCGenerator.create_boss_npc(location, boss, reward1, reward2, parameters) location, boss, reward1, reward2, event = result @@ -7139,6 +7149,7 @@ def run_trials(): 'fourkeys': ['fourkeys'], 'blitz': ['blitz'], 'sinistrals': ['sinistrals'], + 'last_sinistral': ['last_sinistral'], } run_interface(ALL_OBJECTS, snes=True, codes=codes, custom_degree=True, custom_difficulty=True) From b7a69dbc9cf763167ed402b6a4eec4d3823c9f38 Mon Sep 17 00:00:00 2001 From: phku-hk Date: Sat, 19 Aug 2023 14:27:51 +0200 Subject: [PATCH 18/18] Added secret code 'music_last_sinistral' to make battle theme 2 play at the final boss. Fixed sinistrals not showing up in battle. --- README | 5 ++-- randomizer.py | 48 +++++++++++++++++++----------- tables/template_final_boss_npc.txt | 2 +- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/README b/README index b380583..de881a2 100644 --- a/README +++ b/README @@ -39,8 +39,8 @@ Secret Codes: bossy Very random bosses (unbalanced even with scaling) fourkeys Open World, but there are only four keys blitz Allows a faster open world playthrough - sinistrals Maidens are always guarded by sinistrals. Makes Daos last boss. - last_sinistral Last boss is always one of the sinistrals. Conflicts with 'sinistrals' code. + sinistrals Maidens are always guarded by sinistrals. Makes Daos final boss. + last_sinistral Final boss is always one of the sinistrals. Conflicts with 'sinistrals' code. OPEN WORLD ENEMY SCALING scale Scale enemy status in open-world mode @@ -56,6 +56,7 @@ Secret Codes: nothingpersonnelkid Extremely aggressive enemies. nocap Disables in-battle capsule swapping anywhere Equipment slots are randomized (breaks "Strongest") + music_last_sinistral Final boss music is sinistrals battle theme. Randomness: Terror Wave is the first Abyssonym randomizer to include a "randomness" option. This option controls how extreme the randomizations are. At 0.0, almost nothing will be randomized. At 1.0, enemies in the starting area will most likely have boss stats. I suggest leaving it at the default setting of 0.5 for your first run. diff --git a/randomizer.py b/randomizer.py index cf1f646..61b2d72 100644 --- a/randomizer.py +++ b/randomizer.py @@ -20,7 +20,7 @@ from traceback import format_exc -VERSION = '3.16 blitz1.0.5' +VERSION = '3.16 blitz1.0.6' TEXT_VERSION = 'Three Sixteen' ALL_OBJECTS = None DEBUG_MODE = False @@ -164,8 +164,6 @@ def price_clean(self): price /= (10**power) price = price / 2 assert price <= 65500 - if price > 10 and price % 10 == 0 and int(VERSION[0]) % 2 == 1: - price = price - 1 self.price = int(round(price)) @@ -474,6 +472,9 @@ def details(self): coordinates = ' '.join(coordinates) return '{0}\n{1}\n{2}'.format(s, coordinates, hexify(self.unknown)) + def rewind(self): + self.monster_indexes = self.old_data['monster_indexes'] + @property def monsters(self): return [MonsterObject.get(i) for i in self.monster_indexes @@ -5182,6 +5183,7 @@ def create_boss_npc(location, boss, reward1=None, reward2=None, parameters[attr] = getattr(propobj, attr) if 'victory' in (reward1, reward2): + parameters['music_id'] = '1B' if 'music_last_sinistral' in get_activated_codes() else '1C' patch_with_template('final_boss_npc', parameters) elif reward1 and reward2: patch_with_template('boss_npc_double_reward', parameters) @@ -6723,6 +6725,8 @@ def make_open_world(custom=None): sorted_locations.append(key) used_locations -= NOBOSS_LOCATIONS + sinistrals = {"Gades x1", "Amon x1", "Erim x1", "Daos x1"} + skip_sinistrals = 'sinistrals' in get_activated_codes() or 'last_sinistral' in get_activated_codes() bosses = sorted(OpenNPCGenerator.boss_properties.values(), key=lambda b: b.name) random.shuffle(bosses) @@ -6733,11 +6737,13 @@ def make_open_world(custom=None): key = b.name if key[-1] in '0123456789': key = key[:-1] - b = BossFormationObject.get(int(b.boss_formation_index, 0x10)) + bfo = BossFormationObject.get(int(b.boss_formation_index, 0x10)) + if skip_sinistrals and bfo.name in sinistrals: + continue if key in done_bosses: - spare_formations.append(b) + spare_formations.append(bfo) continue - chosen_bosses.append(b) + chosen_bosses.append(bfo) done_bosses.add(key) old_formations = {bfo.name for bfo in BossFormationObject.uniques} @@ -6839,7 +6845,7 @@ def make_open_world(custom=None): patch_with_template('open_world_events', parameters) boss_events = [] - sinistrals = {"Gades x1", "Amon x1", "Erim x1", "Daos x1"} + location2BossMap = {'starting_item': '', 'starting_character': '', 'hidden_item': ''} assert len(shuffled_bosses) == len(sorted_locations) for location, boss in sorted(location_bosses.items()): @@ -6863,14 +6869,19 @@ def make_open_world(custom=None): if isinstance(reward2, str) and reward2.startswith('character'): reward2 = character_recruitments[reward2] if 'sinistrals' in get_activated_codes(): - if reward1 == "lisa" or reward2 == "lisa": - boss = "gades2" - elif reward1 == "clare" or reward2 == "clare": - boss = "amon1" - elif reward1 == "marie" or reward2 == "marie": - boss = "erim" - elif reward1 == "victory": - boss = "daos" + r = (reward1, reward2) + if 'lisa' in r: + bfi = OpenNPCGenerator.boss_properties['gades2'].boss_formation_index + boss = BossFormationObject.get(int(bfi, 0x10)) + elif 'clare' in r: + bfi = OpenNPCGenerator.boss_properties['amon1'].boss_formation_index + boss = BossFormationObject.get(int(bfi, 0x10)) + elif 'marie' in r: + bfi = OpenNPCGenerator.boss_properties['erim'].boss_formation_index + boss = BossFormationObject.get(int(bfi, 0x10)) + elif 'victory' in r: + bfi = OpenNPCGenerator.boss_properties['daos'].boss_formation_index + boss = BossFormationObject.get(int(bfi, 0x10)) elif boss.name in sinistrals: for i in range(100): boss.reseed("boss%s" % (i) ) @@ -6878,8 +6889,10 @@ def make_open_world(custom=None): if boss.name not in sinistrals: break elif 'last_sinistral' in get_activated_codes(): - if reward1 == "victory": - boss = random.choice(["gades4", "amon2", "erim", "daos"]) + if 'victory' in (reward1, reward2): + bna = random.choice(["gades4", "amon2", "erim", "daos"]) + bfi = OpenNPCGenerator.boss_properties[bna].boss_formation_index + boss = BossFormationObject.get(int(bfi, 0x10)) elif boss.name in sinistrals: for i in range(100): boss.reseed("boss%s" % (i) ) @@ -7150,6 +7163,7 @@ def run_trials(): 'blitz': ['blitz'], 'sinistrals': ['sinistrals'], 'last_sinistral': ['last_sinistral'], + 'music_last_sinistral': ['music_last_sinistral'], } run_interface(ALL_OBJECTS, snes=True, codes=codes, custom_degree=True, custom_difficulty=True) diff --git a/tables/template_final_boss_npc.txt b/tables/template_final_boss_npc.txt index efa00d3..c46757a 100644 --- a/tables/template_final_boss_npc.txt +++ b/tables/template_final_boss_npc.txt @@ -6,7 +6,7 @@ EVENT {{map_index}}-X-XX {{old_event}} EVENT {{map_index}}-C-{{npc_event_index}} - 1020. 4B(1C) + 1020. 4B({{music_id}}) 1030. 74({{battle_bg}}) 1040. 53({{boss_formation_index}}) 1050. 6A(FF-@1080)