From 7d95405252ac4c141172af1c4264c55ced420e17 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 3 Jan 2026 17:17:11 -0600 Subject: [PATCH 01/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 140010 -> 145807 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 67628454..f59e805d 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'e188d59e5925d7ac84222b4e1cd5de6a' +RANDOMIZERBASEHASH = '69eef09227f015f7457393e24a0373d9' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index e6438813cb7357bb194a3c5177fcfc367922e7b4..71da05c512240197523576e572125e6965015063 100644 GIT binary patch delta 11282 zcmYj%30Mj!if}+w23Z7I^5z(misM>lYyV-0Y31NX1 z76_OiQX8oSMH;bHkkl%zTE3oNwN`39(JH+yi+~3;K7j@*+_jhsu$OrlP$Mc(ueqA=TzLafj6znBsWo3}}o?oDfic+ufDK7HK{FU%_ADWcJaZPe1ny#8eTN@v_>q4CG(NqUby=R^Ch<_FyhOKT<3;=qQQt!16*_6y-VE=MK!&PVYiHx|?dl7edqz(th~Z zP03xsZ}FQoSpgfKpvCvC+Ix*(YfRX%rw@fmWsXekz%G82gB$tGnby)NLGT*Szw#PJ z{@i%?mH8N!{&VBlX$cUU{bS?K=>>#wCS5d`9qIvve1OqiNjvjs=MgKO+bm?QcE>VB zbs06b=8ht5dO>qnYl-%qf@Uh<#QtcP+o8Qu(7cj%Xum9I9!D2ttVIZ;P0p=}?qt@X zy>Dwi#8vfZNpo}ZZx5#m*0_S^bF}RmZM#>k{odM4;mAn;Ez%y@YHRMAYAMp*Lj5C0 zMx3qrJ!?=qc9l*VSLRS5JE`bn%LX~pXjfnWRX;F>I?ijUat~gG$vu-Rt3MskL1YBj zn)ND*rp`LFA&wK*Xv!IrL|K0l9qupmD~=L$k(Nf(^Y|sR$KblfcN!1Qp4Ts6sL7$# z+nSS2jTe)yL2Sb9#{5N7Aek0MRf)!RvjO`1x@1$jXdF7FUb*Am*;8PiXk0!L%tH(F z_($j8S$4gubE;_UoZ30HG;aNk(M`0IpoC?i=lRbTe}M%(X{<~>IeysT5L@*VZSgP1 zv}b=grlV=cK$B~@)Hc-Y(563b+<4%DG;~#$yP^8&Lw8|-*3soI-8t>YB5f7FmX3?m zJaHFVwd4~QIjfUb&g?u+vkf(=E9oRkShDnv3Tf~a-$D?Eo#X`3&Z z;)k11EZLuYG~k`*g(a540ot-BEnr*0A2ju~L)*+tO_PS8C_jQWvBaaAgY&+pAN%Ap zJO5jyo&1=8-82rCG#)e!Rrph^JpZI@)jhXfyXs!!BFD$Cpp*eY3tunBpo?doaKmgmABwOZ$Tl`>vKl^fLXVMskmwTMklu*g?vEx@4g!ZUKNh z$9jyAzv`ftw`0#sstM2$eyV`z4s|x(_k;jebywp#=m>&sn#{YCwCSD4+9qYz7xPu6 z6H}VFp%k}~qR-ZuuAf2TOsg-vXb5XpfI?+`F@m^s$|-P@=%Sg=(Xy++@%-#9H@}^t zoA`_LxjGa5A^$c_AE_}J=~B)_mkK8Oh|6TZR&(86Syx4WTo=gD=lLLpE~_!o6$qmO zVU+zp4CfTe{=}i)QW(V_w^#F+sR;3`KjO4;hbc53N?S`W8o2Qk{|dzo_RmbG>~pBv z%+|#?Pz3=HTbexXw@s8$6LOnhe0lWig;xw*F?x=mr}PRBEkzwr?~(ES^Q!9&DaJ7v z=sxJ$VzGvM`D(AF+`I0Md zVB1FVe_R>Bd#zdMKgODh5?lk+XpS9?vR({=a5snplXmr~32JftPR z>r=j*MM+f@Nu@;o(z0wef9Gl#EaiKyjzX=red!3{p}S#_YxC%DDiV^5PDyie{#fy+ z9<^`$DXgCG4IlItU(!BZAz4FT&M8zRX$Ah9_I+~sE}EX>+&-CK_F4SspYL7J1hv1~ z5qM!zP{%;+Mnn*!lowRNU0od#kFrV?obx2-iMEly@R?eZ@xa{!pA#{CFZGSoF{9NlLs+-8{VZZ0cxqN_fKGVg3RuDu*Y=DNrft0JKqR=*5ua46 zwHsc_pgNY+?xAjK*Pk=>v}?eh>NE z*9RNN%S;zwRiO;Myet2~5Y82=UWk*JjyfFj3!ooAV-Cf7ppX$q(X*V!qCa2pxLLVh z{(T+&+cciPAF)yo0Bk`0B~t^Xa%CR*UiKJ`u9zA!YEV7RSaQPw!9St~RLB-yaBZ5| zRz+YKfdLG2W=wCR2LuZyem`lg`s48<{n3too|^d+dCQHlkmXO`7z11RTQ|ZZSfZ=O z?D*z~`p=ws)sU6yA$TE*&SlAu=&N63C-Vcph>4~Ty8zABe2CeEb$La8+z;v^hUOMaHg=Xv<#MSU z$X(J<{`42I6A#`wt=4PbK!Hji^Xok|u@AZ7=ITrLkhwDYJ#?4qqYFz9NWQV^+a}fR ze}f;|F)VFe-tK{FFg_PscBch{4o^DWC0sH;Zlj z^*_X*p@VW-&gi}_-j!8S8w#{w1V{j{gSNM_O85X}W5}b^cwp9Bw=YWie>i|r#x-7l zvPTgq+idv-y>)7B?No=nHnM~8zjf|vjzJ1L2I@v1sF{1bapPadq>{Iu)eTfMD*pF5 zHbj`b>E~eE`|E7?k{D*%gQqtIU6o2@&lDD9Mhs)gFAP9e!MMMtG z{a$~n7w?v77yqv+dHJ(bYw$6!14ocB7*O8e0C*z=OI;$|34?>M&}iZBF!(LD=(+Gk zI2?u@e&l@?4x=Hqe3uY93}#@O!`?l^;7=0RCZtEgdm$b@clmb%6@bEbh%jVo{!c=3 z6daB3-Sfixb`+GsAxe0ko4uW?e(-}k3uIi#KVD-PSKyIqA9%~6;VuYqK`{y@VuloN z>L~b75>UE+v4#G}Im|7@kB22e(c|*V(JNhFpG&z8*9!N?!zFNwFl_=ngcn$8p=kna z#Rn|%c;B7~e`eVzt3&N-duVpGcfQ44XtFBj_ z06_8{0A69#Alpezc%C^89J|T1*}nEue~MY zY=F_&>~{oi1Kbz_mlxPSt!l8=5GUPR^};;p#W%vOI5zQ)_swj$2}Tt(Z@*~h2*~+j zn5m&~90hauNi?k&7SiP$TDYsJcW!;f`}byeHXItf?=x@|RAj~<_ z7_3`azsxx{Sa@QFcQGte_=1I@c(PIOK4jqrEI>7uVih*wP_lPv9^^2E@M_N2boYsj zjb960Hkce*5fD@Ap}OUoKA}8e5PAv5L=U8dMRs@yOPS)mYKJ*k=>Dx`)___Czm+Ra z3l*&H_UT^jY9X-z&Qi@=Syl}?melujpXeSTEMFmT1#qtvBWPjnK0(1jyM$koeC)p9 zmIT^HuNPWiXAvq>F{u zs^A#xo&Daot6(i0uw{>>%Ke^wb=?I@RyzEkP1s}AEpyetVEN@hd37 zjN#0lxVt5ZQL#j9?C1Gba;ZUhc4PjEd|D#3SlI^PvU%)A@_QHA$GO_ zuL-hWiWZeuzN`Cg%=3`%#(Y;NE|@rgDl17a8sim4V@-ZZ!oLdq-+%k!Ot(QVlT4Tc ziQE(dL?nnUz-V5F*^gi+Jz=g$25Z|m#nv-I`$im!`M zSvt-+hubIa5Z8$<=J6P8Z6)2EGEHYq=es|B{d;aF9(3i^=ONGe=PN{UmAJwv4o(nP zfK^eVVt}|;oF?uO_ltwsaF`&b6U)RE;*2Pf2o;;e)APlqND-V)5Z8ck)L4g0uxa96 zvlC}Dm~=0~_)7fF5+ea6=8Y2aKO&fh3>~sa{D=*bkWC`iD0(g75|ExCh9sto_5w-n zED0z|Fp3AsH6n1@P7#Eu?|k1$?K4SluLVKOT?unf0(*Pe27>(HndE%mr+tSGv7Hj~ z86os9g2pzxJcdU=?k$`6j&rVvul`twPeAY*f zo(Z0r!=+M#A>Odh@JB-L*@4%Ly>GwW+k3Y6{ob+{@ArO)_&$5qnbhfK!=%KsXXpEh zllo4w1yWFv(03A?F&~s7@~l*9?ez=CjF#q3kTP4*iG(<{G4u7ccT&JbGbWE@e6;k{(3*(>^33TPTC`4Y@C*R-F{<=~HNf zSe2A1mLa}ux0HP#VR|KOrYsAP$&@@@u4W>{{WBRsl&^>k+SNpM;Tvz5DM$ zClStyBLC{e;w76MTpl;}RjNMbRf@eMy2dV~gjXKJ)%eocj|J{A9HZ37Qw~uO1?R|l zl<>)8cxhlX`hiEJQ=EwpT}oL+QEXW~MJVrr%cWVP?(!2BdjIT#OCyag*#Vfb zewft&YxYZ&-N2Cqn4^HTp@W2i$!M;RjR)pQ0I01}!0P;@>^FhYdIOM~)$pO3?2N!f zV9)}|$~CtlB7CKB=}yR#57evzNaNeEurRDI0T_{dfd+Lf(2+g>eA%&y20&)3NrPVj zZ9KMmbv&zqb^?rgDPpW�OD+5euMSL!CuP}4Czf8!9oK-M$?gz@eql$ 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 LwqbQs#Kr#u>a=Mf -- 2.43.0 From 2d91647794dbc2d6247c7ec7d189eb741dadc548 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 3 Jan 2026 17:28:56 -0600 Subject: [PATCH 02/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 145807 -> 145807 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index f59e805d..9ca9bd33 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '69eef09227f015f7457393e24a0373d9' +RANDOMIZERBASEHASH = '490d30d2c817fdd3a01ac7fa943031b7' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 71da05c512240197523576e572125e6965015063..2fa89ef32d859232a597818ec1a8725c6e0e338b 100644 GIT binary patch delta 339 zcmV-Z0j&Oy^9Yag2(VQH1d#P_3bR=Q@HZk^j=AcojUvmAxmbaX zBG!(%EP;_+Vv}n-9sxpwiaWQ8I|01%f1+(Bn3L*(3zyfO4v+$c4y6pLqbD}Ti4Cs_ zs}NMip97tZ@C~mDuUwqD4)9N}5dXP}0RZp=Ab^aM=$Qfl@B<)2jgyX*1OV^@AgGs& zl?VXv10cPZrI`=_@B<(ajg|xunwbFr&Yditv4H`4jjerNO1D8o2Pk@&uF9IV0SeHsK0xkjpZI^m40#pGGm(MQ(8XIeH zCxFe#_yF)N$@u{AD9Pji@B_$z-H3>nCYJ;-0w^2{2w;GhMh0Mjg=k`*gn^fzf|-tB l+N!_6_>(i2NH7AQ23Q(hfO`kG?JxqG2nZHIHFZ??=cgWEixL0; delta 338 zcmV-Y0j>Uz^9Yag2(VQH1kLv{2(wuO@HZk=j=AcojUva6xmbaX zBGQhzEP;_+UXyD(9sxdsiaWQ8I|01%f0`*Kn2qoauM3x+oeq!!g$|_*s-q`1#)%ED z39ATH#-DqfjqnYx3a?b0xeoA8uMq#ai2(rc10Z~iljxZO0Pq7KKaG=)l>`9r10bZA zjFkug@B<*Zm!+8y0Pq7K42_mV51N?)0MH4g0`QhjIg^tMIMN+~273CdD5U~xm&7gt zH~}q}{VoC=3}s>DjerNO1D8t&mX{_k0wV!Xmr5@JE&_RMmwGP(Q~?H;&o2TR8)I-M zfX&JH0Proz`2g@J$>ad=1IU2gh=`XSmjo~ZC>#R_V1SoC24H}NXkwp)ftR0xnT}xE ks=vValPi}4;azTc*O(}lc@W&i*H -- 2.43.0 From b038ee6cbed5b49f6a631c610b638793c6e5857b Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 3 Jan 2026 17:33:34 -0600 Subject: [PATCH 03/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 145807 -> 145813 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 9ca9bd33..da6d5d6b 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '490d30d2c817fdd3a01ac7fa943031b7' +RANDOMIZERBASEHASH = '66804e3a6063d35bee8945c721ad4776' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2fa89ef32d859232a597818ec1a8725c6e0e338b..2b73809ac24b85a08b16c86858fb12fd10a76e00 100644 GIT binary patch delta 81 zcmeDG%rW&d$A(a57K3l+Ih!My+asA7w?{HFz19-$RuM(*j?r-$n?*~m?0 tVfetTuwr`8R1Oeh@ARcJ1wage-f1iXv$k*0W4g=5A?9dW8uI=5asV^_B8C6} -- 2.43.0 From 507f4170c85ae69f0f8b4a59a06dfb3fe83665d6 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 3 Jan 2026 23:19:51 -0600 Subject: [PATCH 04/54] Update Baserom and write loot bits --- Rom.py | 12 +++++++++++- data/base2current.bps | Bin 145813 -> 145846 bytes 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index da6d5d6b..6666c8cd 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '66804e3a6063d35bee8945c721ad4776' +RANDOMIZERBASEHASH = '8e29777cf6d1ff6fceb72bbf7aacb62c' class JsonRom(object): @@ -1440,6 +1440,16 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): or world.dropshuffle[player] != 'none' or world.pottery[player] not in ['none', 'cave']): rom.write_byte(0x18003A, 0x01) # show key counts on map pickup + loot_show = 0x09 + if world.prizeshuffle[player] != 'none': + loot_show |= 0x10 + if world.pottery[player] not in ['none', 'cave']: + loot_show |= 0x02 + if world.dropshuffle[player] != 'none': + loot_show |= 0x04 + + rom.write_byte(0x1CFF10, loot_show) + # compasses showing dungeon count compass_mode = 0x80 if world.compassshuffle[player] not in ['none', 'nearby'] else 0x00 if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off': diff --git a/data/base2current.bps b/data/base2current.bps index 2b73809ac24b85a08b16c86858fb12fd10a76e00..deb687f7113065f7786f5212976816ecf9751ed0 100644 GIT binary patch delta 1276 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 -- 2.43.0 From 5418dbfb88400e369eb61c7903bd39dcd08b87f0 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 4 Jan 2026 07:17:24 -0600 Subject: [PATCH 05/54] Update baserom, set item loot levels for crystals, pendants, and bomb bag --- CLI.py | 2 +- ItemList.py | 7 ++++++- Rom.py | 23 +++++++++++++++++++++-- data/base2current.bps | Bin 145846 -> 145872 bytes 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CLI.py b/CLI.py index 5db1fc78..f5b7bb89 100644 --- a/CLI.py +++ b/CLI.py @@ -106,7 +106,7 @@ def parse_cli(argv, no_defaults=False): ret = parser.parse_args(argv) if ret.keysanity: - ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = 'wild' * 4 + ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = ['wild'] * 4 if ret.keydropshuffle: ret.dropshuffle = 'keys' if ret.dropshuffle == 'none' else ret.dropshuffle diff --git a/ItemList.py b/ItemList.py index 44d1dde9..36a2990b 100644 --- a/ItemList.py +++ b/ItemList.py @@ -1107,7 +1107,7 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt precollected_items.append('Pegasus Boots') pool.remove('Pegasus Boots') pool.extend(['Rupees (20)']) - + if want_progressives(): pool.extend(progressivegloves) else: @@ -1124,6 +1124,11 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt diff = difficulties[difficulty] pool.extend(diff.baseitems) + if world.compassshuffle[player] == 'wild': + pool.extend(['Compass (Escape)']) + if world.keyshuffle[player] == 'wild': + pool.extend(['Compass (Agahnims Tower)']) + if bombbag: pool = [item.replace('Bomb Upgrade (+5)','Rupees (5)') for item in pool] pool = [item.replace('Bomb Upgrade (+10)','Rupees (5)') for item in pool] diff --git a/Rom.py b/Rom.py index 6666c8cd..20cb11c6 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '8e29777cf6d1ff6fceb72bbf7aacb62c' +RANDOMIZERBASEHASH = '3e385a852b789c31079aa6a14ff2498d' class JsonRom(object): @@ -1447,9 +1447,28 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): loot_show |= 0x02 if world.dropshuffle[player] != 'none': loot_show |= 0x04 - rom.write_byte(0x1CFF10, loot_show) + loot_icons = 0x1CF900 + if world.bombbag[player]: + rom.write_byte(loot_icons + 0x52, 0x0B) # bomb bag is major + + crystal_ids = [0x20, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6] + if world.goal[player] in ['ganon', 'dungeons', 'crystals', 'trinity']: + crystal_category = 0x0D + else: + crystal_category = 0x06 + for crystal_id in crystal_ids: + rom.write_byte(loot_icons + crystal_id, crystal_category) + + pendant_ids = [0x37, 0x38, 0x39] + if world.goal[player] in ['pedestal', 'dungeons']: + pendant_category = 0x0C + else: + pendant_category = 0x06 + for pendant_id in pendant_ids: + rom.write_byte(loot_icons + pendant_id, pendant_category) + # compasses showing dungeon count compass_mode = 0x80 if world.compassshuffle[player] not in ['none', 'nearby'] else 0x00 if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off': diff --git a/data/base2current.bps b/data/base2current.bps index deb687f7113065f7786f5212976816ecf9751ed0..b803f6b3526f0bbc1b8d35f22c93169dbe0a83f0 100644 GIT binary patch delta 531 zcmV+u0_^>^^9a!M2(VfM1PM6y$Aex2hh75#w_XDR?hzT&z>^Dgg(ZZCM+5)?Cjf)n z0z()8E&!6$mt7SCn+IG+>Kk>D54Zmn0(TV?!1}om156x;DgO_}4$$u6Aiu$vi7NtL z5t{nBk2=MEuble1k37YGub#K~D*_t=7J&G)L5Wj|(DJ}x` z0s#7#Auj?SNdo%0mj+S&)xem5yCekA#=ivmxrGJ41Nymz1g8X>Dp1gYu$D!3tcAaz zpPGg8o0p88yNLh@(B;3Plbn+`7F~dWyPGx@U4WN~F9PEN0Qt9WFaoy*0YR50Hv%#e z4}k}fn`J!KS%5MxGH)`kGVhmaHv%Ak4l538J}W+JI;%SCIx9M(R2Dmc-32QJYZWUN zD+wzKD>*AUYY!_AYdGZ!WBtHfS+AfR~Gp z@RvJpF@Ti|1qBNN0+)}84-O8>Cso+Kcv;`RH5k;k03X$pT5-XJ4Gp(BcD8eXW_2cj zHG!8hI08=ufd?nWmxVY2SP>%y2!Nk%QHWuHP$hXKP$hVm?l=N74{%*XfCHU<24Yvmt0(TV?VEVZb156x;DgO_}4$$u6AirUkkt+gT5jy(0k2=ME zuRQv>k37YGuRgXc0viGrK=`?t1`xkO__>(~5WhtDxtSgizeblaE&}!f!1U_YZogRD+?pCksqkKV7 zfZYWv1#1;67ApxW3M)A)IcpCq4{JXwKWm@RodRzHD+22Rub<(a3@Z$4JS#kFpV5;y zI5B{M1)fx#qAHrBEzVn+3 Date: Sun, 4 Jan 2026 09:19:05 -0600 Subject: [PATCH 06/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 145872 -> 145942 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 20cb11c6..0bac0581 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '3e385a852b789c31079aa6a14ff2498d' +RANDOMIZERBASEHASH = '8ae09962f63d09c1ba6a8c370819cf4d' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index b803f6b3526f0bbc1b8d35f22c93169dbe0a83f0..95436056136080a43e5fd31ab9d62ca64a3cba69 100644 GIT binary patch delta 2484 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 -- 2.43.0 From 2195adca64a5c0fde653a9b75ed3e21ee16e0170 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 4 Jan 2026 09:44:29 -0600 Subject: [PATCH 07/54] Add HC and AT compass if pots or enemies are shuffled --- Dungeons.py | 15 +++++++++++++-- ItemList.py | 5 ----- Rom.py | 2 +- data/base2current.bps | Bin 145942 -> 145946 bytes 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Dungeons.py b/Dungeons.py index 8fc54156..7b888f5b 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -13,7 +13,18 @@ def create_dungeons(world, player): dungeon.world = world return dungeon - ES = make_dungeon('Hyrule Castle', 1, None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], [ItemFactory('Map (Escape)', player)]) + hc_dungeon_items = ['Map (Escape)'] + at_dungeon_items = [] + + if world.dropshuffle[player] == 'underworld' or world.pottery[player] in ['dungeon', 'reduced', 'clustered', 'nonempty', 'lottery']: + hc_dungeon_items.append('Compass (Escape)') + at_dungeon_items.append('Compass (Agahnims Tower)') + elif world.compassshuffle[player] == 'wild': + hc_dungeon_items.append('Compass (Escape)') + if world.keyshuffle[player] == 'wild': + at_dungeon_items.append('Compass (Agahnims Tower)') + + ES = make_dungeon('Hyrule Castle', 1, None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], ItemFactory(hc_dungeon_items, player)) EP = make_dungeon('Eastern Palace', 2, 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player)) DP = make_dungeon('Desert Palace', 3, 'Lanmolas', desert_regions, ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player)) ToH = make_dungeon('Tower of Hera', 10, 'Moldorm', hera_regions, ItemFactory('Big Key (Tower of Hera)', player), [ItemFactory('Small Key (Tower of Hera)', player)], ItemFactory(['Map (Tower of Hera)', 'Compass (Tower of Hera)'], player)) @@ -24,7 +35,7 @@ def create_dungeons(world, player): IP = make_dungeon('Ice Palace', 9, 'Kholdstare', ice_regions, ItemFactory('Big Key (Ice Palace)', player), ItemFactory(['Small Key (Ice Palace)'] * 2, player), ItemFactory(['Map (Ice Palace)', 'Compass (Ice Palace)'], player)) MM = make_dungeon('Misery Mire', 7, 'Vitreous', mire_regions, ItemFactory('Big Key (Misery Mire)', player), ItemFactory(['Small Key (Misery Mire)'] * 3, player), ItemFactory(['Map (Misery Mire)', 'Compass (Misery Mire)'], player)) TR = make_dungeon('Turtle Rock', 12, 'Trinexx', tr_regions, ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player)) - AT = make_dungeon('Agahnims Tower', 4, 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), []) + AT = make_dungeon('Agahnims Tower', 4, 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), ItemFactory(at_dungeon_items, player)) GT = make_dungeon('Ganons Tower', 13, 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player)) GT.bosses['bottom'] = BossFactory('Armos Knights', player) diff --git a/ItemList.py b/ItemList.py index 36a2990b..4202719a 100644 --- a/ItemList.py +++ b/ItemList.py @@ -1124,11 +1124,6 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt diff = difficulties[difficulty] pool.extend(diff.baseitems) - if world.compassshuffle[player] == 'wild': - pool.extend(['Compass (Escape)']) - if world.keyshuffle[player] == 'wild': - pool.extend(['Compass (Agahnims Tower)']) - if bombbag: pool = [item.replace('Bomb Upgrade (+5)','Rupees (5)') for item in pool] pool = [item.replace('Bomb Upgrade (+10)','Rupees (5)') for item in pool] diff --git a/Rom.py b/Rom.py index 0bac0581..0aa48e47 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '8ae09962f63d09c1ba6a8c370819cf4d' +RANDOMIZERBASEHASH = '5a872cafb58faf8d37cff990b477aa41' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 95436056136080a43e5fd31ab9d62ca64a3cba69..0e0a8b44f19a610e2306b65fab7467143d3855d4 100644 GIT binary patch delta 58 zcmV-A0LA~7^az^t2(VfM1356pgIxoMT>}BPT>}F4G!c_VXfc3+29x-cS9vdhmj!jV QU^oJ=0SCr|)|f&nE{xI^2LJ#7 delta 54 zcmV-60LlNF^az&p2(VfM13xgpgIxoMT>}BPT>}F4G!2(FXfc47i;wV^J8v%u&V*mgE -- 2.43.0 From c94d556c4b3b62f2b9ce682915247ac6567dfd7f Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 4 Jan 2026 12:26:50 -0600 Subject: [PATCH 08/54] Baserom update --- Rom.py | 2 +- data/base2current.bps | Bin 145946 -> 146400 bytes source/enemizer/SpriteSheets.py | 8 ++++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Rom.py b/Rom.py index 0aa48e47..30dc7806 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '5a872cafb58faf8d37cff990b477aa41' +RANDOMIZERBASEHASH = 'a5b1d774279ff49774b3b7f9d0e11dab' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 0e0a8b44f19a610e2306b65fab7467143d3855d4..32eb93b5a18b33f2068c12059ad46250975c0ec4 100644 GIT binary patch delta 2606 zcmW+$4{#LK9sa%d?sCBd`6sdlOeA+nY$ymMB%o<>xp$BR6snj&iDC%H#RyYulv-QZ z-OJm(+~qiqaGE8o4pAmB8Lbc_lc6Jc%^Ir=g`#2=5D?F#)e01-1ijhqi*IIk-rwK* ze&6@~-kzK3mu{sWsz47KJEHxaot=An4|b~k{aU1B_wL>O{hdz)!hLmWVlG=T!S_#0XDg?V#^VUo80IEdy#0^xGF*g#fTh+K(_HFmZQ>YFV_OHYaWOME~ z|GWORq@#JT!=pVe+KLGF@ z|8DGyy`J`)zJYKhTDaoA36H$~4IF{@U44Scl|*(XiR z32YfB$o21*6i$~rb1L@_+*Tk}f6u1(86I<=J!3)loP7wj(oU{=;3 z`z1=wh8V!h4M_WNJYKf3abI&p$-pcZMT!A=22~G4-565A6&U$_RDv222!NY9J$ebE zCaC!+cmnKMSy*&S+dF<B>QEp&$HHkcrX8()|I4V|% z6gQ@Vsmwyi*tl6VtR!t%^0J(;>TNCj7>^Gj5qfT&$vG$`Plu4)(E>{4OfS>*Z$oan6EL4~rmj z9oRHr7%>-AivR+f0|-Q?hh?K>B81l>uL*Rn85##@{`|JP0L5F{Dp{xnp*3ri4XEpL zo)4G}=B7|C;Ks&5ZNVfwMGAcfRs8f7#1aq&VDCZOWQaCGcp(m5=eO+iqTmRMJ%J)O zL9IriAO<1kMm7^#fh~c(878Cvi&8_wdcRNq9KxB1rD2wZl;bFbfQYhNjwAJ(Qow#; zxLO#=7#5O(cy_uVOc%G7j)Q1J?C=(O0%+DGEJ!7o%>`-!%>nj4w!4N2T>6@w#5@`o zufqxLe3k8q9wS>g6Ij}kEO{AAe^v)=jp&;5EJWtmf^}%eYlx-WkOf{#kQ8U^%c%iF5RBk*6ncR~vM~`sa>dKh z0vOvS&JF(-josUbf~)OHy*=o&D?ec-K;%<9*F*ggTU_RZOt0w=txJs$I1=t>C(f{? zVP0NkPyvh3;zd9ga;p?L^Bn~RWt_iP2MY$BzkI|9@5IF%@ISt62pk&O}{LjuKwjCg~ z91^fK-<^CBIMx*i3aX?EovvF;+t| zc`c^EEqXlIM^YIgA;o4B$^Z{? zx{<#u*}$P%HRY0xTg)Spy$gmX?OQwRy#OIu0^zc`+7dw6mLJfOHwp8gAB2 zyDvZXK<^i8jXoBm0jjkY91ds zQ|tmeMS6JFhv{MRj=nh%+Z1}$vfd##=nWG4KI|h=y-@A-u@>qh$5^}ZkN5-1-l^MT zt7Ga0BmQW67v;1XT}JFV`L<4cWCQiFM~#)NlCC6|NV9Q`G}8o45I3!iPf=pt_>l|b zBDugWvO6!*Q|u%;wXZbNb)8(-d?nbOQM9vT9pj9}tK@-$C3rnrc{FoY=EkyFWg9bi zOG``3(B{ek9FImq0lOaS$r#V)h{KL?JQlXw?VW4A{kpW!CLh>5=S{uj>3MP>EuJoi dF~(Z$=6UkVJjOutLfnhesdMvP`zMCa{U4FK!Jq&D delta 2134 zcmWkt3s6+o8UD{Xy9*6yFlfD^0>Vly8BrAR5vt1`d28e?l_X-atPiMZQIkRO?!BD7 zE6chpcn2(k$W_0&&|Gojy|FCQGnO@$)w6ob z%?0OV-6ClfGcJtWSeL#(u3W0vH6dFcHx3kubow zd^|oHIRpIAE$1aj>mI!MG6P7VJVz z?VW^#J7SJ<36wPCyAGCw1S~q(Dip8)(vqiQA=dv2N(B&EF;Wt>f~h#)<1I$WPAJcG zwTGm60NX|6cC$+mm_!I7$_u!}14;`f)Zw5?HVVukiiE-K(+~x-4P$JYguOuuBjA0E zl^Vj*QLq&$r5KIdpC=AHalYntBPv9EwMbcliX#9*C>HX0$q%ODcu(SU3Jxr`vS#10EGd*^jN>2CzCrrxQDsQ9vfp3Bgwm)(8;< z5?KcxWsWRbW7Tl?VhSmMCu`USRaY#+&dJL|}D1yNIljLrYTbrg=A5 z0&@U4uW02j;wAI+MEN}&0WlS#M78rga5>OEeICYg^4P{C}x1EY={DGBnCHH~17W^+DY`RTW#iyw7+F^zV%3} zio^3fb|?|S{}B293_b$>acJkk@4^2PNy|`?KddKSO_O>-uW-V3{0kbjizJ)MJVh3*nGzQNSB7(Tszms>Jn}fG+v-sjIp_@Yj z1a4Wm*!&Jbiz@r>dBY7wzu)X><6?nfT6Z+lR(! zc8Y2jm*P^?qD{@hv!mZ9I}FoYPqoY}Jg=}@BRcCdLenL`mwJ!xlcq_9bQ>w6+gQ*D zvthcQR2fyQidK=Z5oG)6F!_KV59=9HpH7CzG2@u}%TTGT=~;Mg;qgA>INxoe9Pxjl z#frbz@T(=#KR+@)BBr^81jzskvH|idBSc+PH})8N*e-pq^x^!(p&L4DVmfIe?~r$U zmf>{EfUEUOEpr*3g)^B}vJB5f?b`Nbc)O#dGEe#&GtE~?KiR_5*NuLTuCqEmGfgeI zBu@%id?!{Wxh466UYzKbLJO4p^)yKL(!FGmYH`_EnDaB^Q?`?85fpvi3g8X*M{` zyQKR%agloJVr51J%cT{hf>%VTgLnX?HZPJi>mI3_ngk5>rBu1KVy*;c>n+a diff --git a/source/enemizer/SpriteSheets.py b/source/enemizer/SpriteSheets.py index f558eb7d..14ec54e7 100644 --- a/source/enemizer/SpriteSheets.py +++ b/source/enemizer/SpriteSheets.py @@ -465,10 +465,10 @@ vanilla_sheets = [ (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x08), (0x5D, 0x49, 0x00, 0x52), (0x55, 0x49, 0x42, 0x43), - (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), - (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), - (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x56, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), - (0x61, 0x56, 0x33, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50) +# (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), +# (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), +# (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x56, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), +# (0x61, 0x56, 0x33, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50) ] required_boss_sheets = {EnemySprite.ArmosKnight: 9, EnemySprite.Lanmolas: 11, EnemySprite.Moldorm: 12, -- 2.43.0 From 74739347e7443aca5c0d1b8b93905bbe46276e79 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 4 Jan 2026 12:58:18 -0600 Subject: [PATCH 09/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 146400 -> 146434 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 30dc7806..d81c874e 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a5b1d774279ff49774b3b7f9d0e11dab' +RANDOMIZERBASEHASH = '4ba89fbb7fc0e75b483e4289c65d1b8b' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 32eb93b5a18b33f2068c12059ad46250975c0ec4..9efe98e4199911361a0ff55352255f2253c02fe7 100644 GIT binary patch delta 489 zcmWNHK}b_^9Dskn-+z;>Ot-f|%ff6gszG5+XB|q{p2VzEox&lE*hU??L{SHMd-MNZ z+ZbyNgMYCwiMkYoVfLcaQ0i2AP^d%G4w6?5v66VNoxYEc@5gV~_#fAF2BlAP4~?nm zxSoS$1GFilV{_&%uA(DeFz@gL%O@C`2}XPuUJ|Q&XtT2%M2y9ZFkY|#0+m)c-{hlG zD;U=tdDYx%qbMF#EKn9s7F~ehaNZ9%k;$Lqg`0>YBYGMie*>ollgUYu@X)O`-T_4b zrfN}b;f(k( zJ=h|iN)&2wmvU?3m{^dg4-X3FqorUkKcv0JjjSlJ?6xNKH74J^{Cq(`LLooh`2><~yGKUlZ0h4lvL4$~L0RdWCgk=Gl*Z>9o0RCY9msJn~bPj~d z0f+$r1Ac%&fRh1*m)8&iQUb~Wmn#thHUc$(mtzqEDG5aX7=$B_-4%hCl@S6aBZgQ7 zgj)rMWCeu#0)rR;i_`@H0Dgt~0{;WR0KkAl@S8hfm);QqNdhH;mnjkgJOW(+mxvMq zF#!^nx)K5@1{I5e(qKZcj7H3BRFsh8F@0`>v8m(4Z;=N?>;iBQ8plOv14 x-2=~q-h Date: Sun, 4 Jan 2026 14:24:29 -0600 Subject: [PATCH 10/54] Initial pass at door shuffle dungeon maps --- Rom.py | 5 ++++- data/base2current.bps | Bin 146434 -> 146514 bytes 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index d81c874e..d953c665 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '4ba89fbb7fc0e75b483e4289c65d1b8b' +RANDOMIZERBASEHASH = '37cb55253a676976adb3bae6037f6498' class JsonRom(object): @@ -1449,6 +1449,9 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): loot_show |= 0x04 rom.write_byte(0x1CFF10, loot_show) + if world.doorShuffle[player] != 'vanilla': + rom.write_byte(0x1CFF00, 0x04) + loot_icons = 0x1CF900 if world.bombbag[player]: rom.write_byte(loot_icons + 0x52, 0x0B) # bomb bag is major diff --git a/data/base2current.bps b/data/base2current.bps index 9efe98e4199911361a0ff55352255f2253c02fe7..018c68c20b7c2d2f118ad3e3c23792591c518106 100644 GIT binary patch delta 875 zcmWm4e@q)?90u_BzP)uVbX^x2tNgNFBy(#SEnDnxm=f3+WVpB=$qW?Z3|o*!W2PG} zA?0f8yj)2sE6nMiQYpa?VP~u56b=G)qj}g0lEFr!&dQA=Bc2pD8E_U6>9Dq4161w zKV$j3EdSsd^Ee=5jiM+&M3}pLVT~|*)Yr1$KFiC}?E@z%c}m}KehYQ|lCLf6YomT` z+8)BpuX$zfV0JY`9lZqg1Ekpm0c#K;G&{HzQQk%; zg0tqOR`bK+CG!Kb_kOwAT<-06BH?u;9pT=>WZeWWQGaBe+u%zr?K~5y%&zYMTS>(y zCyocd#`!H7YD3<&f$kJt2CnFqflgGlaKvSUQ#5Jm9UyTV)HX;}n1yj$pA)n6w4cRm z{uoXH^2zjgm<3fDRcTB$s-jheQU$H~|3#@L%$8-{kiuKW9#LAwFoBrnL5rjOmb!bu_)y5{= zeapOiZkcB~f^t;*!JH?(A#8^<7D_=dLk948zW7EH^*FpMmLA(Ilta#bzoXmuUFYRH zt(JIjX=@sD#-10|dJCDZA3nDeOWLaX@1vat@>MMyf|?N7WQP~1k4b|a>YIC#H%=$n zqD*fxZQ76n6v}HX3nA%d3<@nNNa3)t1qUp2SPBp63T7t4n5j@aLJwz@j>SmU4lZhx ztl6QmxPRY00dJnr5UYheD-`fwz74=t_z(-qTTFfRx2sAA}2*H8A(Ke6=dT*(-Us< z?6e*7)zqTWz+O-JnHXoE&6Z+hsJlL5BZFDv)Xv-kZn&K^8j+}kIx22tL_3G6IUwr~Oa zRrO$jJ9KzspN$vTJfGYuhJUf^+hyCAkIRUs!!O_FypK5VL_ho8BV&!CC@%x-9j~k` zI~!m%QhY@t6&)>H*^);|ZQ|ybxS4vlZdz#DigXmG8S`J#v!MX%Lr0tggzuzUHH%O9 zW3)hRZ-cdMq)rbWiw7Z%3s+&OrTs%Wf+l0C#`tk+$~a+ky)qe%CRb}Y684L?T5vuh zi~&}`3>>RAz+Ej}awt$3%QAvxnrTS8fPa9~c_Y-Myl@hY=bQsR=SD6af-tGIz;3$h z%uXMpKL;vQsZf;xtqPP1NCo6yjX#m;OTY{D z*|Gj5u$O8$=C=3W>2{!D1P|ym&A#Pjht84ze@)W%KZtZ@Gt&P*AK0 zb|Eg%%o==huwdYBbCls{M6v`EBuZcHb?BbEj(!`jG4JrD@}rp7IV;t81L-esIzAsu zMHMfCr{|HpQrHL+K2lc-%c*_DR|*yDc7=y(!(7hDo^Vt@DSIfC)|i8x()Aw5q!tAMsmp&74*06>Y&LKywP;70j zO>#H8wib5tV|~3B_%9*S8IF4pll(9?AYGKQ3mP#O4>8jlu_qZpq2eQC+zNGIa}rY- z%!Y->NM#x9G*qf@@XiCh?Hm_!M{Q395-x+eP^g%rc2o?p2( I&`~t>4{okbE&u=k -- 2.43.0 From 409c6d9a4e87db281180793e8d9d9d86b498339f Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 4 Jan 2026 23:04:09 -0600 Subject: [PATCH 11/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 146514 -> 146541 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index d953c665..71289fde 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '37cb55253a676976adb3bae6037f6498' +RANDOMIZERBASEHASH = 'b91468dad57710399dd8949e10177ceb' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 018c68c20b7c2d2f118ad3e3c23792591c518106..bcda314445a568885154a1050b9a617bff92c15f 100644 GIT binary patch delta 2983 zcmW+$30M?I7Vg(`at{J74gzfp2!c2$9w>Mu9%#tM3*{IU6$Jz%Nmd0!=mtkYj+vo> zQd#6`l;IF`VmgMzQE&s}Igp5=L3A|6AnGXUs$W*NO?_Q|)vNcv>VB{O>fX1~r*Ea2 zNl>Hp^@VBLl}eH321|BnPfvpfr+)t$7oLcWYShOHLUEho)CM{};t*|7WE`U$o^*315Lk9|Khq`5*<-_r;4@^9Q@f7FtJ zDpu1>iwe&I@k^mj!UNfKpB)-%P?6^tqNY?!e#)Dnl>TJV#M@-4`c!j%AEO!TJ-+87 zD}|;jQ|Q%{b?$hIu2k}tkZw_~(f5p%ituKY{x`QUAubuvyAjDkL34f^ljk)TI+=@J z<)GEadKU=bp8gMC78kf=mN3Qs9s<{Z5`C+`p8yh={=kKh#kftK4DI?QQ~Lp4GDJ`w ztYLIPw?L!MnHGoR(nrk0;7XXO&zTVe5TPHKxn2x^F>}M#!d|8%tOzO@VxA8iWR}kJ zgG&8Z^DaxEfeBku0lzT)O9BEd_u0dA&S6H3`0p=D-G786&1^(h=Pf#C0bN9-m6kf01(bJ2ow+>SCG7UU~i<`y*Xk`u7uXs7N`? zjD}ByoBD~%YG=W8{m)dl_vE9YL7nOu`86RaO%_206`XO@KP2}8;n+;1Hj$5V4`>8L zP&4rdaxT>WaD2H9%+iZaAIA9tAN#i69R`?1z45S8uj^$Tz>Ntr&*96OW|q6!+`P-i zkuHNgtkze)2a$dGT{fAuot$z6s>v}zsr!Df`X4%Rq__2%Oy*Ya<6eOo2kHJESJ z5|0$<;W|F&bmSBTflgoL(Ird}O_wq`+HyYA#EO5RHN3+ky|?&ySFOUgm_^|#x>g-d zT{SDL8#`n=uO|i?RY!p{`FNP^P_znHWLs%8Dq*V_ojxnpVP0k;j!5tAAd>l-^+kcF zujkrgX4ZmBJ^pu+REf;Z2rvE6?9{lr7Kv_DnKi zcPqX--bjwU$(n2!*W5A}BK4B&U885YZr`o?H-0jUfH3x>^x3C+h(5F@7A7wAS?fqu z3N23cM%N^(&N^DEZmAH351$Z*4>N9)U+$nkKW;Q!>SJa8MvF=K$dOuXd|?t1ef?Ch z@g+YoqC2rL%X4o(q3ACU3#qBvz4%w!a*SMFN542m(Jzlt{UhX96r_Xzr;9f)$zD}? zhNx&0@>zH|nj(x`suK8CkG@_H3ukuUVqKH=$30Qwj##}Bc~7fudHivyZqpO>7)Px9 zoB8clxoQtb?1^iV0DGeL`Fn}bkMSEFmDwyC9hF;Kf5bRz>o}h7y49>Q^U>(9cvug$C}t~Ud#5~N zTLQo+wK%rQbJ|SO*1hMlj34-$yyf9ZoVd4oibW7{3VqlLa~Fg@X3E)3w@cui#7xmB)}G!iJm7w5;UUdMEJMOHM3?- z2ho~+4#k!yK_D)hjuc7!?`s0ungnTJM0b-Q(sSXT!_&bsqQjni%)(;FI59z#WcKrn zb6L~~FS=FR!QVbT*;0v9qC_*H12hK}YzKGPh;-Xwf?Viwuw`)mtu~9;z#}zMky>Od z3V?8O06p9e^|LMvu?+^p5UUaxe&P}1Fs&djPxkiEpJJ?0c8~JzkkyJY!to?!6qjNkVb*IP@q5mQN0fzt-QO zxE*eMENBa~ZZyzOSu^41pq8x2t|GIp9#M-|WIyq9K%N;WW(Rn~Hbm_JcieF+SG5B? zt?)66(D~iq>^>p#PXGB(tj*Ez*Wl^f?Nw3dv)(^`+}%wLwHtP$7rSAq^Nw9w+7~Hu znI(I)^f(lqt!<4#!F%AMGx?s)2h8OD{_eD0-@R6LyeT$#A=@;V4?m%ZG&o2&tSa1? zw_!Z3qAU-5w^RQ(XuCMC#$*lDJ-%0?y=Wv2nqU>GN{1?tp!pdPBnscFZ4c&lWk4s+ zdqVa>#kiE62WtfN&yo#fC!LH0sRy<8i6-0dich$w`yg9@+ipQ$(%=EBxgr{jR(#mH zf{)4Oa=Qy)K!^)>p-2r(ahf#Ofy$4>V#@=T6_liR)0->OP?-ioVFuT$0UMBRNO(l! z$bB34yA~v3+q5)migrL-uGV=@WV)cwPeL33 zI(ZV7!dmp^Bz$SJ%&kJl&c$o8(uhOg)&@m z@3Bi1oh`nJ1v(6iRo<(1e&Ig`y@ zBJenoY-46;{akDx7Kbgs#$)w+kz%rPNu+<0E8$b2$zG5D+|KU PSW7>MuRM?(p8oXz?277K delta 2954 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 voGsS%zmp*Teq>J?z Date: Tue, 6 Jan 2026 10:43:30 -0600 Subject: [PATCH 12/54] Update baserom (should fix bad floor ids messing things up in doors) --- Rom.py | 2 +- data/base2current.bps | Bin 146541 -> 146552 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 71289fde..72b97d71 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'b91468dad57710399dd8949e10177ceb' +RANDOMIZERBASEHASH = 'd260b458e494bd2e5962bfa0b1e88825' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index bcda314445a568885154a1050b9a617bff92c15f..7ffb13b82c4454bd3f97953dc82b338fe2fe6e0e 100644 GIT binary patch delta 927 zcmWksZAe>J7=F)tZcP-?w6p5kX2u)8I=dNdJG)g(T&y2c24$12TZL>mb(IdbvULNO zbK^B-sZH)eD2Fa>la1OgbfHQa;ZlZaps;~I#DVOKbri8QYn`lggqYmB_~-fJf#=Wj zC}YfIjB}q5QhD<<`HKj-KAO1sHeGLjWBshU6cjfDYC3sdtWi{{_}c0ENYpQ$RMa;; ze(_U9-RB7&7Zf$!G!;H^Bs%Ezivu(2q;e@MI;YjafA9Ax^J2q{noi%d9B(P`fiu3< zQ1ozR@!hjqCMb4=77h=SMcLeuFn5pxE9R%AdIXUB0jiH&1ZNHi=p^4&G(blLSFZ0=nxQkaSY$Wl%u*4I50VLg4lyh_&17>H9z06)HkB!x_UORJI7!nFrMqMs9?bCA3 zNev6@R!ww6@{CdF?qo#ols(kyCYnC|ACc{XX+#^*M?eS7?JgP}9SeWn%m*rv;gHN1 zE3oM;9PQ|E0&_O99y^0Nam>n~L;gvC)owl0ozo0;Yxgr5UDKS*PIP;>UITV{l@>9k z*VO1to)G$Tn*4;+YZO4&`#Tv03c5TXaN|zgOFm1q?Zk&D*xw7*Cd6tqS7EKh9WA)) z*geba6{R`lj+Y9`vne<4s{g`Y(7#1qsapCvo3c#A9{cwZCHKHzD%>dayjLbJmScQ3 zdJQ8*vn6|t6Hy55mgZ+GHZW>QSz@lW3m861p75(J*hWtBUt4g0X?$j_JSKU|#$U3; zd9@9Ph=YG%!*+6uU$x8g*w2DPl83w?J1x755p6bO{{NIpwd zAQU)n+{&7{-(ymE(Cr`hmWAHuwXNuAN(7`8*Ed<6Z{M^0!vbVg6LH;vrGLVAq8mmo z9$fZIhB)O%xvv!)$P0X~6`$GORW&SmZiO9{!;)`l7Q(~)ZYvI1gcG+tuF%@0=U05Y zyh7~T>w&LGiPy&xLg-7+kNh3}dKKXBrFr=weMJ8*a8}N9+adh05N^_}yeV%w^M&u_6LW{~ Pdun{lKHiqc;4l9JV0Lpt delta 845 zcmWlUVN4r!7{=fK`>#+M0(G#hVe6<@24iDF3#KT@A!RUPV`2<(nM0ZBppIx_OtxT1 z?{3#K0d{RjUH*>Ft{-S-r-*Jb%>@&ie$u4MHWR;0VbP8m;tXnH8q?f){qjD~`^%HO z&s!>4AD66OTp+}8`yzQjEH}na-Msx8{nPjA{RQpL68C#l+sR$wYGayMbK~OS>nW8x z9n(%pDt9iXbx2ER{xSncE+x*NNCgy?>s{35Vjus<`6F83??)$NUvdqL+Ro0et}_Qs z?fGE-Zameuucok2S(dn`8@bF#yMjYv3;ffwDXJgvCNZ zAY%eh02+1=f*=ckqV5>gD<~Isqg;gIaX2aP?CS)q-F&HyZ*3 z^fCvnItBL59vlkIiat>8k&zrwF$WmA3uG|or!XpjIpv>;d>Nqp669d6b+9-K=G|rj zZKDEj_L-h`3$YAQ1b>?_!VA#CO)CYYIvB-aqcmLBZ7ti6N+mjRmYi9a1D*THL&kSvQy|{ETqDJf=ELcg*s**# z@0!W{qjr!rlc=?pH4`Z-GuP^I^#Cf>!K$>a-8z$k)mn?~X1Z|~Q?9%#Gr4^g6SGHG z*{x3WlGE&ACwA8^FK*XoM5QkDoNJl2bm2HT&ff1rANhpc>cVG-Ldj3hCMDb2`DDg! zX!8Visq6mb_-9wK;*x4S8m$`<=UtX)JbJ}iVGgFI?G-blhLpPa%dEqLgJgxh?Lnt) zuIHXARCSu{XT< ziaqdNo2Z1|ydIIH#HCE2iRHb>;n@|o?Zsr(g@Y3!PqPc%_#>g;((kg9&tL)TH|d64 tpx@J9Ox=_>SYI!`Yr-wMDR0SJ{tfvDx{+P)#jmJUuPXdj{ZaSh{{dFsLvH{8 -- 2.43.0 From 870d981eab1f44dd675bde73cc2121cea5e8fbc2 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Tue, 6 Jan 2026 22:40:41 -0600 Subject: [PATCH 13/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 146552 -> 146562 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 72b97d71..3158679a 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd260b458e494bd2e5962bfa0b1e88825' +RANDOMIZERBASEHASH = 'a34dbf39cd329f38a80e4f1345c55221' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 7ffb13b82c4454bd3f97953dc82b338fe2fe6e0e..f156dfa0888890b379b3bc52bbef4076a9cb4e5d 100644 GIT binary patch delta 74 zcmV-Q0JZ=4_y~ge2(VWJ14Br>vswc}0tx_tf$$uKf$$)MgPsM4o&^E7o&^HuG!T<8 gfQ1VJmxhT83k8>vsSCH0Is)AR2+1t2MqXLL1U&~E?*IS* delta 64 zcmV-G0Kfl&`3U&<2(VWJ1N=w>vswc}0s>5mgQf+CrUe1FrUe4$G!B Date: Wed, 7 Jan 2026 20:57:12 -0600 Subject: [PATCH 14/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 146562 -> 149410 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 3158679a..c8e7ca0a 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a34dbf39cd329f38a80e4f1345c55221' +RANDOMIZERBASEHASH = '853a9c63d437833d5812e287544cd0d3' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index f156dfa0888890b379b3bc52bbef4076a9cb4e5d..2beb22110c27c090ac5f75ffd63e3c80dd47bee5 100644 GIT binary patch delta 7399 zcmW+b30xD$`rphhNjMV@HT5EfD5PqOLKQ8VU=XoVwbr&C*ak(Ahqg-lTI-SBWwStl z5MYG`B7$h1MxKJAKbqGA1n(YV?eVJhX)Q&?9= z2&}v?-&j(keZJJg1|G-^Io3F+IasY_ziUZmtF$i_HVDriSMF}z@$oh*2axrykQjsv2Ny} zf2MKvLGqZbHJOL+Hk$|2i)%6yJx2!zw>ER^8lGcE9)?)B_J;IVi#uM#2+_So$#0A6 zsW}0$^+&V|#9GRTCW&8C8x>m{j>J{eXt|CQ`r}}9vO}r*ek|J5F)}SNirLC?6Wd)H zdrOdeoG{T1m0}>%yq|NHa84<{$W~nHk>Z|jPUfpxGxt?``l_@WYCMD8HZ51vwr$?g z!*=b}8qXTeuDwy?nZZ?M=8)dFLTBb$cZOisrc`;7S)1mi0W~Re20}>r&wmT5qW#uz=2t}??Ms5ke4|eNT7=&dbgXN))id0xWw|o3P)KhR z>(6YtEm}QZdbkIhhwtLnQcmhDk#7Mt|HGMQRIYs z{qE!AaME|m_~6Uxc1@*SH8|*1aV=9{zqOicnzOZ{EwS{lsAcQjR3lcnXYD_DA+nFo z{JQi1;5CH6N<*>d`SNLVBPcD9P%Ny9E=`wqd9KEY4 z#~0gZ_K2SLZfZ*w5i4ykL)r!N>g+9IIRDMzi(M*jyM}=Ox=5yLqu675nRk4T%BdS; zyB2!<$}ir4X7fyzYTh!F%+#9i^GnmEt7Yiz$VauJf_KS*@bReD9Uj*f@rty*9BE{E zHAmEpAaUhrLSR%~ed<_N<$OtUk*>Ifu~95nAieNrC8u=G+g4KLm1&mMwXVx;Y*k9go0Nl&0?!pCKT0AfOaZlTCMZ>%?&R}@tPXxEjyb0m`;k@HJpE=>oe)dF%4Zunx)T(GYZ9R(g{17CjU`7GHh;oQ@UwK z4HJK_JJRO$A35LbRki&r&R}hdwqG4ZLf@1&`7Wud0<8`%ZfFnI#5c4jYZgh~3KY9` zQA7LoCUw?WRyY^c^kn{6wqB;OxX(v5Rj+%;Wo)7ea6hW4P?|=%YODkrifVnHkpDe~ zQ&cOavQ6cJI!pD4lCAmjoX+J^ zivz_>FK!rar(BTlMkqhe2pQWNj)n5v8fn{_x`WWSqHWlF#5+a8YwAQs@;cCV`C9^} zIVrL;w-UAPMQ=-yVfgb)tOC#{(W4;8O3_0oG56*#PAX?8J5ywj<5m+BM zsf_EFl5J}XrS~H6q_8&tMwUZ2?3rftesxs37lAdihY{MVUc46q7%%{~#4JKN)A%ib zKTvD2P0s#ELwyYNdMDE`qzJpK{TY%?z@$>l;_U{c%hj5+43!K% z^ZkK|ZQjUGAbq+8mh1rvo&k!716OT9XHIw99c$ zw%SA%(Ji$kW5~(TS^A#@lTM9d)h10e#HOlsC^zT{M26oAPRB?pUd?AV?cU*vZJvLu^wbTUh_g*XO`YFuZU>{TrE`lKNJ(NInc z+Mne)A!;w|H0&`M{It@i^aI}jK@8(pD(^5bd1PVgh>y06`1TN`>wI8Y>Vx8Dq{SfP z|BV=vMJKJvIyaRi`~>9W3}DP%c%|G+d3%!or!iWdP8#wr)TUaJDV;^PE)^`4 z8Y~uV4qBAc9}l)927y5bLOPNIgn@;=kVLd2V2r|cX@^mdg?}BHCNjk4kUYxZi!Z-o zG%|byrWo)mQ~dzSR0cwfR{^dX8R9G>KC9`I#0a02w7};pnlq=!=Sv2QdVMOq0=umg z4oJ?)HJg|4?Fl`>#OC@9hLI8f z2uvO_-S(m{hZcYCqepzdc!#upz7IogDp5{u(M?RPHyYR1%TZZ6Wlco(?ds>vYN1aBL!C7+^C06ocp-lhK^Oe@}yjUkcW5$uZJ82~#~-_7P79 zz~mB*c-vh>nBQgfBDB*u7XlWdosU_N$s7%DTi-=;LvG3|ucVRa zGO~*q7W`J8vLYHNtCi|c1trV;$lPbH7={gh8g|PW18Dt`27^C07WuyP$$hs+sFB+v z|GP87-wvRO+ynjo0Y8wxrj<3bgcZpUt6M=qEM74JvDq{L0%bZFMlFVvNg7S8E(VtP zVJeVyx5IQO+XBn{AZ!DnfaFHllS=e41TjFTrJf5>2&V{}5KRR~E2B*TN(FJk=qT0r zAcdApw+SJNHpvxOse+AwF-`Mdf)3wsMrUU31fGLEhkpabOWI`Ad3loKr zqcd3j5DZ?gLh)<=_`GFnQSUa!8)BbTtVaFaby^q z2Hn>ENNZd|q*{;$h8P`8)lOSH0`ySBytl+WJ|sIkwM3;c8iz;{G874j2&6a{qf!Wi zC=T!)@D~4tKviZ2EC*%LYk=emlOKvdB7{MzZ_g=IcSz(=@+F9&bbvx+T1=Cjz}uaA zhsE7@Sm9qt9&a{l%-sOiMfhIHHJ>tPt(FF zDoR?gv*y{7u;>uOL<7m)tf+n6sk&RJa@=5?7OBdw@PzGd}m}-cg254bS z74(HCjJ?=ck{(|6bAuRY?CH zi&GeP@jYDpHpTxR=1Z!_+&;@@_`CFep24&HCh*7j1Ef#w{7X1?F!5WC7Q1WsTrBtd zYxmi$_bA1o{dWF$O51YaBpl--XbeB8Y;{0&o~jwG{2-Rw?2Blpaz<6{z)3!tE~z6? zJrfmk^qY5k3k5`1~n`rVV(`~u$OGQ zwU7>Nuo^BovvNyQxBwsy1qx6S(kM{DT`;2|*oj)GX6haC_QOVWm};S-U@T}+GfG15 zAQl6DnaZSes0AHH8_BX->M;J4(orpRK*KYugtO%6MnRS8nyL~?AR3+oM$EZXFOm7x zU=+u_FT_KwCEtAuAe?MR36KgeKn}b`h>1s$eNzga|DQ31-3Xu$T|>QGZ%Q9`jXR6Z zrd&JQceWSxp1qdRmqOed^`x9l`IPJ9uBTk*K1F?~o4kGKQzqs5+3To}`}FKt)I*4R zP#gK;^#-{;AiU9K9`fY7OGjH{elN{$nz_MiJ7V=T#Ox{-@vgb-`;_KKA>W0)5w0*> z5cCCCtYQ!P{FbJLz_>sh;6j{*XSxa8!LqaC7}*rt-Q!(5@`kjLfrV)u}G+Ze1L%J0#% zZlIIc3RMbgZ(0P5bD~g|$R6yndX8oOey_BrI>X}*N^b+dhcF`q9h)&pxXgM(+tA;L z^FftZ2qKa>w>MOcqH*gp8|SjjL01@&kib-{#0`rZgh#=ypvx4r(^|XWaRv1SxXIQz zeLksIjALV**+mB@i~x%QaR~N7cJ>b3U_j|SJwP(2~ z$-Hd=`<-HoD`Y8jvy-+2gs|!@fuLX`$U@{8<`paJWn^;FTRoZO@R6T6`rSf~{Xg=n zUdVFvkqQnIgpnYOqX-#6AcBDZEBp;cHL*nqYR$M<)DwSWolBNZWE{Oc5en{Vq`(qK zVRb>m)d$%)U30!<01x0T^GTyevqg~Y8onFPa9UX@2XmS_wRRg4|`Np z#)?wCUwJ;P@5j5EuCv3Qchl2tM(_G#^B%kUzDsro_n{#5W?4{BkU9^<&zPEeP~33I zoh#)@Y`vVI(_Ogp1p<7m&QqwjMUq>P`}IiSPN*jr9Wi2o)3(K?`APMUxkNE?u8>px zRLCh9*1$IQ#P2e92YOZid0uhsyZlkc`a<1D1#p)N$n6nuzIy`!?9TK;i5b6^{jRNH z*yE7KJ%Pt8N#hDq@6^`Smak&#PNlHba@QP%!p2#mm8&AaBLZxC&T+oc+}=I9(tD2o3LE1|XR;_YUV|~C zONEP6Y1`waF7qP--^yqVpVYNa$eMNgD{sVs&5OqleY`GjgF4%r-h9>zO_2e ze0kcjjk~^;6E=n4whEhO-L@X|-_^K&*T?sTNc#9BwmM;j^x+d&&n#fw$PU;ZiuXt2 z{S)y1i8x!9Ek7PYUwypC;te9Pk4bJg%*xuP_gI9(J({*O!+|rI2j8p91{Y3uQRyyP zGS2xWlnp)(_%iLKwPhuqEdsqoptcA&J1krIH=bNrjSQBGX|C_+%pV7dL_L;|LukfJ zXZ|u+n)$!MQirU^A|^F_;~+h*!w#}qk0#&!i+u(frL~99(zLA?LfQQNN_>0*7UbD7 zSCC$j-wcG;pkuBmFK*WKXx!$3dhDF8{>|P6e|p4f`=6eAg$UJ-dDXSRarp?w1Z{etf@FyQ#`ky}S71e7D~|2D@4NSZr70(YrElu(+F* zHgFaCdbdk%pMXaLH#_XQY5)0j4Rfe!KmpD;eC zHFNKOg!xCCN*{E+YxT?*WL>?ZmAprD98|~Dd5K^Ll`}k!gcC8a{0;^wEri&2eMp%! zeeaLoF&C|#&0!CR8?lN+pr&!6$_-;0X;tIo+R*e`kqO)RBezasrI_Fu?3hAY+fwZz zQRzI^#SVGuLDf}ADy-_Vl4`uFtB6z+RqyU9xk8@5x2_16j3f|mup7wTq>4;`<;q>n z1)1vb-w_$+rVbD+r8+QC)i_CYK^`CJhKJ4-yGx~z=}GM88O+C3W<^hY*^PAqkYwfx zOV7q_3TeqPTbK)4v>RINBv%JZzJp;TpNA1kA8SP{7uc#j(K_J-7u2RZ;a2%QHj-8; z%}P=HcRe0$MeY+TYUt6{+fsRrVzgnGTrSmU*welcLy26FlAq~kZRwmug)rzm=)UuWUxsdTDGdS*7BNKFli zlk#Tc=fdZN#<9YdjZIdLa~8TY9Q&jXXX7a`rqlJ9$cu-~(vmkw>KiX*Ag?QXzuERCX4qR^RMzyGvYBt4TzhHFs_lHN?j zdev-{(6Xwm-bwXSn@oj=W=L&`SjW6x7S1}zv}6bw_NwU=l|||Xg3+O=D3Sbg-s_}Jn)Xs^^cadmaVbudo!@IZN&TCQ?Q}lDo_A6l)kF1C z*G<%}tqmSC;1fN`~Y}x-kbQJo$35+d-Y-H=8<5slAKE zd|ORfud}z4I&!{d4jPB{nWXGOF`xO>SrGW!ft{PB`E&8piQz>aCGz{D(f-~B>NM}< zUz74#mr0`heh2l8Y15(2oI}r7y=>Y^trQoPo=>61BI(FnJU7CVMV;zB#T$FK6D=62 zT4$&x2(W=|g#MMho=^M#C#>Ido}sfYQ$s0PYGWs&!^Q(hshO2UsvaGS;4B8RbLCR@;3-#e;PsUitS%c)Vv za5PIDNqFhhp4avWj@{Lc?bY>XdV|nu)A-hZj%%*T;{ARnFD<8=IkOZgMbE>}Csu7I zJhQF2HBBp7o8SL0@y)`fc)J4%9aT1CZ>965VB{U|AL-^6IorgiN}Tql#3JeFJggaW z_O$5?b-MR7|Eg&lg~@mAc;~!W>FaqoiD_7xSG<<}aOQ{GK0N;64-fSZ^ZwNTnRi8h zCGUp*rv8EcLEazwKk{zrZ{^)`-+J)9{`!Hns0Ai(qGE^ul_6j zNBWQTU+cfl`$7Lh-e3B^@|x~6UY>b5@3Q;y4^5BkgZjZd$H~TE^2lVeU}+6GuZi}u r@g?L`?QjK$5+o%Lz*uzH0s;bRvuE^no}7;_BgKw_g~v0NUYz~^U4u-N delta 4342 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 -- 2.43.0 From 8df39da2bd70ea9121eaa2fb6c5d33a06c091a27 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Thu, 8 Jan 2026 08:18:27 -0600 Subject: [PATCH 15/54] Add showloot setting --- BaseClasses.py | 3 +++ CLI.py | 3 ++- Dungeons.py | 13 +++++++------ Main.py | 3 +++ Rom.py | 20 +++++++++++++++----- resources/app/cli/args.json | 7 +++++++ 6 files changed, 37 insertions(+), 12 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index f75617e9..e2fcee45 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -149,6 +149,7 @@ class World(object): set_player_attr('keyshuffle', 'none') set_player_attr('bigkeyshuffle', 'none') set_player_attr('prizeshuffle', 'none') + set_player_attr('showloot', 'never') set_player_attr('restrict_boss_items', 'none') set_player_attr('bombbag', False) set_player_attr('flute_mode', 'normal') @@ -3126,6 +3127,7 @@ class Spoiler(object): 'keyshuffle': self.world.keyshuffle, 'bigkeyshuffle': self.world.bigkeyshuffle, 'prizeshuffle': self.world.prizeshuffle, + 'showloot': self.world.showloot, 'boss_shuffle': self.world.boss_shuffle, 'enemy_shuffle': self.world.enemy_shuffle, 'enemy_health': self.world.enemy_health, @@ -3390,6 +3392,7 @@ class Spoiler(object): outfile.write('Small Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['keyshuffle'][player]) outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['bigkeyshuffle'][player]) outfile.write('Prize Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['prizeshuffle'][player]) + outfile.write('Show Value of Checks:'.ljust(line_width) + '%s\n' % self.metadata['showloot'][player]) outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player]) outfile.write('\n') outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player]) diff --git a/CLI.py b/CLI.py index f5b7bb89..09b80675 100644 --- a/CLI.py +++ b/CLI.py @@ -134,7 +134,7 @@ def parse_cli(argv, no_defaults=False): 'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle', 'flute_mode', 'bow_mode', 'take_any', 'boots_hint', 'shuffle_followers', 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'ganon_item', 'openpyramid', - 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'startinventory', + 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'showloot', 'startinventory', 'usestartinventory', 'bombbag', 'shuffleganon', 'overworld_map', 'restrict_boss_items', 'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max', 'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern', @@ -234,6 +234,7 @@ def parse_settings(): "keyshuffle": "none", "bigkeyshuffle": "none", "prizeshuffle": "none", + "showloot": "never", "keysanity": False, "door_shuffle": "vanilla", "intensity": 3, diff --git a/Dungeons.py b/Dungeons.py index 7b888f5b..a3f2e6c1 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -16,13 +16,14 @@ def create_dungeons(world, player): hc_dungeon_items = ['Map (Escape)'] at_dungeon_items = [] - if world.dropshuffle[player] == 'underworld' or world.pottery[player] in ['dungeon', 'reduced', 'clustered', 'nonempty', 'lottery']: - hc_dungeon_items.append('Compass (Escape)') - at_dungeon_items.append('Compass (Agahnims Tower)') - elif world.compassshuffle[player] == 'wild': - hc_dungeon_items.append('Compass (Escape)') - if world.keyshuffle[player] == 'wild': + if world.showloot[player] == 'compass': + if world.dropshuffle[player] == 'underworld' or world.pottery[player] in ['dungeon', 'reduced', 'clustered', 'nonempty', 'lottery']: + hc_dungeon_items.append('Compass (Escape)') at_dungeon_items.append('Compass (Agahnims Tower)') + elif world.compassshuffle[player] == 'wild': + hc_dungeon_items.append('Compass (Escape)') + if world.keyshuffle[player] == 'wild': + at_dungeon_items.append('Compass (Agahnims Tower)') ES = make_dungeon('Hyrule Castle', 1, None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], ItemFactory(hc_dungeon_items, player)) EP = make_dungeon('Eastern Palace', 2, 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player)) diff --git a/Main.py b/Main.py index 3548a399..0c447cfe 100644 --- a/Main.py +++ b/Main.py @@ -470,6 +470,7 @@ def init_world(args, fish): world.keyshuffle = args.keyshuffle.copy() world.bigkeyshuffle = args.bigkeyshuffle.copy() world.prizeshuffle = args.prizeshuffle.copy() + world.showloot = args.showloot.copy() world.bombbag = args.bombbag.copy() world.flute_mode = args.flute_mode.copy() world.bow_mode = args.bow_mode.copy() @@ -785,6 +786,7 @@ def copy_world(world): ret.keyshuffle = world.keyshuffle.copy() ret.bigkeyshuffle = world.bigkeyshuffle.copy() ret.prizeshuffle = world.prizeshuffle.copy() + ret.showloot = world.showloot.copy() ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() @@ -1012,6 +1014,7 @@ def copy_world_premature(world, player, create_flute_exits=True): ret.keyshuffle = world.keyshuffle.copy() ret.bigkeyshuffle = world.bigkeyshuffle.copy() ret.prizeshuffle = world.prizeshuffle.copy() + ret.showloot = world.showloot.copy() ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() diff --git a/Rom.py b/Rom.py index c8e7ca0a..f0a92d9a 100644 --- a/Rom.py +++ b/Rom.py @@ -1440,14 +1440,24 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): or world.dropshuffle[player] != 'none' or world.pottery[player] not in ['none', 'cave']): rom.write_byte(0x18003A, 0x01) # show key counts on map pickup - loot_show = 0x09 + loot_source = 0x09 if world.prizeshuffle[player] != 'none': - loot_show |= 0x10 + loot_source |= 0x10 if world.pottery[player] not in ['none', 'cave']: - loot_show |= 0x02 + loot_source |= 0x02 if world.dropshuffle[player] != 'none': - loot_show |= 0x04 - rom.write_byte(0x1CFF10, loot_show) + loot_source |= 0x04 + rom.write_byte(0x1CFF10, loot_source) + + if world.showloot[player] == 'never': + rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00]) + rom.write_byte(0x1CFF11, 0x00) + elif world.showloot[player] == 'compass': + rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x02, 0x01]) + rom.write_byte(0x1CFF11, 0x01) + elif world.showloot[player] == 'always': + rom.write_bytes(0x1CFF08, [0x02, 0x00, 0x00, 0x00]) + rom.write_byte(0x1CFF11, 0x00) if world.doorShuffle[player] != 'vanilla': rom.write_byte(0x1CFF00, 0x04) diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 9b26e24f..fafa2ee5 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -431,6 +431,13 @@ "wild" ] }, + "showloot": { + "choices": [ + "never", + "compass", + "always" + ] + }, "keysanity": { "action": "store_true", "type": "bool", -- 2.43.0 From bd5fd9ec56deafa83b0364477ea81c2f55be51a7 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 10 Jan 2026 14:53:58 -0600 Subject: [PATCH 16/54] Update baserom, fix freezor chest? --- Rom.py | 14 +++++++------- data/base2current.bps | Bin 149410 -> 149426 bytes 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Rom.py b/Rom.py index f0a92d9a..b37c2d5e 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '853a9c63d437833d5812e287544cd0d3' +RANDOMIZERBASEHASH = 'd07afe36de0db3b74653570ab03a18fe' class JsonRom(object): @@ -164,11 +164,12 @@ class LocalRom(object): self.create_json_patch(orig_buffer) - # verify md5 - patchedmd5 = hashlib.md5() - patchedmd5.update(self.buffer) - if RANDOMIZERBASEHASH != patchedmd5.hexdigest(): - raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.') + if not os.getenv("SKIP_BASEROM_CHECK", False): + # verify md5 + patchedmd5 = hashlib.md5() + patchedmd5.update(self.buffer) + if RANDOMIZERBASEHASH != patchedmd5.hexdigest(): + raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.') def create_json_patch(self, orig_buffer): # extend to 2MB @@ -1239,7 +1240,6 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): rom.write_bytes(0x18016E, [0x04, 0x08, 0x10]) # Set spike cave and MM spike room Cape usage rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest - rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest if world.is_pyramid_open(player): rom.initial_sram.pre_open_pyramid_hole() rom.write_byte(0x18008F, 0x01 if world.is_atgt_swapped(player) else 0x00) # AT/GT swapped diff --git a/data/base2current.bps b/data/base2current.bps index 2beb22110c27c090ac5f75ffd63e3c80dd47bee5..88d3abeedab8c51d4d989b65bf05dcf8836f13e6 100644 GIT binary patch delta 634 zcmWm3ZAcSw9Kdn!x7}?z-SmZ(m^m&oA4bhm)IF3!(K4kMTBvLoHfUjHZ^|C!f9h#l z-fri4{)?4UanxbDNPIYgh(#}o#D@w(h$6&92qc4GMCRUo_Sua?KNYk`)}p z6t1y?C+ko_Df(3PO*p5Gn(r+)unA$x5!O505Ygfm{Mib|3dh7)#RQWSshp5gw-hgt zu%R-Z7saO!Ag-K#(J!gv>czd1HjW`24yVSkDSBAF=)z?-C?`z#rVX-^l20#jNHea& zRy=Hj956QHx7$6fpwNYw7r}h93wam93BeQij}6WcmvOZn_7JD=B|FrlI#Y5H>uCyg zF-)*St{TDfcA$xi_?I0*Bvs-<*)s!2AVX6t)*)60xZA6vNGuHNbSV@?sWc?sS8hTa zMUv!z+w{6GGh>CJ#;W&sF%&NK6e559pm_57L4?VxNYYW14gm9BgI@p6(&U@@cN`uP O+6&H=vw4*-zx)S87yv>5 delta 706 zcmWm3T}V?=0KoCxvk#}!>m;nqGP{*pN@$s%n-ZEW7!`zIvX#`Zm6ha+n5pNeSDSjh zuH*G!SD8*PI=?3Qpce^aVnHZPD+!+rD#Vvoy^YHB?Z^NBk`HzBq0>mIT5K`Y%&^Kr z5E?klqCk8T3e2pjXU?DN?vnjZ#wy6$uN@2$ybrTShdJiGAeSJH*%0IuHY0IpzYM%iW4x?vh>kQ80kh55RuQCiWUqjur{>9BNxeZC?eZlb4~AZ~f?G*e-cH zy~W97;-KLvRn=5&oUJxexBkR^;ZOVOrC~nVSMQ6j@ciadDDQ6J!c`>U!5ac{K=UJu zYZbs%8-Oc8i*u_jXj$26W9~TR=e4aX6`ma~8h9YLA8-eO7r>E#4%b3rMV+U5JyHl4 z3w)^?r8fFQLEn-oe#rSf(gRuAp0mp-g?{KrT_VJV+3VPB>t+vyja%x-&m3@^iXzdu zz(l#p&0Jt_2v5#}pUf-HGOaJQeWR3BNE(wwn{2?VC6~q=w4`t|RyP-j@ao9FLAndD z^kledY@C89bex$QkDWqc-V;+E{f_LQ6ai)YHH;^E!JhVY<4!@fry9~BX!pPoNz(6O z6WduDXO5DK29Tc=Bf#}CcW{T)C9J(#Py}T?Rkoz?{}7i30$NgjWsQR&lS&dzCJZ1U z^~rrdn(n!G*Uc^rxL&ZoMAFee?@(y{-xl1s53AFx5Y3CKR4a7&C53p503#@-Or*pJ z;;56P+6b=eGa`~8YrpMkMo4V*n0c~c1PoO`{u+TxU6x^m6|;kRASUE0DS-%JuKgKO zi@cjDx4gdftu1tf1PNUK7ns-Ff Y^t;63&$Dz9=%cictMVqzm*1ZK53vv_lmGw# -- 2.43.0 From ea62a5bcb720b9d1112c5435a8e1182deb1f7b8b Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Tue, 13 Jan 2026 00:27:27 -0600 Subject: [PATCH 17/54] Update baserom, write better doors map flags --- Rom.py | 8 ++++++-- Text.py | 2 +- data/base2current.bps | Bin 149426 -> 155182 bytes 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Rom.py b/Rom.py index b37c2d5e..6344dd97 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd07afe36de0db3b74653570ab03a18fe' +RANDOMIZERBASEHASH = 'a9a84bfe3dd2a55f81f5353b11fba3e7' class JsonRom(object): @@ -1460,7 +1460,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): rom.write_byte(0x1CFF11, 0x00) if world.doorShuffle[player] != 'vanilla': - rom.write_byte(0x1CFF00, 0x04) + if world.showloot[player] == 'always': + rom.write_byte(0x1CFF01, 0x01) + else: + rom.write_byte(0x1CFF00, 0x00) + rom.write_bytes(0x1CFF01, [0x05, 0x01, 0x04]) loot_icons = 0x1CF900 if world.bombbag[player]: diff --git a/Text.py b/Text.py index 81a5a6a1..24a799d7 100644 --- a/Text.py +++ b/Text.py @@ -1780,7 +1780,7 @@ class TextTable(object): text['mastersword_pedestal_translated'] = CompressedTextMapper.convert("A test of strength: If you have 3 pendants, I'm yours.") text['telepathic_tile_spectacle_rock'] = CompressedTextMapper.convert("{NOBORDER}\n{NOBORDER}\nUse the Mirror, or the Hookshot and Hammer, to get to Tower of Hera!") text['telepathic_tile_swamp_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nDrain the floodgate to raise the water here!") - text['telepathic_tile_thieves_town_upstairs'] = CompressedTextMapper.convert("{NOBORDER}\nBlind hate's bright light.") + text['telepathic_tile_thieves_town_upstairs'] = CompressedTextMapper.convert("{NOBORDER}\nBlind hates bright light.") text['telepathic_tile_misery_mire'] = CompressedTextMapper.convert("{NOBORDER}\nLighting 4 torches will open your way forward!") text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^") text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.") diff --git a/data/base2current.bps b/data/base2current.bps index 88d3abeedab8c51d4d989b65bf05dcf8836f13e6..9028ac7ca2898fa9457098ee67a5f01960b7e896 100644 GIT binary patch delta 9217 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 -- 2.43.0 From affa2108026d348c63868835e4c19ed875f90f78 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Tue, 13 Jan 2026 00:34:45 -0600 Subject: [PATCH 18/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155182 -> 155211 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 6344dd97..6b831cce 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a9a84bfe3dd2a55f81f5353b11fba3e7' +RANDOMIZERBASEHASH = '64685e3750abaa676988d2dc3c0572c1' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9028ac7ca2898fa9457098ee67a5f01960b7e896..1e19bd9ea031772f18ee91e3eeb5077bcb0bed38 100644 GIT binary patch delta 726 zcmWkqTS!zv7@nDb&bsSrVM?JDi4a|^2#Ii?@=wl0#-*oycMTQx(IS?f7*)*Q7^TF^mPc;e zW)VBZ5~ck`Qyar9N}HI&S{Mivh;A=ZWWWt{d*bz-bg`$--olywK0E0UOQ{}VW6otU zJNd>jk`7O?E9YMrR3WFJ2eStca2Q_UuqHkI*n>WZvC&nq}nd7`nb zh2$W0R!YloIYDix<#j5@3^wrV)%@NLU&w6*TKS{)N)bq3UuJKS^&haf4An_r;5i>s z+?26UtY=gHAfgKs5_Q7_|D>{H;4}ZKW&`(;*=PI~p`pLQ1rCNiY8iT{!{UyXt}s>` qQMyL4nkLqXb$#d!7nTltkDHmJM^a)cQW!{NSZYC#AD|DR;3DD{ti2=!Ne_~eMZV;{v#v47 zGHo|^kfF~Z+On;sOcQ<3^r6hJFoc9iddTv@GJ+`5f7gc#f9^Twch1{U?~_q)f&HiIuc z7vXitrbAT*FLFqbH;U{0g6QElM*3I0jK|$gKJC8ZU;2yKhTYge@=~n;vtnT-h3s@K zySss$B`UMmq|)g)HTB=eZxR@oR0be6pO{C2iYhKMGeHKO?flzI0=~&<#3a;`P*vWL zIWnQXlW&1o@fV0XDq9Ls*2!;?xci65lYkEPejZK+P@Jd3Dgi2?2n-owiv82fg*{?1 zo)5bUq=PAl;1N+##(QN$IrxOe%{uVgbAFQ3*$gcXFe}rT$y4f40aW!XFrk{z17V0d z`9Xov^uVNDa;}zrkTt}kc~d3lF+7vD0T_f)u(PEY*AY-o@n~|ewVRo<@ZRYTFUkql z4))L^e|4Gr3Ttiw8&(x;?LwNog+fTDRss8%VYeM8*`4hyqAGi7p{Qh53FpMlVttyl zRnQu7$%xcaKP94?_cq;8Dp7TEdB~$VVVP;BEuuUaK2O`|gTq~x9x^$NxEoT*+t*|t zVUcAFG@&>XH1E-vC=Jd$q7y0<`lb*yOihy&BXr!Zu3{njT4>CSArUQH9BnAxTC_x$ zopygQ3w@?`Mo=7Q_hsN0{VN&&gpc)+1YR4%lxY2_`K*)1#nPc;C&;F*=d5;|Ze0l+ F_z$L^5_kXr -- 2.43.0 From 54e73c0b99193cbb1306da6405606f70b99f18e6 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Tue, 13 Jan 2026 09:34:46 -0600 Subject: [PATCH 19/54] Update baserom --- Rom.py | 4 ++-- data/base2current.bps | Bin 155211 -> 155466 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index 6b831cce..5657d5d9 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '64685e3750abaa676988d2dc3c0572c1' +RANDOMIZERBASEHASH = 'fa433491ad00164e0a32683918afcb0a' class JsonRom(object): @@ -1461,7 +1461,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): if world.doorShuffle[player] != 'vanilla': if world.showloot[player] == 'always': - rom.write_byte(0x1CFF01, 0x01) + rom.write_byte(0x1CFF00, 0x01) else: rom.write_byte(0x1CFF00, 0x00) rom.write_bytes(0x1CFF01, [0x05, 0x01, 0x04]) diff --git a/data/base2current.bps b/data/base2current.bps index 1e19bd9ea031772f18ee91e3eeb5077bcb0bed38..9e585b723d8c96739069060112dec5a01ceb0b21 100644 GIT binary patch delta 3897 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 QGE7uZ`d!rBiXD;v1?yqI5C8xG delta 3588 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�UOBU>r)_|*vX!xC`T5gbvxNS$VhZ$^_=~T z3rqBR8A#H<-fzQ)3BskA?h}u^pSc%E86UAIq384FNdrRx1uk!TB$Pk3tk-Qcy6R6;y42UFdr7a%?K_i3kS<+#0iz&v-zFKd5s&^7@Hyq*RvJA#te z0uH<(?j2qW)`=G7#6t^X$;L7@9(qWOZ{zkB)-PBdwO_PbEusYIP$xj=T!~ia zqiA=p6x(Wxdv)tUg(znJF%^8TF4fvDpN;-l0W_d&0ZQHg%49_*O45Fb615jqdJ)_J z*2ON|TF=JJ5kuN562R`>FE)T^5!h3K#y5fzP_iB^-UQs3A4Ncn9&Q4uk#Sr9h}P~w zip^jKSh5FYYz9t+kxbE`1r+mjXsaf~?y5&)o53~^v#q!2RUnFz(nqGg{_R&=Z2u2w C^fDv> -- 2.43.0 From 34b5dfb4e8a0088739f0c7d69df991c27384d166 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Tue, 13 Jan 2026 11:01:07 -0600 Subject: [PATCH 20/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155466 -> 155571 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 5657d5d9..eba72375 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'fa433491ad00164e0a32683918afcb0a' +RANDOMIZERBASEHASH = '3f02518fafdf959452aeacd566c8c4ec' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9e585b723d8c96739069060112dec5a01ceb0b21..2b5fca3e320334d04c14314027852f8666a94afd 100644 GIT binary patch delta 3835 zcmW+&4OkOb)}CAfh7cf%N<`E#ib{nV6$Rv9P$Qt=Ur|IG6jl+0~^|*0gH3P4|2FZaU9%&wK8j`+M#= z?>+9{2j3Ke&2Es+^$vdm#1DEB3U1N?uM$_$9FLamXh}WKI7)17yoXVW9Q^Y;dS$Z1 zS()6~Zd6t~_}!FIS?A#6D5hk-gLR}V0&lgmo|M|@4TvWpdoJZ7ce&?pz7hekm8mfN zNgHp;m=3*cLL_V|dCmSeHE!v1JO3$V7^V#WtXHmSp?l6(*sH;l( z`Bgq@LW;k@7E_$73dSg#S-!y}h4oUqaAr_vYS1gUBaSnMm`5G}fhde?&Zu!^+1A3(xeMThx{m3Ps%YeBYX4N@h7 zxe*T?{6u4Oc*3pg%huegx4M;sR1$yuB#d*}IT?o9vV@vtyVe(FA zl;1qRbRci&&CynwhJ12qXllyyJ94%jBPvS*F~R#+4s^U<&BZIw)g-WfA#`HODY%c`-M4KYWGls)kg{_CWWt{S zxyo+NFSY_j`7A<;NA`61`@8)LX}5Fb)Gp|z-DF9PchPOD+rK4V)TJmt3hY)ORg`-} zEqA7>qAaedD&<4;T{4JYzawuSv)i7Ns~WJ}hRV zFH#zI(?vEW3#F!jg`(4Fe+pQvtw5II21Z9{;i8*QsZ6%Aq3u|MEz^>NTZnTSTg2Y; z)8T+MXq_jGkGZ~?keiMHEx(k_q?mWH63ZHxlNgs{ypAy*V-Lm^tigH%Xf@=YYezqp zIN#RY426xEmUKev({NjL^pWE&n@hH(eRc8t3)evGk*HBg-o z(jZ0j?SOj1lH(|b^ph@A1Z3P;niT zj-u1B7w5h#+u*DNVZe_?7SIK}n@_aq|HF}r^6k>)UpQ4F0kO2;gP+U4t zgk+sbgu&273QZ1FkPa3skcK9~Yc`d-k&xH|Rw6s?EMxcBdYc?P9VRq8kTD%B)haq0 zFUcQhBx5Sm5on}ERuNjmg;GLF7cbvBH03>{&-5&g4Yv#Tx_G;LT(ETUs)A9>hAUlF zz9B+2>2IM$@J&7G3HSH=5?2Xfq>G1aW)t<8)iGaTonU7{)?Ke^u!>A&b=x}hD?|{T zt-KXWFRS2)%3F*#R%&-~zoJIGe&WUStXy%0S61UvRLy@lqb3-YWMCiUR@mr&G@!d| z=H+gW$|fT4TK7hDx!i^W1J?qvxpBRJxa}R0iw?4)z_&}Fjfe^JT1PQ$^FA~?y#!JV zxa`ZU<>&p~dQ8`>p+2x>YHC@9^C~s|YpA2_>`Lk|?3RgX0t>0#`U5_hXj~wE^O`5odK2vrN+MI_Qay7 zOrTERyhq$ zH{vEd|MZ^{Su%lQOYo|D{M6JrOlrj~=ZQ;qP7~&vWoz$IlMWsABogWdU8>eqgxf6- z$d9`!U`kTGWcPHuCcnQzgCT-YWnjAUgpOK)U9eq8;w-Q(Eh7q@(mN zb=*a&jm^5uf1#V4fq)MBg*wo-kn+XJEu;0B52D8^;De^%)f9p@jV|;pu=PpOvWKj;$Sgu*7H_ zZ3vXwEo+QOvmVS*e}C0QI_4%OK{hol3F_AqT5dV6)g-{b2p4#J$q)ZB;CGwP??x`N zCeLA&s@sl;lc4=KP0L}b!59`BP6*BHQiKN9g9SV04_%v!sn|x$gb{3=UJgUpi%l{Z zU?U{741LhcZq6uzjb8slpj2NSpk|`{6Gd=DQf8HHChov_Wq~rNC<`Vea0YwkQ_9P} z|0!CX4T==mZj-L=ysj*@6$25fSv&S~xhd*!!&qx4NyIA=`po(Ly^9iAxL z$JnbmT4dvCP+{B4<>efL>}>TR$kgH=EgXXm>_T1x<;m1TkIMQA%QtYW#l?nu6ZBWX zsfKd2aubN$u%(WNGn8LqDN_cqJPcC)7fS*M9v~|GQ^cw~GE`BV1naVL9@bZ=4N`kq z8~VGkQC5FGQwIU@th`h`!wfmIg&IJga(*=BUA%n1PCq!a?_3Ku;?TvPxqm z6)l|hR`*OVXd&?unrDrG+q?{&QG=BrHy7E}AU0Cf`3S&Ar2vljN|z1kDGoy8yaW0ze;w8Tr6u=~xYP7gC?2kouUQOO@e->_obQr$4yY0@y zciC;}9yY)93LPbN1mz<2X0S++aw-Wn;sZ|mJIXGskbWufz%!NM)2DKDsE zgjsZJ9KKLa8jOKMu;we%pDBQYI11^mMayrWyX3|no7w+lhBXLBmNx`*P7{zfMa$jp zG4gJZyd5nlMBi=3`PcR{Nw7QL+pdwgR5hc;v>Qc!Z!85)3EJIHh4r0v8gUL9f{J^t zg_!{zhWXL%2<@kW9po#=oL7|8seEOVPw{#Y;SC^9f6R7Kz@(!Ob+8xe#r~$psFsr8 z?DKQvY?S*OVmna$f9lWq9LuZ#WueQt*vN%;G>{7-*0G&%L}PWw5>pd6?K6usDCZ}m zxYaj>PR#pbzd-nSxkxi8_PpQ*Tf7o9d(oFhIITMXZ3shQc_3!_k;F$-kL9Df)p}ZJ zv0S0Q=TPj=O}F)g#Pd{WWeb01Bdhj7>NfZ8`)Ge2*qDF3TmwIm7;^0f@|e9x>??zx zSx#1JV7Ee}^~FfM0cFru#?69M3t9t__Lzr>qQ$mO$D1cS&6P`NCcmz;Pt2OB`zUV@ z^5%i<^Gk}CL8=zt1!YNublE{R6*A(o{MQ}aC0qV$q{#BnCoslD&LoL6Y?*1obruuT*aC0YbOtco?aeGrHKunlNHY7$zq9dw4pq}^jf76(Au zB@#{^?|Zx*NJXG%FB;zg)F7!Ct=b75gR~P!z6;C+i%;~$?*cPKVEKl=thazDSn_%2 LNb=a}56=8QvB#)E delta 3692 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 qTm}Dxl Date: Tue, 13 Jan 2026 18:58:30 -0600 Subject: [PATCH 21/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155571 -> 155636 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index eba72375..0135079e 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '3f02518fafdf959452aeacd566c8c4ec' +RANDOMIZERBASEHASH = '3454beba5a9ca42fd3a0731afe860176' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2b5fca3e320334d04c14314027852f8666a94afd..24259c6204bb9e5025360f320e4473cfce1e1120 100644 GIT binary patch delta 3513 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 delta 3552 zcmW+&4_Fgdwx78Kj4?p`OQe8f5EX$M6y>iF3)Kjy_!mXA(SjdJ{kyGJwC>gK?xv!zu5PkuUOU=^&K28g(pG}!spOzQ4NN84d{^ozK`6!q?QJI$4 zpO#04O=N#<7E}u?!WBZ{TIQ~Zog#+i63_ge5Yl|uU7`BCK?t9a;U}=w9Ph4xF{&0$ zXf(@Uz04t=9x#|2t5sXkrPV-7R-x}!gEaC1QYHh9K18cpbwMa&Lduw+hUlHW&E+FS zcX|j#*X2)kJ*yX=I)#a*me8czy-Qc!uD1=T25bVCYWxxYuh0~v5Dgfl3h^9<5QSKU zL7_mIAE2u)VoJb1GO}wQ1-oxSZ?KE}#V{bV090@&6Qa;V$&iJ5+yk6StlL~~yDJr&4dkn;;8zq$U? z*cfg)L}H-Rr<>TS`i34C4fMF#KtD7at^!6P60Mz#ls_%iz=0G-&J5Y4RC}#9Wy1fp zG9~)Bv?`JwafpF8{C@kGC)B;JaDPC589?2rwnW(EI_lYlM^jUt-%#@qN&yLyPtNlR zXfOq2FJyZKpHB6=^Fm2b31|fb(uSl$>)CUukecJL%%<{Cd@6|0CwKd!0y+p`Wj6{V zvtV^s320H3PQE$du29HrL5~38nMwVl7Rv8f)$R%^zV=1H;NT0SnwACGM*)Q8DQ6k> zO8Tb385FX>Agakk{odl!jaVaVYCdhld1Pr3%^S11T z+!2We(heQ~4g4pdRyZvA=(|)9rgS*?L-YCo15 z^vJK^{tMhOgX8qlFHAUj0nSZ^YM)Jpj#qKp^7cZzc>B75W8{?$5a!{lV`K0oPL=py zXkNiy$mR?XUL`UP+rJMse;B9_H=hdBi@&`tK!ttO*(ZE=T_|c(6TE+2X6P>emVs+E z`E<+>eLq5VO!EX%{6(nn;|FFa_2Y_* zkT|PT2gVWs6S`O;bYev7vk_i-nm07fJ4?)R;gv-SOPLslr9@0}{gQqiQmt!3>y9Nr z0Spcbw|a39!dSMBtq1oeDiRFy! zNsMtAdodpjEGVA!OwW)gazj^AWpHujj$u_ZvS7dCTR z$R5N~w&1B{7`I{Uz_K&HUqfe>%t z(2(LM-6&-Xk5zaA+?39__H;6w4&9X4j2bcl6(tK!fmiKnZ4)822P7f~<0|8J+pjk} z1tvsnL0@Nrr6tO)rVEP4I_ap|d=Q!#(ng|Hd@wDhcMFP5kEXouS8F_rVnZF`!*0Pb zG$vZR1@-0;Ow)<(3g06_{nBq?NceU&jnt_pb)xSmXBH zC+#1QZYIcv0^ci!b|NOkYa78wgy2K-GK(R-fX}|jS%2QwgXU;J3W*6t10tpA_Ui3~ z$+``l)PN;H8L@Bp-Lc530opmc_K~oDtnI@<`*UvPRdf4GI}w2XtpVZSU^AM(7A)3J zU-3|wnmUWAs;IS+xNz?jVYykh`XT+&X`r8lLBoJs-L`_jDG11qZxAs9s3*DIoo}dD zml*JfAkCHsBELm~64b38QM~&L%T}&B{_x3UE@)=j_Tu)0#-BTWwz%&Gl4M zsr6{JiRL>EdfJ5yboHcxucF(zwHMj^3-zOFZogp%bcpgk!6Clv6FdR=?gmC)66{t} zJ8MSOV`F|RPR@ueSb1nJP7?OZ_bAl6-L2*~pl89jP%(p!sx2Cu?2)8TDz;n~uxBeA zxy82K(1i;_sW)5~uxry?E&fI&%6O;Q9_E0B;6N@K&jAV1*BHXiGo)Q$K)HPn zpO^DK~KbW@*%e4p->|ZcCk=;;QqC@lTM6xf89p7uSya6}Z~m4Cgs29ZdX z3sj1d^uN(X2%Lfr|RBhFAa-(j%8RoWXbL=}zjkbN*{u=2E@3E2e~MlJEvl zr>=3`G%y>O_dB_B^%B47TU1L+@g?kYZ(hz|BBb$VZn)EiI+?PdI2NVlR@5b2M4*l-SKzvBdnupwsMFEg;lj6x^{Z-q5j0A;yP~CQ*1t~@7+wI_6u;v81y#u@j f7MOaEK0W>agY6nJ -- 2.43.0 From 30e85c125691a638ded57548581fa2d7581fa1da Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Tue, 13 Jan 2026 19:45:10 -0600 Subject: [PATCH 22/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155636 -> 155636 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 0135079e..a3d3d41b 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '3454beba5a9ca42fd3a0731afe860176' +RANDOMIZERBASEHASH = 'e1606cf66a3d270d7a7f1002bff99458' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 24259c6204bb9e5025360f320e4473cfce1e1120..04e01a38bb2b8458cdc7b7f3014ef440895fbfed 100644 GIT binary patch delta 55 zcmV-70LcIJzX|le39x|!1T3S|T!V!JhlK+Hw}k@&zfcUY(9r(_Fi-#}{{RTLP*eh( N3kXp;?IrPBk`IO&6}$id delta 55 zcmV-70LcIJzX|le39x|!1pJ``UW0`LhlK+Hw}k@&zfcSSFu2$Q(EqsD{{;)TP*eh( N3kZ#{(e{99{+FLk80G)~ -- 2.43.0 From 5f66483d989ad16a302b320e36dcc4f1ef4fa65f Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Wed, 14 Jan 2026 11:33:53 -0600 Subject: [PATCH 23/54] Update baserom --- Rom.py | 2 +- Text.py | 2 +- data/base2current.bps | Bin 155636 -> 155700 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index a3d3d41b..10564ae5 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'e1606cf66a3d270d7a7f1002bff99458' +RANDOMIZERBASEHASH = '242a1d04cce10fe8cf336848bb4c8bc2' class JsonRom(object): diff --git a/Text.py b/Text.py index 24a799d7..00d9bb6b 100644 --- a/Text.py +++ b/Text.py @@ -2014,7 +2014,7 @@ class TextTable(object): text['thief_desert_rupee_cave'] = CompressedTextMapper.convert("So you, like, busted down my door, and are being a jerk by talking to me? Normally I would be angry and make you pay for it, but I bet you're just going to break all my pots and steal my 50 rupees.") text['thief_ice_rupee_cave'] = CompressedTextMapper.convert("I'm a rupee pot farmer. One day I will take over the world with my skillz. Have you met my brother in the desert? He's way richer than I am.") text['telepathic_tile_south_east_darkworld_cave'] = CompressedTextMapper.convert("~~ dev cave ~~\n no farming\n required") - text['cukeman'] = CompressedTextMapper.convert("Did you hear that Veetorp beat ajneb174 in a 1 on 1 race at AGDQ?") + text['cukeman'] = CompressedTextMapper.convert("Trans rights!") text['cukeman_2'] = CompressedTextMapper.convert("You found Shabadoo, huh?\nNiiiiice.") text['potion_shop_no_cash'] = CompressedTextMapper.convert("Yo! I'm not running a charity here.") text['kakariko_powdered_chicken'] = CompressedTextMapper.convert("Smallhacker…\n\n\nWas hiding, you found me!\n\n\nOkay, you can leave now.") diff --git a/data/base2current.bps b/data/base2current.bps index 04e01a38bb2b8458cdc7b7f3014ef440895fbfed..e117aca7e2c56fbda6a5edb0f3f4ddcb76d6d133 100644 GIT binary patch delta 3315 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 delta 3332 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 MexLAYL*1DF1B0%Vga7~l -- 2.43.0 From e8bc0d81c4192d9e64794b9cc982d760c0cf947a Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Wed, 14 Jan 2026 13:10:48 -0600 Subject: [PATCH 24/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155700 -> 155699 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 10564ae5..b8fdbc03 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '242a1d04cce10fe8cf336848bb4c8bc2' +RANDOMIZERBASEHASH = '6b2304260300f9c3b45a96f127710a5e' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index e117aca7e2c56fbda6a5edb0f3f4ddcb76d6d133..2a760a042f1345e7c5798ceb69d142746564da0c 100644 GIT binary patch delta 2962 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 R834i3!}GKDwPidE{vW2a`s4rr delta 3034 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 -- 2.43.0 From 2ce245c430d16c4bd8893c8f200744ac2a503793 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Wed, 14 Jan 2026 18:23:10 -0600 Subject: [PATCH 25/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155699 -> 155711 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index b8fdbc03..8b1a2eac 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '6b2304260300f9c3b45a96f127710a5e' +RANDOMIZERBASEHASH = 'c52bcbab18e5840e93a57c3e5430467c' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2a760a042f1345e7c5798ceb69d142746564da0c..43ac9a11ea3f40422b2bbffe8a2e9851eafa690c 100644 GIT binary patch delta 142 zcmdmdfOG!=&JB&s%<5e?np>FLTbLQQw=gqpj!K!FoMYHDG zuwgDYFB=;hGdt^aRR^7hUN%-%)@dm^hbKu(K51lI?W^9h5~LBRgbhecuE}ed&RW_q k70BjhVw&FH$dOw036dO8vpb z%FPQDV`gV%Vw&9F$;!$)Ek)<>?0O59hUNKsYi65e7&bJrP3CCmWMX2P9-431FcoM9 gH;~=m$ Date: Thu, 15 Jan 2026 13:47:20 -0600 Subject: [PATCH 26/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155726 -> 155821 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 04971caa..70468a34 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '9b4cee0b02c689b6201036789bb617a6' +RANDOMIZERBASEHASH = 'd3b7765968938ed6de29a9c89a1764b8' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2822c06bbf5c7539df1bb9ab291af45d439a0e1d..198e242e5d649225a7ecfb4606139ad065d6ac73 100644 GIT binary patch delta 411 zcmV;M0c8HpzzMCv39ys_0o=2d0qg+;UvZ$0gM|Z!g#!V%g#!Zj7Xk@^mwp=pCQAee zN5D*}jRt2XKg!sVx*#6A^)c&*pfIv7TGAc?# z7yt$w01f~L00WF804V@PfB+`|NteSL0*XBufDeS|0T2TM4hTOVe>s0Qe>OiE9}f>A z023faNJ%CT4*>qO{(Ss+mNq_vQG-~j&smtPzLhy-S4iXoTl90Do_ z00e{F0)K4dgEXL;nB)2KkpOA+)zw9Rg$m1wS;AVHvl;9|FAx4tWxZnhz?7 zz78sguRj>Kizfn6HUW8;-CY7PHqI%}Dc&jHDd;KaY4|DlqkdT9{m3cEY1k>*DeWok zY5ghvY0N3jDcmXCX~`|gY00U{?Vo^`KVAYX83+ZJB|t2InFa*~1p*2OpL%$vfd;Er zA*`2$UIHN&mk?IzvvL^6zjs>hw<4FmF=dF8H@dgFUIGdM17;wCm&acMe+U=vy$N1i F@c75MVIdz0*Vr?4}|Ce0s{gLi0=U8lQ^Oo zgO|1(0*C}CCXX4HLLCAs1px#Ph)9=n9Re^7@G;N=1OEU9`IiemjJL2I0%QUOA2*Q^ z8@CxC0=)+gQ4@)p4=RYh4l0PRXBW5RCjwD60a=$eUIH;O=qc!F_$m0Keput($SKHa z*eTg5%qh(&+$r2??J4bP{VDxvpWvOzEy-!gsmbl1@t2)m0xVAl1(zj2EP#y$1qB6` zWGusy8yVz*2CGdcgsBD#3kwDY1_lcT29tblfR_bzfRzgd1`7fLmyd}L4i3s{LW;h4 pS>L`j7}T}^AJvmualyA4UjhmN13P`umnL8We+a!L?>l|U{GcOAd!7IQ -- 2.43.0 From f5d5860af0af5d697cefd61b206560ef55e05995 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Thu, 15 Jan 2026 13:52:41 -0600 Subject: [PATCH 27/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155821 -> 155811 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 70468a34..43b6f35e 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd3b7765968938ed6de29a9c89a1764b8' +RANDOMIZERBASEHASH = 'faf71172e92408b787b0fe72286192d9' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 198e242e5d649225a7ecfb4606139ad065d6ac73..ca5ab6ececc0ddc5f753b8e19cd562bddb60a1f5 100644 GIT binary patch delta 246 zcmV6RFs$58v>L> zY_g37i*y2(J7I|lfDeS|0S*HK4hTORKNmk1KN%kn49v2mk;8 delta 256 zcmV+b0ssD^!3nLw39ys_0o=2d0qg+;UvZ$0gM|Z!g#!V%g#!Zj7Xk@^mwp=pCN%^I zN5D*}jRt2XKg!sVx*#6A^)c&*pfIv7TGAc@! z)EfenNjE}(jRlKz0+u^ri5Y+ogy;bf0|E{RKOcWNe>Zq zw3ntG0+a#=1h+gM0?q*hKQxhHw+ Date: Thu, 15 Jan 2026 19:03:51 -0600 Subject: [PATCH 28/54] Tweak loot/map values slightly --- Rom.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Rom.py b/Rom.py index 43b6f35e..9f76c32b 100644 --- a/Rom.py +++ b/Rom.py @@ -1453,18 +1453,14 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00]) rom.write_byte(0x1CFF11, 0x00) elif world.showloot[player] == 'compass': - rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x02, 0x01]) + rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x02, 0x00]) rom.write_byte(0x1CFF11, 0x01) elif world.showloot[player] == 'always': rom.write_bytes(0x1CFF08, [0x02, 0x00, 0x00, 0x00]) rom.write_byte(0x1CFF11, 0x00) if world.doorShuffle[player] != 'vanilla': - if world.showloot[player] == 'always': - rom.write_byte(0x1CFF00, 0x01) - else: - rom.write_byte(0x1CFF00, 0x00) - rom.write_bytes(0x1CFF01, [0x05, 0x01, 0x04]) + rom.write_bytes(0x1CFF00, [0x01, 0x05, 0x00, 0x04]) loot_icons = 0x1CF900 if world.bombbag[player]: -- 2.43.0 From bfd791fc8784e15be13f73b5fb9e2f8fa4de9d97 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Fri, 16 Jan 2026 12:28:40 -0600 Subject: [PATCH 29/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155811 -> 156288 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 9f76c32b..fb91528f 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'faf71172e92408b787b0fe72286192d9' +RANDOMIZERBASEHASH = 'a2c07b8d2b0dc7050102472e28469dfa' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index ca5ab6ececc0ddc5f753b8e19cd562bddb60a1f5..e9c7e85afb368142ba77e104c76308b8a5a2db2c 100644 GIT binary patch delta 3819 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 M{+_zy%Udr0AK-sar2qf` delta 3315 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 -- 2.43.0 From e058fd1961713963c881e7b435a6d0fe5078309b Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Fri, 16 Jan 2026 14:38:16 -0600 Subject: [PATCH 30/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 156288 -> 156284 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index fb91528f..d79f7939 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a2c07b8d2b0dc7050102472e28469dfa' +RANDOMIZERBASEHASH = 'deecff935f83b9050e7b9ef86231d607' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index e9c7e85afb368142ba77e104c76308b8a5a2db2c..7df194c7c969747f607156fb9d194c63db0b3fa6 100644 GIT binary patch delta 2502 zcmWlZ4OA0X7Jz470)`NN6cJ2C#sFFc&=zT`ti^J)-D>S=ZONP9 zPy&s~@PG%V8dM@C0TN_eI(56FoMl(g*3@p#>2gj_tyPLz+ib1d65GSR%sF$vJ9qB; zyYJo$ry_p)M}%#LJ~npw10cOMrQ9;kNgiz8@Qq!-kM0=AYvn!ld4qzVS2YX^cP^M! zy~EypIcEngs++??9cxkjI4oqceEnhM$xWrlkw4cG`!g08h~CU?vmf<+6|8>*?aO0h z3Y>zYa48I+>;!ncUXOmy%Uru{Soo0bxWaba>`}dcN`MmUJOAcYS%boz>^5HIate3m zE%igFI)4XUhfe3Op_SuP`L9LM($?I{iQGyWexH_%1?62idBO&)nUgIrO%+5!pH&Wf z!{2XYH{d{&X zT<9JllW|~>5^VUy7ElwncZ?X$iqr|5U%C?t93@oXuw0P5%IdK_^{f*l?v1D9ATDy{xBz9Y8&O*E zIsA1l7>#?+C%{VOxO@uzeLBex{X9)j_I@q(9^C3%3 z?0{yw6jq^5K9g`Y;Y)-J-c$gt)gJbRVySSF zzzWSiw72UxxsMk^#$)wwefL>{FM^77P?WJF@y`nPrAz;ej=gKRtnX$Ih^C$}ii;MK zufA)2eemO{0l$Q4;F-=|hUsFy#tnslrGxl-A$Vd*a9H4?#fLbl2o&l1Muga^>BYcq zbCEwaJ;p7jjtcIXdGWUqL0vsda(4sCl4(kPFJ$3p_y;rNj|us$A0-(fW{e6DwH#-2 zkcrR6t|G80tg~BCeT%;>0y%UGPAUeuaidrW;$;Q(kWIE%A4QIb;aOy9B zr$1`e3EW~h{;mW(X6&)ctgL;=#450fHQzVc+t|}6-p1>0_S{gTG}BYiE$$r?++xK! z!7tIR#+;%tYEsSY?7X3#pAT8dd1swbB(KT2$%?`0m_W^>+P)8e6Gd)-v3hQ(ZADJ` zwA3dPAD$D^q63e+E9#xkKre}DOrr7Yb3#8Q^FACF5{=jKz#qXHgLPa$HD0tKDhs~v zr<-Wr@d}ND1 z%tbASaj4523nNk6aRrpPC>f`~>&8)SVJ++rgvwi`?Y+n@$I=6}@Do{+Q&CP`fJseZ z3YgdwLCN4UwDBW0fHZi;R#2A^dBtk#dUfN~+l@fWD2~m6IncC)QDAN>SVvdmk*y#* zvDcoy7&8^^|KSEBUJMH7wOVsg;5pABys#By(7SPJ86Yhfmz9C!^+L0E*`nZ&^8z^J zSGs`x<=3wD2pnj3P1sYaV<4(3-wpYBj&cpyc@nPPGO&x5O)QiFKrcBg0k9Chf`JyO z=p8ss3ySGP{Gt~8O4ngSIZ& zL-cg{?ZUimt`O zI*_zP@wNtjq1%rAI-sme8M6eUypdRX?qswLaM2?QsoPWjcQ(S)u;8g(VC7!Jf-81W zFw;~(!hAl2hWkNCyKojA?U#nM92Yv;BMWH^wy?2Q%(b0GhjGbvkf$E;%!S*oi&UT` zP3r$r*nc}zN&y%A#NeDsrvi7U8OlZ*aP*=@dMda`wmZ5VlxD8Y|BUrH-s{?E=EMO< zH}{hrAE4mz^JYrsza^eRN*bakB@K{0Z_mK1tH3s0`pX9RzO19d-N9V;_@u!m_%}!9 z0RtRKG#GCbtM1>>uBng#R zqX#e1+wo~V$>a=tOAj_FDi8jQJuR;ZPl3l;(ru?VV^a-yfj)$9 z)_|F)=S%*DB2y)ho21446X%}-%V<&+pFT}0rV4MU1z*w4IHryyk$xhx4s53B>WRi@ R!14%LbM3DS8+Y~@{|`(IG-v<- delta 2530 zcmW-i4OA0X7RP690)+4(0xBZP5J5$8H@2eT`$M37q|o9AYAHDJ)-oNN{B&(r&?h=zMj#@ZZdoRa^SRKeCP2*~af$Rf88qBr~7*E3ZoK7H@An&a3Qp z@%D_Vx=X0Y+DdN|y0Q}J#Y3Z6Z-&v-(TuX;j4~SCNm_=**jXjH0y@koBMm4?^*|8M znw6+k>68wQ8q8-ol@m{H1_QkU*J_|HYE8d5+t$8dw3Znj+YCAVep^0C$}_+%P97NQ>#ljkTucb!>^N7H~W zzU>zMI@Jd!#Ja#b=l}|9!qbrLH7*S?2V9mYro^ZYpAMWTwu91HZ`(7{;Gdb9hLaIr zOmqi|mVPoB2i=r-3b&`jwy3>>q@!1&+HqFFvqa4zwncVk@!lr4@L636D|e9BSE{AuUR47z)PqNMHk;|z!jSu`Xfh2vIO zu~db>$$){VvmOyeNN*9Vl#UTAmrS@L6Bg0o_=8M1nbP1cp(4z$fL=sGF3Z10gh6QJ zUne|9I6!!u&_j3<@5_RC{lx+EF}{wpdxc`ezd(eOIMfsN5q1*}5MCto2#sv-wJgL^ z!&{M&vK6>?BQ{-_=AE=&%oM)k`v|j%^KHUh!aIcdLIBIJC8G<3CN`z#u4}bnC=|6) zHUp*iTMrx7vynm$%iks*(L&%+{tgj~1^rQetxPY*2u*wnVJzW3!Z@6o4WCyX^32CF z)J_5`zUUENYCcc$Q9IvxuKMloZ$^27sR$cI=^JDAhB~ia{Y!YntnON63;U{MXbqsa zaB%?EU;0IL#RRF{4WvrODD~a>9*#!8F*4o-^M30FNJU7i21qs< z&aq8hscq&x4FbPAvLyWOg-TU%<%<33Z`%E1^# zsdJdxCU4k;9h?&2seD+M%UdZkYwakx70$CVLNh4dk00Q zRP>(cm1$!!7g`rKqGq0Lx}~0(k&5tBTOeV5lk1k+l51Cv$vq0`;d^3IxbHD%X|;V9 za+A=-=)ZbTY@-zJhx7U$xSb5qH4TY^)-5E5tw-;B>HT(9DalwY2X+Q$l0Ku{{x9Jq zA2>51o$C46J~l`BGS>%EKDBwo{JVZ0JV}yCi0*HT9Rt;jq>yO{~ zp$>`}#kpyihWd0yfsYo#YPt-&3Q1C%@nj(^reDDi3t_GP8LbB0jd@8Cb07*dQ!{O} z!tr<;C>$%>WQu93-pKqINjzA25Nlu~ek4iNqa1X8M15FyCD<2n=}ndY?tXXVoal{m z1M2a{I)3FShn1rpA_w~&L)IgOwMZx`sYU#E-nNg_8)!Uvwv36`siU3YB#&T&&Wi!En4y?@w&7YsVv3#Uobf-ucK8F((>n$|qxP^ay=zFt0xB6;8Lw=T)jh zINhq4S8>?HMwl^Y=oQ|;*-t{I+TofGv`k8ruOUh9{Zf482XbtfI}Y@z&OV+@`DVu$ z%0laK;G9W*!9Pcq>wFRlQdVT$WIeWbn;$oFQirXD`^k#;Q|SCyp>*(!xvH~vBFnr=EsGv7Iw-T9oa}BW-E0Md1a7iLE zFHS`6v*xL;cdZul>O^GQk%)Sd5a!KC5^zu@sme&au@d&th1ga}N?V1$t%TIjEeC(b zO6Ty}(w}kIuxcw*(n@XMN_4Iv+0yk}+^`LvCx>-%8;pll<$ofCB+3vsLQ5|U4{wJ^ wnjDky9k7Qk!t1NxYq}PP>?B20I=p5lY^LewhIP9jI#}`Ub1&MCZ0fo6Kbqw_I{*Lx -- 2.43.0 From 6c8a8e18e00813b38719e1af7bb806e021b89a80 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Fri, 16 Jan 2026 15:47:53 -0600 Subject: [PATCH 31/54] Add --tries arg --- CLI.py | 2 ++ DungeonRandomizer.py | 50 ++++++++++++++++++++------------- Rom.py | 4 +-- data/base2current.bps | Bin 156284 -> 156289 bytes resources/app/cli/lang/en.json | 5 ++++ 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/CLI.py b/CLI.py index 09b80675..0fc8e6a9 100644 --- a/CLI.py +++ b/CLI.py @@ -88,6 +88,7 @@ def parse_cli(argv, no_defaults=False): parser.add_argument('--seed', default=defval(int(settings["seed"]) if settings["seed"] != "" and settings["seed"] is not None else None), help="\n".join(fish.translate("cli", "help", "seed")), type=int) parser.add_argument('--count', default=defval(int(settings["count"]) if settings["count"] != "" and settings["count"] is not None else 1), help="\n".join(fish.translate("cli", "help", "count")), type=int) + parser.add_argument('--tries', default=defval(int(settings["tries"]) if settings["tries"] != "" and settings["tries"] is not None else 1), help="\n".join(fish.translate("cli", "help", "tries")), type=int) parser.add_argument('--customitemarray', default={}, help=argparse.SUPPRESS) # included for backwards compatibility @@ -294,6 +295,7 @@ def parse_settings(): "seed": "", "count": 1, + "tries": 1, "startinventory": "", 'beemizer': '0', "remote_items": False, diff --git a/DungeonRandomizer.py b/DungeonRandomizer.py index 94b83faf..06fec596 100755 --- a/DungeonRandomizer.py +++ b/DungeonRandomizer.py @@ -61,29 +61,41 @@ def start(): if args.gui: from Gui import guiMain guiMain(args) - elif args.count is not None and args.count > 1: + else: + count = args.count or 1 + tries = args.tries or 1 random.seed(None) seed = args.seed or random.randint(0, 999999999) failures = [] + attempts = 0 logger = logging.getLogger('') - for _ in range(args.count): - try: - main(seed=seed, args=args, fish=fish) - logger.info('%s %s', fish.translate("cli","cli","finished.run"), _+1) - except (FillError, EnemizerError, Exception, RuntimeError) as err: - failures.append((err, seed)) - logger.warning('%s: %s', fish.translate("cli","cli","generation.failed"), err) - seed = random.randint(0, 999999999) - for fail in failures: - logger.info('%s\tseed failed with: %s', fail[1], fail[0]) - fail_rate = 100 * len(failures) / args.count - success_rate = 100 * (args.count - len(failures)) / args.count - fail_rate = str(fail_rate).split('.') - success_rate = str(success_rate).split('.') - logger.info('Generation fail rate: ' + str(fail_rate[0] ).rjust(3, " ") + '.' + str(fail_rate[1] ).ljust(6, '0') + '%') - logger.info('Generation success rate: ' + str(success_rate[0]).rjust(3, " ") + '.' + str(success_rate[1]).ljust(6, '0') + '%') - else: - main(seed=args.seed, args=args, fish=fish) + for seednum in range(count): + for trynum in range(tries): + try: + attempts += 1 + main(seed=seed, args=args, fish=fish) + logger.info('%s %s', fish.translate("cli","cli","finished.run"), seednum + 1) + logger.info('') + seed = random.randint(0, 999999999) + break + except (FillError, EnemizerError, Exception, RuntimeError) as err: + failures.append((err, seed)) + logger.warning('%s: %s', fish.translate("cli","cli","generation.failed"), err) + logger.info('') + seed = random.randint(0, 999999999) + + if count > 1 or tries > 1: + for fail in failures: + logger.info('seed %9s failed with: %s', fail[1], fail[0]) + if len(failures) > 0: + logger.info('') + fail_rate = 100 * len(failures) / attempts + success_rate = 100 * (attempts - len(failures)) / attempts + logger.info('Generation failure rate: %6.2f%%', fail_rate) + logger.info('Generation success rate: %6.2f%%', success_rate) + + if len(failures) == attempts: + sys.exit(1) if __name__ == '__main__': diff --git a/Rom.py b/Rom.py index d79f7939..d62db40d 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'deecff935f83b9050e7b9ef86231d607' +RANDOMIZERBASEHASH = '1fb7cd3e386f1c48d4abc7cf12990197' class JsonRom(object): @@ -3162,7 +3162,7 @@ ConnectorEntrances = {'Elder House (East)': 'Elder House', 'Hookshot Cave': 'The rock on dark DM', 'Two Brothers House (West)': 'The door near the race game', 'Old Man Cave (East)': 'The SW-most cave on west DM', - 'Old Man House (Bottom)': 'A cave with a door on west DM', + 'Old Man House (Bottom)': 'A cave with a doorframe on west DM', 'Old Man House (Top)': 'The eastmost cave on west DM', 'Death Mountain Return Cave (East)': 'The westmost cave on west DM', 'Spectacle Rock Cave Peak': 'The highest cave on west DM', diff --git a/data/base2current.bps b/data/base2current.bps index 7df194c7c969747f607156fb9d194c63db0b3fa6..1d15d310fbcfef95dc59619ae3e154f92bc4edf5 100644 GIT binary patch delta 503 zcmWlSPe@cj9LHzgZ|3c8X^2QhS{j5H2ze+kSqKS1e{CsSy|_el5{d}SQ!{TJ^JVLE z8S=5c4#C5emTIv!gA$@$kyV6wR+GabMFbK_KtyIr&WIFH5h{;y$QD<<8N^aK!iY8Ub}N2ITC+u;_y|G zjhWmuP zAl+AajtI8N2sW;lG81fyS-M`_PTnJ3NP{M+xE-W3lssU0UE`$Z*i$wWNqJk9TVjG1QSWrd!+k?ebda5-@Vm^w&Tl)Hda-ehYiNK_oGkQ+&d*ycL;Cf}RMyJlYJa6vf=-=HnS(!q`j9Ndpc;^^K{trj#%M%9S4Z-C?Gr-2B8u(UdLAHDat4qXzH zAsz8y+5_RVWS2Wg0tp}uzJMC7!vZYAiWkkPPIIFB^q4zzrC)qNLJb}Wg>~^8tm)iO z_zmmeCAG8=RQ^!_15N+$b~Uq&%snXe%7y? zk8$@x%80@sJMR`#Mq6ft*=k|@CcDiHwMCTDcgaDdUPM|v;1$LxDYM5aY!)hPmOX&1 z(`woCY-I-I^N!tV`Wf{im`bDSl=c_)T`^PsaF*v{N0tx+7;e#j8_eL&FN<*}F05$T zNeXp2XK&&W6&o$|ZRI<-vt8I_G~A2%I-yOv(#?B#jrQs}z};TyCB!{V6MR6ElscN7 fG%8qpg&QUkXWquEXHOVyq2SQ*^*>#w?qvP}^Rdn- diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index e5093801..c8b427b6 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -352,6 +352,11 @@ "--seed given will produce the same %(default)s (different) rom(s) each", "time)." ], + "tries": [ + "Use to attempt multiple times to succeed at generating a seed.", + "If --seed is provided, it will be used for the first seed, then", + "used to derive the next seed, until one succeeds." + ], "fastmenu": [ "Select the rate at which the menu opens and closes. (default: %(default)s)" ], -- 2.43.0 From dd98e55d36390334dcd8ebd12b68dc26dc08cfe0 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Fri, 16 Jan 2026 17:55:45 -0600 Subject: [PATCH 32/54] Move dungeon balancing message to debug level --- DungeonGenerator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DungeonGenerator.py b/DungeonGenerator.py index 3306b71d..59d683a4 100644 --- a/DungeonGenerator.py +++ b/DungeonGenerator.py @@ -2330,7 +2330,7 @@ def parallel_full_neutralization(dungeon_map, polarized_sectors, global_pole): increment_depth = True current_depth = last_depth + 1 if increment_depth else last_depth finished = all([(x.polarity()+sum_polarity(solution_list[x])).is_neutral() for x in builders]) - logging.getLogger('').info(f'-Balanced solution found in {time.process_time()-start}') + logging.getLogger('').debug(f'-Balanced solution found in {time.process_time()-start}') for builder, sectors in solution_list.items(): for sector in sectors: assign_sector(sector, builder, polarized_sectors, global_pole) -- 2.43.0 From 5e0deadf55c355e2df7b94d6c65373c7d72f54cc Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 17 Jan 2026 12:54:17 -0600 Subject: [PATCH 33/54] showmap option --- BaseClasses.py | 3 +++ CLI.py | 3 ++- Main.py | 3 +++ Rom.py | 11 +++++++++-- resources/app/cli/args.json | 8 ++++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index e2fcee45..ddf1284a 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -150,6 +150,7 @@ class World(object): set_player_attr('bigkeyshuffle', 'none') set_player_attr('prizeshuffle', 'none') set_player_attr('showloot', 'never') + set_player_attr('showmap', 'map') set_player_attr('restrict_boss_items', 'none') set_player_attr('bombbag', False) set_player_attr('flute_mode', 'normal') @@ -3128,6 +3129,7 @@ class Spoiler(object): 'bigkeyshuffle': self.world.bigkeyshuffle, 'prizeshuffle': self.world.prizeshuffle, 'showloot': self.world.showloot, + 'showmap': self.world.showmap, 'boss_shuffle': self.world.boss_shuffle, 'enemy_shuffle': self.world.enemy_shuffle, 'enemy_health': self.world.enemy_health, @@ -3393,6 +3395,7 @@ class Spoiler(object): outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['bigkeyshuffle'][player]) outfile.write('Prize Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['prizeshuffle'][player]) outfile.write('Show Value of Checks:'.ljust(line_width) + '%s\n' % self.metadata['showloot'][player]) + outfile.write('Show Map:'.ljust(line_width) + '%s\n' % self.metadata['showmap'][player]) outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player]) outfile.write('\n') outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player]) diff --git a/CLI.py b/CLI.py index 0fc8e6a9..b2ef18a1 100644 --- a/CLI.py +++ b/CLI.py @@ -135,7 +135,7 @@ def parse_cli(argv, no_defaults=False): 'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle', 'flute_mode', 'bow_mode', 'take_any', 'boots_hint', 'shuffle_followers', 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'ganon_item', 'openpyramid', - 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'showloot', 'startinventory', + 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'showloot', 'showmap', 'startinventory', 'usestartinventory', 'bombbag', 'shuffleganon', 'overworld_map', 'restrict_boss_items', 'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max', 'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern', @@ -236,6 +236,7 @@ def parse_settings(): "bigkeyshuffle": "none", "prizeshuffle": "none", "showloot": "never", + "showmap": "map", "keysanity": False, "door_shuffle": "vanilla", "intensity": 3, diff --git a/Main.py b/Main.py index 0c447cfe..29b7e53b 100644 --- a/Main.py +++ b/Main.py @@ -471,6 +471,7 @@ def init_world(args, fish): world.bigkeyshuffle = args.bigkeyshuffle.copy() world.prizeshuffle = args.prizeshuffle.copy() world.showloot = args.showloot.copy() + world.showmap = args.showmap.copy() world.bombbag = args.bombbag.copy() world.flute_mode = args.flute_mode.copy() world.bow_mode = args.bow_mode.copy() @@ -787,6 +788,7 @@ def copy_world(world): ret.bigkeyshuffle = world.bigkeyshuffle.copy() ret.prizeshuffle = world.prizeshuffle.copy() ret.showloot = world.showloot.copy() + ret.showmap = world.showmap.copy() ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() @@ -1015,6 +1017,7 @@ def copy_world_premature(world, player, create_flute_exits=True): ret.bigkeyshuffle = world.bigkeyshuffle.copy() ret.prizeshuffle = world.prizeshuffle.copy() ret.showloot = world.showloot.copy() + ret.showmap = world.showmap.copy() ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() diff --git a/Rom.py b/Rom.py index d62db40d..ac1469ee 100644 --- a/Rom.py +++ b/Rom.py @@ -1452,6 +1452,9 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): if world.showloot[player] == 'never': rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00]) rom.write_byte(0x1CFF11, 0x00) + elif world.showloot[player] == 'presence': + rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x00, 0x00]) + rom.write_byte(0x1CFF11, 0x00) elif world.showloot[player] == 'compass': rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x02, 0x00]) rom.write_byte(0x1CFF11, 0x01) @@ -1459,8 +1462,12 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): rom.write_bytes(0x1CFF08, [0x02, 0x00, 0x00, 0x00]) rom.write_byte(0x1CFF11, 0x00) - if world.doorShuffle[player] != 'vanilla': - rom.write_bytes(0x1CFF00, [0x01, 0x05, 0x00, 0x04]) + if world.showmap[player] == 'visited': + rom.write_bytes(0x1CFF00, [0x01, 0x00, 0x00, 0x05]) + elif world.showmap[player] == 'map': + rom.write_bytes(0x1CFF00, [0x01, 0x05, 0x00, 0x05]) + elif world.showmap[player] == 'always': + rom.write_bytes(0x1CFF00, [0x05, 0x00, 0x00, 0x00]) loot_icons = 0x1CF900 if world.bombbag[player]: diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index fafa2ee5..82fe3084 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -434,10 +434,18 @@ "showloot": { "choices": [ "never", + "presence", "compass", "always" ] }, + "showmap": { + "choices": [ + "visited", + "map", + "always" + ] + }, "keysanity": { "action": "store_true", "type": "bool", -- 2.43.0 From 80a64b884e10dba1332d28f8a237c56c18905b50 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 17 Jan 2026 13:31:10 -0600 Subject: [PATCH 34/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 156289 -> 156300 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index ac1469ee..459f6089 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '1fb7cd3e386f1c48d4abc7cf12990197' +RANDOMIZERBASEHASH = 'c8d02f8e83cb82ee7f2735e83de1d394' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 1d15d310fbcfef95dc59619ae3e154f92bc4edf5..6910d5c2d5fee186c110315b94bd964af3400994 100644 GIT binary patch delta 11321 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 l_vL{tstxeZc?# -- 2.43.0 From 2a7141d24ef2e3b3fc1b13eafdce4b49c515ae96 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 17 Jan 2026 13:57:09 -0600 Subject: [PATCH 35/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 156300 -> 156366 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 459f6089..53e7dd81 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'c8d02f8e83cb82ee7f2735e83de1d394' +RANDOMIZERBASEHASH = 'a8fb2d88663ae7e768703229242e295b' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 6910d5c2d5fee186c110315b94bd964af3400994..49fb0c74895c5f5deb063349700114096851fbea 100644 GIT binary patch delta 1613 zcmW-fe{d5;6vy{oLP+`}ZEcwrtPt7;8!Q+Ql~QUebPy%9%Fp766H0Vi1r$Y?f;4-< z6Vi(5c~cjRCDb;ixioD`M#2pvr`14GDii!eYn@TR0V1>zERI9`qi+1;-sk(?y|=sX z?S2&2TncLftU@`L|7};0Q>d2CIol`Q`o>-~**CDWytn6Q(X)Q3o;_M*@=Ikb|H^1k ztY~4FoLZ&1Q&?=`B1fy& zhZG42O`mkqoBTc%bRKM)yu2r%LD?>ZtgQvFWr&f;d2RM>^TlfGBpZ`$A3wJlbJF|7 zR0SQd*-!qcf+y9R{Sv2@>-|Jm4OOPU{Ze*qbSkmkUL7kjWQj7{FNwo(c}u@!tQ$)c zg&YDNM5omtn~qGU~RrT{FhxsVLoH%$-S}8{LUMqGU8Hv0=#Q+)1ux(hhaw zzH7$zYIj;x8BojhK}oMoEEZpQ#k~a&&^8LJ%Y)K!q#meG>B=DKS_wL4oD8i5L)nDq zTX%E{C6+Hxp@h*fc3@ydW!PK5GnAXB4Zl@1&CzE}8w zEL;n<`DuMORP9$}lxWc_W24fpKT{`qS|q|+=(RS)BN02ovEom6Xo4E7Mv07pO=53C zp8y>NOqst^ z=ASt@-{$8=+!yJD61lqlqEK>3XjYYDE_{j9Hr(*2iZ8S0CT$$}?n>;c$#ZP$Mcd$* z0V!_N#zv1}Zsh0u54nQ4bN$Fs{YWgMJ1=(pHbzPJB{RvV>#(zkiAi)>ZXCTy9@N1x zsL2ZnFG4M|Xs#YRc!!SK96cUTQ*NPOJ=Mn?*SkM=wmX{i*i|qOd-Ry_j>=;4&^joC z4SG_&4w~SAiTKt*HCWQf#5!1#Ic@KKk|u_BthrC>Hij0ihnJXit-2V0)?#Sy-u(n= z-2i4VR*~@y5Y^7CxgeyMC@?p~$ff&2-))2(1~RvkpEkiZP&bhB&2Sa;&7`m%9)^tO bPEXQW~wV2oy$`ihx1!{f-nZYC)&IrgbEDqpN~q zvR(0lsDTQFBs>CC)19`n>J$x1Db{i7@J}tZG!>Xh#hJG0jP&M@J->6$p1ZUA?H%Y1 zzt9`*VP$f1uhiJX$rQ_G7q^KoZdYorv~`vlTbru2{x)$lTdkdF6H{1zyQRmKR>3g& zr}Phie%CjrYx28j zbl-M?*o^SD`fQJ=pF}~fUz13Bjlk!>>=c7$?X9z7iJ}A=0Fh-;M(jAm8L{T5+a9A? zRcVMCQ4HlagUVIvD85?}^!rEPT=e6iCWTnrP9MfW6A~}Alar)zIjoH->!Mk!gszi} zoE=!?kZ2-dX)rrMaN9R*ZHCx=(~yeZ_q2reJ_s3&nq<)iQ%uZhkUu@XN9>!N45)gM z?T1FcACG^5khFu`NrM>m%pMUdox_p2(k}8#8g#@octjj6u~b#k1*&qXhBTzZG-f)v zl@8}p&UCIq(YA81i06bXmOn&Il~BchLV1C*gYqJ!htf{=XTU5A*U@1+&6m)?BjjR! zFE!n?QA+t0WfSEs$}cIu7OL3RhZ&ef-gUSVIda@vF}p$-;a!YH%n_dRZImC-@(apb z$}!43A&ljd>FxsIJe$%o?w)7uiNH0;VMUf;{b#9GHcrT7`4_a2ASh1pW7NzNET{Nn znMKqH=lK*$E#-bn9a-`|{FH6+goYW>OeZTI^a%StzefMbflyd~a^J+GcuzQrb|7S_ ziro|8^7-yXMUR>vW?3fKlW*fvU4)zpLdgnY|th%ZB_@=Td&sC-Q(e053OYygkl*4A+9&5G)lav8j zDR!3DPs3~jS&T{MkwHF=lRI18<;MoEm(AsF7ECz3ay@$1hn@xEeB{8+`S{Cj`Yv{*>T)pELYoN*Quk*$TGjf}rnX9o^~ z<{^jnds15nI?FL1TdQWR?3IvQ4axP{c!sr|>u-KYKR6JhNpuOiQ^LwHBj$Psh^cs_ zWqsl!cF%;Bb<%5m;%{z&`~K~&Aw80f(qr+o7IXbSZ{xUFe|_S^>ZJa`h#SQNb)y&s zn+MEfkKBmaI8wj_8cRm1{~&2=pcdYU@jh7tCT79GIoQVA%Bk*}gF81;&eLJrTpjML zwf%nMYQ5dIREHgVb+{!76W*rQlJ!N90$Lrh7QsGPl~2ZtAPW|TlXus_qR4eeUJ;ec zyFBj|nYrG3XdSF&)Y}zv@RbU^{YK_O(!U Date: Sun, 18 Jan 2026 00:39:53 -0600 Subject: [PATCH 36/54] Add attempt number to failure messages --- DungeonRandomizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DungeonRandomizer.py b/DungeonRandomizer.py index 06fec596..ba7f30af 100755 --- a/DungeonRandomizer.py +++ b/DungeonRandomizer.py @@ -80,7 +80,7 @@ def start(): break except (FillError, EnemizerError, Exception, RuntimeError) as err: failures.append((err, seed)) - logger.warning('%s: %s', fish.translate("cli","cli","generation.failed"), err) + logger.warning('Attempt %d - %s: %s', trynum, fish.translate("cli","cli","generation.failed"), err) logger.info('') seed = random.randint(0, 999999999) -- 2.43.0 From 9db2a3b64b219ddbf8e3e736d4ac0fc87dd3c012 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 18 Jan 2026 16:57:23 -0600 Subject: [PATCH 37/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 156366 -> 155338 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 53e7dd81..3cdb97e6 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a8fb2d88663ae7e768703229242e295b' +RANDOMIZERBASEHASH = '7cabc21858154de52ca1de8bd363ad7f' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 49fb0c74895c5f5deb063349700114096851fbea..e9539df8ddf5638280202d9e4397b410e68d5075 100644 GIT binary patch delta 16957 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 N$2(QF6p^rf(*asvh0Fi| -- 2.43.0 From 3255c75828242114dcb586f4585abb536748d780 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Mon, 19 Jan 2026 13:37:08 -0600 Subject: [PATCH 38/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155338 -> 155482 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 3cdb97e6..95419809 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '7cabc21858154de52ca1de8bd363ad7f' +RANDOMIZERBASEHASH = '015d196d606fe1870a37df38ec335835' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index e9539df8ddf5638280202d9e4397b410e68d5075..01c26f256b197ed72f42837aabe8913692c351a9 100644 GIT binary patch delta 13672 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ⅇL;1Z<>E>?r(nH{0ePooK21=^^H*^3jVS&TvUAO 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 C?XP73 delta 13493 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 T{NO`+ms6+rAI^En>(&1U>3D8> -- 2.43.0 From 67307a872c2a8170dde2fd675c11505d57a83321 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Wed, 21 Jan 2026 08:20:59 -0600 Subject: [PATCH 39/54] Bosshunt mode --- BaseClasses.py | 17 ++++++++++--- CLI.py | 4 ++- ItemList.py | 8 +++--- Main.py | 20 +++++++++------ Rom.py | 47 +++++++++++++++++++++++++++++------- Rules.py | 9 +++++++ data/base2current.bps | Bin 155482 -> 155589 bytes resources/app/cli/args.json | 22 +++++++++++++++++ 8 files changed, 104 insertions(+), 23 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index ddf1284a..0b044a49 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -74,6 +74,8 @@ class World(object): self.dark_rooms = {} self.damage_challenge = {} self.shuffle_damage_table = {} + self.bosses_ganon = {} + self.bosshunt_include_agas = {} self.ganon_item = {} self.ganon_item_orig = {} self.custom = custom @@ -168,6 +170,8 @@ class World(object): set_player_attr('escape_assist', []) set_player_attr('crystals_needed_for_ganon', 7) set_player_attr('crystals_needed_for_gt', 7) + set_player_attr('bosses_ganon', 8) + set_player_attr('bosshunt_include_agas', False) set_player_attr('ganon_item', 'silver') set_player_attr('crystals_ganon_orig', {}) set_player_attr('crystals_gt_orig', {}) @@ -356,7 +360,7 @@ class World(object): else: if self.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district']: return False - elif self.goal[player] in ['crystals', 'trinity', 'ganonhunt']: + elif self.goal[player] in ['crystals', 'trinity', 'ganonhunt', 'bosshunt']: return True else: return False @@ -3118,6 +3122,8 @@ class Spoiler(object): 'beemizer': self.world.beemizer, 'gt_crystals': self.world.crystals_needed_for_gt, 'ganon_crystals': self.world.crystals_needed_for_ganon, + 'ganon_bosses': self.world.bosses_ganon, + 'bosshunt_include_agas': self.world.bosshunt_include_agas, 'ganon_item': self.world.ganon_item, 'open_pyramid': self.world.open_pyramid, 'accessibility': self.world.accessibility, @@ -3340,6 +3346,10 @@ class Spoiler(object): if custom['ganongoal'] and 'requirements' in custom['ganongoal']: outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n') outfile.write(' %s\n' % custom['ganongoal']['goaltext']) + elif self.metadata['goal'][player] == 'bosshunt': + outfile.write('Ganon Requirement:'.ljust(line_width) + '%s bosses%s\n' % + (str(self.world.bosses_ganon[player]), + ' (including both Agahnims)' if self.world.bosshunt_include_agas[player] else '')) else: outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player])) if custom['pedgoal'] and 'requirements' in custom['pedgoal']: @@ -3749,8 +3759,9 @@ world_mode = {"open": 0, "standard": 1, "inverted": 2} sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3} # byte 2: GGGD DFFH (goal, diff, item_func, hints) -goal_mode = {'ganon': 0, 'pedestal': 1, 'dungeons': 2, 'triforcehunt': 3, 'crystals': 4, 'trinity': 5, - 'ganonhunt': 6, 'completionist': 7, 'sanctuary': 1} +goal_mode = {'ganon': 0, 'pedestal': 1, 'dungeons': 2, 'triforcehunt': 3, + 'crystals': 4, 'trinity': 5, 'ganonhunt': 6, 'completionist': 7, + 'sanctuary': 1, 'bosshunt': 6} diff_mode = {"normal": 0, "hard": 1, "expert": 2} func_mode = {"normal": 0, "hard": 1, "expert": 2} diff --git a/CLI.py b/CLI.py index b2ef18a1..c3efe785 100644 --- a/CLI.py +++ b/CLI.py @@ -134,7 +134,7 @@ def parse_cli(argv, no_defaults=False): for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'ow_shuffle', 'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle', 'flute_mode', 'bow_mode', 'take_any', 'boots_hint', 'shuffle_followers', - 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'ganon_item', 'openpyramid', + 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'bosses_ganon', 'bosshunt_include_agas', 'ganon_item', 'openpyramid', 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'showloot', 'showmap', 'startinventory', 'usestartinventory', 'bombbag', 'shuffleganon', 'overworld_map', 'restrict_boss_items', 'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max', @@ -178,6 +178,8 @@ def parse_settings(): "goal": "ganon", "crystals_gt": "7", "crystals_ganon": "7", + "bosses_ganon": "8", + "bosshunt_include_agas": False, "ganon_item": "silver", "swords": "random", "flute_mode": "normal", diff --git a/ItemList.py b/ItemList.py index 4202719a..4b2befd3 100644 --- a/ItemList.py +++ b/ItemList.py @@ -218,12 +218,14 @@ def get_custom_array_key(item): def generate_itempool(world, player): if (world.difficulty[player] not in ['normal', 'hard', 'expert'] - or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'trinity', 'crystals', - 'ganonhunt', 'completionist', 'sanctuary'] + or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', + 'triforcehunt', 'trinity', 'crystals', + 'ganonhunt', 'completionist', 'sanctuary', + 'bosshunt'] or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): - raise NotImplementedError('Not supported yet') + raise NotImplementedError('Not supported yet') if world.timer in ['ohko', 'timed-ohko']: world.can_take_damage[player] = False diff --git a/Main.py b/Main.py index 29b7e53b..2e99b625 100644 --- a/Main.py +++ b/Main.py @@ -80,7 +80,7 @@ def random_ganon_item(sword_mode): def main(args, seed=None, fish=None): check_python_version() - + if args.print_template_yaml: return export_yaml(args, fish) @@ -124,14 +124,14 @@ def main(args, seed=None, fish=None): from OverworldShuffle import __version__ as ORVersion logger.info( - world.fish.translate("cli","cli","app.title") + "\n", - ORVersion, - "%s (%s)" % (world.seed, str(args.outputname)) if str(args.outputname).startswith('M') else world.seed, - Settings.make_code(world, 1) if world.players == 1 else '' + world.fish.translate("cli","cli","app.title") + "\n", + ORVersion, + "%s (%s)" % (world.seed, str(args.outputname)) if str(args.outputname).startswith('M') else world.seed, + Settings.make_code(world, 1) if world.players == 1 else '' ) for k,v in {"DR":__version__,"OR":ORVersion}.items(): - logger.info((k + ' Version:').ljust(16) + '%s' % v) + logger.info((k + ' Version:').ljust(16) + '%s' % v) parsed_names = parse_player_names(args.names, world.players, args.teams) world.teams = len(parsed_names) @@ -478,6 +478,8 @@ def init_world(args, fish): world.crystals_ganon_orig = args.crystals_ganon.copy() world.crystals_gt_orig = args.crystals_gt.copy() world.ganon_item_orig = args.ganon_item.copy() + world.bosses_ganon = {player: int(args.bosses_ganon[player]) for player in range(1, world.players + 1)} + world.bosshunt_include_agas = args.bosshunt_include_agas.copy() world.owTerrain = args.ow_terrain.copy() world.owKeepSimilar = args.ow_keepsimilar.copy() world.owWhirlpoolShuffle = args.ow_whirlpool.copy() @@ -525,7 +527,7 @@ def init_world(args, fish): world.money_balance = args.money_balance.copy() # custom settings - these haven't been promoted to full settings yet - in_progress_settings = ['force_enemy', 'free_lamp_cone'] + in_progress_settings = ['force_enemy'] for player in range(1, world.players + 1): for setting in in_progress_settings: if world.customizer and world.customizer.has_setting(player, setting): @@ -795,6 +797,8 @@ def copy_world(world): ret.free_lamp_cone = world.free_lamp_cone.copy() ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() + ret.bosses_ganon = world.bosses_ganon.copy() + ret.bosshunt_include_agas = world.bosshunt_include_agas.copy() ret.ganon_item = world.ganon_item.copy() ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() ret.crystals_gt_orig = world.crystals_gt_orig.copy() @@ -1024,6 +1028,8 @@ def copy_world_premature(world, player, create_flute_exits=True): ret.free_lamp_cone = world.free_lamp_cone.copy() ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() + ret.bosses_ganon = world.bosses_ganon.copy() + ret.bosshunt_include_agas = world.bosshunt_include_agas.copy() ret.ganon_item = world.ganon_item.copy() ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() ret.crystals_gt_orig = world.crystals_gt_orig.copy() diff --git a/Rom.py b/Rom.py index 95419809..59ee0331 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '015d196d606fe1870a37df38ec335835' +RANDOMIZERBASEHASH = '0a1b516a3ecde44603b6b2dca2b93616' class JsonRom(object): @@ -1211,7 +1211,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28]) if world.goal[player] in ['triforcehunt', 'trinity', 'ganonhunt']: rom.write_bytes(0x180167, int16_as_bytes(world.treasure_hunt_count[player])) - rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled) + rom.write_byte(0x180194, 1) # Must turn in triforce pieces (instant win not enabled) rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed @@ -1285,6 +1285,8 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): # 08: Goal items collected (ie. Triforce Pieces) # 09: Max collection rate # 0A: Custom goal + # 0B: Reserved for Bingo + # 0C: All bosses (prize bosses + aga1 + aga2) def get_goal_bytes(type): goal_bytes = [] @@ -1339,6 +1341,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): ganon_goal += [0x02, world.crystals_needed_for_ganon[player]] elif world.goal[player] in ['ganonhunt']: ganon_goal += [0x88] # triforce pieces + elif world.goal[player] in ['bosshunt']: + if world.bosshunt_include_agas[player]: + ganon_goal += [0x0C, world.bosses_ganon[player]] # total bosses + else: + ganon_goal += [0x05, world.bosses_ganon[player]] # prize bosses elif world.goal[player] in ['completionist']: ganon_goal += [0x81, 0x82, 0x06, 0x07, 0x89] # AD and max collection rate else: @@ -1482,7 +1489,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): rom.write_byte(loot_icons + crystal_id, crystal_category) pendant_ids = [0x37, 0x38, 0x39] - if world.goal[player] in ['pedestal', 'dungeons']: + if world.goal[player] in ['pedestal', 'dungeons', 'trinity']: pendant_category = 0x0C else: pendant_category = 0x06 @@ -1635,12 +1642,28 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): # b - Big Key # a - Small Key # + dungeon_items_menu = 0x00 + + if world.doorShuffle[player] not in ['vanilla', 'basic']: + dungeon_items_menu |= 0x0F + + if world.keyshuffle[player] not in ['none', 'universal']: + dungeon_items_menu |= 0x01 + + if world.bigkeyshuffle[player] != 'none': + dungeon_items_menu |= 0x02 + enable_menu_map_check = (world.overworld_map[player] != 'default' and world.shuffle[player] != 'vanilla') or world.prizeshuffle[player] not in ['none', 'dungeon', 'nearby'] - rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] not in ['none', 'universal'] else 0x00) - | (0x02 if world.bigkeyshuffle[player] != 'none' else 0x00) - | (0x04 if world.mapshuffle[player] != 'none' or enable_menu_map_check else 0x00) - | (0x08 if world.compassshuffle[player] != 'none' else 0x00) # free roaming items in menu - | (0x10 if world.logic[player] == 'nologic' else 0))) # boss icon + if world.mapshuffle[player] != 'none' or enable_menu_map_check: + dungeon_items_menu |= 0x04 + + if world.compassshuffle[player] != 'none': + dungeon_items_menu |= 0x08 + + if world.logic[player] == 'nologic' or world.goal[player] == 'bosshunt': + dungeon_items_menu |= 0x10 + + rom.write_byte(0x180045, dungeon_items_menu) def get_reveal_bytes(itemName): if world.prizeshuffle[player] != 'wild': @@ -2746,12 +2769,18 @@ def write_strings(rom, world, player, team): tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! You can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % int(world.treasure_hunt_count[player]) elif world.goal[player] == 'ganonhunt': tt['sign_ganon'] = 'Go find the Triforce pieces to beat Ganon' + elif world.goal[player] == 'bosshunt': + bosshunt_count = '%d guardian%s of %sdungeons' % \ + (world.bosses_ganon[player], + '' if world.bosses_ganon[player] == 1 else 's', + '' if world.bosshunt_include_agas[player] else 'prize ') + tt['sign_ganon'] = 'To beat Ganon you must defeat %s.' % bosshunt_count elif world.goal[player] == 'completionist': tt['sign_ganon'] = 'Ganon only respects those who have done everything' tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)] tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!' tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!' - + def get_custom_goal_text(type): goal_text = world.custom_goals[player][type]['goaltext'] placeholder_count = goal_text.count('%d') diff --git a/Rules.py b/Rules.py index 91637cce..b836037b 100644 --- a/Rules.py +++ b/Rules.py @@ -80,6 +80,15 @@ def set_rules(world, player): add_rule(world.get_location('Ganon', player), lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player)) elif world.goal[player] == 'ganonhunt': add_rule(world.get_location('Ganon', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) + elif world.goal[player] == 'bosshunt': + if world.bosshunt_include_agas[player]: + add_rule(world.get_location('Ganon', player), lambda state: + state.item_count('Beat Agahnim 1', player) + + state.item_count('Beat Agahnim 2', player) + + state.item_count('Beat Boss', player) >= world.bosses_ganon[player]) + else: + add_rule(world.get_location('Ganon', player), lambda state: + state.item_count('Beat Boss', player) >= world.bosses_ganon[player]) elif world.goal[player] == 'completionist': add_rule(world.get_location('Ganon', player), lambda state: state.everything(player)) diff --git a/data/base2current.bps b/data/base2current.bps index 01c26f256b197ed72f42837aabe8913692c351a9..9f2e0d7b7415df57c30f05e25c05526d1af89cd8 100644 GIT binary patch delta 8645 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 delta 8402 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 Date: Wed, 21 Jan 2026 18:26:04 -0600 Subject: [PATCH 40/54] Update baserom - kak music bug --- Rom.py | 2 +- data/base2current.bps | Bin 155589 -> 155592 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 59ee0331..cc383333 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '0a1b516a3ecde44603b6b2dca2b93616' +RANDOMIZERBASEHASH = '2e8ac9bff46158f7b4848ea1d2bc5a52' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9f2e0d7b7415df57c30f05e25c05526d1af89cd8..9059c2a8f24d2eeea4843e133f5f3c99558617a3 100644 GIT binary patch delta 3332 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 delta 3368 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 -- 2.43.0 From ae1744f0dd216f19f5d2678906055ea48a5254d9 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Wed, 21 Jan 2026 19:47:43 -0600 Subject: [PATCH 41/54] Update baserom --- Rom.py | 2 +- data/base2current.bps | Bin 155592 -> 155608 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index cc383333..c71fde97 100644 --- a/Rom.py +++ b/Rom.py @@ -44,7 +44,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '2e8ac9bff46158f7b4848ea1d2bc5a52' +RANDOMIZERBASEHASH = '2647cc28bca3675152576dd1f5ea0bab' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9059c2a8f24d2eeea4843e133f5f3c99558617a3..79683ba6fbda5484195d004856f5c6c8cdb51a78 100644 GIT binary patch delta 153 zcmV;K0A~NlzX{mC39yF&5Is&+G=YHt)P(?+po!TNQnQx<<^cq`r$$(Vfdhwu0|B>z z0|GP;9z}r&z(8;i90Ude14sZr0V5nkCl~<&J|Z9pJU%|R!x92@1OXzqITr%W0s;X9 zw+I>n$OQ#UERkmwx78m4y$20<4vCr%Du})gDu}N^x1T2h9x?*K1Gm3f0s#gHUlKDL HC~MZebTTct delta 137 zcmV;40CxY_zX`~{39yF&5G_7MG=YHt)P(?+poz&7LbI0v<^cp4s^?XMfdhwu0|B>z z0|GP;4h4Y+z(8;i90UdeHvk2<(-H!81OWoKNf!dm0s>(Jw-_1%$OQ!pEs+Nnx8)xK ry$1~!4~d!&Du})gDu}Nkx34Dx9x?)kgSXFF0s#gHNm+VP*-6Sh7n&

Date: Fri, 23 Jan 2026 18:56:20 -0600 Subject: [PATCH 42/54] Guarantee a bee for sale --- Fill.py | 4 ++-- ItemList.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Fill.py b/Fill.py index c47a2f3d..cf9c07a7 100644 --- a/Fill.py +++ b/Fill.py @@ -793,7 +793,7 @@ def sell_potions(world, player): if shop.region.name in shop_to_location_table and shop.region.name != 'Capacity Upgrade': loc_choices += [world.get_location(loc, player) for loc in shop_to_location_table[shop.region.name]] locations = [loc for loc in loc_choices if not loc.item] - for potion in ['Green Potion', 'Blue Potion', 'Red Potion']: + for potion in ['Green Potion', 'Blue Potion', 'Red Potion', 'Bee']: location = random.choice(filter_locations(ItemFactory(potion, player), locations, world, potion=True)) locations.remove(location) p_item = next((item for item in world.itempool if item.name == potion and item.player == player), None) @@ -1287,4 +1287,4 @@ def set_prize_drops(world, player): # saved fish prize world.prizes[player]['fish'] = prizes.pop() - world.prizes[player]['enemies'] = prizes \ No newline at end of file + world.prizes[player]['enemies'] = prizes diff --git a/ItemList.py b/ItemList.py index 4b2befd3..2460221c 100644 --- a/ItemList.py +++ b/ItemList.py @@ -363,7 +363,7 @@ def generate_itempool(world, player): items = ItemFactory(pool, player) if world.shopsanity[player]: - for potion in ['Green Potion', 'Blue Potion', 'Red Potion']: + for potion in ['Green Potion', 'Blue Potion', 'Red Potion', 'Bee']: p_item = next(item for item in items if item.name == potion and item.player == player) p_item.priority = True # don't beemize one of each potion @@ -1504,7 +1504,7 @@ def make_customizer_pool(world, player): guaranteed_items.append('Ocarina (Activated)') missing_items = [] if world.shopsanity[player]: - guaranteed_items.extend(['Blue Potion', 'Green Potion', 'Red Potion']) + guaranteed_items.extend(['Blue Potion', 'Green Potion', 'Red Potion', 'Bee']) if world.keyshuffle[player] == 'universal': guaranteed_items.append('Small Key (Universal)') for item in guaranteed_items: -- 2.43.0 From 0f7253c94ed0d354331634a9ef16d78521ec0347 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Fri, 23 Jan 2026 21:41:45 -0600 Subject: [PATCH 43/54] Reduce tier of triforce pieces when goal is high --- Rom.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Rom.py b/Rom.py index c71fde97..8702bdff 100644 --- a/Rom.py +++ b/Rom.py @@ -1480,6 +1480,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): if world.bombbag[player]: rom.write_byte(loot_icons + 0x52, 0x0B) # bomb bag is major + triforce_piece_ids = [0x6B, 0x6C] + if world.treasure_hunt_count[player] > 20: + for triforce_piece_id in triforce_piece_ids: + rom.write_byte(loot_icons + triforce_piece_id, 0x04) + crystal_ids = [0x20, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6] if world.goal[player] in ['ganon', 'dungeons', 'crystals', 'trinity']: crystal_category = 0x0D -- 2.43.0 From a8dc25e59d0f80471b466ff1d96ae3064d3ab942 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 24 Jan 2026 13:47:53 -0600 Subject: [PATCH 44/54] Remove unnecessary references to data/base2current.json --- Rom.py | 24 ------------------------ pyproject.toml | 6 +++--- uv.lock | 3 ++- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/Rom.py b/Rom.py index 8702bdff..70ec5eb4 100644 --- a/Rom.py +++ b/Rom.py @@ -162,8 +162,6 @@ class LocalRom(object): with open(local_path('data/base2current.bps'), 'rb') as stream: bps.apply.apply_to_bytearrays(bps.io.read_bps(stream), orig_buffer, self.buffer) - self.create_json_patch(orig_buffer) - if not os.getenv("SKIP_BASEROM_CHECK", False): # verify md5 patchedmd5 = hashlib.md5() @@ -171,28 +169,6 @@ class LocalRom(object): if RANDOMIZERBASEHASH != patchedmd5.hexdigest(): raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.') - def create_json_patch(self, orig_buffer): - # extend to 2MB - orig_buffer.extend(bytearray([0x00] * (len(self.buffer) - len(orig_buffer)))) - - i = 0 - patches = [] - - while i < len(self.buffer): - if self.buffer[i] == orig_buffer[i]: - i += 1 - continue - - patch_start = i - patch_contents = [] - while self.buffer[i] != orig_buffer[i]: - patch_contents.append(self.buffer[i]) - i += 1 - patches.append({patch_start: patch_contents}) - - with open(local_path('data/base2current.json'), 'w') as fp: - json.dump(patches, fp, separators=(',', ':')) - def write_crc(self): crc = (sum(self.buffer[:0x7FDC] + self.buffer[0x7FE0:]) + 0x01FE) & 0xFFFF inv = crc ^ 0xFFFF diff --git a/pyproject.toml b/pyproject.toml index a10a4674..3daaea9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "ALttPOverworldRandomizer" -version = "0.1.0" -description = "Add your description here" +name = "alttpr-python" +version = "1.0.0" +description = "Python ALttP Randomizer" readme = "README.md" requires-python = ">=3.7" dependencies = [ diff --git a/uv.lock b/uv.lock index dc2946cf..5bb90917 100644 --- a/uv.lock +++ b/uv.lock @@ -11,6 +11,7 @@ resolution-markers = [ name = "aenum" version = "3.1.16" source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/7a/61ed58e8be9e30c3fe518899cc78c284896d246d51381bab59b5db11e1f3/aenum-3.1.16.tar.gz", hash = "sha256:bfaf9589bdb418ee3a986d85750c7318d9d2839c1b1a1d6fe8fc53ec201cf140", size = 137693, upload-time = "2026-01-12T22:34:38.819Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e3/52/6ad8f63ec8da1bf40f96996d25d5b650fdd38f5975f8c813732c47388f18/aenum-3.1.16-py3-none-any.whl", hash = "sha256:9035092855a98e41b66e3d0998bd7b96280e85ceb3a04cc035636138a1943eaf", size = 165627, upload-time = "2025-04-25T03:17:58.89Z" }, ] @@ -41,7 +42,7 @@ wheels = [ ] [[package]] -name = "alttpoverworldrandomizer" +name = "alttpr-python" version = "0.1.0" source = { virtual = "." } dependencies = [ -- 2.43.0 From 1d4c5f18849501c9ca08e50e34b85fc87259c03d Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 24 Jan 2026 13:56:09 -0600 Subject: [PATCH 45/54] .gitattributes --- .gitattributes | 1 + .gitignore | 2 - ER_hint_reference.txt | 720 +++++++++++++++++++++--------------------- 3 files changed, 361 insertions(+), 362 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitignore b/.gitignore index f9ac15fa..907ddf87 100644 --- a/.gitignore +++ b/.gitignore @@ -32,8 +32,6 @@ weights/ /output/ /enemizer/ -base2current.json - resources/user/* !resources/user/.gitkeep diff --git a/ER_hint_reference.txt b/ER_hint_reference.txt index 943609ce..9b759706 100644 --- a/ER_hint_reference.txt +++ b/ER_hint_reference.txt @@ -1,361 +1,361 @@ -Hint description: - -Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: - -4 hints for inconvenient entrances. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -4 junk hints. - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: - -5 hints for inconvenient item locations. -8 hints for valuable items. -7 junk hints. - -In the simple, restricted shuffles, these are the ratios: - -2 hints for inconvenient entrances. -1 hint for an inconvenient dungeon entrance. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -5 junk hints. - -These hints will use the following format: - -Entrance hints go "[Entrance on overworld] leads to [interior]". - -Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). - -The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. - -Hint Locations: - -Eastern Palace room before Big Chest -Desert Palace bonk torch room -Tower of Hera entrance room -Tower of Hera Big Chest room -Castle Tower after dark rooms -Palace of Darkness before Bow section -Swamp Palace entryway -Thieves' Town upstairs -Ice Palace entrance -Ice Palace after first drop -Ice Palace tall ice floor room -Misery Mire cutscene room -Turtle Rock entrance -Spectacle Rock cave -Spiky Hint cave -PoD Bdlg NPC -Near PoD Storyteller (bug near bomb wall) -Dark Sanctuary Storyteller (long room with tables) -Near Mire Storyteller (feather duster in winding cave) -SE DW Storyteller (owl in winding cave) - -Inconvenient entrance list: - -Skull Woods Final -Ice Palace -Misery Mire -Turtle Rock -Ganon's Tower -Mimic Ledge -SW DM Foothills Cave (mirror from upper Bumper ledge) -Hammer Pegs (near purple chest) -Super Bomb cracked wall - -Inconvenient location list: - -Swamp left (two chests) -Mire left (two chests) -Hera basement -Eastern Palace Big Key chest (protected by anti-fairies) -Thieves' Town Big Chest -Ice Palace Big Chest -Ganon's Tower Big Chest -Purple Chest -Spike Cave -Magic Bat -Sahasrahla (Green Pendant) - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: - -Graveyard Cave -Mimic Cave - -Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. - -While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: - -Overworld Entrance naming: - -Links House: The hero's old residence -Turtle Rock: Turtle Rock Main -Misery Mire: Misery Mire -Ice Palace: Ice Palace -Skull Woods Final Section: The back of Skull Woods -Death Mountain Return Cave (West): The SW DM Foothills Cave -Mimic Cave: Mimic Ledge -Hammer Peg Cave: The rows of pegs -Pyramid Fairy: The crack on the pyramid -Eastern Palace: Eastern Palace -Elder House (East): Elder House -Elder House (West): Elder House -Two Brothers House (East): Eastern Quarreling Brothers' house -Old Man Cave (West): The lower DM entrance -Hyrule Castle Entrance (South): The ground level castle door -Thieves Town: Thieves' Town -Bumper Cave (Bottom): The lower Bumper Cave -Swamp Palace: Swamp Palace -Dark Death Mountain Ledge (West): The East dark DM connector ledge -Dark Death Mountain Ledge (East): The East dark DM connector ledge -Superbunny Cave (Top): The summit of dark DM cave -Superbunny Cave (Bottom): The base of east dark DM -Hookshot Cave: The rock on dark DM -Desert Palace Entrance (South): The book sealed passage -Tower of Hera: The Tower of Hera -Two Brothers House (West): The door near the race game -Old Man Cave (East): The SW-most cave on west DM -Old Man House (Bottom): A cave with a door on west DM -Old Man House (Top): The eastmost cave on west DM -Death Mountain Return Cave (East): The westmost cave on west DM -Spectacle Rock Cave Peak: The highest cave on west DM -Spectacle Rock Cave: The right ledge on west DM -Spectacle Rock Cave (Bottom): The left ledge on west DM -Paradox Cave (Bottom): The right paired cave on east DM -Paradox Cave (Middle): The southmost cave on east DM -Paradox Cave (Top): The east DM summit cave -Fairy Ascension Cave (Bottom): The east DM cave behind rocks -Fairy Ascension Cave (Top): The central ledge on east DM -Spiral Cave: The left ledge on east DM -Spiral Cave (Bottom): The SWmost cave on east DM -Palace of Darkness: Palace of Darkness -Hyrule Castle Entrance (West): The left castle door -Hyrule Castle Entrance (East): The right castle door -Agahnims Tower: The sealed castle door -Desert Palace Entrance (West): The westmost building in the desert -Desert Palace Entrance (North): The northmost cave in the desert -Blinds Hideout: Blind's old house -Lake Hylia Fairy: A cave NE of Lake Hylia -Light Hype Fairy: The cave south of your house -Desert Fairy: The cave near the desert -Chicken House: The chicken lady's house -Tavern North: A backdoor -Aginahs Cave: The open desert cave -Sahasrahlas Hut: The house near armos -Lake Hylia Shop: The cave NW Lake Hylia -Blacksmiths Hut: The old smithery -Sick Kids House: The central house in Kakariko -Lost Woods Gamble: A tree trunk door -Fortune Teller (Light): A building NE of Kakariko -Snitch Lady (East): A house guarded by a snitch -Snitch Lady (West): A house guarded by a snitch -Bush Covered House: A house with an uncut lawn -Tavern (Front): A building with a backdoor -Light World Bomb Hut: A Kakariko building with no door -Kakariko Shop: The old Kakariko shop -Mini Moldorm Cave: The cave south of Lake Hylia -Long Fairy Cave: The eastmost portal cave -Good Bee Cave: The open cave SE Lake Hylia -20 Rupee Cave: The rock SE Lake Hylia -50 Rupee Cave: The rock near the desert -Ice Rod Cave: The sealed cave SE Lake Hylia -Library: The old library -Potion Shop: The witch's building -Dam: The old dam -Lumberjack House: The lumberjack house -Lake Hylia Fortune Teller: The building NW Lake Hylia -Kakariko Gamble Game: The old Kakariko gambling den -Waterfall of Wishing: Going behind the waterfall -Capacity Upgrade: The cave on the island -Bonk Rock Cave: The rock pile near Sanctuary -Graveyard Cave: The graveyard ledge -Checkerboard Cave: The NE desert ledge -Cave 45: The ledge south of haunted grove -Kings Grave: The northeastmost grave -Bonk Fairy (Light): The rock pile near your home -Hookshot Fairy: A cave on east DM -Bonk Fairy (Dark): The rock pile near the old bomb shop -Dark Sanctuary Hint: The dark sanctuary cave -Dark Lake Hylia Fairy: The cave NE dark Lake Hylia -C-Shaped House: The NE house in Village of Outcasts -Big Bomb Shop: The old bomb shop -Dark Death Mountain Fairy: The SW cave on dark DM -Dark Lake Hylia Shop: The building NW dark Lake Hylia -Dark World Shop: The hammer sealed building -Red Shield Shop: The fenced in building -Mire Shed: The western hut in the mire -East Dark World Hint: The dark cave near the eastmost portal -Mire Hint: The cave east of the mire -Spike Cave: The ledge cave on west dark DM -Palace of Darkness Hint: The building south of Kiki -Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia -Dark Death Mountain Shop: The base of east dark DM -Dark Potion Shop: The building near the catfish -Archery Game: The old archery game -Dark Lumberjack Shop: The northmost Dark World building -Hype Cave: The cave south of the old bomb shop -Brewery: The Village of Outcasts building with no door -Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia -Chest Game: The westmost building in the Village of Outcasts -Mire Fairy: The eastern hut in the mire -Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia -Fortune Teller (Dark): The building NE the Village of Outcasts -Sanctuary: Sanctuary -Lumberjack Tree Cave: The cave Behind Lumberjacks -Lost Woods Hideout Stump: The stump in Lost Woods -North Fairy Cave: The cave East of Graveyard -Bat Cave Cave: The cave in eastern Kakariko -Kakariko Well Cave: The cave in northern Kakariko -Hyrule Castle Secret Entrance Stairs: The tunnel near the castle -Skull Woods First Section Door: The southeastmost skull -Skull Woods Second Section Door (East): The central open skull -Skull Woods Second Section Door (West): The westmost open skull -Desert Palace Entrance (East): The eastern building in the desert -Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM -Bumper Cave (Top): The upper Bumper Cave -Hookshot Cave Back Entrance: The stairs on the floating island - -Destination Entrance Naming: - -Hyrule Castle: Hyrule Castle (all three entrances) -Eastern Palace: Eastern Palace -Desert Palace: Desert Palace (all four entrances, including final) -Tower of Hera: Tower of Hera -Palace of Darkness: Palace of Darkness -Swamp Palace: Swamp Palace -Skull Woods: Skull Woods (any entrance including final) -Thieves' Town: Thieves' Town -Ice Palace: Ice Palace -Misery Mire: Misery Mire -Turtle Rock: Turtle Rock (all four entrances) -Ganon's Tower: Ganon's Tower -Castle Tower: Agahnim's Tower -A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave -A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout -Sahasrahla: Sahasrahla -A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy -A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave -A common shop: Any shop that sells bombs by default -The rare shop: The shop that sells the Red Shield by default -The potion shop: Potion Shop -The bomb shop: Bomb Shop -A fortune teller: Any of the three fortune tellers -A house with a chest: Chicken Lady's house, C-House, Brewery -A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave -A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave -The dam: Watergate -The sick kid: Sick Kid -The library: Library -Mimic Cave: Mimic Cave -Spike Cave: Spike Cave -A game of 16 chests: VoO chest game (for the item) -A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint -A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) -A game of chance: Gambling game (just for cash, no items) -A game of skill: Archery minigame -The queen of fairies: Capacity Upgrade Fairy -A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit -A restock room: The Kakariko bomb/arrow restock room -The tavern: The Kakariko tavern -The grass man: The Kakariko man with many beds -A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee -Fairies deep in a cave: Hookshot Fairy - -Location naming reference: - -Mushroom: in the woods -Master Sword Pedestal: at the pedestal -Bottle Merchant: with a merchant -Stumpy: with tree boy -Flute Spot: underground -Digging Game: underground -Lake Hylia Island: on an island -Floating Island: on an island -Bumper Cave Ledge: on a ledge -Spectacle Rock: atop a rock -Maze Race: at the race -Desert Ledge: in the desert -Pyramid: on the pyramid -Catfish: with a catfish -Ether Tablet: at a monument -Bombos Tablet: at a monument -Hobo: with the hobo -Zora's Ledge: near Zora -King Zora: at a high price -Sunken Treasure: underwater -Floodgate Chest: in the dam -Blacksmith: with the smith -Purple Chest: from a box -Old Man: with the old man -Link's Uncle: with your uncle -Secret Passage: near your uncle -Kakariko Well (5 items): in a well -Lost Woods Hideout: near a thief -Lumberjack Tree: in a hole -Magic Bat: with the bat -Paradox Cave (7 items): in a cave with seven chests -Blind's Hideout (5 items): in a basement -Mini Moldorm Cave (5 items): near Moldorms -Hype Cave (4 back chests): near a bat-like man -Hype Cave - Generous Guy: with a bat-like man -Hookshot Cave (4 items): across pits -Sahasrahla's Hut (chests in back): near the elder -Sahasrahla: with the elder -Waterfall Fairy (2 items): near a fairy -Pyramid Fairy (2 items): near a fairy -Mire Shed (2 items): near sparks -Superbunny Cave (2 items): in a connection -Spiral Cave: in spiral cave -Kakariko Tavern: in the bar -Link's House: in your home -Sick Kid: with the sick -Library: near books -Potion Shop: near potions -Spike Cave: beyond spikes -Mimic Cave: in a cave of mimicry -Chest Game: as a game reward -Chicken House: near poultry -Aginah's Cave: with Aginah -Ice Rod Cave: in a frozen cave -Brewery: alone in a home -C-Shaped House: alone in a home -Spectacle Rock Cave: alone in a cave -King's Tomb: alone in a cave -Cave 45: alone in a cave -Graveyard Cave: alone in a cave -Checkerboard Cave: alone in a cave -Bonk Rock Cave: alone in a cave -Peg Cave: alone in a cave -Sanctuary: in Sanctuary -Hyrule Castle - Boomerang Chest: in Hyrule Castle -Hyrule Castle - Map Chest: in Hyrule Castle -Hyrule Castle - Zelda's Chest: in Hyrule Castle -Sewers - Dark Cross: in the sewers -Sewers - Secret Room (3 items): in the sewers -Eastern Palace - Boss: with the Armos -Eastern Palace (otherwise, 5 items): in Eastern Palace -Desert Palace - Boss: with Lanmolas -Desert Palace (otherwise, 5 items): in Desert Palace -Tower of Hera - Boss: with Moldorm -Tower of Hera (otherwise, 5 items): in Tower of Hera -Castle Tower (2 items): in Castle Tower -Palace of Darkness - Boss: with Helmasaur King -Palace of Darkness (otherwise, 13 items): in Palace of Darkness -Swamp Palace - Boss: with Arrghus -Swamp Palace (otherwise, 9 items): in Swamp Palace -Skull Woods - Bridge Room: near Mothula -Skull Woods - Boss: with Mothula -Skull Woods (otherwise, 6 items): in Skull Woods -Thieves' Town - Boss: with Blind -Thieves' Town (otherwise, 7 items): in Thieves' Town -Ice Palace - Boss: with Kholdstare -Ice Palace (otherwise, 7 items): in Ice Palace -Misery Mire - Boss: with Vitreous -Misery Mire (otherwise, 7 items): in Misery Mire -Turtle Rock - Boss: with Trinexx -Turtle Rock (otherwise, 11 items): in Turtle Rock -Ganons Tower (after climb, 4 items): atop Ganon's Tower +Hint description: + +Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: + +4 hints for inconvenient entrances. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +4 junk hints. + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: + +5 hints for inconvenient item locations. +8 hints for valuable items. +7 junk hints. + +In the simple, restricted shuffles, these are the ratios: + +2 hints for inconvenient entrances. +1 hint for an inconvenient dungeon entrance. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +5 junk hints. + +These hints will use the following format: + +Entrance hints go "[Entrance on overworld] leads to [interior]". + +Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). + +The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. + +Hint Locations: + +Eastern Palace room before Big Chest +Desert Palace bonk torch room +Tower of Hera entrance room +Tower of Hera Big Chest room +Castle Tower after dark rooms +Palace of Darkness before Bow section +Swamp Palace entryway +Thieves' Town upstairs +Ice Palace entrance +Ice Palace after first drop +Ice Palace tall ice floor room +Misery Mire cutscene room +Turtle Rock entrance +Spectacle Rock cave +Spiky Hint cave +PoD Bdlg NPC +Near PoD Storyteller (bug near bomb wall) +Dark Sanctuary Storyteller (long room with tables) +Near Mire Storyteller (feather duster in winding cave) +SE DW Storyteller (owl in winding cave) + +Inconvenient entrance list: + +Skull Woods Final +Ice Palace +Misery Mire +Turtle Rock +Ganon's Tower +Mimic Ledge +SW DM Foothills Cave (mirror from upper Bumper ledge) +Hammer Pegs (near purple chest) +Super Bomb cracked wall + +Inconvenient location list: + +Swamp left (two chests) +Mire left (two chests) +Hera basement +Eastern Palace Big Key chest (protected by anti-fairies) +Thieves' Town Big Chest +Ice Palace Big Chest +Ganon's Tower Big Chest +Purple Chest +Spike Cave +Magic Bat +Sahasrahla (Green Pendant) + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: + +Graveyard Cave +Mimic Cave + +Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. + +While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: + +Overworld Entrance naming: + +Links House: The hero's old residence +Turtle Rock: Turtle Rock Main +Misery Mire: Misery Mire +Ice Palace: Ice Palace +Skull Woods Final Section: The back of Skull Woods +Death Mountain Return Cave (West): The SW DM Foothills Cave +Mimic Cave: Mimic Ledge +Hammer Peg Cave: The rows of pegs +Pyramid Fairy: The crack on the pyramid +Eastern Palace: Eastern Palace +Elder House (East): Elder House +Elder House (West): Elder House +Two Brothers House (East): Eastern Quarreling Brothers' house +Old Man Cave (West): The lower DM entrance +Hyrule Castle Entrance (South): The ground level castle door +Thieves Town: Thieves' Town +Bumper Cave (Bottom): The lower Bumper Cave +Swamp Palace: Swamp Palace +Dark Death Mountain Ledge (West): The East dark DM connector ledge +Dark Death Mountain Ledge (East): The East dark DM connector ledge +Superbunny Cave (Top): The summit of dark DM cave +Superbunny Cave (Bottom): The base of east dark DM +Hookshot Cave: The rock on dark DM +Desert Palace Entrance (South): The book sealed passage +Tower of Hera: The Tower of Hera +Two Brothers House (West): The door near the race game +Old Man Cave (East): The SW-most cave on west DM +Old Man House (Bottom): A cave with a door on west DM +Old Man House (Top): The eastmost cave on west DM +Death Mountain Return Cave (East): The westmost cave on west DM +Spectacle Rock Cave Peak: The highest cave on west DM +Spectacle Rock Cave: The right ledge on west DM +Spectacle Rock Cave (Bottom): The left ledge on west DM +Paradox Cave (Bottom): The right paired cave on east DM +Paradox Cave (Middle): The southmost cave on east DM +Paradox Cave (Top): The east DM summit cave +Fairy Ascension Cave (Bottom): The east DM cave behind rocks +Fairy Ascension Cave (Top): The central ledge on east DM +Spiral Cave: The left ledge on east DM +Spiral Cave (Bottom): The SWmost cave on east DM +Palace of Darkness: Palace of Darkness +Hyrule Castle Entrance (West): The left castle door +Hyrule Castle Entrance (East): The right castle door +Agahnims Tower: The sealed castle door +Desert Palace Entrance (West): The westmost building in the desert +Desert Palace Entrance (North): The northmost cave in the desert +Blinds Hideout: Blind's old house +Lake Hylia Fairy: A cave NE of Lake Hylia +Light Hype Fairy: The cave south of your house +Desert Fairy: The cave near the desert +Chicken House: The chicken lady's house +Tavern North: A backdoor +Aginahs Cave: The open desert cave +Sahasrahlas Hut: The house near armos +Lake Hylia Shop: The cave NW Lake Hylia +Blacksmiths Hut: The old smithery +Sick Kids House: The central house in Kakariko +Lost Woods Gamble: A tree trunk door +Fortune Teller (Light): A building NE of Kakariko +Snitch Lady (East): A house guarded by a snitch +Snitch Lady (West): A house guarded by a snitch +Bush Covered House: A house with an uncut lawn +Tavern (Front): A building with a backdoor +Light World Bomb Hut: A Kakariko building with no door +Kakariko Shop: The old Kakariko shop +Mini Moldorm Cave: The cave south of Lake Hylia +Long Fairy Cave: The eastmost portal cave +Good Bee Cave: The open cave SE Lake Hylia +20 Rupee Cave: The rock SE Lake Hylia +50 Rupee Cave: The rock near the desert +Ice Rod Cave: The sealed cave SE Lake Hylia +Library: The old library +Potion Shop: The witch's building +Dam: The old dam +Lumberjack House: The lumberjack house +Lake Hylia Fortune Teller: The building NW Lake Hylia +Kakariko Gamble Game: The old Kakariko gambling den +Waterfall of Wishing: Going behind the waterfall +Capacity Upgrade: The cave on the island +Bonk Rock Cave: The rock pile near Sanctuary +Graveyard Cave: The graveyard ledge +Checkerboard Cave: The NE desert ledge +Cave 45: The ledge south of haunted grove +Kings Grave: The northeastmost grave +Bonk Fairy (Light): The rock pile near your home +Hookshot Fairy: A cave on east DM +Bonk Fairy (Dark): The rock pile near the old bomb shop +Dark Sanctuary Hint: The dark sanctuary cave +Dark Lake Hylia Fairy: The cave NE dark Lake Hylia +C-Shaped House: The NE house in Village of Outcasts +Big Bomb Shop: The old bomb shop +Dark Death Mountain Fairy: The SW cave on dark DM +Dark Lake Hylia Shop: The building NW dark Lake Hylia +Dark World Shop: The hammer sealed building +Red Shield Shop: The fenced in building +Mire Shed: The western hut in the mire +East Dark World Hint: The dark cave near the eastmost portal +Mire Hint: The cave east of the mire +Spike Cave: The ledge cave on west dark DM +Palace of Darkness Hint: The building south of Kiki +Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia +Dark Death Mountain Shop: The base of east dark DM +Dark Potion Shop: The building near the catfish +Archery Game: The old archery game +Dark Lumberjack Shop: The northmost Dark World building +Hype Cave: The cave south of the old bomb shop +Brewery: The Village of Outcasts building with no door +Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia +Chest Game: The westmost building in the Village of Outcasts +Mire Fairy: The eastern hut in the mire +Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia +Fortune Teller (Dark): The building NE the Village of Outcasts +Sanctuary: Sanctuary +Lumberjack Tree Cave: The cave Behind Lumberjacks +Lost Woods Hideout Stump: The stump in Lost Woods +North Fairy Cave: The cave East of Graveyard +Bat Cave Cave: The cave in eastern Kakariko +Kakariko Well Cave: The cave in northern Kakariko +Hyrule Castle Secret Entrance Stairs: The tunnel near the castle +Skull Woods First Section Door: The southeastmost skull +Skull Woods Second Section Door (East): The central open skull +Skull Woods Second Section Door (West): The westmost open skull +Desert Palace Entrance (East): The eastern building in the desert +Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM +Bumper Cave (Top): The upper Bumper Cave +Hookshot Cave Back Entrance: The stairs on the floating island + +Destination Entrance Naming: + +Hyrule Castle: Hyrule Castle (all three entrances) +Eastern Palace: Eastern Palace +Desert Palace: Desert Palace (all four entrances, including final) +Tower of Hera: Tower of Hera +Palace of Darkness: Palace of Darkness +Swamp Palace: Swamp Palace +Skull Woods: Skull Woods (any entrance including final) +Thieves' Town: Thieves' Town +Ice Palace: Ice Palace +Misery Mire: Misery Mire +Turtle Rock: Turtle Rock (all four entrances) +Ganon's Tower: Ganon's Tower +Castle Tower: Agahnim's Tower +A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave +A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout +Sahasrahla: Sahasrahla +A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy +A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave +A common shop: Any shop that sells bombs by default +The rare shop: The shop that sells the Red Shield by default +The potion shop: Potion Shop +The bomb shop: Bomb Shop +A fortune teller: Any of the three fortune tellers +A house with a chest: Chicken Lady's house, C-House, Brewery +A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave +A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave +The dam: Watergate +The sick kid: Sick Kid +The library: Library +Mimic Cave: Mimic Cave +Spike Cave: Spike Cave +A game of 16 chests: VoO chest game (for the item) +A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint +A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) +A game of chance: Gambling game (just for cash, no items) +A game of skill: Archery minigame +The queen of fairies: Capacity Upgrade Fairy +A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit +A restock room: The Kakariko bomb/arrow restock room +The tavern: The Kakariko tavern +The grass man: The Kakariko man with many beds +A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee +Fairies deep in a cave: Hookshot Fairy + +Location naming reference: + +Mushroom: in the woods +Master Sword Pedestal: at the pedestal +Bottle Merchant: with a merchant +Stumpy: with tree boy +Flute Spot: underground +Digging Game: underground +Lake Hylia Island: on an island +Floating Island: on an island +Bumper Cave Ledge: on a ledge +Spectacle Rock: atop a rock +Maze Race: at the race +Desert Ledge: in the desert +Pyramid: on the pyramid +Catfish: with a catfish +Ether Tablet: at a monument +Bombos Tablet: at a monument +Hobo: with the hobo +Zora's Ledge: near Zora +King Zora: at a high price +Sunken Treasure: underwater +Floodgate Chest: in the dam +Blacksmith: with the smith +Purple Chest: from a box +Old Man: with the old man +Link's Uncle: with your uncle +Secret Passage: near your uncle +Kakariko Well (5 items): in a well +Lost Woods Hideout: near a thief +Lumberjack Tree: in a hole +Magic Bat: with the bat +Paradox Cave (7 items): in a cave with seven chests +Blind's Hideout (5 items): in a basement +Mini Moldorm Cave (5 items): near Moldorms +Hype Cave (4 back chests): near a bat-like man +Hype Cave - Generous Guy: with a bat-like man +Hookshot Cave (4 items): across pits +Sahasrahla's Hut (chests in back): near the elder +Sahasrahla: with the elder +Waterfall Fairy (2 items): near a fairy +Pyramid Fairy (2 items): near a fairy +Mire Shed (2 items): near sparks +Superbunny Cave (2 items): in a connection +Spiral Cave: in spiral cave +Kakariko Tavern: in the bar +Link's House: in your home +Sick Kid: with the sick +Library: near books +Potion Shop: near potions +Spike Cave: beyond spikes +Mimic Cave: in a cave of mimicry +Chest Game: as a game reward +Chicken House: near poultry +Aginah's Cave: with Aginah +Ice Rod Cave: in a frozen cave +Brewery: alone in a home +C-Shaped House: alone in a home +Spectacle Rock Cave: alone in a cave +King's Tomb: alone in a cave +Cave 45: alone in a cave +Graveyard Cave: alone in a cave +Checkerboard Cave: alone in a cave +Bonk Rock Cave: alone in a cave +Peg Cave: alone in a cave +Sanctuary: in Sanctuary +Hyrule Castle - Boomerang Chest: in Hyrule Castle +Hyrule Castle - Map Chest: in Hyrule Castle +Hyrule Castle - Zelda's Chest: in Hyrule Castle +Sewers - Dark Cross: in the sewers +Sewers - Secret Room (3 items): in the sewers +Eastern Palace - Boss: with the Armos +Eastern Palace (otherwise, 5 items): in Eastern Palace +Desert Palace - Boss: with Lanmolas +Desert Palace (otherwise, 5 items): in Desert Palace +Tower of Hera - Boss: with Moldorm +Tower of Hera (otherwise, 5 items): in Tower of Hera +Castle Tower (2 items): in Castle Tower +Palace of Darkness - Boss: with Helmasaur King +Palace of Darkness (otherwise, 13 items): in Palace of Darkness +Swamp Palace - Boss: with Arrghus +Swamp Palace (otherwise, 9 items): in Swamp Palace +Skull Woods - Bridge Room: near Mothula +Skull Woods - Boss: with Mothula +Skull Woods (otherwise, 6 items): in Skull Woods +Thieves' Town - Boss: with Blind +Thieves' Town (otherwise, 7 items): in Thieves' Town +Ice Palace - Boss: with Kholdstare +Ice Palace (otherwise, 7 items): in Ice Palace +Misery Mire - Boss: with Vitreous +Misery Mire (otherwise, 7 items): in Misery Mire +Turtle Rock - Boss: with Trinexx +Turtle Rock (otherwise, 11 items): in Turtle Rock +Ganons Tower (after climb, 4 items): atop Ganon's Tower Ganon's Tower (otherwise, 23 items): in Ganon's Tower \ No newline at end of file -- 2.43.0 From a3f67a39ab437b683e2700bbc1e63da202dcd412 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 24 Jan 2026 20:51:48 -0600 Subject: [PATCH 46/54] Version/romnaming refactor --- BaseClasses.py | 13 +++-- DungeonRandomizer.py | 2 +- Gui.py | 7 ++- Main.py | 17 ++---- OverworldShuffle.py | 6 --- Plando.py | 4 +- Rom.py | 36 +++++++------ Versions.py | 3 ++ build-app_version.py | 5 -- resources/app/cli/lang/en.json | 2 +- source/classes/appversion.py | 17 ------ source/classes/diags.py | 84 ++++++++++++++---------------- source/gui/randomize/generation.py | 6 +-- uv.lock | 2 +- 14 files changed, 84 insertions(+), 120 deletions(-) create mode 100644 Versions.py delete mode 100644 build-app_version.py delete mode 100644 source/classes/appversion.py diff --git a/BaseClasses.py b/BaseClasses.py index 0b044a49..30885a35 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -17,6 +17,8 @@ from RoomData import Room from source.dungeon.RoomObject import RoomObject from source.overworld.EntranceData import door_addresses +from Versions import ORVersion, DRVersion, GKVersion + class World(object): @@ -3078,12 +3080,9 @@ class Spoiler(object): self.doorTypes[(doorNames, player)] = OrderedDict([('player', player), ('doorNames', doorNames), ('type', type)]) def parse_meta(self): - from Main import __version__ as ERVersion - from OverworldShuffle import __version__ as ORVersion - self.startinventory = list(map(str, self.world.precollected_items)) - self.metadata = {'version': ERVersion, - 'versions': {'Door':ERVersion, 'Overworld':ORVersion}, + self.metadata = {'version': GKVersion, + 'versions': {'Door': DRVersion, 'Overworld': ORVersion}, 'logic': self.world.logic, 'mode': self.world.mode, 'bombbag': self.world.bombbag, @@ -3300,7 +3299,7 @@ class Spoiler(object): self.parse_meta() with open(filename, 'w') as outfile: line_width = 35 - outfile.write('ALttP Overworld Randomizer - Seed: %s\n\n' % (self.world.seed)) + outfile.write('ALttP GwaaKiwi Randomizer - Seed: %s\n\n' % (self.world.seed)) for k,v in self.metadata["versions"].items(): outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v) for player in range(1, self.world.players + 1): @@ -3315,7 +3314,7 @@ class Spoiler(object): self.parse_meta() with open(filename, 'w') as outfile: line_width = 35 - outfile.write('ALttP Overworld Randomizer - Seed: %s\n\n' % (self.world.seed)) + outfile.write('ALttP GwaaKiwi Randomizer - Seed: %s\n\n' % (self.world.seed)) for k,v in self.metadata["versions"].items(): outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v) if self.metadata['user_notes']: diff --git a/DungeonRandomizer.py b/DungeonRandomizer.py index ba7f30af..4bf58f2a 100755 --- a/DungeonRandomizer.py +++ b/DungeonRandomizer.py @@ -12,7 +12,7 @@ from source.classes.BabelFish import BabelFish import source.classes.diags as diagnostics from CLI import parse_cli, get_args_priority -from Main import main, EnemizerError, __version__ +from Main import main, EnemizerError from Rom import get_sprite_from_name from Utils import is_bundled, close_console from Fill import FillError diff --git a/Gui.py b/Gui.py index bbb3eada..b422a7f2 100755 --- a/Gui.py +++ b/Gui.py @@ -23,8 +23,7 @@ from source.gui.randomize.gameoptions import gameoptions_page from source.gui.randomize.generation import generation_page from source.gui.bottom import bottom_frame, create_guiargs from GuiUtils import set_icon -from Main import __version__ as ESVersion -from OverworldShuffle import __version__ as ORVersion +from Versions import DRVersion, ORVersion, GKVersion from source.classes.BabelFish import BabelFish from source.classes.Empty import Empty @@ -34,7 +33,7 @@ def check_python_version(fish): import sys version = sys.version_info if version.major < 3 or version.minor < 7: - messagebox.showinfo("Overworld Shuffle %s (DR %s)" % (ORVersion, ESVersion), fish.translate("cli","cli","old.python.version") % sys.version) + messagebox.showinfo("GwaaKiwi Randomizer %s (OR %s, DR %s)" % (GKVersion, ORVersion, DRVersion), fish.translate("cli","cli","old.python.version") % sys.version) # Save settings to file @@ -83,7 +82,7 @@ def guiMain(args=None): mainWindow = Tk() self = mainWindow - mainWindow.wm_title("Overworld Shuffle %s (DR %s)" % (ORVersion, ESVersion)) + mainWindow.wm_title("GwaaKiwi Randomizer %s (OR %s, DR %s)" % (GKVersion, ORVersion, DRVersion)) mainWindow.protocol("WM_DELETE_WINDOW", guiExit) # intercept when user clicks the X # set program icon diff --git a/Main.py b/Main.py index 2e99b625..88f7bf64 100644 --- a/Main.py +++ b/Main.py @@ -40,10 +40,7 @@ from source.enemizer.DamageTables import DamageTable from source.enemizer.Enemizer import randomize_enemies from source.rom.DataTables import init_data_tables -version_number = '1.5.0' -version_branch = '-u' -__version__ = f'{version_number}{version_branch}' - +from Versions import ORVersion, DRVersion, GKVersion from source.classes.BabelFish import BabelFish @@ -122,15 +119,13 @@ def main(args, seed=None, fish=None): world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} world.finish_init() - from OverworldShuffle import __version__ as ORVersion logger.info( world.fish.translate("cli","cli","app.title") + "\n", - ORVersion, + GKVersion, "%s (%s)" % (world.seed, str(args.outputname)) if str(args.outputname).startswith('M') else world.seed, - Settings.make_code(world, 1) if world.players == 1 else '' ) - for k,v in {"DR":__version__,"OR":ORVersion}.items(): + for k,v in {"GK": GKVersion, "OR": ORVersion, "DR": DRVersion}.items(): logger.info((k + ' Version:').ljust(16) + '%s' % v) parsed_names = parse_player_names(args.names, world.players, args.teams) @@ -421,15 +416,13 @@ def export_yaml(args, fish): if args.seed and int(args.seed) > 0: world.seed = int(args.seed) - from OverworldShuffle import __version__ as ORVersion logger.info( world.fish.translate("cli","cli","app.title") + "\n", - ORVersion, + GKVersion, "(%s)" % outfilebase, - Settings.make_code(world, 1) if world.players == 1 else '' ) - for k,v in {"DR":__version__,"OR":ORVersion}.items(): + for k,v in {"GK": GKVersion, "OR": ORVersion, "DR": DRVersion}.items(): logger.info((k + ' Version:').ljust(16) + '%s' % v) for player in range(1, world.players + 1): diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 616a85a2..9dd2583b 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,12 +8,6 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.7' -# branch indicator is intentionally different across branches -version_branch = '' - -__version__ = '%s%s' % (version_number, version_branch) - parallel_links_new = None # needs to be globally available, reset every new generation/player def link_overworld(world, player): diff --git a/Plando.py b/Plando.py index 25003f24..f8d47aaf 100755 --- a/Plando.py +++ b/Plando.py @@ -18,7 +18,7 @@ from Items import ItemFactory from ItemList import difficulties from Main import create_playthrough -__version__ = '0.2-dev' +PlandoVersion = '0.2-dev' def main(args): start_time = time.process_time() @@ -36,7 +36,7 @@ def main(args): random.seed(world.seed) - logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', __version__, args.plando) + logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', PlandoVersion, args.plando) world.difficulty_requirements[1] = difficulties[world.difficulty[1]] diff --git a/Rom.py b/Rom.py index 70ec5eb4..81484e10 100644 --- a/Rom.py +++ b/Rom.py @@ -34,6 +34,7 @@ from source.overworld.EntranceShuffle2 import exit_ids from OverworldShuffle import default_flute_connections, flute_data from InitialSram import InitialSram from DamageTable import DamageTable +from Versions import DRVersion, GKVersion, ORVersion from source.classes.SFX import randomize_sfx, randomize_sfxinstruments, randomize_songinstruments from source.item.FillUtil import valid_pot_items @@ -1853,30 +1854,33 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): # set rom name # 21 bytes - from Main import __version__ - from OverworldShuffle import __version__ as ORVersion if rom_header: if len(rom_header) > 21: raise Exception('ROM header too long. Max 21 bytes, found %d bytes.' % len(rom_header)) - elif '|' in rom_header: - gen, seedstring = rom_header.split('|', 1) - gen = f'{gen:<3}' - seedstring = f'{int(seedstring):09}' if seedstring.isdigit() else seedstring[:9] - rom.name = bytearray(f'OR{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] - elif len(rom_header) <= 9: - seedstring = f'{int(rom_header):09}' if rom_header.isdigit() else rom_header - rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] - else: - rom.name = bytearray(rom_header, 'utf8')[:21] - else: - seedstring = f'{world.seed:09}' if isinstance(world.seed, int) else world.seed - rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] + if world.players > 1 and world.teams > 1 and len(rom_header) <= 12: + rom.name = bytearray(f"GK_{rom_header}_{team + 1}_{player}", 'utf8') + elif world.players > 1 and len(rom_header) <= 15: + rom.name = bytearray(f"GK_{rom_header}_{player}", 'utf8') + elif len(rom_header) <= 18: + rom.name = bytearray(f"GK_{rom_header}", 'utf8') + else: + rom.name = bytearray(rom_header, 'utf8') + else: + if world.players > 1 and world.teams > 1: + rom.name = bytearray(f'GK_{world.seed}_{team + 1}_{player}', 'utf8') + elif world.players > 1: + rom.name = bytearray(f'GK_{world.seed}_{player}', 'utf8') + else: + rom.name = bytearray(f'GK_{world.seed}', 'utf8') + + rom.name = rom.name[:21] rom.name.extend([0] * (21 - len(rom.name))) rom.write_bytes(0x7FC0, rom.name) - rom.write_bytes(0x138010, bytearray(__version__, 'utf8')) + rom.write_bytes(0x138010, bytearray(DRVersion, 'utf8')) rom.write_bytes(0x150010, bytearray(ORVersion, 'utf8')) + rom.write_bytes(0x1CEEF0, bytearray(GKVersion, 'utf8')) # set player names for p in range(1, min(world.players, 255) + 1): diff --git a/Versions.py b/Versions.py new file mode 100644 index 00000000..639ac093 --- /dev/null +++ b/Versions.py @@ -0,0 +1,3 @@ +GKVersion = '1.0.0' +ORVersion = '0.6.1.7' +DRVersion = '1.5.0-u' diff --git a/build-app_version.py b/build-app_version.py deleted file mode 100644 index 69332cba..00000000 --- a/build-app_version.py +++ /dev/null @@ -1,5 +0,0 @@ -from OverworldShuffle import __version__ as OWVersion -import os - -with(open(os.path.join("resources","app","meta","manifests","app_version.txt"),"w+")) as f: - f.write(OWVersion) diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index c8b427b6..fa4f015e 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -2,7 +2,7 @@ "cli": { "yes": "Yes", "no": "No", - "app.title": "ALttP Overworld Randomizer Version %s : --seed %s --code %s", + "app.title": "ALttP GwaaKiwi Randomizer Version %s : --seed %s", "version": "Version", "seed": "Seed", "player": "Player", diff --git a/source/classes/appversion.py b/source/classes/appversion.py deleted file mode 100644 index 3d677d1e..00000000 --- a/source/classes/appversion.py +++ /dev/null @@ -1,17 +0,0 @@ -import os - -from OverworldShuffle import __version__ -OWR_VERSION = __version__ - -def write_appversion(): - APP_VERSION = OWR_VERSION - if "-" in APP_VERSION: - APP_VERSION = APP_VERSION[:APP_VERSION.find("-")] - APP_VERSION_FILE = os.path.join(".","resources","app","meta","manifests","app_version.txt") - with open(APP_VERSION_FILE,"w") as f: - f.seek(0) - f.truncate() - f.write(APP_VERSION) - -if __name__ == "__main__": - write_appversion() diff --git a/source/classes/diags.py b/source/classes/diags.py index e26c4e43..9d2abb82 100644 --- a/source/classes/diags.py +++ b/source/classes/diags.py @@ -5,56 +5,50 @@ except ModuleNotFoundError as e: pass import datetime -from Main import __version__ -DR_VERSION = __version__ - -from OverworldShuffle import __version__ -OWR_VERSION = __version__ - -PROJECT_NAME = "ALttP Overworld Randomizer" +from Versions import DRVersion, GKVersion, ORVersion def diagpad(str): - return str.ljust(len(f"{PROJECT_NAME} Version") + 5,'.') + return str.ljust(40, '.') def output(): - lines = [ - f"{PROJECT_NAME} Diagnostics", - "=================================", - diagpad("UTC Time") + str(datetime.datetime.now(datetime.UTC))[:19], - diagpad("ALttP Door Randomizer Version") + DR_VERSION, - diagpad(f"{PROJECT_NAME} Version") + OWR_VERSION, - diagpad("Python Version") + platform.python_version() - ] - lines.append(diagpad("OS Version") + "%s %s" % (platform.system(), platform.release())) - if hasattr(sys, "executable"): - lines.append(diagpad("Executable") + sys.executable) - lines.append(diagpad("Build Date") + platform.python_build()[1]) - lines.append(diagpad("Compiler") + platform.python_compiler()) - if hasattr(sys, "api_version"): - lines.append(diagpad("Python API") + str(sys.api_version)) - if hasattr(os, "sep"): - lines.append(diagpad("Filepath Separator") + os.sep) - if hasattr(os, "pathsep"): - lines.append(diagpad("Path Env Separator") + os.pathsep) - lines.append("") - lines.append("Packages") - lines.append("--------") - ''' - #this breaks when run from the .exe - reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']) - installed_packages = [r.decode() for r in reqs.split()] - for pkg in installed_packages: - pkg = pkg.split("==") - lines.append(diagpad(pkg[0]) + pkg[1]) - ''' - installed_packages = [] - installed_packages = [str(d) for d in pkg_resources.working_set] #this doesn't work from the .exe either, but it doesn't crash the program - installed_packages.sort() - for pkg in installed_packages: - pkg = pkg.split(' ') - lines.append(diagpad(pkg[0]) + pkg[1]) + lines = [ + "ALttP GwaaKiwi Randomizer Diagnostics", + "=====================================", + diagpad("UTC Time") + str(datetime.datetime.now(datetime.UTC))[:19], + diagpad("ALttP Door Randomizer Version") + DRVersion, + diagpad("ALttP Overworld Randomizer Version") + ORVersion, + diagpad("ALttP GwaaKiwi Randomizer Version") + GKVersion, + diagpad("Python Version") + platform.python_version(), + ] + lines.append(diagpad("OS Version") + "%s %s" % (platform.system(), platform.release())) + if hasattr(sys, "executable"): + lines.append(diagpad("Executable") + sys.executable) + lines.append(diagpad("Build Date") + platform.python_build()[1]) + lines.append(diagpad("Compiler") + platform.python_compiler()) + if hasattr(sys, "api_version"): + lines.append(diagpad("Python API") + str(sys.api_version)) + if hasattr(os, "sep"): + lines.append(diagpad("Filepath Separator") + os.sep) + if hasattr(os, "pathsep"): + lines.append(diagpad("Path Env Separator") + os.pathsep) + lines.append("") - return lines + lines.append("Packages") + lines.append("--------") + reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']) + installed_packages = [r.decode() for r in reqs.split()] + for pkg in installed_packages: + pkg = pkg.split("==") + lines.append(diagpad(pkg[0]) + pkg[1]) + + installed_packages = [] + installed_packages = [str(d) for d in pkg_resources.working_set] + installed_packages.sort() + for pkg in installed_packages: + pkg = pkg.split(' ') + lines.append(diagpad(pkg[0]) + pkg[1]) + + return lines if __name__ == "__main__": raise AssertionError(f"Called main() on utility library {__file__}") diff --git a/source/gui/randomize/generation.py b/source/gui/randomize/generation.py index 868402e4..f67e48e7 100644 --- a/source/gui/randomize/generation.py +++ b/source/gui/randomize/generation.py @@ -5,7 +5,7 @@ import json import os from functools import partial from source.classes.Empty import Empty -from Main import __version__ +from Versions import DRVersion def generation_page(parent,settings): # Generation Setup @@ -148,9 +148,9 @@ def generation_page(parent,settings): "width": 120, "height": 50 } - } + } diag = Tk() - diag.title("Door Shuffle " + __version__) + diag.title("Door Shuffle " + DRVersion) diag.geometry(str(dims["window"]["width"]) + 'x' + str(dims["window"]["height"])) text = Text(diag, width=dims["textarea.characters"]["width"], height=dims["textarea.characters"]["height"]) text.pack() diff --git a/uv.lock b/uv.lock index 5bb90917..81ab815b 100644 --- a/uv.lock +++ b/uv.lock @@ -43,7 +43,7 @@ wheels = [ [[package]] name = "alttpr-python" -version = "0.1.0" +version = "1.0.0" source = { virtual = "." } dependencies = [ { name = "aenum" }, -- 2.43.0 From 9733da9f4404f0b928a2e5cb75a97cf94e894626 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 24 Jan 2026 21:59:11 -0600 Subject: [PATCH 47/54] Always include team number in rom name --- Rom.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Rom.py b/Rom.py index 81484e10..618ed43e 100644 --- a/Rom.py +++ b/Rom.py @@ -1860,8 +1860,6 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): if world.players > 1 and world.teams > 1 and len(rom_header) <= 12: rom.name = bytearray(f"GK_{rom_header}_{team + 1}_{player}", 'utf8') - elif world.players > 1 and len(rom_header) <= 15: - rom.name = bytearray(f"GK_{rom_header}_{player}", 'utf8') elif len(rom_header) <= 18: rom.name = bytearray(f"GK_{rom_header}", 'utf8') else: @@ -1869,8 +1867,6 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): else: if world.players > 1 and world.teams > 1: rom.name = bytearray(f'GK_{world.seed}_{team + 1}_{player}', 'utf8') - elif world.players > 1: - rom.name = bytearray(f'GK_{world.seed}_{player}', 'utf8') else: rom.name = bytearray(f'GK_{world.seed}', 'utf8') -- 2.43.0 From c946981c38e117c02c76b7f44e3f049c44dd8e8a Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 24 Jan 2026 22:09:56 -0600 Subject: [PATCH 48/54] isort --- Adjuster.py | 5 +- AdjusterMain.py | 4 +- BaseClasses.py | 18 ++-- Bosses.py | 2 +- CLI.py | 5 +- DamageTable.py | 1 + DoorShuffle.py | 67 ++++++++++---- Doors.py | 2 +- DungeonGenerator.py | 26 ++++-- DungeonRandomizer.py | 16 ++-- Fill.py | 14 ++- Gui.py | 38 +++++--- GuiUtils.py | 3 +- ItemList.py | 48 ++++++---- KeyDoorShuffle.py | 14 ++- Main.py | 102 ++++++++++++++++------ MultiClient.py | 11 +-- MultiServer.py | 16 ++-- Mystery.py | 8 +- OWEdges.py | 4 +- OverworldShuffle.py | 42 +++++++-- Plando.py | 27 ++++-- PotShuffle.py | 8 +- Regions.py | 19 +++- Rom.py | 89 +++++++++++++------ RoomData.py | 1 + Rules.py | 28 ++++-- TestSuite.py | 6 +- TestSuiteStat.py | 8 +- Text.py | 3 +- UnderworldGlitchRules.py | 5 +- Utils.py | 16 ++-- _vendor/collections_extended/__init__.py | 4 +- _vendor/collections_extended/_compat.py | 2 +- _vendor/collections_extended/bags.py | 2 +- _vendor/collections_extended/bijection.py | 2 +- _vendor/collections_extended/range_map.py | 3 +- _vendor/collections_extended/setlists.py | 9 +- bundle/_rt_hook.py | 2 +- pyproject.toml | 3 + resources/ci/common/common.py | 5 +- resources/ci/common/get_get_pip.py | 8 +- resources/ci/common/get_pipline.py | 12 +-- resources/ci/common/get_upx.py | 9 +- resources/ci/common/git_clean.py | 3 +- resources/ci/common/install.py | 5 +- resources/ci/common/list_actions.py | 3 +- resources/ci/common/local_install.py | 6 +- resources/ci/common/my_path.py | 1 + resources/ci/common/prepare_appversion.py | 5 +- resources/ci/common/prepare_binary.py | 5 +- resources/ci/common/prepare_release.py | 11 +-- source/classes/BabelFish.py | 1 + source/classes/CustomSettings.py | 15 ++-- source/classes/ItemGfxSelector.py | 17 +++- source/classes/SFX.py | 3 +- source/classes/SpriteSelector.py | 30 +++++-- source/classes/diags.py | 7 +- source/dungeon/DungeonStitcher.py | 15 +++- source/dungeon/EnemyList.py | 6 +- source/dungeon/RoomList.py | 3 +- source/enemizer/Bossmizer.py | 7 +- source/enemizer/Enemizer.py | 14 +-- source/enemizer/EnemizerTestHarness.py | 18 ++-- source/enemizer/EnemyLogic.py | 3 +- source/enemizer/OwEnemyList.py | 3 +- source/enemizer/SpecialEnemyModes.py | 8 +- source/enemizer/SpriteSheets.py | 10 ++- source/enemizer/TilePattern.py | 4 +- source/gui/adjust/overview.py | 28 ++++-- source/gui/bottom.py | 26 ++++-- source/gui/custom/overview.py | 5 +- source/gui/loadcliargs.py | 9 +- source/gui/randomize/dungeon.py | 6 +- source/gui/randomize/enemizer.py | 21 ++++- source/gui/randomize/entrando.py | 6 +- source/gui/randomize/gameoptions.py | 25 ++++-- source/gui/randomize/generation.py | 23 ++++- source/gui/randomize/item.py | 22 ++++- source/gui/randomize/multiworld.py | 6 +- source/gui/randomize/overworld.py | 6 +- source/gui/startinventory/overview.py | 5 +- source/gui/widgets.py | 19 +++- source/item/District.py | 3 +- source/item/FillUtil.py | 8 +- source/logic/Rule.py | 2 +- source/meta/build.py | 4 +- source/meta/check_requirements.py | 2 +- source/overworld/EntranceShuffle2.py | 9 +- source/rom/DataTables.py | 25 ++++-- source/tools/BPS.py | 5 +- source/tools/MysteryUtils.py | 7 +- test-options.py | 7 +- test/MysteryTestSuite.py | 6 +- test/NewTestSuite.py | 6 +- test/dungeons/TestDungeon.py | 4 +- test/inverted/TestInverted.py | 17 ++-- test/inverted/TestInvertedBombRules.py | 25 ++++-- test/inverted_owg/TestDungeons.py | 1 + test/inverted_owg/TestInvertedOWG.py | 18 ++-- test/owg/TestVanillaOWG.py | 16 ++-- test/stats/EntranceShuffleStats.py | 12 +-- test/vanilla/TestVanilla.py | 16 ++-- 103 files changed, 911 insertions(+), 409 deletions(-) diff --git a/Adjuster.py b/Adjuster.py index ba502c8a..27ac4093 100755 --- a/Adjuster.py +++ b/Adjuster.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 import argparse -import os import logging -import textwrap +import os import sys +import textwrap from AdjusterMain import adjust from Rom import get_sprite_from_name + class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter): def _get_help_string(self, action): diff --git a/AdjusterMain.py b/AdjusterMain.py index 6b886a4b..76379453 100644 --- a/AdjusterMain.py +++ b/AdjusterMain.py @@ -1,6 +1,6 @@ +import logging import os import time -import logging try: import bps.apply @@ -8,9 +8,9 @@ try: except ImportError: raise Exception('Could not load BPS module') -from Utils import output_path from Rom import LocalRom, apply_rom_settings from source.tools.BPS import bps_read_vlv +from Utils import output_path def adjust(args): diff --git a/BaseClasses.py b/BaseClasses.py index 30885a35..65f7e789 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2,7 +2,7 @@ import base64 import copy import json import logging -from collections import OrderedDict, Counter, deque, defaultdict +from collections import Counter, OrderedDict, defaultdict, deque from enum import Enum, IntEnum, unique try: @@ -10,14 +10,18 @@ try: except ImportError: from enum import IntFlag as FastEnum -from source.classes.BabelFish import BabelFish -from Utils import int16_as_bytes -from Tables import normal_offset_table, spiral_offset_table, multiply_lookup, divisor_lookup from RoomData import Room +from source.classes.BabelFish import BabelFish from source.dungeon.RoomObject import RoomObject from source.overworld.EntranceData import door_addresses - -from Versions import ORVersion, DRVersion, GKVersion +from Tables import ( + divisor_lookup, + multiply_lookup, + normal_offset_table, + spiral_offset_table, +) +from Utils import int16_as_bytes +from Versions import DRVersion, GKVersion, ORVersion class World(object): @@ -1672,8 +1676,8 @@ class Region(object): self.crystal_switch = False def can_reach(self, state): - from Utils import stack_size3a from DungeonGenerator import GenerationException + from Utils import stack_size3a if stack_size3a() > self.world.players * 1000: raise GenerationException(f'Infinite loop detected for "{self.name}" located at \'Region.can_reach\'') diff --git a/Bosses.py b/Bosses.py index f60489a2..22ae3180 100644 --- a/Bosses.py +++ b/Bosses.py @@ -1,6 +1,6 @@ import logging -import RaceRandom as random +import RaceRandom as random from BaseClasses import Boss, FillError from source.enemizer.Bossmizer import boss_adjust diff --git a/CLI.py b/CLI.py index c3efe785..809a90c6 100644 --- a/CLI.py +++ b/CLI.py @@ -2,14 +2,13 @@ import argparse import copy import json import os -import textwrap import shlex import sys +import textwrap from source.classes.BabelFish import BabelFish - -from Utils import update_deprecated_args from source.classes.CustomSettings import CustomSettings +from Utils import update_deprecated_args class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter): diff --git a/DamageTable.py b/DamageTable.py index b3fb8d0a..14fa18eb 100644 --- a/DamageTable.py +++ b/DamageTable.py @@ -3,6 +3,7 @@ from typing import List import RaceRandom as random + def _load_entries(): entries = [] with open("data/damage_table.bin", 'rb') as stream: diff --git a/DoorShuffle.py b/DoorShuffle.py index 3ba2584f..5d0036b3 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1,27 +1,62 @@ -import RaceRandom as random -from collections import defaultdict, deque import logging import time -from enum import unique, Flag -from typing import DefaultDict, Dict, List +from collections import defaultdict, deque +from enum import Flag, unique from itertools import chain +from typing import DefaultDict, Dict, List -from BaseClasses import RegionType, Region, Door, DoorType, Sector, CrystalBarrier, DungeonInfo, dungeon_keys -from BaseClasses import PotFlags, LocationType, Direction, KeyRuleType +import RaceRandom as random +from BaseClasses import ( + CrystalBarrier, + Direction, + Door, + DoorType, + DungeonInfo, + KeyRuleType, + LocationType, + PotFlags, + Region, + RegionType, + Sector, + dungeon_keys, +) from Doors import reset_portals -from Dungeons import dungeon_regions, region_starts, standard_starts, split_region_starts -from Dungeons import dungeon_bigs, dungeon_hints +from DungeonGenerator import ( + ExplorationState, + connect_doors, + convert_regions, + count_reserved_locations, + create_dungeon_builders, + default_dungeon_entrances, + determine_required_paths, + drop_entrances, + dungeon_drops, + dungeon_portals, + simple_dungeon_builder, + split_dungeon_builder, + valid_region_to_explore, +) +from Dungeons import ( + dungeon_bigs, + dungeon_hints, + dungeon_regions, + region_starts, + split_region_starts, + standard_starts, +) from Items import ItemFactory +from KeyDoorShuffle import ( + DoorRules, + analyze_dungeon, + build_key_layout, + determine_prize_lock, + validate_bk_layout, + validate_key_layout, +) from RoomData import DoorKind, PairedDoor, reset_rooms -from source.dungeon.DungeonStitcher import GenerationException, generate_dungeon from source.dungeon.DungeonStitcher import ExplorationState as ExplorationState2 -from DungeonGenerator import ExplorationState, convert_regions, determine_required_paths, drop_entrances -from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances -from DungeonGenerator import dungeon_portals, dungeon_drops, connect_doors, count_reserved_locations -from DungeonGenerator import valid_region_to_explore -from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock -from KeyDoorShuffle import validate_bk_layout, DoorRules -from Utils import ncr, kth_combination +from source.dungeon.DungeonStitcher import GenerationException, generate_dungeon +from Utils import kth_combination, ncr def link_doors(world, player): diff --git a/Doors.py b/Doors.py index 909fe40b..6026c212 100644 --- a/Doors.py +++ b/Doors.py @@ -1,5 +1,5 @@ -from BaseClasses import Door, DoorType, Direction, CrystalBarrier, Portal +from BaseClasses import CrystalBarrier, Direction, Door, DoorType, Portal from RoomData import PairedDoor # constants diff --git a/DungeonGenerator.py b/DungeonGenerator.py index 59d683a4..616bfb8d 100644 --- a/DungeonGenerator.py +++ b/DungeonGenerator.py @@ -1,22 +1,32 @@ -import RaceRandom as random import collections import itertools -from collections import defaultdict, deque -from functools import reduce import logging import math import operator as op import time +from collections import defaultdict, deque +from functools import reduce from typing import List -from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, PolSlot, flooded_keys, Sector -from BaseClasses import Hook, hook_from_door, Door -from Regions import location_events, flooded_keys_reverse +import RaceRandom as random +from BaseClasses import ( + CrystalBarrier, + Direction, + Door, + DoorType, + Hook, + Polarity, + PolSlot, + RegionType, + Sector, + flooded_keys, + hook_from_door, +) from Dungeons import split_region_starts +from Regions import flooded_keys_reverse, location_events from RoomData import DoorKind - -from source.dungeon.DungeonStitcher import generate_dungeon_find_proposal from source.dungeon.DungeonStitcher import GenerationException as OtherGenException +from source.dungeon.DungeonStitcher import generate_dungeon_find_proposal class GraphPiece: diff --git a/DungeonRandomizer.py b/DungeonRandomizer.py index 4bf58f2a..1d8388ca 100755 --- a/DungeonRandomizer.py +++ b/DungeonRandomizer.py @@ -3,19 +3,19 @@ if __name__ == '__main__': from source.meta.check_requirements import check_requirements check_requirements(console=True) -import os import logging -import RaceRandom as random +import os import sys -from source.classes.BabelFish import BabelFish +import RaceRandom as random import source.classes.diags as diagnostics - -from CLI import parse_cli, get_args_priority -from Main import main, EnemizerError -from Rom import get_sprite_from_name -from Utils import is_bundled, close_console +from CLI import get_args_priority, parse_cli from Fill import FillError +from Main import EnemizerError, main +from Rom import get_sprite_from_name +from source.classes.BabelFish import BabelFish +from Utils import close_console, is_bundled + def start(): args = parse_cli(None) diff --git a/Fill.py b/Fill.py index cf9c07a7..0643e509 100644 --- a/Fill.py +++ b/Fill.py @@ -1,4 +1,3 @@ -import RaceRandom as random import collections import itertools import logging @@ -6,11 +5,18 @@ import math from collections import Counter from contextlib import suppress +import RaceRandom as random from BaseClasses import CollectionState, FillError, LocationType from Items import ItemFactory -from Regions import shop_to_location_table, retro_shops -from source.item.FillUtil import filter_locations, classify_major_items, replace_trash_item, vanilla_fallback -from source.item.FillUtil import filter_special_locations, valid_pot_items +from Regions import retro_shops, shop_to_location_table +from source.item.FillUtil import ( + classify_major_items, + filter_locations, + filter_special_locations, + replace_trash_item, + valid_pot_items, + vanilla_fallback, +) def get_dungeon_item_pool(world): diff --git a/Gui.py b/Gui.py index b422a7f2..758c0bb3 100755 --- a/Gui.py +++ b/Gui.py @@ -5,28 +5,40 @@ if __name__ == '__main__': import json import os import sys -from tkinter import Tk, Button, BOTTOM, TOP, StringVar, BooleanVar, X, BOTH, RIGHT, ttk, messagebox +from tkinter import ( + BOTH, + BOTTOM, + RIGHT, + TOP, + BooleanVar, + Button, + StringVar, + Tk, + X, + messagebox, + ttk, +) from CLI import get_args_priority from DungeonRandomizer import parse_cli +from GuiUtils import set_icon +from source.classes.BabelFish import BabelFish +from source.classes.Empty import Empty from source.gui.adjust.overview import adjust_page -from source.gui.startinventory.overview import startinventory_page +from source.gui.bottom import bottom_frame, create_guiargs from source.gui.custom.overview import custom_page -from source.gui.loadcliargs import loadcliargs, loadadjustargs -from source.gui.randomize.item import item_page -from source.gui.randomize.overworld import overworld_page -from source.gui.randomize.entrando import entrando_page -from source.gui.randomize.enemizer import enemizer_page +from source.gui.loadcliargs import loadadjustargs, loadcliargs from source.gui.randomize.dungeon import dungeon_page +from source.gui.randomize.enemizer import enemizer_page +from source.gui.randomize.entrando import entrando_page + #from source.gui.randomize.multiworld import multiworld_page from source.gui.randomize.gameoptions import gameoptions_page from source.gui.randomize.generation import generation_page -from source.gui.bottom import bottom_frame, create_guiargs -from GuiUtils import set_icon -from Versions import DRVersion, ORVersion, GKVersion - -from source.classes.BabelFish import BabelFish -from source.classes.Empty import Empty +from source.gui.randomize.item import item_page +from source.gui.randomize.overworld import overworld_page +from source.gui.startinventory.overview import startinventory_page +from Versions import DRVersion, GKVersion, ORVersion def check_python_version(fish): diff --git a/GuiUtils.py b/GuiUtils.py index 840e8520..10181099 100644 --- a/GuiUtils.py +++ b/GuiUtils.py @@ -1,10 +1,11 @@ -import queue import os +import queue import threading import tkinter as tk from Utils import local_path + def set_icon(window): er16 = tk.PhotoImage(file=local_path(os.path.join("data","ER16.gif"))) er32 = tk.PhotoImage(file=local_path(os.path.join("data","ER32.gif"))) diff --git a/ItemList.py b/ItemList.py index 2460221c..cf76538f 100644 --- a/ItemList.py +++ b/ItemList.py @@ -1,21 +1,39 @@ -from collections import namedtuple, defaultdict import logging import math +from collections import defaultdict, namedtuple + import RaceRandom as random - -from BaseClasses import LocationType, Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem -from Regions import location_events, shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location -from Fill import FillError, fill_restrictive, get_dungeon_item_pool, track_dungeon_items, track_outside_keys -from PotShuffle import vanilla_pots -from Tables import bonk_prize_lookup -from Items import ItemFactory - -from source.dungeon.EnemyList import add_drop_contents -from source.overworld.EntranceShuffle2 import exit_ids, door_addresses -from source.item.FillUtil import trash_items, pot_items - import source.classes.constants as CONST - +from BaseClasses import ( + CollectionState, + Location, + LocationType, + PotItem, + Region, + RegionType, + Shop, + ShopType, +) +from Fill import ( + FillError, + fill_restrictive, + get_dungeon_item_pool, + track_dungeon_items, + track_outside_keys, +) +from Items import ItemFactory +from PotShuffle import vanilla_pots +from Regions import ( + location_events, + retro_shops, + shop_table_by_location, + shop_to_location_table, + valid_pot_location, +) +from source.dungeon.EnemyList import add_drop_contents +from source.item.FillUtil import pot_items, trash_items +from source.overworld.EntranceShuffle2 import door_addresses, exit_ids +from Tables import bonk_prize_lookup #This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space. #Some basic items that various modes require are placed here, including pendants and crystals. Medallion requirements for the two relevant entrances are also decided. @@ -693,7 +711,7 @@ def create_farm_locations(world, player): world.dynamic_locations.append(loc) return loc - from Rules import set_rule, add_rule, add_bunny_rule + from Rules import add_bunny_rule, add_rule, set_rule for region in bush_bombs: loc = create_and_fill_location(region, 'Bush Drop', 'Farmable Bombs') add_bunny_rule(loc, player) diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index 65ad0faf..5ce19e4f 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -2,11 +2,17 @@ import itertools import logging from collections import defaultdict, deque -from BaseClasses import DoorType, dungeon_keys, KeyRuleType, RegionType +from BaseClasses import DoorType, KeyRuleType, RegionType, dungeon_keys +from DungeonGenerator import ( + ExplorationState, + blind_boss_unavail, + count_locations_exclude_big_chest, + get_special_big_key_doors, + prize_or_event, + reserved_location, +) +from Dungeons import dungeon_bigs, dungeon_keys, dungeon_table from Regions import location_events -from Dungeons import dungeon_keys, dungeon_bigs, dungeon_table -from DungeonGenerator import ExplorationState, get_special_big_key_doors, count_locations_exclude_big_chest, prize_or_event -from DungeonGenerator import reserved_location, blind_boss_unavail class KeyLayout(object): diff --git a/Main.py b/Main.py index 88f7bf64..aadbfe06 100644 --- a/Main.py +++ b/Main.py @@ -1,47 +1,99 @@ +import base64 import copy -from itertools import zip_longest import json import logging import os -import RaceRandom as random import string import time import zlib -import base64 +from itertools import zip_longest -from BaseClasses import World, CollectionState, Item, Region, Location, Shop, Entrance, Settings +import RaceRandom as random +from BaseClasses import ( + CollectionState, + Entrance, + Item, + Location, + Region, + Settings, + Shop, + World, +) from Bosses import place_bosses +from Doors import create_doors +from DoorShuffle import connect_portal, link_doors, link_doors_prep +from Dungeons import create_dungeons +from Fill import ( + balance_money_progression, + balance_multiworld_progression, + distribute_items_restrictive, + dungeon_tracking, + ensure_good_items, + fill_dungeons_restrictive, + lock_shop_locations, + promote_dungeon_items, + sell_keys, + sell_potions, + set_prize_drops, +) +from ItemList import ( + create_farm_locations, + customize_shops, + difficulties, + fill_prizes, + fill_specific_items, + follower_pickups, + generate_itempool, + shuffle_event_items, +) from Items import ItemFactory from KeyDoorShuffle import validate_key_placement from OverworldGlitchRules import create_owg_connections -from PotShuffle import shuffle_pots, shuffle_pot_switches -from Regions import create_regions, create_shops, mark_light_dark_world_regions, create_dungeon_regions, adjust_locations +from OverworldShuffle import ( + create_dynamic_flute_exits, + create_dynamic_mirror_exits, + link_overworld, + update_world_regions, +) from OWEdges import create_owedges -from OverworldShuffle import link_overworld, update_world_regions, create_dynamic_flute_exits, create_dynamic_mirror_exits -from Rom import patch_rom, patch_race_rom, apply_rom_settings, LocalRom, JsonRom, get_hash_string -from Doors import create_doors -from DoorShuffle import link_doors, connect_portal, link_doors_prep +from PotShuffle import shuffle_pot_switches, shuffle_pots +from Regions import ( + adjust_locations, + create_dungeon_regions, + create_regions, + create_shops, + mark_light_dark_world_regions, +) +from Rom import ( + JsonRom, + LocalRom, + apply_rom_settings, + get_hash_string, + patch_race_rom, + patch_rom, +) from RoomData import create_rooms from Rules import set_rules -from Dungeons import create_dungeons -from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dungeons_restrictive, ensure_good_items -from Fill import dungeon_tracking -from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops -from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations, shuffle_event_items, follower_pickups -from UnderworldGlitchRules import connect_hmg_entrances_regions, create_hmg_entrances_regions -from Utils import output_path, parse_player_names - -from source.item.District import init_districts -from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config, verify_item_pool_config -from source.overworld.EntranceShuffle2 import link_entrances_new -from source.tools.BPS import create_bps_from_data +from source.classes.BabelFish import BabelFish from source.classes.CustomSettings import CustomSettings from source.enemizer.DamageTables import DamageTable from source.enemizer.Enemizer import randomize_enemies +from source.item.District import init_districts +from source.item.FillUtil import ( + create_item_pool_config, + district_item_pool_config, + massage_item_pool, + verify_item_pool_config, +) +from source.overworld.EntranceShuffle2 import link_entrances_new from source.rom.DataTables import init_data_tables - -from Versions import ORVersion, DRVersion, GKVersion -from source.classes.BabelFish import BabelFish +from source.tools.BPS import create_bps_from_data +from UnderworldGlitchRules import ( + connect_hmg_entrances_regions, + create_hmg_entrances_regions, +) +from Utils import output_path, parse_player_names +from Versions import DRVersion, GKVersion, ORVersion class EnemizerError(RuntimeError): diff --git a/MultiClient.py b/MultiClient.py index 0d238392..98afc42f 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -1,19 +1,20 @@ -import aioconsole import argparse import asyncio -import colorama import json import logging import shlex import urllib.parse + +import aioconsole +import colorama import websockets -from BaseClasses import PotItem, PotFlags, LocationType import Items -import Regions import PotShuffle +import Regions import source.dungeon.EnemyList as EnemyList import source.rom.DataTables as DataTables +from BaseClasses import LocationType, PotFlags, PotItem class ReceivedItem: @@ -975,8 +976,8 @@ async def track_locations(ctx : Context, roomid, roomdata): ow_unchecked[location] = (screenid, 0x40) ow_begin = min(ow_begin, screenid) ow_end = max(ow_end, screenid + 1) - from Regions import bonk_prize_table from OWEdges import OWTileRegions + from Regions import bonk_prize_table for location, (_, flag, _, _, region_name, _) in bonk_prize_table.items(): if location not in ctx.locations_checked: if region_name in OWTileRegions: diff --git a/MultiServer.py b/MultiServer.py index 44559953..f6cefe22 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -1,4 +1,3 @@ -import aioconsole import argparse import asyncio import functools @@ -8,16 +7,23 @@ import re import shlex import ssl import urllib.request -import websockets import zlib -from BaseClasses import PotItem, PotFlags +import aioconsole +import websockets + import Items -import Regions import PotShuffle -from MultiClient import ReceivedItem, get_item_name_from_id, get_location_name_from_address +import Regions import source.dungeon.EnemyList as EnemyList import source.rom.DataTables as DataTables +from BaseClasses import PotFlags, PotItem +from MultiClient import ( + ReceivedItem, + get_item_name_from_id, + get_location_name_from_address, +) + class Client: def __init__(self, socket): diff --git a/Mystery.py b/Mystery.py index ca79541d..834e709f 100644 --- a/Mystery.py +++ b/Mystery.py @@ -1,13 +1,13 @@ import argparse import logging -import RaceRandom as random +from yaml.constructor import SafeConstructor + +import RaceRandom as random from DungeonRandomizer import parse_cli from Main import main as DRMain from source.classes.BabelFish import BabelFish -from yaml.constructor import SafeConstructor - -from source.tools.MysteryUtils import roll_settings, get_weights +from source.tools.MysteryUtils import get_weights, roll_settings def add_bool(self, node): diff --git a/OWEdges.py b/OWEdges.py index 645e05ad..aa198675 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -1,8 +1,10 @@ -from BaseClasses import OWEdge, Direction, Terrain, WorldType, PolSlot from enum import Enum, unique + +from BaseClasses import Direction, OWEdge, PolSlot, Terrain, WorldType from Utils import bidict + @unique class OpenStd(Enum): Open = 0 diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 9dd2583b..72b79b9d 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1,11 +1,30 @@ -import RaceRandom as random, logging, copy +import copy +import logging from collections import OrderedDict, defaultdict + +import RaceRandom as random +from BaseClasses import ( + Direction, + Entrance, + OWEdge, + PolSlot, + RegionType, + Terrain, + WorldType, +) from DungeonGenerator import GenerationException -from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance +from OverworldGlitchRules import create_owg_connections +from OWEdges import ( + IsParallel, + OpenStd, + OWEdgeGroups, + OWEdgeGroupsTerrain, + OWExitTypes, + OWTileRegions, + parallel_links, +) from Regions import mark_light_dark_world_regions from source.overworld.EntranceShuffle2 import connect_simple -from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitTypes, OpenStd, parallel_links, IsParallel -from OverworldGlitchRules import create_owg_connections from Utils import bidict parallel_links_new = None # needs to be globally available, reset every new generation/player @@ -1364,8 +1383,8 @@ def update_world_regions(world, player): world.get_region(name, player).type = RegionType.LightWorld def can_reach_smith(world, player): - from Items import ItemFactory from BaseClasses import CollectionState + from Items import ItemFactory def explore_region(region_name, region=None): nonlocal found @@ -1420,7 +1439,7 @@ def can_reach_smith(world, player): def build_sectors(world, player): from Main import copy_world_premature from OWEdges import OWTileRegions - + # perform accessibility check on duplicate world for p in range(1, world.players + 1): world.key_logic[p] = {} @@ -1472,8 +1491,8 @@ def build_sectors(world, player): def build_accessible_region_list(world, start_region, player, build_copy_world=False, cross_world=False, region_rules=True, ignore_ledges=False, restrictive_follower=False): from BaseClasses import CollectionState - from Main import copy_world_premature from Items import ItemFactory + from Main import copy_world_premature from Utils import stack_size3a def explore_region(region_name, region=None): @@ -1546,7 +1565,14 @@ def validate_layout(world, player): } # TODO: Find a better source for the below lists, original sourced was deprecated - from source.overworld.EntranceData import default_dungeon_connections, default_connector_connections, default_item_connections, default_shop_connections, default_drop_connections, default_dropexit_connections + from source.overworld.EntranceData import ( + default_connector_connections, + default_drop_connections, + default_dropexit_connections, + default_dungeon_connections, + default_item_connections, + default_shop_connections, + ) dungeon_entrances = list(zip(*default_dungeon_connections + [('Ganons Tower', '')]))[0] connector_entrances = list(zip(*default_connector_connections))[0] diff --git a/Plando.py b/Plando.py index f8d47aaf..13a41bda 100755 --- a/Plando.py +++ b/Plando.py @@ -3,20 +3,31 @@ import argparse import hashlib import logging import os -import RaceRandom as random -import time import sys +import time +import RaceRandom as random from BaseClasses import World -from Regions import create_regions -from OverworldShuffle import link_overworld -from source.overworld.EntranceShuffle2 import link_entrances_new, connect_entrance, connect_two_way, connect_exit -from Rom import patch_rom, LocalRom, write_string_to_rom, apply_rom_settings, get_sprite_from_name -from Rules import set_rules from Dungeons import create_dungeons -from Items import ItemFactory from ItemList import difficulties +from Items import ItemFactory from Main import create_playthrough +from OverworldShuffle import link_overworld +from Regions import create_regions +from Rom import ( + LocalRom, + apply_rom_settings, + get_sprite_from_name, + patch_rom, + write_string_to_rom, +) +from Rules import set_rules +from source.overworld.EntranceShuffle2 import ( + connect_entrance, + connect_exit, + connect_two_way, + link_entrances_new, +) PlandoVersion = '0.2-dev' diff --git a/PotShuffle.py b/PotShuffle.py index bd970182..8303ee3a 100644 --- a/PotShuffle.py +++ b/PotShuffle.py @@ -1,11 +1,9 @@ -import RaceRandom as random - from collections import defaultdict -from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier, LocationType, RegionType -from Utils import int16_as_bytes, pc_to_snes, snes_to_pc - +import RaceRandom as random +from BaseClasses import CrystalBarrier, LocationType, Pot, PotFlags, PotItem, RegionType from source.dungeon.RoomObject import RoomObject, Shuffled_Pot +from Utils import int16_as_bytes, pc_to_snes, snes_to_pc movable_switch_rooms = defaultdict(lambda: [], {'PoD Stalfos Basement': ['PoD Basement Ledge'], diff --git a/Regions.py b/Regions.py index 0d187310..dc94fdf1 100644 --- a/Regions.py +++ b/Regions.py @@ -1,9 +1,20 @@ import collections -from Items import ItemFactory -from BaseClasses import Region, Location, Entrance, RegionType, Terrain, Shop, ShopType, LocationType, PotItem, PotFlags -from PotShuffle import key_drop_data, vanilla_pots, choose_pots, PotSecretTable -from source.dungeon.EnemyList import setup_enemy_locations, enemy_names +from BaseClasses import ( + Entrance, + Location, + LocationType, + PotFlags, + PotItem, + Region, + RegionType, + Shop, + ShopType, + Terrain, +) +from Items import ItemFactory +from PotShuffle import PotSecretTable, choose_pots, key_drop_data, vanilla_pots +from source.dungeon.EnemyList import enemy_names, setup_enemy_locations def create_regions(world, player): diff --git a/Rom.py b/Rom.py index 618ed43e..a51e581e 100644 --- a/Rom.py +++ b/Rom.py @@ -1,48 +1,87 @@ import bisect import collections +import hashlib import io import json -import hashlib import logging import os +import struct +import sys import Items import RaceRandom as random -import struct -import sys + try: import bps.apply import bps.io except ImportError: raise Exception('Could not load BPS module') -from BaseClasses import ShopType, Region, Location, OWEdge, Door, DoorType, RegionType, LocationType -from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals -from Dungeons import dungeon_music_addresses, dungeon_table -from Regions import location_table, shop_to_location_table, retro_shops -from RoomData import DoorKind -from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable -from Text import Uncle_texts, Ganon1_texts, Ganon_Phase_3_No_Silvers_texts, Ganon_Phase_3_No_Weakness_texts, TavernMan_texts, Sahasrahla2_texts -from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts -from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts -from Text import LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts -from Text import Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names -from Utils import local_path, int16_as_bytes, int32_as_bytes, snes_to_pc -from Items import ItemFactory, prize_item_table -from source.overworld.EntranceData import door_addresses, ow_prize_table -from source.overworld.EntranceShuffle2 import exit_ids -from OverworldShuffle import default_flute_connections, flute_data -from InitialSram import InitialSram +from BaseClasses import ( + Door, + DoorType, + Location, + LocationType, + OWEdge, + Region, + RegionType, + ShopType, +) from DamageTable import DamageTable -from Versions import DRVersion, GKVersion, ORVersion - -from source.classes.SFX import randomize_sfx, randomize_sfxinstruments, randomize_songinstruments -from source.item.FillUtil import valid_pot_items +from DoorShuffle import DROptions, boss_indicator, compass_data, dungeon_portals +from Dungeons import dungeon_music_addresses, dungeon_table +from InitialSram import InitialSram +from Items import ItemFactory, prize_item_table +from OverworldShuffle import default_flute_connections, flute_data +from Regions import location_table, retro_shops, shop_to_location_table +from RoomData import DoorKind +from source.classes.SFX import ( + randomize_sfx, + randomize_sfxinstruments, + randomize_songinstruments, +) from source.dungeon.EnemyList import EnemySprite, setup_enemy_dungeon_tables from source.dungeon.RoomObject import DoorObject from source.enemizer.Bossmizer import boss_writes from source.enemizer.Enemizer import write_enemy_shuffle_settings - +from source.item.FillUtil import valid_pot_items +from source.overworld.EntranceData import door_addresses, ow_prize_table +from source.overworld.EntranceShuffle2 import exit_ids +from Text import ( + Blacksmiths_texts, + Blind_texts, + BombShop2_texts, + CompressedTextMapper, + Credits, + DeathMountain_texts, + DesertPalace_texts, + FluteBoy_texts, + Ganon1_texts, + Ganon_Phase_3_No_Silvers_texts, + Ganon_Phase_3_No_Weakness_texts, + Kakariko_texts, + KingsReturn_texts, + LinksHouse_texts, + LostWoods_texts, + Lumberjacks_texts, + MagicShop_texts, + MountainTower_texts, + MultiByteTextMapper, + Sahasrahla2_texts, + Sahasrahla_names, + Sanctuary_texts, + SickKid_texts, + TavernMan_texts, + TextTable, + Triforce_texts, + Uncle_texts, + WishingWell_texts, + Zora_texts, + junk_texts, + text_addresses, +) +from Utils import int16_as_bytes, int32_as_bytes, local_path, snes_to_pc +from Versions import DRVersion, GKVersion, ORVersion JAP10HASH = '03a63945398191337e896e5771f77173' RANDOMIZERBASEHASH = '2647cc28bca3675152576dd1f5ea0bab' diff --git a/RoomData.py b/RoomData.py index 13339364..3b4e0ad7 100644 --- a/RoomData.py +++ b/RoomData.py @@ -1,4 +1,5 @@ from enum import Enum, unique + from Tables import door_pair_offset_table diff --git a/Rules.py b/Rules.py index b836037b..8707151e 100644 --- a/Rules.py +++ b/Rules.py @@ -3,18 +3,28 @@ import logging from collections import deque import OverworldGlitchRules -from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier, KeyRuleType, LocationType, Terrain -from BaseClasses import PotFlags +from BaseClasses import ( + CollectionState, + CrystalBarrier, + DoorType, + Entrance, + KeyRuleType, + LocationType, + PotFlags, + RegionType, + Terrain, +) from Dungeons import dungeon_table -from RoomData import DoorKind -from OWEdges import OWExitTypes from OverworldGlitchRules import overworld_glitches_rules -from UnderworldGlitchRules import underworld_glitches_rules - -from source.logic.Rule import RuleFactory +from OWEdges import OWExitTypes +from RoomData import DoorKind from source.dungeon.EnemyList import EnemySprite, Sprite -from source.enemizer.EnemyLogic import special_rules_check, special_rules_for_region, defeat_rule_single -from source.enemizer.EnemyLogic import defeat_rule_multiple, and_rule as and_rule_new, or_rule as or_rule_new +from source.enemizer.EnemyLogic import and_rule as and_rule_new +from source.enemizer.EnemyLogic import defeat_rule_multiple, defeat_rule_single +from source.enemizer.EnemyLogic import or_rule as or_rule_new +from source.enemizer.EnemyLogic import special_rules_check, special_rules_for_region +from source.logic.Rule import RuleFactory +from UnderworldGlitchRules import underworld_glitches_rules def set_rules(world, player): diff --git a/TestSuite.py b/TestSuite.py index ca734581..639dc079 100644 --- a/TestSuite.py +++ b/TestSuite.py @@ -1,8 +1,8 @@ +import argparse +import concurrent.futures +import multiprocessing import subprocess import sys -import multiprocessing -import concurrent.futures -import argparse from collections import OrderedDict cpu_threads = multiprocessing.cpu_count() diff --git a/TestSuiteStat.py b/TestSuiteStat.py index 574e3fb4..a6b4d393 100644 --- a/TestSuiteStat.py +++ b/TestSuiteStat.py @@ -1,10 +1,10 @@ +import argparse +import concurrent.futures +import csv +import multiprocessing import subprocess import sys -import multiprocessing -import concurrent.futures -import argparse from collections import OrderedDict -import csv cpu_threads = multiprocessing.cpu_count() py_version = f"{sys.version_info.major}.{sys.version_info.minor}" diff --git a/Text.py b/Text.py index 00d9bb6b..ea46a307 100644 --- a/Text.py +++ b/Text.py @@ -1,8 +1,9 @@ # -*- coding: UTF-8 -*- -from collections import OrderedDict import logging import re import warnings +from collections import OrderedDict + warnings.filterwarnings("ignore", category=SyntaxWarning) text_addresses = {'Pedestal': (0x180300, 256), diff --git a/UnderworldGlitchRules.py b/UnderworldGlitchRules.py index 56e64f71..f35fb41d 100644 --- a/UnderworldGlitchRules.py +++ b/UnderworldGlitchRules.py @@ -1,7 +1,8 @@ import functools -from BaseClasses import Entrance, DoorType, Door -from DoorShuffle import connect_simple_door + import Rules +from BaseClasses import Door, DoorType, Entrance +from DoorShuffle import connect_simple_door kikiskip_spots = [ ("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal") diff --git a/Utils.py b/Utils.py index 6f1a38be..d7436309 100644 --- a/Utils.py +++ b/Utils.py @@ -1,19 +1,19 @@ #!/usr/bin/env python3 +import fileinput import os import re import subprocess import sys +import urllib.parse +import urllib.request import xml.etree.ElementTree as ET from collections import defaultdict -from math import factorial from itertools import count -import fileinput - -import urllib.request -import urllib.parse -import yaml +from math import factorial from pathlib import Path +import yaml + def int16_as_bytes(value): value = value & 0xFFFF @@ -103,9 +103,9 @@ def close_console(): def make_new_base2current(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', new_rom='working.sfc'): - from collections import OrderedDict - import json import hashlib + import json + from collections import OrderedDict with open(old_rom, 'rb') as stream: old_rom_data = bytearray(stream.read()) with open(new_rom, 'rb') as stream: diff --git a/_vendor/collections_extended/__init__.py b/_vendor/collections_extended/__init__.py index 039fee03..3b39cf66 100644 --- a/_vendor/collections_extended/__init__.py +++ b/_vendor/collections_extended/__init__.py @@ -1,9 +1,9 @@ """collections_extended contains a few extra basic data structures.""" from ._compat import Collection from .bags import bag, frozenbag -from .setlists import setlist, frozensetlist from .bijection import bijection -from .range_map import RangeMap, MappedRange +from .range_map import MappedRange, RangeMap +from .setlists import frozensetlist, setlist __version__ = '1.0.2' diff --git a/_vendor/collections_extended/_compat.py b/_vendor/collections_extended/_compat.py index bbf0fbd9..451eec54 100644 --- a/_vendor/collections_extended/_compat.py +++ b/_vendor/collections_extended/_compat.py @@ -12,7 +12,7 @@ else: if sys.version_info < (3, 6): - from collections import Sized, Iterable, Container + from collections import Container, Iterable, Sized def _check_methods(C, *methods): mro = C.__mro__ diff --git a/_vendor/collections_extended/bags.py b/_vendor/collections_extended/bags.py index cce132fe..2373abc8 100644 --- a/_vendor/collections_extended/bags.py +++ b/_vendor/collections_extended/bags.py @@ -1,7 +1,7 @@ """Bag class definitions.""" import heapq +from collections import Hashable, MutableSet, Set from operator import itemgetter -from collections import Set, MutableSet, Hashable from . import _compat diff --git a/_vendor/collections_extended/bijection.py b/_vendor/collections_extended/bijection.py index f9641de4..7e71a29f 100644 --- a/_vendor/collections_extended/bijection.py +++ b/_vendor/collections_extended/bijection.py @@ -1,6 +1,6 @@ """Class definition for bijection.""" -from collections import MutableMapping, Mapping +from collections import Mapping, MutableMapping class bijection(MutableMapping): diff --git a/_vendor/collections_extended/range_map.py b/_vendor/collections_extended/range_map.py index 19a61238..85439bd3 100644 --- a/_vendor/collections_extended/range_map.py +++ b/_vendor/collections_extended/range_map.py @@ -1,7 +1,6 @@ """RangeMap class definition.""" from bisect import bisect_left, bisect_right -from collections import namedtuple, Mapping, MappingView, Set - +from collections import Mapping, MappingView, Set, namedtuple # Used to mark unmapped ranges _empty = object() diff --git a/_vendor/collections_extended/setlists.py b/_vendor/collections_extended/setlists.py index 2976077c..e772f9cd 100644 --- a/_vendor/collections_extended/setlists.py +++ b/_vendor/collections_extended/setlists.py @@ -1,13 +1,6 @@ """Setlist class definitions.""" import random as random_ - -from collections import ( - Sequence, - Set, - MutableSequence, - MutableSet, - Hashable, - ) +from collections import Hashable, MutableSequence, MutableSet, Sequence, Set from . import _util diff --git a/bundle/_rt_hook.py b/bundle/_rt_hook.py index 17ea446b..2c897afc 100644 --- a/bundle/_rt_hook.py +++ b/bundle/_rt_hook.py @@ -1,4 +1,4 @@ -import sys import os +import sys sys.path.append(os.path.join(sys._MEIPASS, "ext")) diff --git a/pyproject.toml b/pyproject.toml index 3daaea9a..872ff602 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,3 +14,6 @@ dependencies = [ "pyyaml>=6.0.1", "websockets>=11.0.3", ] + +[tool.isort] +profile = "black" diff --git a/resources/ci/common/common.py b/resources/ci/common/common.py index 17b37434..342e1e0f 100644 --- a/resources/ci/common/common.py +++ b/resources/ci/common/common.py @@ -1,6 +1,7 @@ -import os # for env vars -import stat # file statistics +import os # for env vars +import stat # file statistics import sys # default system info + try: import distro except ModuleNotFoundError as e: diff --git a/resources/ci/common/get_get_pip.py b/resources/ci/common/get_get_pip.py index 1de2898b..b076d37f 100644 --- a/resources/ci/common/get_get_pip.py +++ b/resources/ci/common/get_get_pip.py @@ -1,8 +1,10 @@ -import common import argparse import os -import urllib.request, ssl -import subprocess # do stuff at the shell level +import ssl +import subprocess # do stuff at the shell level +import urllib.request + +import common env = common.prepare_env() diff --git a/resources/ci/common/get_pipline.py b/resources/ci/common/get_pipline.py index edc5714a..53110a5c 100644 --- a/resources/ci/common/get_pipline.py +++ b/resources/ci/common/get_pipline.py @@ -1,11 +1,11 @@ # import modules -import common # app common functions +import json # json manipulation +import os # for os data, filesystem manipulation +import subprocess # for running shell commands +import sys # for system commands +import traceback # for errors -import json # json manipulation -import os # for os data, filesystem manipulation -import subprocess # for running shell commands -import sys # for system commands -import traceback # for errors +import common # app common functions # get env env = common.prepare_env() # get environment variables diff --git a/resources/ci/common/get_upx.py b/resources/ci/common/get_upx.py index 16982aaf..d3f8c520 100644 --- a/resources/ci/common/get_upx.py +++ b/resources/ci/common/get_upx.py @@ -1,9 +1,10 @@ -import common -import os # for env vars -import sys # for path -import urllib.request # for downloads +import os # for env vars +import sys # for path +import urllib.request # for downloads from shutil import unpack_archive +import common + # only do stuff if we don't have a UPX folder if not os.path.isdir(os.path.join(".","upx")): diff --git a/resources/ci/common/git_clean.py b/resources/ci/common/git_clean.py index b6e9668b..f4431b7b 100644 --- a/resources/ci/common/git_clean.py +++ b/resources/ci/common/git_clean.py @@ -1,5 +1,6 @@ -import subprocess # do stuff at the shell level import os +import subprocess # do stuff at the shell level + def git_clean(clean_ignored=True, clean_user=False): excludes = [ diff --git a/resources/ci/common/install.py b/resources/ci/common/install.py index 3d0b5965..3b54a3f4 100644 --- a/resources/ci/common/install.py +++ b/resources/ci/common/install.py @@ -1,8 +1,9 @@ -import common import argparse import os import platform -import subprocess # do stuff at the shell level +import subprocess # do stuff at the shell level + +import common env = common.prepare_env() diff --git a/resources/ci/common/list_actions.py b/resources/ci/common/list_actions.py index ec4caf5f..52515837 100644 --- a/resources/ci/common/list_actions.py +++ b/resources/ci/common/list_actions.py @@ -6,9 +6,10 @@ import json import os import ssl import urllib.request -import yaml from json.decoder import JSONDecodeError +import yaml + allACTIONS = {} listACTIONS = [] diff --git a/resources/ci/common/local_install.py b/resources/ci/common/local_install.py index 02cc25a5..ec4aec2f 100644 --- a/resources/ci/common/local_install.py +++ b/resources/ci/common/local_install.py @@ -1,8 +1,8 @@ -import install -import get_get_pip - import argparse +import get_get_pip +import install + parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--py', default=0) parser.add_argument('--user', default=False, action="store_true") diff --git a/resources/ci/common/my_path.py b/resources/ci/common/my_path.py index 7d91f15e..61c4546e 100644 --- a/resources/ci/common/my_path.py +++ b/resources/ci/common/my_path.py @@ -1,6 +1,7 @@ import os import sys + def get_py_path(): user_paths = os.environ["PATH"].split(os.pathsep) (python,py) = ("","") diff --git a/resources/ci/common/prepare_appversion.py b/resources/ci/common/prepare_appversion.py index 0f413298..47c71d84 100644 --- a/resources/ci/common/prepare_appversion.py +++ b/resources/ci/common/prepare_appversion.py @@ -1,6 +1,7 @@ +import os # for env vars +from shutil import copy # file manipulation + import common -import os # for env vars -from shutil import copy # file manipulation env = common.prepare_env() diff --git a/resources/ci/common/prepare_binary.py b/resources/ci/common/prepare_binary.py index 4d9ac5e4..a4b9626a 100644 --- a/resources/ci/common/prepare_binary.py +++ b/resources/ci/common/prepare_binary.py @@ -2,11 +2,12 @@ Locate and prepare binary builds """ # import distutils.dir_util # for copying trees -import os # for env vars +import os # for env vars +from shutil import move # file manipulation + # import stat # for file stats # import subprocess # do stuff at the shell level import common -from shutil import move # file manipulation env = common.prepare_env() diff --git a/resources/ci/common/prepare_release.py b/resources/ci/common/prepare_release.py index c4b4bce3..0b9896a9 100644 --- a/resources/ci/common/prepare_release.py +++ b/resources/ci/common/prepare_release.py @@ -1,10 +1,11 @@ -import distutils.dir_util # for copying trees -import os # for env vars -import stat # for file stats -import subprocess # do stuff at the shell level +import distutils.dir_util # for copying trees +import os # for env vars +import stat # for file stats +import subprocess # do stuff at the shell level +from shutil import copy, make_archive, move, rmtree # file manipulation + import common from git_clean import git_clean -from shutil import copy, make_archive, move, rmtree # file manipulation env = common.prepare_env() # get env vars diff --git a/source/classes/BabelFish.py b/source/classes/BabelFish.py index 40b6463f..e20dd536 100644 --- a/source/classes/BabelFish.py +++ b/source/classes/BabelFish.py @@ -2,6 +2,7 @@ import json import locale import os + class BabelFish(): def __init__(self,subpath=["resources","app","meta"],lang=None): localization_string = locale.getdefaultlocale()[0] #get set localization diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 7a3f3712..780b4969 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -1,17 +1,18 @@ import os -import urllib.request import urllib.parse -import yaml -from typing import Any -from yaml.representer import Representer -from Utils import HexInt, hex_representer +import urllib.request from collections import defaultdict from pathlib import Path +from typing import Any + +import yaml +from yaml.representer import Representer import RaceRandom as random -from BaseClasses import LocationType, DoorType +from BaseClasses import DoorType, LocationType from OverworldShuffle import default_flute_connections, flute_data -from source.tools.MysteryUtils import roll_settings, get_weights +from source.tools.MysteryUtils import get_weights, roll_settings +from Utils import HexInt, hex_representer class CustomSettings(object): diff --git a/source/classes/ItemGfxSelector.py b/source/classes/ItemGfxSelector.py index ee5d528d..5f8b561a 100644 --- a/source/classes/ItemGfxSelector.py +++ b/source/classes/ItemGfxSelector.py @@ -1,5 +1,20 @@ -from tkinter import Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, LEFT, BOTTOM, X, RIGHT, TOP import os +from tkinter import ( + BOTTOM, + LEFT, + RIGHT, + TOP, + Button, + Canvas, + Frame, + Label, + LabelFrame, + PhotoImage, + Scrollbar, + Toplevel, + X, +) + from GuiUtils import ToolTips, set_icon from Utils import local_path diff --git a/source/classes/SFX.py b/source/classes/SFX.py index b98a76f8..c3724a3d 100644 --- a/source/classes/SFX.py +++ b/source/classes/SFX.py @@ -1,5 +1,6 @@ -from enum import IntEnum import random +from enum import IntEnum + from Utils import int16_as_bytes, snes_to_pc diff --git a/source/classes/SpriteSelector.py b/source/classes/SpriteSelector.py index 9a18cacd..ed5d3c54 100644 --- a/source/classes/SpriteSelector.py +++ b/source/classes/SpriteSelector.py @@ -1,16 +1,36 @@ -from tkinter import filedialog, messagebox, Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, ALL, LEFT, BOTTOM, X, RIGHT, TOP, EW, NS -from glob import glob import json import os import random import shutil import ssl +import webbrowser +from glob import glob +from tkinter import ( + ALL, + BOTTOM, + EW, + LEFT, + NS, + RIGHT, + TOP, + Button, + Canvas, + Frame, + Label, + LabelFrame, + PhotoImage, + Scrollbar, + Toplevel, + X, + filedialog, + messagebox, +) from urllib.parse import urlparse from urllib.request import urlopen -import webbrowser -from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress + +from GuiUtils import BackgroundTaskProgress, ToolTips, set_icon from Rom import Sprite -from Utils import is_bundled, local_path, output_path, open_file +from Utils import is_bundled, local_path, open_file, output_path class SpriteSelector(object): diff --git a/source/classes/diags.py b/source/classes/diags.py index 9d2abb82..d971fc95 100644 --- a/source/classes/diags.py +++ b/source/classes/diags.py @@ -1,4 +1,8 @@ -import platform, sys, os, subprocess +import os +import platform +import subprocess +import sys + try: import pkg_resources except ModuleNotFoundError as e: @@ -7,6 +11,7 @@ import datetime from Versions import DRVersion, GKVersion, ORVersion + def diagpad(str): return str.ljust(40, '.') diff --git a/source/dungeon/DungeonStitcher.py b/source/dungeon/DungeonStitcher.py index d7ce3c4f..abdc5df6 100644 --- a/source/dungeon/DungeonStitcher.py +++ b/source/dungeon/DungeonStitcher.py @@ -1,11 +1,18 @@ -import RaceRandom as random import collections import logging import time -from BaseClasses import CrystalBarrier, DoorType, Hook, RegionType, Sector -from BaseClasses import hook_from_door, flooded_keys -from Regions import location_events, flooded_keys_reverse +import RaceRandom as random +from BaseClasses import ( + CrystalBarrier, + DoorType, + Hook, + RegionType, + Sector, + flooded_keys, + hook_from_door, +) +from Regions import flooded_keys_reverse, location_events def pre_validate(builder, entrance_region_names, split_dungeon, world, player): diff --git a/source/dungeon/EnemyList.py b/source/dungeon/EnemyList.py index 32909d37..2511361f 100644 --- a/source/dungeon/EnemyList.py +++ b/source/dungeon/EnemyList.py @@ -1,5 +1,5 @@ -from collections import defaultdict, deque import typing +from collections import defaultdict, deque import yaml from yaml.representer import Representer @@ -13,9 +13,9 @@ import RaceRandom as random from BaseClasses import Location, LocationType, RegionType from Items import ItemFactory from PotShuffle import key_drop_special -from Utils import snes_to_pc, pc_to_snes, int16_as_bytes - from source.overworld.EntranceData import door_addresses +from Utils import int16_as_bytes, pc_to_snes, snes_to_pc + class EnemyStats: def __init__(self, sprite, static, drop_flag=False, prize_pack: typing.Union[tuple, int] = 0, diff --git a/source/dungeon/RoomList.py b/source/dungeon/RoomList.py index 951f5b33..bb81fb2a 100644 --- a/source/dungeon/RoomList.py +++ b/source/dungeon/RoomList.py @@ -3,9 +3,8 @@ try: except ImportError: from enum import IntFlag as FastEnum - from RoomData import DoorKind, Position -from source.dungeon.RoomObject import RoomObject, DoorObject +from source.dungeon.RoomObject import DoorObject, RoomObject class Room: diff --git a/source/enemizer/Bossmizer.py b/source/enemizer/Bossmizer.py index 7b10262e..55cb2833 100644 --- a/source/enemizer/Bossmizer.py +++ b/source/enemizer/Bossmizer.py @@ -1,10 +1,9 @@ import RaceRandom as random -from Utils import snes_to_pc - -from source.dungeon.EnemyList import EnemySprite, SpriteType, Sprite -from source.dungeon.RoomList import boss_rooms, gt_boss_room, Room0006 +from source.dungeon.EnemyList import EnemySprite, Sprite, SpriteType +from source.dungeon.RoomList import Room0006, boss_rooms, gt_boss_room from source.dungeon.RoomObject import RoomObject from source.enemizer.SpriteSheets import required_boss_sheets +from Utils import snes_to_pc def get_dungeon_boss_room(dungeon_name, level): diff --git a/source/enemizer/Enemizer.py b/source/enemizer/Enemizer.py index c1d37981..3ad3214a 100644 --- a/source/enemizer/Enemizer.py +++ b/source/enemizer/Enemizer.py @@ -1,13 +1,17 @@ -import RaceRandom as random from collections import defaultdict -from Utils import snes_to_pc -from source.dungeon.EnemyList import SpriteType, EnemySprite, sprite_translation +import RaceRandom as random +from source.dungeon.EnemyList import EnemySprite, SpriteType, sprite_translation from source.dungeon.RoomList import Room010C from source.enemizer.SpecialEnemyModes import set_mimics, write_mimic_changes -from source.enemizer.SpriteSheets import sub_group_choices, sheets_with_free_gfx -from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets +from source.enemizer.SpriteSheets import ( + randomize_overworld_sprite_sheets, + randomize_underworld_sprite_sheets, + sheets_with_free_gfx, + sub_group_choices, +) from source.enemizer.TilePattern import tile_patterns +from Utils import snes_to_pc shutter_sprites = { 0xb8: {0, 1, 2, 3, 4, 5}, 0xb: {4, 5, 6, 7, 8, 9}, 0x1b: {3, 4, 5}, 0x4b: {0, 3, 4}, 0x4: {9, 13, 14}, diff --git a/source/enemizer/EnemizerTestHarness.py b/source/enemizer/EnemizerTestHarness.py index c8f1070c..d8b5ba26 100644 --- a/source/enemizer/EnemizerTestHarness.py +++ b/source/enemizer/EnemizerTestHarness.py @@ -1,12 +1,18 @@ -from types import SimpleNamespace from collections import Counter, defaultdict +from types import SimpleNamespace -from source.dungeon.EnemyList import enemy_names, SpriteType -from source.enemizer.Enemizer import randomize_underworld_rooms, randomize_overworld_enemies -from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets -from source.rom.DataTables import init_data_tables -from source.enemizer.DamageTables import DamageTable import RaceRandom as random +from source.dungeon.EnemyList import SpriteType, enemy_names +from source.enemizer.DamageTables import DamageTable +from source.enemizer.Enemizer import ( + randomize_overworld_enemies, + randomize_underworld_rooms, +) +from source.enemizer.SpriteSheets import ( + randomize_overworld_sprite_sheets, + randomize_underworld_sprite_sheets, +) +from source.rom.DataTables import init_data_tables def calculate_odds(): diff --git a/source/enemizer/EnemyLogic.py b/source/enemizer/EnemyLogic.py index df8a21c5..a460851b 100644 --- a/source/enemizer/EnemyLogic.py +++ b/source/enemizer/EnemyLogic.py @@ -2,9 +2,8 @@ import math from collections import defaultdict import RaceRandom as random - -from source.logic.Rule import RuleFactory from source.dungeon.EnemyList import EnemySprite +from source.logic.Rule import RuleFactory # these are for drops only diff --git a/source/enemizer/OwEnemyList.py b/source/enemizer/OwEnemyList.py index f89b16c6..581d2477 100644 --- a/source/enemizer/OwEnemyList.py +++ b/source/enemizer/OwEnemyList.py @@ -1,4 +1,5 @@ -from source.dungeon.EnemyList import Sprite, EnemySprite +from source.dungeon.EnemyList import EnemySprite, Sprite + vanilla_sprites_ow = {} diff --git a/source/enemizer/SpecialEnemyModes.py b/source/enemizer/SpecialEnemyModes.py index 5e80310c..fd061f42 100644 --- a/source/enemizer/SpecialEnemyModes.py +++ b/source/enemizer/SpecialEnemyModes.py @@ -1,8 +1,12 @@ import RaceRandom as random +from source.dungeon.EnemyList import ( + EnemySprite, + SpriteType, + enemy_names, + sprite_translation, +) from Utils import snes_to_pc -from source.dungeon.EnemyList import EnemySprite, SpriteType, sprite_translation, enemy_names - change_idx_1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 31, 32, 35, 38, 65, 66, 67, 68, 70, 71, 76, 77, 78, 81, 83, 89, 91, 92, 94, 97, 100, 101, 102, 103, 104, 105, 106, 107] diff --git a/source/enemizer/SpriteSheets.py b/source/enemizer/SpriteSheets.py index 14ec54e7..1347e32e 100644 --- a/source/enemizer/SpriteSheets.py +++ b/source/enemizer/SpriteSheets.py @@ -1,8 +1,14 @@ import logging from collections import defaultdict -import RaceRandom as random -from source.dungeon.EnemyList import EnemySprite, SpriteType, enemy_names, sprite_translation, overlord_names +import RaceRandom as random +from source.dungeon.EnemyList import ( + EnemySprite, + SpriteType, + enemy_names, + overlord_names, + sprite_translation, +) from source.dungeon.RoomConstants import * diff --git a/source/enemizer/TilePattern.py b/source/enemizer/TilePattern.py index a452c547..f85b94dc 100644 --- a/source/enemizer/TilePattern.py +++ b/source/enemizer/TilePattern.py @@ -1,6 +1,6 @@ -import os -import json import codecs +import json +import os if __name__ == '__main__': directory = './EnemizerCLI.Core/tiles' diff --git a/source/gui/adjust/overview.py b/source/gui/adjust/overview.py index 2d062c8a..1c61267d 100644 --- a/source/gui/adjust/overview.py +++ b/source/gui/adjust/overview.py @@ -1,15 +1,31 @@ -from tkinter import ttk, filedialog, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X, BOTTOM -from AdjusterMain import adjust, patch -from argparse import Namespace -from source.classes.SpriteSelector import SpriteSelector -from source.classes.ItemGfxSelector import ItemGfxSelector -import source.gui.widgets as widgets import json import logging import os +from argparse import Namespace +from tkinter import ( + BOTTOM, + LEFT, + RIGHT, + Button, + E, + Entry, + Frame, + Label, + StringVar, + W, + X, + filedialog, + messagebox, + ttk, +) +import source.gui.widgets as widgets +from AdjusterMain import adjust, patch +from source.classes.ItemGfxSelector import ItemGfxSelector +from source.classes.SpriteSelector import SpriteSelector from Utils import output_path + def adjust_page(top, parent, settings): # Adjust page self = ttk.Frame(parent) diff --git a/source/gui/bottom.py b/source/gui/bottom.py index 35b6c516..2784ea62 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -1,17 +1,29 @@ -from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, LEFT, RIGHT, X -from argparse import Namespace import logging import os import random import re +from argparse import Namespace +from tkinter import ( + LEFT, + RIGHT, + Button, + Entry, + Frame, + Label, + StringVar, + X, + messagebox, + ttk, +) + +import source.classes.constants as CONST +import source.gui.widgets as widgets from CLI import parse_cli from Fill import FillError -from Main import main, export_yaml, EnemizerError -from Utils import local_path, output_path, open_file, update_deprecated_args -import source.classes.constants as CONST -from source.gui.randomize.multiworld import multiworld_page -import source.gui.widgets as widgets +from Main import EnemizerError, export_yaml, main from source.classes.Empty import Empty +from source.gui.randomize.multiworld import multiworld_page +from Utils import local_path, open_file, output_path, update_deprecated_args def bottom_frame(self, parent, args=None): diff --git a/source/gui/custom/overview.py b/source/gui/custom/overview.py index b62bff71..5fccbf03 100644 --- a/source/gui/custom/overview.py +++ b/source/gui/custom/overview.py @@ -1,9 +1,10 @@ -from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y -import source.gui.widgets as widgets import json import os +from tkinter import LEFT, TOP, VERTICAL, E, Frame, N, W, X, Y, ttk import source.classes.constants as CONST +import source.gui.widgets as widgets + def custom_page(top,parent): # Custom Item Pool diff --git a/source/gui/loadcliargs.py b/source/gui/loadcliargs.py index 6ca7ad60..bf5584fe 100644 --- a/source/gui/loadcliargs.py +++ b/source/gui/loadcliargs.py @@ -1,10 +1,11 @@ -from source.classes.SpriteSelector import SpriteSelector as spriteSelector -from source.gui.randomize.gameoptions import set_sprite -from Rom import Sprite, get_sprite_from_name -from Utils import update_deprecated_args import source.classes.constants as CONST +from Rom import Sprite, get_sprite_from_name from source.classes.BabelFish import BabelFish from source.classes.Empty import Empty +from source.classes.SpriteSelector import SpriteSelector as spriteSelector +from source.gui.randomize.gameoptions import set_sprite +from Utils import update_deprecated_args + # Load args/settings for most tabs def loadcliargs(gui, args, settings=None): diff --git a/source/gui/randomize/dungeon.py b/source/gui/randomize/dungeon.py index 88f11379..efce57a3 100644 --- a/source/gui/randomize/dungeon.py +++ b/source/gui/randomize/dungeon.py @@ -1,7 +1,9 @@ -from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT, TOP -import source.gui.widgets as widgets import json import os +from tkinter import LEFT, RIGHT, TOP, E, Frame, Label, W, ttk + +import source.gui.widgets as widgets + def dungeon_page(parent): # Dungeon Shuffle diff --git a/source/gui/randomize/enemizer.py b/source/gui/randomize/enemizer.py index 40bf055c..a98f89ca 100644 --- a/source/gui/randomize/enemizer.py +++ b/source/gui/randomize/enemizer.py @@ -1,10 +1,27 @@ -from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, N, E, W, LEFT, RIGHT, BOTTOM, X -import source.gui.widgets as widgets import json import os import webbrowser +from tkinter import ( + BOTTOM, + LEFT, + RIGHT, + Button, + E, + Entry, + Frame, + Label, + N, + StringVar, + W, + X, + filedialog, + ttk, +) + +import source.gui.widgets as widgets from source.classes.Empty import Empty + def enemizer_page(parent,settings): # Enemizer self = ttk.Frame(parent) diff --git a/source/gui/randomize/entrando.py b/source/gui/randomize/entrando.py index ba2bc365..45578470 100644 --- a/source/gui/randomize/entrando.py +++ b/source/gui/randomize/entrando.py @@ -1,7 +1,9 @@ -from tkinter import ttk, Frame, E, W, LEFT, RIGHT -import source.gui.widgets as widgets import json import os +from tkinter import LEFT, RIGHT, E, Frame, W, ttk + +import source.gui.widgets as widgets + def entrando_page(parent): # Entrance Randomizer diff --git a/source/gui/randomize/gameoptions.py b/source/gui/randomize/gameoptions.py index 5f3dfddf..e2e45691 100644 --- a/source/gui/randomize/gameoptions.py +++ b/source/gui/randomize/gameoptions.py @@ -1,10 +1,25 @@ -from tkinter import ttk, StringVar, Button, Entry, Frame, Label, NE, NW, E, W, LEFT, RIGHT -from functools import partial -import source.classes.SpriteSelector as spriteSelector -import source.classes.ItemGfxSelector as itemGfxSelector -import source.gui.widgets as widgets import json import os +from functools import partial +from tkinter import ( + LEFT, + NE, + NW, + RIGHT, + Button, + E, + Entry, + Frame, + Label, + StringVar, + W, + ttk, +) + +import source.classes.ItemGfxSelector as itemGfxSelector +import source.classes.SpriteSelector as spriteSelector +import source.gui.widgets as widgets + def gameoptions_page(top, parent): # Game Options diff --git a/source/gui/randomize/generation.py b/source/gui/randomize/generation.py index f67e48e7..65e546ca 100644 --- a/source/gui/randomize/generation.py +++ b/source/gui/randomize/generation.py @@ -1,12 +1,29 @@ -from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, E, W, LEFT, X, Text, Tk, INSERT -import source.classes.diags as diagnostics -import source.gui.widgets as widgets import json import os from functools import partial +from tkinter import ( + INSERT, + LEFT, + Button, + E, + Entry, + Frame, + Label, + StringVar, + Text, + Tk, + W, + X, + filedialog, + ttk, +) + +import source.classes.diags as diagnostics +import source.gui.widgets as widgets from source.classes.Empty import Empty from Versions import DRVersion + def generation_page(parent,settings): # Generation Setup self = ttk.Frame(parent) diff --git a/source/gui/randomize/item.py b/source/gui/randomize/item.py index bdb47747..4d183c50 100644 --- a/source/gui/randomize/item.py +++ b/source/gui/randomize/item.py @@ -1,8 +1,24 @@ -from tkinter import messagebox, ttk, font, Button, Frame, E, W, TOP, LEFT, RIGHT, X, Y, Label -import source.gui.widgets as widgets -from source.classes.Empty import Empty import json import os +from tkinter import ( + LEFT, + RIGHT, + TOP, + Button, + E, + Frame, + Label, + W, + X, + Y, + font, + messagebox, + ttk, +) + +import source.gui.widgets as widgets +from source.classes.Empty import Empty + def item_page(parent): # Item Randomizer diff --git a/source/gui/randomize/multiworld.py b/source/gui/randomize/multiworld.py index 493f31b5..a3e53fbf 100644 --- a/source/gui/randomize/multiworld.py +++ b/source/gui/randomize/multiworld.py @@ -1,9 +1,11 @@ -from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, X, LEFT -import source.gui.widgets as widgets import json import os +from tkinter import LEFT, E, Entry, Frame, Label, N, StringVar, W, X, ttk + +import source.gui.widgets as widgets from source.classes.Empty import Empty + def multiworld_page(parent,settings): # Multiworld self = ttk.Frame(parent) diff --git a/source/gui/randomize/overworld.py b/source/gui/randomize/overworld.py index 54120417..b453195b 100644 --- a/source/gui/randomize/overworld.py +++ b/source/gui/randomize/overworld.py @@ -1,7 +1,9 @@ -from tkinter import ttk, Frame, Label, W, E, NW, LEFT, RIGHT, X, Y, TOP -import source.gui.widgets as widgets import json import os +from tkinter import LEFT, NW, RIGHT, TOP, E, Frame, Label, W, X, Y, ttk + +import source.gui.widgets as widgets + def overworld_page(parent): # Overworld Shuffle diff --git a/source/gui/startinventory/overview.py b/source/gui/startinventory/overview.py index 97784521..c2820649 100644 --- a/source/gui/startinventory/overview.py +++ b/source/gui/startinventory/overview.py @@ -1,9 +1,10 @@ -from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y -import source.gui.widgets as widgets import json import os +from tkinter import LEFT, TOP, VERTICAL, E, Frame, N, W, X, Y, ttk import source.classes.constants as CONST +import source.gui.widgets as widgets + def startinventory_page(top,parent): # Starting Inventory diff --git a/source/gui/widgets.py b/source/gui/widgets.py index 6038e3a2..001d76a7 100644 --- a/source/gui/widgets.py +++ b/source/gui/widgets.py @@ -1,7 +1,22 @@ -from tkinter import messagebox, Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, LEFT, RIGHT, X -from tkinter import Button +from tkinter import ( + LEFT, + RIGHT, + Button, + Checkbutton, + Entry, + Frame, + IntVar, + Label, + OptionMenu, + Spinbox, + StringVar, + X, + messagebox, +) + from source.classes.Empty import Empty + # Override Spinbox to include mousewheel support for changing value class mySpinbox(Spinbox): def __init__(self, *args, **kwargs): diff --git a/source/item/District.py b/source/item/District.py index bec993bd..867e356d 100644 --- a/source/item/District.py +++ b/source/item/District.py @@ -2,7 +2,8 @@ from collections import deque from BaseClasses import CollectionState, RegionType from Dungeons import dungeon_table -from OWEdges import OWTileRegions, OWTileDistricts +from OWEdges import OWTileDistricts, OWTileRegions + class District(object): diff --git a/source/item/FillUtil.py b/source/item/FillUtil.py index 25bebbcd..365a803f 100644 --- a/source/item/FillUtil.py +++ b/source/item/FillUtil.py @@ -1,13 +1,13 @@ -import RaceRandom as random import logging from collections import defaultdict -from source.item.District import resolve_districts -from BaseClasses import PotItem, PotFlags, LocationType +import RaceRandom as random +from BaseClasses import LocationType, PotFlags, PotItem from DoorShuffle import validate_vanilla_reservation from Dungeons import dungeon_table -from Items import item_table, ItemFactory +from Items import ItemFactory, item_table from PotShuffle import vanilla_pots +from source.item.District import resolve_districts class ItemPoolConfig(object): diff --git a/source/logic/Rule.py b/source/logic/Rule.py index 970062bb..fc60842b 100644 --- a/source/logic/Rule.py +++ b/source/logic/Rule.py @@ -1,6 +1,6 @@ import itertools - from collections import OrderedDict + try: from fast_enum import FastEnum except ImportError: diff --git a/source/meta/build.py b/source/meta/build.py index 4cc29436..b5c22b2c 100644 --- a/source/meta/build.py +++ b/source/meta/build.py @@ -2,11 +2,11 @@ Build Entrypoints ''' import json -import platform import os # for checking for dirs +import platform import re from json.decoder import JSONDecodeError -from subprocess import Popen, PIPE, STDOUT, CalledProcessError +from subprocess import PIPE, STDOUT, CalledProcessError, Popen DEST_DIRECTORY = "." diff --git a/source/meta/check_requirements.py b/source/meta/check_requirements.py index 6976f707..c6fcd576 100644 --- a/source/meta/check_requirements.py +++ b/source/meta/check_requirements.py @@ -25,7 +25,7 @@ def check_requirements(console=False): logger.error('https://github.com/aerinon/ALttPDoorRandomizer/blob/DoorDev/docs/BUILDING.md') else: import webbrowser - from tkinter import Tk, Label, Button, Frame + from tkinter import Button, Frame, Label, Tk master = Tk() master.title('Error') diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index 8ef10110..b0779e18 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -1,10 +1,9 @@ -import RaceRandom as random -import logging import copy +import logging +from collections import OrderedDict, defaultdict -from collections import defaultdict, OrderedDict +import RaceRandom as random from BaseClasses import RegionType - from source.overworld.EntranceData import door_addresses @@ -857,9 +856,9 @@ def get_nearby_entrances(avail, start_region): def get_accessible_entrances(start_region, avail, assumed_inventory=[], cross_world=False, region_rules=True, exit_rules=True, include_one_ways=False, restrictive_follower=False): - from Main import copy_world_premature from BaseClasses import CollectionState from Items import ItemFactory + from Main import copy_world_premature from OverworldShuffle import build_accessible_region_list, one_way_ledges for p in range(1, avail.world.players + 1): diff --git a/source/rom/DataTables.py b/source/rom/DataTables.py index f082a4f5..0ba42bab 100644 --- a/source/rom/DataTables.py +++ b/source/rom/DataTables.py @@ -1,13 +1,28 @@ from collections import defaultdict -from Utils import snes_to_pc, int24_as_bytes, int16_as_bytes, load_cached_yaml, pc_to_snes - -from source.dungeon.EnemyList import EnemyTable, init_vanilla_sprites, vanilla_sprites, init_enemy_stats, EnemySprite -from source.dungeon.EnemyList import sprite_translation +from source.dungeon.EnemyList import ( + EnemySprite, + EnemyTable, + init_enemy_stats, + init_vanilla_sprites, + sprite_translation, + vanilla_sprites, +) from source.dungeon.RoomHeader import init_room_headers from source.dungeon.RoomList import Room0127 from source.enemizer.OwEnemyList import init_vanilla_sprites_ow, vanilla_sprites_ow -from source.enemizer.SpriteSheets import init_sprite_sheets, init_sprite_requirements, SheetChoice +from source.enemizer.SpriteSheets import ( + SheetChoice, + init_sprite_requirements, + init_sprite_sheets, +) +from Utils import ( + int16_as_bytes, + int24_as_bytes, + load_cached_yaml, + pc_to_snes, + snes_to_pc, +) def convert_area_id_to_offset(area_id): diff --git a/source/tools/BPS.py b/source/tools/BPS.py index 78c374cb..53c151ee 100644 --- a/source/tools/BPS.py +++ b/source/tools/BPS.py @@ -1,11 +1,10 @@ # Code derived from https://github.com/marcrobledo/RomPatcher.js (MIT License) import sys - +from binascii import crc32 +from collections import defaultdict from time import perf_counter -from collections import defaultdict -from binascii import crc32 try: from fast_enum import FastEnum except ImportError: diff --git a/source/tools/MysteryUtils.py b/source/tools/MysteryUtils.py index ac130d8b..441d4fdc 100644 --- a/source/tools/MysteryUtils.py +++ b/source/tools/MysteryUtils.py @@ -1,12 +1,13 @@ import argparse -import RaceRandom as random import os +import urllib.parse +import urllib.request from pathlib import Path -import urllib.request -import urllib.parse import yaml +import RaceRandom as random + def get_weights(path): if os.path.exists(Path(path)): diff --git a/test-options.py b/test-options.py index 324d38c6..1ceb34bd 100644 --- a/test-options.py +++ b/test-options.py @@ -1,9 +1,12 @@ from __future__ import annotations -from aenum import Enum, IntEnum, extend_enum -from source.classes.BabelFish import BabelFish + import json import os +from aenum import Enum, IntEnum, extend_enum + +from source.classes.BabelFish import BabelFish + fish = BabelFish(lang="en") def tokenize(token): diff --git a/test/MysteryTestSuite.py b/test/MysteryTestSuite.py index e14baa61..429c95c9 100644 --- a/test/MysteryTestSuite.py +++ b/test/MysteryTestSuite.py @@ -1,9 +1,9 @@ +import argparse +import concurrent.futures +import multiprocessing import os import subprocess import sys -import multiprocessing -import concurrent.futures -import argparse from collections import OrderedDict cpu_threads = multiprocessing.cpu_count() diff --git a/test/NewTestSuite.py b/test/NewTestSuite.py index c5beba4f..6c974855 100644 --- a/test/NewTestSuite.py +++ b/test/NewTestSuite.py @@ -1,10 +1,10 @@ +import argparse +import concurrent.futures import fnmatch +import multiprocessing import os import subprocess import sys -import multiprocessing -import concurrent.futures -import argparse from collections import OrderedDict cpu_threads = multiprocessing.cpu_count() diff --git a/test/dungeons/TestDungeon.py b/test/dungeons/TestDungeon.py index 1db87e39..e4da82bc 100644 --- a/test/dungeons/TestDungeon.py +++ b/test/dungeons/TestDungeon.py @@ -1,12 +1,12 @@ import unittest -from BaseClasses import World, CollectionState +from BaseClasses import CollectionState, World from Dungeons import create_dungeons, get_dungeon_item_pool from ItemList import difficulties, generate_itempool from Items import ItemFactory from Regions import create_regions from Rules import set_rules -from source.overworld.EntranceShuffle2 import mandatory_connections, connect_simple +from source.overworld.EntranceShuffle2 import connect_simple, mandatory_connections class TestDungeon(unittest.TestCase): diff --git a/test/inverted/TestInverted.py b/test/inverted/TestInverted.py index 70e3fd6b..24f518b8 100644 --- a/test/inverted/TestInverted.py +++ b/test/inverted/TestInverted.py @@ -1,16 +1,21 @@ +from test.TestBase import TestBase + from BaseClasses import World -from DoorShuffle import link_doors from Doors import create_doors +from DoorShuffle import link_doors from Dungeons import create_dungeons, get_dungeon_item_pool -from OverworldShuffle import link_overworld -from ItemList import generate_itempool, difficulties +from ItemList import difficulties, generate_itempool from Items import ItemFactory -from Regions import create_regions, mark_light_dark_world_regions, create_dungeon_regions, create_shops +from OverworldShuffle import link_overworld +from Regions import ( + create_dungeon_regions, + create_regions, + create_shops, + mark_light_dark_world_regions, +) from RoomData import create_rooms from Rules import set_rules - from source.overworld.EntranceShuffle2 import link_entrances_new -from test.TestBase import TestBase class TestInverted(TestBase): diff --git a/test/inverted/TestInvertedBombRules.py b/test/inverted/TestInvertedBombRules.py index c3a94ff8..d8675569 100644 --- a/test/inverted/TestInvertedBombRules.py +++ b/test/inverted/TestInvertedBombRules.py @@ -1,14 +1,29 @@ import unittest +from test.inverted.TestInverted import TestInverted from BaseClasses import World from Dungeons import create_dungeons -# todo: this test needs to be rewritten unfortunately -from source.overworld.EntranceShuffle2 import connect_entrance, Inverted_LW_Entrances, Inverted_LW_Dungeon_Entrances, Inverted_LW_Single_Cave_Doors, Inverted_Old_Man_Entrances, Inverted_DW_Entrances, Inverted_DW_Dungeon_Entrances, Inverted_DW_Single_Cave_Doors, \ - Inverted_LW_Entrances_Must_Exit, Inverted_LW_Dungeon_Entrances_Must_Exit, Inverted_Bomb_Shop_Multi_Cave_Doors, Inverted_Bomb_Shop_Single_Cave_Doors, Inverted_Blacksmith_Single_Cave_Doors, Inverted_Blacksmith_Multi_Cave_Doors -from Regions import create_regions from ItemList import difficulties +from Regions import create_regions from Rules import set_inverted_big_bomb_rules -from test.inverted.TestInverted import TestInverted + +# todo: this test needs to be rewritten unfortunately +from source.overworld.EntranceShuffle2 import ( + Inverted_Blacksmith_Multi_Cave_Doors, + Inverted_Blacksmith_Single_Cave_Doors, + Inverted_Bomb_Shop_Multi_Cave_Doors, + Inverted_Bomb_Shop_Single_Cave_Doors, + Inverted_DW_Dungeon_Entrances, + Inverted_DW_Entrances, + Inverted_DW_Single_Cave_Doors, + Inverted_LW_Dungeon_Entrances, + Inverted_LW_Dungeon_Entrances_Must_Exit, + Inverted_LW_Entrances, + Inverted_LW_Entrances_Must_Exit, + Inverted_LW_Single_Cave_Doors, + Inverted_Old_Man_Entrances, + connect_entrance, +) class TestInvertedBombRules(TestInverted): diff --git a/test/inverted_owg/TestDungeons.py b/test/inverted_owg/TestDungeons.py index 3864bff6..4001039d 100644 --- a/test/inverted_owg/TestDungeons.py +++ b/test/inverted_owg/TestDungeons.py @@ -1,5 +1,6 @@ from test.inverted_owg.TestInvertedOWG import TestInvertedOWG + class TestDungeons(TestInvertedOWG): def testFirstDungeonChests(self): diff --git a/test/inverted_owg/TestInvertedOWG.py b/test/inverted_owg/TestInvertedOWG.py index d0b0ba6b..6f13e050 100644 --- a/test/inverted_owg/TestInvertedOWG.py +++ b/test/inverted_owg/TestInvertedOWG.py @@ -1,16 +1,22 @@ +from test.TestBase import TestBase + from BaseClasses import World -from DoorShuffle import link_doors from Doors import create_doors +from DoorShuffle import link_doors from Dungeons import create_dungeons, get_dungeon_item_pool -from OverworldShuffle import link_overworld -from source.overworld.EntranceShuffle2 import link_entrances_new -from ItemList import generate_itempool, difficulties +from ItemList import difficulties, generate_itempool from Items import ItemFactory from OverworldGlitchRules import create_owg_connections -from Regions import create_regions, mark_light_dark_world_regions, create_dungeon_regions, create_shops +from OverworldShuffle import link_overworld +from Regions import ( + create_dungeon_regions, + create_regions, + create_shops, + mark_light_dark_world_regions, +) from RoomData import create_rooms from Rules import set_rules -from test.TestBase import TestBase +from source.overworld.EntranceShuffle2 import link_entrances_new class TestInvertedOWG(TestBase): diff --git a/test/owg/TestVanillaOWG.py b/test/owg/TestVanillaOWG.py index 989cf64e..5669524e 100644 --- a/test/owg/TestVanillaOWG.py +++ b/test/owg/TestVanillaOWG.py @@ -1,16 +1,22 @@ +from test.TestBase import TestBase + from BaseClasses import World -from DoorShuffle import link_doors from Doors import create_doors +from DoorShuffle import link_doors from Dungeons import create_dungeons, get_dungeon_item_pool -from OverworldShuffle import link_overworld -from source.overworld.EntranceShuffle2 import link_entrances_new from ItemList import difficulties, generate_itempool from Items import ItemFactory from OverworldGlitchRules import create_owg_connections -from Regions import create_regions, create_dungeon_regions, create_shops, mark_light_dark_world_regions +from OverworldShuffle import link_overworld +from Regions import ( + create_dungeon_regions, + create_regions, + create_shops, + mark_light_dark_world_regions, +) from RoomData import create_rooms from Rules import set_rules -from test.TestBase import TestBase +from source.overworld.EntranceShuffle2 import link_entrances_new class TestVanillaOWG(TestBase): diff --git a/test/stats/EntranceShuffleStats.py b/test/stats/EntranceShuffleStats.py index 53b2e7e5..a47f5888 100644 --- a/test/stats/EntranceShuffleStats.py +++ b/test/stats/EntranceShuffleStats.py @@ -1,16 +1,16 @@ import os import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) -import RaceRandom as random -import time +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) +import time from collections import Counter, defaultdict -from source.overworld.EntranceShuffle2 import link_entrances_new +import RaceRandom as random + # from source.oEntranceShuffle import link_entrances_new from BaseClasses import World -from Regions import create_regions, create_dungeon_regions - +from Regions import create_dungeon_regions, create_regions +from source.overworld.EntranceShuffle2 import link_entrances_new # probably deprecated diff --git a/test/vanilla/TestVanilla.py b/test/vanilla/TestVanilla.py index 91ec449b..2da6100d 100644 --- a/test/vanilla/TestVanilla.py +++ b/test/vanilla/TestVanilla.py @@ -1,15 +1,21 @@ +from test.TestBase import TestBase + from BaseClasses import World -from DoorShuffle import link_doors from Doors import create_doors +from DoorShuffle import link_doors from Dungeons import create_dungeons, get_dungeon_item_pool -from OverworldShuffle import link_overworld -from source.overworld.EntranceShuffle2 import link_entrances_new from ItemList import difficulties, generate_itempool from Items import ItemFactory -from Regions import create_regions, create_dungeon_regions, create_shops, mark_light_dark_world_regions +from OverworldShuffle import link_overworld +from Regions import ( + create_dungeon_regions, + create_regions, + create_shops, + mark_light_dark_world_regions, +) from RoomData import create_rooms from Rules import set_rules -from test.TestBase import TestBase +from source.overworld.EntranceShuffle2 import link_entrances_new class TestVanilla(TestBase): -- 2.43.0 From 640a5bc3a795cb439859810d5f68521b91a6816c Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sat, 24 Jan 2026 22:16:47 -0600 Subject: [PATCH 49/54] Log exception trace on failed generation attempts --- DungeonRandomizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DungeonRandomizer.py b/DungeonRandomizer.py index 1d8388ca..6a168bd7 100755 --- a/DungeonRandomizer.py +++ b/DungeonRandomizer.py @@ -80,7 +80,7 @@ def start(): break except (FillError, EnemizerError, Exception, RuntimeError) as err: failures.append((err, seed)) - logger.warning('Attempt %d - %s: %s', trynum, fish.translate("cli","cli","generation.failed"), err) + logger.exception('Attempt %d - %s: %s', trynum, fish.translate("cli","cli","generation.failed"), err) logger.info('') seed = random.randint(0, 999999999) -- 2.43.0 From 9e5db19c73b109f9b5540852287557d94aaac1b4 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 25 Jan 2026 10:11:10 -0600 Subject: [PATCH 50/54] Change order of parts in rom name for compatibility with webmulti --- Rom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index a51e581e..e4b133b5 100644 --- a/Rom.py +++ b/Rom.py @@ -1898,14 +1898,14 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): raise Exception('ROM header too long. Max 21 bytes, found %d bytes.' % len(rom_header)) if world.players > 1 and world.teams > 1 and len(rom_header) <= 12: - rom.name = bytearray(f"GK_{rom_header}_{team + 1}_{player}", 'utf8') + rom.name = bytearray(f"GK_{team + 1}_{player}_{rom_header}", 'utf8') elif len(rom_header) <= 18: rom.name = bytearray(f"GK_{rom_header}", 'utf8') else: rom.name = bytearray(rom_header, 'utf8') else: if world.players > 1 and world.teams > 1: - rom.name = bytearray(f'GK_{world.seed}_{team + 1}_{player}', 'utf8') + rom.name = bytearray(f'GK_{team + 1}_{player}_{world.seed}', 'utf8') else: rom.name = bytearray(f'GK_{world.seed}', 'utf8') -- 2.43.0 From a51be12a4a47cf21b8e0f25fa409e38ec3456167 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 25 Jan 2026 10:34:37 -0600 Subject: [PATCH 51/54] More romname fixes --- Rom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index e4b133b5..95fe46f3 100644 --- a/Rom.py +++ b/Rom.py @@ -1897,14 +1897,14 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): if len(rom_header) > 21: raise Exception('ROM header too long. Max 21 bytes, found %d bytes.' % len(rom_header)) - if world.players > 1 and world.teams > 1 and len(rom_header) <= 12: + if world.players > 1 and len(rom_header) <= 12: rom.name = bytearray(f"GK_{team + 1}_{player}_{rom_header}", 'utf8') elif len(rom_header) <= 18: rom.name = bytearray(f"GK_{rom_header}", 'utf8') else: rom.name = bytearray(rom_header, 'utf8') else: - if world.players > 1 and world.teams > 1: + if world.players > 1: rom.name = bytearray(f'GK_{team + 1}_{player}_{world.seed}', 'utf8') else: rom.name = bytearray(f'GK_{world.seed}', 'utf8') -- 2.43.0 From a019fa6478fc48428d9f439213da0871761f3db6 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 25 Jan 2026 13:16:35 -0600 Subject: [PATCH 52/54] romname starts with GK --- Main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Main.py b/Main.py index aadbfe06..4c68d0a1 100644 --- a/Main.py +++ b/Main.py @@ -189,7 +189,7 @@ def main(args, seed=None, fish=None): world.player_names[player].append(name) logger.info('') - outfilebase = f'OR_{args.outputname if args.outputname else world.seed}' + outfilebase = f'GK_{args.outputname if args.outputname else world.seed}' for player in range(1, world.players + 1): world.difficulty_requirements[player] = difficulties[world.difficulty[player]] -- 2.43.0 From becff60e05877e7efb00530d3205874a842c4fd4 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 25 Jan 2026 14:31:09 -0600 Subject: [PATCH 53/54] Remove commented out data in SpriteSheets.py --- source/enemizer/SpriteSheets.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/enemizer/SpriteSheets.py b/source/enemizer/SpriteSheets.py index 1347e32e..47b79e92 100644 --- a/source/enemizer/SpriteSheets.py +++ b/source/enemizer/SpriteSheets.py @@ -471,10 +471,6 @@ vanilla_sheets = [ (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x08), (0x5D, 0x49, 0x00, 0x52), (0x55, 0x49, 0x42, 0x43), -# (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), -# (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), -# (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x56, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), -# (0x61, 0x56, 0x33, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50) ] required_boss_sheets = {EnemySprite.ArmosKnight: 9, EnemySprite.Lanmolas: 11, EnemySprite.Moldorm: 12, -- 2.43.0 From 44687216213aa78cbc125b6bf0762b469a638b69 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 25 Jan 2026 14:38:13 -0600 Subject: [PATCH 54/54] Remove another reference to unused base2current.json --- Utils.py | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/Utils.py b/Utils.py index d7436309..1f3663e4 100644 --- a/Utils.py +++ b/Utils.py @@ -8,6 +8,7 @@ import urllib.parse import urllib.request import xml.etree.ElementTree as ET from collections import defaultdict +from hashlib import md5 from itertools import count from math import factorial from pathlib import Path @@ -102,31 +103,13 @@ def close_console(): pass -def make_new_base2current(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', new_rom='working.sfc'): - import hashlib - import json - from collections import OrderedDict - with open(old_rom, 'rb') as stream: - old_rom_data = bytearray(stream.read()) +def get_new_romhash(new_rom='working.sfc'): with open(new_rom, 'rb') as stream: new_rom_data = bytearray(stream.read()) - # extend to 2 mb - old_rom_data.extend(bytearray([0x00] * (2097152 - len(old_rom_data)))) - out_data = OrderedDict() - for idx, old in enumerate(old_rom_data): - new = new_rom_data[idx] - if old != new: - out_data[idx] = [int(new)] - for offset in reversed(list(out_data.keys())): - if offset - 1 in out_data: - out_data[offset-1].extend(out_data.pop(offset)) - with open('data/base2current.json', 'wt') as outfile: - json.dump([{key: value} for key, value in out_data.items()], outfile, separators=(",", ":")) - - basemd5 = hashlib.md5() + basemd5 = md5() basemd5.update(new_rom_data) - return "New Rom Hash: " + basemd5.hexdigest() + return basemd5.hexdigest() def kth_combination(k, l, r): @@ -768,18 +751,18 @@ class bidict(dict): super(bidict, self).__init__(*args, **kwargs) self.inverse = {} for key, value in self.items(): - self.inverse.setdefault(value,[]).append(key) + self.inverse.setdefault(value,[]).append(key) def __setitem__(self, key, value): if key in self: - self.inverse[self[key]].remove(key) + self.inverse[self[key]].remove(key) super(bidict, self).__setitem__(key, value) - self.inverse.setdefault(value,[]).append(key) + self.inverse.setdefault(value,[]).append(key) def __delitem__(self, key): value = self[key] self.inverse.setdefault(value,[]).remove(key) - if value in self.inverse and not self.inverse[value]: + if value in self.inverse and not self.inverse[value]: del self.inverse[value] super(bidict, self).__delitem__(key) @@ -787,12 +770,11 @@ class bidict(dict): class HexInt(int): pass def hex_representer(dumper, data): - import yaml return yaml.ScalarNode('tag:yaml.org,2002:int', f"{data:#0{4}x}") if __name__ == '__main__': - print(make_new_base2current()) + print("New Rom Hash:", get_new_romhash()) # read_entrance_data(old_rom=sys.argv[1]) # room_palette_data(old_rom=sys.argv[1]) # extract_data_from_us_rom(sys.argv[1]) -- 2.43.0