From ffa7ba0db3ec23e7266f651a1d3fb9571424d73b Mon Sep 17 00:00:00 2001 From: Jan Lerking Date: Thu, 17 Apr 2025 22:29:00 +0200 Subject: [PATCH] Added HUD with lives and level indicators. /JL --- assets/cherry.png | Bin 0 -> 29911 bytes hud.py | 85 ++++++++++++++++++++++++++++++++++++++++++ labyrinth.py | 92 ---------------------------------------------- maze.py | 8 ++-- pman.py | 40 ++++---------------- scoreboard.py | 42 --------------------- 6 files changed, 96 insertions(+), 171 deletions(-) create mode 100644 assets/cherry.png create mode 100644 hud.py delete mode 100644 labyrinth.py delete mode 100644 scoreboard.py diff --git a/assets/cherry.png b/assets/cherry.png new file mode 100644 index 0000000000000000000000000000000000000000..cb902c449568dc43c911d09aff7a92a20f8f26c5 GIT binary patch literal 29911 zcmcF~hdZ24)V9@o?=^@BQKCeN7D9+F61_{5=+RbRooEq>-X%oz-dSCu6TR$;9_%j5 z>U@vi`@Vm|ce!v~yU)y=xzBy>Idf*7SY2&ZGGb<8EG#Utmukwdu&_YKcfW-Az$e4A zu#dn$d>ai_Wvtt~pZt!J6yOsAua{aX1WSZ$_(W1mw%0$gu(1&uzI#(WlP%Fecx8T8jtZYBPnBb%@C8b`@Qf;W!lfr zm^SODwz7SBPfiCjRu4)`-Ce!Cb)sRHve%kAGc8Ssk>fvAV;$SMI7)<^5tRR*|K#W> zpornbRx;J>Kd{`e6Z2ZFiGWdihFhSc>5!5RSNt2+^d~B|w16GT#MjVEh;?m$JEkG1 zeYBmAvFgq|n-NfOnB~xVRRuJwCK~(BW=&8Tgyo^o)?w)xI!h+-?xSo{*=N!=7C{Nv z93VT1!|l74t*N%5Prf|bYN(QdpffSkck?wL;)h!>^KQ+|QKIngy&p^B0UCQz#D$tV zwx`c^b|y47-x>H_gyBqXln(uG@2Ruhv%7}g6C{Co*f#CpsE&{I2_3UoC6YI)bSH&R zs5v7X%;oXh<-c{;vo~8Y39uy@!bEU=ox?AEGoCWMB|(9mi=Wj$r1kgYcCAzd=)s3qsQ`!u~#TL}u>Xj>SpwZ^XeJUO3)Q+e-@5gz?4uc`ak0=%J~o|SUy za&2+8@?u`*m4jK<;GmCw!E9lH+C(H}VS^MoI&9mY<@f~3Z2%1edD1I%R=?r$^5yS9qCQ$c)Kho`C)t=8Y4ms{ zvas&Lsy{#WV#r8$Iz@!ydhR6Q*_X)T+-mXgT1pSZ0&b()gU`P`!X5#&65+J`H>!-VUA?N0{fo?_W+NN$Up}D z6G~1q?N{fZGNiGh-{biHr@tp=gl4gx#o|4UC3Fc66z_U1&iWVg1zik5 z47!F<#(ET)9~hKkw!|pTM5>`n@IR668`%S7568;ohe^7utJ;3?!(HJ6QDo|G3;BEj zFU#j)Cmu6bF-D|pNxD9EWL2Orh!0i!a9WXt zJOwF~JfyfoTs$`gqR}yc)8RfwTbadMV?(*sOf&t#2Pc~A)qftgE!A#lP4AhN z)dVmGckw;^6<_;F8}wfskW!&u3aE{|3q*V#pfxXzZu5aAWLb*~6zrwqlc~PFrwGh! z0L2B@vskCuB5)ydl6qd`KKjCF4;ErEti?m2D)paz=OexCo(!HBYqY)wrvr6<99KT! zGpfQvZ+OU6r5tO1u>n{Iq++qO59r}08RLhM4n^X-Mha z0sf^|7A}VyBMl`&n>-&mO@MxNf~Q{ev6iFa`vQso^U0sVdnkXn;4@vV`fhot7QEuc zxr5L$$;DQ`oIsAU<_E=Ccc{`9ah&OELR0B>;Ug;gEHf6}vPY&(vnw-I)f>`z1+D~^ zv?^gj5tP=)Si;?yG!DJ`l&|5{fz{=lk#!-o!ENjkh_bRQ0!SB>e<+sk#oeR9xmfKK zQgyl7{@mc9zaQ{lM~q&=C0VRO4j*EOQF`!OP}?wb+K>O7y5ad01%k)E^O7(L&CvHc z?QmgPZl~k#=N*u=5~EcRa?vfMt#{EP5ll^hKikdlGdPF7|uUldOsz*XiZPe=5&abHpdCT7+gXYK5N9S$`z zUZ>vVq5ud-K8e##jQ*YWWzrg#RemWVu(~Rq{rWXzsmb{MrO_cDCLoldaNkWZ>5iT8 zsvwTyF-Vh%0eMd;iC}|M-GTzKp&Q}PPpN%P5JMapb*3*4ciO4k7 z|CZDmnZe}lT72QuTF(JocOUZ>gnzIe8RtB?6dbHh>p74$H ztsI>v1TWS;K6&sD@0{tumOAY;s2-~Nijb4Jrv}Ok83e}vs7M0N`Y7n|GTs25wrAyA z^H!v2-s18!zKekk0w6l+I0CJ0@4#dH(NyO*y~Y`LmAqF(N20qIYvtM%B$!3)KI1>% z+NFyofM`H0zeqn2Ik{U!a{7uwb!=Dt%r%h>`>v|vCwT1#Oi?UN(9D(S!r%T}B$+b7 z!7YlOl5U|5{U2&WNY2D)`&W}4mNF>|Y0@bI3Bl6dt8;}zVJq4eSV4)9rb*)ERx-rA z9Wup8Vw$-2%UT7j4kx&&RCk&I%d#p2xA4u~I=7g!4dTE_on4x&&2S&!x_x>c-nJGs z+Svh%9*;u*V_n<2cHhiY@>>wb4mO6(sFW1}0;}9sOT46i^T%H%bH;veW3}(GOq2lk zQgP6YQ~Bz4v#LE}E9`_kQUQHBx}lKA~W#UtAb z_}TFVvAu9xRQZR60m$x&EMnD~>X_XC85ZD!Z~6BC>KkSn+jtl54&I5_LOAUDI=pgJ z*^eo-O|0|}`~Y`1x?uPzBT|1g;>fqH^kN=U4V6?Aa7@0t^IwHJ?iGrA`)@~h4 z%sFFDV!vYhXRvm*+vVysBYU`$1g^I+$O5#iI|o%>`mY@}1IQ9P@!_H(F00J=hmwHz zUkv%(x5<|bb5m;@oVT>1Q?~4v%({N1`Bg?GVZ$EE^H1{KVWIz$1LX@f4Ta<^&}1x8 zP?%$rWH-$CkY+HjHoq`u06=XMmkAxslyiqw=DSu61p6xe*KB|YY6z)|^PyCchzvRk zv@CA=4d(o6%2G`yn3TdWAFj&$+_u~FkB`+M{&R0KO)pZw!+oz&qVRQSc_G`#L9}P; z1=m2q>#9J;Gm3Kmj5s_TcN^^(7_hR1%)h?O!#c%ppkzz1{r-}WQ{9%n(cng!_@m#< zqmX@Td6BAk-k9@UobNH`!jQV^@7N3-RM~ZX133c&LGErw63xR9x4YI!cSNiM6QZ8L z`+zYK(VjT7zkSKOpRk0Z^LcBSz$7R?XSXZQb}}8~bn`^-dhD(xM)A}Dh$L4B*?@mIFtQWlO%4Z zb#VX3GMRV>Qo>tu3Aw9fVCZZ+r%esJv;EV=c@saP{?`Z`3zDn+t$7xYvB$@+OBThP zeMq|xtcl*<5S_i#C7FEkgB>7{o-D2Dw%kt#g6Pq(y0m9`VvF0ME2zr^dJzi(TWA+n z$gr{wn8%%Etl@TjyPGMl)}_*n<{0iF)99>siygM3woyRB$=qF5^U%kh^g{WTMZwaPH%A(X;RD&28)6yOn=vj(;WlBXZ~I z{T-#4S}Ec)2?;?~Oy^ zs>g4!YKh{i8MtWfB8W6M>_B+@*X!Joct`h}S4OmyXPBjv>XuHT9V$2u^!rAvcD!VO82<{ zC5Sj;bPhT1;YvswjX`sF0*WV74Jpoz1A$AOzCvI}B zc%(N{0p-Avq(g?yVM!a$C-jR6Jh&I{FQq@`!srC$LjAbfw!$q%4Kk^d2_9aq2E!bg%xa?1jMJLTtB8DR}Ky6?%2Zt4@ zW*87)B>nZ26KVD*7KmvP0*&^g^ob}y*gNhkXqbF8??sh0U>fet*`CiJ1(u(SZet}K zF$%F(?_hw4g5tET%mq{WZ5QGK4)T&5uErJUell_y01w+d|7!s3{xs;tUI%tup`m&D zmb3xP-~G2w_pAL6v~M!@k1CX!f!uAfgO%ipQ0i&@8nB%_`!H;cSVOS6uWa2*F5ARP z{eY=esz6KQgHs3H4LHh2ei2KWga%wWS~ud{ZZ*<#;Q%PF{BndQiBQPJMB>o@LX=us zl%{`znagrqnmCiJxDlUz8n^u0&cLo9te_3=UU7%!Z6atOAs;MaNbij1puh`O3w`eh zs3@@Lh<1@BE!-R>T=o!1ja7+=2!D=S8777Iv-j?Hq@D{U$y{~2KTppm(IW;{tkyVH ztlK!e9z2g_+2NZlYb4>7jo`jOr|6ZV^QBqQTxuSUltKSmddoS5sOc%ejPor8^JO(x z>m4;#dQ%=#dCbbn^f{8O^_|Nvxe&n9oUB7?{_;Oh{}j@yyXS5;v+mDr$-D$<@Ps50 z7?UK2~H!Q^V!AlW%CD*k;J8dj>govz-Pw)tI z$Y{c#!6~#1h=RLq-sJg}2#O9$HQ*EDD3_WdSCwh>wapjmokeV@-o^xGHgG97Zl|{Q zUn*i-J;!MaXMekq6E_7!{p12IHTuS)*+E)hh)@32=9Zwl)1i1J49|japMUwe)HPH? zE(%@TdzCF-g>`ySvebkHb2kMhmh5dzI9V(UlzZeKld*S9@ov$ z|K{sgFni*OivlOD{WPA~P9JQC3GW!rL+zL`xDDJC7a?XTZk5}jI&w;?)w#sf3g zg{p0b`T})oo^GXC2aK2&5dK2Ty^u>5&KMgAQj9cujW!d%D+e8nN<&WxHMd(GqAW+6 z_M;!M*Y9Gm11ZmF@{PFWKg2?|{YU{J@24qWSntFbl;2CFBzx|(qf{@`^Ms+kY2+8h~amwpnk&2N*J`%o72cV&2lB zxUD?YigZP8XP%n!lE0+|lS$01s>=@BidPV%Qfw``tZ=-ByqG>HTmz)mL4n>{(XLF1 zS&)_Rbc7`4oHBLbL?PT%BG(=qZ$NtSuY&-$w*n`4t&zU)9uRtqaT!Jk^t2N5Xdc2+ z45k~H86=6)gqL&+vW%BPMc8|L?a!Z@?O7_^y5$>POLJo1v0wh!_A-5(#8JEn)-@j3 zdnO(L5`lf>i9dI7AKpS~Ch3Jx2zW;@Aeh5eZenhc&4Q6X?)2qA5jT+j5&vI10}ff6 z@4_|#>zzF|o%9;tpMG6{9f4a19nSMzjE8M=6gCfh;P$Rgod50!6@Vg#fBu9Y9)$Yw z^)Z|lZCNRJf6Et?go7Y)U63`fB6@d3#@6jl`K9-!?ODyrr4nvo5CFP-8deC$l$C$g zI|!QAr1bfS8(iY+Zso!L4Hhy3h|2q>x#b)@A?z_rd<|B* zo<>BpB|QnGjf!Syv|F$wDjI~Ajmq8ispcW(Rrp{^tcMNw$s{Sbd|qAmZ@L&muX=P^ z%N=3w2ihNx&Wm3b!&CJKX=GoZi!c9@k;nIFhhWbk+XN#Yf&kDf2H!!?ImxuMDF&qi z&x5!nM%i^a%YO^b`v=R!N<)ieUsxbz?=iXxx~D9e#8BV4*Q6Z}?4cIkYv1cgf<6E` z9G}blL2yK{2qduB+y10!X~H`S1OJ)`C&dBbuP4{Rx#9fQ{h7&q>~mn-nXjrKJiu)ybU;r6Rz;)V~}Y=P*9(EMZVX>JDgo z(yjq~5*h_ht>^|!i?ctg?ZvCivs`PWExZp5rYTofec*_Q!7xoglg({=EMm#A zTd9ckZ)y+T*>(0+f5k3q3K~mOCOx zm3c@hxOQJ%?yRr@_tQHK8ZBWsW3HZBvbyn-vUluUN#tyPAB4i+(Q{tBJ*u`790jB@ za_rzeX!YFfZbI?EgtpMG0y`u9#}*`Ed!rdF@{ftTEC_n7`OF_dooZg!<@BsUYh{a8 z3Ad!TRU6Oe#;fi~Ckl`*b9frk3aK+y2wYwJBW;P454O)9=vKYR(UZsg&yfEDBbL;jGzv(+A*`4Ot8j}X* zLcGy+snB*-qz5bpuUon#tgIX-mvo=}{ftGkonrgs!95D|dI|t1=HYizvIG38FV=CA}GO=!4)U5w*9_ z+25ArR}w$o1boOGbf}zuuJHK1FhN$0?3t1#)7=2QhtTMbf$NUW#VubXoyk20 z@oq4kC_io+pIZ|Od6tc9t|<+S@O#@FDs8cDyWMk?u^<6d{3Q1Txy`V;3hJ6l`lZQf zPBiUKHpe4gdp!68sEPv!@Z6W-ULv)FrzITPmS0@-LBVYxOd@W=x)6NV3xTP>ub$&d zpw$wG0a9>fzY$Pp#2fwL@4R8?)GY?{7C#ba!eNC*oJWz1E{Y~4;P^0HbM{sT?z?UW zOCa1G10_O3Ft<)0iseQ@2hy2WKXP8p$wsWpzF0j$*AVX?`t9`o!2e%6dc{H+{1ehf zAnTq-^+@)pvR<)nbKjxbs_;xN|EO!%7SW&!E(&Pgs`_En;C2X;NV-fd$ zJkyb*g7&A&O;Gu)f76HfL5EcRiPJM%dW5Gb@#HhWo!7Obqw2cl3l?x`-CL+ zZ3JMd6`DzQdx`4%;|?Yin!YMhP>Yaf%kS^_18j{&NY;jM6k z9F@|&Z8&)h4ge*+BG9wPYPh}{)|iEjey8K>>U+%v)u^93IC&)RCo@ScoKPLu-?Wmf9-J$qOaKlTlo?B?K9vP+ zS_QwpL`ve}S%Ctv&OCJE#s+zJ#sr-J&3bwV;N8ADk1+1N?>ihMQUoa*2h=qGRbOlw zTF)%^DXX7M;LMKm>=eEO)~dDb@6g`%ffC{0^q=Hfa_+&ZJCcRSWAOiU0Ee$BIuVp*XRe@Df z@;VT&*{*12(ML4?>pL=%oIN2RrvQp#F|rm)&+aW}#Bu&6Z0CPGb0Y+AQWR{ZNXw5d zFCh2^`x-4|f)Ds$ccfRns8uRZLLfIeICxvvU7{IANf|TOKXS@=La==Bzq3((iX31f zoSVb3e|r`?Q;N~MeSInKoMmQInu>VaIQX#au{NvUP9fXfOh%qV6wu6h?O6Dtm~4jh z_aOxC_PT`KQ_}x;7a$Jt-AgeoT4?cZ<@Gm;L_M0YK(~?cgov1vbJ5B*tf* zn_El6_jEq1KC@}G+1#Dl%(KyK>+MGY`B7q4rv(tLfw5` zgvDoqRdq@9TBF$?Z+1?@{)at%$`-&*TV#JPbXp914U^#Tv*YDk*;j0ZbAC-E4{c?_ zw0a09sR1WT^~u6>EY?%#-!fRX1bcoeX`%p2XTBE>D~rnX9SG_Zp8OduWI_xW77dme zQ{o5@S_pOD!}Nr=g;!pa!!baG=6C+!5X&YzBl4c|FreE#Qq*T8Rfmow(;6O$2JqJE z+8>5RrI=LCd-q&_g!WQ$F#??pT!!wl_eSEl&zB#gL+0N%jOE1J>|ua`wRbOpbx8G? ziUE5JCwKdaJh$zuV1Of3sqZ(|q27vu%B*ui0#IiHK}!tGJoj-ceiBWm5T^M{;*6OwYA zCJ$bcCUt9>hE-mh!o^cfG`p1e-*pM0e@p(2S6go`Ixhg2QN=&Yw!xI;N+8wtQU zOD5u9A(|q=y9|Xyz*9}4WX*q^0*|ha{TJJ!;0QLwxlY<N*rpF z746tk1GZB01cPtyC%0I8>fT${f~qdh7VhFYyLq~#(G(irjVKxpp{*(rP}AY63$A(> z>G=wD!-_(_Vo)OFrS_UkXs0*Y70F(5qnr86SZ36T!RiEEas7xy!TGKK<*2+20BhvK zfUJq;4gyWKty6 z0*sKaeD4&<9e%eN3;lJfHd@7=Kwfza}?)-SR^)un8VA2S|qJCq0Ij3 znVg)(Kv3?`(^G#M+58hvTP5id`Y|MHu`0Bxr9y@3h3pFuk*!i=<-0#CG=(j9AfsMn zUq%^{7Bg5a)N;%=UnxTE{BA!#7NlBhepQYC&1=TOYcloD%xWxf$KYcwm<$D61KI$% zl*-KS0^5dt2d&elF`;rt(-o-Ydi!Bz=DUFL6r&~riI%^mAXBkhmZpXu1cu7bWAdGT zo7Zy#c<%~8TYT6-yd}zwhJ=_g1?+N?_naU9q9?BVJ;gVL7O8iM-wVCK-}hNPAvMF`2DFNUS{3Oxy8}0()*&c%kH0d zJC?53s2a0%_sj?jA!=-Tb_}@)3NU9W!g>^U@v^DmAx>H}JN0I+0l#GE`P~{M0GL)f z!fkaRJ1WD$6u#7mXMUO^6&D#ZHNPS9loDQWdfKXG?idm2fPeR7J2B0PS#3MI%@?1j zTML@DGFvF1&TzaNtT;Zu@le?_IX_PO8;AWEMizO6d5pYrLzR#+Y}QQL)^~}7b^iHZ zS$UeQ0oi2l{c5~=o_Mbcp$-plb<%qvqzK%wIE68Zsh<%}n%&^ca8A8E;H4;A0SiXoD?buEOVc@gMLYgZqE za|3Or`!AWevDf7^Nz-sot&w#VI)2c+O-H-1%0-G5H`q1SjnJFPT$c&e6JUXD9nN(g zdVa_650(8ND|k`7>_v`p?waZ~!wmseC0(oMNuf@FXH$a(R@Wj9s|Ilftu9;A)<(K4 zd)cjU+&LZ`XVfKLz7XivoO*7a4S90ReU}IW%Z`KZ7-;N>kzHD*l~1It}Tht`Z?+mAm;+6Cfp5peqPszaWAZh4$7&e+K2Z@_l&F*g)nSW&NnS zVr%aOoZTwz^1afxyDWapsXa=y1iYPv=}x^y?3v@3AsP`v{*NbvWr3qzU2?6oCencR zFht0{(aY<+*cqq`^Z?2MF%8`dW%I^7Y6Y@%2m38h$i9e~_@`hRigI5eWFS}gyia!t zR#NY5muaSXuYB9;Q1Qz1*_Ayw>Tqt|De(M?%*JPzx44%>Ehra!dA6qy@D5&e{$t=jy%hZ=X3BQwUIr96Q zi>XL-{tD>`zgS>ZAb#k!ZQTnNh_F@2qsi|8@7j*ktJXyLV&5WG98J@+0~rZFg(bp& z&12e!L+x$!_FTq0sTh66>gt>G=R_I6M3|;l5Ezf%Mfg7$Rqe3GF^odFpgNkcHGb&I z&Dq)kw5zpZDK8FUX|;eF%l!ya*86h#lb|Y1eqKJzVt5y7Up;j0i!)r}BUNbZKn5tH zPH%0@<_E8jGp%xpj?aW~u2Rqk!?92WTacSpkwNxl==r)OK@H2FkwedbYH<&`eIlm- zS}hat%GZJVLNd`-1-&6I+!S)L{ZN_ecb`M>R&ks&r>J710O>mzB9VJBEf%(hI11Rd zy*oxZ_(cjom`{M!Ja3cgm|ra~DvaqJfK~O;Z!)~9b6nXCMV7su|9G(Jk9Ef3OykRL zK@sFHe0*|NvSa!s7%p7xcou>!uk0(E@52T}uB!lc?ha6-mN>q@(=*074~OleX&Cw=5f=TcN)0XK9l5tS1l zI6_t;zsIyySy__P<8bsxT+bM_N91)l!Y6346)i?|IeeU$dje0Tdc{wLK*h1)0H7=0+ZoLZq zKG6j~nBaAe_Cv7iq5AhvV%Tx zcn%cys)sx+ShFvWJUf(VSMhzM#OuE2c%1{>d9hzzOpy+a2Ur3*8E)Hj$CrV2uJqP> zoHK;|Kzv&1r1NZrBvj*S>EKx;ZL(0h04KclG{X0aSsYn&sY!jSU^1`-o_{;E1|ZA+ z#&0wIHqPU4u^PWiq7CpytdhkxeLeVcy)fn^(ed=)`6ltjwGnM_k;EQ{skC!`S!YfY?@9oWQMnWlS%&jAhqFn55@Ec#` zN>!wZ_UH0%93u7m7T(dwgoNo&G)3bMNS_wL){wQd#n$>qd2AtaiLZ*y8Eo{C9NW6k zP6wR3-oeF#KX}zw1LO@tFR!N$x(3?6_yDD*G(NC?F3Hss35rYcSH+*5R2sKBOovh~ zh-p#HIffIy6zA)FTTes6n=VI~drF}JHPYzq4-Rc+id=ASsBldJNg)}K2>NtC!E1Id z=D~>tvQIi&k0axzcTQ7rDneZh_9KddR0hjerbadAudRnrzj;}8E<0m<5!L3C)9dQo zM%~Eoya(xOHvD)Uzp3G)^YOoFeq27d)fJeyX*o&M5N8L(oFK99$YQ&%&Zqs+xLddDmA za{2v?7Q>hH=s##_t}ca-)GCjgr8Gjly>xmQAuZSPJWDvTJA1W`*^qb1=eQ4!yixQc zhlX@b^eRiU$}({3qrb9e!+hz`wJ z1hNY+Q2wJ7v1z%S-IX_Oql!?_Lz>IdQD)y)Iu!9+RW)F_W8f&Pd?>{lK@NXx*`&3} z3U`_}88NI8^uYrQr8=JO8X;IFfom-)Wp#|h_cMoocWfM+}G(sgKB%V?O z_Y8=1Q`7DJc3vW#7G1lkKf=Zep6vWv;O_1gJXW+e2&o z0$08A@?qp=`>p=yjKp_Ie%Pra*NrwSW>{DFV9`|Mi+Vz8FDiQwyR;yEc;oYcwM@=;Z$+Vxn}$A}^VPq21>>Kr*iA~d_9*JBk% zQcI)pGKkj))&^>(LdQ?rVVN(@(2uGmx`se4?|+ELjF9?Dpxg=)av^e{=Fj;&g!WV- zdG{CBVZ1y}8q{Zf+qKPBhD&ewvzb-Qj0^JvxL0l=LFp!P&m5Ukv$q5Uz(VDAR8|xh z3V7^s${jqP@_i-H=|&w#wD7m-X5FEh1td_poJR|G!1Y~v&# zywGvz02j;BWEIP2R?Av{gm?C; zd6F${R&R{wQ{1_YqVR@;Vw7f#>F?>e5t#%TsJ-=MP951(oi{l-nLpms2u*RI5YZ`Q z2)O6hG6=r$8g63ag~}*E{8|tCV76mlvlu32MSPJj3A9HRKN|Fc1Q;9(qgi1|@`!=} zSN9^iuC&gH7VENH@8b?5A;`9^4Y@?*t*ZdIT2HgrN2WbjNiy;0kG3O~n1OqWZo*sE zzuM%ZwJ2aQa<3I~2P%V_#2-x+FI`U_D14is{`MsYh}W z*OvA7&Yv!I7KX}Hd6jg?vtA`Fm{{m~w#CI(kdRnYK5RoQ3;KAAO@V;KD2`&6J+rRl zs2{2TkFQD}!rl+ro&TVEzg=y@G_M7!0lDp0XAWiqGc_{2{=~Y{d4RRg?&B*08GX-c zxtPy9h(+JNT{(6B+L^iJ_z7B9q$*g85s$FSlrCHTM=Eq}S%tNKg3r4^4P>`a2@Gk~Er+o^oH3w(=6+-^EnX zUHhhZg?`#YwC!+`a4VshG<^4`#Ucui0yMdp{C4yQS)FB2Ebgn{vbtFXYTqHwE?b@e z^7|}f_eo>JUIe$%z46?`^|pa7*8%$5;Yu*I_4L7Egs87`Gz)XqJAYpKykjb7gIcC` z4shAr*@~2B-Q4HPTc zCm20*eSS-E2@$IvDvh>s{JZEPawGqMfcpF4&YS9o7@XBElFC)xqx`FQP#(dmqF-IP zz3sSk%WWBzf%AIy#3NkohLXw*d%R(ug^~oE0Hq6BgX~oevmvK0SevgfH}^pqPg2hj zVZFNXtW(YRWN2i3$bG8?wFquSH&&|D{oQM$$&@H}TzZw$$8b$%nRlzCHxw|h!+Lh` zfL@9>a5S~nUFti4vDw>0^3Eq`^yzqvRm!uSEpZtRkwlb99(Bx0>|J+1k4_9?h@&4} ztp3EaF@t>cmAK6pseSTqnCoNVt11tAiTiBE#JcP6>mo!M z1;xn+iAIUJe}1nOl6dlothgJo=jW?ugjB*Tgv21HHg$U6?bc-IJ*U~@{5Erbqia~e z>?MNrf=&(2z%9}8L-Xw=qkFvx(3$nBOPm3wp{5!(vVu5JSNFLtqnX!t^-SMfR40{9 z?!yhD!57t}9+tMXO}Y2;jeF!pMSD=F$3;a&@zOtQc#`W6Dh)>BVlKp;lh5&tmNjH_ zyW5XBqMlshW2%JIUxZn(GuTMa4*$#?(iG5IuB$#lY1^})lmqp_Nybm4t1zRca0Auf z6}C0d8YvbC3|nDfmT+%@Hydi_Y~L%HjoG#h%N@qvk1gN}bw7#mOZ~Ks3w`59StkDl z6ZbMJScm%TCstBI0vqkAxMCs+xIL-fmYv@AvNiWP$$=%A6(Px=HsDUX806L!>fXvs zUS&m5-cjnBCK>yM)=;A5T|d-ScFb_?v;NY4M!p#}8vVtJzcsOfK~5Gqd$ zZ2KuOXIbU_#j8z{cFHTUxE=E9=-=Gs^jmQ?$LcFX1Spj!ycK!T&W4v#^c(O^%%Mk6 z-W0XIThFVvC6OcogV;BoBo=ImEmx7R$e@Mf8ZVK*Ijx_6i)&i`i|F-jhC?qY~`YXq8LBj*g)8FBJu67MRMfxb1AxgjIUpK z)U>zSM6YqYv`SKCNlLKu%6>oeCpG>IVt?SKPHu0Op(+fo<^&CMi3ngl;UDjnJ@%gu zuP_dwqd9-tLSI(iBSDaik7*$3XJ9%))5 z`>)A>pMaz1H!bjXpYd1X=r{bVB-y&9?oZvlzAK62NpF;V=7iH3(W~+L+NONgn)jMI z$9?mLHalDnLcc0VZyo9iyxCwvHz0V{*De`$PDI?;ow0yk{-pT*ag1Dy97~xU=FNk) zd5|panVf{;q3yo(_#4l4<3F5Rj)Um-1K>5!nCM&{)cW=okUVp!G^*skDxg*=FMZui zGEb@E{PQ(=@CvPpbLs0Jt}mbs4eMjn%y)`^Z+)OYbMirlm zGov=OKbJLLvBLdFhcZ(5BshNdz4$XKY7^J()WaTn;N88~&iWtPoL@RVkd!*0C)e!E zLozj{MSp5Q%i7tzRLG4DdK|2|_N9)bhUdc9`sK}sj3^Zqh6ft2DcHvvOEpG3BV?T{ z{lA9m?>00x48C7g{YqR`81v@I;8fTwMpWp4PB#Y8*xDilr=I9tqF2w+}GF_x~w}N^;YzIOqf%W@LXwnX=DI7%-U; zQJ=@-w(o~*i;uQy5zjuh%E(h;Q=3T1h;wlZ`j9*@K7jq*M2^Dq;ccQz)g^)R?3#&{ zD$%un2YTUpf@8@&$colSS~9wgzC`0M;r{7~=zkik$6?z$(n1FNgN@uVGkd=ipGU<=s^pz65kL%I;Ne#Uyf8Mf>FzK z5|X@;^SRo?i=ZPq51$sY;HMJ^X^UQ%Kg)bc(P-ewk2-}`e!d8Do{aKab)!PIZv`P* zKg6i{mo~-{3?-B2Hhj_op71H;X<_M7PcoK$G9)G*uHq8ltzvUG`9SzFkanKS;j?!$h&(WZ{ z6fjLnFKHOhQc-IS&aB=}kduf~UL((FKxOYK;n(~)#adnb6zT=M@L9w#{LfF(p;rTv zWK$Vr-M*@pn>JuDS3@s-%w*Un3t+e$OR1}n=yM1?Jgc2$)_ zbS2kYNJk(p#*bU>_)JP})juXpexZ84g?!r>_uaZbbwV890Z=9#7z{0m6pyKPcI)Pu zopMzN*1Z(m;Kb>%lF%kqbwd-eB!p;R^j=i5~38RrQ*X&Qn{*4O+7y6@$-4TCATqB^X$E)Rmn#1c82^G=|jPTZ+jdU17vdy>*_+W1Uh9a+i9X~+M& z3jn63_t@V!H?lLQde%g8!408^7T@VD*7Drbu_tt?e#~%CRx)V8Gf7CX(iYr#&+&R$ zdL_6vKzwvl587o#b;fD-Jd~`B6FY@>ejOS9s;&6s4R>xSSI%Lz$^8ONSAl0chpZw< z%zd#p7li6D;$&GP)F7|A{3_hem(bY`5S*i?+^tkfS@Hy*j(=x$?@eUKSk^D4;Bcla(&Zeei~E z`BPen)`8UfC0Zy;Khm7R5(nIvdN(Tr@!jSL)ouFUds86Qu#(LXMDSa&OA^FUE0(%{wYz^BSWQ@m>zsEWlpyK|>4IZ*&KVaq+xV#7y3(3#yrG0DvkXI|#7Q`<+( z`KP>4Jg*2`)WKjajoko2RE*E(phfAV`N47fSl7&I`@lrr28}(1gR;|YLO;qQ*?2Dz z5{T;MXr8*RfVuCq&}nOJI#3GoTsCWGj8n_)Yi6XUIx5EN_lxK#iT=?v=baLZB1rf9 zAh~+5|LEmJw5&cBZh2`vp*?U!gP?ebu{tiOPw@ziWAhElJHh&ND!=CWRa(#@2uam( z-@58N^U*)4kktCafWgI0?A$(%bFIrzh9}PV*j_XdT?9bZI|h=Vm`t5}AIV=NMiZWY ztB`oP`r=1^$uW%p0*;y0@wh=$LTjP#)=nn2?<+S46fbcK{L(6OXJ5;5za=PpK&w0k zTRJG%BKoEZEwfDN6Wv4S%@`hlKL;B`r`zNIzwW;CAFl3uTkn08L>bWuF&Q-&+*%Nw zB!=jM=zTDHixxf68AOTb(ff!Nb#$YI5z%`W^*7(=&v@RP&v|k7*=_B;&sl3-*EPVC z@9o9Di8Fk+kuLVXS|v%ZrJ%q^OsZD98-O4Muse*@CM|ldlbM#D$>Z*ut+VWA`j#b= zn_vGw+FRNKbzp1Lh)P=!5}~cjNreoPI7Es30;D$kt~dCQSbay95O-Bew986I|XnhCX=$H_lR_IssXysk@`{E3wMR zHqu4aVB)vuDCub42g<1ghP!3YF|KA(MLGKsfw03C7u$TZ^ME0g__m3@d;uQF-A?LA zx63a?X{Ey}JRj7<%EY8Y1T^=5@}q2v^kLda(MT6Lbv+sYo{uACy!aecF7GoLzj>UR zP;}bzd96Hmf3s-Mb=y10Be%uQI1LwrAMvKB*(ckuIyYNW;`JJsLtTo=jZnAmMm}U#!DDw~A(A!f&w9r0L@BIJ@pm#&=H=V`9+mK`4Gl)39m zmiK9MMrrhF_o;hZ)*+zd=u;4Rm(|@Sng1x7Pxk$Ef;^)TQ{=6FXt0$>&}G9|W1aqm zE2T_%YQ6Pme>!R&p`QMIq@e>fJ#BKkgpuN#)1XQGwIUahd&$YFY`4nSdMIX}fE;^R z%x~_TbYJ4ykbGluV^vha6ycqIj{I65vZs87JH~IX!|ui?TGA|cmKrX_wPp(RpG48$ z7&)li>Gl4h5J7*8fj=`-&>@S)54Ote4oGcWoq_5WrUw%PM_!n#B`J2I0MlZNS2slu zwF{o&&LVTuF?SS{5j8E}L#K^~?Kgq|>qgvvmLQWoDsSUCBMcPtF>7qFY9ENOhi%IrSOeUVb?i zaCBAWm*MZV-)-f@^b$CO>h?wkYe7~WSY)36L;ro*>8WmoxM;YR+paV57cO_6^`08@ z>un{WyHZZz`H<>orA}$-^*tXEBN}2QC%)V54rY~46W9>n|DoJE(d||+r$PC#{7#me zwVL4^=yVg(biel~&F9uf`v!|!IrqOcI4G5>p3#QTJ3Wt2^taHAWodi z)1jMVX<_?Voo!?$gxg*zK9D8?_W)oTzbnf>(%qnWK z|2!c`?(Z7#z5t${rFsgB>WU5WE*p-8D;sNc$?Mm&k?Y;#+eaOEno6zKH? z436|Df1~Ctk%}j^xP_kI2!RpPCCaoq%;b8?$_l7H_khV3=Iov0Vrb36;Z)Enp`V+i zlMGJVN6UR+vwL0FesR*)ojHCxS5&E<8+=*@D*zRfM=C-? z*E#y9G%OD$e1QikK$_HR^_}uYt#jGu+oCz|)9qxA)06Ksyn<%Q*#W{X-MMtvM3|kI z3B{({V$^p6FR+JD+;PL{r?QJ)YYr?GlDVhc+$sN)4Ry&$b;(h5vxw~ZXBMx8+8vL+ z@|wGC8~yHxTk3bKWBd0ojf~sXPAXrvw{({YS!>p4SWUY}b>*+xt5g%i5S<9K{QM+B zf22KL?!`Yr>4cYLRlV)P+LzfwN;(Bo1a}O;uX6o!V{3V;m1=#i+zl6NhX%441PW)q z2gRKZ!5=HY>oM?26!1X`2M&*}NvRuv-;+?5Ff;h!T*)!sUX>Qf&#n*${5bA$AgRW+ zoen_olynihjBO2fXzy|8Xii;g(d}_tqF4}{a1|%Tq+e}P-LCKetcfmrrR1aVu{jw5 z6l*;H8QlAcMwVYdvjRtWJso6W@soIeCV|{m)|$EZn*ZhjeVrRu6d0ul27o|z(2Fa# zV{Xi02DE}Zz8YUr+yzQ$O?y;`a|3#_^7+~81nWr7mE50s*PXP}6Tt>^hl|l%w zE2h{g`>G5ZQd^UN@_{w;x(MmDFKFI%=1iEMyy4Ix=ke9m90Rh{ zow()m7=L5suK(Y?u7rs(gTwSB)6&k1!+(yLWxA?)8kFps=uXh1Ba^AAmttT1t{SbZ z*v|>$SvA@w)x+)wfM0uR0;vIwWpC75?YY@dC(J33HREgoy^C1iyk@%v+?c{VSk(o( z$XxaQxTogZPDts&dcMcE_iSTGi9zu_r zxcCXELrz*{+%C04WBZ8?2h8Be7aJxZ?$Tnss37?x5(zOtm(L}}%V2k@pt1awH>3Y- zGG4$nDjUhnyE$DJe`=7bbH@HzU(;A4QQ>#;}hXi>#|L@zl zdD_szoVNw+zMWGr`nbm*1SXZ`w2-n^GLc~w0(WkB_lNY4(*G+Zxi)~jIBj!{g&YS8f#{qUa|S|gVtxzU+4OssNxt{+8od| zmFtfmu+?y>juV|aJ2FKue~$AR##Oa?oME_S%wo?eSQ~u>qIoM@#gIt|S+s8>Z!UCK zvgbbuk^#8dTL^hJMNg211+k9p_$P)qC2K!HXQKdvSN>Lin6HL3dy|ikl5aex^E5b4 zOR_v%aF2p8ftsfD0blx{Vz-jDd_T3X>~P|!au4e7T)2oim7k39`{;i5=Ug62uN+YU zeqBcZ&iFVth9EjxB0>m_$Bt-;I454-F@0HS0yX4Tt(N^6LF16Mz@e! z$05p{5gt`TeQ5mIrkW@9TA8!!9-K#bPW}B1z7w`WIC-zjj?5EK6O_ns+t|M+~js4pLxl58txDON=n`|VS8qcliTB~o?E;F#lTn1_|Q`m%SlWZs0! z6XHi_T zfO;(&W7?!&hJH|3s7O5xwfNrdH_90?l~@d3PIr~Yp}_NJmMOd_{7o1Lbkoe!qjr1Q z|ButC1R@c$>^FJbJZ@*=`ST3^C5y#OdGBQktQ{`wx&Tofk)7J*5bEP>K#1Sp@m3@a znL=T8&T9h~mJbtw&?ln-PSm>-8A*i7!!RKoe7U`vMT#Xgbp}uhkcf4FD%Qt18~YXU zGOk3q1q(so*|Gq*(w#9cn2w_&ddV^YFPJk-t3Rj?(qdAtNpi=uvqeykQ3|1BC;h1j zo4MtAKGA*$e$`q;aRcT|jMxCVALkJW8Ut0M8D$PqNXVC*a;$E7`=CYFT;&reyBSb5XC{;I>HMUk?7kk^0UrQ%B@An8 zKCY8`JtpDGxSn2+>tFgqX?9R_+0dan{mD*?wfc){0rv@eugH7^-GU>j)fe8SR4h?k zFygar{{*jNMZB>wP35qG=-3R|0ug2m4%(pkrOufp`Ngb^yGy6lcIz5`f)mH?Sx8Je z!T-N*pF9#5NpBYHj#Rx(P3SXIpV+a9_TozM;y)gs*XMduD_Ot<~`@Bt540omeuA@hpgy^!g@*s~zaTZ*!5pF;U7U$U^F-IvFm1k1M$9AD;paW7lN+S@6}r)A|z*jE&W$`{>-s<0fnmCgn7@$g&?(%!xb z*n#kl$Ar2bcm8QKnxi%`M~HRS%MDRg01CCS&GwY4*a+mBts)~P;+g0Ey>*h19_gaY zHvI2Ozx(Y|2A3S)CxgFyg!TinbW8lM?3ewP`u%f{FR`icyAN7oAuvWSL)j&+*fW!j zh3qxkbT7|LFC{MPK+#=h6}&I6{tK0_?D4`tO82!w12@U6x9minoguK%*I=J|pS7bU zQ&9r@fe8LgZ11sXPh!9)F@qv^GUv(B>W%)_F&+A{7xnj6o3T#&0`IwuKklsD7DiY% ztQaQ#_S&-0w^LYQiv3U>ROuI;dlsBDBP>T%J(qXZkwJHHt>q)>LcgyrL*81R*GuQ> zDqs*?1~b|eb();r6e)dV&)GuH{dY=t?WeonNLI9hO6vtX@`MmHQ+34;WOLaulgGf5W z%MnS3Y|Cfe?(buq)1vaG4f`A7cnbs^`(Jez&Z~{@el;Zw6i%o`y?X9JTwaWR->CB< zeFLl`oz8RcnA7Yoi=IJ#+ob;mUycUXrcdgknI_wpA#MePlT~orV)yrdGi$|gWwD_B z`lzKVaeW}p(jxjt|Kq18snoW?Ad!h{zrgzP{8H)V2F<5^1}Fe5D=D5GMK?N~{pQxB z+prLuCMHTu&9fplmEa$2nDxa+jIL-n`wexu%upzK-UeAIx>WypNPE1nrtVyK zjbb*;frMTJjPabfz^=5K#IQ!9(MEP{k~k3|5+L?By@-SWH$IMcR-Dg z+22c^l05Xv-*OW1?OC!wl072v>V{Ph^^W(|@6%_R9*#r4XsO}VaZXG#`jmZ_>RxhZQg8hM&FDK^O4 z;tP|pW0TdYe{w+yJO9KcmF4Z7utO!E=jDk#*BeJq#!~xftw32Cx2I-hZtq{d>DaO3 zisgKp`s70WK|XJHmQ`b4^uq1AT+*In5!RD;MB^?j^09t5P7`>PegAMVCS#oPeQXUe zK*LRqp;1Op*wE9OJm;*6uHrB0ql~SxpAl#4fj{4CZEfAvV`S*7$beDC#l<{P(=Ej1 z)?iK&qw=$T^oSQZ^1S*o(fqP~XUBhc`JL%`Yx(t!RH?RMv-j@Y;hVXppv(J%!(}Lf zVYIj`tkX!dpb)fq-nwsr)c<6PZk8@5}3G3 z`HK9dFIpabxb|vi^*!`Qq~|esKZ3}E{+0pZu-}(qyZi?AK=Gm~R|8J-G~!SmcNIgW z;OeC3Sqo8etb~Ps>HG1jVHW1LvM+=x-`QrUU54i8(}NR_tJs3^%@Ku#ivtKhXw8Rj z?1A>BqN%mzTPmP>GcS4iT$a{ElS{bTNZ_T@ue>FgZoO$^$!CPF3x2SnwY+3MQ?5|f z)2;QarEZV~NB2o|pc=n*pL8~aSAt)-_}~MJ#x3O;lG)SaA<+*PeCP~vXFZ+WrEA9v z)nRtnHpYW}P6z zDo)gIffGXDV8~om)XY^1Evh~0fbO)cOu*5D{ig zy*Rfbvq9^*Ii6eS3^x0FP`e*!rP0;wf9ep`em1g+bnSgp)kHm+I`rQ8sj<%;k^U|} zKZ5n2@O86D=a$O3(L?~&n)IY@t!2+XtRAF|vg50AK0cDHmZ2LP$@mkDw%vcW!~~D- zi}st%bL#kK4R;fd)h_KZNtDcC*u>rh!fGC%q^S0zrEv}KEAoF$fMDW48x!vVGtfrH z*4oZhVOJ$8c4O+bLZX9*IfKEkb*-}tCHKNdhCe9gc--2BD3ro{^!}Pg;cdni?#xUt z|JQoCGdre~i)(3~Dua4sc)t|7Hou~}6^Zk|PE<1)qg+ayIgUs21}v7LJC zR+g%5#my=WD6?-4Fm+^XpgI5biAq^yB-UX?XGo}|OthlMpQIU$>cKup-d32*-E z=Swe3Aa&(mC_kU(0#2wDsl^gAm=fHX;(Pfp#aTri+T?xwz<=}p<-Kvv4q=&v z{%uFaPd1E!EPWKDqx(%?DclvZgtjhw>0kNYWOKZn_U9I>4j*s?StC4s7J4cUSq)Ra z_O^d{A1Q4#a%$G9w3VxMh+(+e3*2S6%sBijU5)Xf5&iV6b!@3MYjI8OgNyuQu^!`S zUh-=;aAew-O4&^T3g17S7BA+)h1|4*lYcRVk1O%D?fW)=CQAT}mQJm%l7JCeSwEt} zQ9V??yA#%^y4|ytxdQ%M3z77~bmNtvl|!y3EWFFtg^00_NxoQEW5yKqjgq zw%o4<6VX*U(T|@$vLv>>O{EgJ1Be;#{e%s^b5}-41;eqktD$S*$Rix~L z%+WME0AgG(dLNnUfg$;&-r$i>p}Q|FTdLAsM= zxRYqn2g-RcLgi94wkXeS+Q{?y;;uRcX-huX29W_#qC>%MKyB+^a<-IL?hS(1Mp z3=4A9Ea0C>jkQS?ScV<*q4d#s2eP{n+$%baC=APnP3};ePJhmi7pQip4e^ylP3ns1NFupdL1ca zhtmap`PF~%#pOjE3^AtvZpz)2OYmDANgIxXcP1E}jHlM|!G}JYrOYe=RTZPI98!!o z`LeNd^b9*kxQ?OEzPEdf39{2%WR#qncpZ)$aD@GVH?}ldv&+Fr8uEzU{Qq|HUS@nd zhw3bAXPZ(7@`Dot1^9ocp4EOXT6N&FvSjBB!@ka8Z#l#8^*4MWBF5K&-Y6x?k4No~ z&;EqZfff#p(vx%~F70OH+Ryf#dt}WZoD2$d>-yiM6b*(^Nz4Zp^Y=*W(v`)F(T0PHQYYPMelVO8Wr~Z1K|rZR+!W931*L|I-NY=H`J8Rg@OJgw66C zw$sZ;gRY++jV@5w3(%cO3(%RN?ia%TL?G#`+J5b_KiSzL=E1?&NlZ?YA6oOxSqwhVGAcBASC$Y&-xjFKQ&|z3MpFcP z?0Jf}9Bu;~*@cr6;+=fXzg`}h$`mY?iGZp7t_zb04zVzlbLfOiVJR8A0pkE;`wwlw zq4DkMIugDAMxZF{*<HT?M5K)b4`0c8>6nG$=HhUl}Bw4*|g~TM{$zEUEpL zYdOuma>p-+<}xc~>U2V}E@Aj4Hsxo=Mq|-FJYSWE&6uR(`#cRte`a>5IPE%Y*9)B$ zZM!K_XvW<0B!R#i4#@k;So%{eYG*Tc0_YP6#>vNNl^OIa}2(+=+F|8gxCf$kT4} zpZ@J+F0yIohYj6_@ce2H{c=#n|7*%H=kPw@1SzZd_=|U?n%g$h#%CVGmeA zCBVoSW$hUIrBJ#-3axhpvJUW$Vs0J@nnLj<&4(f(xeXkh5MR_Z*UmEURY;WFlQD4I zVZe&GWYw#YT`NL2lLdhXLdff=XQ|5A@H3fExlPhHu!~~-Cp7=s0B+)zb8l=`se0S^ zyXs*jYEv%P>|xl-CF4W@8{k~c<>j&;Prb@`Y3P(S+5LB0rHDtWh5ax*ozcT++H<_a zncYgerobD0*)tMLAEK@nC!d(+_EUaFtI>VZfaqwXEp5rOFe*1=&4PE2EnR##ULph0 zP|Tyeg9R*al^OThyeI3x^+mDo4p{3jb2t5QYE{XF*epIfpM7k7TnJ+N{aEh=uY!E; zFA{aXZL5?kN_T4XXy~0%q`tCjlN@%jByGtg%*gVZo_Vs)1_9NHeSNtQSy~{DCc8^iZtSni*g5Sx8Iu)R2m{#|Wgq`#{!I3^KJ^?~M!Fsq zD{y?Ks!H1CYQB@w#8(4)y4mh_@|+Rpa_!6jg(GKPE5+H9qsO8P&<|0D>UKwk->U~B3>Pn$`7xn?Qk#bSD90!VGbNNx2wS0d9FLz=*^9Z|K&t~c)! zqKig>($LsdKDyO_Y9iPkBV%FAQVd}a&)+GklP3~I&hMVyJNNox3PdCWE){}DC?!JnUPvhWG3^m;B5y4M*HtaU`!s$~U8!Og-=MjNz@*q6MDVC2BWw;Aq-xgsfl<{O z_?COX3Q#M{cP=ehOX1}h+Jz&bRr%j1N|q3W<>+p@=<6rzY)Fj>?ldkteS$#nk)}np zZnrnOXD7e)8C@Y~6^{U7gBe4jnVxQGzmytgErTus+2JP=0>60tcqGM!nS=6OqH6Wz zl#W<1x)!T7u$a}%2)Q$$4xh;2Ly)p<-0`)Af2EEquE_}+XHGbLuaptA>9UCR2`mJXK zKZ+Ui20CrW{XiA))6+><;?v!F54s*-0(N&8GWxMhjbc<1XO9_Z7e2n236wxT}DndBvLxCuydMOUMd8 zuid>AZ4<)pjG`ox2Q)WjIUM3I$9i{ESCzcd6HnbJ2&a_nB0W_LYfrhSQsw9mRe=J0 z6k$D0bnxaG?}B@Rb;V zjECZ7oYp@0jSjjnS>d|!&H6vq<4e77n`b7sO=J#kv|a;adga(A|tvILI^P& zOhYC^`^R6Eyh7Ch(q@k{p#u*vZN zUC(Hz<3+#~y8}FhbahokC{^_*;8F+^DV~X+c6|QGi9f&@m8@0smsZw27;^D)!b`#; z^|wjXovWQ5(%&R;o%@P|?qv3ff@A{WGRwOwBdBi5^=+?{8z?Q*+2~fFJmjtho6hJb zB0+g$S?BglqPxHGFx6;7bU9Vvciia5CK7`QmYR*T2#%;X9s&|@1)v{!az4vDE8MRW zf#I%52rtLZd*(Kju!hV&qV_6j{;vf_z6Nt{WCyGvmf+;MY2ivM>a6-J!4k3#o&91n z67A#K!Zy4mX*FvNC=bLPzTq;CB?$b8U;BArV*XSP@7CLSg9O*S=cJbRNCq?iY3yc! zJuXEq4E&0&Nu2kp93TJBGc zvAA3WHLhwO<1&T+dZ2^zMzs0{9tNLVMY6h=;5-d3^va4FBMY_4Qjc+DA)du8wJwk= zwXRc$BUK1nM)5-b6mJgX)ljCXSDm;+tO{F5Ss-~CVmI;V@PHgNm9K%%ylZb`eI|LW z5h8H_j@wJXslfi;utGjC9SwjXi8jZo2cLkAmJ;J7yPoaWBXFv}b>}>tXCIF9Bw*wL z4T;9{^h*=6$e680I24wtjsJ$QTrtd6GWLySl-_T(3ef?&;X;M`ll4>g5h~e|eWKan z4PhNrFIeO8;@3I$TD)HQOwgAUV&!TOJ{H~F6A&_TtA$ENPvymJ9QGa$SKb;bf835{ zc${ryWetT_l$FxT1+Ywft⪆i&z%)_+e+ zNHd8M~y&>phXPDDw9{XnKx%4*|lMj{<;un`eIJ+yIh)kzyjT)wMo;r&*8a=h~ zDKxbs$8Yd?Z@Sf~*6ccOw5>Z?T1t&_(5#OI7dKXDjG7cKto~^#G|Ne~58uiLa5s@-wdIw62<^jXB zNx%YXEtNtD07AiaVV6F)Nl$OARf%T-Z~mcUwXo@uB-Xz6DuKNd{K2eWgDAFNjd z5@LniOjdab1@$5NP=15^9 zA}*R_7MIU!4xtpoRJ>SIGEbGZ>oGN?38))vfX+4{a2|q`qKlrLjs$jxv)4 z;diRWSUStX2$xCQaqhyietI}LbQ%bVH$sLDYt1rx|GFzitE4r;91&_*=pXwc&I+y>Sd+&98hy%A+e82cR^SAMX!*SD zK7(r1>>;~=oliM>i#Qdk(*-c2NW0pc38gn)SUo!@xB!^>pj-L2^!03aATL%GY0Tj} zKvDB4-PydQ4(1)Q;LYnsdEPzZf?$l3yST)sRTC#z0vQw^%M8gpbk7^{4QIQ14@}rj z_<{)C7)!>4Q~fjR?|`4kR>==WjR_c@n`y%vbBcCgbHRc`Bu(lkg20PR>HrpBvo{Pb zgzYpe1YPEDzG(BaVO|N{t$@k`ICs5~1ED&WrysC#aahh;)gJmInA1sv^Y;p0kS5w3 z&&k}T@7bn=X0HyhOZ6t*rsY>!LD)qk&CjI##5CDj0kFAB-$UGJjle1uF4fD&TPI#2 zyWlUf?9IiU8o#O95t+S8iX?j2ETd!0e;D+E-MXeF{vYb@N%Wl&8~uP@A9A^X#?MyY2szjs^EPvesKC7s(K3Wd)g%pZ zPRIE^x)PQE4HsU6_#$XN5(M6&=`?73xNFv&Ox%1lmk<;XpfAPfFi#h5GlS#HF5vFB zJRaP`!3@BP5{4}kG$Q+jf@!Aal7Fz(u<#zV;mTOL0vBP4&Qo_w zjM+o31{H(deNUZ;QpAzr(9+YVLh{!h7LVOrZ37>>1yin+achKBTgO-)0BfIN)CMG}}cqbUIAeBS9DwfSwbwK?Fg@1@)TX@l&!6(X|tkT_4Gu@SPZ&J5I0^-H{g*kyqhtdg self.highscore: + self.highscore = self.score + self.save_highscore() + + def lose_life(self): + self.lives = max(0, self.lives - 1) + + def reset(self, reset_score=True, reset_lives=True): + if reset_score: + self.score = 0 + if reset_lives: + self.lives = 3 + + def draw_pacman_icon(self, screen, center): + start_angle = math.radians(30) + end_angle = math.radians(330) + rect = pygame.Rect(0, 0, self.life_radius * 2, self.life_radius * 2) + rect.center = center + # Mouth: draw arc first, then overlay circle to mask + pygame.draw.arc(screen, (255, 255, 0), rect, start_angle, end_angle, self.life_radius) + pygame.draw.circle(screen, (255, 255, 0), center, self.life_radius) + + def draw(self, screen): + # Score (top-left) + score_text = self.font.render(f"Score: {self.score}", True, self.color) + screen.blit(score_text, (self.padding, self.padding)) + + # Highscore (top-center) + highscore_text = self.font.render(f"High Score: {self.highscore}", True, self.color) + highscore_rect = highscore_text.get_rect(midtop=(self.screen_width // 2, self.padding)) + screen.blit(highscore_text, highscore_rect) + + # Lives (bottom-left) + for i in range(self.lives): + x = self.padding + i * self.life_spacing + y = self.screen_height - self.padding - self.life_radius + self.p_man.append(ActorPacman(screen, (x + self.life_radius, y))) + self.p_man[i].draw() + #self.draw_pacman_icon(screen, (x + self.life_radius, y)) + + # Level indicator (bottom-right) + if self.cherry_image: + cherry_x = self.screen_width - self.padding - self.cherry_image.get_width() + cherry_y = self.screen_height - self.padding - self.cherry_image.get_height() + screen.blit(self.cherry_image, (cherry_x, cherry_y)) diff --git a/labyrinth.py b/labyrinth.py deleted file mode 100644 index 0251e4c..0000000 --- a/labyrinth.py +++ /dev/null @@ -1,92 +0,0 @@ -from actors.enums import Colors -import pygame -import math - -class PivotWall: - def __init__(self, screen, center, length=40, thickness=8, angle=0): - self.screen = screen - self.center = center - self.length = length - self.thickness = thickness - self.angle = angle - - def draw(self): - x, y = self.center - angle_rad = math.radians(self.angle) - dx = math.cos(angle_rad) * self.length / 2 - dy = math.sin(angle_rad) * self.length / 2 - - points = [ - (x - dx - dy * self.thickness / self.length, y - dy + dx * self.thickness / self.length), - (x - dx + dy * self.thickness / self.length, y - dy - dx * self.thickness / self.length), - (x + dx + dy * self.thickness / self.length, y + dy - dx * self.thickness / self.length), - (x + dx - dy * self.thickness / self.length, y + dy + dx * self.thickness / self.length), - ] - - pygame.draw.polygon(self.screen, Colors.Cyan.value, points) - - def rotate(self, delta_angle): - self.angle = (self.angle + delta_angle) % 360 - -class GhostHome: - def __init__(self, screen, center, width=100, height=60, wall_thickness=8): - self.screen = screen - self.center = center - self.width = width - self.height = height - self.wall_thickness = wall_thickness - cx, cy = self.center - self.rect = pygame.Rect(cx - width // 2, cy - height // 2, width, height) - - def draw(self): - r = self.rect - t = self.wall_thickness - - pygame.draw.rect(self.screen, Colors.Magenta.value, (r.left, r.top + t, t, r.height -t)) - pygame.draw.rect(self.screen, Colors.Magenta.value, (r.right - t, r.top + t, t, r.height -t)) - pygame.draw.rect(self.screen, Colors.Magenta.value, (r.left, r.bottom - t, r.width, t)) - - gap = 40 - gap_x1 = r.centerx - gap // 2 - gap_x2 = r.centerx + gap // 2 - pygame.draw.rect(self.screen, Colors.Magenta.value, (r.left, r.top, gap_x1 - r.left, t)) - pygame.draw.rect(self.screen, Colors.Magenta.value, (gap_x2, r.top, r.right - gap_x2, t)) - -class Labyrinth: - def __init__(self, screen, width, height, wall_thickness=20): - self.screen = screen - self.width = width - self.height = height - self.wall_thickness = wall_thickness - offset = 50 - self.pivot_walls = [ - PivotWall(self.screen, (offset, offset)), - PivotWall(self.screen, (width - offset, offset)), - PivotWall(self.screen, (offset - height, offset)), - PivotWall(self.screen, (width - offset, height - offset)) - ] - self.ghost_home = GhostHome(self.screen, center=(width // 2, height // 2)) - - def draw(self): - w = self.wall_thickness - mid_x = self.width // 2 - mid_y = self.height // 2 - - pygame.draw.rect(self.screen, Colors.Blue.value, (0, 0, mid_x - 50, w)) - pygame.draw.rect(self.screen, Colors.Blue.value, (mid_x + 50, 0, self.width - (mid_x + 50), w)) - pygame.draw.rect(self.screen, Colors.Blue.value, (0, self.height - w, mid_x - 50, w)) - pygame.draw.rect(self.screen, Colors.Blue.value, (mid_x + 50, self.height - w, self.width - (mid_x + 50), w)) - - pygame.draw.rect(self.screen, Colors.Blue.value, (0, 0, w, mid_y -50)) - pygame.draw.rect(self.screen, Colors.Blue.value, (0, mid_y + 50, w, self.height - (mid_y + 50))) - pygame.draw.rect(self.screen, Colors.Blue.value, (self.width - w, 0, w, mid_y - 50)) - pygame.draw.rect(self.screen, Colors.Blue.value, (self.width - w, mid_y + 50, w, self.height - (mid_y + 50))) - - for pivot in self.pivot_walls: - pivot.draw() - - self.ghost_home.draw() - - def rotate_all_pivots(self, angle): - for pivot in self.pivot_walls: - pivot.rotate(angle) \ No newline at end of file diff --git a/maze.py b/maze.py index 76fa5d3..a5abd8c 100644 --- a/maze.py +++ b/maze.py @@ -35,21 +35,21 @@ class Maze: elif char == "*": self.power_pellets.add((x, y)) elif char == "P": - self.pacman_start = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2) + self.pacman_start = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2 + 32) def draw(self, screen): for y, row in enumerate(self.layout): for x, char in enumerate(row): - rect = pygame.Rect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE) + rect = pygame.Rect(x * TILE_SIZE, y * TILE_SIZE + 32, TILE_SIZE, TILE_SIZE) if char == "W": pygame.draw.rect(screen, COLOR_WALL, rect) # Draw dots for (x, y) in self.dots: - center = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2) + center = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2 + 32) pygame.draw.circle(screen, COLOR_DOT, center, 2) # Draw power pellets for (x, y) in self.power_pellets: - center = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2) + center = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2 + 32) pygame.draw.circle(screen, COLOR_POWER, center, 5) def tile_at(self, x, y): diff --git a/pman.py b/pman.py index 734dc3d..1c00794 100644 --- a/pman.py +++ b/pman.py @@ -1,13 +1,12 @@ import pygame from actors.enums import Colors, PlayerDirection, PillType from actors.pacman import ActorPacman -from labyrinth import Labyrinth from actors.ghost import Blinky, Pinky, Inky, Clyde # adjust import path as needed from actors.ghost_mode_controller import GhostModeController -from scoreboard import Scoreboard +from hud import HUD from maze import Maze -__version__ = "0.2.3" +__version__ = "0.2.4" def spawn_ghosts(center_position): @@ -29,43 +28,19 @@ def spawn_ghosts(center_position): return pygame.sprite.Group(blinky, pinky, inky, clyde) -def place_pills(maze, spacing=16): - pills = pygame.sprite.Group() - height = len(maze) - width = len(maze[0]) - - # Normal pills - for y in range(height): - for x in range(width): - if maze[y][x] == 0: # assuming 0 is path - if x % spacing == 0 and y % spacing == 0: - pills.add(PillType.PillTypeRegular(x * spacing + spacing // 2, y * spacing + spacing // 2)) - - # Power pills in 4 corners - corners = [ - (1, 1), - (1, width - 2), - (height - 2, 1), - (height - 2, width - 2) - ] - for cy, cx in corners: - pills.add(PillType.PillTypePower(cx * spacing + spacing // 2, cy * spacing + spacing // 2)) - - return pills - def main() -> None: pygame.init() - screen_width, screen_height = (32*29), (32*30) + screen_width, screen_height = (32*29), (32*30)+32 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("Pac-Man " + __version__) - scoreboard = Scoreboard() - #labyrinth = Labyrinth(screen, width=screen_width, height=screen_height) + cherry_img = pygame.image.load("assets/cherry.png").convert_alpha() + hud = HUD(screen_width, screen_height, cherry_image=cherry_img) maze = Maze("maze/pacman_maze.txt") player = ActorPacman(screen, center=maze.pacman_start) ghost_mode_controller = GhostModeController() - ghost_home_center = (screen_width // 2, screen_height // 2) + ghost_home_center = (screen_width // 2, (screen_height) // 2) ghosts = spawn_ghosts(ghost_home_center) clock = pygame.time.Clock() @@ -99,8 +74,8 @@ def main() -> None: elif hat_y == -1: player.direction = PlayerDirection.DirectionDown - #labyrinth.draw() # In your main game loop: + hud.draw(screen) maze.draw(screen) player.animate() player.draw() @@ -112,7 +87,6 @@ def main() -> None: #ghost.update(maze, pacman) ghosts.draw(screen) - scoreboard.draw(screen) pygame.display.flip() clock.tick(60) diff --git a/scoreboard.py b/scoreboard.py deleted file mode 100644 index 798c0f4..0000000 --- a/scoreboard.py +++ /dev/null @@ -1,42 +0,0 @@ -import pygame -import os -from actors.enums import Colors - -class Scoreboard: - def __init__(self, font_size=24, highscore_file="highscore.txt"): - self.score = 0 - self.highscore_file = highscore_file - self.highscore = self.load_highscore() - - self.font = pygame.font.Font(None, font_size) - self.color = Colors.WHITE.value - self.score_pos = (10, 10) - self.highscore_pos = (10, 40) - - def load_highscore(self): - if os.path.exists(self.highscore_file): - with open(self.highscore_file, 'r') as file: - try: - return int(file.read()) - except ValueError: - return 0 - return 0 - - def save_highscore(self): - with open(self.highscore_file, 'w') as file: - file.write(str(self.highscore)) - - def add_points(self, points): - self.score += points - if self.score > self.highscore: - self.highscore = self.score - self.save_highscore() - - def reset(self): - self.score = 0 - - def draw(self, screen): - score_text = self.font.render(f"Score: {self.score}", True, self.color) - highscore_text = self.font.render(f"High Score: {self.highscore}", True, self.color) - screen.blit(score_text, self.score_pos) - screen.blit(highscore_text, self.highscore_pos) \ No newline at end of file