From 147ef4b89bfa8ae724484a1c1bf50e8e458f5f57 Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Mon, 8 Jun 2026 19:09:40 -0600 Subject: [PATCH] feat: add Hexsweeper logic game - Register Hexsweeper game in server registry with icon frame 52 - Add HexsweeperGame import and scene configuration in main.js - Add hexsweeper slug mapping in GameRoomScene.js - Update game-icons sprite sheet with new icon --- public/assets/images/game-icons.png | Bin 195628 -> 199162 bytes public/assets/images/game-icons.psd | Bin 516314 -> 528835 bytes public/src/games/hexsweeper/HexsweeperGame.js | 438 ++++++++++++++++++ .../src/games/hexsweeper/HexsweeperLogic.js | 201 ++++++++ public/src/main.js | 2 + public/src/scenes/GameRoomScene.js | 2 +- server/games/registry.js | 1 + 7 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 public/src/games/hexsweeper/HexsweeperGame.js create mode 100644 public/src/games/hexsweeper/HexsweeperLogic.js diff --git a/public/assets/images/game-icons.png b/public/assets/images/game-icons.png index 4ad394358010f9ce6fbf9dd227e9c2b1b041a8dc..6c662e2381bffc46c13a18f23f5e1b392f75a90e 100644 GIT binary patch delta 36720 zcmV)dK&QW~_zU`z43IZP2kWfPh z=|vEw2m*qDy?}zKe-uPSK?MW^L3$NTXrYA^(l$NW&GtUK)BEk;Id>K;pdW#RAnu#r zWRuyMxo7S@_q@+}%kvniene#x>qdRxoDNIJ*wBg{t+X+K=WQ0iWJLmo{biOU99?*H zRexsFxx#*}?cqP5*p2-^V>kcduhhZ*f4O7#mMMxlM5SykKuM{{1PSG3H7F~o8k6-K z>*Hj`(zgGIAkDw4y%fn6O{+7ND&`acqik^>CSws~(x$9AhgZH_mN#-io@ZPRQAkt1 z@zM}C*wvq@%@t&BLY*^fV`W)Y`ZdN>vTo6ymeHV_t|?3=xq8~xU9!+M3X{MDXxS)} zF`Q6MjsORl4ftHTKWKY(>ICPyWL_D3b#s4nTldh#4u@^oP0y`;vAH%BIdx9M2Y*IV zGFeqO^{ifux{|w^HH)3M^qbJrMAO*>RMTdh;yGh1B4_LO)_P9KQP^Tv_n3qtO?|%` z^`$9pgC@O+V`gbHm6aYR*N%WimTYQE&OQtMH{OKQid6`nemXdhm%K}}f}xpz6Z?7Q znHTI;Rh1JRPPbREd$I!~iT?0t?0@EK?`|&$)_Os%Pn5wKu;e^#ZiQgnQSHx z{WkOB9SO9{axN@D=sUD;$C5C+0fE%Y-j=5-LIp~GH)EVV8+TSJG&q|oV%LMjDLKN8Mcds z%I)MD%!IslB`WKp7&3W;R}Nx89zhusgqsSC=rnUvK(0K5zL*dEa1u;(1nK0+Krm2x z!{oZAKmGo-`*$nK_K!BSvoI1(OXnvGxw#AGJ7!fjqIqbG=hbp{ZgYK^r##@XPmm|`>ztlU?pmFl%#xk7!tkbh4HR;_4#RI(A&(J`RnYseb=Cm?)G@_nMkQb?)@?mG*xZdMb4u`%+so|~;SM;E&F3fwqj}f~-*68{)$_=LGxyDvn-`Bp616JX z6flAlQlP@>yvvSuffa~T$S1+tN?;FE!pQYvR)Zh8K^=u`!Ae3^R|imtk_FU~M}<`@ zY9oNs)Mc32EPqt86YYc({V@}MH%}vwRyvMGDn*;!il9*D5{rY+Quq)FX!gKR(_;>l z!yX}i9Jdc`nq~|$DALaqQm{j5Wtwv z%fzV|$P*w*RlpSa-FeHH8Rt0;s?M!vN4IAL(&XMH^jgoC)iYuV{J~!<4UHoqtR^M-Bc3nsV)t0I>Q=v zfzN5Wk|uXdQq)HcBiC0G&qiIk7ECqQNkLy(HFUd&iOL-O5}$Rsq;x^ompMdcmER|K z#|zn*Q-2cTr|n<5QQ5EJF-2$Oc&4Cd3#$3tnl|R-{hQynmPqUfncCASiy)cjIdU4w z=9hC=CyNqI7xUBP{uL;{aIu$?DON>V1l9B>YZM94X~T|2DTc=CDw#1ZKC%q}tn~mz zMI45=>eQ$@m!o+igfdztB_VX$sn(ieniRwqEPr{#f3=%$`i(Su*4!IJQF9;w{r_}Mqg?|kI-q2cYl>942rIeW|7BSM^1FctFBO+;7i-c06X7+gRE&~HXlkB&qH3ZBccrFl$mB~!n?s^htVH61HH*0@%^)l1I>T?XHn%6;*z>#upp3K*So ztcPP})QUQvJj%#BXxeK5nLAN(-G2AYYkzJX`k>F+n_!aKNF)*vnQYZF_ur0SRU>9C zSO|wFgkWh6s-_-<(Y`haR1VVZ9-|Xtt@O9Zb8vfu#9uft5>F%2--UdXtRK-)IPJEH zcDvi2R%BYd`TuP;9tV{FY-80g??u4Oe|Vk=MU*vDv=!_dYU* zgB}N~GORo6aJo&-QU{>-3!5)-I|eIC$(FL9`Z%T_r3$PXE3nitM}JM|qc%Q}s0~S6 zezfI?9K-rJr(lMh3ZwA_oo9Ts5G`!uhF@-QB{ZH@)>8>L zqt3B5MDA*rVQ8vS7#^T5O|*sH`%X!vQcD+nsuOxqP7xU^x@cJPh~|6skyO=+#k&Ar z8{1GxMR>^+iwR7NxPQC|E-flbioy)WY7=L;u`IFmd2Eqvni3kh9k7LhQ2P48`@L3O zCjIbiGG?R{^L^{$AqN~O4)$igpHfn00lKJg#z0P0oE=ePzpN@8G_ldQUv-5?cLsdu zj`G$zbkBWlsB`AfnXqHVrB{%(AqypU2y!X1hDipdPLyOC00g`m- zA=_fW(mSB_6=c)AccPKIW9{9&I(g7&_}Z^kpLtJX7k8%^<_{Tm`|VP_pRAQ+Lv6(2 zB17#Qj3Z7!rY2?~Mq=33+uuHrh@J0XjJ3PEckc0^&cjbW^xpM)_QlurXJ5oW)?qK( z)5qIgd;YIa^nV?+__+Dye)fkwtsBnl-?2gTmXxA?LIY}RDv59MLnOYiwzd)>pB+QP z2`hjxJlKaA*?{&gTZ3GD#Nvo`c}f+ZFYpMN64#`Yk$AC6Vw(|>C3NoLB~RAyl7ilv!g>&h_W zzEF01zt!XmmfNKShO;{2iXLy@)&Iq+iQ>>;U)S*Fbz2gfxA*N6GW)^7L3Qnl*X}y~ ztaHA*a9$PP6-t4VY2yq-cCicuQ?YcnHA?VGz@I2`R<|c_5x#O(Eo4E}t&|w$Io9Sn1`7dMzpIH z6DL+#(bHTajncYu0!njW90VNpc97S)2tc$!C4X>sL>0g`O~Y$H{1pL+6A8FhC{l#Y zO&1j(Fh+=ru?JONki_ByC%^y>8;eZ#Gsh72ske=rcf=<*S8BSh^M+cKYAfXPR&C=b z!Am29{m7(~R#aS;6AI;T^Fz9OeFwbS~zzJBPj5Y}|ARqNWVxB8l#X~x!#mllN;u+9)DRbFp^}m)}U;rkdB6jA|*j@EzeWHM=3P3 zR*49m^E6^;DI?NaNz>x|vFarMt`=gBrMDTYk@ zb%LK+H%h*GDY=I=i!|DbT#{pq4E41S3|j&l|74QW=I-yvWrwpl7(8Rf3Tf9sT7Uj+ zBxgTyLURqb|EzMj-2&MN>*hP#Qp~GwbijxYWAi`{vOOCxyo#nX$^GjNnI%;djQ!?M zd}m&B+1lF4C9BZX-YQfQ=??}FJ|8T{Ik8+UVP~loS`3M#?6bh zlsY}b>q0Wfq0F9!90?+$48V-Hnt$n3YSmD_@a;5`tJDA0?)T%_+pjHcWjOA<^6JJP zGJ^XOmgP@KM8Z>Ik+49yB_$d_$j6Z;z_LJmOn7h*qa(w}rjn*42r0?t*k*J3UKAXj zCt7!{ZQb4Dj|0jNw*T*xq-5^b|KI<;e8gdgw3qlj4dJ1|HUcPgvJib}o`0_Y1~bUE zJRTWMWX06&L7(_?TbwzqoVT60t}Uvj&B50;kHp^j%VSIF4rX63Oy&*0_;vqbhaCRR znzFJhSyO3BrSq^ewxarvAX?1;lyF$G36{hfjn07=V6sIWbibVAoi(H3vGF!-HQnH+<&3;jG z;rhru*-hqRpP_4Qq9i34PK?L1O5)|^+Y>Eq1E1(ctErtsBSG{bKmGJGnUb>7NNr6` z((Q7G8IE3<+|+z=QuMPO1);H8*occ;0z^A$5XVT1hItNXbOCOpl=fRinK zTL}4D4O>}3N29`#^|ajU`nTW7=028E!q5i=xD;eF_=n~93+I2e@aTj0UC;C4Lk$zk zyrPgLKu;*9uxYKbIaWeIL7{2Ub{89KP<)uCPz03BnEDMAFx7v;e4XDT?#x+P=9EjShVOvA^6B{nzi4lhgjHrcf^1&E)$>6ZXNu z)c0a(?bv80%|#=5tXn$>rJ%v(q;yOQSyN7#SNEa(_!XpF^P6z~tE?QkLwtPqm*?RMoux4|jCdR8-!1;c+KD>*n3Z7KS3n zXg%GB<@{Qx5R+LYs&(g6(c6RYJ&-g8c1xM=vub2>WDfPTQR<*;XH1>*qd-ZhB3uxg z;zQk>l1`V!M}~aV3Grly#j#ApAqgo@WyO%w>)zGcvVS6#N`*i2ych?RyJ!D&q6>wB zv2x9t&O%=9&FAy<1#gIUpc%K|!xki#;oLTYJsIMf zS;a#xp?^owOj9#io4_&x0hWS=Ex`ziCR5^L8rEY~jpgz(TTtQEc}^&^iM)-VG=|Is zJI^pZ#GAaedgby5&%N-1_`7426`kQF$#PDHRy=KLA#XV(CBBm!x{iGESPEKngLn9$ zqy|xu7)E6Mo2YJ{4l~>he`$%;?X3~CEXVVZDu3#rNE}kcDMs2`;Y=uaV?!8@;KX7I zlyZQ`Sxdv4mqf6<11j06%CTN6%Bq_j%1hlAh#nqE!0xc);5iL=a>G8mod1*d>)Y=# zPoG_PuizApEwA?M^!hy;IZo(HXN|s{9pU!pmv8;g@+$k#PCM;Xec7^QIk_N*Z8lp> zAb&HBY{l#hnVAdoWW47X#yDFw12av zM9?Iqx1p;6xxYUZYxak+zM(<$C->bs#B<#J)0>2VJ!VyOQz3?)>{SE;#l3C&hu9I+R~t<5+b@G zC*z5;zp`NQJ0E9UPi^eEk^H!E4}8T>+>SWn2)Z8b4(PQw!|``g=DlLyynp`N50W1b z?#*NDDZAzeSJA-4yA4sa?u4EjDqFkc!+yrJ`p{=Cut7G@=Efa66!KU{{=05pk7wN8 zZ{vV+-1exQdHR_Q!}0rRs&b~PDsv*S1e4BWM(j>|QZ5vtnN(^U@z1N=Zb#q7md&4P zU^;G}UHjFNhiiPLfrmwrpMPU1p;)RhG)V1eEvv>0w7jd6m@B-j)2? zl^6WePVR?7 zxh|7UAC}MNSXu;3X$cyq%)<0J2cdCd4SxEA@6dWaLllLzvu98L?#7K$OtX1{s;sV2AI`!FvEb17gnX;TtQYf;DQI5>8!=CoKE z%)Uz?&K9GSH0`ZZ&^h)RtJ%UFBQ{`)zvl&hlE>$H{Eus2{X*xq)^$I>;EM4`{J4$V zxP9jBGY=>)_<#K8eYwQ&&!eNk&$n;i>+ztT(R}M9+Od9SVL{2u5)%&pa&Bwlx z80yEIMMn`tB%ya`2(efS{(ui%i9SJ9jQdVJ`3qmY^LM|$?6NB^-?*>8+o#1!s%z&2 zN@~6p83|hswMe;9)WqfAlaYhP0m*U2Zb$0COG-<6fPcL$8NK`V!b7)y-qiJ3%Qy90 zd-JV(ULNb?TFde!j*7Yo_e(bWJTka;(=Z2g-RMviEl$q$pr&iX!=sUoch+u*U48X8 z_bSQ$f0Nz1?C~b2$9*3s@N+S?*%@OPwA3MtF@0ylQmH9YLa}U7wMHG|C8h77AhSpd zT#R5+aDQnZsRs?pM-tp0cBTD$K_pZ z?_4@{-m#c4cRuWn8IV{W>0}y1BLi?(PJ$TQge{w%Ln<)}#^FFNI|5FPVAu8$NKU7v zjv$Io^bC$LYuByXzs4uN{lLBVA9emk7p&TwV}F0)p$A=VgPX0giF55CX1>aMcJ3M& zz2+959 zs;padZP{Gj0-BZrjYXm>kaOy2-xuTkPxjQqch#4ayMN3v`O1S`{-9?!uU+wy z&41%`O?J4w-_&(26N#no8XZk04 zn&6p?$K#GQO=w7b;mlLJ8I~I~bbXhmDT8t#nb{d+l3@aZ5`gN&@qb58 zhqrVZByR`2O$35I*!VH6VHyb{ z&N!XTzmM2=Uz^>=|E#(uI7yTwWVPPw$WteMlE;7Z^(D57iptq`yZswH#~;peT!w?^CUuGDM(vumbNyRO&!2n9aebfUciUHX%gc|{Io!^Bd4WI3YRew0jkM@u zE#`VqZBFnOH=$|ORMG^vt|=BJOp$a6MY%)rUP`?pa-0P!X;hQ^O&LicGL-9+Y@o>c z!5VoOk`I!WoyiR8yjG1Iuc1AWW|T!{_S8j zHx51I7{~<`uIfg3eQpeo#tu0IMHX2-jZBWw0MQ5}l?$OwI3fjyfW=3s zThb|}rFg>8v^d8XiL1%;j8$Vv_M7BAx~`9#zf`uNj$t5b!CfH2?0{g6&)Ff!bS8M79_=1OAY+O=4=Y#n~` ze?LLlQX(qN^10!WWvxR9%J~KKi;vD zv-y_V?SHPNN1bs>cu${uUCVWo2kdsI<&0_M#!i5wDDX%{N3k^?Az(NNe@QvwqhU~P z@JzN4r0@O4^|!b*j?3MC-8c3bciO8<{!;C6iZ|Nq0(;;Q7onl95(h4r#hh@=p}%mu zoEvYv37huTvDd9x;w~*My;_o7UttAL%}`G-Mt?iE!ANzXe98i(_!{_}PAb7SV`6>X zmq)^3`MKv`=6z(7^v;^K$ma`KwsILxKY2D{v4hELd2HXl6>gy)m8E^~cD)62=CK6y zABRcJ^H7jAJ)TlO^R<-(OipxqJ%1Ez(jq#sY`ie0c0xg+VadBtFe%Wc9CDB8jMY!} zo_|sbH`c6U)kG2mN;gAR&81n?*rt(7j%u<~H54lyZon4V0Xdh2mQO+{od$l_YOu}w zLzbM=31gkjB0R+hb8 ziS*2&SqFYUwI`4DuXf)9_fM^;tbDPMmw&65KKlgb?LQfssUzImf}zd=l_NnRlg5fI z5ga$C0@J3=$D17qu)Sq7Q)nMLTxy(jD;dTY{?izjE&WSLz*BOjHkv#^a^?;dMSrJ5 zkR;f=rErF-!LW&9bVPT<;h~zdv~yGh$MaVDjnz$*kmm#L{3W8Jhplh;0>1zKYMge; zT3mbG*;uu_9s4hs1A+5`W$PgZvT)>5TzPH03To!e=*Y;K@oda|{qf&)%XxE|ODK6$ z(fOr|zx4T!Tu*o4qD6JtoO((kYky3rsGeZSg5|Plu*B)Q+;-xW1>&$7I9*-@OG`1( zy^}a*-qOp>q$0;3cKlgiShf7M6WpTl82PvhKk7I>uDKkJvqB~A##|vo|BXWqnuT-E zIsu$uFU#ffm;L;wKfLk>Kl<4o1z{W3y(R^M?!!buI)~%!rxvmqch{yzuz!8^TCfPf zQTVdUOf`_xM~s0wyKtV1p$K9VIG9kwM$k zRV%FxtNOwu>x60PoLdw^x_@4bN}9#SGTPg1@lw)e9IGJ*#l{<>D9K6RN7otN%AUKS zF$wpNboECsJd0~p=kpA?WWltY{^%19i=*{Q2joY}5+kb=YF+ka| zvEJ_TI=-*#$!~7$*iP_+6FeKnXw*;|n&fb__u{9!b`IY#@8}m2dw=Sf@7k|!y(M6C zd0vb}hN_=>VGc zSHFYFLqq>Ief#nYe}6mD#bv+aWLpoE%(%-rwH7uP0a`*80e&6=9BH{@oH#N&cu}SvTOHBmNWWY)kY`VZxDjp*Nznz&`THk<@(nhqlbz%0*TGUrhMB};57FYwrTXZIz zJphK*FnYY8Vm@W%l_=G-jGi58$S0E*5B2q4oQwN2_uhHevVXpu@j!G}=X1CJ;g=se z9e2p$#f!SThnEcZce=Gr>j>}_;PnOIaJnGbZ14v{2#`m0O+9h8BKe*yCQO}=WFn5} z=nzyzy=dLr%V4+j2!;GLdtxqp6npdKM-O(pZI^r8BI|H?am!8L!Mb(p@Vh%7#^qJG^SAUR~KD4Kf+1|Q-hQsOnz9`vGF-_Lqw(c>sZG42x(?RqOcyYpMGYJ6k zW5=$|D1{3)yC3D`Tq2&GPr&EwIkToC8t+AK*C-}Wo{MC3GkVwW!a)Ztgquu(ic&vb zfCt))W5M}VjP!TG$2zTs5=B+>$*laD1(Y{F_ov!GS%2seP81KMh|ucRru0=9(?um< z&|r)G-I`|6{E+*MOnXDOq$hcXBOuYRnr&E)>N0c1UL5jPjsi+6N~wcM48u_JWCO=Q z=g0<7DqkF8LN4y5KUH`fjBVZ&|TEu>RD~KcN4+525A@F8H=X zNc@QBGdO5&837C3$jBPrUY!?@I%ri5uj6Vv+fPdlqaWr=h;G-FsRCQw)4mQJySCuO6Mv6~*I$N1k8HwFZ?6?`IQ*!C;FN5r ztSCWuZ$AofV)0QYz~Odbu&)zNR|$Ii`cYk34xQ1_85@SvU5}BZf^3EZ=N5tCewfit zbnalVb=wX!S5_h)ABE5FBd@g!A2haAFFy4hyOjL7x6H$u${Y;8x*ERIXTc^3#94VQ zhkwMd@22AHFti*DBLnDOD8#|BtPPqzk+HSFx{B^we0y}g4d@il-mL$HY@pb<*BP)KEEbFXF$_Lcqox%+B^6=jby zJbQo@PGo3fmb7yW277TEw5vES0`EH2mmFUHNoXYA(ccXm4HA#E8w+5B|kG{!{{jtA#U?SC-*YF zCwWPl<_d6+{C>sX&b@rm37hxzIUBce8@F-W6J`O*mSv|(bxpBLZ1%2ia({edoxzqv zl{q-poLI>M*$wwPa4a*%`!JRWy0 zJ$T9AhQiLDHqZI>zun3I`hWMo@fUL0E0k;pmc9HEf+Zn{4hgB8hGZgXMGYKwKcXoE z)f1f%U4GDPpV!49*4u)e>!T&X+>0Mr?qL)AQY8?%@mskGz}VMMj;N+giZiz88oL1uWtfs*a2o+9}dB8 zXb3Z=`I6J&I7d-bCVx~K!bx8|2J?eK1beq&U}O|qhtp`RE5k8I9S)D%YpIR!fgqlH z?ggYqM{&u4hZ>K(zV+ei>Z)Ho`tYNBtw!vV zzkzr96o{3F}I7*xx*)(~qd6HA)bZgt@^qxGI zyJPpCaRyT}G=EShijLD6lRv{WRPk*NEsAOGIv|e&r9_gmPn&dO#A#oD!h`oIyYt!J zlEAH;ARJI6CZ{QBu1F8W6q{)n`hP3JSnSxA$Tb%U;FQRNroRiSOg40;6^UdCAf%~s zT`nNjKWyDUP9}r&n&*)c$`CyC9Fzr0V5ln8e1>eIa({4Tw!@z2Kqi_7SKDkg`D8tl z$VyAVqy=Va#FX;0^3z-%*PqCc=I)h~JZ|GQZsYa|8^7{}tHlY8eZR0fb61#L9dDXW zEO|9SoGOQNPl+K^LRC-7Yk4Dnxr<``3EH=;FWTo3$TdqE#vOM}rNsuNpY!WXlRWO{Y z!0E@N;P-hQHV1QNxxZ_{nrDvv?$fWipZLY?PrNT3%Rz4lm4t%ZTGnEquNyU0RbXg7 zi#Xl9hlL|hLqGwKa+}RcClB_tVaJvhv~Jr1Nq=&Ymzj_wL&%f2D2jr-LO_=y!%aX$ z$VUL3w*ic*b*;v&f2Vmrn zPaw8t1Da1i5}X(Y3mTnFg0ojyP7XQ&ehgQ`6|Q{Ih=jY=O8Q8Svtt)as;RnkZMGVfYFq#p9~iw#~=<3IS8x_P0m^oPs1et zr|EGs13f#0c#hw#?$Zq|TOV9}_z_x&)qb?NRGHioS5WRuAt>pnm=?t1qZ<$zWw8FG zXK?Td$G}%!f!;Tt!ePzTFd9VcV1?Y3hks1I{PREi+IZVzTo4_ajdu%gDa8G}P0KsFWj(aU8`rm64OKk`8f%GN^5#wI11Vb$N=2EDfr zu1QnipFRUQK_;6M0Um-nHuMi-II;$9YX^`YRG`&|uxjNdOsTIyDCmGr=3l&h2!GC0 z7E^sDBAF7hZE?WMkHFvv@F@inasWGb?1Y{p6kk%e^q^ z$Jc(Sj&yRlnp9o0>LD#999;#K;D0umB8fR`QT-HaCqu(|zYL5`ph-i1uZR>)lRggi>ALd=i;@k7kq-6bZc7I)xTkpM{-0WeuW znt*IH3f@d$@+1d*?g;BFvs)Twt6%?}vOJ?A*a|C4DQ5N#U=XapCdGfSh9CV}f{cGMY$yl&SFR^xf&VOE6j$QXWjs>?~ z1D>mespY^q%81V+4oFKj7%Q`|8RmhUr)UtXP+Jy=nJ7*qZ z9X$wEPk_^3f!A6im|X3`!l{#7BiYmh@-d%y+V7?tf5_Nu!W99({Y+8fEuw1*B3atJ zK}!(mPdcBqjFs*bZ6a!F%FCI7k?%kE^nGhjKJCjN2?VF*!hdhwwKe+{Hg0d=zI-XT zn|}e#VTaSDpo;*PvN`*MaRy))LKxf;hMDg`MYo2s2~&`$@ZqhMtvKnpc}Ne1p}g|~ zPCKy@>wBC?w`Pz@^r9k|heGbfZ98>r?(w6^*@3A+8*L?dwa+eaI$nmuPQ7cmZ6xDEwsczZ`W>Ezhx^>@C zj!8-fM7d?Du@;4piF_uF#ONq;WX(`>dAQ^PB4izl^?$eHjV>9gs}|zQHJEkcF$72! zyS-^M4xIuJ(y|cb9At5y0Y*F>yvTreB%miYBHOwN+0k|+bQ`wB$}y!`uBUHY^U?vH#->S! zvu2@*<$v@3O*>MEMhz^Uxfyv)!G;bm=1$oKQ<1^iRa9CveIDcsbW^?or6GB-!?voF zVdCWf$CK4O0GreT$v#LHTC%9eau{jf0a4E(C@PNHAWsRV-v=nadhw<0xBcqYi~IUw ze{y@vTt^*uJO=v*EU7eT1!xv=v5AuE3d~wC8-I3Z5G5r(2o68CZrX^pq4j9*>_<46 zM?onDZAM}VEPs158Gj6UbuCt}Z%1oS1d>1%UKl83eA6a36M!uvI?@HF(=~7Mgu}>} zz%&0kK8IUfmP%|js!lqT%{z5;J@|wbN%Bl9fna2bpHpDSeK5%PH{k?J08H#;tAWl?ZMXMIjG*VXQxXHN5=TS0dvI#I~-DLtXRY0l7`PxUBM16Mlol22KU6!1~ z91p!dh?TFOdB&$(_)}vCe5ej&a&B_ZE)u1HR_kEP(o_FD;Z$JL4 zn;v9dfAu<}q8$F09)%JaL4e#N%im~0&ogfzK!D@a(h7LUsfo-ffz8>E;0rH6#DCEk zX=1JMX=Ga47R|w`HUq6g11R+lp?64xndv2)vK0Cv&8RIisg6A~a(zcfdLS?w`CX3I zU3TxubNQd_<}1H8yJTqS#>q44kKr;pqooT_9b_$V)PVDm`;gbcPC0VW+aD3$R+1!Y#-s_DC(-qkx6CYt8PMk zWW-8+x4iKV<{f(oG{$Dp57BZ>h;|EDs{RJpc@YkB{G6_WqZ<-(Y#ISojenvHY4I;( zpV4HE+qjL}xb11C-W6@+|`J;Ka5y-0~|sKcCzZr1PldAQsw{dOAHP6 z{B0-Rs3pKmMM+s5IDg(Cjw#D@wzkZ} z2LQ@^Hr|mL80o2*cVt8Ai8yBe^y}DqgJWA zenveGIA$R>*`3($9+{yqGI3|7rc~JVQ6|wA z#no5U6i9ICf-gY87y4u1dUGh9&Ba?cml?2f9GpA=gKRW)qXLQ`;PKWz zbQxZBWwOZ03Qk$O79Mi@y;fR|!|amBZtyq6`}-(u!GE_u=-499o02Gz^@Ow1$}H{N zW{cpk7?~{cNYdPePEepkueT~=!z*th+cOAXD2N%eCKEtOfO=aWsPfa!oiPlDBarhN znKwSN@hreiX}#!tq0vS|qlJ;hbUHbbVF6Sf1sb~~b4w$~P}HIpxHdKhIxd=yAGdKE zw{iQd7=Q1O4Cbp}%E0ZMYNe?eCIVA=1o196I-&xe-RQ&DPm3VLk0PSZL~TRG!47Bm zV1_Kl`RvPh;OQVHH&x=W1A54!It{FE4*U{_Gmm~7o)QsSSj4i8BATa&u<^>StTw@_ zpH$3B&SWEC3>gL4j*hMeF?m`B*}f;y(LNenw?E1pc+e&S4`vzGNSQxu|5u*6)}h>@~}xv zF;YRDf&r@=b2O_%vI%IYt3p>tA7n*FO_>{R@|=w^z&h;&yyelhX$uCsy7#~Oic97M z+<&-?ILPO2`1vhM=-5s={}%PNdoFzzGYj9a#fd|Y%BZ{M5{RWP{O!Kikh<$Zgb1wD z7A!{13@;gj3{H=tb$JVBA9D~mj(h=@`cDq=xD2mGfT5Q!s?q4Q?n}mNZ?r%XT)6YT z8{l*X@a7vUaNBKn<1deeAqY0?KX*C~*nfXI4m*4yrcP~woo*1|g2;+is4F*UL&0R$ z%{lvokHkm$gGV1L9DL1rf6f-vtNd=N>S71lJFVJPQyxYJ-|(C$iQiCrH?gr~8n3^)8m&VHTs0CF zOy&^i??*Tf_%s1I0t81z&5EKQ7z|iZ=J?_z-27-vnMv#S{rIAHXYlsb*ZXpZ9@YCod+#G z;bYZTW|G;j_2#we`dRy3Jazwa+nVitcxn3(*7#XWVO1=0i>S`0p=EN=6dMvgFaFxq zikJaNRV91B7wP;+9uD7l%AYyI+s8G0-R)3nL>bMRT(*dWKJZ~c{p5ltJAxuyB9XQ zMAo|uhWZAqj_x@P^P!n+@pH{$1GugmR(S+N)u33`s@2pCSU{FWCw0@X8icGUsU}lW zb>`!o=W!diaT~W!laZCz$$wM?))OZcAPXGrKp-nQ+YiA#47aa_reQ09d2*k;AjN?<~qd4!k>-Dp;A&0va0g}2f^W@>1pt84*{7e ztKgoqOd50$P#}&$u+pCm^hRxZ)f>6y8Fu39DMXdsrtF!>C3XB$M~ zaN0UY5b(*1>}~CD#(zh{t{GDr&i%;`zO(qcpZ{_V9bZ;<-5wu}UU}pb_wlka3coN&`X7;d`hTbMb0l66U){<-+&ugT_sb>rHfUXR{^Eq{3U=@)VPA0NT@zV#)1 z?dq!uJf%%28ECSOv>>1?;9UA~CerO~{L6<3=2bOL10un{^3*ycQp4~{P68&vc)UM{ zW9C%i?!RrpWtKguEJdHB9e?yxF~!JR^TOw`!S8XNedldI`srm~|LJb)k9^wheA~ z0B>~wc`_fX>pYlJXQDTphSN0z_3=EkU>USEYmoZGZ-2mq%AkJvD^TawK(Z^G%i9nP z`fC?D?Y4!Yq+Ven?Pj0 zEj<6|t0)gRG4Ig1SQk!VeKwC~&W5A?F1*~M;KfZ5lGQsiX2+k znW2esx*=1s=C7~7%?jk)Rg-lti^ymJp|Wy>d=gr94WZH?qR|xkI{J~LwZ^InK~JIO ztyKuz6~Y-;oQER%W~^gU>}r8Zde550$Rxc_>4Pfj&|`m7(+QyDF{( ze)7OzQkm+px56z_VCX7FmWcB-h(CR8r40+}QwS0u=@eGN$c%s$tI0bT!gSOTfU}i2 z+5`b68D#q3LAG}nd9R4H!oyKXtI~2P_i-2;np zRVN_SL``Mmu&yze&1|UkBR%}{VO2e@ZB${h1A~9aM0w;g1xunWo0V;&LxaST+tJz8 zi6_@!?H}EUw{J%>T!2u` zp>z3G)X$s(f3@4{-ZqG%QwxL0rV6O9ssU@SC^i8w^w=UUyzo>4ggvmT#mM*E*s>1E zSRQ{5njF=7Hq+l$(+!{Um~sMp2O5;L`c$Kk6hp?c!@1 zw{F;Y-=y*a5^jzFieBiYWw^U#2>q)RyuPLlr`HB?LZBWgb^tg3`4v1-SA|38H0Rvn zrric)AJv|F_944XFn>|vx7Bc>yGYe!`E-B181ZF_N9UF2FykQEid=4oi_+Je5m2--&&Os|ws;j2VlV-kNV zn}f&O3~6u}DJ24~q8ugxLn!njM>b5WUwswpS8PW^t&Rhan1qT63sGHDBS=zZh22(i zn!|28&Fymcwr^c~?ZoNx|MFqK)6!Fp5b~1mTgwBb7v+Q;0b(Oag~L_@o1il2iX`Ci z8R!|*(2;dOamDd^imV;9DJqjdA)|j{-a-YA2>CuELAXap(bcmP8oyPuhR#n)~+q&Apn=+WF)sh9mSBec9Nm%5-`#| zfMo9|>KkhiA038|fN!e5?UY1Iv)g93gCiT!ii!%@?H&wt_aK!>S)Z>J@>qZN=yRBT zz-%szai$+pnbcGVA(@h`k?xwZ4bYnv6I>~e72;f;^JVH5c<2G)e8RKEN zTGwup;|?IZa*2gQvSUTdS`3fq`24BsX^0Jw7Q+PvT%N!jpA9T=GBkSD6$zrI3oA+ zsH%z;Yt~}sv}s@@!2$q8HcY6;l*Vcd4faB^ z0Rw}PQ;#@&F~98f*NOoQCAqASkIr&BTowSQO#mzfx$Y1q9k~E&{`eHyRgOCW?0Zb-R=B!pB*xP$-~0wD&1=_T}H zz~Bzj-t)fCy8}h_l?d8L?>c(X z_y6IYlRgW{VoZN@+AU{!JVZcCj(pA}jW6lc>QKnr%pmVsn2%Jl-h3?D#J0VWk7Uww zZ&A3b=m$8y@)m*`6t-}l7)Qy1J)*)*o6V9asYvvnU*p&YWCBJlb$ z&?_n+rH3Jsx7xH?7ZmGg$PNc+Ms1)tOGITeURk{Y0kVIV80C||r#djS-vCd>@06(x za5YXrE|CJ?(FwkJ3b-@Qg6GJw7`-w9PjMRSc15u|(~U7Dk0CZ^44TOzW+++-yL$p; z$y$}n8rPFU{aiu$^33s~oJxGj(b09Yj9_ir(t=f!reMHRf@#Meho<^EY}~jXB3VTF z-45pDP-%Y`$!AFnW2)`w?Cb*P4l;@h98J}LQ-A7l+kf!vk_Vr2di+0F`ToW(a&36(BT0+RXzrqpeBbSS8`Hee zIYuIft($hj;c}956hUDTt5;9HIM)=$V4m}cxjavHRU=Sr5V)MJ0Zz5pD&5DYR4a!Y{!?+ z?SOyMMdsW1M&v9s>NA9KwK~csOhRF?21sC~{kCR&;_$>VZC*m({A(LqaUpmTyfn1T&-e-IL;|G7%8Ryt0G&kR{X7!r$ zjlKbvADPMIy%#rZ*$x|xNK#Ka3$5nl5Q%?9VV82`gPlg^a!`n%(v&Q0WO7p!4Y70< zrLwGgo%T(#$N&3CJo_RMlOJxYb@v91`+Jwu3X(q+dcC*EHv3H_#Q_{Sc`QoG%i#+6 zQBqxqj@>P&s;zH5dhY4vL{N6n$A-GXi&KI3za=*wOLUBvyw)g0Jx1mhD{ALW#;$)q zK7qEiTToakBihnR4Y0{Ia6)BXl6IuC0vtLIk(yJ3nxXrd^$91~@}7xga)Txjkr>9h z4LfN!4$M7zB1GoLmqkUuj$ht#37Z@#+=wMkB0)s8;eKhyu3ZN;xp4x=opS0q-lcE9 z^FSI`r%kX+9{FFQ0r_v11>Ano?qC9(8p-E#>qOSOnHAsAbII&v z4u}sT-we7YAV1?Ib{`sX;>oxw3IxPV&ba=?7nZC)ec^=%ZOne*rB|svUAupNW3yU+ zdeQ}_`*sgKhV5JS!%G%B{V4(VDhrhU6k3|f(bOG<&9#p$cvLlup7ve@3OL;Klhd$y z-F~dz(1sb~3NT@OIdW+OrDWk`h-6&n$T)M`Vf)z)NVpYjTe%EHv|G^$RdDRwhi&V7 zu$72d-J_zetPvmr%O-JTyeWT1G?Dt;)_||gJZ82dnfSgXV?Qyc!;&MXZ@i5|)wZ43 zG#J6YDlZDk-B@^9B^l`&x_+WpjoOJ8TuC*6^&spI6P0k`XEkc|K$r>_gZHLDe!^zWQP!-AO zANCk&UgLZE2gsue$izy-m{EmDWFPFdAu`!!A(4;HkkyXL(s~qBOb4&8AfK-mrgffs zy^u_ZHk21_g4bUO$yx4=wrW;Y=ihXBL&vi`dIVre^#C?2+aiBTOJ1}^s(U(y%D*cZ z(qB#3H{SRoyTDoh5Km?5h|Qk3)8Npu&PoHi1YopDIRu>pb3qCnq)5{92aXt-pWrsn7HpoH=W@CzFh!al&LA zGjBE#qj7Y%cSC>YJ!qUflV(0P*sL<`I&&et|Ms@z?)tF<`~10RBgfI6%0zryeGs)Y zDkn9-R$769)$6b_K1AJ)@a_#aBNP7)n$H)QeL|b|E;FHnOVi3vX*u znkOIO7#s+mzk0>;>vM`SR@VjQd%1h}76eb44`*-(ENKOWp&;~u95Tr?Ce)J&S{Xtp zlfsZ>V8!l1Jil~#eL-=?OG4PSwVVm^Vw%1R`oZtUG^MI(7_ev1zorxSlpPXO_F7P)Qvuy5P@P^Ws(wkHio z4-s?Ys$i99m`p`Cd5v}TN20hshqkVlP%-9YBEHJWLL(B*DcWZmxGz0rzEcjTZ8IVZz-<5ScR$&!D6o^AE>QFj8-G3CG9Oc@rHMl{7b*H_-A${K2^2Iwn!Y+oCWsF zdfL0c8Ovn9PjsqX5NPy;_UcWMNrQj3UZWF4{&Ss95WDv8y)c)IUD(jr5WD2!%hyT{ zSE{a}Vz98d^3PXZ`6U)5z3GOp`}cSBTu@#|MB9W$1d0m552Ud#mO+1e2-Wp9Cw8~C_?>@O;7Y_%HO3EJD!}F~`^X8lz*$v~tgadx`cj75Tgdme zZ$q%(W90>I44JRT3=Sv>Gz4uTD`3ui1mJ9u^Z~A>UpCH-u z#Wt++H(%8~veBKtCNxUPD!L_R4MpKbx|^`Q%8@-x`Wyneztb)Xe!qYB2@rbe&kqB&$jiD=LBGMCs0~u!9b^gDvuB2j%EMmbh z5@bwRizG5u8p$Hgj(vX}tI#-|2qUssNu<(kf}Z|Vqx*G>&MuHciDxy*dW_Qt#Ck(; zIg8*ZD}|WNLKzw$>m@6s>hX|rF`PEsf{D&jtXR4WZOub)4C(0Hw-@f#Js3)6QHvZZ zi@eahZfuHih-X!}qcN;Ygi%Tabs`?c{`P&CJh~7ig~h0DXhwha=rJsc92p*dAsSC! zfA;wox6@;LaO2XvUOOPw*t)?uaD~~A=qXIa;~YIkq<@^j~$I3ry@ZB+N* zKxXxt_w2D$f^BaqYL;mOT2LdOOLb;Z5+ z{^@_NzWRUS?}~QYXwB{|q{4&O(@2Jgh=|R=?{}l4L#C54#Nk0yxOMACkGp>$`iJ1a z-Wy8F%fL$xwiV4wGMQxTs5tg01fP8zwu(uZ{k1trAA2NTz54qw9$$=G_w2GdrqO?%&$MTEluT|}BAt?K0;UGfl4gU> zIgyN$Nir$EdERB0{>^IM>bfS0=iDa=7U|qZKS~Dh|cPG^IPJqHwta`3=4V9fdZ$kytL?d&po~Ps~e$boSg+=VQwU4y=D!z63?_7y_q^Ckr*2-xok_O(Q)jRyYzU zX~L%NO;A$1U<6w*UP@wka|+%u$HV0(i@Zbz>)#;abZjjGWdV5FZ3t(!K;5ryEU zs~L2+w}Jc;nmvcEz92j<^4@V4koRj8nXIzn*b`4}`?TZjtGAtC^*WAeAmdK!kHUXh zV1*z%psEH$pB0XpG6+PJCVPhw>5W2C$)Xi8Tvg*CLQX(i?*N=+@nO&|hh8%NohA4{ zvmiQ@MoB7;T|^8o&smU_0@$^D6$W}+vGC**&@g5q8pkyw79pP_S!Gz&^k3idvtQiy z%(Kt_W$&2F|BnTrN3QOHr334H#HxS4$@NoJvZz$ac}jp!X2{XXqbjHUZ1 z=@?lI8Ehvbo1;FuSr+wV8j*|(3rBru-b=$fE`DS z6R06LF2DL^x?JD?MGl&WdR1h&-{tjM(bwI9zMet!4Gx17EwBm>jH{@?n5Hq$#bfc= zt&zk_ds_Fo`ucmJ6EViqN?w0nU~SlF?i`Iid3}DQ5)tGwWI`0lzlngfy1a1Ntx17?cKZ9|H07pgHAegIP8=CKF1|CyOeK< z$D&tOa{L+OLq{W9kX&9CGh3GrC;z+&HXU(vOP{_*j%CH^>}P-ZoH&gZ`=GGEbF>ET zvZtSU^5%2T`O-mc*PngCm1iv7$=48eMWd)8uY2RJAi7Y+T6e0Y zLBuv~A@2nhl`el3>mydIT)r8V6~KhqQy^Lt#9~@5na;iWX~+8f(|@YjxP0}(%Fz{M z@zjsG#@gBDfr|*>q%w2Qav|7lJ0jVG$q}J0O+FXbS2DA zWS|S2nM8kSVq$Xm@CiZrSxh?mw>>S(zj0l4ar8E_Y`m!6>}5!ocyDb@vIdF@oS1(+x-Oa&uzi15`_thp=L!#pS&Ktn z_Cci8ms$>zO=cEJg+&1j^|r8%7*m=jLemsf){lk5bV-NTCy;@N_(4cB= z2sVG}1xc&V9b{5+L2Q};W9@njclV*Fp$wjC3CI2MMu>MkjM6b)GGRHu6G36IPz#b2 zxk<>8NtTQDlld)<73(_@?2e;p{3ukE$;|qR&ZYtW!v#N4tr2|M-J0zkIlJN);lo1Scbz{ZL z&v4ys{n$6w$8Fm(2saU-vg{NREh}WYJ)VjUK-|M>fM=-Hj00F zF-Zgi%?Zv|chdr=eDsr+=$>ZqdJYXj@A~;!^g+|AnHIvOC6q2QMEgvku9(nyAdMq%eJliKrSRog%pN~m|tdi;NTr7kMw_|k0`Jw z`4S>Ji_usslZ9#_iVIw*ZJ2__rm4p8U_Y0P5#c90_vW? zjFN~qoq13mNQ-4wTVg&gSW;CEUXqYV<&feO7SR>SipELalbXTPASDxi^q~qFm(g$> zskFj8ZF9LCi*||*GA76(rKEqVj4V1i7OhtB7r#qpW}ff4#Qwf;plD|#HqIHQo-{Er zIehrSf|9bQHSypmm1~oeq3hh9!(E?zy!jFdArO*HCf1zdfRz80c4#VrV5D^n5 z!Y&EfE~B!@g>kht8Qtx^Vbceze$v$+taLbKWYZDoN(NSuhp)&@g$=93%#z7ONDm7>o=f9PC}B>Lm~K^z<5S`}cE#)yY~N zT6r?jWYXa6PSlL5Wf6ajaEhp;k1^Qqd?6j#^DVh(78E58i;y8YMus42D4aGG1IypX z=9e~L{%8*D4k9)M9C2hL z91bEl1==5+8qUYaBsWMVv{Du!QFBqGvms>E`qe-9=@p+EO`Cr=Z=SopzUCKQUG3G0 zIE@}gP+ZZ-qIBt0jGP|>L;$fuCac{Je_<)y-T>P7u4B=lmOb5U(%ri^2P+Yq^UpZT zxcEz_8hw3j-0D?ZiQo=%C(UVwqGhq{tre^tAIQUN3$re>cRLDvbae3uycP7o7*(Z zKgL6ZQafDEqv3Q^5P_v3o>Vut?cd%W^ZK)K^pgN0uMU<%OI&VopzUA9afr4xfJ;zS3g!?QLhR6SG7ta^yW6%4w|k zHjPMAyD@4*mQH7xaHP+d%Vfx+Q-jSa!5t_@A~cM;v2{d9=A+dajoF)z7^>%UC;7h| z922npCe7rex`lzM9xv^-hw?Mn5PqSVm7~>qF!DJ{B z_56RvS>SrB+$BDlNE>yN$Lh$2a&SB2_{n7v*u@xr_Fy?Cj`8Emb9a#s`!rOJGxl~2 zd?J$fS$yl;KbYz-^o$W49_-q=7u`LrpqWv!qYUFF&&-q*xNh3HZ_m6?#&!}S0@FqF`qNlvaOw z8+sCHDiq08NsvkUy_K7g%_K49h(=iW3^^;bDmcfihd85#9KVfBhG_^|7^z_yIRz^} zb6{8upUWZE`h0~%Gq#h-HI3fRU8o;_6q%TFWDyXCod|Qfm7Gltqig>V>`pHcmo9P) zL@0|oiwM=#`Ed6=zceIU3N=*|F?oOTG-KWg3&ATP=)40$Q5BXiTLzoMi$plZDui>{ zEDB3})Z~{5Bm%qq3dFPdf?KZ1$r`u&Cy4;qp!J+4jSpba` z-q5Hv{kO$Ies9f3EcI~SDv0G&^7(`~x{0Z!@|IdGs+7rB*0b+b(0o!VwB3Jh8J-9? zM=dQnXYqq~J$dQn*B(^W_mt@;#QJ--{f{I`H~V}|j#z4lEDSo3jdsC9L~+&llTknM z07#m@I(H=10#!!bm66Z+!im-)3ot-}}xD z69lU~Mbiu=ms2<*usCwgxPpcnaHZuq|I+zb`}zv(*svX46PlqFWFWU^5Zu{`j*Uw} z)gv zd1zrEQLSw8!gk#;QVM^>890!zL8W9)C5!8kQE6ggVsbceP=fLRYd&Z*jyj`l2l@8v zFFbMi52ua~7T7FG-?3kMHU8wo|7FjrL#vt_H`npP81O{6QJ=R;5BWeAbX;_n1*LK) zI3ggjX$>jOrS0ilp82AGJDo^e6EV`_hIJcJPQ->JH=?Jr%@}`MUfeG`9M=togUyPn zT~Oq;Aw-J?aw!(cqY*HLOeRU%*+v(M=rNFGX6O0mrQ1_9+LoieebgATiUEh9FagIK zNm>Me;!&dzPG*75wjWL$KOxrD-Dhwj&&`-V#n`%j4Hru27$yRc+RH?P{T;!<;!lX5 zbFNsNTmRB6%W{A5)FnI-Ac92mD2b>MoCs7FAzk7Jw`Vv0_mr<<=69}urK%F6s)#Ul zy2!C+p{O?SmJIUg{u!i+(0k;mSMlasTak#R;c~grG**U%D?rZZfh1It*D1hakiU~o zASU#|XSm4(>QuGd(2JjSp0gPxwP|aI&E+Xco^tA$@uh!nzFZuMM7X|=ohYenL@Yc2 zRn6xWN|F_FVKEZ%BsteH)+3#sa|`+TMxx{yu=;bb|QIy0N6mGpI@1s;#bnp2D~6v=-1`NcM;+jCh_v3~;X z!OSdwsE2lOU7gG2SdSU`UeLezwTS#`LJm11@DDFe0jrI=ey#bg7D17${C(*%Pq^154h>zQxK6^nF3| zUFpcm`(friF(1Cw{>C69~aD~_y4LFcVV=TwN2-`KI&IV^`>{=z+jckbADYez9}I&5g!z6mxm;e&{%3QfWkl;MMWBh z$oc5l)s0alH4v-{i%8lney9l|g?JTCp$;lHh?r*E9}ITv`mFQJ^HOPXAh3Ve>6Dk} zRK3*UaGn;A$GKD@hR9Ga>#Lker`h(fT_&%AZCP8$IdHRxFg26s1r85B_!4*GaX&TO z+z^~{A=2p_WZBMTi~!Mf!<8e(*B;se_?+}!Y zV`mQcbZuE;v)fMfxJo3uZ2=jl9w@n7cOn*h>fQHN{N~=@|7l?Brj37pbqwWp;(aUl+mu)P&3+(M06O6BT7VM8D^FHSb=*q zo?NA7V;{D|Oe7Nem0$b%rXSq+y>ljyZ#;5%uy3)!^R-7!A8QmAc<{*cY3{B^w<6uY z8GJN|9l<6XHL)7G@pFH$Dz^{efgy~aIUXgY9>kJ4h@y(KPN>7wrV7}c)y9OWGj-W% zLvMQFa9)h1#fmWD*cg5dUHIMV}(c8D=-MASG@F{vN+#6{n1&K_WeO;aC z=^M-vQ5$xZ>P6Ze&!tU7RFB(Mm+14BhS^VkHQdT|#H)5bpoO zi`@6W|3kw_lWUgk5H$BN#BNCPJx|F_N67oIOW*M z2ooVP5DIaltE-xdi;G1vIjdb=U7vdFe|~1M;C6qzzTx*+$6Bp+A|S;B>W~%BYT5%coAzaSOJ%$%C$Ptr^{3r#N|U$uC?gAOam8EMl&;!>cxs(?nX&{ z4XP^(F&xbz8i_n|(V}xd@ppdyi(BalTKV`R4<6z3c)rr#(Ry>h<8WVh;aDtPZNVEW zb;QLkbne=L&h4Aw<#b5o93_Zs>hEjArpAyrlWD5*W zpa`d5c`o>e|BRjMx5MvtLABbD$SP2%r4YHcc9#sz;f2TPfT-pW4<*n%Ya))n;8cHd z9&OCeHcJGhs;I2Oo7qq4DzgTnxyDqy(&)B!!04PUM0oP{Qht6YuhqoF#N^+Je~O@_ zoPOb3OP>D2TwA%X@Gh?ulhV-)vbv%VCd7SxA;*h-$)cyblESWE{&+?5V4gP_5BH89 zRa!MfCcnXfepHngJlE3Qd&illo?CyuY0HKg76%bMQVz7)u8`x27>Tj=icY7ORVN1= zJjT^jx)(qH(wXGLU6(|W%Ve`E{h&W{-t0@F@dPW};2ahrz!calR^%*B=4~n3Xz_&v zowuPVP<0ir$ESt+hps8~R3YG$kjd%DP+v=%^KXiXGq3qgYQ!UTA;koe+#H znc!@&1|}k-4U>sI0~@aq@f9V4l89Ja1DU9@BwQGh}u3Gs95s}=K zDU)tIe%{<;ckJBl3rAw2?2vyE8IFP)wChCN(_F)h%0o{CQBYWnR7Qc7h)P;{PpyO= zdvX~ToVEy)$Ja3f`tWeju-RR3I6a1*)5*hC!QPAh8kPE6c!a%L?Ve> zAN<2T=UslqHJ^H{pT&gc+37VapS@C+ZHr%db>-3+bpYHD(~!QM=}vY z^|YN<0o=QO{&3)4MaHZX+kX2gIJP`Y1xlDPa1Y@ z5FPt=;gl0*MLE&=z+gh}sH!Zy#v+K7f@r_5rLFUhMT;)%FpPggFMGb?=!H+*yY#6c zm(%%t+R&YfC0|q}&~0gQ%V}gWO5WFW`&+hH$U;j*U{ob8y74Nkdiiaver+`}(Kze) zBNX_c#-e0xLEbOPD3o*rC8Mh__wMB7NAhcqfA8~(N=QvKy#1h~9=FIu`9qQ{fF)=aucj2EVD0l8^*T)_8&;zeLe96{m zEIT)vDQz8yCRX13vk&?JS_sqgcRg=?N+Y+dJ z#?Z4xJ3jAqbaf3sR}zdYl*|0Ax|I4N(sqcV#Y3ct4pogJ98%Cw*i0ruD~o{Xh!L?; z1f9GNT_b<5M|6?j8AQ|(@oV=$)XRy0>xYoe@7Z!hP-Wxfn1_e(<6CaQWtW|S+KF{Y zB-PaBZM#0RtsX_opBHM8Vys>JLHqoZ7Mwg|#?0UD*|U3WYg@aIh&7IG>uFjJiQz%m z+=Z|@Jmk5F&?F+m@}j?>84Ka%`l#TOjjA2M_H*)%`$Gjm)&%Cc7; zvk*Z!C+}?-#-vHbWbC>TDlLWRvZIlFoi*_Y&@MsmF5d;YCkQRG9pyznoN?S~7}qof znRL#GL}IVpe9J9gs6g(bt8du(;61lrQr~~z`yF)QG`GiZKj)NEea?|lW7Dp7J{ZYx zPC0^#fE9&~BO_Le>-A_#f8Fo)A6s5ku!sz=cTySc2kSO|@XGbq|JOkY?$6`u6V7}4 zj@KVM!{c#1ukpMqAIdh^+Q2GGv=9*KT$WvDSrk}%QWsfl%{yy8W}P?-ox5AnvTc74 zLVbf!3#|~yqNa3IDHVK!J(3F1!5tJ_U z>n;prvKZ|ug^`QWM&tB9P%$pRLykC2j)lhBsK26v<@8CkYMOUL6(Z15L9i}yG^bId zo3VB@Pi}_Br_d3MZn*Oge~cc)X*b?_d+DZAPC4Ui6DCYNn@pbH>**bo6@}xdk+Vi4 zk?ABvB5k=C=67=MlFAp$OKN?T<+Vu9gjcx3a-5L93DK0lmEbC}nGDMhb~v0Ut*qnH8RZZ6|Nf3CU;Wzk2Nj7w z7z&FD3q(mALytk?Mfd~t*t1~+dOCZM8YbhWOa!$P%F;HOHUrJG3s7ECf>D*_sHr## zu0j{hZ%l_GiGzBdUVeYgw+DZC+WPmeb{PuUtUvF@N3ELSdq=CSN`vPcfI}GbI<)lh2%%Me*U6&Zhz;=t8AS8KJun; zaU(|Og2lr8Ch2mC7VM;0F_i#?Cs$V@OF54RwNu8SX3|*XJ7IrmP-tNm?TTcTS(KBG z4qAXkA5WvzR8%UO&Z65Ck^GMOlhVJ%Yg*oOlJyhU)m%FB6H`o@n3x=n{L=;HKbpl$ z9-{e{H=Md){x3@cb@GcZJ=cBoypx}G`CU>;RS~9HCZeyq4OU5jWOb8?RAf;C*(U3? zwWHT3wfL29yuE*dO0ADucCZ~cSD^GqYADd>r zBu*znGpDfbLGQo65z~%nfRl)vfk+n-f9d7J;o*bYUQ|`pc;SU-b~QIoxjmQ5Ro2#y zIe9=iXRrGBsFQW_f~`a z@9g;~Dhkw9M^j(>(;t8HyNfTo;h;L`d{JE9KqD`RbvcCyAFTwT)>iD;yaNtVBnu%K z{ev=sX&r-+2pZ>&K_Eng&YxGo_njFKT>>jyi6k;R!?EEP4)$;V^cTOPqVUbTetX-R zF%5t9$E&%_jpSpcS>b&TD2ebD4xhccvdn#-U3Lv+H$721 zt2t_O%8!tDgr8Fs79|vHGA*kDwY68tf*_`-uyNG>iM*$XxTKL>TDUXPLy6s2XA26j z>TK4^k#@u}jFFs4@-eDrnGYouoOGF|sVaXnHMitffi#^$$)z&a2fKRi|5vMMcg7N?_zxFz-E_XPb+(2J@4Q-`3IM_>sUoRvg%nAZUNN2JL4F@r*rY@jX zfvR|D_W0@Z?>+LUhW7@8-S>8Pws$`H%*$W6xQG%@3NNPmIxdte#zD{7VF*Mhie%c7 zEbwazgc29_hf{dw=}vgP-I&-^h=%$K*!(&S3lVQ{vz$O`xGjiOG)dsC4lgh)Yycfp$H@)n^P6#q1}6SuTWVJX63Jh*}ZrE#8z2R{M({H`6z!;&~U_* zdfa}`bC}%Rl#d#*mUx+w3(n`as+l0niI!r2Whw0b6EMpmV$XlZ&1jyMM1T7L?p-{H#>urfp7%q#=U#|eB7oLSNAB*& zf#c^QIQGb;*Isp5$KQJl*M94}^nLaGg^Mm&HhEHW<=DpBDdcc|Cs@S21Hs6p7o2+5 z=ca-Dqq*ltzcLnG`Q_K9FFNHyn@f6D(RJBEx2VZY6s^#Bo<%DaO=W*||1_0EFnCtX zMx7yO6q~-QbPglMG(0P~p*fKXwf;eV>@bTg>N`oJnB;RvAIZJdiCCppOhioTnN<4v z;hygMZ$9(Vf6Ai5#Kgqp|C;|;L3w~&julsgJNC6;IM{+jLZJD1NF|a;WYVz7G)GU! z1jE4>pMK_X+G>WwXA6Hyo=zMOKl|d_XP%05=BxW}v+Nnn%T8Y3B$@8mZ zE(s6x{HdKhOG#Pr&~fwTJv3qbJ!`a=hhl9H#-qLcfD9A8)GD)c% z?79`boL5wnO}mEuP^7DoDg=;T6%^6XrHLY45NXnpBE5+~-VYQhQiLEydPk5ZozOu@ z1VZm6N^hZs5JE|I^gsRA+6Q~BeI2|*P6K?rVir&|wJHi?$XpG0a&2CxIQ3c@cr-mEJToAMdQ0|@{z^`M z4cmFg?f15gnB8wL;dnh%058`h@=1V0f68}mXl0#o9d*rx$4foYM?884PUInBPhZJQ zfx{5?A53yWOK69fuDB?^i8E_?%MhC~VI@4B-?9H(HDT^Ui4X$^s0;9w7U&Em^e$rR z(JKyvUvgTGN5qR zzY4SFK6cv|b-E5C!v>;XoUsv9IEHp>g9dkkAPL~2OQ>vx1&y7qlBW2IWkoA3>*O#5dwg_>x;9b@%eSFXKQ0GO% z^V8q8Clg1@?gu0dxG7nDhd+vOQmoA_+=o1c+G)u$Q?N;=a7O@ndgRGRmFT%k>W$ewO2W*MEm0UCB)Y8QAxJk zTr8Q~Pf~|E>g3m-%Ub9SyBV^dM|O1E-TzEo^=uH);TeF(dRN>e*SqiIl_x+G+%>y$#^@yg*tSr|O0sfl*9kZV5= z$1xF{6S?%={ro<$XGsZ4PJm_F@9+KczP+3a)P8O6T8|vs>-afnQcFBEhe<=<4 z_>2`y1J`)D-~Ca7(~v4zmye5k$Aw+a&E8$NmRc2JFxt75+}h}%V__kYthM~<870e# zH=GvuG@zEE_)+7Ymn%iX*21ahu0{Rk?Qk_g?+3V8LCqN*RW%RD>ob$0L1VO8tELwO zEa##zE_^ZA!nn+ofGVP`!Y{ljQPkTew9c-4r+vi43-TCjX=YIfR)r87rq$T4Rkh0} z7E>ptTmUu*H@Q5s>!afFrFP?UhZrD!cRXVkTegN3Kn|uFU5im%DWKdk9sBMt zv|w6yg_+s@MV$>}tC#W}kmzNTUk$(U-MYH`e~?{wehrKAK9fCi_O>x^1F3wpqT?=*kSUVk$A96280kAj30K zL{OXT%61_xQ3?p8jV_1?*8tKfz>&$>mAg)+42QmS)ap!*k68SM-D0j>HFq5LUh7W_ zp4*61z^)&F!V`3t^|_9FMCEFGdT0@D6&edMjDUJ3HzO8^K>zkFP5%lIiYIg#55RFjs#Xxe ztfFn4F!oUb;GH2L@^pW2{c|7Y{(w99a4e9uKUE*CXXNuJ=UvuT6_U{~3+{0^CFNh1#{;DqV+NzWf1!u4(6e(y+Z4W~a6M%S-byf3+k+dwB61 zoQ5&+a`J9rXWcg}SAy*PWpEVfHukgcE)0c|naUdp$?h#Av*jIdh zm_mKuYWLN0_@{Lnngk;?l2x?tXwDCd#%Mt^`g7AW#!D+2gc)gcPKNygN8|75qFwJ; zS9T?&h@1|K`u^iI)l7SllKRa7287$Z4vXX+{;~tOd-I9osS>t<$T_u-npx}Nl2eVh zK%rqS7FxkP)u~K3fTHW5FcoN8TB8VCKRm&B3{+a&EZ6=|mzONdrI&0~Ik~9(x6ok~ ztANCskFm-VsTvy5@Ebs|y~aYhKFg zyByaWdvHAsq+J;E$szs`YZCzRK8aQ@MO&)6nkcdtoE19)QVV8Be!Bsz76)FCalb3c zum*lt>(_RT6j@YN9`q}DLaJVGW9VPKOYUQr2k}qarPs@C)15&{*mv*VSw7Z-ZbWfR zp6wIiv0}_WV~w5}@Nz}9!PgJe&#AB{#^0v0<2hoW=TQr{n~zl{oiw!E4;|0;(=Rcx|ZSZAA3V;XWLM8e_^7`O!3&PH~!~xCYTMNZ*>^1-eWnAL?k1+E2_mbpE3EU zsy-jS7WKoL`I3X7Yh@=mLp@Dgr4?%Spm>l!>p_Td^*wD07JafG?cq3OlD9@)Ok;XS zQ_)ay;lp6aS5Q;o9Uhf3>tf;BJy9Ql@SIl3M6gM8z6Nc`0fQ;AAU$};=-z71uvqNe}!G{f)Sp#TBspDQ|+bGk2P2IgCI4=wESGjb5!J zsVv?S@Ui`J`)2XK`S!B1Ch~fo!qLmxt4cS0$Qe89(1hpi)wy7WwjT;Mp9kelrk5HL z69(qz(euH*ajY+${kr}%SV^H>Dtd~I%fA61Utb)q*2q`tsCGL&NwWuG=dNzu{%UO8 zc)dhLaYel%UPrz0g-+(&kX|4dl&Jf=f^x;O%5_%IHvVutjgEq7Ym?*HzBNJMPyND| zDjxKb>gUCmY%Jj&G%Tt$2;n^ly?$jkTn;|*c?tsEgYn{|8n;U)M=(9WRMJv{5^yUL zHv9GfLpDNrL)rJ=eCxv;IrpIh@ok$LlMz_m^ygG(|aTM|LHZ^X@c zbdU9@X?m^)9v#xU2BI^8#n7+4n1$+IuhTLm!mkJL+2Eh>M{ zy$azm+5L8RB@eeJI&<6kwYAwh^w_T`hjuMZj=xS=!zJ?cJs)s}jp;#BzPS zq%L&|Yi5AMbXXB5e8FZ#@acUEcDYs*uNSYSp*dm(7j@tm1G8}M`KiQ>I#f(1+amqx zDZ6e3=Kv`K4hq}#ASE4Pu*2HEzyEx1_s_Ja$*#wUid`__#3|l-$<|Vvh=q74kT4a$ zZT*$3rs!Pb`eh0E_<-rfY>N0gTRW8m4rCnX##^b83yPL-dp5p+&sHLgghVRl++r-FI2%&lO%$HMSMwvG$e$eS4^=y_7 z1ZzVAW4OS*RXDxZ>^Tq&Cjaiq0qk&C_C3O2NAx3d7mN(}QA+3t`Rw(V*w%UXUi*BRA28SG#=IrLSHHl; zi-Li^&j(6`NPx6RfJV9iGhm9bm2clWr#u@Q8!J9i*TjKy!v75asi}%0BNtQC1Qmt@ zXrf{bKVX9%5QE5w3PR8p^e1Gzy3_m|eDc0}Ss2vk2m^`A-Wx?Ko5Fhmv<}$Fj{XlodwsL8@XO6%ZE9WWdY9D3fO`78{l}!TJkM;&wC_Oy5z7Kka>Y10 zS!uy?Ld$$&@t6pW*_ak4Ln--Rn@|^=6sg+0`DJRSZd68S3c+ddis-8VV@7a1vh`~> z>z;tirBj4hx$!REyR)Z))YzW+s0;UvN}ar&w#E_)EG{=d|I^1?nORGWrMa5@)Qwz$ z%}(~Ji*0tOOZM2AJHcE8XK?dO&-uF){MWY*)ABN_U-5uZ0E?FpRSDdNUzD(Tp}#rL(lgYO$?DKDd=+U zVUvRqR~I*cr!f^TO6O&$Plt4yR+zqFJvDR>Gc7|yFMv$!587{1hBH1`SEBy4Pb`Xs zl)Oh@kBHOXPHEJ9F4uM+GR0=lcA>to%*0HGVY#kP)Gft4b=hMcELef|%d(p4i_4+; zDDBAei*$UUv7|+2X91SEbH~&^)yw2`U(1G8%-acYr}IG1!Tv^Lqqqx+)H@`Y3T<}! zMPprr#isdtCDu?AM}itXV3LlpFoTu@;&37eE843+mRv||G(kQV3F@ODt8|(D`%0s3 zt5-q4wRh=X?tmxjuk1X!Lkv3pKK`;olwUYWY!ydZBC;4dWmVKFX`!juSr-17oX3wE!r=Ow9u&Ytz2L6u{ zT2qqp0v}IGNFVp$=Ecf-GfQTytU>Jt7QVA~aIc#&P9@94c-fPh3kVTX>Itgi*a_F> zuYjYFNmVUxgOz&dWS|bn-qhhRSaGvk>Tm--O9FS@M&)u|TeId<+XqoGU3r~)Yrf`8 z5LlqPM-QIM8-J1pw{l&6NP4sbU#;)j4xKmICCC%CiHl&);VC`u6Rmvjffh# zsb`Vbr5zITI5Wz5zg8>D;=;1g5(RQy3~@TY_t@Xa*$E8eduVep!91+_UZX*TNN8Y#4x3m!_K2e zUi&?df!EO=q|JAH53zf>hO+yEqu-O5FgVrlbawLjV?}FS|H^ z)bZ$$RK1JTVa+NN%Xs?E(9{gQa179*)|ld?&0Qd>Kip{^*v2n1UvOTWtRNQa>nIX{ z%Bn&sK?EVV^K8fC)%E9Te9g`Xp4ar=XRB=}zvE)wrSo*Td@@5#5RDP0fIvG5*k$9)*2ucw6gpe zZHob$5%JU)Sdb2q7sbXGzwDfST5)JscqGKclBUV^QVmPU8)(kqO5VK^z`V*3K^Wz| zqpao^Jz(mMJE_8+0pr80^|b9dDwUqS$$bB3>3u4UBrBSfoj?5FDl#)T*1cB*7COEc zXrehfqt=^CZwdU}TX?C}IXWP=CCtAya{m#o#mAJSl4N&Tbedx0(LEWy>3v@F#sJ*v zRaSl4LouwDi_XxOcjTXT0l)WbVF%~f!*<;%RMsLa*{`kXVIDL>KBC3vJH{Hg)RGnt zBc$%uf7hNsRvoOBtEhlgq-qoI{;CP0=%^?k>Z7dJDpQffWVK7lDFc>YyOa&O;$yhL z>HXIW=hVIYUk@6^rEX<~CNayBjz?*4v!y~maGtKSOw$Dw=ben1ktG?7*z3`; z%s(8yv3mJ)vGm>?>PuTQ(=13U+I^Kij)VU@4#i)RWoqWAO9`+Q$X-g^9ZUS!eUn-PLJO6;FodiEU2Hk-( zJ**EpY9t>tVd6DVADTbNs>eX+R@*MqFjY5FnwMf&Qb;F3W&uS3LKG9h7^)dmM-!iD(`-`(g*PU|-_I7g&YyAnr>Ug@k^?jk~n((0+3W^&V_CoJ?IMh-~ z*eu3~phI1%q(vTFifpg9-t+w+ZpVsmxqFR|OoJRi-^p7TUD!PJXgjvG zIznB;c+q3m7NGm2E&C>)y!pq#|L83*x@X11FPYKGn)m1Jy=v>-+WWO=ej|zt21DQ$ zz9^Au%*1J!p>aJ}wie>T(R!AAcx!5}S8CuSD$&zG?5!tGLV^Bak?BXcd>`?8rszC* zso6OE_J;rmE@t4}bqmMa5d#6^frEb8zUHkg?jKJ(#RrWkhQ9b7%d~~8*lrNRVwxw^#Am{J^$6%8he_tqxv)!Rk1BB?UbRT z9g)h}1B7vu547~%`(?BI_sx?k+Ae;hwVdKmjo|qs;UK$)F6rY=X6e{3Y)zTSOmu~u zR*YzCWHc-x$R^}A=$?x%P?Dx2<|SxM2PK^61A@QG<0G6>Rax@4H}}f4^x<Uvu>; zz$^sM=8|OR(f6Y@R@0bwvvv-v(#l&qpkz^{Ocu_(X@ySxqXU^lp=eX{<4)gZFre>W zI`Bf}psRGP%!!u;{X%ndvNyW={$7`5L4|gwWtzxT{FBLa(Hw{6&H^-XJiR@F$b>lI zR4WO+B!9v=uheF%qZC1zby14R);o9D+h% z-rF>`usb@KB?vJ?c`ax}S)T>@m#xW&euW2xYHFegO-2=N;@SM)d<|sWl^1+Ba~O{9 z_q2~OnOgrsOE9!$T7`ru`QZ7%MWt?g=%ZD17P+? z-BpevOp>RR93(21`u?3%TeGrKCR(Y=GP_gcTBo$FA0c0c?YgYxVdEeMydVJ{==r^- zQ^s+cMG_MqIqo$MCKAsLmA@&Gi=MPRHiTu@)W1P4F?Uyq$5*Wop5lsmp5DsM8mj^K`kn6& zO*5Zwi6JSr4vY}u%p5a{rWi7TET&agt=1HtrpkGBV-vBIYVNkD-6BvPhO zO9!6JOqyTUR`dztOpj1&k>ZSaHFbMU34nLzyV6N1=VuD{!PZ|(In z$P()#GpGX=0iLDVcvF9IB5Z~N4E!{Y1Xqd@wz$kHl~3PQK3_2qVb6mmwemBvHWn2Y zw+xL<{u24yV0hgP|DdDY zi+xe69D1t03n&YDkQTN~mL)ji7SUE9NH6(JRLuwPH;)lolO@JSh!d9v&BaM&3!IfL z$Y>E3o#J=!hOe0jH?J->I{IkXC;Qg^HMH8r7{-Uz?beLN(LZ zyp{|XXU}3iB#}W+IM--N8pqCyew=AU0;)4~v>Fr_04V#7ToBw&8co*lTvM5iLz-PU ze|_>MqNZ^)tFlBLC-)!ikBMrsY_DY$>iZSpdi%m}guN$R?gTZs9XnHa`RfT46*mgy z0fLJ>a5~Z)%d)?;uALjQu(T&9BMUY-N5G{->S6NIrQN@Y4stPbaohF^W#}zjFEvT+ zb&E@rfedW*gG3O>5@Q@?vVdq_c+zeAVwDQFqSt{IE3%cc@1p7Ju*HqK8p|@QV;3{E zn4Ln-m0{ND-1P9@Wy2&!GgH5)(-D9B;#q;FLKvG2kdmfj5sI*NgGHqH;8d*4$lcexdfzY$ z2e{(<>zNICyxoe_Ze(n54QCk=pv)LFmx#s7(Ds6)nYQ~ zrNH~yj4opW@y;@^?MjyP=qDF07xx&j&$pYSFMQ`^gPrLCQG?D!o;LI`{8*mNPiUzZ z5|14)Oa9BDC^xAf+D%B>eAg=12A@ZV2>?^x*s%1=M-S$L@+~1xC2msANasnJB6qs$ z2LC}(<&F$yjmc%|0s*={L;;s=6%GRpZ2oxw6gJ#lD^z)T%PrfzJCioUT$y#o%#;(8 zIXK?M#$#~FW=#oCqk=n1-EV^8^Rf5|W+x&v)UTzR-QmA=9JJl0c^6Slza(dQfqUE1 zVpg<@idy-O>{`a*Ir>awbUAGIg;BRyW@YdsV?5d+&-oN{3_K#-`OserHgz)|XR4l| zfksgH-dS+o8*VyQLLx;|@wd%W2Oni8rY`svrN5Z~**-SntbrZ)-aP(qnUGO}u4^8; zNdeUz#k0M3IuJg4XPAv>HTI`a06AUJQq!uFl4IHMZj`Z2D!=$iy|;h@vjLtNBu6%! z-;2(~p~ika|C#?_W?WFzMVAUj^GBr?`mol+)w+JTcvzj!$KFQKw&r7BJY&KMwiyMJ1A15Lj)XqsX&i< zPOs@*3l!&8>{sVh#$>==eYZdUD5zfEeNu^}lAB4K5U|L7$umFs8(g#IXw3_RLHLqD zmPSN`Gu;P}_j+Fa5$Nb`EPW+OTigIo%QE50J?7L`Is(ne%9;-X#N`*8$zByg3;qQO zszgtUuO^X{W~6Q%Vsw}-F{%c)IE+5uB+Gq%PZbRh7eYeLXRx4E#X^u!~P%>mGkLf^4#az6e@wNv-KppRPOAt0%Z(Ma_!9m!0) z8pz>&@~xa<{!W3AnAPBHSN8>*Un-8tszoAb>Z?y1Dq=WmA@i~423TS`{p<4PZ8eUu;Hoyh+`Llal*)44D_gCX zDzjDN2iUWIjU?oXml~6Zc~gXd4r4p5i8WaT*G~NWU^WS6T|X%sI-;x_$*Oa}vmgIi&qC@}f!LX5gzsB%!OUbe2Us6?g7kW3bfH5gE=BP-$EuFF7nBmrD zwK^{0W$t_c#2Sk0Wu`<-aZi~tTY0@`-QhJvs|_?5iW6#2zE7F*X10skAD6HiEj+lN zRjO%;F5Vq4%iBPZVW-WlY-izZ_FP)5?A)K9Y*&3k5%PMR{1SNKVzF7Kn;9%CA$O_j z%}R;MdqNs5lm6+JUrPNOlPZOBF%~{dsb~bVL^HD#u>Fv{|C@NTpV4zDq$2Z>%vMj`%Gy(L0(VcnvR`h`DA3wji$%4<$8y3K%V{3T*4-ytxM zbWM#3_)W8Rc=&E!dNPpn_}?lJdH#t?RH!zP;=XT*9)vU;Vmid0?YI z25mmyYoy(j-V4kAJnabkZ{0clISBqYMjFRDI_MXuPiw*Xm6`lXIq6gI;%9bGP9>SUJ5@M zE{*|57QvHC-0L8A!@pR}SgE7I36SRJW~ygT`KKlSnv=KQ;TC650x#+_MLm8tr&A*iPCfec zTVC@k4!sr2tQehYt4uA1cIf2)KQV;0-`@EjA8QsqE)flcqLiQ(fXC(faY;Lst~(;0 z3M4tL0yZv=kUVqz5@f^e^k|(_G@{XVzXU4DPew-WNKHD3yq*8}UZS$GH@``RuZOg& zx1&1x?uWa{R{zbDCn+TQRIAz{sZT&~zeZJhSb>U}CI)0%V*qsS_V&GwTTK zJut4r^r7c`ILzM}Xf3dEQFl1+-D}Oe_`cI5RIjNrXiQsS-(*-F3MqEd3$=&0$=t3P zv(DB%M^RH59ibrEy0+c?*?Cr3=UXiG6!m`+9!WFt7vNKTdh#$>-ngA1U&JH`3x$9Z zY@Q7gY?7p0#KI>GtulsvS!KUied1M)fKhbkab9y`lm-WKI!A~(@zmYGb3O6_)9m#& ztF1z7hVLh^=WXEO71Q5;OJeN_lhAwabRnZ1HiuIIUKxt2+DGB!X6Vs?_xr5(km3DE zZ|7m|iFqcsl=;NK-)yhQc2;1qw&tAU_r!#Us|R!wQHET8wfFq7yoA_7wX5Bl?l!1g z6=+O~Xc|De@^|~usrlL9^i<-imX_MZFRkDXJ&fCLcJnDIj`GFlAT!O*KFp*zJI zv?4>2&hL3hwBz#Sh|+R9vGM2JLlAx^_qq9Orj~?LvzCt70fZjOYA%Iro>Qk@!*S@_ zP}wYROI%?Firyl(ni@fZ^6k7WzW|fVJjyT{t{CutTjrAEa|QG$IPNp>7sIcr-lMmu znexm(@NO)aef=v%%HxWUz2xvb=W)v?ngZ=iO6>8gvxY%#k(KUSSdoRo17r_+TMf6w7{;rO3;pFKX z1FNY100crOi{$#R*)&pBQm+l6W1l?#LyJG`tf>adjE$|n$})VPhk7s`Mr(pqkr})a$eu08Vaqd_T!`yu5~WmC)*pu%Dnaje^iXTqFXy z)vMur^SX{a3J0%{!bU$&WkK||x-~oPQ4#f=iA<>M+!2jQs0TG#?1;P3mvm z`A#Mt%rMrzD-Rpv+GqrTGk$-ws*%rT-oC1W+*uAMXI-SbvMyRFCRE6^J%mOlOhI}XZAfWeNdkvCJJ z(R(vMNJzG_f{m!aNhRHP5GN49v8^3kT4^0_OOTUg-@-fKABP~MfepUG%6ZNY;Zu(Y zif?-1-WomEr2?WMj;IBIPyBCYKSh021>C)+>1P}}b~xB=^xXeO2RtKlJ^Eay_-?Sk zyWlqqVRH*^S5aqoYX~6hL5;RcUnR>}un2L7s=1&Bk7bR|M`AQvtWkTOzk9+`v0V}< zzxCBrA|y!yMSbDb%n-?x(cEpd!vb5|6!o-yRNrP9;5+P+EF!e7NJOfR((5WhuY1v5E+lL>RrOw#Nnw;6AD)db(2>Er&Li z{~-D1tLF*G%seL*Ko$!-3S>2*76VP>9VJ1}5!B%oHst(aAceh;YLwpI&$1@m_i@3t z)4o-~EPFMBTlc!^T-N=zFsNn^1w_dm{tJ%nLVj#P=d`@VI~y`V`YxC}UG<)|%SeDIGuwLu zdrqEI?7?m;%5TtD*;3{BHtvEFg)hB5X}nU)-quE}`WtfZ)DLdt;sE-AFpl~coKn2% zuUzHGhLry;x=W5rjeOs?Ta)sUOjj9wJ8K>;yH|xRTcV$eKIO& z=#j-{G0ok`ic>4~^pb2U&neBZ}J zFz1Tz31B?wMp9QrXb6vIW8)JFu;j*I*9qJ<@l!igJ3Es*OyG1HuUX7~_1(GxQ24%% zcI;)@iDPF7M`{S_TJ^f@2$?@h7RiGOxExs_!WM%CsebSE@EMN3rawBfRE)vMC~%%H zo~!q|7e=iRQW|*lL)ndnr7YSD&}!~mPoXm(=Q*tsyEtxZQ3mY|E$Gq%r%3i+%ji2F zPtVV^zwOo@GIx>MQtz@I=?5c$GK@xSjq6s42AfauxtqaL#9*fi$F*1@yUO52D-k-S zm!QSdOa9O1qhg2h^1A$Z6+6q^eQ|{qb5;e1zzt%e43oJIFCLn#u7IeA0$;pH2fR`X z%|%w~jB$YOw)KDY@abXQ`(LvybI+eP7?fF!*EPFclYH#{kO^Y~P?nC~%&GD4+x}&2 z^O&$Mx;rr3Qt07FKHRRZmB4fJ~M;u1tb~wH)bv}o2tMz&awG8YmiV-Nm&>Z3bW(N+(PPc3N%E-d}{GrBBY9d`?LH`Cgm zYdbX%jvt^3bNFU=Ue5`;uS>QDQ-ATa)j3?0G!zh|b=aYT7$6eV5xR$=22Dfe2|x?H zR#eu4P2U~zTCvIs{1_L-n~zYUYINQ!{i7j-rUf3{bM`rp$sfM$d(j)k-)Ha?l5kUUK?9O?9vx)*xNhnYgz&Kvth5VAu<1iyDdH{y?FQ@Ns1zdcz z{b=8@Jf8FJ&o)U+Dx}vNl1)Vme5jE!L*H^t{dJ=yfGicAJa0-`ET8WG-jUY5r`G{@ zJw82>3<7VL!-czgr8e0rWoK`P!d-6D=HJIEv;Knb76!%>xSGB-IWoRkW-OehLezmF z{HA2+4t2Bl5`>MlnM;l-l1L@vIu5>dvjUzwEguVmG??5kEisu_v!bLA8!DJz-us`~ z;Mah&ege&$+NWOD+*Ui-WLn;jxH_~j!lmf>KoC%C_*l+2WKM8gnhBXX4#wZ0c$)4H z5%rzfSlAbVgIYm>{luzj$wEb}4?`onj!Qer!#L)g*>pVzCd%{xg*{{v6=O1VI>k* zHYmN>ADK{%wJ5vILTY0^nz-`P_je{Xnvy?v(n%1{Cn zJ*=BMR}0PKwMHjes;MuEGlwIY*{R! zoxR{xw9g!Nx?N`9`5yciYyNCXdTq{Jd-ECxXYkyIq^T$PGe&!`Uk+%M5kh6kVo8hi z7;@*lKCvi#T(vLGbnJ>ODcf({x!VCms@@KG-V9p%lS;qU2s2DU`M-xr3_pYd1vn$D}|IzhbRWZ4>uajwiquU5W*72BWf#F z7g+=;$haXP#TEB!piIDx4rC0ysY-;2Q&OViT!-`j2NA!2X$h`%oT(N7tz7O6au=Vl zgY3&^uGnZ1fqL-$SG1!Iqm5vvw+!8!n+$-(8OU=_)v@(StWKPZr%dm#A!_zgFPQdxKO>Ek(fpB4L!j5o;JI-Pw9~>FB9EG|XFZFQ2q( z5{8TAv1amyBIUe&DY3LIZ@h}4S}3P_o`Fr@N|NLWW>4If9KXPko?3Ky%&NrbmVF9JFjwFmvP*!rnun^ z!#f?Ukj<7|rI_1b2@U0jDwUtV9d*;$b&vNKe!KlEjg#YZv3tZRjR&8>+Fs+Im{j8G zGy3%K)s+go7rxJO23Hc`*B*JjpCU^Y5HFUKQp*rMrqt4!~_eV;kQpBl%}%5L+N|72}RQc-^)i3YZ|NbQCAr~zL?2d zo7kP>Lh124oObleJpX(cOIwgmUwi}`-$^V7>SXeJm<0PQ_*q%xW_LeVR|`lre?=jE zwuU%lbWdyB+cncXdA7 zb?ki?=E473d!z}e?N?8RwYt`UG8pVvURw=bvIq{&b-2ZP@nsDPK{sK`Zo}nO+zZwT zcr+LKoghL7C3Q^)pka&U`iiES9h!maHG*RXhUcgK$SEU8rVxo}Euy=pQ13+@a$SZ6 zd6&}J|+%dI?*kVLzEhxVNz|xGQR8&HWjTjtOC&?Y#%XSffkSc{CS|5LA z23LhCK1+}?WFi*V=R;y`TBC;PhPnWuB>HN+`nz3_h`4Jn}h@Zhux-YKb4DJKLBay6*FFAi2d?u zs!S}eOHq;dpAYa2ir-Smp0?TEE;R{T`}GKa4ia)Nn;D@eqbdG?jG1e1cbVE28>e5> z6pWi4kyL<0qz2A-YuzqgT_eU2=tGQo==EHo!mFSw^+6D2CO2I-4hzE%n<;nv9q{{b zGF@c4qK58?Hdoe8v&o^<4v9`&DS< zu&Z^hwpL`qoAsDDSEi-87OB|fY45F1@2|P3D3u-`5hn@n{|m+`HEjVuyVDabokz1! zLksE)B16>C+ps9bMwnGyek^V95JyVpExY*ie-U24r(l_OzBU+`oS&1iqJ`mu5&0%j z<6VCSjDre;HO^CMk_J|&T-;aYy0aMeSJEPe3ilb9&Rzd2#Q#)##)_u^J(927F8Vh~u57Ns29C&VmxfxTHUDQg z=mk3n&rc~+5-=*$qI@gt{!lQ*jlV&{rqJ#l5c{F033ei6S;MPi(EoUu4o{sy(Mcua z+)Ua`p!9($gg~);)=p{A)hN$|bV!qPVR3ax1 zd42nNx=5)Nfd$8Xt1>Y4SckJx3-XzQ!m!D^5_JE0$#$upsx_l>-EEnwYGZiT&Tr}h! zKL(cd9;YzrL0mSF3f9Fqvzfg;F2ql}#Pad{!*!8KI|mu>wy3UEl-3y$BAgkvwKrmu zVhzF{EV1r*81|cw&{sFF1v~hHWsQFv1@fBS(Oqp88Ts@gO~=~HBCQgYy~8-3DXKw? zt9oBlKwWi5H-`f{!3g;>rFNL`JzeP=hN?1-PUT}7cC1e!4_W& z{jCnY4-G;G_Ns|^px4=N!v*fSrjKek4Ze5{I>DglDz$e z3Wy9UO5)~YC7{AVC(UTKvUjRjU~xv-D-kX z?QF}h6N>1sg+FF>&TSJ0_GO^!Q;ik-v6QwV_oX7^Uxy6t>2kIhQFFoYzQQD3RrJ2G zUl7+p1ZP&FSjH<|-zC{ppn#KKmY|J=B0PWWb5V7mHd$zxJZ1lE>juZuf^rRokhoW; z%P%Oa&N+ZQBH1YuA^t9MWw~MwOdlXVbnki+;-1f!>{aPsET2xaNjE82f>6{`20)=Q zc<_{tDKBq`KbN!m`jDk{N)M{3oh+?jY^76^YxS;qmKMHLMf|ja2aR|ZFAu3gA5f|q zk+235L906w=B8C857W$tix$vA@^@lv)wM}z-?R=9p8etv{I7y!w*B`<|L{w8f1Sm6 zdtv)B2taZ%BMNwltM|@Fep&1U0C@oi4~kryhYO;|DSgLS!n?zm{Rddl9E2-)z!|!& z73Lu+uwIP@Dq$N1v=;*ZTsGu+PDYjGmh_^o+CKe;H8B6D?OdZ&S<8+yTqEsv9obo0 zMGTD91@&hO`@>1vdHooK=sVfVKi<6YR9(zaWLfv`yVQ@nk76}AWrqGY=L&g`k%cRz z3JU8sM(JUs;J}7s1N`Z;nH8R3Hhkel3lZbQXUz$9^a=flw!E^ZSRV9@{IP^RH0GOt z=fStH7e|D#4a$T0dkiZc8va#A+3fp*OkCpan=?~3&V}xpuFf`S5LHk;ra%5}PK*Ih z8tw6y3o$f(aU!+tRu|a$vcphpO^u{E^9|Id;j|nnJI)$B0LnAN`z zAOrcW!6Q*Z5!}Y2LlYu+n3sra?}J?n@f%(08`ts-7a;2L`Y=O{4I!PO*_s1j)rmP8 zpeihJ{2jPpi-PM{WI^&^MJCBx9umnRKF<1)oL7;^fj=9sHHLlj15OXc9Er>a@-QVC zeRiQRnn$GLy@5@s1LIp^f)v^*M?wc%4jC>${Nu&DRg0U_qcLnXiX9(~+E!ap5k)4xAQCyfUTTA8}_SwQ!%21(;n9{?I z<#>V-02}ur?6*Ljl3rAD1~$d40Q6CflK%zr%2j8?0%8 zxKt}%+v?2>HQeeKskL%Lcy3VXG{tyP*Ju9l3Kr%uME;N~e`DRSY))Gm5P9ifg1ZET zzbL^RwuxJv`yZ@xBhkmw=0|zU`)d+}fjY$~Qj~_s$V+HMS+auj8bl1ZW9Vd}2dCpN zoQ#KV__v}2?17EWlnbn2Ea=7UBHkoGl~BD?d0maD!!r??matm|9Q|Ep%z_Y)D5!&% ztL;W$!gi0ChMxZ|Z!cWhPq5byIf1rM@+LdV9H8@V-GRXiu?cQvb$=*dg8Z*O!1NN2 z3Upnw6<_%y3kA8I?VFY79ueEc_gN}6*VzwmnjnD;#-rxTy^j+Sr0pufV0iSGFxf`na4{{5bmeZVsk7mUm-$uKEY#!up-q>9iS9q3AOsN+js|A5N!{r(r;| zcdfRa-HyaV1ZDvY;pXegy))&`vs3$hC z(}N@>LEW=uVn`Ayk3VvB2OaK=@nMR=E~%y1i{ZBgcAZBN9=_cE8wxL~{qoY^ty6+* zoo_J3sq5_^xGdt%UIN8XFxw@>5#~hlR72zf4MOd*_L@h6efh=U;%f?^iLdBrDwhUf zz>C7tG5@6!-7=Ef7PjZnrjapv7>#G+Bs187uIvKUor9Xcs@dn#l@{SCtJq%FH_+?3 zY`bbjkF0c$MnrnXYrGgjLN~~eGVkS$*Qh!>p6a!HD`egX)eH9YTA^Zpv6L-B$Gg~9 zN>LD*KFptBC+i~kDDVJ&*pOOzW@*PO-8-iII67jvy|9MW@D!u-NF&0@5;XW`jJ^{b z46`!$Ul+U^&=rtWZuVwiQ42Jr9V3D>CoYQY>Y6xu!Et)pBQ{$j|8p@u9;oZT`jhm$ zh4fDkIfQJ6Gmv<07Q1!0g)6pPK3COs)}1P7R16Mb8^v8&mJ^`+IR{&JEJry zpiDTrHX^+gNQx8zVI9_*%zJbrNDiUVS6)0_Yxk{{CSI}ROdY^_MbuD$@&v`f=R3IZ zDG45qt>rjCH9D!bdOY#F&N9$(KS1(t?zc5icizU%3)gr0oAlg}$O}R!F~gfO=!BUY zY}fBx{XL^sKWs9Gz+*YYw7?actM~ab#n1!ea=K&-q>+@3S%{+$)r)UTw{p=bR2Cc& zksG%?F4q}9O;IoZa(ltpl@K6L0$UHkwf{nd4E5Meuu$Kh+2M_J@O^B0xl_|X;br3} zFwK|7S-=ZZ?ll<>JC*csudl-!!PZdcalQEsl$^Fm7LV+r;DJ*N{P*t_W^$son=5eD zR}u{dlp(iS!pTTJBYjP}s=n*c8hB4#KRXK0!6B!c+8yHDE{BqG24|p%zm=U5UOb{GoHMjaL42P z6Pz;uQeBI+0*jlHPiDyTY$&&vq8%<;ha zhGo4hw2FBe&o&%|oZn?;-MfdoJBDYd5DE5ZTT2&?C|PC$yN)Gz7r00WFi9*-Ni=c` zE9zXk=81Nyo15K)$d=YDjmJH9P8VpXHV^$9r@Yn@Z&CGZVeOHPzj)N2v6O1mLv~En z-4i^6DoVHXM<^a?R*EfZ5$RBT)W6fqKWQ4OKnm-nZIj<5!?)8;Wt#oA)*96;ie2f+ zBv|Ty{0YUpt1}z>*GPybutHBZ2;ry(@2&o)!2XH#rBZkK%1&=um^zv$izdIe5vN&G z{>SJ;ddBFnQ$Ix6Ph|JOV#1v4ljUVO$&tHsb`unN{T^iY4H7y|Q>NO^!;N(IcOqwB z7LJm3BPpV2*1(`$(4?8(8zG)~D@?te)mF1}Ka~ks$u=xdG_W~gprozL4Nc_Sw5z88 ztZW6`v9K4B+8gW7=a+(KW9!ebS)1|p7rXCPIgD9>=XlG5Xu{MN+a>txOxYz*yN4OLjs%~Agpnd6#wCE=3+pTnn;eLFdmsPHkvAHU4E9l0k{s9nO=Q^*U#DN+0JBX zm|X^Xmq>c)2hQQ*qY1EKH3+uZ!UY_O0UK3CfT)bq95!#ip0qRgWk8e!M-E6i$PIv#U z-f|hUqKoxsBH%LljKC{`T7U=^|3Ds@;7mtfb(+e2&Kg>cu-JG~TMaxAEEuxoFPEP4)?I?y>#i(Hc z_}Br4V4)HuWdvSB%6 zGShn1^B(%<9?IP1Y)_(gw0}QZ@Vz98W!C$WhbsEuUv}$Z0JP^$RRbf zT*OEzlzLr?bp}LEOqiLjH)MCYUiY+`y`JVR5`Jyz#o<3!9Q11N*;(ruo+ViBY)9y- zhW^bASkVa3SA*au1d||W2|=Kz5=Om1gqjLpSF8}tcSihbb7vDarB}K>5IT8dnl}re z`1JS+!e}d<3dI3dY3g7N{B4wo=k}#Jj+dGe zZNw?`!MNyBOiGEikyQCs$oIX?&&cLWrKCSv!9L_NOGr^0+k(}+WsTf{a>~%vI)Ks9D19~ZjQ4YzE;or|1T8(WQd9h zYoSd2^;5v+hK*n@cv)Tp40|p*r>`&&bJx2;yCG|L#FO z{_NZ(3FVRV7Z;L2;{68<$Sr8XA}!T z=Qbf^!1QW(dSm_nEAB0W;)<5GQQ`ptBoKl_2=2ih65MrgnFNQy-FFfK1P>lOxI@rk z21|kt?k>Rw7+}!B2D#k(|E;>`tyACkXR3Bht^M@wwN~%my`Jv=z%QAQju++{Vxy&0 zknr3u?OoA!T4L_=pJOipTp^2vm-4dgJh=6YD~H&TL^C>*QqD&@0w*f;>P|*nu)VfY8iehv{Bl@NwPfpYwh9 zT%W4OyLg&wbZRDqI5Ydr%$uJdXC-#q_IXdLmcu^4Xb@;x{(C|I?1@H+KDY7gt$!RP4GeMun{Rl zO*=q$)r#+78NnI8xX=DlF?G^QS#6eJ)U*8@{npbA(3FS(4c*@%JJF(KzuZzho9{V& zDa;c;4zoE$RehdL0#y#IYXR@{IDc0`B@2uwnoJg7HkuWd;;qqinjw?C z!h&BsE~u_}3cJqS`h~Ng#^`dY5yGeYP`z8*czW!uhp$fJ2j!p3ZwEy0`NgbOp8cRz zOFt=3(E7&F+bszA-mIvzWCbosvDirOe^H%W`LhU}f4G9Q90nv2P}|iP^-eoqQq{b> z-Jf+*zUnh1TpVZTbz;TMC?8KhC@H(6pS<{b|7DxkxVz)xOlU(!fZM-l9Gk(4ubIMH z8q6Ax6)zjqF4IiD?qR3jtm*$++nd(5(B}|?KaMranyIlTpU3S)(UQiH>f)r52xY&y zR_9GfTae~rJ+K8TMYev)QqK-}Ilh-rnEKPVel%FGT{2sPU%7_sIpzDJ#B*(ZW3r$a zLLSXGqWkEfgSja4Tl-4<_d# zjQ?M=nGFR?e*v!2)QkMd$8lVtB(Dm8vbXTQIwtos&JXYTyRLiB!Vou_LQsiOjDC*! zTTSwBl8_gqa-dXU2Cast^=;|oR#O&Pw)&4F-q+{W7Lb|)g1)we!n66fWg6|PM+$Lo zyb}!fpU*4+Z$FSc4YBJzHa}r@2*qfdLYd>}>uuDh;`o*e5!B~5n(~A96S6)FP zbt4Tu6K}P0;8SK!ekoHj7Lb~El3es=hdt7oiz7u3_-M_wWg+|geSvDSIq~Zx9A%~I z#O)0YSZmI))TY{M`BNDYcyn!gHIknnF_0y`nZ0s@7TxsAMyPfTFj3}{PC|Kh9dF~_ zy{^5sg)Sd9dJv$2-|t6F#ptt+$q;|S=?W|a*jmk6^ThMUV0OT9Ur(Bp%kMyU@#(9p z2Jta~%65QaPDk&Xk3%}Fs5a8YrLd{r$lgdqH!x<9@8mDXk*RxU=AKeE?1&w~B+Y_9 z^dtXoEn~hcTPe}k39OBWdaT$~r?8*gAZyv^E^Y_Tw;ALc&C>&jn zY+Yz_Yv_y>)t9O9TJ3vPXd}RUsrBA{yJ8?G-T*uLEgH$kx5{gE(ftv2c4*CCwqtu! zP{sShC0i<}r(P6)s=h(3UHG5Za?l#V^tC$6l0N-KP50bE&5GTOar&5PgYA(3RILpV zq;8gKspbi&GCSKl<^&4b<~14Kc9dLxdcI`{ zEdNvIs>D1QOq=(gf^AasKd`l`^pJbAF32z&X$=bCjj`Nj4vw_t@wCCg&TWQgv}Gimb7PU*f{=3k$QNT zbnT1|iqaMsTu0OJpC(^YJenOn{v_vKh6`_K#^(xkoOS?%r5Squ zIq^c-R`RUNZZQhY60%bN_v{^EO)`YDhO?Y$xTGDbulnM{_qm3pH))dAsui=}vabb2K)kflGYC%EVw|;4LNhTKq-Z|z__qlebRtaNX!Go+at!wC2 z*ZLBZ!EfRCm$MR}<#yhsiyge2wE()--Nr-V<-;&|(eT+RLDuBV0xQreF02CkktRV< z@#S^KppvzGB}h--oUH5=JTX0q<%ux8i7L~*)+qKnDdY^5QOHCcw{m-2W+CERkzNs0 zjm}cg?;4rnbsjdWUygZ#M@gR9ilt|SLr^Bcz;+>BV{Ah3MxQ3gX>r!aTQ@wi@ghsd zz=R<-x580*-Rc(v1kBmgt9oTcIxG4Op|RMQ+bc7_m4$w~A7a9j+wRzkN!NP!2{8;! zbjed`SC?70v&CAQpC+f*1J-;;^UHljF2SmB^Xs3Pu9LGm)OwmTP7Tc|dY*<1-z!II zG`b>_@GTuo;`(aIpi0V%r(e2`8DDxDDy}>uy=9VQNuQ4{0a`A7)g-03*_fYzL_`!O zUIp|pXczh6zp^g{UDVUeH@BOz+mJn$rFBcvn=4}#ipwO$7xlB5B{|yW2?TZL_$&P_ zEvO$VBVN?yD%W?>rkY{OouWvXR_!i-K*6A+y|%UQFKZE^UENVS=nl73zYnyu2W>1}wW=V;Zi#eU7kbIIos2=}l^x3b=55Er;6CGJ7Zmp}p9w;i)ObjMP?v z$U%G3DfkKpgon z&IG=nX}3(p!Q`rxMc&G0pShZl>s(x~z+sJUtLp-s2%UvwXEFzRH^1-7g{oD|Gsmtp z_4=xWMOjBM>Wqn5md$Cl@WDM|T5hg)3P$v~`j-#-e%l#q7|s0r%fk~f(^N1awNi;G z2`bcW{dU}+k~OTlImTwucE^aQ70>iPX7_w{l_RXIcW^kxuO7E#UU&2to0GpDk zQ)m*$nZ&HHvmKvhLi%28;IAgvKCEsN|O%DQ)qFkG*_L@r%x4r9a$mZ3`MS^I5+3X$IZL zIY2ipU6IkXyUXh{r~aL9pk7)xjETGLF9zsh&a1QLgtlJTR?FpguyY0>wcja6+gkU3 zQVqr`g#>P7z9&_3+kr%nS)wS``d0^*n76a~nO;Pdhp{Wa-c7}tmn5OY+IRV)*EW9+(K{6ANC1!Qv|Uz0RhFF{#diM}}d`69}a^!t))=+|rW zQL}r8BA$NRg`3obvbU-Gf!J{Ap~6PJADf5xKv!+&nyB(QiDmG=IZR{*~eu_@yWX9giZ1K$Ad4IuiN+KVk z^tJ*G&DMUAMQSG8xqWK5qQ{P`++m?>$Gjih7g<&kWzd=B(_OCjt4s;B&x*Fn@-N{s z_1)72KYRA9D|021UC+&&D=!$m-q{2QqPrGeA&pVUEfj%Ei=kd0OHR6^&$g|wv*Cqm z$CXV0EBOgeS=lr5f5+vEQxcO-H2;pvusL;&ITvMr@hqJ9q6nPanbHxKDRb-JT-*$c zPX=>FqqR7g2cPQYly6&m{EC|ZDN1X-+RGE)hhLZR51${raF@2aXwnw0~=yY8Z= zRoOa=QVo`H&zuo@E`A0+m+fHU`Lq{70&I^w6z(@Hr|~~Omu#s0u%e?}L6>^4+w$;> zxb<5hdP!N60!hyle{puIRX2MB=`#qG#TY~7)L2$w_YX#MaAh!=$`~;>q7S!P0_vDt zFAy~#ZCBG|Ca=uc7wXw~Fk=ENP6zB?sbeAi<|2jG{&oI`0<7UeumUOL?+d=#kzGH} z1L5mEVOG8#?IQioxbV!?Dx%0@`qyUpaL4Un<)cGhUa+D)>QQIoyDTerHe9m0v1+{I z={9yY13iQke|Z7SJkh=~yuW1@s|=aoF)DT#sCCD{Yee&iq(W11QwDl~d?CQ;*7 zrm1$rIY>A4gfK?cL4=;FMGBEhGbSuj5gZH!k&`B9bTVxMp0>+@%RSg9w9eT=0(GF+ zZ{xN@kL+Wmh*U&~U!Cn;lkp&vInF#|#r{XXZaR1)vZR`yZfJ2FcMnfv zhcBuYw(RF|@wYHEFF3WOi#T^*ZV$}Uw2-~?=EZbF%(#hF>?revmCWOCe)fM4YSD*e z6Q^!~QqU%GgxJ6zA#PldT73EgWa&t>>fX7&J(V#BDQ1xP+Y};fV_0QIka_+w@sUb3 zeYV33Fx%@4_hjNUbV^^zTpJ=Y+EYEA4Ruyhm8<8Fv1vHH%B<5x+Yog%dx;WWKJPD! zjO?|Yv~=4>B8~JovcdEr^TLQ>mNECPdr`o~c`5y237PI;TXd2l!C~l5C#h>hyVRR} z)R}uvI#(X8lD(&mm0H);xB}=)>`wvpXMLYg$MZA<>|#5G9>(ulwJPH;QNPqOV1{D0 z`%cjWL=M|>GA*A+kTRkHC=yMny6w6gtOPwS&TUl7&QAfSxor4H2j%$}N^!yL#OeTD z;AMnK$UUf1>GJn(SLMH-Gd&3eyWXVpB#|FnIP93BV3&dvDi<3m#T@Hb`Kl;{8)%G8 zom;ZefPL`Z@70uZ-_*^lcI++GX^pa{^SlWpXUcBTtv6H1^pEJySvEv!K!&&Ddy}i% zudb#89$Rw#(Rz0@i#r-6dI+b{F#@P~JGzbYMRVA`@r%DXJTDRK`QYLb2YP6hK#fY2 zfoXUrhSUQMmYYVpQnW{`5r>ad6I}!6_Td!R`2rmdi z3GDPv`zq*-WjrGaL-%VqUV8pK#bJAuxay7s^*rp{=2jg{XtlPRRjoyRHUKteG@(kJ z8}ZT0T*t8vuiU01WclMXP^hBusn^6FOKQckp?SJYaSmDGv}VN?<80X7dA2`4@idBI zQca>Ofim(tzwr7Myr>9Cv2F;YB9lS-;osDDKZFUby7<*W2Lr!NJ?muUbgR8CeUFh}eDxe@15oze z7j#miqzh|vyy2YREkt=VrE3<9V~1Oo__HWe(R+}|j+Ix%u;_fe_L|X^ zNOX1^57>95FmBOzjpu0JTYA<7u^W>A;v51|*=?|aH?)WFFw z)ECm}8djUa(}JR6uY2$B_HjusxBmF z0HVdi&6ivo40*4=$J$@>M3E_RFTr)|0WqGCD!Xoq6};Y|XR6@=^4h^UJum1s-34s8 zJaIA^7S@e4WzHW=A1(26iH?L8nSDVF9@VKY9(8)h6L|skeZiG6c?QK3_>VF7JIRt$ z4XTsRQ`E-{wC^~A*UXYquLH1(i@H z1<{=NKj=MU>%pXZP##|=O_$-Aa9Zz9u&E{i&Up@0@x9-bqBGyxTFrH;M$lCNxGYOo z+pI0{=Pn>QY(GE{OIWPPvO2mSTGpW{5V{C0u2tyC6NRrU;uGUCZS0V#e_PJ_?y@+- z7%*6t0El^p_`exeQ67&T6c4{yRa%DuH8Nu&D9 zGfn9kz87BKiO*Y~^~PrukdPeW5pE`PEz>dEC}p`zN0SyI||!A(of z_+QRFSt?QUtbK+iQ4<5{LH!x~?JFMDKghGT4)r#SJI&~sER`0EabLul%n_L|LICpQ z^#_1v-_0gXwUhxPX;kS`x)-U!?8p~J&~cYXC8A^VBjX8zvf7gDY#7GtU5{#2snnD% ztY>6@ysk+XHL2;ZBHFQNZ?D@R9sQ5%oN=l)oUcRkB+eSe!}?2}J-LhFb3j1+-pU$X z?!ejOG~WGpldF#~Z$6k_u@4ODA}$7goHznBFMtx6E^EWZC!~GOivx6dDZBSI5BzZF6~j8_ij^-eYM3oufV@#bk-;!UtQ^QQq#j!Fp|V$V-v5} zNR&$}N;1J_Wz9Ahj~n-TpOo+W2@ai9b=-!6=;DBavaJ@=VpjT+<=Uo00hY)>m(((wfs~ zDwihoDL&85I&I9QdCN&j=Z9sg+wDW&sm>^M=bOfbVYC=94Gbety8X?0ye*?bf&Pq1F@ROo{)!WQvsdOkEpJNmGmK zN4Qqt#FR2Oqu?`rdq?+vB&e8kv02vp)RD~PEoY5q!`C3aG2tY>+U?!^ob%LSB zD;@?zKK>7)`mOT~Szk6-)RdGu73mE-l2z6y55W%%{SMMI z?`uF(&5eIq@{vD3%XEt+*wWtPc!i%JWY9Re$nO6PVUn1ox#T=6F?Z+xm0h{36eWER z9R2>Y&hAlWhf+oePC+mVM4`DUe^(jDtJ?3FM6&fk7}DDg%Vp+RVFZ(*Qs3q)x<8U> z&P+?SKtWY?8+9(amOzEiL3iFg9%_ZWACC9DxThsnM?Qw1(Tl4g!KsAUXRo9J*@n3Mfj0(KgjD252+5n4~0%9ZFa0b2rjd!NT z4KJgm4n<5RhPPj)=C)}HG2w200#UwDW|k>*|G0hwogca|8Don$q-RTJuI4!LZ6PixO$G5)HhTRvW>^FkkldIvGT?+UKi})! z!p#FKJ5L#iQ@Vu+Xo3n^uZTLFbveAhHj*DZN*i$Q<`&SApx(o1WtLxRk~o;bur0p8 z9ifoFBs1!3pjb=Sa;5-gC2lQgY;$NE-p|TB>dBNHyUG#ugE`Z#a~hA@88Wm=CITlD z>!wKLvq#-%BOqkpj|fukAoy4g3bXEv_S_Lu+kxn1ie*j-Rw7HUF2k53dZx{_4GPm3 zHkW;&Sd8tkWzd%HUd(i}FF5t?$FNI8%51&TF%4t#R>Q<5h zuhgqa3<~s7Wsu6*2MLIQDIM5VAA0_Jy83E8@ z%PFe+9tE8tPdIIp9G^yYMX+0gRk5O8(_<@v8tum|>5kDty<(XATl{1+Oay`iM^}AZ zNB%(fcYA)yjS(S!W?Pk@#h3Y(r-2=T@zc#g`PuzNsR1oF5cjUJ$Oo^uly|p<9^zb` z1!%s%DAo|&3Dd^dc%Jpp-4x#rES)D>N(b2VXOb*te`ZfrO|=kZgpYGcK@CowhQ6T> zR2sF2p~ZcMP*H(b3hJ=efs%r{-{DV-=c){ilx3^c1@vX?fa*I^SzSh26DE}y5ydz3<|;&1tuT#PME z%^?jW!>n*w>6Pp;TjAwDL#HJj;?*}-*!aFv?2V%a^S-Ntdj|oLog&?#IzwKJ5~~)& ztmFIp_u5nVQK0D<`ymS*siXMgb(n2-QeZb1`pZ1!Ue@4xMY7{5_V+#aOTg_(-}RYf zrQbq!NUQmN>qX#AwYju`o}Q@5qYdleoN=*9C$14^^EW^9T-+c3{6bovSX?;>(S~&5 z$$O-~KK4ATn*BV`({=fqFw{Ne5Ms)e5DWzRq@_lx>xCoxL7B8>cHiUo~)jHP+1I*a$V*|7yd{>cTamO9V6 z_2e|-AEdKa-a{W+U0&!&9rkRz)h$g5-tLh)yi9FB3FUt^xU=Bn==%>)=vevT{clWE zLEQ`F+$LOZ=F?A!Agm%*lwjVmsN4A6I#=*^|G8h=FZu3p1*@f-mcu|RE} zlu2z@wC_YB@|`C1gy7kx-bAe8-?lKv7S-eQ+?5d~EnOCjU<1(=8rtrU+6xYgusA%+ zjlbEs;-dNE&do&#lgTd03CebBfI~krNV2>>bapF0vZt z+Mdub#x37|_m5vml*wfc&e5c#LT!BQc!g-fi_aa^cJepb*}c5n-K5W!IXdU+^>>_91N^Kb@n)j@%ySR7?p1^y}p5DiX-IsKDfhr7p)w8 zFU);>1l-3oW@ehc@1gu&2T4;nPJbv1{R^5G5j3`$UKg}H z_M$>5fdy4d7vXjyt}5(Cb9}r)fx4QS)0%NomkZF=;9p*-Xd~x1?7CXf>sCpK)lizFv_N7F@% z$Iw;O{_*~D+uXvt;YIIb0xU=&pN?Vyc3lRydwW#svDv%E)3iRi>8T74CexEiV=#M0=?vu{qGf6i#9xruY>-XXsoFrKbsq0Z>+Bi9{rl2MV z+O|WAb42Tl=kak4r1$rUlZq0DgI1@+0l$*!(pn@OPxEhL%qC+s8D=FZp#Qhs!OdsS zy(~%l&9MDICqI8pXW=aB{T!)=8ZSA?3j!hn6^JfIa^4@?e*1@H*wH@-Q;vmwVfUAK z6mM#t`6xUx{%b>v1uN)dj7Al{n3XdSpt{~2KzIHV@805?Hv|^gW~K1w36b>H7hgVW zf`ySU+@v4m4`D4juAvn$u0<)2gHT1!a7~9DV`=nAqH6aOMegc|MisMO2G|#FQ4e!f z@K&`#=M$dWrOte4&~=1E(ACR!21X4A9_M1s7Ow#1Dv6@(8IM(uB)z~cJ*_g}8)opO z*%9gwyK2pDQVRnUA*on;v2vz$_``a3H?r`~9dtqmkwZ%D(i@Fba6{~6x$w~$PT!HDeB2NM3M1ajm3x4`Om;HR2)4l#OQZ#Uz1q6 z@v_)W>n&tVQzBIeM|F8it4e`XwJKI~(qv?BfCqc-^3qK`wa=Jnt(|$e;Jxc}!-0c~ z4&rC>1g$^Id3Y#_v;8w0SGS9;IKjV|m54$E$3{o#x!XmBt#yLh>sy2x(KnZH)LKGm zrr$EYi&r}bN5_*e*=&-lJGBj<{h09+`5zjMny5R2uKd?!c|Q+gC_VS$Pb28+XDkZT)Mc1gV0824DKJ@zGmax>WSdT{<9mrqyYl zsy%HEdPK^w0tA#(mPo2YwOcD31=hP0yQ@QfruO@!`!-7-+i)>O+kr298# z15jZEccG4Hw_+4uoy}*F!QZ^YLn<;|DwSKP&5?f8Cg2u6*-pWZ0$p9^uTEuveiKCU zi~9}f>%LFcEW=6&y#Zsph1c_n-tj{38}}T0~V-r7%>fc>?3t! zlHXIU<0Kgn5r&Anj2wOasom6mOvW_JP1n=QjNro{m$zG3hu-}X4`WphWQFeGlsyCj zQ*oN^lVQhGwT5_}uGhc6K=?@#^sLWq-BmpXe9)JeUpK8MEYP+3wxP_|K}VlQeF$dQ z_9;7c6SPF~^b8(r>R@l$P&_H^{fpSRQ|T?wX)Dc|igAQ2(cQUHU{b%YR56p$!N8a!AZYToU`2w$zw;oA&UT*YqKbq?&GIQ&)J!NgWhjWX)TKwV;CArzQ zIsVoImPFOCNM!#jr1i1$RgwKia+hf9KUVfl$_>*XE%m|GYRd%uVPtk`iN1Bwgeh@H zs9KyPu3y5Pb!=*kS#R{Gws;}(Voy?hS;DXzuP*?7drh)QQ*%NjJ3DabOj_Vi?_y?2 zab%ZZP&3-#mXV|i2dO`MNF=uPsVK{2ipFt>J<*`@#k2DQpAUv&874q_)Y)DAYYpk1 z6!c6hjbz9)NVsvTIp!0&lm|RDAt{QDH0dM7LKxaJVpJs^EJ7JbyWk#)lF;{{(8mS>QmBypHGLVqnH^}&eGOCTJ^+MuAcc7H00`2 z4_RQgwt6f7L;`)oERnJH1o0zm@mj6|)Q3`uJn-A=B`i9q2O?8_b68p0YI`$IGX84M zt4f6f@;a*HSQ`T2jgAg7S z$c~!515mbnG*`~imNHaiUR7Fk*m`lZcyhcips&}&Ef7b%bT)!Vky7s(3G$NRlGXGCrOu)hqF-^uoKL#N)_+KxZKR z+2W^$WDVSf)0x&;Obt*drr^PNN^dJTS;g1^ZM7Hx zOk8mSZBUE2nxK11luWQW+d~8V9gmRvqC1asAazVcmeeeH9 zY0(BN(>%1KHj`cr34qt^mt|H+<0U=vxO>QY~J#3_XiwL{ihDpC5A809emc)vS4( z-O18@bXc=qx$o6nZGLSm^pX%PG)T2z^KG*kw);ttQk)uBNxqY%>u7!Z^fb1VPlBAp z)?01irVL@tO(P0BeIlIzslF(RHvqug)8%0v8ia|Xomx;1+idS>iPl}x!R-kv?@dPv zinQl({9snnC}F3CdN&vzVB#?{loL9Ok-mag7s76yG%=2@`%wf%PwlQdPT~p%|HZA_I-y>IDL`IhnQ81R!XWd2iwtCb9X|Yy= z-EY|u@+hTHUy@>_L2CDbmxFE-i*r23o?zkL6}vRl2ThXZq>jNJvF~Q9?)OwWw-<<6 z1(xg!o1ye6izecz-Og8p2XmlXC`i@C6j~Rt@B2~#I98;kh;zy;v2!eQ6@OqM(wCPi zaJXZRVBsfbE41SA(RvfZJxi_`Cwa0uL^jpZ=H;}RbP%21-P@L&Jn9c_`r{-raeW-n zNrS7*ChVXdnK=0jwp}G%@(caFZRLf%UBz9?r?_YqJV=iJO4p!wqaSWU0h%w(eu|3;NJIGU4ye<|R>crhNL1t517SP3FBHD}V?_haa8 zomG+cKrzAKil9XHH|??UFwHJk#ek6GCQG73mYhHZ@vTqSeP_}K-x-Xx{q~PG!7bz4 zo+*QDA#fk>TO%#+Av@_{W5r{HMnk1e>5nErGWep8j61$M@Y-M5%rj5U6z>1Qqq*pu zm-)%uw~Jsu_dztGBOVp(FULP1xa1QQD_Ca2tmwX<{bS5nyN3g~n&dU;dr|CVH6;-m zytzo!d+uv26?8E>we3m@8WSmm37KqR|L!}(ZY*uHe2m718Uc>h#rdU?{;tH$fITO&Ul=YOfUe9i=QPc)X4ljS#?L}&l-U8HTOZo=Qt zxkzj83W8yvP<6+-7PjDxVyV(cfmIxjN?axG)K}FUuPZBqm6@5Xd`pJ4jiz6xeKAiRB&~9UK$4jP z_K#gS?v7^6vgTU0#-){{{O6~$`wG{JVR?jZFaPQ&Rg(q@Fm%z!b-IsQ?E{84X>Dq& zXmosh@y$-S!L3{CG5!!%%gW8f)mU`|&@v0UW)q}Q#~Os?-8&4IH~3hps%FDum%@_c zr%oLl9=KOV*BjBZ$8lr#;bI>Re2CL`_2WRS&-~sM^~l-Thj>J-EI>_Z!58P29E96j zThn8uUtX$c?686vO}Q=>fUlFbh=^K$N7Ooe2jHFt`!vuJ`gg8GZ}}S~XQ71$ym~_3 z=d9Hy#&JnD@A_%JB{!9JatLs<`?E>4csd@7c zS)t1ZxmbzS*N07uc_tpLX)m^F?zR)RJQ4+ zNluHo&ULGx-uDh(KdPyO82i~qzgCIE6OOS33HfaE8+hRQu0Q7fA1xl&H#(&1*_kS- zLS>paVT(?;HsRDkMSi2jq7)Y#(pUtr&}4OYblT9+(9^WoR;Zh9Lg;AkbT(wtG?E_r zE)t$ZBq4`4EX9QePW9unxp|QTG?a0Lw-(>W0~*{nAl*ir;3j02Gzrc@@F5XhQc+;; z73j{T%CB)OEN3st7HAE7b|Pl&na66)z!MBzrlO+~n=T|961n=xpmDQj2IZU=ltq9| z6=7H!m)9Wlu4Br(g1@dwwaA1pV??3yS*-bvn0Oo>J}DqU>`7Ls+(uHGnQyOhkeF(I zG+eG<*>+yFnBTjMkedr|x;@=Z7)c6*7{jAYhe%Wj<>_ML#At^%68f`!*CWv4XyAY+ z)_WPF5uJTVqT|#f`xRMwz@p{+N_X zlWACMo8o>O2I?aIsdxL(Jdp>5A0DPKapoBT^smK74N1%Ikvzf;mq<|A?9u`vHwqeB zib#{#J-r|p#zlY5%FlCQ9mZ_k&y-tDYrVg^i@FR&@Mw@GYG7i``N%FnV2B#`A3K_c zi9r~P*_2aw5dFnb@sOU`?u)o-u8vM^vJ@5S;{Ktf@lS2n6d>fVEL1WB)W_o*p z%HF!CYqHn3tZ2PY&}5;x`FYz^R#p}e9v;4|rxkpjz*BiXIb1ECH!8aEOQ$ZUZfS?ZExH$GE4yMxXXxjBPPoT1X$=A(`SJa!h1Mz|`mFHI z&AS2yvY&^EVx2{790RW&%$oYmOP($GAdGCY{K|_S{jF}hoLhvM+O#w`Lnd`KCF_Ex zDqzL7e5JP26-L)b;AXls)0I;ocV&jo)Zd)FtQ@o+09x3dVsJ3e`$=VuAnWH#SBjk8 z7O1xWRVA9$QdP^zy}5qwwD@*2%~MU|KDaLhh5mrD^}jc6MR~Ez8sz2eabpPAk7xW zke*I<03%lQ;c>K@B+^CXkLw=XMy-a#rLP~7j@d|!u#fYP~`V|IS= zSS3W$RsWwMAgQD!EQj8~HPo2?rTwCO(a zKC4lrbMN~iT6g0#ImcD4uaJ+`2Td*{YG|0khL^HR)p$!>=75R)g_;Y5Wt^1rK7)|+ z+&cUeRo&h)oJWyEO+F-SdNZ5@=ckP$^MGZNnjJ=*pJkghF0`DYtDQUY(!>UVZKeNIoQtdgZ5U;tL24Rnn~`|{v7fculA1A2RH`?cWN6G5D+M!3+&|`diU1h z2ShD3a*g;IaKUKcsU$#N&n$KZf)v(P*@x!Ama_fi5V=MnY;xW_rM2Sb735db9NhCa zv%|nmEvn>J9~w`TXA=Bxm*-LUad27? zSZ3BcEs^^NtE)RL{&i<_>QtyB_Vi~YuN+gosPD+Njehsr)Xc{nr7DM)XglasH&#r8nUJK&cJMAnP z8jg#i#8k^dZ_^JhT5dNr7-D1NOy&<2r>`d>lY3}^%Sq{rO**tcR$nnJM!2<0I(spW zC5|5Fite}#SEZ|IBLxgDSu#I|wv1K+^H8$3n~uHk8!i_Tm#F6#J>6?haBdY_bG{JY ziil9+;{3)weUFQSgJW{n>I4U8Mn>!IVSm5+LVS18_&n+E_gCo8hd4N&xE?ayT{zOS z-owH9fdBt@2=Koc^WPi-{8yjmKbH*n-ze=rhxs2-fdB4v{>PF5|EpE=AH)2QD8PSt zJ^!bY0sp&g^Pj@}k0`)@dqe++k^%oqyYU~w{EsNWf8C<}XOaQ`Tf_OE!TgUXclP)H z>I%5S{~zb(|Ab^lcY6G9DB#oWv@;F<-OX^G9YJY3m-3!MdG9~)dGIO)hj8%QPvwUD RGXL+N%JLd=RWcvG{6ApH&|?4q diff --git a/public/assets/images/game-icons.psd b/public/assets/images/game-icons.psd index 3c583ac29a8d8d3e412739144827b2e7aa3de733..c73b9b2351627ff5d1f58d13bc0f034b36256f3f 100644 GIT binary patch delta 20587 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 Mz1WVAeKh9(0Ah?Op8x;= delta 6812 zcma)=c{r49^v9pc%sjG8Z;A*}lp@|1WM5MDC1hV(?2UcT(iFv;j5Y48kzJvLv1Dnp zBzu%KUi;cm2;ny#+k0KV-ygs0zV4atInTMzx$pCQ=DB9(eF|sSTaK`!D9i9;7Z30M z3_%czGSfCE>Ia09riGyWFT?NjpP<@Sk{9TbInub@J)|0OCr8V@~1nSPc^;xuX-ev+4 z7ebv0(r!%IZ>&{Zrhmjn`-vGojJ+8imE3xEC4@~M=M*i@eSnz3<^PWXi{vTAsTVn& zC!!l-#By@^etl%8b04YE(;t7*IcToogtKRp?Vg%JEkY~9u0ISjzgQpYvz@2+nTn;h z{PvEPHr34B8WuU4D^1}0nR$Wzl)T}zf?P>?e|2%;60o(D`*0l;=HPg^sBAuUSC*-2 zq&BoZ!z$Sqy=mB|0Lw;+b~773*kOP(g&XN$)%K5AW+vwG9b zo7XOU@*pb+h*Z0TNk;iU&*W!xchPZ5&d3Rgc`z$1 zH$FtTh<{Z7PK+d*TZ`@iK_b4)@}a-IQ+O@Ci|3-W&nO}Jc1Kriq(PJI^ha8* z_)E1F@#VSbV1_CGdPND2clUe5J{no3SiGa(tDt_$rvCb!ss^G@E|$3KGllEIsl&WMBFp?a#Z9NA@IARqd=|qY zQdxQZv+ek(iAQRL($Xg5E<^Xd70=Y}7c-f!Lq0e1W*cReG}R;Ud^tAdfhu}VcDWs0 zc^N)0T!zACj+Qvk^Vkf|oXgN`Z|N&YGd^b|H();Vphe@TT97aGL33J{T`4*=6`+Vqp<;|tptD=A79vtyC@)ckB6Q20UjbYR?-z2q6 zr2W0x84HYR2vsTCDAg_V+=o@G)Gf-SQ1)1%T) z&^Lt$$hS<_FgNZ!(ue*delTUUdqhL3?o?f!0-8&AlHb8cx0lE`#n`<_gzsg|J66};ddMQBwI!Z|rzyXyWKxnv?Rl1|Jhd29yU0cjR}~yPyQ2tdOFBkm!mE@g%}(9ZyuvABiy2Q9oLL-r!pdLIPTjS4c!e(f<41V7 z^r`;Z!QMGTsnrJEj`sbA3r2%Qj_S*rNi)KFJwugJhuS){ioze?R2z78FVO0nRX@XX zHSN~K5JQKlwhqawz2ZLE?$!C(O1I4DIL7@(u?3-QWdu=?q1+k&5)*9Z>$7hQ$gw%E z?UK*T)H*o{NOdl(L!*rRU71>AzBaZcx*FQzwFThn>ya6y z>Xmn^NccjC%}BqhTWsd%H&w^wN=(!Yn5u0wC^jcM?)^FJ93xy%X~V~;<~Ph}tYtKw zYWt;)WR`Bd$7HT>NIFa&i&dzgnRZ=>yL#uLo^ZOa@oIGGNt+RlvQsytOA^(MT|%Yq zKzfZ&zQvm-9D-@FsxRvH(6Nj(=A-3HZmOoQgIY0UIOvvFZOHcY6 z{G9$I9w(6ns;AP2B}FPtavht}?7L338H^_#{6(18EXhrGJz9221OHN~swQ=R6X$Iy zA}{S>mpb;i`p;zvN@Ftu8BxzV1?|IA_bjmn_%`t*kNzmD-T`9R&v&twBzd_X2wtrlNY?xQ zMW^8_K_K}{7cp-g5)Pt1mD5}j>QpMF^)-Nm#<8i~ZalLN#q(JYOjR)GD7d~395edx zF8A=aEd6-X3kKEK)J=!$)!a!W#r6duM)a|Cp7)Al{;$w+PKmzioF%F8bWZQa#-6N{ zPbNqT3GtVv$0j_Ul|65P557@VOY8a8#!R7ti@;Lzz`$6LvHw?4n}r+wCGGtCAN4vv zL|j}vOXR-rr-~^aMP?$Y%}4!ISF>tvu=NO3uVYavf5!8Hxo6txNPnWU$Y>(tUnC}* zh#I@6cD2e7Q?7SuxCwY&b=mdeJ$b!33X! zyhU2e9;2n*SrOwR$1^Hz0jxf6rRJI*A5=#WC|@DkK7d0k7;yPr~(Dsi>wm^hJPIbbHsG@p ztE!m4#s>>J2+%v#RaJ5E_T~2$tYx=dF*!NOPx^Ey_+b)#1dpPK2s)l^*1vX9Qxe}Y zEt7>ws8cCwSq*@zi7 z3({-@S^=vLDbwAPr5@=y!Y3!wLq^fjwMKu@xq3R5JWVl>+ypd1RqVPrJ^_k_A zFrQbySvc;NdZ@9a&Ae*PAGb((vCI@uWf9EKj6J)^;Xqq<(CIzv&4)xHkr{7z23o;5 zB-HZ<@_JQDG8tvVF}WI}Zseq-=H7j4q=Hf9_A`q;voPcvN_&p;>>;hTwpQ)@ z#AxcI2mW*+!q~!;DHz3cHS#EfQDoBoCkF`Yogx>N)X)bhzo{VzO_}FkhcWP=Q0F6y z4{%a*k3eYdzV-Uo{RhImBJ;#A?GM<9({*+=vvshyqR0mk7YMH}hhk~`8{z^R;!u>i zhtv>9<@A(vQyaYxrAG%bLnooLkOE{5IY9)72&F=KPz}@veTPP&F=!TAfaalfXbnY; z`U`aswI8(?MUSGPyh6}2M5aV^K%by@P%%^p-jto1(gwfFev@$2EWO@A<`5y5a_HVh)56UCg~k|v@U8F({f z7`zw7m~0u7Kv4{HYs;7d-C`Ke9pkPzCSb=nFM&zeHliglncEt4Nn)yYj7BL;CsHvA zbW3Bp5DCDz4CY@%#(;HM%pfA;0FxYMih5&9aqD~wK=lOrFwnk)`LcD@=rV?k$ap}I z$1Ec<5#%Uf+R?{WN1K7lIW!x6-lv7tjSR`_oWIEc#e-%CzZEg%C@xT>gyBZkBm-Jy z%n<50AS+`|YP9LiyVY(J>@Td1CXnQSwY-UpjR6+kH|=X)xk_6G8`P&-8y_25Yxl7 zAl?ulu8;YM$Y3B~fGJ005MVLHyhdao_-%-JiO2xZVuVTGYBm`p8t>c^GPq%a3EjH# z12C9kRCf%5DMkWW{up$dVlE)kk2K%|moNcbCYqi!>4sry;n;-ZKU_I@K8pGeS6T|# zZLWX@HX3%Ge#QK#&SHYb(JNuu#SB zf@PqF-3H529ovf>0ss#U>^4}$E7)Pg8wb)gu{&Umg7Q-oum-iT+h9#^4~6tgvqpZxHxkjV(lEAV{;>k^#W~7Iqgb4gAhMAp-_mY}gJAx(~tHi!QpDiNHqfHxS!S#F&-8QiplDU7w) z^MjM3Xb$+(SA;R}#0nm!kafoz-X^Qv8lI$(_0|U7CX3}3yhD}=9^T?6fdp*fod;E$ z9Sm>tgmZwmdCIu#xaE!lo=)&KPtTm;O%TJudlz^F*>o7_c7?Zj>UV={5pOW)aEGf9 zN#V%@CLuBqqh$fQA?|EHuhHOf!#2x`+G4AdrI4$Ou@1l|)H{Y7N%1bhnK3>gL^6Y!-iV-ko> z!k4#R8t>mUHMuF}GiPB1Y=reXutOR&;b%YOilWmtJD;0M$M`l_i;fM?4v1CstR__(}5 O5oNU>iFO4pX8Iqp4ZVl} diff --git a/public/src/games/hexsweeper/HexsweeperGame.js b/public/src/games/hexsweeper/HexsweeperGame.js new file mode 100644 index 0000000..9ae79ce --- /dev/null +++ b/public/src/games/hexsweeper/HexsweeperGame.js @@ -0,0 +1,438 @@ +import * as Phaser from 'phaser'; +import { GAME_WIDTH, GAME_HEIGHT, COLORS } from '../../config.js'; +import { Button } from '../../ui/Button.js'; +import { MusicPlayer } from '../../ui/MusicPlayer.js'; +import { playSound, SFX } from '../../ui/Sounds.js'; +import { api } from '../../services/api.js'; +import { + DIFFICULTIES, DIFFICULTY_ORDER, newGame, reveal, toggleFlag, chord, minesRemaining, +} from './HexsweeperLogic.js'; + +// Scene / board theme — a cool slate felt to read as a classic Minesweeper grid. +const FELT = 0x12202b; +const HIDDEN = 0x2c6e8f; // raised, un-revealed hex +const HIDDEN_HI = 0x3d8bb0; // hover +const REVEALED = 0x18313f; // recessed, revealed hex +const REVEAL_LN = 0x0c1a23; +const FLAG_RED = '#ff5252'; +const MINE_HEX = 0x1c3a49; +const BOOM_HEX = 0xc0392b; +const WRONG_HEX = 0x6b3b3b; + +// Classic adjacency palette, brightened for the dark felt (counts run 1..6 on hex). +const NUM_COLORS = ['', '#5b9bff', '#45d17a', '#ff6b6b', '#c792ff', '#ffb454', '#4ec1c1']; + +const D = { felt: -2, hexBase: 0, glyph: 1, ui: 30, overlay: 60, overlayUI: 62 }; + +const ROOT3 = Math.sqrt(3); + +export default class HexsweeperGame extends Phaser.Scene { + constructor() { super('HexsweeperGame'); } + + init(data) { + this.gameDef = data.game ?? { slug: 'hexsweeper', name: 'Hexsweeper' }; + this.view = 'select'; + this.g = null; // logic state + this.difficulty = 'easy'; + this.flagMode = false; + this.elapsed = 0; + this.timerEvent = null; + this.overlayUp = false; + this.cellGfx = []; + this.cellLabel = []; + } + + create() { + try { + const music = this.cache.json.get('music'); + if (music?.tracks) new MusicPlayer(this, music.tracks); + } catch (_) { /* optional */ } + + // Right-click should flag, not open the browser context menu. + if (this.input.mouse) this.input.mouse.disableContextMenu(); + + this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(D.felt); + this.layer = this.add.container(0, 0); + this.showDifficultySelect(); + } + + clearLayer() { + if (this.timerEvent) { this.timerEvent.remove(false); this.timerEvent = null; } + this.layer.removeAll(true); + this.cellGfx = []; + this.cellLabel = []; + this.minesText = null; + this.timerText = null; + this.flagBtn = null; + } + + // ── Difficulty select ───────────────────────────────────────────────────────── + + showDifficultySelect() { + this.view = 'select'; + this.overlayUp = false; + this.clearLayer(); + const cx = GAME_WIDTH / 2; + + const title = this.add.text(cx, 150, 'HEXSWEEPER', { + fontFamily: 'Righteous', fontSize: '78px', color: COLORS.goldHex, + }).setOrigin(0.5); + const sub = this.add.text(cx, 224, 'Clear every hex without striking a mine. Each cell counts the mines among its six neighbours.', { + fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.mutedHex, + }).setOrigin(0.5); + const pick = this.add.text(cx, 312, 'Choose a difficulty', { + fontFamily: 'Righteous', fontSize: '32px', color: COLORS.textHex, + }).setOrigin(0.5); + this.layer.add([title, sub, pick]); + + const TILE_W = 360; + const TILE_H = 220; + const GAP = 40; + const totalW = DIFFICULTY_ORDER.length * TILE_W + (DIFFICULTY_ORDER.length - 1) * GAP; + const left = cx - totalW / 2 + TILE_W / 2; + const y = 540; + const accents = { easy: 0x45d17a, medium: 0x5b9bff, hard: 0xffb454, legendary: 0xff5252 }; + + DIFFICULTY_ORDER.forEach((key, i) => { + const def = DIFFICULTIES[key]; + const x = left + i * (TILE_W + GAP); + const stroke = accents[key]; + + const tile = this.add.rectangle(x, y, TILE_W, TILE_H, 0x16303d).setStrokeStyle(3, stroke, 1); + const name = this.add.text(x, y - 64, def.label, { + fontFamily: 'Righteous', fontSize: '46px', color: COLORS.textHex, + }).setOrigin(0.5); + const dims = this.add.text(x, y + 6, `${def.cols} × ${def.rows} grid`, { + fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.mutedHex, + }).setOrigin(0.5); + const mines = this.add.text(x, y + 56, `${def.mines} mines`, { + fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.goldHex, + }).setOrigin(0.5); + this.layer.add([tile, name, dims, mines]); + + tile.setInteractive({ useHandCursor: true }); + tile.on('pointerover', () => tile.setStrokeStyle(5, stroke, 1)); + tile.on('pointerout', () => tile.setStrokeStyle(3, stroke, 1)); + tile.on('pointerup', () => this.startGame(key)); + }); + + const back = new Button(this, cx, GAME_HEIGHT - 110, 'Back', () => this.scene.start('GameMenu'), + { variant: 'ghost', width: 220, height: 60, fontSize: 24 }); + this.layer.add(back); + + const tip = this.add.text(cx, GAME_HEIGHT - 200, 'Left-click reveals · Right-click flags · Click a satisfied number to chord', { + fontFamily: '"Julius Sans One"', fontSize: '20px', color: COLORS.mutedHex, + }).setOrigin(0.5); + this.layer.add(tip); + } + + // ── Start / restart a board ─────────────────────────────────────────────────── + + startGame(difficulty) { + this.view = 'play'; + this.difficulty = difficulty; + this.g = newGame(difficulty); + this.flagMode = false; + this.elapsed = 0; + this.overlayUp = false; + + this.clearLayer(); + this.computeLayout(); + this.buildBoard(); + this.drawHud(); + this.renderAll(); + } + + // Fit the board into the area right of the button strip, scaling the hex size + // so even Legendary (20×16) lands fully on screen. + computeLayout() { + const g = this.g; + const LEFT_STRIP = 300; + const TOP = 150; + const BOTTOM = GAME_HEIGHT - 50; + const RIGHT = GAME_WIDTH - 50; + + const availW = RIGHT - LEFT_STRIP; + const availH = BOTTOM - TOP; + // width = (cols + 0.5) * (√3 · size); height = (1.5·rows + 0.5) · size + const sizeW = availW / ((g.cols + 0.5) * ROOT3); + const sizeH = availH / (1.5 * g.rows + 0.5); + this.size = Math.min(sizeW, sizeH, 58); + this.w = ROOT3 * this.size; // hex width / column spacing + this.rowStep = 1.5 * this.size; // vertical spacing + + const regionCx = (LEFT_STRIP + RIGHT) / 2; + const regionCy = (TOP + BOTTOM) / 2; + this.originX = regionCx - (g.cols - 1) * this.w / 2; + this.originY = regionCy - (g.rows - 1) * this.rowStep / 2; + } + + hexCenter(col, row) { + return { + x: this.originX + col * this.w + ((row & 1) ? this.w / 2 : 0), + y: this.originY + row * this.rowStep, + }; + } + + hexPointsLocal() { + const pts = []; + for (let i = 0; i < 6; i++) { + const ang = (Math.PI / 180) * (60 * i - 30); // pointy-top: vertices top & bottom + pts.push({ x: this.size * Math.cos(ang), y: this.size * Math.sin(ang) }); + } + return pts; + } + + buildBoard() { + const g = this.g; + const local = this.hexPointsLocal(); + const flat = []; + for (const p of local) flat.push(p.x, p.y); + + for (let r = 0; r < g.rows; r++) { + this.cellGfx[r] = []; + this.cellLabel[r] = []; + for (let c = 0; c < g.cols; c++) { + const { x, y } = this.hexCenter(c, r); + const gfx = this.add.graphics({ x, y }).setDepth(D.hexBase); + gfx.setInteractive(new Phaser.Geom.Polygon(flat), Phaser.Geom.Polygon.Contains); + gfx._col = c; gfx._row = r; + gfx.on('pointerover', () => { gfx._hover = true; this.drawCell(c, r); }); + gfx.on('pointerout', () => { gfx._hover = false; this.drawCell(c, r); }); + gfx.on('pointerdown', (pointer) => this.onCellDown(c, r, pointer)); + this.layer.add(gfx); + this.cellGfx[r][c] = gfx; + + const label = this.add.text(x, y, '', { + fontFamily: 'Righteous', fontSize: `${Math.round(this.size * 0.95)}px`, color: '#ffffff', + }).setOrigin(0.5).setDepth(D.glyph); + this.layer.add(label); + this.cellLabel[r][c] = label; + } + } + } + + drawHud() { + const stripCx = 150; + + const title = this.add.text(40, 70, 'HEXSWEEPER', { + fontFamily: 'Righteous', fontSize: '40px', color: COLORS.goldHex, + }).setOrigin(0, 0.5).setDepth(D.ui); + const diff = this.add.text(40, 112, DIFFICULTIES[this.difficulty].label, { + fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.mutedHex, + }).setOrigin(0, 0.5).setDepth(D.ui); + this.layer.add([title, diff]); + + this.minesText = this.add.text(GAME_WIDTH - 360, 88, '', { + fontFamily: 'Righteous', fontSize: '34px', color: FLAG_RED, + }).setOrigin(0, 0.5).setDepth(D.ui); + this.timerText = this.add.text(GAME_WIDTH - 50, 88, '', { + fontFamily: 'Righteous', fontSize: '34px', color: COLORS.textHex, + }).setOrigin(1, 0.5).setDepth(D.ui); + this.layer.add([this.minesText, this.timerText]); + + const BTN_W = 220; + const BTN_H = 58; + const BTN_GAP = 16; + const totalH = 3 * BTN_H + 2 * BTN_GAP; + let btnY = GAME_HEIGHT / 2 - totalH / 2; + + this.flagBtn = new Button(this, stripCx, btnY, '🚩 Flag: Off', () => this.toggleFlagMode(), + { width: BTN_W, height: BTN_H, fontSize: 22, variant: 'ghost' }); + btnY += BTN_H + BTN_GAP; + const restart = new Button(this, stripCx, btnY, 'New Game', () => this.startGame(this.difficulty), + { width: BTN_W, height: BTN_H, fontSize: 22 }); + btnY += BTN_H + BTN_GAP; + const diffBtn = new Button(this, stripCx, btnY, 'Difficulty', () => this.showDifficultySelect(), + { width: BTN_W, height: BTN_H, fontSize: 22, variant: 'ghost' }); + this.layer.add([this.flagBtn, restart, diffBtn]); + + this.updateHud(); + } + + updateHud() { + if (this.minesText) this.minesText.setText(`🚩 ${minesRemaining(this.g)}`); + if (this.timerText) { + const m = Math.floor(this.elapsed / 60); + const s = String(this.elapsed % 60).padStart(2, '0'); + this.timerText.setText(`⏱ ${m}:${s}`); + } + } + + toggleFlagMode() { + this.flagMode = !this.flagMode; + if (this.flagBtn) { + this.flagBtn.setLabel(this.flagMode ? '🚩 Flag: On' : '🚩 Flag: Off').setActive(this.flagMode); + } + } + + startTimer() { + if (this.timerEvent) return; + this.timerEvent = this.time.addEvent({ + delay: 1000, loop: true, + callback: () => { this.elapsed++; this.updateHud(); }, + }); + } + + stopTimer() { + if (this.timerEvent) { this.timerEvent.remove(false); this.timerEvent = null; } + } + + // ── Input ───────────────────────────────────────────────────────────────────── + + onCellDown(col, row, pointer) { + if (this.overlayUp || this.g.state === 'won' || this.g.state === 'lost') return; + + const flag = (pointer && pointer.rightButtonDown && pointer.rightButtonDown()) || this.flagMode; + if (flag) { + if (toggleFlag(this.g, col, row)) { + playSound(this, SFX.PIECE_CLICK); + this.drawCell(col, row); + this.updateHud(); + } + return; + } + + const cell = this.g.board[row][col]; + if (cell.flagged) return; + + const wasReady = !this.g.firstClickDone; + let changed; + if (cell.revealed && cell.count > 0) { + changed = chord(this.g, col, row); + } else { + changed = reveal(this.g, col, row); + } + if (wasReady) this.startTimer(); + + if (this.g.state === 'lost') { + playSound(this, SFX.SCIFI_EXPLODE); + this.renderAll(); + this.endGame(false); + return; + } + + if (changed.length) playSound(this, changed.length > 1 ? SFX.CARD_DEAL : SFX.PIECE_CLICK); + for (const [c, r] of changed) this.drawCell(c, r); + this.updateHud(); + + if (this.g.state === 'won') { + playSound(this, SFX.VICTORY_SHORT); + this.endGame(true); + } + } + + // ── Rendering ───────────────────────────────────────────────────────────────── + + renderAll() { + for (let r = 0; r < this.g.rows; r++) { + for (let c = 0; c < this.g.cols; c++) this.drawCell(c, r); + } + } + + drawCell(col, row) { + const cell = this.g.board[row][col]; + const gfx = this.cellGfx[row][col]; + const label = this.cellLabel[row][col]; + const local = this.hexPointsLocal(); + const over = this.g.state === 'won' || this.g.state === 'lost'; + + let fill = HIDDEN; + let stroke = 0x0d2330; + let strokeW = 2; + let glyph = ''; + let glyphColor = '#ffffff'; + + if (cell.revealed) { + if (cell.mine) { + const isBoom = this.g.exploded && this.g.exploded[0] === col && this.g.exploded[1] === row; + fill = isBoom ? BOOM_HEX : MINE_HEX; + stroke = REVEAL_LN; + glyph = '✸'; + glyphColor = isBoom ? '#ffffff' : '#ff8a8a'; + } else { + fill = REVEALED; + stroke = REVEAL_LN; + if (cell.count > 0) { glyph = String(cell.count); glyphColor = NUM_COLORS[cell.count]; } + } + } else if (over && cell.mine && !cell.flagged) { + // Reveal remaining mines on game over. + fill = MINE_HEX; stroke = REVEAL_LN; glyph = '✸'; glyphColor = '#ff8a8a'; + } else if (cell.flagged) { + if (over && !cell.mine) { fill = WRONG_HEX; glyph = '✗'; glyphColor = '#ffd5d5'; } + else { fill = gfx._hover && !over ? HIDDEN_HI : HIDDEN; glyph = '🚩'; glyphColor = FLAG_RED; } + } else { + fill = (gfx._hover && !over) ? HIDDEN_HI : HIDDEN; + } + + gfx.clear(); + gfx.fillStyle(fill, 1); + gfx.beginPath(); + gfx.moveTo(local[0].x, local[0].y); + for (let i = 1; i < local.length; i++) gfx.lineTo(local[i].x, local[i].y); + gfx.closePath(); + gfx.fillPath(); + // Subtle top bevel highlight on raised (hidden) hexes. + if (!cell.revealed && !(over && cell.mine)) { + gfx.fillStyle(0xffffff, 0.10); + gfx.beginPath(); + gfx.moveTo(local[5].x, local[5].y); + gfx.lineTo(local[0].x, local[0].y); + gfx.lineTo(local[1].x, local[1].y); + gfx.lineTo(local[1].x * 0.6, local[1].y * 0.6); + gfx.lineTo(local[5].x * 0.6, local[5].y * 0.6); + gfx.closePath(); + gfx.fillPath(); + } + gfx.lineStyle(strokeW, stroke, 1); + gfx.beginPath(); + gfx.moveTo(local[0].x, local[0].y); + for (let i = 1; i < local.length; i++) gfx.lineTo(local[i].x, local[i].y); + gfx.closePath(); + gfx.strokePath(); + + label.setText(glyph).setColor(glyphColor); + } + + // ── End of game ─────────────────────────────────────────────────────────────── + + endGame(won) { + this.overlayUp = true; + this.stopTimer(); + + api.post('/history/single-player', { + slug: 'hexsweeper', score: this.elapsed, opponentScores: [], result: won ? 'win' : 'loss', + }).catch(() => { /* best effort */ }); + + const cx = GAME_WIDTH / 2; + const cy = GAME_HEIGHT / 2; + const dim = this.add.rectangle(cx, cy, GAME_WIDTH, GAME_HEIGHT, 0x000000, 0.62).setDepth(D.overlay).setInteractive(); + this.layer.add(dim); + + const panel = this.add.graphics().setDepth(D.overlay); + panel.fillStyle(COLORS.panel, 0.98); + panel.fillRoundedRect(cx - 320, cy - 200, 640, 400, 20); + panel.lineStyle(3, won ? 0x45d17a : COLORS.danger, 1); + panel.strokeRoundedRect(cx - 320, cy - 200, 640, 400, 20); + this.layer.add(panel); + + const m = Math.floor(this.elapsed / 60); + const s = String(this.elapsed % 60).padStart(2, '0'); + const title = this.add.text(cx, cy - 120, won ? 'Cleared!' : 'Boom!', { + fontFamily: 'Righteous', fontSize: '72px', color: won ? '#45d17a' : COLORS.dangerHex, + }).setOrigin(0.5).setDepth(D.overlayUI); + const stat = this.add.text(cx, cy - 30, + won + ? `You swept the ${DIFFICULTIES[this.difficulty].label} field in ${m}:${s}.` + : `You hit a mine after ${m}:${s}.`, { + fontFamily: '"Julius Sans One"', fontSize: '28px', color: COLORS.textHex, align: 'center', + }).setOrigin(0.5).setDepth(D.overlayUI); + this.layer.add([title, stat]); + + const again = new Button(this, cx - 170, cy + 110, 'New Game', () => this.startGame(this.difficulty), + { width: 280, height: 60, fontSize: 26 }).setDepth(D.overlayUI); + const diff = new Button(this, cx + 170, cy + 110, 'Difficulty', () => this.showDifficultySelect(), + { width: 280, height: 60, fontSize: 26, variant: 'ghost' }).setDepth(D.overlayUI); + this.layer.add([again, diff]); + } +} diff --git a/public/src/games/hexsweeper/HexsweeperLogic.js b/public/src/games/hexsweeper/HexsweeperLogic.js new file mode 100644 index 0000000..ab18f56 --- /dev/null +++ b/public/src/games/hexsweeper/HexsweeperLogic.js @@ -0,0 +1,201 @@ +// Hexsweeper — pure board model for a hexagonal Minesweeper. No Phaser, no DOM. +// Self-contained so it can be unit-tested in Node and reused by the scene. +// +// Layout: "odd-r" offset coordinates over pointy-top hexagons. A cell is (col, row) +// with col = 0 left .. cols-1 right, row = 0 top .. rows-1 bottom. Odd rows are +// shifted half a hex to the RIGHT, which gives every interior cell exactly six +// neighbours (so adjacency counts run 0..6, versus 0..8 for square Minesweeper). +// +// A cell: { mine, count, revealed, flagged } +// Mines are placed lazily on the first reveal so the opening click (and the ring +// around it) is always safe — classic Minesweeper behaviour. + +export const DIFFICULTIES = { + easy: { key: 'easy', label: 'Easy', cols: 8, rows: 8, mines: 8 }, + medium: { key: 'medium', label: 'Medium', cols: 12, rows: 10, mines: 20 }, + hard: { key: 'hard', label: 'Hard', cols: 16, rows: 13, mines: 44 }, + legendary: { key: 'legendary', label: 'Legendary', cols: 20, rows: 16, mines: 80 }, +}; + +export const DIFFICULTY_ORDER = ['easy', 'medium', 'hard', 'legendary']; + +// Neighbour column/row deltas, indexed by row parity (0 = even, 1 = odd). +const NEIGHBOR_DELTAS = [ + // even rows (no shift): the two cells above/below sit to the upper/lower LEFT + [[+1, 0], [-1, 0], [0, -1], [-1, -1], [0, +1], [-1, +1]], + // odd rows (shifted right): the two cells above/below sit to the upper/lower RIGHT + [[+1, 0], [-1, 0], [0, -1], [+1, -1], [0, +1], [+1, +1]], +]; + +export function inBounds(col, row, cols, rows) { + return col >= 0 && col < cols && row >= 0 && row < rows; +} + +// Up to six in-bounds neighbours of (col, row) as [col, row] pairs. +export function neighbors(col, row, cols, rows) { + const out = []; + for (const [dc, dr] of NEIGHBOR_DELTAS[row & 1]) { + const nc = col + dc; + const nr = row + dr; + if (inBounds(nc, nr, cols, rows)) out.push([nc, nr]); + } + return out; +} + +function makeCell() { + return { mine: false, count: 0, revealed: false, flagged: false }; +} + +// Fresh, fully-hidden board with no mines yet (placed on the first reveal). +export function newGame(difficulty) { + const def = DIFFICULTIES[difficulty] ?? DIFFICULTIES.easy; + const board = Array.from({ length: def.rows }, () => + Array.from({ length: def.cols }, () => makeCell())); + return { + difficulty: def.key, + cols: def.cols, + rows: def.rows, + mines: def.mines, + board, + state: 'ready', // 'ready' | 'playing' | 'won' | 'lost' + flagsUsed: 0, + revealedCount: 0, + firstClickDone: false, + exploded: null, // [col, row] of the detonated mine, when lost + }; +} + +export function cellAt(g, col, row) { + return g.board[row][col]; +} + +export function minesRemaining(g) { + return g.mines - g.flagsUsed; +} + +// Place `g.mines` mines uniformly at random, never on the safe pocket +// (the clicked cell and its neighbours), then compute every cell's count. +function placeMines(g, safeCol, safeRow) { + const safe = new Set([`${safeCol},${safeRow}`]); + for (const [nc, nr] of neighbors(safeCol, safeRow, g.cols, g.rows)) { + safe.add(`${nc},${nr}`); + } + + // Candidate cells, excluding the safe pocket. If a board were ever too dense + // for the full pocket (it isn't, for our tiers), fall back to only the click. + let candidates = []; + for (let r = 0; r < g.rows; r++) { + for (let c = 0; c < g.cols; c++) { + if (!safe.has(`${c},${r}`)) candidates.push([c, r]); + } + } + if (candidates.length < g.mines) { + candidates = []; + for (let r = 0; r < g.rows; r++) { + for (let c = 0; c < g.cols; c++) { + if (c !== safeCol || r !== safeRow) candidates.push([c, r]); + } + } + } + + // Fisher–Yates partial shuffle to pick the first `mines` candidates. + for (let i = 0; i < g.mines; i++) { + const j = i + Math.floor(Math.random() * (candidates.length - i)); + const tmp = candidates[i]; candidates[i] = candidates[j]; candidates[j] = tmp; + const [c, r] = candidates[i]; + g.board[r][c].mine = true; + } + + for (let r = 0; r < g.rows; r++) { + for (let c = 0; c < g.cols; c++) { + if (g.board[r][c].mine) continue; + let n = 0; + for (const [nc, nr] of neighbors(c, r, g.cols, g.rows)) { + if (g.board[nr][nc].mine) n++; + } + g.board[r][c].count = n; + } + } +} + +// Flood-fill reveal from (col, row). Stepping onto a mine loses the game. +// Returns the list of newly revealed [col, row] cells (for animation). +export function reveal(g, col, row) { + if (g.state === 'won' || g.state === 'lost') return []; + if (!g.firstClickDone) { + placeMines(g, col, row); + g.firstClickDone = true; + g.state = 'playing'; + } + + const cell = g.board[row][col]; + if (cell.revealed || cell.flagged) return []; + + if (cell.mine) { + cell.revealed = true; + g.exploded = [col, row]; + g.state = 'lost'; + return [[col, row]]; + } + + const changed = []; + const stack = [[col, row]]; + while (stack.length) { + const [c, r] = stack.pop(); + const cur = g.board[r][c]; + if (cur.revealed || cur.flagged || cur.mine) continue; + cur.revealed = true; + g.revealedCount++; + changed.push([c, r]); + if (cur.count === 0) { + for (const [nc, nr] of neighbors(c, r, g.cols, g.rows)) { + const nb = g.board[nr][nc]; + if (!nb.revealed && !nb.flagged && !nb.mine) stack.push([nc, nr]); + } + } + } + + checkWin(g); + return changed; +} + +// Toggle a flag on a hidden cell. Returns true if the flag state changed. +export function toggleFlag(g, col, row) { + if (g.state === 'won' || g.state === 'lost') return false; + const cell = g.board[row][col]; + if (cell.revealed) return false; + cell.flagged = !cell.flagged; + g.flagsUsed += cell.flagged ? 1 : -1; + return true; +} + +// "Chord": on a revealed number whose adjacent flag count equals its value, +// reveal every non-flagged neighbour. A misplaced flag can detonate a mine. +// Returns the list of newly revealed cells (empty if the chord wasn't valid). +export function chord(g, col, row) { + if (g.state !== 'playing') return []; + const cell = g.board[row][col]; + if (!cell.revealed || cell.count === 0) return []; + + const nbrs = neighbors(col, row, g.cols, g.rows); + let flags = 0; + for (const [nc, nr] of nbrs) if (g.board[nr][nc].flagged) flags++; + if (flags !== cell.count) return []; + + let changed = []; + for (const [nc, nr] of nbrs) { + const nb = g.board[nr][nc]; + if (nb.revealed || nb.flagged) continue; + changed = changed.concat(reveal(g, nc, nr)); + if (g.state === 'lost') break; + } + return changed; +} + +// Win once every non-mine cell is revealed. +export function checkWin(g) { + if (g.state !== 'playing') return g.state === 'won'; + const total = g.cols * g.rows; + if (g.revealedCount === total - g.mines) g.state = 'won'; + return g.state === 'won'; +} diff --git a/public/src/main.js b/public/src/main.js index e3e6c97..d0fed6d 100644 --- a/public/src/main.js +++ b/public/src/main.js @@ -62,6 +62,7 @@ import MonopolyGame from './games/monopoly/MonopolyGame.js'; import TriominoesGame from './games/triominoes/TriominoesGame.js'; import FreecellGame from './games/freecell/FreecellGame.js'; import RushHourGame from './games/rushhour/RushHourGame.js'; +import HexsweeperGame from './games/hexsweeper/HexsweeperGame.js'; const config = { type: Phaser.AUTO, @@ -137,6 +138,7 @@ const config = { TriominoesGame, FreecellGame, RushHourGame, + HexsweeperGame, ], }; diff --git a/public/src/scenes/GameRoomScene.js b/public/src/scenes/GameRoomScene.js index c0c29db..ee83d87 100644 --- a/public/src/scenes/GameRoomScene.js +++ b/public/src/scenes/GameRoomScene.js @@ -22,7 +22,7 @@ export default class GameRoomScene extends Phaser.Scene { } create() { - const slugDispatch = { backgammon: 'Backgammon', holdem: 'HoldemGame', blackjack: 'BlackjackGame', parchisi: 'ParchisiGame', yatzi: 'YatziGame', skipbo: 'SkipBoGame', phase10: 'Phase10Game', chinesecheckers: 'ChineseCheckersGame', gofish: 'GoFishGame', uno: 'UnoGame', craps: 'CrapsGame', roulette: 'RouletteGame', mexicantrain: 'MexicanTrainGame', hearts: 'HeartsGame', catan: 'CatanGame', tickettoride: 'TicketToRideGame', nerts: 'NertsGame', bingo: 'BingoGame', baccarat: 'BaccaratGame', dominion: 'DominionGame', checkers: 'CheckersGame', chess: 'ChessGame', wordle: 'WordleGame', scrabble: 'ScrabbleGame', ghost: 'GhostGame', wordladder: 'WordLadderGame', wordsearch: 'WordSearchGame', hangman: 'HangmanGame', sudoku: 'SudokuGame', othello: 'OthelloGame', go: 'GoGame', battleship: 'BattleshipGame', mastermind: 'MastermindGame', connect4: 'Connect4Game', boggle: 'BoggleGame', oldmaid: 'OldMaidGame', blokus: 'BlokusGame', spellingbee: 'SpellingBeeGame', minicrossword: 'MiniCrosswordGame', forbiddenisland: 'ForbiddenIslandGame', solitairetour: 'SolitaireTourGame', splendor: 'SplendorGame', tectonic: 'TectonicGame', labyrinth: 'LabyrinthGame', videopoker: 'VideoPokerGame', farkel: 'FarkelGame', stratego: 'StrategoGame', kiitos: 'KiitosGame', monopoly: 'MonopolyGame', triominoes: 'TriominoesGame', freecell: 'FreecellGame', rushhour: 'RushHourGame' }; + const slugDispatch = { backgammon: 'Backgammon', holdem: 'HoldemGame', blackjack: 'BlackjackGame', parchisi: 'ParchisiGame', yatzi: 'YatziGame', skipbo: 'SkipBoGame', phase10: 'Phase10Game', chinesecheckers: 'ChineseCheckersGame', gofish: 'GoFishGame', uno: 'UnoGame', craps: 'CrapsGame', roulette: 'RouletteGame', mexicantrain: 'MexicanTrainGame', hearts: 'HeartsGame', catan: 'CatanGame', tickettoride: 'TicketToRideGame', nerts: 'NertsGame', bingo: 'BingoGame', baccarat: 'BaccaratGame', dominion: 'DominionGame', checkers: 'CheckersGame', chess: 'ChessGame', wordle: 'WordleGame', scrabble: 'ScrabbleGame', ghost: 'GhostGame', wordladder: 'WordLadderGame', wordsearch: 'WordSearchGame', hangman: 'HangmanGame', sudoku: 'SudokuGame', othello: 'OthelloGame', go: 'GoGame', battleship: 'BattleshipGame', mastermind: 'MastermindGame', connect4: 'Connect4Game', boggle: 'BoggleGame', oldmaid: 'OldMaidGame', blokus: 'BlokusGame', spellingbee: 'SpellingBeeGame', minicrossword: 'MiniCrosswordGame', forbiddenisland: 'ForbiddenIslandGame', solitairetour: 'SolitaireTourGame', splendor: 'SplendorGame', tectonic: 'TectonicGame', labyrinth: 'LabyrinthGame', videopoker: 'VideoPokerGame', farkel: 'FarkelGame', stratego: 'StrategoGame', kiitos: 'KiitosGame', monopoly: 'MonopolyGame', triominoes: 'TriominoesGame', freecell: 'FreecellGame', rushhour: 'RushHourGame', hexsweeper: 'HexsweeperGame' }; if (slugDispatch[this.game.slug]) { this.scene.start(slugDispatch[this.game.slug], { game: this.game, diff --git a/server/games/registry.js b/server/games/registry.js index 61dc267..0194fc5 100644 --- a/server/games/registry.js +++ b/server/games/registry.js @@ -77,3 +77,4 @@ registerGame({ slug: 'monopoly', name: 'Monopoly', category: ' registerGame({ slug: 'triominoes', name: 'Tri-Ominoes', category: 'word', minPlayers: 2, maxPlayers: 4, minOpponents: 1, maxOpponents: 3, iconFrame: 49 }); registerGame({ slug: 'freecell', name: 'Freecell', category: 'cards', cardGame: true, minPlayers: 1, maxPlayers: 1, minOpponents: 0, maxOpponents: 0, iconFrame: 50 }); registerGame({ slug: 'rushhour', name: 'Rush Hour', category: 'logic', minPlayers: 1, maxPlayers: 1, minOpponents: 0, maxOpponents: 0, hasTutorial: true, iconFrame: 51 }); +registerGame({ slug: 'hexsweeper', name: 'Hexsweeper', category: 'logic', minPlayers: 1, maxPlayers: 1, minOpponents: 0, maxOpponents: 0, iconFrame: 52 });