From 5a36bd270c5947f8f95070566eaa2c82dbbf7287 Mon Sep 17 00:00:00 2001 From: P-Rex <168558789+Pixelosaurus-rex@users.noreply.github.com> Date: Sat, 25 May 2024 22:50:38 +0200 Subject: [PATCH] Starting the project --- .info.pod | Bin 0 -> 86 bytes Readme.md | 3 + captures/alpha_1.gif | Bin 0 -> 69759 bytes contributing.txt | 66 +++++++++ gfx/.info.pod | Bin 0 -> 86 bytes gfx/0.gfx | Bin 0 -> 3034 bytes main.lua | 30 ++++ map/.info.pod | Bin 0 -> 86 bytes map/0.map | Bin 0 -> 200 bytes sfx/.info.pod | Bin 0 -> 86 bytes sfx/0.sfx | Bin 0 -> 265 bytes src/.info.pod | Bin 0 -> 86 bytes src/board.lua | 293 ++++++++++++++++++++++++++++++++++++++++ src/conf.lua | 79 +++++++++++ src/data_tree.lua | 10 ++ src/debug.lua | 37 +++++ src/drop.lua | 143 ++++++++++++++++++++ src/gem.lua | 53 ++++++++ src/state/.info.pod | Bin 0 -> 86 bytes src/state/game.lua | 85 ++++++++++++ src/state/main_menu.lua | 17 +++ todo.txt | 37 +++++ 22 files changed, 853 insertions(+) create mode 100644 .info.pod create mode 100644 Readme.md create mode 100644 captures/alpha_1.gif create mode 100644 contributing.txt create mode 100644 gfx/.info.pod create mode 100644 gfx/0.gfx create mode 100644 main.lua create mode 100644 map/.info.pod create mode 100644 map/0.map create mode 100644 sfx/.info.pod create mode 100644 sfx/0.sfx create mode 100644 src/.info.pod create mode 100644 src/board.lua create mode 100644 src/conf.lua create mode 100644 src/data_tree.lua create mode 100644 src/debug.lua create mode 100644 src/drop.lua create mode 100644 src/gem.lua create mode 100644 src/state/.info.pod create mode 100644 src/state/game.lua create mode 100644 src/state/main_menu.lua create mode 100644 todo.txt diff --git a/.info.pod b/.info.pod new file mode 100644 index 0000000000000000000000000000000000000000..c9fcc9a3286093ca11d80067061a245465ee1abe GIT binary patch literal 86 zcmdPZjgBtJPti#(N=+K4X0RA7Dlub;nVFfHnWY;2-cIkl*SkI4 z6EVBf6Z0}|WMo9vU-iA8drlq_lMvHgo z1k_4|G|FE;7OnC(T9t2fDn#^Z-x<`%m^CQNK@2RSjI82}yap^Bk{mp8GK%K1$`%@W zuDV8E#vAu8-YKp>3p@ggJc7!6NtOIV@_vRE{0am73I_y67RR0n7S+s^DzcS++-v7c z>*gvG$E(sNs~VSUlBa6ZXX;aD>r?0I3l{5(mK)OM8&ek=(-svH{wc4Dq(pR@%=K+HFx zaD0iH{Gs0zN+sGuHKf8n8DN_;Bx(U;=^ReSt3$Pg6WIa*2n5ee0O?%u-&8uob;UD< z@_CY(TyuvCCF-@7Ys2-W3zhmkru9?}WlOc@GbK7B4K{K$wmZX_QjHaBE$#u`VTW4}vfNds$^29lVq)<=Q0W(g_$5ri_$bw{H)a;3Us z&GlCG#d;%IGA#{fjiPoZ>tijA7tz&zh+kz}n@%?Se^cv?XE0vxPv%KwkKc3Noh;T` z*;)FuJX~z{)Phdw+FPG)4oTzXCfeIxE>AW_vgPzVUY{RtPO^RcIzS*W$9X+}C~Wgh z14zQ6&0k2viTVL(q7(*dsIul;L0`yJ41)1p4-I7Sd?~g=Nq%7(hEV{DwuQ(m4!0wy z8sK&!SsW>hqB!;kH>0@j5A*zZ-YIrt&!HuDwBgd&hxCu*!g#}q9CE3n( z$H%3W08sOBnM=22X=%-L33Ytqz2^yjCk%C274Y2hG^U;GZ0v+f90b6 z9R}&L^BMcKvI_#wIB4H9vn*S=}wq_HEs^r|0!;)g8|fzd9@?YC( zL?C1kPkXwL%Wiw*D{^K5ysK zzj2H&N>;G$y=c7G?pF=8Gai^k*m@o1`T4e-+h^Ol9hWGLHoI0dQoURa4#;{nj^b-d(fvxWxCkqr+<6e6VrRUTePynd*~0K2fYqP=-ECW zrpJKZpTD>HHY|?lR=GoVoKIc&!`-I8HM6$8vtIsu3ix(M1;GghGwG8^sSm+E_~V&2 zRtv*fA4+Vn1MMBv{S0r@lx49CyIJ1j5ALd*q_`mZ^kr}!_f|aw94yjykQY5tE*gmY zvCDjmAyB-`07C>IWOX$e;s(BrRw&+gfrYLqRhNTZJJ{#PTCE|cOr)-^-p7qO+q^a!VgbVVt=LfMU80l4Pn5@3 zak2TtU)@N>1u7V0{YZ>aov;N&JmZlfcf-Daml#&GwU2LZ&ZnXs8ot&rj?3s>C&$7W zj#-^bXc{%aQIIHAQN2!1(O#kcfito>#uQh7J4ov?G-`^$7|e7E&)|bIs=8lAT*b1> zXaG+WMl+MTiDX9T!C7jd`8(|pe~E!~e#i!+HXZ#5z;Pfk@h#p-<%p$_uM{3M5N2GP zxzd`3@2xuV3%4%yL0N_GX=pO&*ebJ6Ig>l=iQyOFZSEHzV?nukxsa@zJf?j zjjAN8{kBj8=~z5ULOGA>u0&nto01T;N{Z)Ph9Gw`SkRtC=Gv)gIfl6E!tngA&76`> z)QJ-4%RFQxtGY?Sq6SftDp=iJr9bqlmcrc}kn1j9Q0sG5Ls(k~C0kW&6wLt4NO2GL ze9fNJX$!X3X#en5bv$ypc?isy`MGdK3hOD{i6*NWaI3z`=M2wOYGncBxYeL-zhLgx zqBU%aP@jxUhpfTPzR-`|P*+}#XP>U+dUX$szoP{xO6hF-aj`$L^H_3(@;Wvee4cay0pd_)rH-_?!-WG5T$&jK*W1&#a*Whu{qg7 z6;khIV50~laM^xY=J2G{WsJ~5+WzvQp22LZ93|tu6St>6K#un8@k9M`QOiihEX*EY#h|&;kSvHY2C`#$^~Y=RJ*c zsobR59M!W200)gs?Njw44+Jk1C%ouFd8+RYL_f1lz7pKVBg-67@_C3yv?t}gy_$2< zr;NIgITwhnbxV1fCv5K2m8ej&eAat{tctELGq5pJT+#IPiIM=yzqP5@Jr|VsJNjwy zoEZB3nQxS3yLLqWBx$ldt@Q3<86OH z=Q-M)^{s8k3h{O0H(OIbckpE({pkh-`yUt%c^d+NJ5^lVfe<-=dYgMeJ;Js-w7e2MR=-^~Tyn>l;0sTqOo#3AF=1;KQ z9b?AtIGweRSk1UhGP0bCvPF);0nbD9-gl_RnQK}X%~KsH_XX@NN3d0i<3ZQ^V02vogLB{w$S-0IEP4yy^hN09xLdwaC5A{tu+XoT+7 zM082aA71fQ&lpZTK5PogGB5#Y#gLgDICNHe%r6%*x$w3_NZD2@J7M~G=4({en0i9Z z-`qU?Uf(c4du~zsvSWvL+Yak1Ht0*YO-*t)zhDhY87dLad$+ygzhIf1hxT!8bZ_{B z%wKSH?v-Yh{eAU=s~(-Jrj6|qGp`n@$w9xeNOLkx z1$+$pbP&@36ZH(|s(SSc!NVKOBl19u=E5*`xQV%BkRDya5@{)RIy8s?C;0R*8j_Oc zz)<-%G?s`ZJ~%1nn?*F8M0^!&n1gG47brd+QUsP77xc5njt zQ^*%!B#niP1*M^&MG_NdGEP&H=2DVGUc5d|GDl!ChHA2_M8dBnKi2*vm;lutvjCi@ z1Z|I$Ns*Kwi#R0EGlAdW`8MY^O}T2Gj}9f0{$0dp*6($JGyzC}i6 zXwuY>%ZLQym;~d*5&Z&XCa-vAB`7p~!@@bbU#JV7bHl5BV72*_*F}>uFq7P|0&4R%m9R2sPUbcMnp;-KwCz(qmL9>|X zxtMXk@Ki{QExbTpq6FW$D7U1Lf4GF$v;fTQ0WhDZBYyHq2Eri=ZbsEGvX1U(8iRoKU`QRK5^izKx)> zf~yeEtkCOOI=#$x&}_Y>QPGB5diAVrFkG&@S3Z@N^^nF{Az8U(Rte(Ld@8AM@2OzJ zErvc}2dA#$d(KCG(LRz?s-3MUp^E?HWq*TE?Rr#-N3DT{C_fNby%}yqG*V4ymHsWg z=BG;)_KU>Xa1~uTEh?y`29mm(6;Fdfs^)V`)kT^Cw^eORcx{11l~9YSpk~;brV@8* z^?Yhwk6?wUSCS&4hE#f-47ZdhbiLXLjj~p~?sL5#7C^eCLZ$vUi&wn?b%T*qgSAP6 zW<HOc8sBPBrbKH%jJFrBq7hq`%RvY8UPJ`t~meWY1F1y~WG zP~}xq3f&wk)iP_*(&!~$R9aHAQr&Kq)CSSor6u1}+LEo*I$)JP6j3+gr2u@%faY$Q zTA?PLY+GMx8wP2$-8i=er3ZjY+6G42Hcr~MsN1(@Tl;YkQMYg;7=nFKr^V31_;*n3oRQ=Lh6cK9Tb8ZvTBXcqv{VG97yIFen=lm!xzqY zb+bhncBL53e;wXz=_@P~)AJ6?E*miNrmkuoQMVqh)wYaT9ZGQ?K`t9<^&Vw89qAbT zQOq+aFg&b(Fg(aJ=2TWRQYJN4<~p(3GD|r&`#Lu4JqD*d()9|2PitI%9Xr+@!=)b2 z7amtC%RRInJ<*Qso9Fw;0{VC_@brM&n^O0ssHFUCLe*!sm3QuR66m5zyis#!}$LFY#2(f80f*H2e zDN4|qAa%JNEy3_D%?uB6FNMwwgY!(cc9s(S46n~Dy7ibql-TR2xA5D9q}i;v&n$o2 zZ0h&fXxGd?3zJG~b8XTys!;;!Zxxz0t=eaE=9#1V1oMQ-Q}8|>g`Bh&ybDR%bJpbo zwr_nv$_3}O1qbT|Hv%@JF^go%IbWZ}Q~dg$w88;x{XuOrp#)2MG6NA&q8>g=WKM}@ zv`ZN>lU6!Qwn0mFXT=J@rA(h?w6~={K0Hxxeh(=$5NIn9msCYME5FNUOV0$$qw?P2 zR%&Ec8VFV`WtM>DD!FT|HH*|WZL6beRNZf@57MiBJ_0fXqeDK_qnT^9GO&|tYxp3f z#Ti<z!w7$2!9$1nVix>&@xG`#$SSnd>J$8`U&x=g53>I{suF8@B|T z<53$>d^68&8|yP0c{bzou$$n~>#I7O7%1y-<57sdtNAnG?bn<5?<*C=Ti<-A&py5# ze745Qwoul$(D*iqWH&Kow|jCo`5qz{%eUFuS83L_Kk;od`1)V+hT|n~vyX3aR_xG? z@9?fO@}oqrlI;rl?ugj#iurCzRB%ekMhx%o%2jMD(Ct0EZL84jh-q7Bw(rTmZ|M?l z>u2p6(m5FG?wArDtgP)>w69yO@2L3#v{d&U-*=sL4<3CE7_tuL>JRMK4?;oj2mZDP z;<|gdGy8eGDR|L`3DG;|?T55SuC*2i?&4hhq z-8H1IrzrH7XkV|mY_Z7Eu8CuQVpUqa`Zj8nT;X+GLtb1dp?o6dzup8XUProKzm7{I zcU(`bU(@MbGNRuIe7$7?v65C^?!!oMR^A+Bo%4dOM2T+Y`EPv!E=4y~#4E2QC$0%L zZd=}O6+n0L*)-Ab=YB9HVA*%(dK>rScm62X`k;G8`g;T0n_h0=>#TeCjy3C;BU{u5 z->-KhdP^$VzRk<09)6F@V>e!)Yly3dX!_fq9g6{eU3dw%p&eJ@9glpdH!&MezVr_Q zGWVGXd`W&!Tobox8y~LvQyJ*)kKRl!$TUCZ4&e7#l>MA~eplY{;s<)J<$1C$KZ4X!jfL+)%7ye(kNi?e}|4-*_C!e#`v&1Pj7{!J=VtJDRh5 zTgZN0&VJA4zu`E26NY&=$0XfhN@s@)!lqqHxb#%ia;dWjzutai-JlOH(;ft zamgQ>j%V_Eu}Q0(nNJtUWQ%5MvMzOcLU*_lwA`I`)qxCFl617(enjNpfnW%=ABP8$ zqrQq|X+K@(r1JBJ5c)VBMwOQ94P@!OxYjncU5xwSy}DiP^<)pMtz6pQpRKXejcdPq zKi?&ru~F%OeBWh@wf5))z+p+MI?G1CqqbdP3&;L|#tWP*k6O>G5=7LP9^^x2->nkL zx;&v5M!$QR5cnh~%qUV%EL|l6t7Cj6f@73%DTrt1ZTB73ZMRzNMF5{soJb;HR^)q( zaE-v1uf~oN*8{B^bX+YNeTFyqH8;^R$^|*d}V3 zWI4m~0;ISvdX>oOdvtrZVSy@0+>}!$cvSMHF#0PlD3lgSz-+Eb; z^1+Z3WHn3&Oy-x&Cqy2I^()J< zwOqZ{*w(3;p&E6)qCO>S`=rw{>G-|rEa?1PA#M8Mfod8#=k?k2OOf|OP?NR*s6c)4 zCnVjYPShviCZoh=8xG?*J5LV7-%qTKhKVYz?mLlM!B5{}%-G;}6B!MVd8rEbvq^dFxTi%WwE43|^;wjsW$i%u zvt|8&;Iet+%KDvE3>IO_dGH7yw_V9k-4?rsMqfPprqaX~qvkWwR^8S+Q~a~Ax8POc z3dn44du7BJ_S0T=cGs(Z{tfQ4!O9A4`x&VYd?y>$gH{)*Oh{hWevz+l+9Q+$Z?3D# zYIpVvetvUKOCfqm_scnRZ?~(78<}q6KCpbx5<%qc&pw>Iglevn-E?6%gU8$_YuwyX2S{KPWUxFI(UO2)hZ|H6y)Rn(!y=&VI){Y?{19 zl>h~7zSy&OQej>Ce||+j#cukseKi64S^QHEj5LJ@K^M;Ri!c!c>);P;-|>L2JTh?K zDTK-sCk4r+4N#byYO(Jxy%z(B(nL9gab?GYIdij75(o33o+rZ=l=RTVn1#@>r)os(>*4z`UVej{f?TxKP(qO}!!#z56CGS8!iY(B{!RS3R#eROnmjhan4%D- z_fBIfzEC@sj9-*qu7OEg7t@5s?@QlK>UC^mU^10Lx0u@fv_VyZ2?MA2kXg=j(m>#E zI>uco)Au-v?m$z-uvBUzLyTl;km5d5I&h2*oH=d7c#CBuaMUtMiFgSUo*W32P4&mf zxL`@=7!n@0N>gGuL<-|t0?K9be#!y`ey4;tk+Yhfp?ieFqkaNTqI!J#gGxX`ORFju zj?0pIxJxR;`i$WwIGb1V`@oV$QeN3GAr4Q3atQxfAu0H`9Tl#H2x1!EZ@?^o3ffr8 z1$QVmHz=Q}96-hFsg&UATqx$UB?Y{hNg-A$LLjwN=4@8XSH+5ih}x1)EtzvVR>)Q~ zDO4!uQk^uIW0BdT(uB<&to)UjZb)jSZMGy(6=+)OmZ*=ray;Lts8ZqgwvB&=pxj-e zVyeDMt(Ok3*2%^enK3;G5=Y|Juu8Ho3a2g6BWPJF6})F4%AwI+G1DkAoG*{uv$p)L ziG^IJ3JE$2HJ{;{0VkWU^BF6)bXn1uZ^mwbh_$f?S6lhLu3BBRX5)B=g}cDE0GzO~ z6&2J{ued(1>6f8&Ol;B7Wc=K`;ZxykMy-vj*;u!@SLzCESx0|^ZM_Jxvl`-F=QbQ~ zIMgZhTx!{PYhrH)`J8)0OE-0|eePJ9rT4=^!n%N1?7Gaf4HP-7KOtNM!0XxvCr@v} zx;+9h2pRe*ymb-3s@39(UYT*68ej*o_uj5$O(SV>#@rc0xj zZ;Z*zl$8hpPXI&08?g~@Q!d!1A-9IZuI1DH(`Alvv3AEyXk>lX9gpsnUrgCn87usD zpN9g1>zojIEnH2`N5aW!vhjRo#l)6pHe{G1$rrgXjFy}1*PXv{zgeiZu+3Jll| zA0t|E&0T7{l)AhbDD-IdPPDL;S4SLcp)yalh&Cj7*_aCfsHVDgZxbSrCppPimd#CF z8_FMx%!Ig?(^Bt+N_}h`S5l|j+Yet`2}}$_yb=cJ+*;w=PMy-}WNUTV6;{q{v-dRD zL9RA!(1ZmbuVk)`!Uook14%4@_ST-m;74t$FQ)-{ZW{>6DbWP&R}Z4zn@YKgjnwaF zuln8r@B8k<9%l}o$-|wAh-Yhpe3$ zH+oKwo;%fP@f=#ADz2=xKM<;|T`&?x51zEk*YD_Dc#E}qgVwKCs>Ln?Hq5r3d>(t% zbf+WrUN-}8+y}+p&)q{%_GtM%o6O$j(v=J=)iyD{2&oQlcm=Wap2GTbX7ATsHNW)^_BMTAZj3D<{<7== zj*D{s_jcy&y^FV)ha6g;z3}YU3$@m#T0g>DC9$_|Q$M3MRKIsU!WS;ss>sb>;Jd$W zTlf)2_&b+7-i-vFes_T7LqgC9yl{7}Lh|El3Bb$>ETwmVS|T1X1mH2d(03CMq+1YM ztC3bav2Hu%A-mx4yT0IeVzB)15&ChS+m1EcMdBo|91(x942Of+O++F9S@vT)y#ar< zi}bdNFp}fjEF5t{_ZOD#@4{7ht29`~-Ly3PU#+{k;OM_(bTg6&;nsEYNp|W_3(^_) zfF5tUQASf3NP0Lk1etk+*d%*6G<(=~g+Kv9K*Im^0*>#{{y*rL386`Qp+*{bYKvd1YZ9a~Z^g@%NAQg}8fQoJ^Chbzt+jt}6=N=L{p=MO?s~yfKMCxCuAhAJ9+&o#Z)lN&znkpKm#1r)L`NQnd22`ZL0Eg8#8P3p z!c@QrQkZ2?Ad#LzF`2^ik%C&2TML~cw2^(jEhq|;$0wZ*be>|rogy)j2iq&;#hE4! zn!ZPx(omkJqMg8zAtJAzqS%`z;Z|I#nPzyKLb4%wT@0lYQL;*(2AyEeutmwyL=iI2 zg|ZYV>1fSdInVI)$#Oswz81~!&(+iG@bHodf$ooC*BPg&wFNzP{8%7s2{7JeN$^cArd%blUM0i^nB1okSfI+As*$Fn5;xY6 zfwe5NHxzTX#1F06gS%W1wB*9NoL8Wf&Z`C}SXO+CDGbtNNz@c7U9JfFh}0~V>CEQq zuvN0IsP}1BM=92@7S_6~$jE5b(@vL*ls49{2u5iE`xKh7>Rax#*vGWmOcWa0YCBl9 zsgbq2-sHQZihEqNzshL$CCay#0|x4~F`~4GNacqMDn{;Bp~tkx`sDfxDkoTVo{)5= zbmXQ*3T9l^PNj9`-ekw?ix%qFHY0VGGG&)D%UAB!K(nJdYrL}aq-7hd>jOx-TWd1g z1%*2<>p*GUJs+9%`uv0X_0mY)BLbP@#Nv}X-ON$lvwG?My^;%7y=Wx8D;eo)*8Cfn z4L@nUyE&S#saFuS`Uq%|sk)PhovTk#A3Rd`4N-q{`St4Pe3;w5J|DtWmM2BRj3t zzZZXNtcz_*dbg+7KB!N)ZyY>j$Y$y@Yhn_-k7%-QYC2#Ry>E3sVF57J7dExNHwDe^ z+XVO7zVADdP1s`}h}D@onI7y5A2^@)xY!khn3yS>*B{9#6Y z@6C`&%zlcR@2>6s0*nX99)=`I{W3iSJwTd=Hkjup9EK5ggts3?s}4oZA1*qX$BKw*4jKv@3*969c2Le(;6&_l`Jx0EMIw#vIvK>QI7NI zM6<{&6MHQ3U5^!&j|=vj0KUg1WW7a6mi~E`rTdmly~kxqjpgUZ)r8%ZFek>$mNlwY zm4wH&=lylMCrxxG4X!78m{!1kD+rd8=J&dmajVvKtM&@!ruUQXV1s6CYd#X|9@EoK zS!=x_MaqHgoQ>;_#30+ryGE?O>EmCvh&IPvz`7kuQ{6q)AK`7 zgLz-uMrPZi{?lFT)06)5e!%(hy#?dx`Bjp@nd`|Oncc>_?PWXXt*qVMxXryN&x7wp z1=~f|{`s@$`CXD-xv$Ne?8S?y#WRfkqwD!Q$^`_yJvja0tLo+Hz8#bp8?2xGMYJ8f z9S20EeLY>c|KF8Kc7uC@eFGB&1N$h`LxjT@NBf97!6FeWyZis?2|>Y;*T|uPXvpyW5-c_r6#<6+uHr?M$v% z05|J8K1UrzZys3uxJGkL$y}*AqA7{w{+4hcA$+^Ah5U|GB_>WV0f#F}ccL<^r+2!_ zNe>X~1Y_1bkxsQ;0+fB8KJ@`+z$=L52ejq7G!vfvy*;Q(Rfkg?9G3<@4QTvfscELz~b1rz53SKmLx% zR z^EC8>al&b}=$?Zrit<+Sss0MVgH|UqW)_+!TxPIVgHlK3HHCcoZaBQU;_UZgn!k_a>VBJ1t3#eu8KPl z^+yo$I%0AZ<`2a??k3=Cd^7HjVGxPt@nG5;j-vaHi|OvLEx{xZ0LT{_01Sn35}ngb zDs4~v5eUIn@xaWLj*^1bB~Zt(>`j2kStn_7F`Q4L|LThTtRlPk$B5c+H?(R~yTZxe z5sDklTszpA`MOn#i9WT>_9Y$&uWljTg@RWpB0YJL(d9xw?nAM}VA97v!sN4>ayl}E zW--3?f<}SQk^7^4)Oz`wWj%`qw=;6#tw6F&{WzaJUgh!c@}bsyTJ3v{p9s$wJ;4){RX%~FhqxPDmsjPyT;Y75-8oxR^ITBCZtO44Vm^`J`gu8>-7^Mm zSZ+<#eI?j4ctEqidt=M6IYC!e`pGVlxT#U!m0;k8jw|-Z9a`Od&5wqWV$#a90I(q- ze8s-)jSMr786Hv$mn%R^{Fv*FXLx`YMHBXzrgKR9s2{-J9Y<_PhmyLcie$@%7K>3p zf~8=`DUtt+K@@%|Omcp4KGE42K1B9_KqFs>g$^edpR;)|UBhCSO(ET|9j7qbX*-`R z8MiH%Tv;C8b6;H7P&_Utkj*kPN%c)4+Z-LoviJ|vJp86;vTlh&Zd!Q5K~a8#`EGu^ z<)M6WS^v`ak}5XPA{D_?qBCWZ4gjGr1{0Cy)1G65ZS(weHC^=?@e5tkcDUAs z^Fx37MeVYz$vJSngu9~lMK+?M3zVByW%;Iyc-aNUBdyfCC0kb6xo^mGQ7cS(Ql1yc zRK_@1hapWnWccLeSVmM@Ml)g$d}Z`u?2xK88B>(D8|J#Oz8;I&i##8XSUPno5sjg# zn?|-;xE+>zz^_l1A#AHv7B(t3nq-l}+MJFu;bopS4yC18a!XyKT(;=JIb8(tVcsYO zAz1FMJ38U@->12y&lcr)YlTruh1POdm4>lbJZ=|YV50rE<8K?>{~vhyhg0tVl^1+Y zrVmUgMB=q^ri_IHAn0o{I44PkQ=pBfwTl(M%l_nbvqa*$G6T;QBxU+Q;9Gw_Ub3yV z<`t!Kf$G;^qeZMIDuv1|%a|i~R%5@78~KEvv5r)Wp_X)myzb9_Hj($FMIB+8uXl(J zob!gy=jgO?!G2;JULaZP4LEwPUwN$D9<~C{E2CK|(;jd;v2B0VVAdTB-)ms;d2%)f zlxZ0y!Fe{EX7~`y_m@Ag8BhMQbMkHDC@|Twh$fDMCBqreNtkK#c4 zMMnj*Bg#~xzN61>nP3FYGVZXA57*zc9cg^}s1k#+$374PMFa7C@kR4f|fYeY=NAvL0IsAkYe1pFGXsUIHLs+OV*d={X!% z80F0NwEO2YOl%;Bhm7kW3lo8bFy9NhnXmvuSF%6JM3O7kHxfaksPGRJn@QZ!&m)Qw zKa{A3lH_u(r{lcr_~Ko0!g0yzUrhi{K(XK*0&J;hw`6=3{u5Q4S7-D9aV@4oXZw-ZQa3_W_U3n%T{agJGCna6R=gT=xy-aj~z<8`ldhh*0&p>=%Ez4A8rSynhGNmR5(Y@<{V_DygZ$9>Xtf{z{XU!WQ6YbNkQ>p zxj0^PDan$eWb)!X3_)1QK!k11Ew_UXKkuf z%(tw*B$=;=p-U8QgF98H7=RP$4*rR3)VL)!B{=$MEc*^25gaRoEdgUaYLT)naAk0x z;%~x;x$1>#129UUn8#K~bkeq1*M_#i(M@*rhR63tA|pTWG->xpPaqP#O-X0y=Pb-n zUDo&-?txNw@Y_Cxb35CAKFlPl;_mZSj(j_iBF{O^!z{%~e0ayv`4axXFU3?6);e9% zA}=R4%+sRyXKo}{QHc@)W@_n|B+pGFh#`cn{2XG-(gNTyu6d<>{xDIID7Jt_b-}SH zY|XH2U20t`_T*`;uP7o_eXXH0ZPAh~o^@lhB)4fzQzDy&BW+EIk#{pyGHuha;R==Q z)$x<5jS~j@dDDZWuyz}mtT9=qBLYuV^B00LtL`svrdM@#QE*#*9Y2a3#Q)JeG<C}o=0v@HYPg$>TQIf*!){><4-uUzj_B(X?pmAA%<4+kfkA45w-M*n%H9=f8p`=HJ7dcZ+tSdG3ph9Gsvi zjbj}L(TyGW$cjl~g%C7$HwwzPA}mvy9RQddV3bH`=2c1!jrjuT5-SC>jsqt_41&XP8CA+*@k z0cEMnnijg_&N2^N)6W}EBv~q2_Ofs*Q*T6__cPJ4JT6*X&!s{d2gZL|{01LkyzDAk zKHl%u&0Q&IMnttZ>gkb`zUsw3Ij-!kv*eMF#uv*t9{4um#n=W)Ln0%fv>Rb6cx~r# z95upba2o4f*S;!IJ4RyeAwPku8xUmHtQ!5);4-ibvh)zh?Cr6XpkoQ?UpFM106ll1o84Hf?^=5iyJqYLO$#{yJ^sgUktPoSS zB=pS@Dhm8vU~(HA3S0op`d=9P&uaw!hZuYQ_ZdU^U&2@lIswQ2UySXmui^{9z~|#T zf@x^Sh?70##s0vs*j1L;|EL7}(QUAo$YDxCf}`y!K@u$s<6)HGEKRwas6L%z6074$ z37ewKhl8FWJ=O@%6J2l+7J|}vXUuD7Mq$+4j!~sU6zQn71J`QVjIb3tAfP+KsIh%#&_d6YKLPlVHnbzc3|qIlEb&_yJ@E}1!tV# zu^waFF((~An%5{EI<1jro{T_2b{q#w&d8gfWG*iekUdynZh@eDW1eigPQ7!~(pst? zJyq3l8ddN4!ICfBe)PT46l7VsOjWDXx#-_7Q=V7k@;&Nd*->owc7^d|(R9shBa>p$ z_Il|)4}z4>B{@<`r?A(&|IB0SOAb6|nvpG`!$I~5Z``5&Z$gaJDrV252C;rZ6NkEx ze~hBYe-QS6Td{u<_D?JJPb>C6-HK&>F!o{B{+3?*kH&%ikMb1ljt>9kDZcfM5pDWI z3=@U;_q`QYnykyy5lmL8m4|B34X3LME79GAIx9+KY0o!Z%0|7?}Pe5i6Tk4@O`#lah&KJHkhNk}P^)Mnx&2A56!tZvIe<;XnnOyJptx;$+&n47wx9>U8u)VXNHqDAE%fgX4r zuMXCBj~!lFZ*ACQ*E*KlqSv{BvYOwuL+o84@X9!P-s$%YcjXA`SFbF^6!W6*55caw zas&&&r>H>wNW%({BU=0!;M>M!8u^U+S~Fyi&oed3!fkOgT;UkT7|GYYdJ{7K{6HMM ziruz5MR;E3oB%PUbrm8nHER_zTLQ;2DIt}=Jw=uDg?3TSjN^XPM9i73-y+0#drda0 z&*GQ69E|$vI?>;UNdL_o=KsVO-Qa{^bzmPk(EkfRfx>T@oN%9r6MCwM1Ub;QkpA@$ z8fsjgA_fDY5GP_uq@kLEkz@v=kFhkhn}VDODkTYj8$$EVYQ8m9iCp;4#}Jw*kDC0M z1W^|%ZOQtQxp0|m>?mA^mar z?uFCwc!BQ5lT8ZHaJEwaqi4NM!Bu~?bLeniX4UX~NjqSNP`4G>xzmxjVtU@n;oLf1 z*ite62DIN*sQn7!Uu%20YuxT&rqO%nvAJSjN^d0KeUW%twOdH`{o3L5c2O`O|Kt5l zOwWHCSzPSr+z;~RQ9@q)AXy3I(y|(ND&ay1wwA;>-cXfM{lHXVVPB@zn3>h|NQvGTirz z%`#2da44cZ9lHv%{jfdEbHj(t3v*(~nkn)a!8MQm#AAC>AW-JGrCAo^ zhvO?89ha#KN`i6As=lF9lT?;@J{OlY zGNs4WYLACe)znj2(H2LOm7bNYz8{}8RtB$}HF^KyI)J_Gr>1XB&Rv+U6a@B=JjpW#a>SjGP z@Eq)Y)eBZST0KO;T;|w9V|IF7LzZoQH3-M7f!42PsqHxasZW}5NV#1Bt(6B>duN1T zWQC_JuEsc}ip;;;vO?rt5YJ%WCXSMDh2UeH4TSZEe44wvNIwZO@x%k`w~) zB2G9MMC&H{INsD4?X$x1DJ|eY-F?+h3$rOQ%&Gcu4V$vqcn7ajGfk9qn@9@y_3KMuUu)m`O9-#A>I4&K!LBX+|h&r z-pghSeaP9>R|bB$^4hOB*9-0IjDcKH3gfsuA)aKgKAeC3N%-`q!cgjE~Gm^LSZ#3Bvxw!ZQI zFb#}#VA;h-w-Df@z#xut-W5?)8-#_>7li3rC&nt0h_Gjh&w?`fAqW z-$Eh{EYz*CPMqdDrxf(sl|a*I0i9i8{B03QN;m#KrHMyw=r`un;Zq&`MOc|Af4em3 zG5}lS(3q{~P5LHMA;*BkxMSK)#-Vf}*TT@aYx7O!Wn>}G#}FFN<(sU>(L%n5A<%^H z^G!Awa*+V6Ca`>>p3NKFt$)P$=&Y{FFs}mM2?97PkPj_X$^(8b)PO-~h6+_` z`#(cn&Wdy&6sh$9Cn}Q8icMsTG++>#nufCyo6sVyP2gn1%o)^as7U*wf3oEo2BCRS ztcxN&)j@n-79d-!PcSgm4LC242rULNNKf}`oL3|a6&vvmOb@%9S7yKNmp(Pf^(z7#nGv_rC&vUF8rg7wqaNjqc?Vs~e&k-WWN2SfJ(S|p+ ztpXhD@SNE%HyGZmX*g1UB83P+NSb$42pXq9S;5x@KU+?Uk3!%`f6A1gy_I&*v~Z>a z|LI2Ze0Z`sGx*TC*0nM0>v`hU8|b?WfrVS}S}QVy%nik2ei0M5c~r^9hv@5EF!sj| zwC)rS2AKt~NAc9B-)8+( z_gAx`nJ9O^YMe#6yR_iMukbnCUBPIL{~*uK89*enc7)8=cMnpI(LTG}jl@6j`rwF) z?yDgxg?jy)ZqhhcH>20b=c0~=1gX?S~>Md2lC&}=nMgk}Gw&ro**f;9STSyvh z;ttlC^^RLF7Mm^9yZH6Bskb!E#TEEpKw=5-uIo%|R}u~OAJq+X9l;&Mqp9j_xK ziU5$C2*b29@Feco+>@5Q5JhZP?!mP^waBcn9>c!`@Jf4GFVqnoh_3)=n%yNZUo|;> zSgoE0roU=#_)d3|1}!w**sw2s2v$aEeN%UFusUuxI^5Fiy8R)$n}YAo)IEFc^TvyY z;}0lj%V=wh@9tp|YDwS1C+K+H_ps3gu{if+IJGOQ>6v7VQt5d;(s0rP-DhH;4j2jD zA`$tq*4zP4`5$!BRB&*xlYVCNuX)nc|3N4HukF*c|3N4HukF+H|3N4HukF)}u#*n? zQ>EuGzKFh(3REA02yxH{{~GV~m#1dZGaFdCoy23iP+ZT&AeSoSiGC(km8Xy@=0i{B z5>qe+k%qNrcB;&j^3~p==eV3Pi9pp8f%h;}R#b}gER)zi;;{`?Th0PQk{uXC8bDa6 zox3%U7jvEOCLUNQJz4(Xjze;;=~%wnu8b$*@im6ipih`XXTj}rg>i4vi--6_&d0+a zAqwf=zE)RF`V|g!YfHm;r?Yi-f8d=i!W2K>d8c1iYquHmxbo^xHo#fZ)|h#Klt)vYpn@jCnv~mm2u1`NBIV`@q6Zm>MvI!f*UUcy|yiu4;_nd<# zgf#|}2;RIKrc#^t#Nafc@WxJK$n>#Mf^`QG&73lQ$Tm|=^KbJ=MJ#Vkj8evirX!+6s0rsa+|IZ1 zNT~DVPR4K4j9@JWL6wM4BW}7Q4C_qZx~Z3Drw!=5ie>wht0oh-4oa=8su?hE$KTa zE~)&CJHT4gzi`b`JFhLU51nV%v?yCxxo&URt7&9!*tp#}XrgE%VQW5^8DMSM-_c}k z-MeOa+;$drW74#P%WBgBhthb^d`~)Q{=<#<*X~Y=uhK^ixQ`_`KH%>b%oUt?GjI1X z7z1|N)8gEi`WcIg3$lahfm~TXDb_mR?P30F@@N13mE;N6qOOd(D;S0Dm0Ry^e0X+vw1Sh%h~X9WKi&*1Yo7P8;eEM9zd?^t-|+Mk1fpFSqw+U~$D&CU9+bWD19~ zTLQrCgYgE|R+cUt7SqM1(lsSSyrB6;j*IgL&n~yRTkr_N2T7cdr@NA)Jz7Y^PB%Y# z>EyMzxgPH<1UlXk9DKdGTx<=FRv&5k<}$JE)tD}4^yOx+VY{(bhvJ3hxBV{!Iv#Kf z@l)=f@l2LTQQ7l!Jwu=7r+H^r$7gsas&7&Hg_%k&`GgW}EPG-_;ZTzya5zr8r5MH~ z>fsdhE(Wjzkh4Wm5Y)5`!0Y*oVc_1_nFvvI7_T?h)R&gbs_siSi7ZcFSB%mE$2=qeLr3G~)#MVIsrSHw#k!DR#%E zc_d~V1q|`t;AMsk3;IIFOk3i@yzF2gu}M}eIglYe(G19x<75_;pW$Jpv5AroDP%6p z4eQ@5Eb~zPSeRW71(;`57rGQ>)I%C}i<(Ogb=5z_2R!r=%>v66JvC`D0pe8ZQA3IMS@F}pG_{-n& zweM_b>aO>MBt~vdAG3PG@pu8GOkk?sXbNdFtv*}Y{&-yFnwV|e4e2C4b@H++Fl0Cd z%Q@>*DrQX%?xh^UQw?sW-dyQa4_5TIxk}+m;YQ77~gx-IWs$c(M-o+k6n?MVk0*_WQ)#DnBq10oKe@;=1G3M50-vFil2jR zK!!ijt0~?0WG<-sTGYsrD?t|3s7t~0Rskyk%t@E2PS4JJyTXN#uM9*v6(wkFzMSRf zki6vSLyF{WNT7-Gba&G81%V3IMF!BnFr;FKnG9hWvQ{kY!BAXQCkD#3 z(Kj-Flh*{4=qZID3$T_Cq1#*7^wHN^*meQ!7i&KQ@1>*?3IcKJE|j_1Q`Y-&6oh_y zp|-$$jQUSL_G^vKpYJows>`zM58=c};IDk(%x-Tgl#ELH(D&eVRs3U$x#+R3tC3r-JgTy!eE{@2A(i?%vs7|FJY+ z9xj>p3;5mjZu6^q*wx7fER?Ou!(92+x(4DYS_NEAcc(|3v2<444u84n;gNg0yigr_ z<~{9m7*JfkeyLsZgvV6NAVH;L*Xo*>Rd*N>5$P}lKlesjfxQaoTG z;9ioNeh?E>QX=@V2jQwK*O+itDAGzm7ECKOwGb|pCP5QPK%7Vwbo(Svd)KPRX#JNfOcWOre4O@moP z262}5K?IH$Jml83=!z*YfSs=JT2jl1eWs5l5iRU+weG7FW}2ILmD!h@WDXvM_<`aAb5q{DRLe`%Bi}ZPvPmn* zjdpjrT2E!(P-jdJyzMhdb74m_O^-s>fK97t12>bR0W;f~rY{o<5}cy0wlaf&SM5b* z-4oY^k+v!`G(>e9g)C6n8emRwn}<+Q=KBLPR-)!GHRG}h;=ZC1R`N#k3QtawqRQTv z1DRC~ijBq9mB`l?<#U206fP|js8)4bp%}*X8^d1E3Ueq-1vnk0X%%#$(#T$;nuKOu zbC!8g*t!ImvVvZNr8C+oC@o4l?6+phs<6gwkK)f;faP6km?7rv+m?G~JrrD|6}_~L zj5KAm0LIEeJWQosw{CJt-EQ(0R`Wrwaf_@Wzm=wg94~MABQ7?3-hIoJpm4uf z=I!zLDs`If^2?q6fTy?1_Ys6()Ei+~kHQ_5+KI~VfgoWf$s-lX9)FAp1{8m?9R_(9 z>M+J^U%ClCJ)dnnzNIjfnkg#xColQ3LwIHaXvhG^y;XBI0VGPzm}1kcSKp zzfOcg7@uLFGO?3kxO&GjZOj`FDLoihQpzaK7=4;9&hPN2bD9T$+786DP_pBs4_$QTvGTwjoFA|AM%r^2pLknQ2| zM_1p8bVc9!qpQEF0pxynb@S|yUtE2xz^JT(9Omk5-(B7B53WA@-PJYos>}3)4HM@! zcJ?cl&~LUYyW)~d+_tYYKn**P9%$Nuk-1J&e?tkPTj~yq(z;v6ZiIUVM(tNibIz{Zqd3k0y$L%2%Y} z{`K;eB8bQ@g&T9bn&)}7hYMhDjKc?cd@1ww(F_u=ZZ52sKWq}dU{`Rq z%pN^i&g?CcSs@RyF116o=1g?Lp5XUnhu?i>1cd>#ooJ(kkhhV&*n-qRA@pWbG@(N5 zQlLn=Yr@=kc5Nd1c;G93y;!`Y#Ptx;umYn174JmDC}xk0%`~?irp!oLddcn#UwnXx zpOeefW){WQ!1Y)^aUgQmi-}&7bX;;`Mvo|BplM9}apHDPa@M42W;z1VPFi*t>S}>6 zB-(7dFto6MDW@!IhQu=PrKEXD)w~7>nuFY9p6fg|V^%PZqe)@u;tecvXvYm=DgG#Y z<5g9pC@qmWnU=&xHcAg0zFmrv+{@^mP=RK(dc1>H??7jv9`={DjBYb$v(`?C@Yk9- z3vf+ul^BpPMy7b?69T`6bCEFtY2j^$vYk#deevY)b#f1)hrH~;D{ z^)h6U-luI44Y2N%?mIMkPVC1+<|^9HtTBkB5b`L&Wf%aiW0q z+d0u>FZm}!!1C&JVO)mJIH3rJ)4B12XlQH6qG9T}ArJ9D5HS<{j16xKgmwB9{r*In z)O(|mAPHxPRCkhl$0^1YueVISVWkLz^Aia0;trzCt(1_0#TG$Z}!tH_qd5 zM>omm!@V*mPJ!Ny$7=095n2!)aeg7Xg41ItRfRtL3N>=xIdg!q{vA ze=@f&-}Oc>s)OjW7$)3dg0{;LVPKY&Oe53sC{)$8!{oPd=(e4BvQ4{P1jaH}A+Hgb zBBBv|iWQFd8~8#{aoy9#BM2!+?%TCg;?!us zLV=v8%=sje=k3X?j@)%E&eyI(0fbXD_^0}9tF-d;7%2g-@AE~@kgj{N2QCTGU%m)Z zv!Npd1tJS%w_y2|(b3TAiOD#1MC8c3zDh(DQJd-rZ+hZJ7r9JgqV^$dPM(G3Ya7y? z>y`*_LO8XkGZ5QfvNJU2NuaiHI=1kXXy~)i2Twvm9wn-Yg$S($;K66vLZ-SFY~VvA zl~xGr)w+Y-M%~G$sqtnLB6&ST!|c}r$T-H*(W5xRiKka@7@dT85XPvjMQNzu?R&#$ zal<^eGaQ|!dWFPkp9>V^NGN&t1(-z9d0nkZzhvrHOgfIqm&s*T?dw-*IF2m~$z?T` z8qkaqJt=zCMm`yAOHdFEyx7e3H;B1L2H^Eo}mvBz_EmaOX)4nQ5FPO%49P zqnDAQZ7v2K$G#Wq(|d0!sm*g9;p-N73r944A6Y&+R&3djB~cy6swOh^?Xocyi&TOP zPk1I$pXqjj21!_4MQ-e#xdMsifNEStHMzPaiLGX*qTobjOKP^Mv9tvDad@32_koRc zfz~u9K@_&A6;bjo?gDOP16#QjR`~$#{zOD0)fX#__F(DbjpN!)yo1NH@l?=&+K|1j z2SJKNKR_J*u7qR@0+WzfbGG~_A<0huNkX#LvHt&ELIVEV5|UN_R*Ih`BwtYeC?Q!R z`IUquA^49H62O)hA{^XONYnA#y{sC;)lM0Pi;t6ReW(=d62tu~Y}SZK!(cw!Rr`oa zrQwMBlZ-9{0UfF4cW28}>n05p!(?!?Cx`~6kJvdJ4ko*Z&`Td^^4|Cz?0$%+Nx%Os za~@4;&RiBrt?eDkv!^|zb#wurydOaE(ls8EE0g*P5vhH8f8WSt!G}ym4bG1mUyRxl zF_m%D1w>f46#N)nl+wh0a8fIng7Y3t2q&Od-$cCG@twUKniQ=(>ow0ukB4!_G$K+H zs`C+DnOixYk;3Y$Hdj&vq|WL*omn<-US6z6zf9epOJc*z-AK|!*xs;UeJW<0`tnCP zZwLI}(W(4fnUfI?4h8eSZ_aQ3s5#;ON#;cP=bQ7p80Np)fxi}b{R8dn{_pEMWn*BV zDn1(_2D$X-j>zAb9x;k!NCq?0^`E}$%#qE+e9K(^?o*L;fr@27?B+x%Vxt+7z!S5H z91upr8ZYZi5`30pB@7BE4|ex53Tz`(w+X|A)V|D_s*v%XYho~EZ5$r5aUS?cUSPia3jsd zc{7pI(Q>D(0A>qe{o3L{;;cC4w<`NhtwQN^L9Ls&n+u5scUYdJZeO-mhA;@izWUr; z9L={Hy?EC04J%~b?$G^(hsW2O`3VZQyV0J-ch^i13I`ZxrQ3V>DQboRcFkml=@G{i zr7@9s-Le50Ib)`Q|9i#^Uy2Axf1wdmqebHsTL(fBwp(NUkno|Y2yaB{%_)^<=bNh} zZg_1oCSpK)S|cgqKtdvUaVCFKf7w1-^#m~{x>$R)KteTt)B4Xb2&M(uQT74qc!@{} z_4*=uQ3|xlhEcWs;K>z7Z7 z9-b*GK!k7HE^eCGDG<`$=r0h8!^ALyAIf4j&u+nQG%cILEy^zs+9_nHn+Y;!j8D3C z*-v;4E-+|V7o3%EJZM2HZ7}21v`)F`sL!w0el_zr>8qLPQLL_&*-^U=eLd)dtVbiQ z+RuFjAj~7*{oQx^{|^o7h6l{Gu%@8{9bl-jyy#6ZSi~U)!-@S}Eyh#&4Nc0Nwytn0 zPKP-HOU-U1Hsco8#6zP_6d@FP{)QusF+XeIgqwiOcGv z58Vn9``L-r{D<&HT4>Vo{$#%dt{*u+A87Cs3m5bt@=Rx|%H97C%F=9W{3XUV?x3Uv zs@`%~d%^bjg^NR@{qeZ%ht?N&yl}|96a@FcRPi1+-=F9R4GI}vxKxap9(T>li#}N5 z+{?ar+5uEv2psuK0hk^EnV!^9TbY4KSyLH7h!s;S-j6$Alh=3%s0NkuWpcv(D!qrd;`|b7kH!gL#A-Zu_UY>gFeOZaR zS6EoyGByB$b?YUzH}JE|1kpwpcq zQt%oItGC;i9rMx;W04kxC}Xz8T5ag|td%%`U6v}a`&&oGDUhxy~9WZMb%4!D&O?6eugdqYpXiKuUH! zB5eaalMrn?A2{g569_3MB_<)oX(3|>G4I6y+$pH@!g<3{IY?L8|e63g?YO|Rn?n4A?5hlYH|I% z!4u!{j#-Q89>`FMW_QgzPx}ArZ0#$?gfTe%Z23$g$ey zP5L~Flo6bh90hj|KSu<1NhcwQ6n^S`Kky-0XnW1Ro>N~gn)t^Z%iqUaioWkyF09J! zFC}*kB4feNku1~gD_qx)VVm@Nz6jf~9B(>W%W|mETvThO1F=o_^Cg}#?ZpasQOu@E zS-uJ*IRmswFU!}lBH!bqHrbgDv?JMcyq&GzHTKGSt^GuOqIs!8(_O5BgvHA z-bH}X4A2-qTr35tv*ibyP}c@3t=J@Whco0=HW}F^qGXV$27T4FPa5)8k@%K8RfjlGtWjU)Qu^5MGsOGK zQC;XN!UGJKy$KU#jB{N@B!`xhD#XjqG zt=a=k2}m7!_x;nt5Yf;^rBEK3QipBi#(~1RyLeM&7fs`+W4qMRl;ULch~^VG%<5wj zKt@ctuj{5k%E?bT@P0~!LtqWlKU?wF4by)!HN;buYN%^R*nBlr>TI1gMw4ZYz7;P_ z4dMA+4Z+@9@1&I=aA5^#X8J`9VawYW8$2WnX>{ZVTlw6LJmAqkIkER^#Yua9)9F3e z>_{Q!f4hH-ILfO!((?Q`;AoUeM{J3VcG3N1;-}%cPoC()C^j|2vP8>Ku%0i8hajX z27Mo94>cSQ1TWPH30}?w8UmnVCkXx(wV^@`#w&G0F}uMpF>wgCQmOIu9*;H>a1#5d z0(Ag*phR&~J(Xm`Km{uzdOJt7k8ejAbii-Oy+ zGV5b2JR;_l+-Y^=)b@ur=C)nK3OTkmqzs$3wv;yzif#t@o}!@7X{Vfnlznr|L)M}{ zH%Fl`FQ)$EUGx)3R>U6zi$12ej9Ls1iwnPu5GS+SpNzq8jqi(rR{)H7Cd2f^P&AYr zr6Ex&dMP>C+6cch0cRZ;%eLLLH!V*un~G?=VPE-h%_|m^1&pO(p!*z)j7I&nFE*?# zS%Lz*9QAfdB~~#{CD%^bP~FS85rGY^2J)fYa0K#M^0V$tjI}H}d9f<94!=h(!UjJ~ zZ}AJXM~0}PJw|~dDhK$aa3Cx8g*GI5dfA9Swa*PxmcLA>kVAcde5(P@;$x-VNTLX# zqg7v{>m7Moq@7}lMD#f6Koh^+N{s?VY0=mGlU*&!*ALRl&(*ekYEOC&hMkrikBI9@ z2=cW7ExTgKnJ#JDzQJ5AwBT>E%fBz{?T=G4>o)0zI zk*@edMV?G|kuMUlw!zMj41>)F4zJ}E-kL1=kG)Tz1ks^8tO%Wpb;)bWGx6xdQ=DGH zJB)nUT8$7{IHd?uoUc;}qsHZ?jo8FtT1OE-AXEx9h0(>uH{YK{Dsqu;V@IpsK8;tK z##_o2*KNW1qzks3o|1WejY>zr)j^b(KtHO!87{w}F7)$vrVM7=mw&eH54^=c+qMhw zZ`hXRad!xs-3n}9)OOP#-|HN?C}d#-H7Q8G0zX)h`VEo2u3QGEr@lQvDR(qmYMWJg zT4`xKU*3^g##xz0(MR<)&jXgTqMm5w0i$QGlx(Thx+e{mCKaW9%@%CeWP_C@%WcS5 z5p*XJw2IzhZ^$PEi0D$YLbCDVM zlNjt`Zr7ggPu9Oaq}y|>RQ=d!{P50%6l&4gwSGC=3*b9mc8`2DlA?ZT96g@we-}@4 zT5ok!gApLN__gk;G`MIo?Zutb@bKY_9@Xa&g6=m+tPmA&1slPb$~uk{xh;xOY=)!! zyhQh_9;)i;cd2MG6q>k-sPXUDkepQCfXYDgehN5MY6|x)#bOlb@pE+Luu3GwgVmc8 zGDR4V<08XUkpjmho+GGcD+|-}ubFXOi%!YPkCo5GC-#B| zji)sQPipQr?%K3s-(eh~=yj{@bl@YVl*b?v2<^u&bxa#26JtHAh^I?-u1H|=pQCHe z@*@I^b2Vz(b?_2k|MZ=$_#s>R>4y3db-nc+b)6v|f{&)Z);mf=7D0srru|TnOUh5I z1Lk)6($*ixYB)Ap5D5{9wYSl5GsQNRgQK=Yw&YiOH5w-&0!#%~?fNrXpcuNiE~GdFVXV0+mH`s;XTxDbj;0q@a(P4=XejQhS*@W zQvDovGLlyo3CxE4PILwi39*CvUd|%^_`S6!LnBC{!SruNxlVDw+N434;YmB(vlPgfrncx#7niUStR+LZ>VMzQWHpq0<03N*pg&~*|3ZUsP3ftM zVY;%IqTwQnj0aqH5E3`jdd#^g?RvD>tAceDKShDA}s150qku|D!$sMi;BEa@oR1bg$uFWeS!6{VjTm5N&6)iYki~BN39vaDwG`UX~kU z!4?F^70t%jVD#p?emsD0vj2Fz?|S@rDFUB{Kx=U7i$O#b7eU6{BquNuLqJeDpCe1j zTh0(+X>fvz;3L~+6xC40^0rsOd+2aqUCDYI>L_l^j1Bc}HPnmZkzmB7xNnaoy}yj@ za7s|u_%U=(o&V+TRJ!%u!a}{k+oAXC*dYg#<&LLApRvB~&3^H}xjb3)w3cVSTzA0} zg)!;yF5x|qt{lnUA@8d$>LBmD`$XOxcZUphYq&=^uK&?4)E=4KJkPgCe+vA0`{+ns{(7WZ!pn8sm#2Y`Oo7pHN~XdgMuklB zXkIZ{hKl4dAQhF^8vG35LWkZR64YjNb8Yhu2K6W+coy^07Dd{n7uFV(TWEi`a$t(t`IIkFr<}Yfdpg z9W;+_3>Y=R4eVIM!yoRJv?84pjkY1r&RVxT;C*J(fhM5i-h*-6 zePJf^rHkI+D@O;j>L9rH9Fz59-%0;7y8({bXV^m{J6hNyC>TG!da~dfV2(`vTNRk! z;yedfDHeuYLe`UGaD?@>B=aCcNeJfbgHGU#{#e8}E%px|!j1UxT5sf3zSeKgk>5tO zxU!=rVCO^>j&eFl%6-U7Gv#Az zzVKO^Z)Ku|@D2f0#@J^053injaJP?5Ux0ltwnZltfTe~Rm{@8QNQ31>j+#`kH5!59 zvyVnnV*yi~e@NqEu(q0yaK7eeU{9t=iWFAlO98AgBv^{#b39 z5XG+dQ2W^R@JPIm0J$`^ne=RTq&EJJ+`}s-5#?l|RcCj1kdNO#-Sqm)WV*O?HT_48 zSPnHciMNJpOQ454NXuH$q4BEHXi=jvp1LLUQ~IELk_moJwrWB~6lRa~-D#NB+EBPX zbl=!@*Mb7-bmPihagh>it(e9@_X8tAQizr zWi8#BiS^jYc@!ma&6aW{aV5XLsRY6La!{xwI8$HSm?>8kXg8*|nd-D|`uZmdbQXNm zkH-Cr!pv_#y#KCoPyVUKCI3z1!vD#*@V^`PuNe1l&WHRSx&Pjg`+WxG&)4$rk^7%@ zEqDBA++PcJe~;XM@5t@^(YU`y?tfO~eh2&i>fyJ|n6nDW{NQH|BV+gGQWN+Ra+y7< zi&z%%$7N_Jce2gy3nhEa?t8gGB^AYBK(15}1%oBv8Sb!RA7_t5^63c9Iah3sBnz`) z!uB6;DFjKy0zflLYp*jD>REGxMz_a{@oK@(x6T;VN?!L+v)-H(t5x5dzP3-sw-TYpU#cX!{kxzVv|i7A+(b$;o)cC0D{ys)fL-}zoB^x}{aa&A%iGPs!N zOMt4jvPi*<_Y5SEF@351c>#4RFWFlNX~?+Pm9mBSAZnmUgyuZ?aMX4}opAKeP9Xo+ z=m~4^(hXBNq;d^}>;6b^Xg zb0+1M#H(oT$I{#q?I(`k0wSs>^v(6sKp*Sbk~z@`X)88)5}UkeUc*W+C`GDaa8PV0LJS8N$}B;O_%3S&mYe+kFE*xl_oH~eH9 zPV2~B(A7ZSNz=!gY>_7QsNpMEhU0O}uO^D~e<(w-{`zYA^GwvM-|Dub{5yBs;r{V% zJ0INtbhjPu|EAks2)lt^{^pDQud)Z0MFEW4b?SZK_2l>`s^G*vLw%`GKK`(0i4}&@ z2^{kui}{Zrud)R&aD%xYe1xeeIsYXJ;0dt6CE_cl36#Bi%F|N)}_SF$Z~zF|u`8yNCrF zPnHZJC4s z)0gtqL%hi-dl7gfr2w4JOZmXKD_?3^=8n!RF>G(8HsB84c~ltE8Y*u1>eZ#6L?wJ+ ztco;~6t+7(Qy(ZAV5FoVAxy74stDWNkV^{AxJMsL6)A}m2XOApjeip+<)6$e{)kRe z?G;j_C}X)gP69$X(Ps2pk4IZ6i0j+yY2efC_4LOo&O*V&_&|wxp<{mecwQcKMd1iA zGgB@=qtGNE2}nB;8%eBTniU@DJf!Ks?V6(}jPSHjq;7F*8Q7n*mtVFUIVIls;u z@^08C)rAO1i0V?iGBgb|kic%U2b$Imm;J(Q#p?~ZtRkD}v}L5{;vh!g3U#%O@B@M) zo6dCaS!lIyPz*;Eq6kYw^7V02S==f+H@IpC{~c%D1b}HQ>KIw3Ea%}a06L_yeE&$4 z^zpP^sU-4#Y3DFAza0eiE@@+oOyH_& zEPmG`{FxZ{+p+jRPu%*~6f~b-U;cWFl&*(8t)xH6eV*PW5^V8aN`gl)k+U}jU`p2) zw?QHEJ+2;OmN!<*@{&J=IQL2bU0MM3dj#A3 zM9wThbvosQ6aG|0gFGz$q-cW47TN|&7==3<)8VcX|w5J{QLs4WalDV%<#|3*zsrLc! z^r#C}TC3y(p-wSJ*O|t%o=UP2oYBhrhb)|ZWa+FD{df}gPX-8!)DF5?1{5lWp7^tJ zbv`9{XE{PTQe4^dQpA<37rcM}NiQEkD0id$-Ru(s5xK$25jB?m!wHAyMf9tTP@xYZBIk4V(j1q1=U7Vc9G$>A=ng|l980NeYAwqxEo@~>7MIT~`%e0wFA;f1K zFSx>#m*#vNn4NBmpkbWud$7HfrcPg&PZA=yZIXd2z5~f-=$_8cCO2bd%6sS%w3UO) z&bX5i?I91Nf(iF6r&77xZ7qA_)T3_|RJ@Wb5)H;p%JBuC?QE7>TTD_1-jEgPxf4e% z?^S|(%XO;;Ha_oF4l7Fg*EAYQqSS!JSg>p6!!GwLm-{&mD%a7gGAd^S1tKcfTcpLC zc7~SZTaGHxTL8YzN2Y@n7JKEy1CSrKEGI8|BDb^ouI8jSQag2+fbWOf2w(Ta> zbbH)wCwlXR6h{muOruTyYTFMkcC!^lYb@pn-gKC&AZ1u(J?Z6^cC&+@x!toJdgdcj zRmC67syc!YTzoPLY-D-chQ*~~-zA7x@^l=|(NeW)4w=;96IY`c&v;|n{M#AB+1;A@ zCCo<`^>*g=Y&CAG59gqot`|e>K7-6RwdH;&tUrwctia2_Q^JA&6equ(68vw)$${73 znvQ|{N2g<|DN|Qrb6+~puc0TK{q>TY2oIgX8w2Sgj$Ek#k=2P06nECQe$E#MSY5#k z*0)WkJ~QP5n+LbgPA*SoC(}JVU2nH;zQm_`-XSqkIuC!VP4OB#gFzcliMDi|u{mMX z7Hn}sNY(WZjUz75aI*X)nMM41Os=0 zhN+n6V*F)IgMct3VC70#o2A6Om70KY*DimvhIY7%aMGQc}87 z$Wl^*{)xq)0*YQ-me;W}K|08zxmOy`T%=Grys0;!wL!R_ceJ5Zrs)los+pLE2AE@Po6Na9)N6WW-5f@g3&6_EU zE||2%X>F*mBxS~DLRWr|%R0nnhx@oFvwgCqcp1Ep!0`rL8?K=r(PSN;MVQQEItM3o#r+4ok7_Sme9#bmlC( zQAGyId&qn&gj%Ty%Ahf{jU16NgxU8MJI)r8X$J0LCmQtP6zw7p(Jp=!9|jCy?3W70 z!&QBx!w%i+l#DMn={(|bAMGv@e^8Zyq|Ww5l&e+YL^Rc5|E-uV1~bn9Xk4#m)YROa ze%#vpu9GVg<8F>4({|Eu%*o+;kP%&ONv;-X3LJ6Rp%3yFEH!HzMZ2# z9S{wR;a_-EX^Fjv^~QBl`XDf z&8@dLb#1PuPOV)eu5MzA5Tb(P0l9nGhbxN72Fpl9E_^k$n~BY_bB>QcUJU!o9bD2R zEg- z^2Md_k?f;ARk-^mIGl#^KFG@%;^d4ku^WzT@QSs?-^IMdb6HcR9?Zm4KBFOa8TKP= z&&0g*?-il+Fr>xL4#50K!N#Ep#;s;+Mjl=G!lc9Zm{MZO=b_9;uTZcEI; zYcx>*9`GDlrSfg+mk@Yq1Gx#l3Z5365Zjn+nTaWJt_7S>&dNk`gN`0S?Jwc7#jBKP ziO)sIaU+AY)}+y=B}C~tBcf73G|@cR(qO9aL=YO?>q#kTZ_XG>qV-48fxWM@a2=EF z4dI_L4X9d)#(K+8vrQWgD0N50C#2*uc})+5agT<^JzGXIS04-}J&E*GGD1$AmWif% z7&*rJ@M%#&vAH-`vfKTI{FRo8!Mp1zbkq{Z z9l|QGqY$9aO|y$&EGFqP7Mf$9PWm?MrRKlsvY5J|5-Z1n*@f%#+O`K!8-MA!72=D! zURfwOeqe3`a8ds;6l$L*J-?%I(J(axb*LSfKXAEdTzXLI)FZucoOIE&C0pt;Ik0fv zaM64eT591Xv1of$)p9Hy^Xd!9v#rmjt+zv^?$-T_2v`XaWc;I2i^8Q_^n`ZIure>p zBwaL$x?DWy6JIV;U5tsUc2bCqKYz%J`{9?J7`J8bg_{Z=WIJ_{iys9))q0KlVXBMO zqb$f$O9yB3vioV;mtfobt7wO6y@0qc;a9t>)L2)&(&vvOo#$4P#nrU{&0tUGLPMg1 zs(~(Cv#4-@QRd9lpk&RsTyXERr+Eo?c@_}V=!KNm-=OkChd0)#XHAi~v(sH%3!O?c)4q16pcFS*f5ja0j+m34^KyB$R$(ALbsj`jJPVR zaHdhYo2t0Zq$gWd3vJ2lNI5oqs9XSNG2!k=Cf9Z5L%5ET+#>aYuR98F1Ilf$&4O8H z`*SzW-ciWDHlq;ent(bqd$a96w!WE}->8VLOdV$=dHP9G%u&HyMbR2PcAot0g~G{3 z4;OLl!uq`&SzGn;H_+ppuaJaRB&qRtp0){h-TCdi-z1#CcFR|O1_1cmfusj+i+Bvv zUFPVvCJUp>pZ6}iG19(x(4;J}dE#C5ail#JfHpx!o|*6nFAOG(JWSz!Y$VtkcoJw} zzxgP&euM`7l(&IvvzhgpC|vOLearZ&_zUA1i$eP+obHf|ds{=5{PIa=Z_=0cT%=pc z-#Y5gr-O7F1YX!Ucn8J2VW2gYa=t!~k7~}bd{HnT8`#@qV1HBeY zm!9(Pw1DR~=qWEyDQ-80{x&^j@o&;oJZbI_f2OCb`;q*k^c0GJC3?!gl{x=9J>?%Z z=Wo(eer-;;Xa5{?{twYp{@i5#i)A4HR_n2TkIoMG|Db(EfZwAN{y%6b((lpP0snpT zlKr1cpZ^V1)&K40rKg$>C9{>Pi@-e%Wh?jw=|%iE(hm=Yt6itbk7jE#F-*jY9hN|?0fz{e{SPab+6=lpc>3dwK^<9mybs7GkA??AJ`|qsB<)y?dy>?M zxodE03@ZvuLU&<1E1SAPuX8@645w^;0wqsXjd^f^o)98FK zo*hi^_{&#^ZSbekR`w&;i<{-m(r_z^R=00cUr^FKC*TP)91(F%mb{K~C3L+o(6^R+ zFti!;+^{wXsJtICt1Z7LGBcqJAW}g^34G+yOXbI8rAFzC97VMn!rjkE5dt@nPeU|1 z&8QzHFg8UK{$ht9C*tFk$x0*_W?*)t4DMA*6rQ-$n!OUc37s1^JJGu18-K}OXzPjKCkzqq=eHRb92e{Pu~S3}r5N5iaB{ClV!W!INEb$CmM}U#T0w}*iid?Sn0EQrl3gOihH-X1Q(~VSaeu$z`Ux3N5Wj>v%@ZHO|s&y zW$ls~32UvD5&%kaUzvHoe5(-FN3(8fWD^#LGw}u6LXWE`hKkNww7AXoV z1`p8(qZbcxBnzBqB!ii`+gV!iPCu3b8cec*FZwygt$%EQb--)=Y6fj(|$uTo&8PN+3wh~i9Z*vi~Y`csli=(WvZ+7;a00=o_0%9_vu2>fZn2Z zqtKV7ljzdLG=Rsq(=WBDo~!T)sqYZ|RAI~G=@}PYkjbYgy|BfnG8`Ta6D)hcyqn60 zz^IPOA2q0M`MphoiCzG?S)IN=3NV0@hCiJwAaVhj!lrUKs?ZH%b=!!6GESUqiCNQ9ck#ayBygsI04K@XKY zd_9nXJO!~&oi^D)+uvAJnSMIsEf@)~mH~dE0_V2HbWNW9k-ve_ob zAT2G;qC*;$`@psW5&)m89+?jLdUs&&YzHfbg&zpdDw2_9FXvS3dJb%!PsR*vF z(4-Llac^Ns=pyr0shzU(v*J2;5b*EDyJVrLLb~+Qv=n72d5yOry-{H)b*H3!oYbX6 zeA=I-M110qG^%zfdaI-kUMz&E-cr=pv~JLQtFr;tdx_N4o$9hjwlBU?m^XO={LkSr zKbMG3Q{J@%XB}!-HO$bGAJiWky?WmM0S{xRbAWl)yrn0&|5lIdQ`hacq`HF4sS{|) zw~9G#Ye4%;1Z8XnN|!#v3g8clD{35YKW_{Zzi?(7DT*$HWXsD4GL1R>{1=Y|{^Gw? z%fI}Khw|qEHdZ#my+7Jmtt3bP1lFP;5B~i&R(|?_Xk#VG71;B$jg=wSFKnzxuzqD@ zb)Hds!1w$=*jW7x)_(2$0~@QKahAG8q(8Hq|Z@#sIfAg*F`Nw=~ z$$#lv3w&_$H{V(*|3C1p9sCpDS_sLX`qnac{oq?mb+oxf_WTchYoGtlx7Hm5_}02Z zf9G2pNA{<_wPj?jg4^PM^Q}D~`^mTVfb75Bw{{wk#J|bsUs^f;ihS-O2gv7i@@w*$ z93PO$U&-gezmd?Hdm z@_C2scjPnGHTg{Sd-8d;^H0g=?am5{hTq8N&*DFl&n^GmV3spMk^m zfKH^p*H^!;lK*S<)d5XPnjJS^V1V6x^(9q=75U#3Rw^NmeE{Zpp-T9@?``U_Qaoi_MA!c^N@ zOT899GFysJ`&;@wa1qSmp>>`{-5&HExD5i81|3;lXeq^nRVtOmqrvndYxySAwYJNt zPcLos=UQE;ax64#tmYa+uI@MAVX^)gkjTe)@wxhFe#}}UewX{yVQsET;;Kdd6-;4o zx#yK}F9G|0oqUR=+yL3V4`*ULl;nerw}!o?C|W;Sf9(P5fU!-F2-NV}vKPEnc)Ev# z;n4zi<;QVy`$wr2CebJqGmLy3jxtA2Ahu`Q)u~F{RQal9jkNSbj z&%{NE+PjCssg5Lm_AF!=tOWqO-N)J;Wv8L95H$A5j)j^|Q z6Gs*m&3=MdySVnss@^mz`dO}kVzOiXE#r7m_o-Ym(zOk7NzxIfWn}ky5|dQlW?h&c z1=EFpIzHh(3^@u;&@?qxi&-KtO&#&|lqEzhY zFS?~bGmU0c)QDxb`kJ1(V6Di+)KRaj6D?%>NpD=Yc|3MF@o+h<9`pm93*yZ@n;XPXa_Obn-FSw=?y4&Alkd*-_k zzy^an5GO;}pG+i}T&g^~ClCcQU$Y<*D<7(GB&fI}Cs826QK5(S*Kr!c2j2=I zEUbgB52lGkXg#gq*7eIn#ZgvEtlG)&qG)Evb#VxquJMVmlLMWYdb4|>Yo|ulT93iM z^r`M|bQW7`$khu#PL5thuoq8F;+2Jfzj)X7Pr>g~h9~G#U zPc|+Q`4v5gz8I%^9^yjA<=K_&slC^k&LV{|Mi$fEaR!N?O7M>%PhCmOx-+1Z?KLAl zGz|HZ{sL8MB*9FDl4&6VC4su3DAW1N!Tcv`t>Jer0vB9F2~D%3gn7jb)Kf?d=tL#N znGB<4*``z-qXc^NMIJV<`;$FyJXi(nlueC%l&8mXWRP(EaUw5Dq`KmDzZom5Cm6}u zR74vcbyI z$QcRY1x%UA&YKXwOzA7>LPMk{NrfpzOH+kKboWTN@?ZK3dY05sCb1AT9Fj)AZZVT8 zEPG4nQk-eYSy(LI&wGcZq$Ab2pmLPK#X@}QYkf&U{=6Vt`M85%sYe;_oz^;Ju_DXb zo#qgW#_7S}-I`NMmeOXUgJ-2J$IcqXZ|bmQ_eEDbrJt9eaWs~8U`yb?$-nWUZ@-Yr zm-VolMnCyLBv{}MQy5#)#hculU7x*r81qy&8!O6_mD@QOnQ!-Se_)O8wc6Aqc>hBF z@>91Edea9@{+DLl+W4oTun}55Hg4@1c})9pDXI|ro^wG8+z$c@J2sPb;rDE(j2`$_ zj|rkTyc~C|FR>r6eSM|*0*o3ZA)>KQ6U%X8x`0=cXu0&y%ZSY|}2;|A1Beq7#r@QF#kqkloeZeYXxg#i=+gXOH` zhOOv~+E;a#yG@s0>GtpAa^F3uv}IaP8k9kZ-ELuVAa?&Ck?5u&j^46#x{Pe!3I>77 znnC+r*eyt;tslQ$?Bwm?f8C{`Zuxvvp?!6j_aI{*8xF;{^@7k5bWwNH^I%yU>}Au6 zz-8rzl?{)u$k>KDlI@MrNOgH3(Sm-V0HQcbmx9(paf8cziB=X+9y>;#&~W;~_tPNp zw6>gP?1Q+ugD|fMCWR@&tpe`dUA*vCi$0#)4^*_H0l^rBsqi9$Xsu~+a}wU3D82De zK>!g-9E!42QhT9(*28n-7mtb=4m1%>C(Y>Yq*=?O&!Go|FK8 zR-$`eO#KC^=K=A>K_s!%3d(9eSUh|v%HMZIY#&8T8tb7idqEZhOS=@VvrR;Lwhu%? z09Oj@AjV`?7oyND{m}AOfQhC7xnY5{`h*QF*ETJPb?QEC$zeP;su6xboy1p?(fDp( z$;%j1aVDdo02$!m9vCV|r~U}OA|`{E#(Th!H`;x{6&oIre=s1XBI%Ln`t6QM`G7#h z#C7fwK}71Sc4yv|)CX^Mk=C8s-7h|+eR-LNDhGMsLy4bp|LwXk*>p>Q(F zCt5eelAn$uuFOjTZ^_4irmaTd}P!4a|y1AB?XJRdkDSFxDB%wnS z28$3PUx~s>>=I+xh+-@^FyIxSRVX!#q2e-RVodC2F0lbuZX4XDN$k6S!u9eU#;E<& zSU(FU3W(+$0TB&^2x4sqy94K!b-tHxzaNkNUDr?G%Fb%_f- z<$C8s;XIt{`B(Z$KC7oqj$K&1$+mB1x~#4kESc*#4FWw#PVMhb!F0Tm+}!6~oVH9x zf)r#h1{A+vKN&B7GX26rzmuYl4VLuA<#p){*V%4C0ICm#8=2GFwd5$~*sl%go9Ux; zdJ$Sm-0yZA+MZpVer~c~UCsZ{D@H{mxG?oTqKn{lvbpPp@y7Z<*n?u1(ea+H36K4z zbuIU`IpZ`h_l=x1J&cpCaj#<@#t|KSt!^r-b^6m7`9dXPyudsuH5wxZT9c<1?`{!m zguwBLlZ7%m2fQ+>4O4v_uBX(w9C-gL@i4h4p;R`xB!kpVa@lsUfhoC)L3WfBvw*}) z`4g0!Ktc+pfG9P+0v%&cCsd;Z+3*65kjL^HYq2K&rUu5eRp)Do*1Q7iNfA>{>(Ne| zPi{VAK0h~3_r{ZgDf!O_L0-DBPe06hejiODTO(Yo;8h$cQ-RVe`KgWcL?Z&`R4+Yg zW05>U0p_S8`2w@mG%MOo(*m<9wEU9n&R(4CDkSMnAp6}ZE_4k>D9-8Rl|d>`qa-s= z9VB%rdW|U6XI}MI>(#c>^!;9o8Zo^Y#oEAd7PjJ#gnp%Eo6hH^;(HIt_Q)j%8y>!y z3D?M}Lq1?Bt-q?4iEBM6ltGFHZ-!VUqha@1`PPaf6-N!|Ju!^6C?OqwCuTIe(kbO& zz8@?yc#A#r#;Z^|G0{?TlfI4|UPUPA$A2&74XT**%!Ws3Xo*t`4c zy)o`cQ}o6P+;~$knx}}4M-gemC>n5Gp zj!mDiIMLR)JPlJ#{_>b1rAY+0+;vW|(konq$J+u`*&gIwZH>;IKXYp@yP0H~Qf}71 zZ!F#8Lv!)N>QC!DstOo#O}Q^VPT#YszxtZe&;<{C+y#B#?KB;xFZ(1l{Wfh~pIUhDP?zIy^&j$janWJbc{qGm=Z3_E5Bn>3H_1(8!@ZdsV$kWhmI$1eT1+P96=h68 z_?blb@rdRB_u-TPfw0Jb2q)#Ya8msXh4cD|<#({;e|$LQQLo9F3XNQ(FAXP#u>)xm z@mjXWZ-+iS3$8!inWH;9SZ;H1P5lBoJI$Eki|?MVb2-~vh1WTo%{l_q$^AEVo{|5k z&grgnyMGdO{)l1!&j}~cdti}M2Wrqw#?=cUQ=5?0Sk8l7?;yED`9)@!>`xu$xT-!) z$3K=D)OK#2D92ME`@N`cSi=Z zP5?(8HPiE#!|$F*F8NTy2}DLx;+@BY($k_omZ5U>Tn0)C;DF0RUKE{|3bazIaa3wj z8ZtbVsQNwz(NlOrI^~eH5W_g9HDQ9zIvo+438_~<8Hxe(?f)_2bXfp_KqXH`rtXv- zZ%y(U^Wj^x@`Ai;+p1kL1wlgd&0bVPkYp_D@lFzYpm(iT$tk-Xddh`t~JO0A(FQwXEqBm(jrUJ1*=Xb#96g z@QC*yMiPBW6TC51zS}1Ukx?YO8!MRAhDMVJUg+;Jq59T>U6^V{D4)6a;wH6=lD}S- zOHU8D7&pJ}d8%i+$1^I!v2)bue7t^d6UnXF-E=>Zeh^vb<9+wB4nJNc2L!wXDqBi| zd}_OVuWB6!xTXVtGW`0sNb3ghKD7g`JV0V&EHV788UjMfnoF6{tjb!pbAQ!pWP;Y;OBP5!`4uS7X(*m~_L5R&CY?!p3wSLhZdi~*Q)PK-i7+WxhJng0bt3Icr#X)8SPAB7bD zKMASZ|5ivJ{8vIs@lO*{)_>NJVq%lGUh-Kkw4t*}BNW$wmYai+S$SvAZgqgb57CTJ zYHW?YfJuRQBHnGIfk0H}6AX1b@CXuT9wr+yj>WC6oU8}Js4YRyQk9ha{nV&sqJ#A`ou@A~^`=F^X*U)veJ(YJ_d&lnL zGWXqcOEoHx`{#?CwPcAI0<{JA5?qr7?@PaG9k1^y9kOl&?=SpCr6Z^bGv9lbYn4{R zVtfgJo`vWeQI63DSq|qr>Glf&RJsz${Lmyb3Z6zPGg@J>HuL4T#^wG5WGF_>C@9Bw zM(#<@OLhNqaC}QurG5ghbbf9U8?HfasL4d_T9O5Ozq)TP=VE?Ff0fC2=y}24T^tv+}>m> zE3~?g$U}+83#o3BBu-m8mJ6YhbFtG6})S@2XZjK%^0FH1j<*ccB+^){oNZ<%J3_7$ z&>JqjUVrQ=($=nW1@FO%D$*3vZYu5|gF&1q58S?7fwb(X?9O*o6+I5Th!(uj4}Edm zcZJm8Jk~ReGh8u@_|trlr6eN*kX6no{7K{TwLoC=oHU{LRg;-caBfuu!TaOlnL+$o z0hz%_?y#khJuk*AFeHg@E=+*oT-)Me{De@LS0ykzTDi3ACP+SR|8cA)Tx}Lu6)%R~ zTzi90AM`X=U_M?Ki+jx%F$T3Y(QJZbKK`ze>0+ea^hTb&Bk9lz`1zAbl_(E}Uh-hC zYI{gluy{Rr7L%YEQ%tMM>yY;GwGQd$M8=Aewqu##VChR)&z2@VSKE!4aGV6XT0+IQC8wz9b zemlmfAgeewU$W&}LM7K5)_6sx98ZXiXIDEPH?3IvYrE}xwR}P|IP7J8O}-t+6Lj~` zn?5b{um!QQ_!Bb6sP0RX+oQ5w&4Qz3+rttapKr?wA)gTpvyp|_jojB}C4C_`8n87{ zj%Uv^@uZ^bcoOFHg=bQ?!i9I*wCK`)2CfD3#jNam3eF*iOOhYH--m)YL7Cv+DxyCS z1nz$jL^*w1BxeTaU8~j{KoGW@vpu8q-C(E>9GemxMADbrg&A1&0rMex4>U~aF_?r8 z_r{PET2;}9*E${LN02eksS4356-;Iuorw~jcff`2n$o9U20p1`8p0Mz)m(FwLxr(h za~**q8X2 z!V0z9x7b0{ao2u--{A~y+1NfHQHQQAWZT1$Minx#-~QUrWq zIG%<8ngL}2DpW-H((I@T3P>zxS?>OIGIJ+fJ)zV1&UNriRXmF zOp?cp5%YDquUkrnG`zl3pXfzasFiGfHdYWNs2Z&Dmjv-WP5q|{qWeu2kRTB8Fs@hM ze@PJKIemTz8$%@L<+*>=!%MyXL_`-f3hCz@S9dxY+#VlzGN9fu}`Xk_CeQ#Bf zc#cYLJiEMsX@A*bM_>dNL-O^N zXhGC1HjL{8K|x>iuD`Bg{e8Mf2&G(o<;EzGAhZVRtF}Ir0eX;|;lhVh*=~tDHq`9R z(?8#%OuekJo}~`Ep*=W#>IrhUyDmieJ5M;DLfUO-*w$3Ml>)_mr_kkhsvkWA=i)yKkIuzWIg%irQF-B97%n)Y#HBAd zW55AlZQ?rQ&-jx&Lo&^=!cCUcZ!mDr+aVXk>x$8*LYCE-4jsrtkm~q7JqZW+mLtr; zAgJ)D62rVTl)*GEQZ!B{J6h3M90bO`N3t3lB==-hQ_X>iG+fIcl{7&w?)-zDI`iA? zMDx@q!bzwlQ)|gu_i7ZA43?h2rMTJ{<_SAf;+v%TN)tdqn?0sOF`-<{4;8rzUYKOW z5Zaq$iqMXkWJRFi7l2=?Fq^3$ph_va*o77{tLDI2ZMqkfUNN&M#FGwf3cX%}yo`)S z;@o=8Gwxg@RJZ%2wG?!Owq4FX9=uWH;#SC7F;==#49=zW+|)YvQ{Sn9P&iw-&jq9J z)-49h?AE6zh3qy^RY^zI9!fIJ1M8=L?hodl2Kd*DKMmeJ#Tb7_ zip<7MBuZq#J$#=7y>dvFYKNOhN`mcpOj*_9cwEi6U_zx zFw1E(RpwD-s=H4sp;jL(Ud$2ojXA_W@8V+P8$+CBJ41Hrs^^R2y2VyIOvE=|J0IYZ zSUVI#v{SnrDZ%d4og7kJmyi-*=?MO@D`N#}y=t(*zlMzNdJy_w*I5zK>ss^ub+#gq zbP<Ix&%sew~=>*b>%3PHjI+Z2nzW^6Bw?4l2 zV6+|jf`~Hdp@?F#pplQ6zTk}(r|9k7MFG)OMdhjmCSkmMi~fpUo#|j|e^|OKF*^!% z07P(g(VHe%4K4^fNlho18?Q<)1YH0{J%nTemgS)c3Ct1}6mDAvF@DWoiI(NvSn)?d zHH8Wz0Q!mr@jK!KqN$&+#8Zn2fC7~%b?D>NN#Cx5w7fUgr2GUX*IwC`;~S&eP81kR zBjD^Srn(^YDy4bAQNuD=bAn)*3{1VSEL;J}eBqZuW~Slvvg&I&@yxYD+2P*maCvdg zg^~Hl8Pc0sU<8n!u3P67X%W<-7eTM62x)q=D2af&sJN0;-LnK~A!+N4aZ=)Hh#mPB zt8kCHfL_IW+WI1J59Q4gpDZl&u@bOy!+O;eX{AMysuxRXX{mo8LxoF~$#(s6b>CLC z3vLm6lXtbVMF@y!i=$=Yg3PM*tG~>C>M&g7e#ck6CmZc@ycoCM;+;z0dg)0Uv)5%~ z@!6mY*$dCdPLIpC{mxrJWM(8RT(*5W@$_NN7vZM;?%UJ5T#IZ%r@8m;d={SYRYI%+v_UMv-#m?8_e1ao@ zvVQqhJmbst5FhpnSW>*D^I+M_-Fl}tUG6_^^_YQaUM<-1o4l~e(?!-jk#TYHm_t3= z(88GzX@3K>X8)3<{t9S)%Tnh`)IvTeL<|UvKK{6I->SBXy!Qa0h1LX%)=9wSx{;ZH zySz4Zou$6DF>&yyaZ}|&?d@nQ{@JI^xxSj$ z9|J8m@^5tr$)KR&O3qph>-T*8cGc6IYd?wG_-%rub%q}XF*H;0Tb63}nkiHAF%k}7 z*VfwBpx`)d^H>b`z$+Ezh-r^;FlBjrBB7BxYE;FQFMMBaopGmKn;sc{7SakhwrKQhpN> z0B=xenoA!O$rKRB5WJC_QiKz>3R;oS#d15;m09t-u%OS%zqK)za3D|xl5%zl^dsfahG>ZqGfuUwSzk#F z$aAK&mOk>CXWd~&LtZt3y>n@k?~+VZ^YNh!1dL!_`MT8&&)ljNg;CJ5BlteXo75C$ z^Qe{^drz#}h~Oh{B`0bbym^ZlO1{@+>2Ds@bK^~@%_}g%5OXIUu6f0P=eUew(XAF& zqyF12vcm&>>*T|ONJrbYDZ6M0EEF<(Q{0URVgn3ANVRvOMpIH{BdhNs>m0x5GIj$E zXg>JN1JaEMW0(-Kl^dG1TPduZF<2+v9krV|VdI@Q?ZkLd>WluBZ@~*){%lDKJ)A%3 z5gB{k!s5th$Al;acBfTgZLGC6!eO?0Se#2KJ&Yi%RFER)m8GFhk;HYT9orS(EPkLo zo3UpkSwn0T=+D2cBMJxi+k&41cnT`O&VP9dpgq7D>TqI_dRM16K0z^XKeC$t@hRAb z><7g_MBT?07DWSan6XuX2JWv<0flr7Z3;X}x@1)Oiewb6WYPlb^+cmc4JcSQ5AvZ9 z)oeu)4aATbMooY&zAjiR?HYv>WnS#gG&o*A1$=t5@Y-9`J2JJ`1*=Tw7qSG)rR%3) ztwF7Hq361RW5wsxX$u$lRQ*Fsr|6ee^s zFp+x5{~;1d+0-z~T7YRqM@gJNCsIZ0iEx~_C6h)xHXH~VsjIGhQ%4sGl{g8ruqQXx zG7gj%YeNbB_7vpXd(KJW>X^}@L8I^1i7`FK$m1qB3nP*3rk@~i3eqOwxvBLC3&;H}(xcD0)&1R2vs-Yw0f#c3U1iL%97 z*U*$I8X0CjmJdfKr*dX;R5IrUAVbMSQ8p2)!2TyI@R!3{@S%=0!o|}25LdfurK*OBA zQ(uMfbu9UdMypoc+`9+WpOT8H`Y?(bZ}qV+cX9OdR}|;h@N~Se9pv9@w0yt!PCcqy zlB4tX@CJ#6@`xnIfSr?>@KX}e>z&|)73(w316U5n$yndgeC&}*@D;J+|!R9X>w;vn#8+j*JbMYN{p)IxxdD%nDf>57V^>S z$@;2}u=Ozc3wvv~eeklkNcP26SxYLA&SHAo@-k`cU-A;+EFb=6*d|DX#MQ~SYDD!P+ z@U3_qle!Ee?=&JLl=MSuujYIu^z5yNtFYl5CT!UhXP(6gB=HY&TUEX?Z{eNRV^C&V z)v}vD)Za|H18Q69@?rd_spB-dh7r=GvNe-)`l_DHtb=ceC+~&eLW+W`+(oX-hu1mf z9#^SNJ@8Mbwmjy>D|bF$ZhS~HuXeJV_d=dWR1-nrl|)u%6mU%aHiz@GI&O1BqE(#ZfC(Rk&w0fyz-T0Lnhh&k#;fJ(U|^GLpd%Z(a|;VssAq zjLA;BQ#8NZGTr^-xPJSp1D?yQUoBI#Gnj}G3n9olt23O6jS}aHb(U8==be!ZpNIP0 z{%kz$p-=RT215Bz*JhdCEWb;Es)i#(Mwy6YAxC1NFqdDyvdCKIW}b^;(FAw!ToY}! zJma;nJrSuLsHeaLVh;%>Z&|8%+oF#lTE)|V;Z%0?fXDT@c98{kh^%WB-J-t}ZoFf1 zoUV9K1c@=bt`o?p)mZ?0wjThi;+?JvRoI4h`{Q%vvQ(t4jyEU#waGZ$UX;iR2FJS_ z&fIVmnL?68qn~$J8=eEB(5g09>e~vwcj6Gef5-eFv0hi=-2->hwf&C^8{1>-w;aw> z_A@HdVE5f!Pgx(U*u8&nvfqurfeiKd@_RUY@cTZZ6~Xm?#6- z3Jc^Bf(X1{0N-#pKy8op(MWQ0=i_Y z-a5rV*WfdqG*`SI_Y&>k`#(n(r08+ENZH_Eb|(l#GiuS0n{F=jO^_C>hV@b9l;jfO=v6g(_+^z zYvTVymo6Z;*x7a7%xsf5$=MU5BcObGeI;fFkt~Ev7LdU>a$XV`peRMnb&L?`) zkz7V>fISNb3fhn_NV+o`#ao} zE@%CFchZR3IWQlU?Cq842G^V=eI7iW`VeA{P33+W+lXEH@yeN2-v9H#dYYooJzqev zoySC?fMUBIq6h?jS1j=vwHTheM1~)+nIoyyUjezlDps0656GXIV?bni?&B|q-d%#x z5pi5En?y?;7lS0QVhn<0v|{N(6ut%Zvq=_I*{HxUjv!MaCsx6dX$|@52+fe}-C!qu hKl5^_*+jeSy456$dedAHinR?IALlix>kjG8{{pcgsW1Ql literal 0 HcmV?d00001 diff --git a/contributing.txt b/contributing.txt new file mode 100644 index 0000000..9692459 --- /dev/null +++ b/contributing.txt @@ -0,0 +1,66 @@ +--[[pod_format="raw",created="2024-05-24 11:33:38",modified="2024-05-24 11:52:39",revision=11]] +-==================================================- + CODE STANDARDS +-==================================================- + +** Naming things ** + +VARIABLE is a constant (must not be edited) +_variable is a global variable +variable is a standard variable (must be "local") + +** Adding things ** + +/main.lua is the unmovable entry point +/src is for all the code + /state is for state files + /character is for characters files + + +-==================================================- + PROGRAMMING PATTERNS +-==================================================- + +** States ** + +All the code must be encapsulated in "states". + +Each "state" is nearly a screen in the game: + + - Main menu + - Options + - Character selection + - In game + - ... + +All the necessary variables to make the state running +have to be declared in the state: + +my_state = { + foo = "bar", -- Foo is used in this screen +} + +All the states must have init, draw and update +functions: + +function my_state:init(options) + -- Things to do when we need to initialize the + -- state, using options. +end + +function my_state:draw() + -- The code we want to run in the Picotron _draw + -- function. +end + +function my_state:update() + -- The code we want to run in the Picotron _update + -- function. +end + +To change the current state, simply assign the new +state to the "_state" global variable. + +Keep in mind that changing the state will pick up +where it left off until you manually call the "init" +function. \ No newline at end of file diff --git a/gfx/.info.pod b/gfx/.info.pod new file mode 100644 index 0000000000000000000000000000000000000000..36527a736e337bee0d5a4d0e847262a95d95e826 GIT binary patch literal 86 zcmdPZjgBtJPti#(N=+n-7FP`@FwEuL^+57wc zelx%O`Q6{WyEB!QEiIXz{(S;J!xX9wY6)*c(5T4fD^R)=4giM&T2otLLeZL*3;`mfsj;Rd@z}I36@tK+io!Z*XtSoN`Zkad zxwTa>C8-;x5{bncbdZcKY13o5Ag@zXmd=g&WPVUy%3nG+oGu1 ziI@6+;EAWR%4{tVS+ys6v#iz=-C1^(CzkcI`JPyqWo@3A z+0U-`L_?OX^~AU=+vbU~ezwySu`Ju|iTr-{h$n_**>TU#vKPFw{p>aG<1BmIdpFBY zd$0Giue=wt?7a7MKNA73Kg)#X?U7^D>ywd@(AzGZDi}dtukWz~A7Ie~!N&hZ*%G0I43!e3Iq}_*Huv5k# zgRcKJCZ0xafQjd!JA{enkekcI3Froy$U-;7#Iwi^Gw}>`6(*iSuFAxd(2X#09J)Fa z$B>)P#8K!LGI0dCLl=O7S;Lrk6uF3re&`l6aR|CmCJrLEgo%ft8)xDGauZDKhpr)O zf$nf79z<>_6MLb1F%v&S?nowfLw5vb;sN9uxIyOM58VX5`4uow?v~&en7CIG2nS5u z1Ko=-m!ysyAX3Z;T_1$!CcmHyX*qy z5`QZ?MffF5+yYNxUe3gJxC8SlCbpqg%*QdY6;={1Yuaq`S|&DOo@Sz#@M%n}A<2Bi zFJ~fyTOhwu?gZY5IAP*Cd<638Ok6|WKzs%hZP@WaK8uMK?Bqb+$b^ZVT*PNH(S)54 zVRh@B|n%@>wTO3G;|V)~ zod(FSw=Eo-4*4qUa>Diyhd|zAO(*Og?94zsW6d_%?bvCA{6=d& zVVkjYHR7wSMJ8KAoOzJnWVI1?J$4pCzSde!*fQ)iBfie+G+8rtWXF509>QebS`pu1 zts(3R>~uhWv(;;|DcHFN@lDod!p34}CFGke*`PAwbV9zxy2E4%>~tZ%)w-Loi?GuJ z`H!so2ve|g1LE7Q-6r#6XAR`HTKmWb;;e)GHtXOzX9ME5TL*D6Mx3>f-)Zf~hl$gJ z_+8c>LUT;#I>>ie4`3Q0P6y&Ut$Q&oB1gcW+GpL3>2TAT5BX25I|(f(P9x&?Shr$2 zq1ZR*zt7r+X}#$*Aim4`A*NTY^bL-9!0IJ*uIY@0{HNAUm@XksIpVvm8!%l#oRN_4 zvAQu`Wjb-h_gbBpt}pcu1Rj#TqFafhBfigS$Mi09g?~U)9k7;Qx{Ejg$bW7%WBL$z z9`T2*CPMqonUFtXU5)8egdehIVtN85iwHkp5lo+l>rKhIjL?(l4B_`%^_ad4?Oc=h zSv8pc3fU@=%b$qptI!@wWW%ZneGS=BQ}($M)89h7l<O^b=?| z6F$d+n0}7zrG(G40+^nG_6n0<@foIHBD;(5^nHY$h4yN~r_9H65Zb*apCIQvhwLqc zrw~04?b`@1r{|Hq!{j6BchKHNxIryw?;*T|{vFu|On%W6FmTCX!gcyBvY#+{n0^E8 zEa5}w*T_C8|BvWb(Ehc#mwpNDH^?k{2H9^B`USNA{2&;}dyjqw?f2=Y(EfmajOs(-));$W67y5c-_dxpJ><5u{l;hUl|05~j~cthze54 z7t$kA52cSuJ&ZmoHKP4e7t=#>jM9TLQbHe=I!+HrouK=rHok><4XH5`nu7oH0DpVV Jg}3NU{{(;}QP%(f literal 0 HcmV?d00001 diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..0f172ca --- /dev/null +++ b/main.lua @@ -0,0 +1,30 @@ +--[[pod_format="raw",created="2024-05-23 17:40:17",modified="2024-05-25 20:32:35",revision=1935]] +--[[ + + Pico Puzzle Fighter + + by P-Rex for Pixelocene + +]] + +include "src/debug.lua" +include "src/data_tree.lua" +include "src/conf.lua" +include "src/state/main_menu.lua" +include "src/state/game.lua" + +_state = nil + +function _init() + game_state:init() + _state = game_state +end + +function _draw() + _state:draw() + _debug:draw() +end + +function _update() + _state:update() +end \ No newline at end of file diff --git a/map/.info.pod b/map/.info.pod new file mode 100644 index 0000000000000000000000000000000000000000..5203c1588e2947ae84f1aa61824926eaf71dfb24 GIT binary patch literal 86 zcmdPZjgBtJPti#(N=+n+a literal 0 HcmV?d00001 diff --git a/sfx/0.sfx b/sfx/0.sfx new file mode 100644 index 0000000000000000000000000000000000000000..cf705730d4bce004c80d33d28e42dd67523b918f GIT binary patch literal 265 zcmdPZjgBtJPti#(N=+f}{ kz+QQvA#3)Z;CEo)b@=~(!-oPchy+*`Otb_5h5uUu06?5oe*gdg literal 0 HcmV?d00001 diff --git a/src/.info.pod b/src/.info.pod new file mode 100644 index 0000000000000000000000000000000000000000..2ad1c83ae14be80f75c9d12e9aba5f0abaf892c5 GIT binary patch literal 86 zcmdPZjgBtJPti#(N=+ self.board_height then return false end + if x > self.board_width then return false end + if x < 1 then return false end + + return self.grid[y][x] == 0 + +end + +--- Everything must no escape gravity. +function Board:apply_physics() + if self.state == BOARD_STATE_RUNNING then + self.chain_counter = 0 + self.drop:fall() + end + if self.state == BOARD_STATE_AUTO_FALL then + self:auto_fall() + end + if self.state == BOARD_STATE_EXPLODING then + self:auto_explode() + end +end + +--- Store the drop in the grid and require a new Drop +function Board:persist_drop() + if self.drop.grace and self.drop.grace_delay <= 0 then + local x, y = self.drop:secondary_coords() + + local main_x = flr(self.drop.x) + local main_y = ceil(self.drop.y) + local secondary_x = flr(x) + local secondary_y = ceil(y) + + self:set_gem(main_x, main_y, self.drop.main) + self:set_gem(secondary_x, secondary_y, self.drop.secondary) + + self.state = BOARD_STATE_AUTO_FALL + self:new_drop() + end +end + +--- Get a new drop +-- The next_drop is moved to drop if existing. +-- If next_drop is nil, we create a new Drop instead. +-- It also ensure that next_drop has a new Drop inside. +function Board:new_drop() + self.drop_counter += 1 + + if self.next_drop == nil then self.next_drop = Drop:new(self) end + + self.drop = self.next_drop + self.next_drop = Drop:new(self) +end + +--- Set the Gem to the given position. +function Board:set_gem(x, y, gem) + self.grid[y][x] = gem +end + +--- Convert a "grid position" to a "screen position" by applying margins. +function Board:coords_to_pixels(x, y) + local x = self.left_margin + (x - 1) * GEM_SIZE + local y = self.top_margin + (y - 1) * GEM_SIZE + + return x, y +end + +--- Automatically make gems with empty spaces under falling +function Board:auto_fall() + local falling = false + + for i=#self.grid-1,1,-1 do + for j,gem in ipairs(self.grid[i]) do + if self.grid[i][j] != 0 and self.grid[i+1][j] == 0 then + self.grid[i+1][j] = gem + self.grid[i][j] = 0 + falling = true + end + end + end + + if not falling then self.state = BOARD_STATE_EXPLODING end +end + +function Board:auto_explode() + -- Increment the chain counter to increase points + self.explosion_counter = 0 + self.chain_counter += 1 + + -- Look for all crashers and recursively look at neighboors to mark them for explosion + for i,lin in ipairs(self.grid) do + for j,gem in ipairs(self.grid[i]) do + if gem != 0 then + if gem.type >= 5 and gem.type <= 8 then + -- It's a crasher + self:mark_gems_for_explosion(j, i, gem) + end + end + end + end + + -- Explode all the marked gems + for i,lin in ipairs(self.grid) do + for j,gem in ipairs(self.grid[i]) do + if gem != 0 then + if gem.exploding then + self:set_gem(j, i, 0) + end + end + end + end + + if self.explosion_counter == 0 then + self.state = BOARD_STATE_RUNNING + else + self.state = BOARD_STATE_AUTO_FALL + end + +end + +function Board:mark_gems_for_explosion(x, y, gem) + + -- Upper gem + if y > 1 then + local top = self.grid[y - 1][x] + if top != 0 and not top.exploding and gem:color_match(top.type) then + gem.exploding = true + top.exploding = true + self.explosion_counter += 1 + self:mark_gems_for_explosion(x, y - 1, top) + end + end + + -- Lower gem + if y < #self.grid then + local bottom = self.grid[y + 1][x] + if bottom != 0 and not bottom.exploding and gem:color_match(bottom.type) then + gem.exploding = true + bottom.exploding = true + self.explosion_counter += 1 + self:mark_gems_for_explosion(x, y + 1, bottom) + end + end + + -- Left gem + if x > 1 then + local left = self.grid[y][x - 1] + if left != 0 and not left.exploding and gem:color_match(left.type) then + gem.exploding = true + left.exploding = true + self.explosion_counter += 1 + self:mark_gems_for_explosion(x - 1, y, left) + end + end + + -- Right gem + if x < #self.grid[1] then + local right = self.grid[y][x + 1] + if right != 0 and not right.exploding and gem:color_match(right.type) then + gem.exploding = true + right.exploding = true + self.explosion_counter += 1 + self:mark_gems_for_explosion(x + 1, y, right) + end + end + +end \ No newline at end of file diff --git a/src/conf.lua b/src/conf.lua new file mode 100644 index 0000000..a310968 --- /dev/null +++ b/src/conf.lua @@ -0,0 +1,79 @@ +--[[pod_format="raw",created="2024-05-24 08:18:32",modified="2024-05-25 20:32:35",revision=1261]] +--[[ + + Configuration variables + +]] + +-- System informations + +SCREEN_WIDTH = 480 +SCREEN_HEIGHT = 270 + +DEBUG = true + +-- Game modes + +MODE_SOLO_ENDLESS = 1 +MODE_P_VS_AI = 2 +MODE_P_VS_P = 3 + +-- Buttons codes + +BTN_P1_LEFT = 0 +BTN_P1_RIGHT = 1 +BTN_P1_UP = 2 +BTN_P1_DOWN = 3 +BTN_P1_LROT = 4 +BTN_P1_RROT = 5 + +BTN_P2_LEFT = 9 +BTN_P2_RIGHT = 10 +BTN_P2_UP = 11 +BTN_P2_DOWN = 12 +BTN_P2_LROT = 13 +BTN_P2_RROT = 14 + +-- Board rendering tweeks + +GEM_SIZE = 16 + +BOARD_X_MARGIN = 20 +BOARD_WIDTH = 6 +BOARD_HEIGHT = 13 + +-- Gems + +GREEN_GEM = 1 +BLUE_GEM = 2 +RED_GEM = 3 +YELLOW_GEM = 4 +GREEN_CRASHER = 5 +BLUE_CRASHER = 6 +RED_CRASHER = 7 +YELLOW_CRASHER = 8 +RAINBOW_CRASHER = 9 + +-- Game configuration + +GRACE_DELAY = 3 +BASE_SPEED = 0.01 +FAST_SPEED = 0.4 + +-- Secondary drop position + +TOP = 1 +RIGHT = 2 +BOTTOM = 3 +LEFT = 4 + +-- Board side + +LEFT_SIDE = 1 +RIGHT_SIDE = 2 + +-- GAME_STATE internal states + +BOARD_STATE_RUNNING = 1 -- Standard state, the player can control the drop +BOARD_STATE_AUTO_FALL = 2 -- Make gems with empty space under falling +BOARD_STATE_EXPLODING = 3 -- Frozen state, can't move until animations ended \ No newline at end of file diff --git a/src/data_tree.lua b/src/data_tree.lua new file mode 100644 index 0000000..81c33c2 --- /dev/null +++ b/src/data_tree.lua @@ -0,0 +1,10 @@ +--[[pod_format="raw",created="2024-05-25 13:14:53",modified="2024-05-25 13:41:12",revision=118]] +--[[ + + Data Tree + +]] + +_data_tree = { + state = nil, +} \ No newline at end of file diff --git a/src/debug.lua b/src/debug.lua new file mode 100644 index 0000000..8620aa0 --- /dev/null +++ b/src/debug.lua @@ -0,0 +1,37 @@ +--[[pod_format="raw",created="2024-05-25 14:23:26",modified="2024-05-25 18:38:51",revision=549]] +--[[ + + Debug utilities + +]] + +_debug = { + vars = {}, +} + +function _debug:push(var) + if var == nil then var = "nil" end + if var == true then var = "true" end + if var == false then var = "false" end + + var = ""..var -- force string + + add(self.vars, var) + + if #self.vars > 10 then deli(self.vars, 1) end +end + +function _debug:draw() + local char_width = 4 + local char_height = 9 + + if not DEBUG then return end + + for i, entry in ipairs(self.vars) do + local x = SCREEN_WIDTH - (#entry + 1) * char_width + local y = (i - 1) * char_height + + rectfill(x, y, x + (#entry + 1) * char_width, y + char_height, 0) + print(entry, x, y, 7) + end +end \ No newline at end of file diff --git a/src/drop.lua b/src/drop.lua new file mode 100644 index 0000000..722e9c2 --- /dev/null +++ b/src/drop.lua @@ -0,0 +1,143 @@ +--[[pod_format="raw",created="2024-05-24 19:25:58",modified="2024-05-25 20:32:35",revision=1534]] +--[[ + + Drop management + + There is a main and a secondary gem for each drop. + The player control the main gem movement and the secondary gem position: + TOP, BOTTOM, LEFT, RIGHT. + +]] + +Drop = {} + +function pick_random_gem_or_crasher() + return rnd({ + GREEN_GEM, BLUE_GEM, RED_GEM, YELLOW_GEM, + GREEN_CRASHER, BLUE_CRASHER, RED_CRASHER, YELLOW_CRASHER, + }) +end + +function Drop:new(board) + local o = { + board = board, + faster = false, + grace = false, -- A short period of time where you can move even if blocked + grace_delay = 0, + main = Gem:new(pick_random_gem_or_crasher()), + secondary = (board.drop_counter % 25 == 0) and Gem:new(RAINBOW_CRASHER) or Gem:new(pick_random_gem_or_crasher()), + secondary_position = TOP, + x = board.drop_start_position, + y = 1, + } + + setmetatable(o, self) + self.__index = self + + return o +end + +function Drop:fall() + local speed = self.faster and FAST_SPEED or BASE_SPEED + self.board.drop_speed + + local main_new_x = self.x + local main_new_y = ceil(self.y + speed) + + local x, y = self:secondary_coords() + local secondary_new_x = x + local secondary_new_y = ceil(y + speed) + + if self.board:position_is_valid(main_new_x, main_new_y) and self.board:position_is_valid(secondary_new_x, secondary_new_y) then + self.grace = false -- If we are able to go down after a grace started, we must cancel it + self.y += speed + else + self.y = ceil(self.y) -- Ensure the grace is visualy complete (no 1px remaining) + if not self.grace then + self.grace = true + self.grace_delay = GRACE_DELAY + end + end +end + +function Drop:secondary_coords() + local x = self.x + local y = self.y + + if self.secondary_position == TOP then + y -= 1 + end + + if self.secondary_position == BOTTOM then + y += 1 + end + + if self.secondary_position == LEFT then + x += 1 + end + + if self.secondary_position == RIGHT then + x -= 1 + end + + return x, y +end + +function Drop:move_left() + local sec_x, sec_y = self:secondary_coords() + + if self.x > 1 and sec_x > 1 then + self.x -= 1 + end +end + +function Drop:move_right() + local sec_x, sec_y = self:secondary_coords() + + if self.x < self.board.board_width and sec_x < self.board.board_width then + self.x += 1 + end +end + +function Drop:run_grace_delay() + if not self.grace then return end + + self.grace_delay -= 0.1 +end + +function Drop:rotate_clockwise() + local ori = self.secondary_position + + self.secondary_position += 1 + if self.secondary_position > 4 then self.secondary_position = 1 end + + -- @TODO Smart repositioning : slide on the opposite side if possible + + local x, y = self:secondary_coords() + + if not self.board:position_is_valid(flr(x), flr(y)) then + self.secondary_position = ori + end +end + +function Drop:rotate_counter_clockwise() + local ori = self.secondary_position + + self.secondary_position -= 1 + if self.secondary_position < 1 then self.secondary_position = 4 end + + -- @TODO Smart repositioning : slide on the opposite side if possible + + local x, y = self:secondary_coords() + + if not self.board:position_is_valid(flr(x), flr(y)) then + self.secondary_position = ori + end +end + +function Drop:go_faster() + self.faster = true +end + +function Drop:go_normal() + self.faster = false +end \ No newline at end of file diff --git a/src/gem.lua b/src/gem.lua new file mode 100644 index 0000000..66c27d0 --- /dev/null +++ b/src/gem.lua @@ -0,0 +1,53 @@ +--[[pod_format="raw",created="2024-05-24 19:41:08",modified="2024-05-25 20:32:35",revision=1391]] +--[[ + + GEMS + +]] + +Gem = {} + +function Gem:new(type) + o = { + type = type, + exploding = false, + frozen = false, -- If frozen, the gem will not move even if empty spaces are under + } + setmetatable(o, self) + self.__index = self + + return o +end + +function Gem:draw(x, y) + + -- 1..4 are "standard" gems with no animations + -- they are also stored in the sprite sheet at the same index than their value + if self.type < 5 then + spr(self.type, x, y) + end + + -- Others are crashers and need to be animated (in the futur). + -- And the sprite index doesn't correspond to the value. + if self.type == RAINBOW_CRASHER then + spr(8, x, y) + elseif self.type == GREEN_CRASHER then + spr(9, x, y) + elseif self.type == BLUE_CRASHER then + spr(10, x, y) + elseif self.type == RED_CRASHER then + spr(11, x, y) + elseif self.type == YELLOW_CRASHER then + spr(12, x, y) + end + +end + +function Gem:color_match(type) + if (self.type == GREEN_GEM or self.type == GREEN_CRASHER) and (type == GREEN_GEM or type == GREEN_CRASHER) then return true end + if (self.type == BLUE_GEM or self.type == BLUE_CRASHER) and (type == BLUE_GEM or type == BLUE_CRASHER) then return true end + if (self.type == RED_GEM or self.type == RED_CRASHER) and (type == RED_GEM or type == RED_CRASHER) then return true end + if (self.type == YELLOW_GEM or self.type == YELLOW_CRASHER) and (type == YELLOW_GEM or type == YELLOW_CRASHER) then return true end + + return false +end \ No newline at end of file diff --git a/src/state/.info.pod b/src/state/.info.pod new file mode 100644 index 0000000000000000000000000000000000000000..f4cca64ebde573ac944578cd8bf37ec9b0bc0325 GIT binary patch literal 86 zcmdPZjgBtJPti#(N=+