From e9a9e2cf7b2c5e23bccfde0e77345876bce01bce Mon Sep 17 00:00:00 2001 From: nek0 Date: Wed, 20 Dec 2017 02:00:28 +0100 Subject: [PATCH] making things work --- assets/haskelloid.png | Bin 44788 -> 6424 bytes haskelloids.cabal | 1 + src/Commons.hs | 36 +++--- src/InGame.hs | 250 ++++++++---------------------------------- src/Main.hs | 1 + src/Menu.hs | 36 +++--- src/StateMachine.hs | 20 +++- src/Types.hs | 35 ++++-- 8 files changed, 122 insertions(+), 257 deletions(-) diff --git a/assets/haskelloid.png b/assets/haskelloid.png index f75a4e7d5e45cbb074192a4db23bc4cf0a82e0e2..f633deb21ea3235c53516c2757796e5c2187fdd0 100644 GIT binary patch literal 6424 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 CA_}Mg literal 44788 zcmZr(30O_(|36I>BgGgBrL2)Cdqg$EP@+uCpwP`aO(>+I(#=xVgpi@dC`~`o#iWS3 zB-y2?kTzS}I)e1ILXVNPm>PqRl<FGJrd9BNaWlnA@M!K$Fb-Z$NACA-Gtfu`m&+9~azE$ws`o)Dc zg{k8P_TGQ@h`~|up?S|bT-A1~o2O@zC*3i4!n~dbMUs5m`n_v<_dTB8cg>xq0n2us ze=_C5UhVp>T`E-jaKloQ5)wXZWX~{m)R~@QY_$!l5z; zZpizYE)`Yh;^LauHg?0xxc3X3oab3N*sFFq?*rRQR7BU-Ml(>4!IQ5M~> z`8UVx(&fu#=9850gz<#o4h{~jo>~D3^o(cWu`#P!mNs^J>#}OqyNbAk)`RrSl6?E7 zJGI^E6;IA**}EJ+emphPzG+@VFY&OZF7wYVdNxz{y3fmvxr_H#RaUmlaj96}*h}2m z`^DS0ZwoDT=|vV@hubzL%$sa+WS-AYb~W5O{K0?sAM{X8#;=-DC0!2gR^91cW2|O= z*z7x862GZ`tyzxSHrds5v`SZgz3)}S@3CI=RM4Mq3{v%bY6K7N=@^WsPt2Q4KhLQ9 z*MG4=zsN5912^#yesvo(-~0MV+^o;v94_3v?y0};{{Ku!`}sIkk6179$P7Q^V_ZI?B@Q{7cEnO%}qvABXhR=r*vY23{?7 zTI4BmjZ0Xk?f5jRMCqWg$V0nTaj{6c)HWXl8mYR@e0p@^@q zACyg{b(CftXd9YtSmIMt@(Vw5xZ7+0Yvb@Hb<1?kK^SC5q9v1$>UVEPw;z@#sMn2r z6_Ny+CXL1a`bXS@bt2b_GqDXh&r?sli|8!%&mSN3YFpXBP$S$tk{{E!(BJpbnd9Kr zeUqR<2p$QVAf=yl^P)?XK1P+ekihe@5SsMMRnbwb^bq4YNiZ#^$E9FiMuX@1%*Iaw z0ef7Mkeov@QikB2yx@p;*}v{0%$JCBMUOGZ_@^#9c@8cWukRd+{}V%udS$Yu@cHxS z=2nH*eJY|$3XjS~XviPM%1zHMu1dwD!Q+BnHQUvE&fn5h;VEa3c-O)Pxfo&rrCXU+ zNVjX>J6>TQ?1LfH}$N{Po*_l@nQ(YBF%}E-2VS&wj;eAcS%yxCq(ZjvWr@l z%BRPKuy;UlAn9J#aj*_|yx*l>9)}4=S*7QWJ^sKf8w7`T)1~isGc|;U6|~-+pYqWt zx{B8&{_^f!8s%|Q4(x8#EHmYXlwUf&_DY$5ZTI^}F*=MO8=-6|8I42wwkcPL2$t!& zkXJ$3=2%Yne+c@E`X4rAE1TY(oMjK6kuY z8c8Lz?56J?Uh>wLZ4s=`qa(ZHXUL_=digMwx*X6ntDUqg7+^hyO%c44(^WF)$jWv` zOpqQ?XTzuepZHjd%G%_o&aNiHx=_j339H3_VGdXPuO-BvF3DK;^&R8#v*E*sYn+Bn z#hpg3yoA!7Iu3VnXU^J`FK=_lLX)Ga4zm>q#Ee{K%@dQPEa=tCxP-#l^qRtt`hFkv zU2T|Sm1d8qkZYv9gG2IUwX`teoYxw3y{mF@EqE6-nP*u_h!$_xrS$|p=D_jEB_ML(3PzZ#>$Iz2 z%^*&CxQN9@_E^EQgC;>B}DQ>DP7+ZFxw0FDjU0r8n(-4zI*P3%|%;{_pwo>sDxI%qJde@e6u2ZkNLKl$4fd z(8*xPBPijvcgX)Ep>DJAYhvBgc|I-`?|3}IkQCq%p5Zc<*?|yoVUss~JjV~E0F9)h zLi3sPhATP*0_7(zy6ROkq71;8;|z}H%LRx``VCuNYz!X`QV^TQ#>Q0{>wG*L)y16! z&5XRGE&#M~i<8`n!{tkm=pBOF!EG|c0a!vle1X_X5UC>XRTrP#BY2AWuhR#XYVfUp z>1oZ7ta#=SCXw#NX@a(2D?Q?{cGHH&P8ft;RRjVuUpGUgPOvxx7zOWf{{ZhpWe}5} zduR{krbA>#tavmaSfh!?67%$j4A=texySmL-1I%#d0ZjjQCQI#S9abIJJE|7J!MLwaR0lflKwJN%n>_S^LOfVob_x+xHm5W$bs|IE`WeuXGv+lF@!n-5}sPc9mP z4v%x52b*pGLQs~Mz6N`hx{379J^{ta^XJcZ3{Tni1+x$s_{r3bw4m!UYdD1gzgHXR@Fl#+~udrK7uB9Tgx4kD^6CsFi1| zHtOj&NrAIGc|ul+G+@NQA_~g{$ZFxNQrGQUi4$k3mG}P-wN~`b+a^rqd0t-9g$oxx z?v@+OkmVu`V%Wjm@y<|$4RRWplAj;g1n3Ii!OgWKcuH4 zIX@mnitW_O!}6XzyL<*>GRXI+A{Mg%(QN)BULj7Rs-1XVFiwKOo@p%coX#XjAxMqv zpzOU0YXQd4HnEkQUHY znEzO{a_i+TE+39k)R%RUWYIdk@EP8H5PzT-(ISzf8OXDcw}N;#Whbn!OH-ErXM$H& zi5!3a4=GFk^7q~JpC!6OH=}3-xKP4&!=WV7Y_K_!2Tm_Yn9EAf2CbCZX-ozzjWG8a7o&s}*FeGwNt^60zl0@KN zz^|sb1kckzgS^AjyDME1@}Fhz^}mM8AgrRf`%&4OaG>DZ1g>^hsRJ3l(T^b5*YD)3 zzTG#Vcps(o3att$?3)$n?>j(#d8g_53m0J7a7DYXa?>;geXakFd77dmtvr1uat2n|Wk?VroFe3HGE$|kY||Pti;Xt14V!^Vs^ox0dfr%KyZ770 zN^kVe(UNP2ZRc$kXel>s7bpx|D>xa$-Tpcl z?rhbG2P-`(B+ALn_4CutP$0gjzgl?@*xbw=8e{~DZ|tZi;LKwvQKecrPYO!n2!q}~ z?jL53C)!WTc)p5$c11Xcy%BHp#0nUc=<~t>F-@bi_{f1)_Pz?|JUrxs=hq9X^3*-4e;4 zBC5nh+(xK)sQ&`Gx@rYzAbCQW%KEMMjvBc}vGh*ka?!g?IqM1e?cluiHUFt-NEY4<0;lToX5iCF;Y+simdO zHc0sqi{Ld@Dt-9()pNuwa2TQPW`4?8m#9Ro+;IE1dT;Ec;?YaN;q#+}j#M_?Lr!;) z5I^3j~@N?xQ8Dk(5GE~_V8BPv9N*<6{{Ho&d zx5BKLJc+lel|z(d;*_~#!s@kaTbh|7NWW_3mF)okWXa*-allGg!_b>j8v=oC>q}v3 z@x)0K(-)8tF&5P_6fA&vfLeL&+s~x_h_d7<<)JsEHuDt*;-~bTTDd#2Y%<5dXS}5c z$4Ih=L+bPpdXZfdX$2(9(UIXqWz)ric$9tp@~KLm1e4svczpVZIU3n`qb1o14r?#J z*+|n`shx2Y`OAgva*anq{KL+@^lNSQBgw4)shx0l?wwZ#g_3CzZ|cN@mx)#lgAr;a z!xRe?Cl8K}?DY?emK@!kdJ*&<1od?X`mEPTtFEGDjK_ls;kA z>bNT5_=#uY@%uZzy<5_ghk%&I+qcNqGBtkVO!aG}$!} z-Kezgg)0>{@FYxWkXGKXsl4n&npP&gBF9MRiQ_UmE1O1>S4DE*LIVD))nPet-c-6n z5{KbFWYxDI7b#B!l#2bs*8gX6+k58?;}eex(%fl`WG;o|?VxP8<)Rovxy2U}N&Qtk zWsEK%_of~tfptHATkWTo(HyLyhvbo?sNN)EtG%G%{|K5vS_y{H41wkz_s%Oekc%HiB`F^` zT9Wn~UMKRh?T;K#ov?T^D z6>?~)euux*-gXpq!)VG>jyF?Fo66sQbqC6OUYYkF^9aO#5uxVaO zOf;vvKR;l?=C(}5!$cupBq-YiktlE~C04x45bl+=<88j!Uq_u322idZhEQH~&UM05 zg7nGLF>YP)3PeZk5nNFpP^kmvKnQM)tE*pRLY=EThqP#izfO=4>JVUm8SnE(j@YYz zRPhLvWv3pVnD{A>hsi{&@EcO~4Q|XPR905*=hOQN7@){Xt=w2&V@hpi4C;pP?g|F9 ze3T?jTQ27yDTR98cz|+zGOX$QDK4>~F^Gvy@JdnOL`axSc3rhIbPtojiQa>i3JKPm zOgN1r754-XmxKx_M!`TyTyL9#?qr65Ccko>_wUw219o>#@JbhcLovmtR$hVmyi@sMY??$z71X+~* z=Iza!-g*5oXAFdJmj^Tr4toM4ik5fRSWN?EVUCmB z$L#t;DhXr|#PTMAftSG?tihwO|LC;g2;IFWmk|vCUdOacZXE$3Cy`s&LFvLa;~=#g zEtyJLzxI&DIwNrDg70V`ff;eAFIJ=9!F9GSH5@gq5CskfjoVCYxM#`DUCG%L7)ZCk zl3K~#3GN}NeI!8RreqrODXmlqn5PKUq*=z2v>%WId_=T9sMz&n*iqTku(#Yw@rKZ% z-bX87Fp;sHxV;>MVL%k%F1~TM>xGi&dvIxSeLuu^6a zGDqOGqXg2o1*aBAF~;kDn@dmH?thhZEQK``DcGr(HT|`|_bNZ1Q9v>CQbbadHoU#B zdnu>jFaBOgd1;Wp&i63kY>uS(LKg-oPKMD!L#=!cC8^qFr}Z8NIt~@I-}MDj|Gy~)2x1cqMf5~%fC^x!4YXvM1hrCX zpHz(Fx{Zs{;CfNv$=^wfC3l~i1f@2gcsKdo;J$tPCYL#cMgYRQ_RFXl6PFNgUHF~x zugPega`*LZPRt6#@{Fe}kxX?GD2)ikT)y&~P)^AVUEf;kxP+&Kga#^Fk?ud#7%P3t zA-D3YqQK4+@G2rt@iKrP_N!ukO}uPyca0tjG~}&Q#;q#FT9BC z>TE%elHL`#XV0!;J$e?tnA1;a8XOpxz>1sYo+-tBQ;J_im$>kdiF{2lO%Wy}t1nA* zCqnVY9DmUAhjvC{R9pVE*F&j#4NrzsN=scw{~L<@DD;@9%^ zjI6#q{FRBBAqkRna&LCs?5cxe9PxJMfPP*I1x4N{-ruKLE>*}9^7u})R*nBvX1{sL zZ*UT+rrgTO$#MNRr{64=j@8bnIk0bESM!*j7tWtQ50BK87MEZYjk@apoV1o)q`ppA zM;OI?pQMiALe?d6%&Lc9YfOS%q=0ol6qH`tyqsd>o2 ziJ^wFsl*7qq^YCS(v%gE=v8|{hT`Ur{=M=Njr_jcGcUjx2LXndAxTs;Bzf?D5(-Rd zmVbDAH>Kh4zv2(amGAM_F(DBal5@P#ly?1M+(nzpjqTE9`N6oEa`o*(S?R{EWy<0= zs4jSTXlKBcAVT&Wx#ViYL0jMVa~-X8Z+!K6Jy3U3!R!eyYcJJ8e9kTf4L*)9^7FsOmrV_g0AM{F-`W`8x-aLs zbrwn-dA>-d#m`1VF6@!(>bPsBz8O#VzJe=ubD-LG(R(!~X}(~RDS^G(jQ+#4>H<^3OqPiflWq_q-UK&$V7?i%;Q+Hvt0%s#>;u35z1 zGSTb0`nNa8T3sL;pnRw)C@=5TBoBsY=H~(Z7K9>GaxpGpJ~jJD{JhcUhm1r#1!*>r2Mv;cC?C`*-f-%7c8RB(9^UBM&uYvmv&qd%>b<8#JaTmV?epKs z;f{rlT+wtGvRImve$NQ9uTZV+Y^i+@>{NYA_6S-%x={JAa3Uf5GcgM^XhqoB^Lk+cJE8Vb4*C#M#V_-InJvafw_9OK= z*!F}S-ohELRq?>=STRNRK31^UdwkmD%&t5QI|G*xk(kWfy3@rYQeT)MTY22)=Et7g zUSx0iA#GGVBKzWo#a>3J?5QY!Cv;4xZGry#lnsU=;8JH0O zCyo&ck|sg7YD=e(LI9>JvRk|k?%^c{BVflaq`WJCb}_Y&Z-=za?_*JotR%)4NBh0~6^EBTy)%bg(8+Km;{o%S2so0uS z$T(0R3Tk$w9ygxapW(^D1;g+x&|(Z&U|^<8R86!>e+MJMaTBd>DtDpy@EaWxFQV}d zD2xXQ!lXHlOz93ho4I5E*|TST9BaF)QDR&s(ZPGBO_oUhACbF#9ZGosl#_|vqPT>I z;XWVlRP8m}?xYh{(rQZrFTF$K<4rU^64QRd`1xzFgX4=O{`EnxXKFv%5#Tl&w*Q91 z;>EsKb2bly-B%EQ##c!mEn-RB=c7~}M9;u>_>R;?GcTJ9H!}h5bsXgJBJw~vOV2nq zzjvj|6qJtV^U^~*RkOf7(#>|lF>2Fw^(ab&L95!y>eA5?WoK{;sWtvW;^NEe-^?e$ zCq7F;A&2hmNfZl#d1iOlXc|@7wSzRvEhyPuT(JJrg9)i)1cAYOVqd;|>51vV^Jzg- zsY>k?mk=0T@(Btc%#h;@d+qYl8^NnjJ7w*)4I|sr$Z~U%OWA&oLkOqrOzb(d`w``n ziJ^emE;QpzbBs6T{~53GZAa7Kf}adp;$cp;MhT(^;bNkqgCWbvzhBC!Bnfx2chNnt z`;koCX!PiiJ+KuVmpi1p#@+zA$dkchWB7jDs-xB3?mS|xx|5cRRHsww8E()%dEkW^VepYRlVI52xwga5HPTu2E?;V#KwCkdLi@yDDj&Pjp2gjAYhj{PAWF zmx_yQttuX(`~nB!|Gzl}a!rr=Gp=eVQM()BlD+5-wg6B#LASlEE7@bzV$W*=oR$dF zB)2Z;T+N?xA9&BjSxihRrjRobMT5uux}*W!W%g~#L7jw zc%Z|dao4_}7MA*>uPPZD5;5lRZUSd$Q#5@;!E3@aaokd^Jf(9GDH;8}5^_G5xi_AA z>`6YD<3i1qO{K$W?1Q|dEgBI$ix*%{`~|9Wl|pFL2HW|c`$sXOJ_<@>Yhb3&hSSAx zpB07!Rd}netKuR4KvR_Y1%61p1ar?PG70vz1Okf<5?hi(J|2Vb;q=B}$TMWx;lQ(z z?>&0Y{A*B0y?}W>OR5ZsZf>ZcaPcMooA-4I;P=2G@DB4+8=vY^$)D^D=E)VgBZyOX zLMz6ngx{e%g5wbM3vOXQRuqiJA;Kw6Q6(D$@?w(($DQ~NQ|OOXwb>AvIYPNuS=+z; z&ix zgT(j*D#9EXIa6>JX>hdK1i{YcJU{N(^gOpf2U210=-B#!_-$oi7Vmk)uEmpLElDXT zltGvyKBv(sw!ueW9q63$y9;H6#XT^u6AEl#PS$-=a~QKn`cOs_GOMte6F~?74qi)b zkl%MBKVKuK8DtkU+v~3*q6{+`w<`ucTm4Q!3CSp(&MvEZVjr=aB8FZlxrnGu6o_iW zB+K+vW&+Mcha8*dV-}a-$Xv18a>$PVeVDEsd&Y4Ye>~w-sXvZ$n~Xb@X2)b3kz3|b z6m_)lJ_98eB^3(5teKR`Va#JF2fM(FFJ0&i-)9tJXAeQ*B%MID7)mw^x=lXmk4a%$ z&gC>R(G+#Z05*c3KcS8useK6CZVJd(OdL8v%^^@ajreotS}baH)Lcd%n@nzMCi6z< zv_jQOI_xi-7{{T}tKo2rm)?VbHY^8+hy{$6S0~|~vgA}OZrYW_0&0+9v3*#b%`wP< z%s}zzlH<@Rt;)&}v@E&sa$J%bhWm=aWX@lvq;BY05L1)!P8b#vtt5x~y1IV5%(gn= zc}|*uSG`q$v^DlF@JL@~#biG^Y!}WLx*38JYEFWZ7=g5Ic=wtCb^(Rn_br zQ0LMc@s>=K1=GZFUc;14EvWn;Ot?)sTOcKR51XSyQum_A3iOp3Bc`3`YqAL4Ht*|V z1@|C$R8H&%^9;iww|{X72?*|%$?PBWx0X1J22O@n|8!Yn&@+N1mrsFyogg-pS0o!E zz;;fW2Qt7$%g5w(f-^={R=h=^>mNw?#k<6%Y9n>HQ&4{CPw|auO;$irKomLprZV2+FvqmQjd)Y%4%gHe$b`3qctiZbiBX3d)BEiM&v3Ft_z zAXdF7m=ydhiSx#6c#(W6IoWyVGF4@7X6z*~qB>ZW6u!xM0V zs5^A$pn$70(Mwh+@Xv}&ljILPeFsl}>!H~NvVLtMBZ#fU5>HsYq*OM!`~z!Kzq~zO zB}m%#GjR#}=FMfcspA{FQFzEn{|4U%B_JnDU>5z*XrUt4Q@r-s%a_f65UM2kNytg; zN!o^1998u&Yn&*+p9^3~iR%3Iai1?9y7PJ*Vp45V(X;U7W5R5xqmvUC(E14G)StHh zFhwCpLhH*kg%Yhtfx)z?sYz2oy<|qoq6*6yC_$rJ24;1VCmNI7?6O*onZst{9thl>8q_NQaeF9oTC-W-IS?s4*3mE_8 z;lqbho#S3=l7>9B|8Pn0(6ul>#-lMc_zaE3*hv;Kqwu-}*_+b}R-0pY{fu&u-=djc zmNQU)H8r)hcWlEVx!`cz6sXGHCm%n4Y*u&}+IonPQzRO4#Rtfi!HH!fee-WZU4%kF z#Fdh&z=<$}KF?(hwh1q0A|Oawq$&-dkV}BVM3DsVghSAp2xf-IH=3Xgfv3b0T!JaEk~Nd>adVf=m@%Q5ael3%o^RhqSApdVj1~ z@y2!Lu&N*hfK>D^1TKjzB&~1ku~|sK$V8W87rlNX7329LU=ogtL0^mXq}&S-I%6@$ ziC&;iAkkaFhG8RR&FALk=0ujGQz1HJ0!+6iqUHH~(lRqiSYfs!5^gx>%Mz8(_8ZBK4mp(*}7}V0uXhPJaIUIX=X$pa-l} z)l*e0RV2tES0sTdocIeUGTrX3K3SIYZ|v@(=V1dBr41}-2SA=TPcee@*ZCgHn!z4jgp4z`?X=#~>@hOW9f^Pu=!5JKg*^D)b`GSh% z+P~ObvP=IV+17BsmM@;n8J#0VWG&`GHYtC^s)r{w4HE3P^fRO{w69z&1s}?B=Kv<9 zi%1f@mkoRKQt(M_Ygi9Ly@mWnc0qBKGMH^hehHE$(tJULWM~BcL}ng@?++FTeyf|z zSft=p7M(B$nFdrIxwz_4TR2?g0D5g#a6wmdow&qk+pxlX= zfhMmxZGjV^F@17*qJL>v5);pJmgzCH1YttrbxSHJ~G=W^#ZF)sX_A_ zE6!gKA~n(=GKHjN#_IGk1y>~F{%atdNEf_<;sS-3ko!V(p~Sg>Gi4(MBeN^sL19zn zzUUvVYL+X!B^dc6b}e%U3M8`ZX=b*qdGkKIyMK}cvP6rQ^u{+7g-%mmjC;KdCPmRD z2ndGzg7q#SLda&B-!Tw_ zRF#*1&9%F$F^$YrRm6jp8Z%%|kj|JnY{hVj)x14iU8^Een=4%XMgli}x|DdW!t_!2 zl;kBYpQrTVMAyG;Qy1?TcWl;LjKbK z;A2QFW<}9Z6T_=y@pAssu;tc0JZxt+TvinU+$}}2NBkqsB{{81$^9r@=t3DhG*l6( zr4%s1vKWQ28N=SB(~{vRP9kKg0wyJchm>}AsEac)JVpsQX5EG0Dj_vB)gD4JfH-WS zk10fvB^4kM&Kz|CFe;~(Tzx6+zqXm05cJ=PFinqo;ss6NN8)HC z!5@*&V%;jCNNsYb+@Q&yguse9IwYcz$|FaIoQn^6xgDTZ7-3yB;Mr&zE%CX4)lJ)+ zhAsbQ{b-NtUSL}BV?jG;{3LYQ(9@WvmZF(q%c7L4F{RezNjs!0Hy~9al2t-@$BTv9 zppiuUs{$-!+j~qFV?EPlB*S*K)&Y&`td7Q-b8L{X5kLOx!AeJi=!WVJ-QMMAWo5xb zewv6=G?*K!&A}!lKR{wW-WEN9#WG*Ob6ejX8~9eC{dMV6`$YW2iO_S-u_QYf5CSBEx8vrM^S>dtULYurKv0(6 zQy7wI?Fo9(Iay|xX9Dum%P}dpt`y-}TU%36No*b($wNrmFFk^KyQfD_4aFR7+%TNGYojULfH-ld+Rm{Z;5^|DZDfyUo z3iMh!N~~-KoqC;s7ASRq94Kb~fd=VJgEXDYdCschxEoFb z*IZ~-bnWJu1Z*YYYqo4Gw2pHuE8cFb`9Nh-iU)7B#eiK7 zZW~&Dd`@d|+<>qV(fOLb9b!sOmMU|%%7KpJ$-9Xyu>!5U>u2sn?4%cYSPvtg7VBjU zr*{`{fa8{t3Mrx4*!gk@6-8aBmUhPeLp-cCX1C1=S@**wx_R8@>P9$>$-PLWr;*f% zmv|NL2%I_0yc-$xW-FJ9Q$Ubsv8%EWu4xdO08%O*q84@N@eFizP-LsNeDtxau{oQm z_B`;C!_3Re#vi|?g`&E>z5R28=-b_uYu_Myfn+ASz&YjM0BBrbRPm<+_zRotDMZ|2 zCCfCh@z8+&;SYc6)AAUWHEAS0G#vdNI8!BkkCUSf(O6 zgt2;Qa&(Akbn&N!AizjWU=JyT7zZD4ZXNK?#lZo#rFvakU%~miF;5yr>>3Elbkgq{ z5sU><$jU__0o`@_Y>8Y_;;t*WT-9YF41 z>o2D50vV3tc#`OZx9`3WX4&^Lc$lK!h~$U(WsW5Ywj}YJpw|_lxHBTMVkIgLbK-gQ zB4xa&m?yIqRG;I}_N*-3s4&F8YzU%bE)B6m;IUR*ZdFy4Ig_vxz%j6*m{b0k=#Uvy z&Bw5>a_p1Yi+%w*6(5CM2xQ=3n2~~{kUeR)oXtfjcyU}8MEbDb@|)+o#JwDa5~Kk& zs+g!lHnimw<#My^n`YCzsd&ZFX!`tWiYBp_kWLMaE(chgi7|H$Vtn9e>oszv6tQhq zb#Cxx87ZDNCTeUn*i`Yahak#Zd12FLRfsO2r1T$1mq1_fDKbhTG;%6wjerEXWmR{^ zRX1(ovmwQ`ry$}ovXiC5M7J^@E?=NNQb?E#=x#iTxZ$yTtPlM~4JMt>L~4};8kB_!(I(t6+fYgO<~RljWB)siD~l-7ugpa$r7X=I>B{k4-jMu!2=~$Y40#8 z3v`NNeE>mvgXMJXhQuu=cB26V0fGAD*hd&*!X3zU=s`KeL=YMV_0->8;vk`_+$q|f zV}WhETr8c4nFR5kc93a^_#u1=*9{3#i#|v%)a5*X$*}uFU?iQa>dUw@b0E#-Z^D=) z;y^to0hi48!`y<`nXGHGK^DYP#Z(8UGGy9ZeCNyz!1aZiWOKR3&ISYc1! zE}S+qyPwvNR}7M{fDQ)(9$A6@9Y4p-`>I1dSjkl>O%Xn?`W7~%+n>o;%2{asS*ygk zX`}OWKRQxa;WT_$bbjUM%_ETjPOPk`Xm+mItRwFDn@e*UFpDmwVL-23>tR)JR$Szd zyS%twWa0z?xeebOSC5jn0gM)HY2ge*DQrU%2#6+|(V!)%iHY?e$P*!+d64sbadb#C zf)bAI4?#nZ#!CSDcp;OTXg3cL0NkR`4@os{XuV zIe8|ly0AA$qXuMyt{+bC1YKozOk-x+yMd52WGks8!A*ezO1cs4r_7!C#fw@>K(p6E z4&iTTO{szcXeq}wkYyAbLmICPkt;be`Yh|kyg6MU2iM=(i<|!T9VO}~35g!^%9#o_ z!+1JXnorP>BsQ5O_A(8%^iAY5_slUbe*Wy)CMLp-b_W7%XJD2{khA1B?LOjOE?l^9 z(}rPhj?3>VvQlZ{WWW+sKV09^Esu?-<~WfSC&T@ehK)S53`a`(}_ zEnX}43fvO3G!Q|Ho)BTS3RWDIa~Fta_4fizKS6;by9nmwc|k!+LQbP4@C1~GCsH;n z82ovg*c3grN{^uu&xt-*2}B$j7v5y!%m|;K=SP>+1M+Ymv4UR3U9b0q-fMAU%Ln*e)AAhI!>iO-#1`92n*VP zab)tK6~uRENeMjO-zU((-ese!tLyJrxX4(jWKSi}povx1L=|r!3P*>Kk>^ld3h zxe<*|KK#umR#|D%6orN6Ceb~& z7kj?kc!+LP<(;Z{NA(p=N1qyibJi$Ejo-MoL=}0>XvPggC8+EuOs@r4`&0x1qQhdOK@mD^4;;xbb z9SC3~fY*^DM$E<(I72koGJEI>DgeDlDG*p57dVA>!aNa!7o z2z#)yb-Z8|eaOyCMQ??-^{_WO<=f%yuWcN;+;*)FY7Sn34m3Ik}DE?vr@l`Q8gZrol5b%C=AT0Sxm4=Gc~;8uIZdA^J~r+h6Kg)waE0Ff0Xn z552b5*}06lG~}`@QYAvV}Fz>?NWeZE_p-2C*~>BurY6Yd|AWnlj}|m>Ic6%9)5?1Z>NB z!PpT?MI9h*sErn*TZXsAZe8O|v563nk=0^YS~`XF@CeT=>F0lQTEgJ65Hx2{XiE)! z92O72(>WpMJu+o0$@nCx;|;7)K@WQyrMK~N_n#njQ0vb*&-YWuulsDiHS0DN0MqCl z2ZeVa1Iv=)o8W+^m+N))p))by=dRZu<62_euYPrvBX56fI`^rmYQ&k4X|i5` z!afiFC=YpKV0yUh&dT9K?tJIq;C3MJe-{0Ey~r0yHIJ{bx^Q9e*zA`V#@0O-E8Vg9 zBnj^L;zl2rCmIL4-+6oI^1`$W6GCGKi4M)H`0WQZtJMZ~eqZxH?#|60Hfw!0*Zg+`#axhDvhLybTrLuc&!0{2ir zr{gQQ_fX>d1g(HAe}ZC3ov}}~_SS@ynv*C6a4TTSR!-+Nxg)BP*K9#qlfgKIs^6A| zVsjkcAttNx30Nn1a9797W!N?ye<^3ncwi-CUw$jCg$}Chy-9Ws1sIXiE*Oh*U?^pv ziVaXWrJgg<0U>8;pDy-`#iR#WrD>9nG4#i#R$H?#uQ#L_=f5CX!8U5{Q%${tOY8K; zPU7CO;d=2WdWsrxc?{rJH~p@T1pX!1Vm?mibV+L>DHa;sm39k37hCD~w8=Phcj^-w z`XHYDjF&GLUVavcfOfD@8X8?Kw9_MoT;Zrve@$6gfsM?Ok;72Mo<&%d}%Awv)ZPwXQZopNqt~ z4C3!_K3MC^b=tagNXN2Ai8)cld+6THw1abxQA)!c1YhE{(3K%Jm;=rp*pEo4kvkiD z?b@}bXe{I*zaNwHg#n*MkPON^JJ7iyf{wRy>yqM$76x;CCxVvAd|3~gmcU2jadf5{ z?dN25&{^bK!|^0Rbv9V*6PP^brVID+V>BQL)cmNz@ ziZPd_uH%_sBVtnrm4>WDTTjyx>*&DfOJ%f-*HbPJsT%$dH+M>XVLgI7sg)AT`AVaD@HC#a`S@? zVD5*=FB-Skgli_h2l6`;X>fA#EF^=(>Vm}HLw>1Lfe&0ffAR#jK*9hJ;zA;kS%xIU z9c;|Ydna<6Feg}iyO>tPJJ6?2ZiVXx6vKa$mUCx> zNweN`D`C>;nD>h$hMa|vkP&nnJzZBkSny1L5clH}m_rh+g=Gv!iXb&CWm`It1)@b>0y#$RSn=CeiBGop$+E3eP>7X^~k5HIi z$ijYbfQ|e+93()z%|)7m`C(JM>jt9g$gM@`SE7e%k*kS`iPwcqYdX@I-Tej5UV&DS z>gD$t*iE_>9<=o{G;+)k-T_+R=xt_wj??TFh4^LiC3M>vMei3;8KUSj^u&h1tzezR zmDfH;A6>F}kigvdM_L`+W-9P+);6Ah)z2Y^F$z9cii5wIrKX;A6Qm}@BPS2->bM`~ zK;hDl-?2+ckEWnQ*X-tSAPi3QmoVA+m@LcC3zm;N#P2`nuHu}SqEIjsVLNm1(%08E zYG=Hx?QTd|_3FWOo!I3PK_UNf!qK7D?CcND523T0n!*Y~$euVEwD`@22XclKItW;u z*`d1!1iKGkSE3X;Wngz{T$3uyrk)k=V8t}s=PzC~VS5($7AXO@F2MLH2?=#6#DKc| z>({Se%c@R*L*PP$`EP(JN$Si<(f~1N-9i?-Bz@2Pzd#*}6}-wDd)^u#K290|C(mT^ zl?k1hg7ZZ9gK)UF=zy-C1TvJg_-JP&M;E)0FAmk=Eko#V_#qcqw9*?>(Lw4LDqs)! z^;6xYF2eYP#zf)5O0MNR&mgHZfH173Qb^@OLCRLb-Os{IdC4d@R;xN3 z5KkeBI9n^D=2!kmpns4hz8^%d=!df^n+vmNNEYBU{VG>Xmpg%)ArW}qvPIv$1=ENq zk<{v#kh8^r)|V|H$ivvhxlk}@#9Z+&JkA#zU?D7ZTbGI!+mjqwqXNJ>%5$h-gn1sf5)d~+1ZEJ_!o;eXf=yh359U`#R_+Dj)H z7Mb9p6)wu$D!!EAn0-j&8tCh1PA5 zq~O}iF%erD50wpEaMmUFobO_23a1BJ5#~RQ1EoSJdjVidUo&{VCh=w69s*PJ;iy~y zROviWZ8W4o<|HG>2yf|$x2P$sx%2>UL1&@kU?`>j1?0|c7Fc-=X7G?cW`vg!n&QIv z^_-2aYuTHk`|4P=nYJO$(~`kn+2o78b;Gy~F^XgV==M!v&ugLXy}j*qyXcM;BV zL{~>jMR0RRtEK5jGbcuU-y$e2n>KAMv!G>*CJ90=yGn+2(yX-B<$Se_XId$0W1)i- zRu&5W6E{my<_guu1tFT@LeX+S;HB*X@n1c=+8l>qAdH{N6PflE4Osy!{sQy)8*kja zuult}3XDeK04J|`Jlx-mfM>|7bIFyPm$?uXfQ1QGbGtX8d6&NPQ491t>lU=mk&a4P zCWzo1f$Fs|BC{y5Eb}q*1ggUmM0!I|fZrH)n_F(A88B_0;TG^orLf;@ zAXGCDuDRHbrlSLwPNvCz-_)|Y~(%Q4P9n{s;>$0Hgm~j+DXDz*= zxe{B=e44y9rf$wB2gYxiK1g#+8sCkZdqddo1 z&AK=twFS>?5QuvQti6I{CWHIH;??!U;+9gJ24?>8srl;Ft9`B{)D?EDQVLB@)YjH6 z7x2jf6zwzjk&602E-m30OP?pWIN~D#wsZ)`d7QDk&%5eceXHrmPxaK06;)M$2^I*z z;0#Srg6?p@yEr*Kl1=on?pkaYt||7spxkYA&?`YDM9)Azic~duyS~%=mp(23AbIp? zEM6cSguh@s4uXJ=3X!TszDsoRe!xW>(PV@c8u1FmF_a?^ER%b2fOEqsXaLTCBU~n0 zhBvpd8(}0uH7*E)=oG)+ zrp|p@XsZ%3u%x;RP-u|Y2`j>BiSatx+LH_HO(W1;c*`avz#L7&!e>0VUZ`iErPbkE zPUeOT16t(AW>wF?3vp-=p+qSPpZ{|wN+X!MV$3Br~%q-q2J|sI7`m~Euj~W6C&EJ+IFj; z(%llz@?+uzI7)RjX9EwxXd2H3ZDJLvjP=tRaK==wJI=qXK%z|A84HQVLWDR*uX6u6 z$JCaAXBq+PWbAaa!${6J**0iDEQC08ownZ$7Q%~@NP?THQd@@)Z@GpCXbO0P+YfkP z7~1Po)@Z5po+>`EN<&?p&%Ko1034Uif+)ET25JYvI>dc}5nd&`S_k^7?n%Jc3x2}8 z{yBV_2__vmLxTAVg4u7{U*{2qpc7MLB_<@HZ6G?ljd3 zC=N$rI^G!HZ=*&_D;}Aw-4Qd(e@7Bd6MK=HlVkSc>NzfIa#NPIk?+NrTo)YJwj>#? zQm&ge>*&2dgkw(UXU)jJ4fmHE=+rO+hH_=OE%9JNWom1SU%1)!bQ}h8_wu`N?@C>q zA^#TperwBSHFBaxV1siL@UgOrajzz^d;@To?&`SSxk~G=KoD`>@aJQohAphw6!@W) z@9}|0&lnA-b?S3#{O}SEMP6P*MQ!&9^r?W1S0d)OjhsqbfaLLaF9DQ+V~V05-@0uE4nF=`ie)z^V|uTT@>PBGE#KF zl=v9ZKKkE48cMz4m8a%f@>)p!4P@klu*AqN=7YLAK7ubPXj9mYd$!zgfu_GY$_P zCxc0&qRIB_9C9lLhk5fw-4)+MKPGI%5k~td9ME!Z`0L!_>zm zM%30r@TbxeusL^QSypsnV$OKNTBt42j5qzpFV?-dJHWs{sDoT35fL&y-R4i~>PKC? z)G+!Z+~X2JJ(e7$sbAz7z!v)p#;1ajpn`g?BY889O#>QSM_i<~rZzHNHzm>E@O1>$B9-}p+=~xE=V3c(?*$jCr))}{ z6KI&)O13t|y}9voVAhOUawx=+A&8AHf$V+i9E@ebzUiPOxExpiq zgUu~?43Hh^5VV$QSf}LzCBaqusqr?Mqu2mp3o@i>W4|JlSYU|11C;jgs!7*uJBHr4 zd$|3MV|1#aV29MdwL=a-%oT6THj1NWAX9E0Y_@baK9yB4MJ>&oKBcnE7Ae`U`>jKLLj4;MlLjsP**PrZsD3zfq%&rGdS{@Z0zVLL!2VbI}MV znH0t)M6g7BR&^KZG9^_A!$F|;>F`#3mU$mbK$If^@h0bas9<7}D=xk0=NcDgiyaNi zBJz0~Gq+xUEHCUM~J7iA|#FLbu6U;U^&&5IjAdaQm{dIOLYMXY( znXKwFAayX2+ZRXQl5)3UDr=)_wOKQ=X54>@pfnXl4a$A9?Fm%pkr^li8>;x0Y`Q9c z>g!|#$1NXvE`WP{pT&!RXnr2OvT;jVPRUphIGfdClr78(@qqb%Q<+Lp;;^u#&n z+pksM=%TwOt{I0y|dWeHH4ZjTy-;Q?8xkR zpKeZ{?{1l+;&a_30yhK^5Ou_2 zm}6-ZbWOL=-L3R#*0+Bmft~;C*_UMeBNAWlnMGh$2pAW8P3yCz5deTx=k02(fHUB? z1c#G^QXXH3czG+Pi{loTl4gU*(jTA|Kl2Jhkeyj`=nWmMbOc??J?QI=>KI`tFA-!R zh@(VY!$6Rrh=>b|Fqa(bbRKSifo<#QjP)o9%)ya+Tc+{>Q-o41VR)1Pa8i*wX$zn< zEAu#MVK#tbt4Mumk4!J@>C_=0iFC9xj@X7CrtWrUo7)!+$Z@AOQ+Udx=qUOj& z4Gakz%}o15n~m4GZYhgC+Rqy1ZY~aY4id)t7YDJT3i#EFWXu%#ITUu6zyUE9(f*Gx z*r_%goK=05w&)XksMIitT$oVH0x5Qk_H&f=0&Jpk2c6sLhRRi`^wT5r*7Jm2fToB9 zh%_hgksW%$urvv}Kt0h(h3vE}dEs8%Bda=}{}|U~P8(%SvKdT5FhIU$JizWUeDp&F ztR@>~qM~ftfjl-+76|4GZTO+I>1ba1YU1U@M9=v^l%Y8DNU?CKLl}2fpYUbi1nCap zmLzUp~soYlJ@$k9cMgFQS%MtJp zR3KKyqdGJkX0nZPDPC|dP@A8+(m^P+gM}(g@xV@WTU)RV6H$Nl-IS_LLwq}Jgn}(6 z1#^KX+}&O-dJ+3zM@dDi|HQ%fN{~kx0MqaKD2tTyAC0#Uz}u4w^HE(Q z!$2eI;KaR`Bf35^xYkgzhvAM1{aGBg&HNJQ!>3~}( zU4@fG{1!m7XZ8u#f(Rs;B3SeQ5Vt^Y)R7_tK22UwYpNbih${X-hgk%m4~9i%&R*n6 zOK>o)hBO}*>N;RdAq#YG{Essyl@m$1o<;(VIuc&UP~`Z zOv9&~jtSrVUKQWB_GBqX%_;=Ex==IWW6}M@3qi^6u-+{AmI4rc+?`lhX#@J(n@fg*&sI7pfm^*C~t6Yqax>Z?0#m@jh z%)NsCDO1XV@%a*1xK-a{1biIP3mbF96YbVw^{HdVJVGa^RA-(h22`LiYjNc17qy%0-dG^VqXmtZI1>5u*G zU3vLk8NP%~3CdL<Hp>4Fa*y_- zzYsE|qB5r| z<(dcl(3cg`>dou&mO0K6wACtY3{DVWwmbx%C!t&9ur&M`C`;58eZ*HIs1sNQ7=i;< z)se7~l!Gl-74v?F0s_e?l6#m1ZCyfnls5F`WkNz%xfuPiRah#gPhU6Tg`BWCY-+zC zu(b4sJ`FuU+4SG|=wfp!!yV-1d}ougvscn6fu%!Wt14Wa8~g@CHqlI+`!6cNR2%tK zH4ee9myT>ALH=RS$Y7w&idcXD`gP)TP8w1zt;-ral|GwNpZ}>AACV#|5^1eQNybnw z2BG3o)HTiX?3);vLv=j=Z=6N#hf~(cluME7K1P8xi388z4W2 zxMpgB8RPM;BC&8}PYsJie4vlIlQFZ|D8Clw*?;m)rS24o2&d0nW3UK-N*%hjd4*`z zc)6&<8U?09aOk7~Zt-Zz7{p$(G6Y{i2LE| zR#nDb{pd^VLW3M^a=#<6hHSeeKDl7y+&}LsXhQmDvj|+O`Szb}` z5}1#($9J-**Fg|!xE;x6kP~Ux7MeD;Im|tX%R(yzD9%260{x|Lv(6*70`Ks-fyvup zK*(j&R~_Eq({)?Cu_j9H^M0fsX$t+Z#5?bT*kP#MDOzRF%SM=bw-ut8K9DD&_oO7M z_$2CXlt$(7ZRufCp-z>LZmqi-W0iK4!UbeLn-PeRiPQr@Iuk*#1SvA1t%uvJV4w|V zck|_@riw)KQ9-93ZC6@=bL(ga9QDui1$*H=Sp}J1xB+#PR{j4g>)PXTzT5vdd1{`; zJ!^>MFw|pg-4vlDGmN5*O=&;e4y&lAn5Ial%^|0fL&8IO<}fP7G%eIUIs9g*he@mx zQdudK`z}e(`~5xC&9m3*{$sx1zTfZXx~|W4y|2UPy11t>rR*^-)&aX|&q89MkQIEK z^#owK>Q6X{Oa>GEXpi+Q+)d|*J_8Q(NALvLz?NU_@|@})JQ{#f09l{lWWL)zS+bDV zj^#iFJS>5>p2&XIZ`$jyMk3sk@rihir?_WfzUDw&D{p75IriZ@V2pMuzVIMss2>pD zo7J|X)Z8beUWmsw^dYf0$emCNE62ah3&Q%_9OQyWqG!|A14k=zsb`! z1`j^0JoqinJ$&uKP~&d_YihdUsT|Jc2${v#144*d$NaUiQ*(3AV#zeVOTA21WPJl* z&v3)?Qd>F0($}f}s@ADue;QGs9}6AdJO&y+Y&d|9Psuq|Wl&ccpCaHQem_S$U^cC%Nnr5OFGN2h> zy!2g8N*e>;cE9Y~W)9+9&$eQgXhi8p!PZar?|oVCfTi#ZFsiezUoqHpYhz1-OT%)u zJ9kLHNn}xQ12Cs_DsC}woiyx=L)i*Jb@41N1;#!JDTbVnApFphL&=#UN4;K8@amFi zR+DlS8t@Dg%_wmjk3_T2y7?0DFzwC|DQj*~qq-C!tyv3@JilJRdjW^XLsvu$kz~l& zl?}zX={xrh4fR~3#lpDo@`V^;5QfBjd`>SlH}2`$#cy${#}kCX)%yA-jGjW z_lC@Cy5f$RPk+e@tE?L)MzVsFA0Y{scB;H%p8(0l8zeTNAvL!^k7uZ0;C3v)pW@&m zGlz`Z`5+82nd`aHBOs?mhwO;d)bt!G*u{HMUglDeR)=`U2gq1u{PYvY8mh$HFtXg= zyW#*#-ttEiB3H_34~!AKZ?HI+gM;#>(rA2mFsxmLnG$%AX6oe_ek=0|6*LsPq#;m` zRFihld`xM<4p5+A%1u`>3Xp48L1|_0R54-*J*zeASvWca2q+j9Xg`sM&L=e^bg%vD!M3isi5x=YapQ?g z9chVQ1;*$eeO+m~!A^@$LSAZgH*p z`N`|cuwD#R<$+p$j0O>-Lf+@K*Eis`vhd(BDz{=0;@@x#2Ku)}=Ky4fDhu05R&_oP z>z+w90#Un+IO7t`w&vMexf0_-*gZ@a7#HW*B5z!w4 z&-FO@z83I+2;)7>xQ>_k%`;yWWo2a>3hv%P3eZkhuP+WRZQX%(v!BaU`wKIjUAaU6 zwItX>wqZ#pSMVDoOYnR6{CF-gYz68@d$5jz>drpqfx@yMX@UUBl91VOcpcD25eAY! zIDJu{^*S-Vk+q60{xDx-&;Zfs49^W0|zVkgP%c9En`V-Y-HVolEnwFa3 z4$8S<67&yv|H=0EhYUK3{7W!6#fxcD6q^uGJlbh12XlE0L#*>2yR{ATmYIMQlmlxh zVGr{I5&uS=^`cWymO>9&jc!QM&BR^Wg%G0(=y?_J67pZI4q`~U2b-CoGE7)?8Yy9S?A76-Ud2lg`vVQ+ z!!^(XMltg(*5#l?*l1e`TweHNDJg>>wq8rV2im zI+1V*YofxkU#HqA_A7&)j_jmP&y(VZO1wm1b2G7@+4Y`IvhBvWOh z1Yw?3T}>mWQ4&C77HDj1APvDHdv^uqw5%9?aRDfu^@RDvWQCB^EebbDYMp0j`qk>u z>8p7r1VJ2w!_8`LqWibRAwL|TZmN(ejFITlVvLMKl`I3QW)cyD+hA~u$St*T=rFug zQFmBY5JU3RB3HF@rNE04+!Cy0O^rMd^B;<$2B2weT~T{z@{Q!|2aPMI?(b>o`nkzx z_dj1TWyLQ`@0>I`**SfR+eh2_uQ-6@cNLXo2ED9&nkws9h z?ePr3@bS;>(qqX`e!NVlF*3?X_cqbRjsEtpKYV!h7KdMy8(v^vpzceRKFLJab$4E6 z&RoBiVgLXfl#&SK#KJn2@&+t`2v>PScIdP6-(ru%3YrX=J_Q%F&hN_fAqIvis8YVY z7rvbdLW6IwBJY5md6vhLg+t&A4m}eEMKU`W-F(!mx(A*;>$0|l{|H^E@Yana&sUpq z*0-mXacFM$O&1-pZtNIGda51yjM+oG+hPh?#M9H=Fnkp6u_&~BUZT&|AMr~Sg~vds zta)a_lJWuosF`S1vxU3!SVs6iVT(5*kI&Wz{D{TS>u(`%`55WHdJt=&k0y}XvgmD_ z>HjL6-dALsJzPi4d3^ewCmzfaH6aIzUPys&aENB&Oz6nHj{&oL?~6Le%}U{tiC1$k3Tj=PC2ACoj?jl5?|C zpZnpfQQ!!ciAKXHWQ2+h-slmdS(n2b94d?F5+FuPKQ+;*@d4N}!IA{_iTqQB0HX#P zhcbQxOs)tPd(zM?;}8Q=Ns7fk!&GI2#EeF<`p+8Xx%bwnu`CHdu*510Ra9a>fNj~F z*@n73LCvO^+#IHhG^)`npOshA)4$TG2PUMo56IPK&*z41)Z*N9>yWUH z$r8F!X-~)os%TwQSgu4g3K(>VN_$1df|#(-Y$7kyclSDs(7+A+tPd0(bvLWA#6LnT z8@qgX^GP7{W_)1^;~d1`A6gVT$Y(9(IINIzZFslVM3|<-aK@PRvNX_L@NR^H#k)5~ zB;gwd;x%VCM}=MEjJqtaYL-xK*uJh#P67&kuzj?DNEPWuoI%Z2(~K*OQ(L=9iUeR+ z@MjXRV0br94@~NY`y?3@p8>2c?1kCMU*irzeVGsyHVu^6(@)Y8nRU>k>CD=YRj&9` zrECDqDthjfjKA)RD~$V$^VZBm;8+pla(En#sO}htj1kZ3h_dFkKPv1Zo{u<6Vcfbp z`eD$@!ZPITNiLRT$ zO3a<1(OiZoZ;Fo!lTV*D2UT3%E%qk35j=grQhbFId@>k zvm+Au`b2tz_QZt9_s%nFUzxZ?d5v2%p|^4KFvtfmg?8nF?;o(c#a5G9XvSTa2*iJHI%|Rk@nv(VERR~D;KvvHGyQr3EQVxoM zGOFK)W;;%M(4(&lrz_RgdR0T+s{dx98z9ppAJIumT7?_Wy{bb|V08ST$|#aEWW-mW z*M>6_2>GxYgOrL@MnPT=tPz#@!X&yOFw!o1vzqmInSt__+9?8LRPB#y*^2K0I#u?J zivws6eHFCB9@H~Q8}Hl zM5))xoEM)$mOovkYj||CFGtc>%it^MvNl|dZp|w$Ep6S~&^1LYLIe?w^(CQow;K8j z=>d|=y9Aomq{)TG+}bNM3NGWt34e!h!Eh(pnCQM@)CFw4iJ{e`??E3<7{bsh~*EE4y4y7Llx)JhIfQ#TNEsyg| z<}Cmtf7)>X7gj={~7Z$!vT6od(JN_$jplFJ)M_hQ?IcnJM z1}&p!`m^?{Blx{bQe&@G)<^Jw`9fI5t)SE9-xitbzU~!nOWC~T6>LDE^|G*Rz9ioA zif6mscD7r|vS=&^<|pd&gmUpcGA^ZVA2mi|kH*Z}Asw!cf$9)q*f|y3%eSQ5WCh4z z0E@I@;^iFtfk3+7scuWSL<$RSfq9>uXb^J?ipBT*Jal+X-E)=iWpw2G8&6uOwnHiE zv4>)X$o-TZ(DIsm6K1V@urd{G7!>0u_{oly{o;3x&)@}!zEZwm8C2r6{Em>=(Z#A7 z$~|z+DrBeoe1!j*f?qlt_QPbjEYIp&$mAPHcM9FLF3q^oSCn>;q3|7$0V+6Y@Eq|W z)I?BSzKBi;{?XtQh9yUN2RXh;qLKdGHW>xKi&6zrO*(DdoZ)xd84}DCyr>>w!iD}G zX>(ha!t?nQn}1LKLv6NOZVtoaYsQW<`(AZsABZBpZ4JmlT^?N>AW98N;(vuLXhBkJ z7DFni6vTmdJcNnb`&pLCih?ly)qydwgVktS4+|kMFuw+bzi90r$ z7W^~FxEbDmH3bLL_I9nS%Uhl|R{tMq$tq!hLt1>q=Y1ZD|?5(lIpM2hqzZ5rPyAvc-6|Ht|orQU@ zlt=#p;Vny!_EB@l9ar1%`As(sEOZZPZG@h%! z_mdsIi%x0ehD*GRzZ&k8rSoXx9J;#rlsYe1{iX)#*o`^f`kMjctWE=dwMHE zEW2IOHP}xZTU12AbBbK%Cv6!63nS+Dii#ZqilB^Q4*g!The&f)}%nhLnxk z)3#B9P{cJ8*W2z%`Wr~T%)X5&kN!A1Q?#MnMP)Yf3MLnbicWF-xq>pL%m_q&ShB!S zM*;`LLYxH$IZD`j;%Z*@J&%LSuV`n`AQDq%FaKrl(2-0``l-9*(vaD8CAjeGbh zyc4j{SR7445Z~L=U-{mAoarmYsR|zacY_Niwv{8!){dWOD8n!w#=>N51nT3mpGP`V zgn>}SC;~~TJs}h7^v*_;=CuZDBeVL@4j%H0d>~`O0G}Tu$r}97!J)~{sIgP&nFleB zKjXlm7oM~dWlkqOhrVKVLLH7RF|G077fwruSW2r(UykP7ty5$w@w0|-kLr8jyJn4S z>MWZxI=N5*#)2Oz2h6)F*hW)8SWjdu3@T~U7Npwb0UAJ$D-rg|+`q)jSxp>fZs6TemuYcMAnr_xGYnE2|CZu)1vL zwuwh?X#^MiOQyDQ1>B;~Blt2{YrY>Zd^B2TsL(P40ojBkoRFrPRF6*%d4lI5+ChUJ zeP-^|m4N1gZ!w(SI_P9Ny@xA3{|8oVJ`a9=iI0GDF#qEiCqr$FI4qhmOPVQR>jS4C zFewF2zupH9(lt4nCs;5$fa->Xm;s$@>YHAckO~dw9BVTd#$m-{B3`{bI^)Xr*KS9! zBDZ7jRhrVfcUQHj%_?s%GZRb)w1uk#4XaaOdFOYCd8U=HjL5s-RO%8d$(39G%IXa` z25=#)lDS@081<$G7Um!*SK3Q*d|&`3T<%hzZt!#hn4m}39qV2a!Ju|veYlmcq8teL z5NljWrp3y;#477C0ZxRs`DI}#!qH-&sadBsW0F>-h^Dt~;R1~dW8OKE-wdd@&i z41}71m`#Y7`>o+?7#~oh-vMmP#`Q5p-|(8DKcOBhF+D%dBlQ0bnLcLkwGzZh1h*{^ z8bqf)WK#7`gO&DaaggB)u#UK<)vx?fSsXbH_=E=%mmLkU$nh`}p+-i5-ZfWWNlI)| zWZF$mZw8fhQ)L#cIzc@e#&$e?ky!JBd6bklc z2tzwfqF-*vH4ObY;d%Be?6to_VFe4(r)r6zVvF3%mbc-bP2EkVAUtPr Affection UserData [Haskelloid] -newHaskelloids img = liftIO $ mapM (\_ -> do - posx <- randomRIO (0, 800) - posy <- randomRIO (0, 600) - velx <- randomRIO (-10, 10) - vely <- randomRIO (-10, 10) - rot <- randomRIO (-180, 180) - pitch <- randomRIO (-pi, pi) - div <- randomRIO (1, 2) - return $ Haskelloid - (V2 posx posy) - (V2 velx vely) - rot - pitch - div - img - ) [1..10] +newHaskelloids :: Affection UserData [Haskelloid] +newHaskelloids = do + img <- haskImage <$> getAffection + liftIO $ mapM (\_ -> do + posx <- randomRIO (0, 800) + posy <- randomRIO (0, 600) + velx <- randomRIO (-10, 10) + vely <- randomRIO (-10, 10) + rot <- randomRIO (-180, 180) + pitch <- randomRIO (-pi, pi) + div <- randomRIO (1, 2) + return $ Haskelloid + (V2 posx posy) + (V2 velx vely) + rot + pitch + div + img + ) [1..10] updateHaskelloid :: Double -> Haskelloid -> Haskelloid updateHaskelloid dsec has = diff --git a/src/InGame.hs b/src/InGame.hs index 5a5979c..c369b4d 100644 --- a/src/InGame.hs +++ b/src/InGame.hs @@ -1,235 +1,81 @@ +{-# LANGUAGE RecordWildCards #-} module InGame where -import Affection +import Affection as A import qualified SDL -import GEGL import qualified Data.Map as M import Data.Maybe (catMaybes, isJust, fromJust, isNothing) -import Control.Monad (when, foldM) +import Control.Monad (when) +import Control.Monad.IO.Class (liftIO) import System.Random (randomRIO) -import Debug.Trace +import Linear import Types import Commons import Menu -loadGame :: Affection UserData () -loadGame = do - liftIO $ traceIO "loading game" +loadGame :: Affection UserData () -> Affection UserData () +loadGame stateChange = do + liftIO $ logIO A.Debug "loading game" ud <- getAffection - _ <- liftIO $ gegl_node_connect_to - (nodeGraph ud M.! KeyShipTranslate) - "output" - (nodeGraph ud M.! KeyShipOver) - "aux" - liftIO $ traceIO "nodes connected" - hs <- liftIO $ catMaybes <$> foldM (\acc _ -> do - coords <- liftIO excludeShip - insertHaskelloid acc Nothing coords - ) [] ([0..9] :: [Int]) - liftIO $ traceIO "inserted haskelloids" - liftIO $ gegl_node_link_many $ map hFlange hs - liftIO $ gegl_node_link (last $ map hFlange hs) (nodeGraph ud M.! KeyHNop) - liftIO $ gegl_node_disconnect - (nodeGraph ud M.! KeyFGOver) - "aux" - liftIO $ traceIO "nodes linked" + nhs <- newHaskelloids + kid <- partSubscribe (subKeyboard $ subsystems ud) + (\kbdev -> when (msgKbdKeyMotion kbdev == SDL.Pressed) $ + case SDL.keysymKeycode (msgKbdKeysym kbdev) of + SDL.KeycodeSpace -> do + liftIO $ logIO Debug "TODO: PEW!" + SDL.KeycodeR -> do + liftIO $ logIO Debug "Reloading" + putAffection ud + { stateUUIDs = UUIDClean [] [] + } + loadGame stateChange + SDL.KeycodeEscape -> do + liftIO $ logIO Debug "Leave to Menu" + stateChange + _ -> return () + ) putAffection ud - { haskelloids = hs - , wonlost = Nothing - , shots = ParticleSystem - (ParticleStorage Nothing []) - (nodeGraph ud M.! KeyPNop) - (buffer ud) - , ship = Ship - { sPos = (375, 275) - , sVel = (0, 0) + { stateUUIDs = UUIDClean [] [kid] + , haskelloids = nhs + , ship = (ship ud) + { sPos = V2 400 300 + , sVel = V2 0 0 , sRot = 0 - , sFlange = nodeGraph ud M.! KeyShipRotate } - , pixelSize = 3 , state = InGame } - liftIO $ traceIO "game loaded" - present - (GeglRectangle 0 0 800 600) - (buffer ud) - True -excludeShip :: IO (Double, Double) -excludeShip = do - px <- randomRIO (0, 800) - py <- randomRIO (0, 600) - inter <- gegl_rectangle_intersect - (GeglRectangle px py 100 100) - (GeglRectangle 350 250 100 100) -- Ship's starting position and size - case inter of - Just _ -> - excludeShip - Nothing -> - return (fromIntegral px, fromIntegral py) updateGame :: Double -> Affection UserData () updateGame sec = do - ad <- get ud <- getAffection - when (((floor $ elapsedTime ad :: Int) * 100) `mod` 10 < 2 && pixelSize ud > 3) $ do - pd <- getAffection - liftIO $ gegl_node_set (nodeGraph pd M.! KeyPixelize) $ Operation "gegl:pixelize" - [ Property "size-x" $ PropertyInt $ pixelSize pd - 1 - , Property "size-y" $ PropertyInt $ pixelSize pd - 1 - ] - putAffection ud - { pixelSize = pixelSize ud -1 - } - let nx = fst (sPos $ ship ud) + fst (sVel $ ship ud) * sec - ny = snd (sPos $ ship ud) + snd (sVel $ ship ud) * sec - (nnx, nny) = wrapAround (nx, ny) 50 - liftIO $ gegl_node_set (nodeGraph ud M.! KeyShipTranslate) $ Operation "gegl:translate" - [ Property "x" $ PropertyDouble nnx - , Property "y" $ PropertyDouble nny - ] - liftIO $ gegl_node_set (nodeGraph ud M.! KeyShipRotate) $ Operation "gegl:rotate" - [ Property "degrees" $ PropertyDouble $ sRot $ ship ud - ] - td <- getAffection - putAffection td - { ship = (ship ud) - { sPos = (nnx, nny) - } - } - ud2 <- getAffection - nhs <- mapM (updateHaskelloid sec) (haskelloids ud2) - ud3 <- getAffection - putAffection ud3 + let nhs = map (updateHaskelloid sec) (haskelloids ud) + putAffection ud { haskelloids = nhs + , ship = updateShip sec (ship ud) } - ud3 <- getAffection - ups <- updateParticleSystem (shots ud3) sec shotsUpd - ud4 <- getAffection - when (isJust $ wonlost ud3) (winlose $ fromJust $ wonlost ud3) - putAffection ud4 - { shots = ups - } + +updateShip :: Double -> Ship -> Ship +updateShip ddt s@Ship{..} = s + { sPos = wrapAround (sPos + fmap (dt *) sVel) 40 + } + where + dt = realToFrac ddt drawGame :: Affection UserData () drawGame = do ud <- getAffection - liftIO $ gegl_node_process $ nodeGraph ud M.! KeySink - present - (GeglRectangle 0 0 800 600) - (buffer ud) - True + mapM_ drawHaskelloid (haskelloids ud) + drawShip (ship ud) -handleGameEvent :: SDL.EventPayload -> Affection UserData () -handleGameEvent e = do - ad <- get - wd <- getAffection - sec <- getDelta - case e of - SDL.KeyboardEvent dat -> - case SDL.keysymKeycode $ SDL.keyboardEventKeysym dat of - SDL.KeycodeLeft -> do - ud <- getAffection - when (SDL.keyboardEventKeyMotion dat == SDL.Pressed - && (isNothing $ wonlost ud)) $ do - let rawRot = (sRot $ ship ud) + 15 * sec - newRot - | rawRot > 360 = rawRot - 360 - | rawRot < 0 = rawRot + 360 - | otherwise = rawRot - putAffection ud - { ship = (ship ud) - { sRot = newRot - } - } - SDL.KeycodeRight -> do - ud <- getAffection - when (SDL.keyboardEventKeyMotion dat == SDL.Pressed - && (isNothing $ wonlost ud)) $ do - let rawRot = (sRot $ ship ud) - 15 * sec - newRot - | rawRot > 360 = rawRot - 360 - | rawRot < 0 = rawRot + 360 - | otherwise = rawRot - putAffection ud - { ship = (ship ud) - { sRot = newRot - } - } - SDL.KeycodeUp -> - when (SDL.keyboardEventKeyMotion dat == SDL.Pressed - && (isNothing $ wonlost wd)) $ do - ud <- getAffection - let vx = -10 * sin (toR $ sRot $ ship ud) + fst (sVel $ ship ud) - vy = -10 * cos (toR $ sRot $ ship ud) + snd (sVel $ ship ud) - putAffection ud - { ship = (ship ud) - { sVel = (vx, vy) - } - } - -- traceM $ show (vx, vy) ++ " " ++ show (sRot $ ship ud) - SDL.KeycodeSpace -> - when (SDL.keyboardEventKeyMotion dat == SDL.Pressed - && (isNothing $ wonlost wd)) $ do - ud <- getAffection - liftIO $ gegl_node_set (nodeGraph ud M.! KeyPixelize) $ - Operation "gegl:pixelize" - [ Property "size-x" $ PropertyInt 8 - , Property "size-y" $ PropertyInt 8 - ] - -- ad <- get - let posX = fst (sPos $ ship ud) + 23 - 35 * sin (toR $ sRot $ ship ud) - posY = snd (sPos $ ship ud) + 23 - 35 * cos (toR $ sRot $ ship ud) - tempRoot <- liftIO gegl_node_new - tempRect <- liftIO $ gegl_node_new_child tempRoot $ - Operation "gegl:rectangle" - [ Property "x" $ PropertyDouble posX - , Property "y" $ PropertyDouble posY - , Property "width" $ PropertyDouble 4 - , Property "height" $ PropertyDouble 4 - , Property "color" $ PropertyColor $ GEGL.RGBA 1 1 1 1 - ] - tempOver <- liftIO $ gegl_node_new_child tempRoot defaultOverOperation - _ <- liftIO $ gegl_node_connect_to tempRect "output" tempOver "aux" - ips <- insertParticle (shots ud) - Particle - { particleTimeToLive = 5 - , particleCreation = elapsedTime ad - , particlePosition = (posX, posY) - , particleRotation = 0 - , particleVelocity = - ( (floor $ -200 * (sin $ toR $ sRot $ ship ud)) - , (floor $ -200 * (cos $ toR $ sRot $ ship ud)) - ) - , particlePitchRate = 0 - , particleRootNode = tempRoot - , particleNodeGraph = M.fromList - [ ("root", tempRoot) - , ("over", tempOver) - , ("rect", tempRect) - ] - , particleStackCont = tempOver - , particleDrawFlange = tempOver - } - putAffection $ ud - { shots = ips - , pixelSize = 8 - } - SDL.KeycodeR -> - when (SDL.keyboardEventKeyMotion dat == SDL.Pressed - && isJust (wonlost wd)) $ do - liftIO $ traceIO "reloading" - liftIO $ clean wd - nd <- liftIO $ load - putAffection nd - loadGame - _ -> return () - SDL.WindowClosedEvent _ -> do - traceM "seeya!" - quit - _ -> return () +drawShip :: Ship -> Affection UserData () +drawShip Ship{..} = do + ctx <- nano <$> getAffection + liftIO $ drawImage ctx (sImg) (sPos - fmap (/2) dim) dim sRot 255 + where + dim = V2 40 40 diff --git a/src/Main.hs b/src/Main.hs index 4a1e68b..668b0a9 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -49,6 +49,7 @@ pre = do liftIO $ logIO A.Debug "Setting global resize event listener" _ <- partSubscribe (subWindow subs) $ \msg -> case msg of MsgWindowResize _ _ (V2 w h) -> do + liftIO $ logIO A.Debug "Window has been resized" let nw = floor $ fromIntegral h * (800/600) dw = floor $ (fromIntegral w - fromIntegral nw) / 2 GL.viewport $= (GL.Position dw 0, GL.Size nw h) diff --git a/src/Menu.hs b/src/Menu.hs index 2436a6a..fa12dcb 100644 --- a/src/Menu.hs +++ b/src/Menu.hs @@ -24,32 +24,27 @@ import Foreign.C.Types import Types import Commons -handleMenuEvent :: (Affection UserData ()) -> [SDL.EventPayload] -> Affection UserData () -handleMenuEvent _ es = do - (Subsystems w k) <- subsystems <$> getAffection - _ <- consumeSDLEvents w =<< consumeSDLEvents k es - return () - -loadMenu :: Affection UserData () -loadMenu = do +loadMenu :: (Affection UserData ()) -> Affection UserData () +loadMenu stateChange = do liftIO $ logIO A.Debug "Loading Menu" ud <- getAffection - hs <- newHaskelloids (haskImage ud) - _ <- partSubscribe (subKeyboard $ subsystems ud) - (\kbdev -> case SDL.keysymKeycode (msgKbdKeysym kbdev) of - SDL.KeycodeEscape -> do - liftIO $ logIO A.Debug "seeya" - quit - SDL.KeycodeF -> do - when (msgKbdKeyMotion kbdev == SDL.Pressed) $ do - liftIO $ logIO A.Debug "screen toggling" - toggleScreen - _ -> return () + hs <- newHaskelloids + kbdUUID <- partSubscribe (subKeyboard $ subsystems ud) + (\kbdev -> when (msgKbdKeyMotion kbdev == SDL.Pressed) $ + case SDL.keysymKeycode (msgKbdKeysym kbdev) of + SDL.KeycodeEscape -> do + liftIO $ logIO A.Debug "seeya" + quit + SDL.KeycodeSpace -> do + liftIO $ logIO A.Debug "Leaving Menu to Game" + stateChange + _ -> return () ) putAffection ud { haskelloids = hs , fade = FadeIn 1 , state = Menu + , stateUUIDs = UUIDClean [] [kbdUUID] -- , shots = (shots ud) -- { partSysParts = ParticleStorage Nothing [] } } @@ -83,12 +78,9 @@ drawMenu = do fontSize ctx 120 fontFace ctx "modulo" textAlign ctx (S.fromList [AlignCenter,AlignTop]) - -- (Bounds (V4 b0 b1 b2 b3)) <- textBoxBounds ctx x y' 150 "HASKELLOIDS" fillColor ctx (rgba 255 255 255 255) textBox ctx 0 200 800 "HASKELLOIDS" fillColor ctx (rgba 255 128 0 (alpha $ fade ud)) fontSize ctx 40 textBox ctx 0 350 800 "Press [Space] to Play\nPress [Esc] to exit" restore ctx - -- t <- getElapsedTime - -- liftIO $ drawSpinner (nano ud) 100 100 100 t diff --git a/src/StateMachine.hs b/src/StateMachine.hs index 0758306..ad5dffd 100644 --- a/src/StateMachine.hs +++ b/src/StateMachine.hs @@ -14,20 +14,30 @@ import System.Random (randomRIO) import Types import Commons --- import InGame +import InGame import Menu instance StateMachine State UserData where - smLoad Menu = loadMenu + smLoad Menu = loadMenu (smClean Menu >> smLoad InGame) - -- smLoad InGame = loadGame + smLoad InGame = loadGame (smClean InGame >> smLoad Menu) smUpdate Menu = updateMenu - -- smUpdate InGame sec = updateGame sec + smUpdate InGame = updateGame smDraw Menu = drawMenu - -- smDraw InGame = drawGame + smDraw InGame = drawGame smEvent _ _ = return () + + smClean _ = do + ud <- getAffection + let (UUIDClean uuwin uukbd) = stateUUIDs ud + (Subsystems win kbd) = subsystems ud + mapM_ (partUnSubscribe win) uuwin + mapM_ (partUnSubscribe kbd) uukbd + putAffection ud + { stateUUIDs = UUIDClean [] [] + } diff --git a/src/Types.hs b/src/Types.hs index c063c6b..017e6d5 100644 --- a/src/Types.hs +++ b/src/Types.hs @@ -23,6 +23,7 @@ data UserData = UserData , font :: Font , subsystems :: Subsystems , haskImage :: Image + , stateUUIDs :: UUIDClean } data Ship = Ship @@ -60,6 +61,11 @@ data Subsystems = Subsystems , subKeyboard :: Keyboard } +data UUIDClean = UUIDClean + { uuWindow :: [MsgId WindowMessage] + , uuKeyboard :: [MsgId KeyboardMessage] + } + newtype Window = Window (TVar [(UUID, WindowMessage -> Affection UserData ())]) instance Participant Window WindowMessage UserData where @@ -67,10 +73,16 @@ instance Participant Window WindowMessage UserData where subTups <- liftIO $ readTVarIO t return $ map snd subTups - partSubscribe (Window t) = generalSubscribe t + partSubscribe (Window t) funct = do + uuid <- genUUID + liftIO $ atomically $ modifyTVar' t ((uuid, funct) :) + return $ MsgId uuid MsgWindowEmptyEvent - partUnSubscribe (Window t) uuid = - liftIO $ atomically $ modifyTVar' t (filter (\(u, _) -> u /= uuid)) + partUnSubscribe (Window t) (MsgId uuid _) = + liftIO $ atomically $ modifyTVar' t (filter (flip filterMsg uuid)) + where + filterMsg :: (UUID, WindowMessage -> Affection UserData ()) -> UUID -> Bool + filterMsg (u, _) p = u /= p instance SDLSubsystem Window UserData where consumeSDLEvents = consumeSDLWindowEvents @@ -82,15 +94,16 @@ instance Participant Keyboard KeyboardMessage UserData where subTups <- liftIO $ readTVarIO t return $ map snd subTups - partSubscribe (Keyboard t) = generalSubscribe t + partSubscribe (Keyboard t) funct = do + uuid <- genUUID + liftIO $ atomically $ modifyTVar' t ((uuid, funct) :) + return $ MsgId uuid MsgKeyboardEmptyEvent - partUnSubscribe (Keyboard t) uuid = - liftIO $ atomically $ modifyTVar' t (filter (\(u, _) -> u /= uuid)) + partUnSubscribe (Keyboard t) (MsgId uuid _) = + liftIO $ atomically $ modifyTVar' t (filter (flip filterMsg uuid)) + where + filterMsg :: (UUID, KeyboardMessage -> Affection UserData ()) -> UUID -> Bool + filterMsg (u, _) p = u /= p instance SDLSubsystem Keyboard UserData where consumeSDLEvents = consumeSDLKeyboardEvents - -generalSubscribe t funct = do - uuid <- genUUID - liftIO $ atomically $ modifyTVar' t ((uuid, funct) :) - return uuid