From fd99620ac979e52c934b0cfb7de9d02cb590dd28 Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 6 Oct 2023 12:56:29 -0600 Subject: [PATCH 01/17] Standard: generation error fixed --- Rules.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules.py b/Rules.py index 4140469c..9b6ed1a9 100644 --- a/Rules.py +++ b/Rules.py @@ -1375,12 +1375,12 @@ def find_rules_for_zelda_delivery(world, player): if not rule(blank_state): rule_list.append(rule) next_path.append(ext.name) - if connect.name == 'Sanctuary': + if connect.name == 'Hyrule Castle Throne Room': return rule_list, next_path else: visited.add(connect) queue.append((connect, rule_list, next_path)) - raise Exception('No path to Sanctuary found') + raise Exception('No path to Throne Room found') def set_big_bomb_rules(world, player): From 8b5c5ce2547b8150afb52e1b686d294f0c4df535 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 10 Oct 2023 02:08:36 -0500 Subject: [PATCH 02/17] ROM Fixes - Fix standing item dupe respawns - Fix Hera boss room falling fade out --- Rom.py | 2 +- asm/owrando.asm | 16 ---------------- data/base2current.bps | Bin 107671 -> 107686 bytes 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/Rom.py b/Rom.py index a99e98c7..97edcdce 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '52317b2dd4fb303887f26ecc40a4cae3' +RANDOMIZERBASEHASH = 'de030c9fec5157af4ad1cf1948428210' class JsonRom(object): diff --git a/asm/owrando.asm b/asm/owrando.asm index adc7635e..16c60aee 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -169,11 +169,6 @@ plb : rtl nop #3 + -; follower hooks -;org $8689D9 -;SpritePrep_BombShoppe: -;JML BombShoppe_ConditionalSpawn : NOP - ;Code org $aa8800 OWTransitionDirection: @@ -541,7 +536,6 @@ OWBonkDrops: INX : LDA.w OWBonkPrizeData,X : PHX : PHA ; S = FlagBitmask, X (row + 2) LDX.b $8A : LDA.l OverworldEventDataWRAM,X : AND 1,S : PHA : BNE + ; S = Collected, FlagBitmask, X (row + 2) LDA.b #$1B : STA $12F ; JSL Sound_SetSfx3PanLong ; seems that when you bonk, there is a pending bonk sfx, so we clear that out and replace with reveal secret sfx - ; JSLSpriteSFX_QueueSFX3WithPan + LDA 3,S : TAX : INX : LDA.w OWBonkPrizeData,X PHA : INX : LDA.w OWBonkPrizeData,X : BEQ + @@ -873,7 +867,6 @@ OWNewDestination: ++ lda $84 : !add 1,s : sta $84 : pla : pla .adjustMainAxis - ;LDA $84 : SEC : SBC #$0400 : AND #$0F80 : ASL : XBA : STA $88 ; vram LDA $84 : SEC : SBC #$0400 : AND #$0F00 : ASL : XBA : STA $88 ; vram LDA $84 : SEC : SBC #$0010 : AND #$003E : LSR : STA $86 @@ -936,7 +929,6 @@ OWNewDestination: sep #$30 : lda $04 : and #$3f : !add OWOppSlotOffset,y : asl : sta $700 ; crossed OW shuffle and terrain - ;lda $8a : JSR OWDetermineScreensPaletteSet : STX $04 ldx $05 : ldy $08 : jsr OWWorldTerrainUpdate ldx $8a : lda $05 : sta $8a : stx $05 ; $05 is prev screen id, $8a is dest screen @@ -1161,14 +1153,6 @@ OWEndScrollTransition: RTL } -; BombShoppe_ConditionalSpawn: -; { -; nop -; INC.w $0BA0,X : LDA.b #$B5 ; what we wrote over -; JML SpritePrep_BombShoppe+5 -; nop#20 -; } - ;Data org $aaa000 OWEdgeOffsets: diff --git a/data/base2current.bps b/data/base2current.bps index 3c56274a00f1b9d319f2082083e17de09264ec86..930280e65cf3437d9796b2f5d3dacd74d95a28b7 100644 GIT binary patch delta 6808 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 dP2h)MUVO=KXjJyZ4*V&gI1Bd?${|}+Z(;@%> delta 6668 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 Date: Sun, 22 Oct 2023 16:24:11 -0500 Subject: [PATCH 03/17] Fix for Hera boss music fadeout when falling --- Rom.py | 2 +- data/base2current.bps | Bin 107686 -> 107687 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 97edcdce..d253271d 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'de030c9fec5157af4ad1cf1948428210' +RANDOMIZERBASEHASH = '2a89df65883fba75578061ebfb4b1003' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 930280e65cf3437d9796b2f5d3dacd74d95a28b7..e46b012a02d7c37315fd2bbf44178e69041ea6e9 100644 GIT binary patch delta 6193 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 g=U6`~09So@kww3wu~s( Date: Tue, 24 Oct 2023 05:29:52 -0500 Subject: [PATCH 04/17] Allow user to change and save output directory within the Gui --- resources/app/gui/lang/en.json | 2 +- source/gui/bottom.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 66aefd98..8a6a0212 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -391,7 +391,7 @@ "bottom.content.dialog.error": "Error while creating seed", "bottom.content.dialog.success": "Success", "bottom.content.dialog.success.message": "Rom created successfully.", - "bottom.content.outputdir": "Open Output Directory", + "bottom.content.outputdir": "Select Destination", "bottom.content.docs": "Open Documentation" } } diff --git a/source/gui/bottom.py b/source/gui/bottom.py index beb77a1f..4c21621e 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -154,6 +154,12 @@ def bottom_frame(self, parent, args=None): open_file(output_path('.')) + def select_output(): + from tkinter import filedialog + folder_selected = filedialog.askdirectory() + if folder_selected is not None: + args.outputpath = parent.settings["outputpath"] = folder_selected + ## Output Button # widget ID widget = "outputdir" @@ -168,7 +174,7 @@ def bottom_frame(self, parent, args=None): # button self.widgets[widget].type = "button" - self.widgets[widget].pieces["button"] = Button(self, text='Open Output Directory', command=open_output) + self.widgets[widget].pieces["button"] = Button(self, text='Open Output Directory', command=select_output) # button: pack self.widgets[widget].pieces["button"].pack(side=RIGHT) From 42c51d28155634f6b98ec176368dc1fed5b04628 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 24 Oct 2023 07:38:45 -0500 Subject: [PATCH 05/17] Fix Hera music to play correct dungeon track following a floor change --- Rom.py | 2 +- data/base2current.bps | Bin 107687 -> 107693 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index d253271d..e74a80bb 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '2a89df65883fba75578061ebfb4b1003' +RANDOMIZERBASEHASH = '52bd727d617de6491fdbb74fd047852d' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index e46b012a02d7c37315fd2bbf44178e69041ea6e9..0b9e4f9d64f7a216bd5c188920d1b726fe5b0c05 100644 GIT binary patch delta 1042 zcmW+!drVtp9KFBNQc7R6<qplXH@Da*}hVm%=|? z3csL%HtNuuKv83VvTwhaVyCUJ0uO!1So_)V9DO>RfhWE!F2&+X{&rWKBa`VHykDTq zHx^mQf-CfI0yW$j6slO*LmC%$LJd7GtN}y^g_ZD#E)<;sqwjMO69Mng@5ULsOM>p? ze){F(gBph&Z&`P-KcevGgYJ73$sie`(5ehn@FLokf$q>T`_GPaz;yTv>+a=-Tct@@V9zw)%cCpl(IegjYj&Vw zs>4R+I<4eEr?n4XQz4~|T%hHsBO1y@g#%=a(@F`~R34+V0WC*Eu{w3by%qj_)Q*j~ zIYZc!lCEW=Vj+*%osEpNU>EJu@;a9aTT}USQBDj@=IoFBk$JrNZJ!_iaM{wtC78@c zE`d0wrWlUmldCi4nf5@JCtBNGRM%X;{K4M+lZYJ)nNZ8*#lkHR7>X|pZ@Ttj-e2jr zkVp(3y6Ud1vhev8SI5+TbV&|f(2DjcAS-%g z+pPvHkhu3pZrc}+P1pVr`Nz;33Qz!!&L|)i@{mgby}(E6csL6xv=ARE(T48C!$~MX zRS8fc5EohJ+Ka8+zN6=q%uoUhhQ+`7%)b+1o{dI7{v9;ZX8Z7#s39QGIS&wwRtX1q zTq%s8YHWnDqydWqxu_{4G<`dRGGKwjHJC4xEL6=H@?e4$5th_Pj>-rNv-2$YSR6sA zb^7?UR|9OmGO?FxINa!RdGnaBieQ_?YZ2QomdUUCBn+d4RUY4PYJk!aiE1$_V8)KZ zVwm)><;id=hJ~JRskQ9#^f1z*Ry`zes&j^D9isGb0`zECA8I2($p#qU$7qJAs*s@! n#WCL)z@m(j)XaIR%^3GTEF{-BUttQG!BP-G`2Bp;pj`VO6%vl} delta 1070 zcmW+!YfM`O7`@-+Q3|vSTA;k7y*#AI`(=^G){SY0@=#nh9qMF6=$N87oR1Cey&D6{ zF5Tr)zp*+gv>ibdW*WRR#z3|yLtNIWGyHJ6Oo9dppaqv;w%P2*IVb1*I5|JgXS4nz zv;L=b(83q)hhF~dg75I*mwE&iZo-mlFZqZsug{V38TW#!CLsGPo^gCEen+FC{zoBvKr_YJhG=?MJSTL2NkYKxflR-!t0UM?L{6( zVvkU@uTN*@sOCkR?{S{m?r|)YF%NAu{ZMYZo_V`(o}*yh@#lo?>Q^iCtG8-TaJ6F| z$Ghy{6-$S_Hh0~T(!ia*yLEBP5-?DD-@9Ejgp6?FGYW zCwQuT(dH^vRcImEWzyd@z=Vr6HH5%^*V4d|R+tm(LLh|Hekpej&q@e)`fx;V8qmpD zp2eS&k7vQ{zuhVdKToA&rT?sqn`MpfImE~o3)Xr*a9lDiJqD)wEtoeVp<*tdoI!bdI z&7~}S95vyfgiI_5hhdc}@S3=>I^8`*eK2?6kc1Xfnj|!~H{)73sGuID5s(2@qAmii zL$IObv}M&6OHBMI>_deLk{|~QRghWaBjcGAG}O>SS*e+MVTNTIy)X{4-1NaUKjGRC zwPCR}o#7TptU6?N9((cAd6F8xX?x$ULc0o%K@)1CATz_V?$83^j@$e-r}c}C+Dre+ zr*Pe|sWK8Dbr4<#!)PwiK{j^yjOJQnu`LRcAq$;R&;@>&5e+9H8YiQ@i<@yF8V-UE zt74!uSX#`EwUn@u?p>Xai32gv=M$x?^f-N-D@{|>WoR;B57+1pHdtRXc8WXWAweoB zSDI0(G>gqCK>9%%wxoM+&?cTshYNlZL;ZP%#HYpQb76=KkZQV_0R??Pyq6Cy($9Yz zJFgAO Date: Sun, 5 Nov 2023 08:46:58 -0600 Subject: [PATCH 06/17] Various MSU corrections/fixes - GT2 track now plays if DR and GTBK is collected --- Rom.py | 2 +- data/base2current.bps | Bin 107693 -> 107715 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index e74a80bb..f11ced3b 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '52bd727d617de6491fdbb74fd047852d' +RANDOMIZERBASEHASH = 'd1f78b0b0a4aad1523ad0068dd24aa50' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 0b9e4f9d64f7a216bd5c188920d1b726fe5b0c05..ec152a61ce211a64429ba9a4a4c12b4aa3eb0a40 100644 GIT binary patch delta 15584 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 delta 15386 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 Date: Wed, 8 Nov 2023 23:10:34 -0600 Subject: [PATCH 07/17] Marking OW screens as visited --- Rom.py | 2 +- asm/owrando.asm | 13 +++++++++++++ data/base2current.bps | Bin 107715 -> 107745 bytes 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index f11ced3b..3a82aa7c 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd1f78b0b0a4aad1523ad0068dd24aa50' +RANDOMIZERBASEHASH = 'fe9e7870071daa40829c1072829bf30b' class JsonRom(object): diff --git a/asm/owrando.asm b/asm/owrando.asm index 16c60aee..485bab50 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -29,6 +29,9 @@ BCS OWDetectTransitionReturn org $02a999 jsl OWEdgeTransition : nop #4 ;LDA $02A4E3,X : ORA $7EF3CA +org $02aa07 +JSL OWMarkVisited : NOP + org $04e8ae JSL OWDetectSpecialTransition RTL : NOP @@ -340,6 +343,16 @@ OWOldManSpeed: lda #$0c : sta $5e ; what we wrote over rtl } +OWMarkVisited: +{ + LDX.b $8A : STZ.w $0412 ; what we wrote over + LDA.b $10 : CMP.b #$14 : BCS .return + LDA.l OverworldEventDataWRAM,X + ORA.b #$80 : STA.l OverworldEventDataWRAM,X + + .return + RTL +} LoadMapDarkOrMixed: { diff --git a/data/base2current.bps b/data/base2current.bps index ec152a61ce211a64429ba9a4a4c12b4aa3eb0a40..a21ad3abf7406231397ccf4c057391d8ef5b7d7a 100644 GIT binary patch delta 395 zcmV;60d)Su$p+!c2C#ks1R-1Aq_ctn#{vonfRQ3`iK^-(fU`>kAO!)9vup|L1p$Y% zSP#N70U(1LLYEst0q0I3fba^Xpeg>z@bD0T2BnJ01Mmo?Udaq=WL|5j42526riz>r z1f>wk6tI_UG>?UVpO1{K$ppeM@DQT@1HC!dmT(n`jrM|Q0GD4gkC!_`0U`nnikDwQ z0b@yui&~qnLGpen0!YvWsT++i0j~hOs_>U%ZjTj$CX28CyQ;~s&;_Y^Oa_a|LeK{y zSgi(33X91!&;_a4Oa_a|HP8jA+DrzEmkLAyHw86~s*?kkMnnNR0X3I_L;;sU7K)vK z*yz0gyV^*XR}%t&g(CrHrI7#t delta 302 zcmaEOlI`$GwheWREK13D=WK3bJkG@A(zrR8MS+#Ed~*rsYgWd>%?bR6j2O9^m7S(5 zJ25_I)SS-k%&0Kk-kDL1Nv~mggfpWO)3?s)HO`F5j3v__I5SG=whDCjch@$a+;D+) zWu?!Du9Hp|*p(vIviW@JI%xtFy9p9A1u|{{8Phdf7|mJbdsj_noSx#sXvHW$eZC9h zbjPgDxeYg7>}A+}%VWB>FjGUTGUI#^UZ#eNi Date: Mon, 13 Nov 2023 15:43:27 -0700 Subject: [PATCH 08/17] fix(key logic): typo fix(bunny logic): multiple paths considered --- KeyDoorShuffle.py | 2 +- Main.py | 2 +- RELEASENOTES.md | 4 ++ Rules.py | 177 ++++++++++++++++++++++++---------------------- 4 files changed, 100 insertions(+), 85 deletions(-) diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index 7284c0cf..6883fb94 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -1800,7 +1800,7 @@ def imp_locations_factory(world, player): imp_locations = ['Agahnim 1', 'Agahnim 2', 'Attic Cracked Floor', 'Suspicious Maiden'] if world.mode[player] == 'standard': imp_locations.append('Zelda Pickup') - imp_locations.append('Zelda Dropoff') + imp_locations.append('Zelda Drop Off') return imp_locations diff --git a/Main.py b/Main.py index 24fa0080..d5b39084 100644 --- a/Main.py +++ b/Main.py @@ -34,7 +34,7 @@ from source.overworld.EntranceShuffle2 import link_entrances_new from source.tools.BPS import create_bps_from_data from source.classes.CustomSettings import CustomSettings -version_number = '1.2.0.21' +version_number = '1.2.0.22' version_branch = '-u' __version__ = f'{version_number}{version_branch}' diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cae2bc56..5abff4a8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -109,6 +109,10 @@ These are now independent of retro mode and have three options: None, Random, an # Bug Fixes and Notes +* * 1.2.0.22u + * Fixed logic issues: + * Self-locking key not allowed in Sanctuary in standard (typo fixed) + * More advanced bunny-walking logic in dungeons (multiple paths considred) * 1.2.0.21u * Fix that should force items needed for leaving Zelda's cell to before the throne room, so S&Q isn't mandatory * Small fix for Tavern Shuffle (thanks Catobat) diff --git a/Rules.py b/Rules.py index 9b6ed1a9..1560dba2 100644 --- a/Rules.py +++ b/Rules.py @@ -101,16 +101,20 @@ def mirrorless_path_to_castle_courtyard(world, player): else: queue.append((entrance.connected_region, new_path)) + def set_rule(spot, rule): spot.access_rule = rule + def set_defeat_dungeon_boss_rule(location): # Lambda required to defer evaluation of dungeon.boss since it will change later if boos shuffle is used set_rule(location, lambda state: location.parent_region.dungeon.boss.can_defeat(state)) + def set_always_allow(spot, rule): spot.always_allow = rule + def add_rule(spot, rule, combine='and'): old_rule = spot.access_rule if combine == 'or': @@ -140,22 +144,26 @@ def forbid_item(location, item, player): old_rule = location.item_rule location.item_rule = lambda i: (i.name != item or i.player != player) and old_rule(i) + def add_item_rule(location, rule): old_rule = location.item_rule location.item_rule = lambda item: rule(item) and old_rule(item) + def item_in_locations(state, item, player, locations): for location in locations: if item_name(state, location[0], location[1]) == (item, player): return True return False + def item_name(state, location, player): location = state.world.get_location(location, player) if location.item is None: return None return (location.item.name, location.item.player) + def global_rules(world, player): # ganon can only carry triforce add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) @@ -187,7 +195,7 @@ def global_rules(world, player): set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) - set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith + set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest @@ -625,7 +633,7 @@ def global_rules(world, player): set_rule(world.get_entrance('Swamp Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Swamp Barrier', player), player)) set_rule(world.get_entrance('Swamp Crystal Switch Inner to Crystal', player), lambda state: state.can_hit_crystal(player)) - set_rule(world.get_entrance('Swamp Crystal Switch Outer to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Swamp Crystal Switch Outer', player), player))) # It is the length of the sword, not the beam itself that allows this + set_rule(world.get_entrance('Swamp Crystal Switch Outer to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Swamp Crystal Switch Outer', player), player))) # It is the length of the sword, not the beam itself that allows this set_rule(world.get_entrance('Swamp Crystal Switch Outer to Inner Bypass', player), lambda state: state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) set_rule(world.get_entrance('Swamp Crystal Switch Inner to Outer Bypass', player), lambda state: state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) @@ -668,8 +676,8 @@ def global_rules(world, player): set_rule(world.get_entrance('Mire Crystal Left Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Mire Crystal Left', player), player)) set_rule(world.get_entrance('Mire Conveyor to Crystal', player), lambda state: state.can_hit_crystal(player)) - set_rule(world.get_entrance('Mire Tall Dark and Roomy to Ranged Crystal', player), lambda state: True) # Can always throw pots - set_rule(world.get_entrance('Mire Fishbone Blue Barrier Bypass', player), lambda state: False) # (state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) and state.can_tastate.can_use_bombs(player) // Easy to do but obscure. Should it be in logic? + set_rule(world.get_entrance('Mire Tall Dark and Roomy to Ranged Crystal', player), lambda state: True) # Can always throw pots + set_rule(world.get_entrance('Mire Fishbone Blue Barrier Bypass', player), lambda state: False) # (state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) and state.can_tastate.can_use_bombs(player) // Easy to do but obscure. Should it be in logic? set_rule(world.get_location('Turtle Rock - Chain Chomps', player), lambda state: state.can_reach('TR Chain Chomps Top', 'Region', player) and state.can_hit_crystal_through_barrier(player)) set_rule(world.get_entrance('TR Chain Chomps Top to Bottom Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('TR Chain Chomps Top', player), player)) @@ -691,14 +699,14 @@ def global_rules(world, player): set_rule(world.get_entrance('TR Pokey 2 Top to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('TR Crystaroller Top to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('TR Crystal Maze Start to Crystal', player), lambda state: state.can_hit_crystal(player)) - set_rule(world.get_entrance('TR Chain Chomps Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Chain Chomps Bottom', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('TR Pokey 2 Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('TR Pokey 2 Bottom', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('TR Crystaroller Bottom to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Bottom', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('TR Crystaroller Middle to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Chain Chomps Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Chain Chomps Bottom', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Pokey 2 Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('TR Pokey 2 Bottom', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Crystaroller Bottom to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Bottom', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Crystaroller Middle to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player))) # or state.has_beam_sword(player) set_rule(world.get_entrance('TR Crystaroller Middle to Bottom Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player)) - set_rule(world.get_entrance('TR Crystal Maze End to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) // These work by clipping the rang through the two stone blocks, which works sometimes. - set_rule(world.get_entrance('TR Crystal Maze Interior to End Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # Beam sword does NOT work - set_rule(world.get_entrance('TR Crystal Maze Interior to Start Bypass', player), lambda state: True) # Can always grab a pot from the interior and walk it to the start region and throw it there + set_rule(world.get_entrance('TR Crystal Maze End to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) // These work by clipping the rang through the two stone blocks, which works sometimes. + set_rule(world.get_entrance('TR Crystal Maze Interior to End Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # Beam sword does NOT work + set_rule(world.get_entrance('TR Crystal Maze Interior to Start Bypass', player), lambda state: True) # Can always grab a pot from the interior and walk it to the start region and throw it there set_rule(world.get_entrance('GT Hookshot Platform Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Hookshot South Platform', player), player)) set_rule(world.get_entrance('GT Hookshot Entry Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('GT Hookshot South Entry', player), player)) @@ -811,7 +819,7 @@ def bomb_rules(world, player): ('TR Tongue Pull WS', True), ('TR Twin Pokeys NW', False), ] - for killdoor,bombable in easy_kill_rooms: + for killdoor, bombable in easy_kill_rooms: if bombable: add_rule(world.get_entrance(killdoor, player), lambda state: (state.can_use_bombs(player) or state.can_kill_most_things(player))) else: @@ -828,47 +836,47 @@ def bomb_rules(world, player): if world.get_entrance('Mire Cross SW', player).door.trapped: add_rule(world.get_entrance('Mire Cross SW', player), lambda state: state.can_kill_most_things(player)) - enemy_kill_drops = [ # Location, bool-bombable + enemy_kill_drops = [ # Location, bool-bombable ('Hyrule Castle - Map Guard Key Drop', True), ('Hyrule Castle - Boomerang Guard Key Drop', True), ('Hyrule Castle - Key Rat Key Drop', True), -# ('Hyrule Castle - Big Key Drop', True), # Pots are available -# ('Eastern Palace - Dark Eyegore Key Drop', True), # Pots are available + # ('Hyrule Castle - Big Key Drop', True), # Pots are available + # ('Eastern Palace - Dark Eyegore Key Drop', True), # Pots are available ('Castle Tower - Dark Archer Key Drop', True), -# ('Castle Tower - Circle of Pots Key Drop', True), # Pots are available -# ('Skull Woods - Spike Corner Key Drop', True), # Pots are available + # ('Castle Tower - Circle of Pots Key Drop', True), # Pots are available + # ('Skull Woods - Spike Corner Key Drop', True), # Pots are available ('Ice Palace - Jelly Key Drop', True), ('Ice Palace - Conveyor Key Drop', True), ('Misery Mire - Conveyor Crystal Key Drop', True), ('Turtle Rock - Pokey 1 Key Drop', True), ('Turtle Rock - Pokey 2 Key Drop', True), -# ('Ganons Tower - Mini Helmasaur Key Drop', True) # Pots are available - ('Castle Tower - Room 03', True), # Two spring soliders - ('Ice Palace - Compass Chest', True) # Pengators + # ('Ganons Tower - Mini Helmasaur Key Drop', True) # Pots are available + ('Castle Tower - Room 03', True), # Two spring soliders + ('Ice Palace - Compass Chest', True) # Pengators ] - for location,bombable in enemy_kill_drops: + for location, bombable in enemy_kill_drops: if bombable: - add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.can_kill_most_things(player)) + add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.can_kill_most_things(player)) else: add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player)) - add_rule(world.get_location('Attic Cracked Floor', player), lambda state: state.can_use_bombs(player)) + add_rule(world.get_location('Attic Cracked Floor', player), lambda state: state.can_use_bombs(player)) bombable_floors = ['PoD Pit Room Bomb Hole', 'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole', 'GT Bob\'s Room Hole'] for entrance in bombable_floors: - add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) if world.doorShuffle[player] == 'vanilla': - add_rule(world.get_entrance('TR Lazy Eyes SE', player), lambda state: state.can_use_bombs(player)) # ToDo: Add always true for inverted, cross-entrance, and door-variants and so on. - add_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: state.can_use_bombs(player)) # Is this the same as above? + add_rule(world.get_entrance('TR Lazy Eyes SE', player), lambda state: state.can_use_bombs(player)) # ToDo: Add always true for inverted, cross-entrance, and door-variants and so on. + add_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: state.can_use_bombs(player)) # Is this the same as above? dungeon_bonkable = ['Sewers Rat Path WS', 'Sewers Rat Path WN', 'PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW', 'Thieves Ambush E', 'Thieves Rail Ledge W', 'TR Dash Room NW', 'TR Crystaroller SW', 'TR Dash Room ES', - 'GT Four Torches NW','GT Fairy Abyss SW' + 'GT Four Torches NW', 'GT Fairy Abyss SW' ] dungeon_bombable = ['PoD Map Balcony WS', 'PoD Arena Ledge ES', 'PoD Dark Maze E', 'PoD Big Chest Balcony W', - 'Swamp Pot Row WN','Swamp Map Ledge EN', 'Swamp Hammer Switch WN', 'Swamp Hub Dead Ledge EN', 'Swamp Waterway N', 'Swamp I S', + 'Swamp Pot Row WN', 'Swamp Map Ledge EN', 'Swamp Hammer Switch WN', 'Swamp Hub Dead Ledge EN', 'Swamp Waterway N', 'Swamp I S', 'Skull Pot Circle WN', 'Skull Pull Switch EN', 'Skull Big Key EN', 'Skull Lone Pot WN', 'Thieves Rail Ledge NW', 'Thieves Pot Alcove Bottom SW', 'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole', @@ -876,9 +884,9 @@ def bomb_rules(world, player): 'GT Warp Maze (Rails) WS', 'GT Bob\'s Room Hole', 'GT Randomizer Room ES', 'GT Bomb Conveyor SW', 'GT Crystal Circles NW', 'GT Cannonball Bridge SE', 'GT Refill NE' ] for entrance in dungeon_bonkable: - add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) for entrance in dungeon_bombable: - add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) else: doors_to_bomb_check = [x for x in world.doors if x.player == player and x.type in [DoorType.Normal, DoorType.Interior]] for door in doors_to_bomb_check: @@ -984,13 +992,13 @@ def ow_bunny_rules(world, player): add_bunny_rule(world.get_entrance('20 Rupee Cave', player), player) add_bunny_rule(world.get_entrance('50 Rupee Cave', player), player) - add_bunny_rule(world.get_entrance('Skull Woods First Section Hole (North)', player), player) # bunny cannot lift bush - add_bunny_rule(world.get_entrance('Skull Woods Second Section Hole', player), player) # bunny cannot lift bush - add_bunny_rule(world.get_entrance('Skull Woods Final Section', player), player) # bunny cannot use fire rod + add_bunny_rule(world.get_entrance('Skull Woods First Section Hole (North)', player), player) # bunny cannot lift bush + add_bunny_rule(world.get_entrance('Skull Woods Second Section Hole', player), player) # bunny cannot lift bush + add_bunny_rule(world.get_entrance('Skull Woods Final Section', player), player) # bunny cannot use fire rod add_bunny_rule(world.get_entrance('Hookshot Cave', player), player) - add_bunny_rule(world.get_entrance('Thieves Town', player), player) # bunny cannot pull + add_bunny_rule(world.get_entrance('Thieves Town', player), player) # bunny cannot pull add_bunny_rule(world.get_entrance('Turtle Rock', player), player) - add_bunny_rule(world.get_entrance('Palace of Darkness', player), player) # kiki needs pearl + add_bunny_rule(world.get_entrance('Palace of Darkness', player), player) # kiki needs pearl add_bunny_rule(world.get_entrance('Hammer Peg Cave', player), player) add_bunny_rule(world.get_entrance('Bonk Fairy (Dark)', player), player) add_bunny_rule(world.get_entrance('Misery Mire', player), player) @@ -1109,17 +1117,20 @@ def forbid_bomb_jump_requirements(world, player): set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False) set_rule(world.get_entrance('Ice Island To East Pier', player), lambda state: False) + # Light cones in standard depend on which world we actually are in, not which one the location would normally be # We add Lamp requirements only to those locations which lie in the dark world (or everything if open DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)', 'Turtle Rock Isolated Ledge Entrance', 'Thieves Town', 'Skull Woods Final Section', 'Ice Palace', 'Misery Mire', 'Palace of Darkness', 'Swamp Palace', 'Turtle Rock', 'Dark Death Mountain Ledge (West)'] + def check_is_dark_world(region): for entrance in region.entrances: if entrance.name in DW_Entrances: return True return False + def add_conditional_lamps(world, player): def add_conditional_lamp(spot, region, spottype='Location'): if spottype == 'Location': @@ -1221,33 +1232,33 @@ def swordless_rules(world, player): # todo: new traps std_kill_rooms = { - 'Hyrule Dungeon Armory Main': ['Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES'], # One green guard - 'Hyrule Dungeon Armory Boomerang': ['Hyrule Dungeon Armory Boomerang WS'], # One blue guard - 'Eastern Stalfos Spawn': ['Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW'], # Can use pots - 'Desert Compass Room': ['Desert Compass NE'], # Three popos - 'Desert Four Statues': ['Desert Four Statues NW', 'Desert Four Statues ES'], # Four popos + 'Hyrule Dungeon Armory Main': ['Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES'], # One green guard + 'Hyrule Dungeon Armory Boomerang': ['Hyrule Dungeon Armory Boomerang WS'], # One blue guard + 'Eastern Stalfos Spawn': ['Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW'], # Can use pots + 'Desert Compass Room': ['Desert Compass NE'], # Three popos + 'Desert Four Statues': ['Desert Four Statues NW', 'Desert Four Statues ES'], # Four popos 'Hera Beetles': ['Hera Beetles WS'], # Three blue beetles and only two pots, and bombs don't work. - 'Tower Gold Knights': ['Tower Gold Knights SW', 'Tower Gold Knights EN'], # Two ball and chain + 'Tower Gold Knights': ['Tower Gold Knights SW', 'Tower Gold Knights EN'], # Two ball and chain 'Tower Dark Archers': ['Tower Dark Archers WN'], # Not a kill room 'Tower Red Spears': ['Tower Red Spears WN'], # Two spear soldiers - 'Tower Red Guards': ['Tower Red Guards EN', 'Tower Red Guards SW'], # Two usain bolts - 'Tower Circle of Pots': ['Tower Circle of Pots NW'], # Two spear soldiers. Plenty of pots. + 'Tower Red Guards': ['Tower Red Guards EN', 'Tower Red Guards SW'], # Two usain bolts + 'Tower Circle of Pots': ['Tower Circle of Pots NW'], # Two spear soldiers. Plenty of pots. 'PoD Turtle Party': ['PoD Turtle Party ES', 'PoD Turtle Party NW'], # Lots of turtles. - 'Thieves Basement Block': ['Thieves Basement Block WN'], # One blue and one red zazak and one Stalfos. Two pots. Need weapon. - 'Ice Stalfos Hint': ['Ice Stalfos Hint SE'], # Need bombs for big stalfos knights - 'Ice Pengator Trap': ['Ice Pengator Trap NE'], # Five pengators. Bomb-doable? - 'Mire 2': ['Mire 2 NE'], # Wizzrobes. Bombs dont work. - 'Mire Cross': ['Mire Cross ES'], # 4 Sluggulas. Bombs don't work - 'TR Twin Pokeys': ['TR Twin Pokeys EN', 'TR Twin Pokeys SW'], # Two pokeys - 'GT Petting Zoo': ['GT Petting Zoo SE'], # Dont make anyone do this room with bombs. - 'GT DMs Room': ['GT DMs Room SW'], # Four red stalfos - 'GT Gauntlet 1': ['GT Gauntlet 1 WN'], # Stalfos/zazaks - 'GT Gauntlet 2': ['GT Gauntlet 2 EN', 'GT Gauntlet 2 SW'], # Red stalfos - 'GT Gauntlet 3': ['GT Gauntlet 3 NW', 'GT Gauntlet 3 SW'], # Blue zazaks - 'GT Gauntlet 4': ['GT Gauntlet 4 NW', 'GT Gauntlet 4 SW'], # Red zazaks - 'GT Gauntlet 5': ['GT Gauntlet 5 NW', 'GT Gauntlet 5 WS'], # Stalfos and zazak - 'GT Wizzrobes 1': ['GT Wizzrobes 1 SW'], # Wizzrobes. Bombs don't work - 'GT Wizzrobes 2': ['GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE'] # Wizzrobes. Bombs don't work + 'Thieves Basement Block': ['Thieves Basement Block WN'], # One blue and one red zazak and one Stalfos. Two pots. Need weapon. + 'Ice Stalfos Hint': ['Ice Stalfos Hint SE'], # Need bombs for big stalfos knights + 'Ice Pengator Trap': ['Ice Pengator Trap NE'], # Five pengators. Bomb-doable? + 'Mire 2': ['Mire 2 NE'], # Wizzrobes. Bombs dont work. + 'Mire Cross': ['Mire Cross ES'], # 4 Sluggulas. Bombs don't work + 'TR Twin Pokeys': ['TR Twin Pokeys EN', 'TR Twin Pokeys SW'], # Two pokeys + 'GT Petting Zoo': ['GT Petting Zoo SE'], # Dont make anyone do this room with bombs. + 'GT DMs Room': ['GT DMs Room SW'], # Four red stalfos + 'GT Gauntlet 1': ['GT Gauntlet 1 WN'], # Stalfos/zazaks + 'GT Gauntlet 2': ['GT Gauntlet 2 EN', 'GT Gauntlet 2 SW'], # Red stalfos + 'GT Gauntlet 3': ['GT Gauntlet 3 NW', 'GT Gauntlet 3 SW'], # Blue zazaks + 'GT Gauntlet 4': ['GT Gauntlet 4 NW', 'GT Gauntlet 4 SW'], # Red zazaks + 'GT Gauntlet 5': ['GT Gauntlet 5 NW', 'GT Gauntlet 5 WS'], # Stalfos and zazak + 'GT Wizzrobes 1': ['GT Wizzrobes 1 SW'], # Wizzrobes. Bombs don't work + 'GT Wizzrobes 2': ['GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE'] # Wizzrobes. Bombs don't work } # all trap rooms? std_kill_doors_if_trapped = { @@ -1262,6 +1273,7 @@ std_kill_doors_if_trapped = { # 'Ice Lobby S' # can melt rule is sufficient } + def add_connection(parent_name, target_name, entrance_name, world, player): parent = world.get_region(parent_name, player) target = world.get_region(target_name, player) @@ -1299,7 +1311,7 @@ def standard_rules(world, player): return loc.item and loc.item.name in ['Bomb Upgrade (+10)' if world.bombbag[player] else 'Bombs (10)'] def standard_escape_rule(state): - return state.can_kill_most_things(player) or bomb_escape_rule() + return state.can_kill_most_things(player) or bomb_escape_rule() add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule) @@ -1326,6 +1338,7 @@ def standard_rules(world, player): def check_rule_list(state, r_list): return True if len(r_list) <= 0 else r_list[0](state) and check_rule_list(state, r_list[1:]) + rule_list, debug_path = find_rules_for_zelda_delivery(world, player) set_rule(world.get_entrance('Hyrule Castle Throne Room Tapestry', player), lambda state: state.has('Zelda Herself', player) and check_rule_list(state, rule_list)) @@ -1502,7 +1515,7 @@ def set_big_bomb_rules(world, player): set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('East Dark World', 'Region', player) and state.can_reach('Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player)) - #crossing peg bridge starting from the southern dark world + # crossing peg bridge starting from the southern dark world def cross_peg_bridge(state): return state.has('Hammer', player) and state.has_Pearl(player) @@ -1524,28 +1537,28 @@ def set_big_bomb_rules(world, player): # G = Glove if bombshop_entrance.name in Normal_LW_entrances: - #1. basic routes - #2. Can reach Eastern dark world some other way, mirror, get bomb, return to mirror spot, walk to pyramid: Needs mirror + # 1. basic routes + # 2. Can reach Eastern dark world some other way, mirror, get bomb, return to mirror spot, walk to pyramid: Needs mirror # -> M or BR add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: basic_routes(state) or state.has_Mirror(player)) elif bombshop_entrance.name in LW_walkable_entrances: - #1. Mirror then basic routes + # 1. Mirror then basic routes # -> M and BR add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and basic_routes(state)) elif bombshop_entrance.name in Northern_DW_entrances: - #1. Mirror and basic routes - #2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl + # 1. Mirror and basic routes + # 2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl # -> (Mitts and CPB) or (M and BR) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.has_Mirror(player) and basic_routes(state))) elif bombshop_entrance.name == 'Bumper Cave (Bottom)': - #1. Mirror and Lift rock and basic_routes - #2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case) - #3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl + # 1. Mirror and Lift rock and basic_routes + # 2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case) + # 3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl # -> (Mitts and CPB) or (((G or Flute) and M) and BR)) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (((state.can_lift_rocks(player) or state.can_flute(player)) and state.has_Mirror(player)) and basic_routes(state))) elif bombshop_entrance.name in Southern_DW_entrances: - #1. Mirror and enter via gate: Need mirror and Aga1 - #2. cross peg bridge: Need hammer and moon pearl + # 1. Mirror and enter via gate: Need mirror and Aga1 + # 2. cross peg bridge: Need hammer and moon pearl # -> CPB or (M and A) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: cross_peg_bridge(state) or (state.has_Mirror(player) and state.has('Beat Agahnim 1', player))) elif bombshop_entrance.name in Isolated_DW_entrances: @@ -1809,7 +1822,6 @@ def set_inverted_big_bomb_rules(world, player): def set_bunny_rules(world, player, inverted): - # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave (top)', 'Bumper Cave (bottom)', 'Two Brothers House', @@ -1848,13 +1860,14 @@ def set_bunny_rules(world, player, inverted): return region.is_light_world else: return region.is_dark_world + def is_link(region): if inverted: return region.is_dark_world else: return region.is_light_world - def get_rule_to_add(region, location = None, connecting_entrance = None): + def get_rule_to_add(region, location=None, connecting_entrance=None): # In OWG, a location can potentially be superbunny-mirror accessible or # bunny revival accessible. if world.logic[player] == 'owglitches': @@ -1877,16 +1890,15 @@ def set_bunny_rules(world, player, inverted): # for each such entrance a new option is added that consist of: # a) being able to reach it, and # b) being able to access all entrances from there to `region` - seen = {region} - queue = deque([(region, [])]) + queue = deque([(region, [], {region})]) while queue: - (current, path) = queue.popleft() + (current, path, seen) = queue.popleft() for entrance in current.entrances: new_region = entrance.parent_region if new_region.type in (RegionType.Cave, RegionType.Dungeon) and new_region in seen: continue new_path = path + [entrance.access_rule] - seen.add(new_region) + new_seen = seen.union({new_region}) if not is_link(new_region): if world.logic[player] == 'owglitches': if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon: @@ -1923,7 +1935,7 @@ def set_bunny_rules(world, player, inverted): else: continue if is_bunny(new_region): - queue.append((new_region, new_path)) + queue.append((new_region, new_path, new_seen)) else: # we have reached pure light world, so we have a new possible option possible_options.append(path_to_access_rule(new_path, entrance)) @@ -1975,7 +1987,6 @@ drop_dungeon_entrances = { "Skull Back Drop" } - bunny_revivable_entrances = { "Sewers Pull Switch", "TR Dash Room", "Swamp Boss", "Hera Boss", "Tower Agahnim 1", "Ice Lobby", "Sewers Rat Path", "PoD Falling Bridge", @@ -2035,14 +2046,14 @@ bunny_impassible_doors = { 'PoD Arena Landing Bonk Path', 'PoD Sexy Statue NW', 'PoD Map Balcony Drop Down', 'PoD Mimics 1 NW', 'PoD Falling Bridge Path N', 'PoD Falling Bridge Path S', 'PoD Mimics 2 NW', 'PoD Bow Statue Down Ladder', 'PoD Dark Pegs Landing to Right', - 'PoD Dark Pegs Left to Middle Barrier - Blue', 'PoD Dark Pegs Left to Ranged Crystal', + 'PoD Dark Pegs Left to Middle Barrier - Blue', 'PoD Dark Pegs Left to Ranged Crystal', 'PoD Turtle Party ES', 'PoD Turtle Party NW', 'PoD Callback Warp', 'Swamp Lobby Moat', 'Swamp Entrance Moat', 'Swamp Trench 1 Approach Swim Depart', 'Swamp Trench 1 Approach Key', 'Swamp Trench 1 Key Approach', 'Swamp Trench 1 Key Ledge Depart', 'Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Departure Key', 'Swamp Hub Hook Path', 'Swamp Shortcut Blue Barrier', 'Swamp Trench 2 Pots Blue Barrier', 'Swamp Trench 2 Pots Wet', 'Swamp Trench 2 Departure Wet', 'Swamp West Ledge Hook Path', 'Swamp Barrier Ledge Hook Path', 'Swamp Attic Left Pit', 'Swamp Attic Right Pit', 'Swamp Push Statue NW', 'Swamp Push Statue NE', - 'Swamp Drain Right Switch', 'Swamp Waterway NE', 'Swamp Waterway N', 'Swamp Waterway NW', + 'Swamp Drain Right Switch', 'Swamp Waterway NE', 'Swamp Waterway N', 'Swamp Waterway NW', 'Skull Pot Circle WN', 'Skull Pot Circle Star Path', 'Skull Pull Switch S', 'Skull Big Chest N', 'Skull Big Chest Hookpath', 'Skull 2 East Lobby NW', 'Skull Back Drop Star Path', 'Skull 2 West Lobby NW', 'Skull 3 Lobby EN', 'Skull Star Pits SW', 'Skull Star Pits ES', 'Skull Torch Room WN', 'Skull Vines NW', @@ -2077,7 +2088,7 @@ bunny_impassible_doors = { 'GT Double Switch Exit to Blue Barrier', 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS', 'GT Ice Armos NE', 'GT Ice Armos WS', 'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS', 'GT Mimics 2 NE', 'GT Hidden Spikes EN', 'GT Cannonball Bridge SE', 'GT Gauntlet 1 WN', 'GT Gauntlet 2 EN', - 'GT Gauntlet 2 SW', 'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW', + 'GT Gauntlet 2 SW', 'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW', 'GT Gauntlet 5 NW', 'GT Gauntlet 5 WS', 'GT Lanmolas 2 ES', 'GT Lanmolas 2 NW', 'GT Wizzrobes 1 SW', 'GT Wizzrobes 2 SE', 'GT Wizzrobes 2 NE', 'GT Torch Cross ES', 'GT Falling Torches NE', 'GT Moldorm Gap', 'GT Validation Block Path' @@ -2227,7 +2238,7 @@ def create_key_rule(small_key_name, player, keys): def create_key_rule_allow_small(small_key_name, player, keys, location): loc = location.name - return lambda state: state.has_sm_key(small_key_name, player, keys) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys-1)) + return lambda state: state.has_sm_key(small_key_name, player, keys) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys - 1)) def create_key_rule_bk_exception(small_key_name, big_key_name, player, keys, bk_keys, bk_locs): @@ -2238,7 +2249,7 @@ def create_key_rule_bk_exception(small_key_name, big_key_name, player, keys, bk_ def create_key_rule_bk_exception_or_allow(small_key_name, big_key_name, player, keys, location, bk_keys, bk_locs): loc = location.name chest_names = [x.name for x in bk_locs] - return lambda state: (state.has_sm_key(small_key_name, player, keys) and not item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names)))) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys-1)) or (item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names))) and state.has_sm_key(small_key_name, player, bk_keys)) + return lambda state: (state.has_sm_key(small_key_name, player, keys) and not item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names)))) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys - 1)) or (item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names))) and state.has_sm_key(small_key_name, player, bk_keys)) def create_advanced_key_rule(key_logic, player, rule): From 7030ff01be58dc914c2e8f4928d9dce74a5cd806 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 15 Nov 2023 13:25:13 -0700 Subject: [PATCH 09/17] fix(ER): Links house on Dm won't allow a cave to be used twice anymore --- RELEASENOTES.md | 4 +++- source/overworld/EntranceShuffle2.py | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5abff4a8..a2486806 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -109,7 +109,9 @@ These are now independent of retro mode and have three options: None, Random, an # Bug Fixes and Notes -* * 1.2.0.22u +* 1.2.0.22u + * ? + * ER: Minor fix for Link's House on DM in Insanity (escape cave should not be re-used) * Fixed logic issues: * Self-locking key not allowed in Sanctuary in standard (typo fixed) * More advanced bunny-walking logic in dungeons (multiple paths considred) diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index da71c661..9f7ee90a 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -497,10 +497,14 @@ def do_links_house(entrances, exits, avail, cross_world): entrances.remove(chosen_dm_escape) entrances.remove(chosen_landing) else: - connect_entrance(chosen_dm_escape, chosen_cave.pop(0), avail) + chosen_cave_first = chosen_cave.pop(0) + connect_entrance(chosen_dm_escape, chosen_cave_first, avail) connect_exit(chosen_cave.pop(), chosen_landing, avail) entrances.remove(chosen_dm_escape) + avail.decoupled_exits.remove(chosen_cave_first) avail.decoupled_entrances.remove(chosen_landing) + # chosen cave has already been removed from exits + exits.add(chosen_cave_first) # this needs to be added back in if len(chosen_cave): exits.update([x for x in chosen_cave]) exits.update([x for item in multi_exit_caves for x in item]) @@ -1094,7 +1098,7 @@ def connect_entrance(entrancename, exit_name, avail): def connect_exit(exit_name, entrancename, avail): - world, player = avail.world, avail. player + world, player = avail.world, avail.player entrance = world.get_entrance(entrancename, player) exit = world.get_entrance(exit_name, player) From a50170c54f0ad5694888f4635ef456d015ee3e32 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 15 Nov 2023 14:33:11 -0700 Subject: [PATCH 10/17] fix: Flute doesn't work in rain state (even if pre-activated) except for glitched modes fix(msu): GTBK Music in DR --- RELEASENOTES.md | 5 +++-- Rom.py | 2 +- data/base2current.bps | Bin 94199 -> 90613 bytes 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a2486806..0c754ac6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -110,11 +110,12 @@ These are now independent of retro mode and have three options: None, Random, an # Bug Fixes and Notes * 1.2.0.22u - * ? + * Flute can't be activated in rain state (except glitched modes) (Thanks codemann!) * ER: Minor fix for Link's House on DM in Insanity (escape cave should not be re-used) - * Fixed logic issues: + * Logic issues: * Self-locking key not allowed in Sanctuary in standard (typo fixed) * More advanced bunny-walking logic in dungeons (multiple paths considred) + * MSU: GTBK song fix for DR (Thanks codemann!) * 1.2.0.21u * Fix that should force items needed for leaving Zelda's cell to before the throne room, so S&Q isn't mandatory * Small fix for Tavern Shuffle (thanks Catobat) diff --git a/Rom.py b/Rom.py index 9351970c..637cac4b 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '9b6e57f6e9d92934ce14276afd715849' +RANDOMIZERBASEHASH = '45778dbb52eca64611fbdb43a3a11ec8' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 643e68f74b79b1aa1e7712e5e48e71831c6eedc5..f5e4d204be7572897f98e8a1cfc4ad9c9c9f9dd6 100644 GIT binary patch delta 4867 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 delta 8559 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 Date: Wed, 15 Nov 2023 16:47:17 -0700 Subject: [PATCH 11/17] build: forgot to include lower case --- Rom.py | 2 +- data/base2current.bps | Bin 90613 -> 94262 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 637cac4b..11bf35ce 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '45778dbb52eca64611fbdb43a3a11ec8' +RANDOMIZERBASEHASH = '7ba119d84e56617f8da16669f8b519c1' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index f5e4d204be7572897f98e8a1cfc4ad9c9c9f9dd6..14084390990019b05bc8462cea1d18ba84db3938 100644 GIT binary patch delta 5268 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 A`v3p{ delta 1593 zcmW+!3vg3K6y29LP^86vu{70wX!!`(XbYrRCDaP)@JWOU%CB^aqE=c&pkUj#oA^jm zj7#%qwl#!Jg*MPMeGO^y5}Ohz0|lwVh`;f}#~JG|f;giN!wgQ`FgtVa-E+@5_wKwG zxS{;_ta4xz7yo46x2t{CocmG5hC|}ZDRU;*nOeSk^uWim<}H&Cro6-{N`4Y+)8-{; zi$~*++t;T0y3!UYmK^)dS#UsHwce`1mi$w{IIDz*Ne3UM8@}Z`t!tpca6rg5W)p0bZ2vSgak>w!Jo_Wu7<5%3T6pqug@;TVkTf2lyv(NKr?k=) z8*bC`)D9_2chxM`TJ8LlF$(mTXnfFd4>+pLyVaMREI~G&H`BfS-Hl*>L+n^S0F|#C+TM z?Nkq4U%K>0GCx4oMiT0BRNHGD)g#aGzLj3QWY5M70*W)#I!8@8Tw|Degg+-S3FE1F9r*%9LXFbb)Bz zy-1S8GAERZA{%#-yyyhyuQWnYmrqsMYK@&GhTQY>r6OfNPOn}EoGOo zg*&F~X7RZ41dDx24~qjzuaa)GidVlY%E0ei#Rb~2uDIpt-6QJHwDCutD8A{N`u&C3 zX=vNxKX&KdS+?k4R^BJ5!Zv*ok~hV1zLZqk#7W&p;;UTf^yihSh^)@PCl_RJA>|~c z_6wvSiuG1`Jd2}>M^?@K33aBy$LICR_;F5BObX#%L*v)$$dp!;-li0oN$g_?FT~`b`7)j zhnUze?m(SGjL`=M$p?luFI%HuTw!o!8<0%)+wEj05?AS=hsi*1%>N|l6Dy3k&@k+0 z=6#?)28P+*r|i!|95@$b8-!z6fKkJ-abgC<3L_dKqptbrtOA)&gI;ofEmt^09(@+E zkt2+=pEMbds)ab13|)H!8(=n&9e{GX(C%_-_Jt>f!spC{C=}R4dCI3XS5Vq}}Jnqep-ch~# wtNI~I{;A_~^Wv7cJAYNX$1}F=J6gKRP_%D Date: Sun, 19 Nov 2023 14:07:47 -0600 Subject: [PATCH 12/17] Added missing saved user settings in Adjust tab --- source/gui/bottom.py | 4 +++- source/gui/loadcliargs.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source/gui/bottom.py b/source/gui/bottom.py index 4c21621e..839f2dc9 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -259,7 +259,9 @@ def create_guiargs(parent): "heartbeep": "heartbeep", "menuspeed": "fastmenu", "owpalettes": "ow_palettes", - "uwpalettes": "uw_palettes" + "uwpalettes": "uw_palettes", + "reduce_flashing": "reduce_flashing", + "shuffle_sfx": "shuffle_sfx" } for adjustarg in adjustargs: internal = adjustargs[adjustarg] diff --git a/source/gui/loadcliargs.py b/source/gui/loadcliargs.py index aec14a72..d99f6c9a 100644 --- a/source/gui/loadcliargs.py +++ b/source/gui/loadcliargs.py @@ -206,7 +206,9 @@ def loadadjustargs(gui, settings): "heartbeep": "adjust.heartbeep", "menuspeed": "adjust.menuspeed", "owpalettes": "adjust.owpalettes", - "uwpalettes": "adjust.uwpalettes" + "uwpalettes": "adjust.uwpalettes", + "reduce_flashing": "adjust.reduce_flashing", + "shuffle_sfx": "adjust.shuffle_sfx" } } } From b65c55e1b550aea854738533d67303a74ca1ea1c Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 24 Nov 2023 16:38:21 -0600 Subject: [PATCH 13/17] Fix some issues with Smith return --- BaseClasses.py | 2 +- OverworldShuffle.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 08ccdd93..94287939 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1627,7 +1627,7 @@ class Entrance(object): explored_regions[region] = path for exit in region.exits: if exit.connected_region and (not ignore_ledges or exit.spot_type != 'Ledge') \ - and exit.connected_region.name not in ['Dig Game Area'] \ + and exit.name not in ['Dig Game To Ledge Drop'] \ and exit.access_rule(state): if exit.connected_region == destination: found = True diff --git a/OverworldShuffle.py b/OverworldShuffle.py index cd41b663..7c581fac 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1378,7 +1378,7 @@ def can_reach_smith(world, player): elif exit.connected_region.name == 'Blacksmiths Hut' and exit.access_rule(blank_state): found = True return - elif exit.connected_region.name not in explored_regions: + elif exit.connected_region.name not in explored_regions and exit.name != "Dig Game To Ledge Drop": if (region.type == RegionType.Dungeon and exit.connected_region.name.endswith(' Portal')) \ or (exit.connected_region.type in [RegionType.LightWorld, RegionType.DarkWorld] \ and exit.access_rule(blank_state)): From 98dc38e3ac12af7677ca55dc25d3c48b8f87ebed Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 24 Nov 2023 16:43:42 -0600 Subject: [PATCH 14/17] Some minor OWR corrections --- OverworldShuffle.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 7c581fac..869f43ed 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1173,6 +1173,7 @@ def define_tile_groups(world, do_grouped, player): (lw_regions if id < 0x40 or id >= 0x80 else dw_regions).extend(OWTileRegions.inverse[id]) tile_groups.append((group, lw_regions, dw_regions)) + random.shuffle(tile_groups) return tile_groups, flipped_groups, nonflipped_groups, undefined_chance def remove_reserved(world, groupedlist, connected_edges, player): @@ -1623,7 +1624,7 @@ def validate_layout(world, player): or (entrance.name == 'Big Bomb Shop' and (world.mode[player] != 'inverted' or not world.shufflelinks[player] or world.shuffle[player] in ['dungeonssimple', 'dungeonsfull', 'lite', 'lean'])) \ or (entrance.name == 'Ganons Tower' and (world.mode[player] != 'inverted' and not world.shuffle_ganon[player])) \ or (entrance.name in ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)'] and world.shuffle[player] not in ['insanity']) \ - or entrance.name == 'Tavern North': + or (entrance.name == 'Tavern North' and not world.shuffletavern[player]): continue # these are fixed entrances and cannot be used for gaining access to region if entrance.name not in drop_entrances \ and ((entrance.name in dungeon_entrances and world.shuffle[player] not in ['dungeonssimple', 'simple', 'restricted']) \ From d9e515429a24181525402bfbd78d29cc9b84ab30 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 2 Dec 2023 05:29:11 -0600 Subject: [PATCH 15/17] Undo bunny walking change due to infinite loop --- Rules.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Rules.py b/Rules.py index 77677b9e..dc7463ac 100644 --- a/Rules.py +++ b/Rules.py @@ -1707,15 +1707,16 @@ def set_bunny_rules(world, player, inverted): # for each such entrance a new option is added that consist of: # a) being able to reach it, and # b) being able to access all entrances from there to `region` - queue = deque([(region, [], {region})]) + seen = {region} + queue = deque([(region, [])]) while queue: - (current, path, seen) = queue.popleft() + (current, path) = queue.popleft() for entrance in current.entrances: new_region = entrance.parent_region if new_region.type in (RegionType.Cave, RegionType.Dungeon) and new_region in seen: continue new_path = path + [entrance.access_rule] - new_seen = seen.union({new_region}) + seen.add(new_region) if not is_link(new_region): if world.logic[player] == 'owglitches': if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon: @@ -1752,7 +1753,7 @@ def set_bunny_rules(world, player, inverted): else: continue if is_bunny(new_region): - queue.append((new_region, new_path, new_seen)) + queue.append((new_region, new_path)) else: # we have reached pure light world, so we have a new possible option possible_options.append(path_to_access_rule(new_path, entrance)) From a1b570da621fa79cfadc8e165762ec7d6b5d1c50 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 2 Dec 2023 05:46:33 -0600 Subject: [PATCH 16/17] Added song instrument shuffle --- Adjuster.py | 3 +- AdjusterMain.py | 11 +- CLI.py | 3 +- Main.py | 5 +- Rom.py | 9 +- mystery_example.yml | 3 + mystery_testsuite.yml | 3 + resources/app/cli/args.json | 4 + resources/app/cli/lang/en.json | 1 + .../app/gui/adjust/overview/widgets.json | 3 +- resources/app/gui/lang/en.json | 2 + .../gui/randomize/gameoptions/widgets.json | 3 +- source/classes/CustomSettings.py | 1 + source/classes/SFX.py | 755 +++++++++++++++++- source/classes/constants.py | 1 + source/gui/adjust/overview.py | 2 + source/gui/bottom.py | 3 +- source/gui/loadcliargs.py | 3 +- source/tools/MysteryUtils.py | 1 + 19 files changed, 804 insertions(+), 12 deletions(-) diff --git a/Adjuster.py b/Adjuster.py index 9e003b3f..45cf37d3 100755 --- a/Adjuster.py +++ b/Adjuster.py @@ -36,7 +36,8 @@ def main(): parser.add_argument('--ow_palettes', default='default', choices=['default', 'random', 'blackout']) parser.add_argument('--uw_palettes', default='default', choices=['default', 'random', 'blackout']) parser.add_argument('--reduce_flashing', help='Reduce some in-game flashing.', action='store_true') - parser.add_argument('--shuffle_sfx', help='Shuffles sound sfx', action='store_true') + parser.add_argument('--shuffle_sfx', help='Shuffles sfx instruments', action='store_true') + parser.add_argument('--shuffle_songinstruments', help='Shuffles sound sfx', action='store_true') parser.add_argument('--msu_resume', help='Enable MSU resume', action='store_true') parser.add_argument('--sprite', help='''\ Path to a sprite sheet to use for Link. Needs to be in diff --git a/AdjusterMain.py b/AdjusterMain.py index c6f19680..a3a08924 100644 --- a/AdjusterMain.py +++ b/AdjusterMain.py @@ -10,6 +10,7 @@ except ImportError: from Utils import output_path from Rom import LocalRom, apply_rom_settings +from source.classes.SFX import output_song_data from source.tools.BPS import bps_read_vlv @@ -33,11 +34,14 @@ def adjust(args): apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, - args.msu_resume) + args.shuffle_songinstruments, args.msu_resume) output_path.cached_path = args.outputpath rom.write_to_file(output_path('%s.sfc' % outfilebase)) + if args.shuffle_songinstruments: + output_song_data(rom, output_path('OR_SPCInstruments.txt'), outfilebase) + logger.info('Done. Enjoy.') logger.debug('Total Time: %s', time.process_time() - start) @@ -68,11 +72,14 @@ def patch(args): apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, - args.msu_resume) + args.shuffle_songinstruments, args.msu_resume) output_path.cached_path = args.outputpath rom.write_to_file(output_path('%s.sfc' % outfile_base)) + if args.shuffle_songinstruments: + output_song_data(rom, output_path('OR_SPCInstruments.txt'), outfile_base) + logger.info('Done. Enjoy.') logger.debug('Total Time: %s', time.process_time() - start) diff --git a/CLI.py b/CLI.py index 72fc7a48..5087eabf 100644 --- a/CLI.py +++ b/CLI.py @@ -140,7 +140,7 @@ def parse_cli(argv, no_defaults=False): 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle', - 'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', + 'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode', 'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) @@ -258,6 +258,7 @@ def parse_settings(): "uw_palettes": "default", "reduce_flashing": False, "shuffle_sfx": False, + "shuffle_songinstruments": False, "msu_resume": False, "collection_rate": False, diff --git a/Main.py b/Main.py index a8fede2f..0fae0394 100644 --- a/Main.py +++ b/Main.py @@ -35,6 +35,7 @@ from source.item.FillUtil import create_item_pool_config, massage_item_pool, dis from source.overworld.EntranceShuffle2 import link_entrances_new from source.tools.BPS import create_bps_from_data from source.classes.CustomSettings import CustomSettings +from source.classes.SFX import output_song_data version_number = '1.2.0.22' version_branch = '-u' @@ -393,7 +394,7 @@ def main(args, seed=None, fish=None): apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player], args.fastmenu[player], args.disablemusic[player], args.sprite[player], args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player], - args.shuffle_sfx[player], args.msu_resume[player]) + args.shuffle_sfx[player], args.shuffle_songinstruments[player], args.msu_resume[player]) if args.jsonout: jsonout[f'patch_t{team}_p{player}'] = rom.patches @@ -404,6 +405,8 @@ def main(args, seed=None, fish=None): if world.players > 1 or world.teams > 1: outfilepname += f"_{world.player_names[player][team].replace(' ', '_')}" if world.player_names[player][team] != 'Player %d' % player else '' outfilesuffix = f'_{Settings.make_code(world, player)}' if not args.outputname else '' + if args.shuffle_songinstruments: + output_song_data(rom, output_path('OR_SPCInstruments.txt'), outfilebase) if args.bps: patchfile = output_path(f'{outfilebase}{outfilepname}{outfilesuffix}.bps') patch = create_bps_from_data(LocalRom(args.rom, patch=False).buffer, rom.buffer) diff --git a/Rom.py b/Rom.py index 3a82aa7c..6095ace0 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from EntranceShuffle import door_addresses, exit_ids, ow_prize_table from OverworldShuffle import default_flute_connections, flute_data from InitialSram import InitialSram -from source.classes.SFX import randomize_sfx +from source.classes.SFX import randomize_sfx, randomize_songinstruments from source.item.FillUtil import valid_pot_items from source.dungeon.RoomList import Room0127 @@ -109,6 +109,9 @@ class LocalRom(object): self.patch_base_rom() self.orig_buffer = self.buffer.copy() + def read_byte(self, address): + return self.buffer[address] + def write_byte(self, address, value): self.buffer[address] = value @@ -1826,7 +1829,7 @@ def hud_format_text(text): def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, - ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx, msu_resume): + ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx, shuffle_songinstruments, msu_resume): if not os.path.exists("data/sprites/official/001.link.1.zspr") and rom.orig_buffer: dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380], @@ -1932,6 +1935,8 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr if shuffle_sfx: randomize_sfx(rom) + if shuffle_songinstruments: + randomize_songinstruments(rom) if isinstance(rom, LocalRom): rom.write_crc() diff --git a/mystery_example.yml b/mystery_example.yml index dbb455d7..4cf785b0 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -269,3 +269,6 @@ shuffle_sfx: on: 1 off: 1 + shuffle_songinstruments: + on: 1 + off: 1 diff --git a/mystery_testsuite.yml b/mystery_testsuite.yml index d2355f4f..733adb6e 100644 --- a/mystery_testsuite.yml +++ b/mystery_testsuite.yml @@ -199,3 +199,6 @@ rom: shuffle_sfx: on: 1 off: 1 + shuffle_songinstruments: + on: 1 + off: 1 diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 52edf0cd..8c21e15a 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -347,6 +347,10 @@ "action": "store_true", "type": "bool" }, + "shuffle_songinstruments": { + "action": "store_true", + "type": "bool" + }, "msu_resume": { "action": "store_true", "type": "bool" diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 6d41b23d..7d028961 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -425,6 +425,7 @@ ], "reduce_flashing": [ "Reduce some in-game flashing (default: %(default)s)" ], "shuffle_sfx": [ "Shuffle sounds effects (default: %(default)s)" ], + "shuffle_songinstruments": [ "Shuffle song instruments (default: %(default)s)" ], "msu_resume": [ "Enable MSU Resume (default: %(default)s)" ], "create_rom": [ "Create an output rom file. (default: %(default)s)" ], "gui": [ "Launch the GUI. (default: %(default)s)" ], diff --git a/resources/app/gui/adjust/overview/widgets.json b/resources/app/gui/adjust/overview/widgets.json index a24bf7b4..8489bcda 100644 --- a/resources/app/gui/adjust/overview/widgets.json +++ b/resources/app/gui/adjust/overview/widgets.json @@ -4,7 +4,8 @@ "msu_resume": { "type": "checkbox" }, "quickswap": { "type": "checkbox" }, "reduce_flashing": {"type": "checkbox" }, - "shuffle_sfx": {"type": "checkbox" } + "shuffle_sfx": {"type": "checkbox" }, + "shuffle_songinstruments": {"type": "checkbox" } }, "leftAdjustFrame": { "heartcolor": { diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 8a6a0212..36ffe2fb 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -4,6 +4,7 @@ "adjust.quickswap": "L/R Quickswapping", "adjust.reduce_flashing": "Reduce Flashing", "adjust.shuffle_sfx": "Shuffle Sound Effects", + "adjust.shuffle_songinstruments": "Shuffle Song Instruments", "adjust.msu_resume": "MSU Resume", "adjust.heartcolor": "Heart Color", @@ -190,6 +191,7 @@ "randomizer.gameoptions.quickswap": "L/R Quickswapping", "randomizer.gameoptions.reduce_flashing": "Reduce Flashing", "randomizer.gameoptions.shuffle_sfx": "Shuffle Sound Effects", + "randomizer.gameoptions.shuffle_songinstruments": "Shuffle Song Instruments", "randomizer.gameoptions.msu_resume": "MSU Resume", "randomizer.gameoptions.heartcolor": "Heart Color", diff --git a/resources/app/gui/randomize/gameoptions/widgets.json b/resources/app/gui/randomize/gameoptions/widgets.json index 5d8faeba..d6f4e76c 100644 --- a/resources/app/gui/randomize/gameoptions/widgets.json +++ b/resources/app/gui/randomize/gameoptions/widgets.json @@ -4,7 +4,8 @@ "msu_resume": { "type": "checkbox" }, "quickswap": { "type": "checkbox" }, "reduce_flashing": { "type": "checkbox" }, - "shuffle_sfx": { "type": "checkbox" } + "shuffle_sfx": { "type": "checkbox" }, + "shuffle_songinstruments": { "type": "checkbox" } }, "leftRomOptionsFrame": { "heartcolor": { diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 5ec40409..a3402318 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -183,6 +183,7 @@ class CustomSettings(object): args.ow_palettes[p] = get_setting(settings['ow_palettes'], args.ow_palettes[p]) args.uw_palettes[p] = get_setting(settings['uw_palettes'], args.uw_palettes[p]) args.shuffle_sfx[p] = get_setting(settings['shuffle_sfx'], args.shuffle_sfx[p]) + args.shuffle_songinstruments[p] = get_setting(settings['shuffle_songinstruments'], args.shuffle_songinstruments[p]) args.msu_resume[p] = get_setting(settings['msu_resume'], args.msu_resume[p]) def get_item_pool(self): diff --git a/source/classes/SFX.py b/source/classes/SFX.py index 750b284b..e9f41d5d 100644 --- a/source/classes/SFX.py +++ b/source/classes/SFX.py @@ -1,9 +1,9 @@ +from aenum import IntEnum import random from Utils import int16_as_bytes, snes_to_pc class SFX(object): - def __init__(self, name, sfx_set, orig_id, addr, chain, accomp=False): self.name = name self.sfx_set = sfx_set @@ -16,6 +16,68 @@ class SFX(object): self.target_id = None self.target_chain = None +class MusicType(IntEnum): + NONE = 0x00, + Ambient = 0x01, + Melody = 0x02, + Rhythm = 0x04, + Beat = 0x08 + +class Instrument(object): + def __init__(self, name, id, srcn, adsr, gain, mult): + self.name = name + self.id = id + self.srcn = srcn + self.adsr = adsr + self.gain = gain + self.mult = mult + + self.target_id = None + +class SFXInstrument(Instrument): + pass + +class SPCInstrument(Instrument): + def __init__(self, name, srcn, adsr, gain, mult, min=9999, max=0): + Instrument.__init__(self, name, srcn, srcn, adsr, gain, mult) + + self.type = MusicType.NONE + self.primary_type = MusicType.NONE + self.replacements = [] + + def add_type(self, type, force_primary): + if force_primary or self.type == MusicType.NONE: + self.primary_type |= type + self.type |= type + + def amb(self, force_primary=False): + self.add_type(MusicType.Ambient, force_primary) + return self + + def mel(self, force_primary=False): + self.add_type(MusicType.Melody, force_primary) + return self + + def bass(self, force_primary=False): + self.add_type(MusicType.Rhythm, force_primary) + return self + + def beat(self, force_primary=False): + self.add_type(MusicType.Beat, force_primary) + return self + +class InstrumentChange(object): + def __init__(self, song_id, segment_id, tracks, orig_instrument, type=MusicType.NONE, ban=[]): + self.song_id = song_id + self.segment_id = segment_id + self.tracks = tracks + self.orig_instrument = orig_instrument + + self.type = type + self.banned_list = ban + + self.target_instrument = None + def init_sfx_data(): sfx_pool = [SFX('Slash1', 0x02, 0x01, 0x2614, []), SFX('Slash2', 0x02, 0x02, 0x2625, []), @@ -178,3 +240,694 @@ def randomize_sfx(rom): last = chained rom.write_byte(ac_base + last - 1, 0) + +def output_song_data(rom, filepath, outfilebase): + with open(filepath, 'w') as outfile: + last_song = 0 + last_segment = -1 + outfile.write(f'{outfilebase}\n') + for change in spc_instrument_changes: + if last_song != change.song_id: + last_song = change.song_id + last_segment = change.segment_id + outfile.write(f'\nSong{change.song_id:02X}.{change.segment_id:02X}.') + elif last_segment != change.segment_id: + last_segment = change.segment_id + outfile.write(f'\n {change.segment_id:02X}.') + else: + outfile.write(f'\n ') + tracks = 8 + for track_id in change.tracks.keys(): + outfile.write(f'{track_id:01X}') + tracks -= 1 + if tracks > 0: + outfile.write(' ' * tracks) + outfile.write(f' = {rom.read_byte(snes_to_pc(next(iter(change.tracks.values()))[0])):02X}') + + +def randomize_songinstruments(rom): + # categorize instruments in pools + ambients, melodies, rhythms, beats = [], [], [], [] + inst_lists = { + MusicType.Ambient: ambients, + MusicType.Melody: melodies, + MusicType.Rhythm: rhythms, + MusicType.Beat: beats + } + for instrument in spc_instruments.values(): + for ins, lst in inst_lists.items(): + if instrument.type & ins > 0: + lst.append(instrument) + for instrument in spc_instruments.values(): + for ins, lst in inst_lists.items(): + if instrument.primary_type & ins > 0: + instrument.replacements += [i for i in lst if i not in instrument.replacements] + + # randomize each instrument change + for change in spc_instrument_changes: + if type(change.type) is list: + candidates = [spc_instruments[i] for i in change.type] + elif change.type != MusicType.NONE: + candidates = [] + for ins, lst in inst_lists.items(): + if change.type & ins > 0: + candidates += [i for i in lst if i not in candidates] + else: + candidates = spc_instruments[change.orig_instrument].replacements + candidates = [i for i in candidates if i.id not in change.banned_list] + change.target_instrument = random.choice(candidates).id + + for change in spc_instrument_changes: + for track_addresses in change.tracks.values(): + for addr in track_addresses: + rom.write_byte(snes_to_pc(addr), change.target_instrument) + + +sfx_instruments = { # table @ $1A9C04 + 0x00: SFXInstrument("Fwoosh", 0x00, 0x00, [0xF6, 0x6A], 0xB8, 0x03), + 0x01: SFXInstrument("Swish", 0x01, 0x01, [0x8E, 0xE0], 0xB8, 0x02), + 0x02: SFXInstrument("Bomp", 0x02, 0x14, [0xFE, 0x6A], 0xB8, 0x02), + 0x03: SFXInstrument("Ting", 0x03, 0x03, [0xFE, 0xF8], 0xB8, 0x0D), + 0x04: SFXInstrument("Rrrrr", 0x04, 0x04, [0xFE, 0x6A], 0x7F, 0x03), + 0x05: SFXInstrument("Clunk", 0x05, 0x02, [0xFE, 0x6A], 0x7F, 0x03), + 0x06: SFXInstrument("Ching", 0x06, 0x05, [0xFE, 0x6A], 0x70, 0x03), + 0x07: SFXInstrument("Fwomp", 0x07, 0x06, [0xFE, 0x6A], 0x70, 0x03), + 0x08: SFXInstrument("Squee", 0x08, 0x08, [0xFA, 0x6A], 0x70, 0x03), + 0x09: SFXInstrument("Unused", 0x09, 0x06, [0xFE, 0x6A], 0x70, 0x01), + 0x0A: SFXInstrument("Bzzzrt", 0x0A, 0x07, [0xFE, 0x6A], 0x70, 0x05), + 0x0B: SFXInstrument("Brrfft", 0x0B, 0x0B, [0xFE, 0x6A], 0xB8, 0x03), + 0x0C: SFXInstrument("Brrwwww", 0x0C, 0x0C, [0xFE, 0xE0], 0xB8, 0x02), + 0x0D: SFXInstrument("Twee", 0x0D, 0x0D, [0xF9, 0x6E], 0xB8, 0x03), + 0x0E: SFXInstrument("Pwing", 0x0E, 0x0E, [0xFE, 0xF5], 0xB8, 0x07), + 0x0F: SFXInstrument("Pling", 0x0F, 0x0F, [0xFE, 0xF5], 0xB8, 0x06), + 0x10: SFXInstrument("Chshtsh", 0x10, 0x01, [0xFE, 0xFC], 0xB8, 0x03), + 0x11: SFXInstrument("Splssh", 0x11, 0x10, [0x8E, 0xE0], 0xB8, 0x03), + 0x12: SFXInstrument("Weewoo", 0x12, 0x08, [0x8E, 0xE0], 0xB8, 0x02), + 0x13: SFXInstrument("Brbrbrb", 0x13, 0x14, [0x8E, 0xE0], 0xB8, 0x02), + 0x14: SFXInstrument("Bwow", 0x14, 0x0A, [0x88, 0xE0], 0xB8, 0x02), + 0x15: SFXInstrument("Uughf", 0x15, 0x17, [0x8E, 0xE0], 0xB8, 0x02), + 0x16: SFXInstrument("Aaaaaa", 0x16, 0x15, [0xFF, 0xE0], 0xB8, 0x04), + 0x17: SFXInstrument("Twing", 0x17, 0x03, [0xDF, 0x11], 0xB8, 0x0F), + 0x18: SFXInstrument("Whooo", 0x18, 0x01, [0x88, 0xE0], 0xB8, 0x01) +} + +spc_instruments = { # table @ $19FB1C + 0x00: SPCInstrument("Noise", 0x00, [0xFF, 0xE0], 0xB8, 0x0470), + 0x01: SPCInstrument("Rain", 0x01, [0xFF, 0xE0], 0xB8, 0x0790).amb(), + 0x02: SPCInstrument("Timpani", 0x02, [0xFF, 0xE0], 0xB8, 0x09C0).beat(), + 0x03: SPCInstrument("Square Wave", 0x03, [0xFF, 0xE0], 0xB8, 0x0400).bass().mel(), + 0x04: SPCInstrument("Saw Wave", 0x04, [0xFF, 0xE0], 0xB8, 0x0400).bass(), + 0x05: SPCInstrument("Clink", 0x05, [0xFF, 0xE0], 0xB8, 0x0470).amb(), + 0x06: SPCInstrument("Wobbly Lead", 0x06, [0xFF, 0xE0], 0xB8, 0x0470).amb(), + 0x07: SPCInstrument("Compound Saw", 0x07, [0xFF, 0xE0], 0xB8, 0x0470), + 0x08: SPCInstrument("Tweet", 0x08, [0xFF, 0xE0], 0xB8, 0x07A0).amb(), + 0x09: SPCInstrument("Strings A", 0x09, [0x8F, 0xE9], 0xB8, 0x01E0).mel().bass(True), + 0x0A: SPCInstrument("Strings B", 0x0A, [0x8A, 0xE9], 0xB8, 0x01E0).mel().bass(True), + 0x0B: SPCInstrument("Trombone", 0x0B, [0xFF, 0xE0], 0xB8, 0x0300).mel().bass(True).beat(), + 0x0C: SPCInstrument("Cymbal", 0x0C, [0xFF, 0xE0], 0xB8, 0x03A0).beat(), + 0x0D: SPCInstrument("Ocarina", 0x0D, [0xFF, 0xE0], 0xB8, 0x0100).bass(), + 0x0E: SPCInstrument("Chimes", 0x0E, [0xFF, 0xEF], 0xB8, 0x0EA0).amb(), + 0x0F: SPCInstrument("Harp", 0x0F, [0xFF, 0xEF], 0xB8, 0x0600).mel().bass(True).beat(), + 0x10: SPCInstrument("Splash", 0x10, [0xFF, 0xE0], 0xB8, 0x03D0).amb().beat(), + 0x11: SPCInstrument("Trumpet", 0x11, [0x8F, 0xE0], 0xB8, 0x0300).mel().bass(True), + 0x12: SPCInstrument("Horn", 0x12, [0x8F, 0xE0], 0xB8, 0x06F0).mel().bass(True), + 0x13: SPCInstrument("Snare A", 0x13, [0xFD, 0xE0], 0xB8, 0x07A0).beat(), + 0x14: SPCInstrument("Snare B", 0x14, [0xFF, 0xE0], 0xB8, 0x07A0).beat(), + 0x15: SPCInstrument("Choir", 0x15, [0xFF, 0xE0], 0xB8, 0x03D0).mel().bass(True), + 0x16: SPCInstrument("Flute", 0x16, [0x8F, 0xE0], 0xB8, 0x0300).mel().bass(True), + 0x17: SPCInstrument("Oof", 0x17, [0xFF, 0xE0], 0xB8, 0x02C0).amb().beat(True), + 0x18: SPCInstrument("Piano", 0x18, [0xFE, 0x8F], 0xB8, 0x06F0).mel().bass(True) +} + +Me = MusicType.Melody +Rh = MusicType.Rhythm +Be = MusicType.Beat +Am = MusicType.Ambient + +spc_instrument_changes = [ + InstrumentChange(0x01, 0x00, {0x00: [0x1A9F5B], + 0x01: [0x1A9F9D], + 0x02: [0x1A9FBB], + 0x03: [0x1A9FDA], + 0x04: [0x1A9FE8]}, 0x0F), + InstrumentChange(0x01, 0x01, {0x00: [0x1ACA1A], + 0x01: [0x1ACA39], + 0x02: [0x1ACA5E], + 0x07: [0x1ACC01]}, 0x0B), + InstrumentChange(0x01, 0x01, {0x03: [0x1ACAA3], + 0x04: [0x1ACAE2]}, 0x11), + InstrumentChange(0x01, 0x01, {0x05: [0x1ACB25, 0x1ACC78]}, 0x02), + InstrumentChange(0x01, 0x01, {0x05: [0x1ACB3A, 0x1ACC51], + 0x06: [0x1ACBA9, 0x1ACC7D]}, 0x13), + InstrumentChange(0x01, 0x01, {0x06: [0x1ACB94, 0x1ACCA3]}, 0x0C), + + InstrumentChange(0x02, 0x00, {0x00: [0x1AA04B], + 0x03: [0x1AA10E], + 0x04: [0x1AA143], + 0x07: [0x1AA1D1]}, 0x0B), + InstrumentChange(0x02, 0x00, {0x01: [0x1AA087], + 0x05: [0x1AA176]}, 0x11), + InstrumentChange(0x02, 0x00, {0x02: [0x1AA0CC], + 0x06: [0x1AA1BF]}, 0x13), + InstrumentChange(0x02, 0x00, {0x06: [0x1AA1C7]}, 0x0C), + InstrumentChange(0x02, 0x01, {0x02: [0x1AA27B]}, 0x13), + InstrumentChange(0x02, 0x01, {0x03: [0x1AA2A2]}, 0x0A), + InstrumentChange(0x02, 0x01, {0x04: [0x1AA2CD]}, 0x02), + InstrumentChange(0x02, 0x01, {0x05: [0x1AA2E0], + 0x07: [0x1AA34D]}, 0x0B), + InstrumentChange(0x02, 0x02, {0x00: [0x1AA5A8], + 0x05: [0x1AA449]}, 0x0B), + InstrumentChange(0x02, 0x02, {0x03: [0x1AA3FF], + 0x04: [0x1AA42A]}, 0x0A), + InstrumentChange(0x02, 0x02, {0x06: [0x1AA49E, 0x1AA4CB]}, 0x13), + InstrumentChange(0x02, 0x02, {0x06: [0x1AA4C0, 0x1AA4EA]}, 0x0C), + InstrumentChange(0x02, 0x02, {0x06: [0x1AA752]}, 0x02), + + InstrumentChange(0x03, 0x00, {0x00: [0x1AA84A], + 0x01: [0x1AA864], + 0x03: [0x1AA885]}, 0x0A), + InstrumentChange(0x03, 0x01, {0x00: [0x1AA89E], + 0x01: [0x1AA8B8], + 0x03: [0x1AA8D9]}, 0x12), + InstrumentChange(0x03, 0x01, {0x02: [0x1AAB86], + 0x04: [0x1AA8F2], + 0x05: [0x1AA93C]}, 0x0A), + + InstrumentChange(0x04, 0x00, {0x00: [0x1AACA3], + 0x01: [0x1AACB1], + 0x02: [0x1AACC7]}, 0x12), + InstrumentChange(0x04, 0x01, {0x00: [0x1AABF5], + 0x01: [0x1AAC0B]}, 0x12), + InstrumentChange(0x04, 0x01, {0x02: [0x1AAC21]}, 0x12), + InstrumentChange(0x04, 0x02, {0x01: [0x1AAC55], + 0x02: [0x1AAC6B]}, 0x12), + InstrumentChange(0x04, 0x03, {0x00: [0x1AAD93], + 0x01: [0x1AACED], + 0x02: [0x1AAD07], + 0x03: [0x1AAD75], + 0x04: [0x1AADB1]}, 0x12), + + InstrumentChange(0x05, 0x00, {0x00: [0x1AAE3F], + 0x02: [0x1AAE72], + 0x03: [0x1AAEAD], + 0x07: [0x1AAF02]}, 0x0A), + InstrumentChange(0x05, 0x00, {0x01: [0x1AAE64]}, 0x09), + InstrumentChange(0x05, 0x00, {0x04: [0x1AAEE8]}, 0x16), + InstrumentChange(0x05, 0x01, {0x00: [0x1AB156], + 0x03: [0x1AAF48], + 0x04: [0x1AAF71], + 0x07: [0x1AB1D3]}, 0x0A), + InstrumentChange(0x05, 0x01, {0x02: [0x1AB186]}, 0x16), + InstrumentChange(0x05, 0x02, {0x00: [0x1AB088], + 0x03: [0x1AB0CF], + 0x04: [0x1AB0F8], + 0x07: [0x1AB11F]}, 0x0A), + InstrumentChange(0x05, 0x02, {0x02: [0x1AB0A7]}, 0x16), + + InstrumentChange(0x06, 0x00, {0x00: [0x1AB338]}, 0x0A), + InstrumentChange(0x06, 0x01, {0x01: [0x1AB68F], + 0x02: [0x1AB69D], + 0x03: [0x1AB6B2], + 0x05: [0x1AB3D7]}, 0x0A), + InstrumentChange(0x06, 0x02, {0x00: [0x1AB622], + 0x01: [0x1AB63A], + 0x02: [0x1AB648], + 0x03: [0x1AB670], + 0x04: [0x1AB6C4], + 0x05: [0x1AB49D]}, 0x0A), + InstrumentChange(0x06, 0x03, {0x05: [0x1AB548]}, 0x0A), + InstrumentChange(0x06, 0x04, {0x00: [0x1AB722], + 0x01: [0x1AB739], + 0x02: [0x1AB745], + 0x03: [0x1AB759], + 0x04: [0x1AB765], + 0x05: [0x1AB5E3]}, 0x0A), + + InstrumentChange(0x07, 0x00, {0x00: [0x1ABB1F]}, 0x0A), + InstrumentChange(0x07, 0x00, {0x01: [0x1ABB31], + 0x02: [0x1ABBE6], + 0x03: [0x1ABC0B]}, 0x09), + InstrumentChange(0x07, 0x00, {0x04: [0x1ABB53, 0x1AB8C9]}, 0x16), + InstrumentChange(0x07, 0x01, {0x04: [0x1AB8E6]}, 0x0E, type=Am|Me|Rh, ban=[0x06]), + InstrumentChange(0x07, 0x01, {0x05: [0x1AB8EB]}, 0x0A), + InstrumentChange(0x07, 0x02, {0x04: [0x1AB981]}, 0x16), + InstrumentChange(0x07, 0x03, {0x02: [0x1ABC37], + 0x03: [0x1ABC66]}, 0x09), + InstrumentChange(0x07, 0x03, {0x04: [0x1ABA09]}, 0x16), + InstrumentChange(0x07, 0x03, {0x05: [0x1ABC8F]}, 0x0A), + InstrumentChange(0x07, 0x05, {0x02: [0x1ABC9D], + 0x03: [0x1ABCBA]}, 0x09), + InstrumentChange(0x07, 0x05, {0x05: [0x1ABCD1]}, 0x0A), + InstrumentChange(0x07, 0x06, {0x00: [0x1ABB72]}, 0x0A), + InstrumentChange(0x07, 0x06, {0x01: [0x1ABB83], + 0x02: [0x1ABB95], + 0x03: [0x1ABBAA]}, 0x09), + InstrumentChange(0x07, 0x06, {0x04: [0x1ABBBD]}, 0x16), + InstrumentChange(0x07, 0x06, {0x05: [0x1ABCE6]}, 0x0A), + + InstrumentChange(0x08, 0x00, {0x00: [0x1ABD3A], + 0x01: [0x1ABD5B]}, 0x06, type=Me|Rh|Am), + InstrumentChange(0x08, 0x00, {0x02: [0x1ABD70], + 0x05: [0x1ABE06]}, 0x0F), + InstrumentChange(0x08, 0x00, {0x03: [0x1ABDAC]}, 0x0A), + InstrumentChange(0x08, 0x00, {0x04: [0x1ABDC8]}, 0x01), + InstrumentChange(0x08, 0x00, {0x06: [0x1ABE3A]}, 0x09), + + InstrumentChange(0x09, 0x00, {0x00: [0x1AC25A], + 0x05: [0x1AC28E]}, 0x0A), + InstrumentChange(0x09, 0x00, {0x01: [0x1AC26E]}, 0x14), + InstrumentChange(0x09, 0x01, {0x01: [0x1ABF0A]}, 0x14), + InstrumentChange(0x09, 0x01, {0x06: [0x1ABF43]}, 0x09), + InstrumentChange(0x09, 0x02, {0x00: [0x1AC450], + 0x05: [0x1AC56D], + 0x07: [0x1AC595]}, 0x0A), + InstrumentChange(0x09, 0x02, {0x01: [0x1AC2AF]}, 0x14), + InstrumentChange(0x09, 0x02, {0x03: [0x1AC4B3], + 0x04: [0x1AC510]}, 0x11), + InstrumentChange(0x09, 0x02, {0x06: [0x1AC2E9]}, 0x09), + InstrumentChange(0x09, 0x03, {0x00: [0x1ABF63]}, 0x0A), + InstrumentChange(0x09, 0x03, {0x01: [0x1ABF80]}, 0x14), + InstrumentChange(0x09, 0x03, {0x03: [0x1ABFA4]}, 0x11), + InstrumentChange(0x09, 0x03, {0x05: [0x1AC01C]}, 0x16), + InstrumentChange(0x09, 0x04, {0x00: [0x1AC04D]}, 0x0A), + InstrumentChange(0x09, 0x04, {0x01: [0x1AC05D]}, 0x14), + InstrumentChange(0x09, 0x04, {0x02: [0x1AC5CF]}, 0x18), + InstrumentChange(0x09, 0x04, {0x03: [0x1AC085], + 0x04: [0x1AC5ED]}, 0x11), + InstrumentChange(0x09, 0x04, {0x05: [0x1AC137]}, 0x16), + InstrumentChange(0x09, 0x04, {0x06: [0x1AC146]}, 0x12), + InstrumentChange(0x09, 0x05, {0x00: [0x1AC178], + 0x07: [0x1AC229]}, 0x0A), + InstrumentChange(0x09, 0x05, {0x01: [0x1AC196]}, 0x14), + InstrumentChange(0x09, 0x05, {0x02: [0x1AC19E]}, 0x18), + InstrumentChange(0x09, 0x05, {0x03: [0x1AC1D3], + 0x04: [0x1AC1F4]}, 0x12), + InstrumentChange(0x09, 0x06, {0x00: [0x1AC317], + 0x07: [0x1AC3ED]}, 0x0A), + InstrumentChange(0x09, 0x06, {0x01: [0x1AC332]}, 0x14), + InstrumentChange(0x09, 0x06, {0x02: [0x1AC33A]}, 0x18), + InstrumentChange(0x09, 0x06, {0x03: [0x1AC36F], + 0x04: [0x1AC3A4], + 0x05: [0x1AC3D9]}, 0x12), + InstrumentChange(0x09, 0x07, {0x00: [0x1AC40A], + 0x05: [0x1AC43C]}, 0x0A), + InstrumentChange(0x09, 0x07, {0x01: [0x1AC41C]}, 0x14), + InstrumentChange(0x09, 0x07, {0x02: [0x1AC492]}, 0x18), + InstrumentChange(0x09, 0x07, {0x03: [0x1AC680], + 0x04: [0x1AC6C1]}, 0x11), + + InstrumentChange(0x0A, 0x00, {0x00: [0x1AC72F], + 0x01: [0x1AC751], + 0x02: [0x1AC772], + 0x03: [0x1AC793]}, 0x0F), + InstrumentChange(0x0A, 0x00, {0x00: [0x1AC740], + 0x01: [0x1AC765], + 0x02: [0x1AC786], + 0x03: [0x1AC7A7], + 0x04: [0x1AC7B4, 0x1AC7C9], + 0x05: [0x1AC7D1]}, 0x09), + + InstrumentChange(0x0B, 0x00, {0x00: [0x1A9EEC, 0x1A9D26]}, 0x0F, ban=[0x0B]), + InstrumentChange(0x0B, 0x01, {0x01: [0x1A9D3F], + 0x02: [0x1A9D5A], + 0x03: [0x1A9D75], + 0x04: [0x1A9D90], + 0x05: [0x1A9DBB], + 0x06: [0x1A9DE9]}, 0x0F), + + InstrumentChange(0x0C, 0x00, {0x00: [0x1AC83A], + 0x01: [0x1AC84A], + 0x02: [0x1AC857], + 0x03: [0x1AC864], + 0x04: [0x1AC871], + 0x05: [0x1AC87E]}, 0x0B), + InstrumentChange(0x0C, 0x01, {0x02: [0x1AC89A], + 0x03: [0x1AC8AD]}, 0x11), + InstrumentChange(0x0C, 0x01, {0x04: [0x1AC8B7]}, 0x0E), + InstrumentChange(0x0C, 0x01, {0x05: [0x1AC8C3]}, 0x02), + InstrumentChange(0x0C, 0x02, {0x02: [0x1AC8E0], + 0x03: [0x1AC8F3]}, 0x11), + InstrumentChange(0x0C, 0x02, {0x04: [0x1AC8FD]}, 0x0E), + InstrumentChange(0x0C, 0x02, {0x05: [0x1AC909]}, 0x02), + + InstrumentChange(0x0D, 0x00, {0x00: [0x1AD003], + 0x03: [0x1AD02C], + 0x04: [0x1AD03A]}, 0x11), + InstrumentChange(0x0D, 0x00, {0x01: [0x1AD010]}, 0x02), + InstrumentChange(0x0D, 0x00, {0x02: [0x1AD07F]}, 0x14), + InstrumentChange(0x0D, 0x01, {0x00: [0x1ACD10], + 0x04: [0x1ACD9A]}, 0x0B), + InstrumentChange(0x0D, 0x01, {0x01: [0x1ACD41]}, 0x02), + InstrumentChange(0x0D, 0x01, {0x03: [0x1ACD7F], + 0x05: [0x1ACDCA]}, 0x11), + InstrumentChange(0x0D, 0x03, {0x00: [0x1ACE8E], + 0x01: [0x1ACEB8]}, 0x0A), + InstrumentChange(0x0D, 0x03, {0x02: [0x1ACED4]}, 0x14), + InstrumentChange(0x0D, 0x03, {0x03: [0x1ACEE0], + 0x04: [0x1ACF07]}, 0x11), + InstrumentChange(0x0D, 0x04, {0x05: [0x1ACFE3]}, 0x02), + + InstrumentChange(0x0E, 0x00, {0x00: [0x1AD29C]}, 0x16), + InstrumentChange(0x0E, 0x00, {0x01: [0x1AD2AD], + 0x03: [0x1AD2CB], + 0x04: [0x1AD2D9]}, 0x18), + InstrumentChange(0x0E, 0x00, {0x02: [0x1AD2BB]}, 0x12), + InstrumentChange(0x0E, 0x01, {0x00: [0x1AD1A6]}, 0x16), + InstrumentChange(0x0E, 0x01, {0x01: [0x1AD1AF], + 0x03: [0x1AD1CD]}, 0x18), + InstrumentChange(0x0E, 0x01, {0x02: [0x1AD1C5]}, 0x0A), + InstrumentChange(0x0E, 0x02, {0x00: [0x1AD24C]}, 0x16), + InstrumentChange(0x0E, 0x02, {0x01: [0x1AD255], + 0x03: [0x1AD273]}, 0x18), + InstrumentChange(0x0E, 0x02, {0x02: [0x1AD26B]}, 0x0A), + InstrumentChange(0x0E, 0x03, {0x00: [0x1AD1E4], + 0x01: [0x1AD1ED], + 0x03: [0x1AD212], + 0x04: [0x1AD22F]}, 0x18), + InstrumentChange(0x0E, 0x03, {0x02: [0x1AD20A]}, 0x12), + + InstrumentChange(0x10, 0x00, {0x00: [0x1B816D], + 0x02: [0x1B81A0], + 0x03: [0x1B81C0], + 0x07: [0x1B827F]}, 0x0B), + InstrumentChange(0x10, 0x00, {0x01: [0x1B818C]}, 0x11), + InstrumentChange(0x10, 0x00, {0x04: [0x1B81E0], + 0x05: [0x1B8220, 0x1B8229]}, 0x02), + InstrumentChange(0x10, 0x00, {0x05: [0x1B8224]}, 0x0C), + InstrumentChange(0x10, 0x00, {0x06: [0x1B825F]}, 0x16), + InstrumentChange(0x10, 0x01, {0x00: [0x1B811F]}, 0x0B), + InstrumentChange(0x10, 0x01, {0x03: [0x1B813B], + 0x05: [0x1B814E]}, 0x0A), + InstrumentChange(0x10, 0x02, {0x00: [0x1B829E], + 0x05: [0x1B8310]}, 0x0B), + InstrumentChange(0x10, 0x02, {0x01: [0x1B82C0], + 0x03: [0x1B82E3], + 0x06: [0x1B8342]}, 0x0A), + InstrumentChange(0x10, 0x02, {0x04: [0x1B8308], + 0x04: [0x1B83F2]}, 0x02), + InstrumentChange(0x10, 0x03, {0x00: [0x1B8360], + 0x02: [0x1B83AD], + 0x05: [0x1B83FA]}, 0x0B), + InstrumentChange(0x10, 0x03, {0x01: [0x1B8396], + 0x03: [0x1B83CC], + 0x06: [0x1B842E]}, 0x0A), + InstrumentChange(0x10, 0x04, {0x00: [0x1B844D], + 0x02: [0x1B84A0]}, 0x0B), + InstrumentChange(0x10, 0x04, {0x01: [0x1B847B], + 0x03: [0x1B84CD]}, 0x0A), + InstrumentChange(0x10, 0x04, {0x04: [0x1B84ED], + 0x05: [0x1B84F5]}, 0x02), + InstrumentChange(0x10, 0x05, {0x00: [0x1B8548], + 0x01: [0x1B8575], + 0x03: [0x1B85B6]}, 0x0A), + InstrumentChange(0x10, 0x05, {0x02: [0x1B859B], + 0x07: [0x1B867F]}, 0x0B), + InstrumentChange(0x10, 0x05, {0x04: [0x1B85D0], + 0x05: [0x1B862C]}, 0x02), + InstrumentChange(0x10, 0x06, {0x02: [0x1B8726], + 0x06: [0x1B8745]}, 0x0A), + InstrumentChange(0x10, 0x07, {0x00: [0x1B8768]}, 0x0B), + InstrumentChange(0x10, 0x07, {0x00: [0x1B8B04], + 0x01: [0x1B8B10], + 0x02: [0x1B8775], + 0x06: [0x1B87AD]}, 0x0A), + InstrumentChange(0x10, 0x07, {0x05: [0x1B8792]}, 0x16), + InstrumentChange(0x10, 0x08, {0x02: [0x1B86B3]}, 0x0A), + InstrumentChange(0x10, 0x09, {0x00: [0x1B8A63], + 0x05: [0x1B8879], + 0x06: [0x1B8AED]}, 0x0B), + InstrumentChange(0x10, 0x09, {0x01: [0x1B8A87], + 0x02: [0x1B87E5]}, 0x0A), + InstrumentChange(0x10, 0x0A, {0x00: [0x1B88C8], + 0x02: [0x1B8946], + 0x03: [0x1B88E5]}, 0x0B), + InstrumentChange(0x10, 0x0A, {0x01: [0x1B892C], + 0x07: [0x1B8905]}, 0x0A), + InstrumentChange(0x10, 0x0A, {0x04: [0x1B897D]}, 0x02), + + InstrumentChange(0x11, 0x00, {0x00: [0x1B8C95], + 0x01: [0x1B8CA2], + 0x02: [0x1B8CB1], + 0x03: [0x1B8CC0], + 0x04: [0x1B8CCF]}, 0x0A, type=Me, ban=[0x0D]), + InstrumentChange(0x11, 0x01, {0x05: [0x1B8CFF]}, 0x0A, ban=[0x04]), + InstrumentChange(0x11, 0x02, {0x03: [0x1B8D6B]}, 0x09), + InstrumentChange(0x11, 0x04, {0x04: [0x1B8E2B]}, 0x11), + InstrumentChange(0x11, 0x05, {0x05: [0x1B90F6]}, 0x11), + + InstrumentChange(0x12, 0x00, {0x00: [0x1B9275], + 0x01: [0x1B9282], + 0x05: [0x1B92DE]}, 0x0A), + InstrumentChange(0x12, 0x00, {0x02: [0x1B9290], + 0x03: [0x1B92AB]}, 0x11), + InstrumentChange(0x12, 0x00, {0x04: [0x1B92C6]}, 0x02), + InstrumentChange(0x12, 0x00, {0x05: [0x1B92D3]}, 0x10, type=[0x08, 0x10, 0x17]), + InstrumentChange(0x12, 0x01, {0x00: [0x1B917D], + 0x01: [0x1B918A], + 0x05: [0x1B91E6], + 0x06: [0x1B9229]}, 0x0A), + InstrumentChange(0x12, 0x01, {0x02: [0x1B9198], + 0x03: [0x1B91B3]}, 0x11), + InstrumentChange(0x12, 0x01, {0x04: [0x1B91CE]}, 0x02), + InstrumentChange(0x12, 0x01, {0x05: [0x1B91DB], + 0x06: [0x1B921E]}, 0x10, type=[0x08, 0x10, 0x17]), + InstrumentChange(0x12, 0x02, {0x00: [0x1B9313], + 0x01: [0x1B9320], + 0x05: [0x1B937C], + 0x06: [0x1B93BF]}, 0x0A), + InstrumentChange(0x12, 0x02, {0x02: [0x1B932E], + 0x03: [0x1B9349]}, 0x11), + InstrumentChange(0x12, 0x02, {0x04: [0x1B9364]}, 0x02), + InstrumentChange(0x12, 0x02, {0x05: [0x1B9371], + 0x06: [0x1B93B4]}, 0x10, type=[0x08, 0x10, 0x17]), + + InstrumentChange(0x13, 0x00, {0x00: [0x1B9458], + 0x02: [0x1B94DA], + 0x03: [0x1B953E], + 0x04: [0x1B95A2], + 0x05: [0x1B9606]}, 0x0B), + InstrumentChange(0x13, 0x00, {0x01: [0x1B94A4]}, 0x11), + InstrumentChange(0x13, 0x00, {0x06: [0x1B9650], + 0x07: [0x1B9696]}, 0x0F), + InstrumentChange(0x13, 0x00, {0x06: [0x1B967B], + 0x07: [0x1B96C0]}, 0x02), + + InstrumentChange(0x14, 0x00, {0x00: [0x1B9901, 0x1B97A8]}, 0x15), + InstrumentChange(0x14, 0x01, {0x01: [0x1B97C4], + 0x02: [0x1B97DE], + 0x03: [0x1B97FD], + 0x04: [0x1B9813], + 0x05: [0x1B982A]}, 0x15), + + InstrumentChange(0x15, 0x00, {0x00: [0x1B9A32], + 0x01: [0x1B9A50], + 0x02: [0x1B9A6D], + 0x03: [0x1B9A8A]}, 0x0B), + InstrumentChange(0x15, 0x00, {0x04: [0x1B9AA0]}, 0x02), + InstrumentChange(0x15, 0x01, {0x00: [0x1B9971]}, 0x02), + InstrumentChange(0x15, 0x01, {0x01: [0x1B9984], + 0x02: [0x1B99AA], + 0x03: [0x1B99D7]}, 0x0B), + InstrumentChange(0x15, 0x01, {0x04: [0x1B9A04]}, 0x14), + InstrumentChange(0x15, 0x02, {0x00: [0x1B9B45]}, 0x02), + InstrumentChange(0x15, 0x02, {0x01: [0x1B9B58], + 0x02: [0x1B9B7E], + 0x03: [0x1B9BAB]}, 0x0B), + InstrumentChange(0x15, 0x02, {0x04: [0x1B9BD8]}, 0x14), + + InstrumentChange(0x16, 0x00, {0x00: [0x1B9CE6], + 0x01: [0x1B9CF1]}, 0x09), + InstrumentChange(0x16, 0x01, {0x00: [0x1B9C82], + 0x01: [0x1B9C8B], + 0x02: [0x1B9C93], + 0x03: [0x1B9CAA]}, 0x09), + InstrumentChange(0x16, 0x01, {0x04: [0x1B9CBA]}, 0x09), + InstrumentChange(0x16, 0x02, {0x00: [0x1B9CFB], + 0x01: [0x1B9D44]}, 0x09), + InstrumentChange(0x16, 0x03, {0x00: [0x1B9DBE], + 0x01: [0x1B9E47], + 0x05: [0x1B9EE4]}, 0x09), + + InstrumentChange(0x17, 0x00, {0x00: [0x1BA287], + 0x03: [0x1BA26A]}, 0x0E, type=Am|Rh, ban=[0x01, 0x05, 0x06, 0x10, 0x17]), + InstrumentChange(0x17, 0x01, {0x01: [0x1BA20F], + 0x02: [0x1BA231], + 0x03: [0x1BA24F]}, 0x0E, type=Am|Rh, ban=[0x01, 0x05, 0x06, 0x10]), + + InstrumentChange(0x19, 0x00, {0x00: [0x1BA476], + 0x01: [0x1BA49C], + 0x02: [0x1BA4C1], + 0x03: [0x1BA4D5], + 0x04: [0x1BA4F4], + 0x05: [0x1BA513]}, 0x0A), + InstrumentChange(0x19, 0x01, {0x00: [0x1BA357], + 0x01: [0x1BA379], + 0x03: [0x1BA38C], + 0x04: [0x1BA39D]}, 0x0A), + InstrumentChange(0x19, 0x02, {0x02: [0x1BA3D3]}, 0x15), + InstrumentChange(0x19, 0x03, {0x00: [0x1BA3F8]}, 0x16), + InstrumentChange(0x19, 0x03, {0x02: [0x1BA40D]}, 0x0A), + + InstrumentChange(0x1A, 0x00, {0x00: [0x1BA70E, 0x1BA71A], + 0x01: [0x1BA729], + 0x02: [0x1BA743], + 0x03: [0x1BA763], + 0x04: [0x1BA783], + 0x05: [0x1BA7A2], + 0x06: [0x1BA7B9], + 0x07: [0x1BA7D0]}, 0x0E), + InstrumentChange(0x1A, 0x01, {0x00: [0x1BA5C1], + 0x05: [0x1BA68F], + 0x06: [0x1BA6A6], + 0x07: [0x1BA6DD]}, 0x0A), + + InstrumentChange(0x1B, 0x00, {0x00: [0x1BAA55], + 0x01: [0x1BAA66], + 0x02: [0x1BAA75], + 0x03: [0x1BAA86], + 0x04: [0x1BAA97]}, 0x0F), + InstrumentChange(0x1B, 0x01, {0x00: [0x1BA956], + 0x01: [0x1BA96F], + 0x02: [0x1BA98A], + 0x03: [0x1BA9A5], + 0x04: [0x1BA9C0], + 0x05: [0x1BA9EB], + 0x06: [0x1BAA19]}, 0x0F), + + InstrumentChange(0x1C, 0x00, {0x00: [0x1BACB6, 0x1BABAD]}, 0x09), + InstrumentChange(0x1C, 0x01, {0x01: [0x1BABC7], + 0x02: [0x1BABE0], + 0x03: [0x1BABF4], + 0x04: [0x1BAC0B]}, 0x09), + InstrumentChange(0x1C, 0x02, {0x00: [0x1BAC26], + 0x01: [0x1BAC44], + 0x02: [0x1BAC61]}, 0x09), + + InstrumentChange(0x1D, 0x00, {0x00: [0x1BACEA], + 0x01: [0x1BAD06], + 0x02: [0x1BAD23], + 0x03: [0x1BAD40], + 0x04: [0x1BAD5D]}, 0x0B), + + InstrumentChange(0x1E, 0x00, {0x00: [0x1BB14D], + 0x01: [0x1BB169], + 0x02: [0x1BB17E], + 0x03: [0x1BB193], + 0x04: [0x1BB1A8]}, 0x09), + InstrumentChange(0x1E, 0x00, {0x05: [0x1BB1BD]}, 0x02), + + InstrumentChange(0x1F, 0x00, {0x00: [0x1BAE86], + 0x03: [0x1BAEC6], + 0x04: [0x1BAEE4]}, 0x0B), + InstrumentChange(0x1F, 0x00, {0x00: [0x1BAE9C]}, 0x18), + InstrumentChange(0x1F, 0x00, {0x02: [0x1BAEBC]}, 0x13), + InstrumentChange(0x1F, 0x00, {0x06: [0x1BAF02]}, 0x02), + InstrumentChange(0x1F, 0x01, {0x03: [0x1BAE15], + 0x04: [0x1BAE32], + 0x05: [0x1BAE4F]}, 0x11), + InstrumentChange(0x1F, 0x02, {0x01: [0x1BAF2C]}, 0x0B), + InstrumentChange(0x1F, 0x02, {0x03: [0x1BAF53], + 0x04: [0x1BAF69], + 0x05: [0x1BAF7F]}, 0x11), + InstrumentChange(0x1F, 0x04, {0x02: [0x1BAFAA]}, 0x13), + + InstrumentChange(0x20, 0x00, {0x00: [0x1AD49A], + 0x01: [0x1AD4BA], + 0x02: [0x1AD4D3], + 0x03: [0x1AD4EE], + 0x04: [0x1AD507]}, 0x0A), + InstrumentChange(0x20, 0x01, {0x05: [0x1AD475]}, 0x18), + + InstrumentChange(0x21, 0x00, {0x00: [0x1AE8E3], + 0x01: [0x1AF18E], + 0x02: [0x1AF1A9], + 0x03: [0x1AF1B7], + 0x04: [0x1AF1D2], + 0x05: [0x1AF1E4], + 0x06: [0x1AF201], + 0x07: [0x1AF21C]}, 0x0F), + InstrumentChange(0x21, 0x01, {0x00: [0x1AE518]}, 0x12), + InstrumentChange(0x21, 0x01, {0x01: [0x1AE540], + 0x03: [0x1AE58D]}, 0x0B), + InstrumentChange(0x21, 0x01, {0x02: [0x1AE564]}, 0x09), + InstrumentChange(0x21, 0x01, {0x04: [0x1AE5B1], + 0x05: [0x1AE5D4]}, 0x0A), + InstrumentChange(0x21, 0x01, {0x06: [0x1AE5EB, 0x1AE60F]}, 0x02), + InstrumentChange(0x21, 0x01, {0x06: [0x1AE5F9], + 0x07: [0x1AE61B]}, 0x0C), + InstrumentChange(0x21, 0x02, {0x03: [0x1AE651], + 0x05: [0x1AE69A]}, 0x0A), + InstrumentChange(0x21, 0x03, {0x00: [0x1AEC5E], + 0x01: [0x1AEC71], + 0x02: [0x1AEC90]}, 0x0A), + InstrumentChange(0x21, 0x04, {0x01: [0x1AECB6]}, 0x0A), + InstrumentChange(0x21, 0x04, {0x07: [0x1AF3A3]}, 0x0F), + InstrumentChange(0x21, 0x05, {0x00: [0x1AE6D5], + 0x01: [0x1AE6FD], + 0x03: [0x1AE748], + 0x04: [0x1AE75E]}, 0x0A), + InstrumentChange(0x21, 0x05, {0x02: [0x1AE72A]}, 0x09), + InstrumentChange(0x21, 0x06, {0x00: [0x1AE774]}, 0x0A), + InstrumentChange(0x21, 0x06, {0x02: [0x1AE7BE], + 0x04: [0x1AE825]}, 0x09), + InstrumentChange(0x21, 0x07, {0x00: [0x1AED48], + 0x01: [0x1AED7B], + 0x03: [0x1AEDCD], + 0x04: [0x1AEDF4]}, 0x0A), + InstrumentChange(0x21, 0x07, {0x02: [0x1AEDB1]}, 0x09), + InstrumentChange(0x21, 0x08, {0x00: [0x1AE876], + 0x01: [0x1AE881]}, 0x0A), + InstrumentChange(0x21, 0x0A, {0x02: [0x1AF17C], + 0x03: [0x1AE8BB]}, 0x09), + InstrumentChange(0x21, 0x0B, {0x00: [0x1AEE0F]}, 0x11), + InstrumentChange(0x21, 0x0B, {0x01: [0x1AEE22], + 0x03: [0x1AEE46], + 0x04: [0x1AEE74]}, 0x0A), + InstrumentChange(0x21, 0x0C, {0x01: [0x1AEECD], + 0x03: [0x1AEEF9], + 0x04: [0x1AEF2B]}, 0x0A), + InstrumentChange(0x21, 0x0D, {0x00: [0x1AE954], + 0x03: [0x1AE9D4], + 0x04: [0x1AEA03]}, 0x18), + InstrumentChange(0x21, 0x0D, {0x00: [0x1AE971]}, 0x12), + InstrumentChange(0x21, 0x0D, {0x01: [0x1AE983]}, 0x09), + InstrumentChange(0x21, 0x0D, {0x01: [0x1AE9A6], + 0x03: [0x1AE9F3]}, 0x0B), + InstrumentChange(0x21, 0x0D, {0x02: [0x1AE9B6]}, 0x0A), + InstrumentChange(0x21, 0x0E, {0x00: [0x1AEA4F]}, 0x12), + InstrumentChange(0x21, 0x0E, {0x01: [0x1AEA84], + 0x03: [0x1AEAE7], + 0x05: [0x1AEB94]}, 0x0B), + InstrumentChange(0x21, 0x0E, {0x02: [0x1AEAAF]}, 0x09), + InstrumentChange(0x21, 0x0E, {0x04: [0x1AEB69]}, 0x0A), + InstrumentChange(0x21, 0x0E, {0x06: [0x1AEC03]}, 0x02), + InstrumentChange(0x21, 0x0E, {0x07: [0x1AEC3C]}, 0x0C), + + InstrumentChange(0x22, 0x00, {0x00: [0x1ADA2D], + 0x01: [0x1ADA41], + 0x02: [0x1ADA51], + 0x03: [0x1ADA6C], + 0x04: [0x1ADA83]}, 0x0A), + InstrumentChange(0x22, 0x01, {0x05: [0x1ADAC9]}, 0x0A), + InstrumentChange(0x22, 0x02, {0x07: [0x1ADB60]}, 0x0A), + InstrumentChange(0x22, 0x03, {0x06: [0x1ADC10]}, 0x16), + InstrumentChange(0x22, 0x05, {0x05: [0x1AD7CC]}, 0x09), + InstrumentChange(0x22, 0x05, {0x06: [0x1AD803]}, 0x11), + InstrumentChange(0x22, 0x05, {0x07: [0x1AD81B]}, 0x0A), + InstrumentChange(0x22, 0x06, {0x02: [0x1AD8A6]}, 0x11), + InstrumentChange(0x22, 0x06, {0x03: [0x1AD959]}, 0x13), + InstrumentChange(0x22, 0x06, {0x06: [0x1AD9B7]}, 0x16), + InstrumentChange(0x22, 0x07, {0x00: [0x1ADCCD]}, 0x0B), + InstrumentChange(0x22, 0x07, {0x02: [0x1ADD73]}, 0x11), + InstrumentChange(0x22, 0x07, {0x04: [0x1ADDE0], + 0x07: [0x1ADE9E]}, 0x0A), + InstrumentChange(0x22, 0x07, {0x05: [0x1ADE14]}, 0x12), + InstrumentChange(0x22, 0x07, {0x06: [0x1ADE62]}, 0x16), + InstrumentChange(0x22, 0x08, {0x00: [0x1ADF02], + 0x04: [0x1ADFA8]}, 0x0B), + InstrumentChange(0x22, 0x08, {0x01: [0x1ADF2A]}, 0x11), + InstrumentChange(0x22, 0x08, {0x02: [0x1ADF83], + 0x05: [0x1ADFED]}, 0x09), + InstrumentChange(0x22, 0x08, {0x06: [0x1AE02D], + 0x07: [0x1AE047]}, 0x0A) +] \ No newline at end of file diff --git a/source/classes/constants.py b/source/classes/constants.py index b41d03a6..e3fbf1b1 100644 --- a/source/classes/constants.py +++ b/source/classes/constants.py @@ -139,6 +139,7 @@ SETTINGSTOPROCESS = { "uwpalettes": "uw_palettes", "reduce_flashing": "reduce_flashing", "shuffle_sfx": "shuffle_sfx", + "shuffle_songinstruments": "shuffle_songinstruments", 'msu_resume': 'msu_resume', }, "generation": { diff --git a/source/gui/adjust/overview.py b/source/gui/adjust/overview.py index f7c6faf2..967a9780 100644 --- a/source/gui/adjust/overview.py +++ b/source/gui/adjust/overview.py @@ -107,6 +107,7 @@ def adjust_page(top, parent, settings): "reduce_flashing": "reduce_flashing", 'msu_resume': 'msu_resume', "shuffle_sfx": "shuffle_sfx", + "shuffle_songinstruments": "shuffle_songinstruments", } guiargs = Namespace() for option in options: @@ -158,6 +159,7 @@ def adjust_page(top, parent, settings): "nobgm": "disablemusic", "reduce_flashing": "reduce_flashing", "shuffle_sfx": "shuffle_sfx", + "shuffle_songinstruments": "shuffle_songinstruments", "msu_resume": "msu_resume" } guiargs = Namespace() diff --git a/source/gui/bottom.py b/source/gui/bottom.py index 839f2dc9..c53842d7 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -261,7 +261,8 @@ def create_guiargs(parent): "owpalettes": "ow_palettes", "uwpalettes": "uw_palettes", "reduce_flashing": "reduce_flashing", - "shuffle_sfx": "shuffle_sfx" + "shuffle_sfx": "shuffle_sfx", + "shuffle_songinstruments": "shuffle_songinstruments" } for adjustarg in adjustargs: internal = adjustargs[adjustarg] diff --git a/source/gui/loadcliargs.py b/source/gui/loadcliargs.py index d99f6c9a..069b1fbd 100644 --- a/source/gui/loadcliargs.py +++ b/source/gui/loadcliargs.py @@ -208,7 +208,8 @@ def loadadjustargs(gui, settings): "owpalettes": "adjust.owpalettes", "uwpalettes": "adjust.uwpalettes", "reduce_flashing": "adjust.reduce_flashing", - "shuffle_sfx": "adjust.shuffle_sfx" + "shuffle_sfx": "adjust.shuffle_sfx", + "shuffle_songinstruments": "adjust.shuffle_songinstruments" } } } diff --git a/source/tools/MysteryUtils.py b/source/tools/MysteryUtils.py index 12266f22..afaf6108 100644 --- a/source/tools/MysteryUtils.py +++ b/source/tools/MysteryUtils.py @@ -219,6 +219,7 @@ def roll_settings(weights): ret.ow_palettes = get_choice('ow_palettes', romweights) ret.uw_palettes = get_choice('uw_palettes', romweights) ret.shuffle_sfx = get_choice('shuffle_sfx', romweights) == 'on' + ret.shuffle_songinstruments = get_choice('shuffle_songinstruments', romweights) == 'on' ret.msu_resume = get_choice('msu_resume', romweights) == 'on' return ret From 257eabb6c67dc2965f83bca01e9198225a6f76a3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 2 Dec 2023 06:30:12 -0600 Subject: [PATCH 17/17] Version bump 0.3.3.2 --- OverworldShuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 869f43ed..a7380f47 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.3.3.1' +version_number = '0.3.3.2' # branch indicator is intentionally different across branches version_branch = '-u'