From 35d0b2d664efc5214a4ffbfd165dbee45dba3a2c Mon Sep 17 00:00:00 2001 From: amrouchi Date: Mon, 1 Dec 2025 19:32:24 +0100 Subject: [PATCH] Transition du menu aux jeux --- Makefile | 18 ++++--- obj/main.o | Bin 3304 -> 3368 bytes src/game_view.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ src/game_view.h | 12 +++++ src/main.c | 2 + taquin | Bin 21848 -> 0 bytes 6 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 src/game_view.c create mode 100644 src/game_view.h delete mode 100755 taquin diff --git a/Makefile b/Makefile index 140eca7..b358db2 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,12 @@ # Variables de compilation CC = gcc -CFLAGS = -Wall -Wextra -std=c89 +CFLAGS = -Wall -Wextra -std=c89 LDFLAGS = -lgraph TARGET = taquin -# Liste de tous les fichiers sources (.c) -SRCS = src/main.c src/menu_view.c src/game_logic.c src/images.c src/utils.c +# Liste de tous les fichiers sources (.c) - INCLUT game_view.c +SRCS = src/main.c src/menu_view.c src/game_logic.c src/images.c src/utils.c src/game_view.c # Liste de tous les fichiers objets (.o) correspondants OBJS = $(patsubst src/%.c, obj/%.o, $(SRCS)) @@ -21,20 +21,22 @@ all: dir $(TARGET) # Crée le dossier obj/ si non existant dir: - @mkdir -p obj + @mkdir -p obj # Règle de liaison : crée l'exécutable taquin à partir de tous les objets $(TARGET): $(OBJS) - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) # Règle générique pour la compilation de tous les .c en .o obj/%.o: src/%.c - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c $< -o $@ # Exécute le programme run: $(TARGET) - ./$(TARGET) + ./$(TARGET) # Nettoyage clean: - @rm -rf obj $(TARGET) + @rm -rf obj $(TARGET) + +.PHONY : all clean run diff --git a/obj/main.o b/obj/main.o index 945b9cba7878da5042bcef1da0429320c997d862..9e8a3b2f78c874c139c7ef91ac58c82ed6340397 100644 GIT binary patch delta 305 zcmaDMxk74!2IGp2np%vE_a}!iZf5uBb)DeRd3-VxQ_$oHrXxb~ObiSRj(h@bOwPP) z9?i_mLX-8Fs~F`suVkLj$oOjVMrQHJ39J&VY>W&H0+S1wg;~WQEKZTh6It(brYGj6 z#^>bc7fjA)v){ad?F1v^`N@?W`nI1K8Nh&rfq_Asfq~)Ae+c-4Brbs@E(&r80|Ns{ zz2xMx9KRXmC!gdr=e)rNHip4rGAEZgWBg=CE_=rK$&Fn0j0uwua@jMkoy^E>&v delta 247 zcmZ1>^+Ixj24luXO)W;o%acPGH%}I3@?~aVV3-`wbW}{3iGhK^kx!tF$(fhUqnVkR zjfsbyWAa8$xycdC5sbo{H!{y>Wc)NakX4_NXL2K}_~Z?&4<^rIv)g=)?Gz*9t;q{H z^cg=)zQ`fY%Ly`yfq{XAfq_9{GB4+EM&ZevT;`k`*ciY-W3nfgIb-nTMlO5C;K>KM z>=`2_GjiKAE}iViZO?dcawE4r +#include +#include + +#define WINDOW_WIDTH 800 +#define WINDOW_HEIGHT 600 + +extern int _X; +extern int _Y; +#define MARGIN 50 /* Marge autour du plateau */ + + +/* Fonction utilitaire : vérifie si un clic est sur une tuile donnée */ +static int is_in_tile_rect(int x_click, int y_click, int tile_x, int tile_y, int tile_w, int tile_h) +{ + return (x_click >= tile_x && x_click <= tile_x + tile_w && + y_click >= tile_y && y_click <= tile_y + tile_h); +} + + +/* Dessine le plateau de jeu */ +void game_render(const game_state_t *state) +{ + int i, r, c; + couleur C_FOND = CouleurParNom("gray"); + couleur C_BORDURE = CouleurParNom("black"); + + EffacerEcran(C_FOND); + + /* Calcul de la taille de chaque tuile pour l'affichage (utilise la taille de la première tuile) */ + int tile_display_w = state->all_tiles[0]->width; + int tile_display_h = state->all_tiles[0]->height; + + + ChoisirCouleurDessin(C_BORDURE); + + /* Boucle sur toutes les cases du plateau */ + for (i = 0; i < state->rows * state->cols; i++) { + int tile_id = state->permutation[i]; + int x_pos, y_pos; + + r = i / state->cols; + c = i % state->cols; + + /* Position d'affichage sur l'écran */ + x_pos = MARGIN + c * tile_display_w; + y_pos = MARGIN + r * tile_display_h; + + if (tile_id != -1) { /* Ne dessine pas si c'est la case vide */ + tile_t *current_tile = state->all_tiles[tile_id]; + + /* ChargerImage(fichier, x_dst, y_dst, x_src, y_src, l, h) */ + ChargerImage(current_tile->path, + x_pos, y_pos, + current_tile->src_x, current_tile->src_y, + tile_display_w, tile_display_h); + + /* Dessine une fine bordure autour de la tuile */ + DessinerRectangle(x_pos, y_pos, tile_display_w, tile_display_h); + + } else { + /* Dessine la case vide en jaune (ou couleur distincte) */ + ChoisirCouleurDessin(CouleurParNom("yellow")); + RemplirRectangle(x_pos, y_pos, tile_display_w, tile_display_h); + ChoisirCouleurDessin(C_BORDURE); + DessinerRectangle(x_pos, y_pos, tile_display_w, tile_display_h); + } + } + + /* Affichage du compteur de coups */ + char buffer[100]; + sprintf(buffer, "Coups: %lu", state->moves); + EcrireTexte(MARGIN, WINDOW_HEIGHT - 30, buffer, 1); + + /* Affichage de la victoire si résolu */ + if (state->is_solved) { + /* TODO: Afficher un grand BRAVO */ + } +} + + +/* Gère les entrées (clic/clavier) et la boucle principale du jeu */ +void game_loop(game_state_t *state) +{ + unsigned long next_update = Microsecondes() + 50000L; + int go_on = 1; + + while (go_on && !state->is_solved) + { + /* Rendu et rafraîchissement */ + if (Microsecondes() > next_update) + { + game_render(state); + CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0); + next_update = Microsecondes() + 50000L; + } + + /* Gestion des événements Souris */ + if (SourisCliquee()) + { + int i; + int x_click = _X; + int y_click = _Y; + int tile_w = state->all_tiles[0]->width; + int tile_h = state->all_tiles[0]->height; + + /* Parcourir toutes les tuiles pour voir laquelle a été cliquée */ + for (i = 0; i < state->rows * state->cols; i++) { + int r = i / state->cols; + int c = i % state->cols; + + int x_pos = MARGIN + c * tile_w; + int y_pos = MARGIN + r * tile_h; + + if (is_in_tile_rect(x_click, y_click, x_pos, y_pos, tile_w, tile_h)) { + /* Tenter de déplacer la tuile cliquée */ + game_move_tile(state, i); + break; + } + } + } + + /* Gestion des événements Clavier */ + if (ToucheEnAttente()) { + int key = Touche(); + if (key == XK_Escape) { + go_on = 0; /* Quitter la boucle de jeu */ + } + /* TODO: Ajouter les flèches pour les déplacements clavier */ + } + } + + /* Si la boucle est terminée par la victoire, on affiche le BRAVO */ + if (state->is_solved) { + game_render(state); /* Dernière mise à jour pour montrer l'image complète */ + CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0); + printf("BRAVO ! Partie terminee en %lu coups.\n", state->moves); + Touche(); /* Attend une touche avant de nettoyer */ + } +} \ No newline at end of file diff --git a/src/game_view.h b/src/game_view.h new file mode 100644 index 0000000..e3e4015 --- /dev/null +++ b/src/game_view.h @@ -0,0 +1,12 @@ +#ifndef GAME_VIEW_H +#define GAME_VIEW_H + +#include "game_logic.h" /* Nécessaire pour connaître la structure game_state_t */ + +/* Dessine le plateau de jeu, les tuiles à leur position actuelle, et le compteur de coups. */ +void game_render(const game_state_t *state); + +/* Gère la boucle principale du jeu, les événements (clics/clavier) et les rafraîchissements. */ +void game_loop(game_state_t *state); + +#endif /* GAME_VIEW_H */ \ No newline at end of file diff --git a/src/main.c b/src/main.c index bb57b5c..bd2428a 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ * Point d'entrée du programme Taquin. * Gère la boucle principale des événements et la transition de vue (Menu -> Jeu). */ +#include "game_view.h" #include "menu_view.h" #include "game_logic.h" /* Nouveau: pour initialiser le jeu */ @@ -76,6 +77,7 @@ int main(void) game_state.rows, game_state.cols); /* TODO: Boucle de JEU (GRANDE PARTIE 3) */ + game_loop(&game_state); /* 3.2. Nettoyage après la fin de la partie */ images_free_tiles(tiles, num_tiles); diff --git a/taquin b/taquin deleted file mode 100755 index dbd973c166d07ea6a103da7bcbcb287994b987fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21848 zcmb<-^>JfjWMqH=W(GS35buK^M8p9?G2HNlG8h;b92hJZco`fR3BTn1*SJ_!(mfq?;?mVv5+(I7X0gg`XNJ`fulzQGF-h0zQG5I#sB zD~Ji@!^B~9p(sd_fdNLt#6kMN_8CCr8PI4Su%QeLFdA7OC~OYcLi8Pgh98Xffckp_ zl!oa81s6!)1*pCYP<=4^1IR%P3=A+D7M>tCg0KbDJaifsA21qSUjO6l!gW`gMLnCl9`EqPKs_$W?pH9ZiR)Ju9=BmalW1r*m{t=KuG}< z{qBCD3``9S2S8#l{frEZD10U;AFLUg_C**N!1(~ApMSlS(`mbK^`gXQ^IB^cI<5`v zS`9J}|KdNeF_fs8*r%a#UWmdLtGArcsdSoX+{PHK?X?%g+NHm!17)zR6GGH4lCbu zpyCctahQ6B`1thP{Ji+$lEk8t_;`kR&k*1El+>cs^vvRt)S?hy=bZe!)R4raoK%P$ zRvFjiqRgVykkpEjREChm%$%H5=ZwV6yj0iZqQpF?NN{OEKz>eUaw>ysT3TXqY7s=z zIU_%_IJ3w(zceScw8$m3xHvP9!8yMmGqorxKQEObB)>E{Bh@v}v7{t5uOyYhEwv~& zwaC3Fu^=O}ur!q+IKQ+gv)DNY#7SicO3f|E$t(&=O)g2yOV3GVa4t$sEpkiEOD!o% zW$?_)EXhpF$t*@T0Agh-k{*ba4Dk^RzM08I`NgTp`FSa+#SHP03{YnVBo_JQ=Q22F zBo?Ko7J23-rl&F#mlP!zR5HYaf-*TfJ~<;hJ}ogbhas&fHI<MVF3VPIf5fh5icQ356}Ac=#@T(BSm1H%m@acGkjEcF0MTpla} zAz=9!RBt1fx3K&Q5(m|p5Y-F}u>1`YSB43KXsCbLp>;1v2!uJ1#KDy?NRWYnK>$e{ zRA)nl86=RzL3Y5z6_CV1VFVM`KoSSp4HGv&5{HE~NX`ODoD(Df#STc~Tu?C(<$)y5 z4HAIj03>l9s2GTfKoW;Gy+OhZ2}t7nU=awBfg}!1YG8>1BynM|2!yCW5(l-HAfgNm z4M^h9raM@w14&#AECL}WAc>1ZguvtsBykC_2!vRGBrXXN0+TC{#HGL@5Ml$8xHLov zOzuDuhxKJZ5(kjPWkCW^d;&>a4k`wsE+B~`w;ygGi7SE>j^fb}ARz=k^UMA6Xnw=t z(apNio`J!m^*{;J{|g??M>r0HP5Ezn%ASGYzv>x#1_pk42ZsNuAbti&?&X93|NsA2 zJ!H?okO8V?US0t6cY*kzqVMGaFn<$>4=VCrZUFOFf%u>z|K$QOe-VfeD*9ed0P|;o z_@E;1WdoQ$3B(5#buSCR{4Nk5RK&eZ0P~wbd{EK$G62l40`Wmb+Div8zX-$!6=g3C z!2B!_A5?_BQ~>jnKzvZq^-=)Lj{@;QRnJQXFh2;y2Nhv2Kl}sv*9*i4RY5NwfcZ`! zKB($>c>&C~0`Wmb+sgxBz7dEID$-tV0Q0p#d{9yLasimH1mc5=u$L3Sd?^qgRCK*; z0P}@Fd{B|~vH;BI0`Wmb)yo7hp9#bV6;Uq(!2Dl!3=A2dqUogrnEwgH2Ng*#4gUTA z4~lQYx1OCB<2*Vac{D%y5D?;Oc);+aN3ZQI1_p-zqNi;c7`~+G@yoY>;+Vms*Y=?u z1A|8|>n#vv`J+VCqnowQ7Lrsr|3BcDZvZJg45dAKZ8w4x_L{B&QJVieIzM-Y^25|g;kj5|X!oUF24{~3F?O8hp28L4OP>*I?BhWyIN9WTL zUXN~DGdqwI6>J$8UL^nj|Nj{45<3P4#@NFM_a06|utDh+WZuj4|NsAodUQSw_Go-F zgMon|#iN@=RfBAq`uqR?&Il$3hFuEG3=I1~DQG{4coF&U|Ns49 zCF}qF|KEB1g~q@C|2=wL8$3FXzu3XZzyQ(T1QKNpI1Dni6_iw8b~3=^(m-;SVA0|L znAXjV3=CNeSqzR~TOD_RtlbH+XBUXr2O=QWuK4r+zen>C0f;?PAhVF|fd~u#{r|u9 zKnV}b^j9pPSc5q7BO3!lw`))90sfYp|NsAYyY@8yVB~MT%)r3V9oo|E+QGm6P-iPx zDzw3)*Y!Z>HIUy5_!th#&A>q;O`@o~qL!tBfi(h;U3?9u#3_LnpD?qk}c667vcy#xII3B&O6F^ox z;sm>L!oDwzpm00>!ipE_7Gd;S&MnarJ>upl@7^Z!3sn@4x(ixdxS5paZ;u)gpDg=Tl`kCTT%Ny4ME_J>Ee>yP80;AQ}` z99Tf56@jJ1OsGkjyt@`!<|8ZAvCVsgH zlp2R(XO^}wba+E>HK!0^J41(cIO zY8Wr{R%jqpaUrYHfT`+1G3ki}$iq;RSm0{VOgez9>K-!#DF5sLMPt~H|NnP_Vq+I5 zA%QdZe$dFsi?iQBMJMY$agg!HU&#FcrRn1@)PDT`@3<3`fPH#db0ioTuxkFy%)l@K zlrK{}v?1kp3G0jMAOHVDvvTtr2anF$6Wy%t77PrXt`E9duq;&t|xa%KK>h1RZ(;fPwyYxx7>jPMN28nkbe=(Pd zfuZ$437xu5rJDmbA+Zh=cnqBWOHrL)^s$1V3`lj3U1LL9Y+85ovFQ7(r{&eg- zu@e+QoyT89LrhQuo8Z9G{DYmp-x5?1f=qN^0cE&u*AtxqEH9NoX&GYPh28)S+(vSs z8_CSy_Yzc8!Hfju8L*L%(*I4j>lb`Z1l4b?2TGt$Ewt>nHkQ2W! z;&);yBRJgTA-?8l{=r-q0A=?EK%K|&+7=pM;FRFF1C)+-f+~q!pmfxE{DnNk6mgKw z;|@HaO#Yf{!fW;kuURI%W}E;|5(*xjwJ*R$(2EOSK~*Gw%R_j*EcfmI|4!FGjkSNI z|1&U@3V3w8zBul{18VoZ+|9ti&{+E?2qXdW{)=vC41o$skiu?Q47~uwP!B|T2uL}| zYY^qkb>(oSAg_UxzD{YZ{S%C&4iu{O{t$K05Pi`Z!13CqvGz|OsygO6b+|gHc^t1r z8f*XXg4A(?HDJF^^djdmm1CP&@bJtZx}CF zy8fw`>302L?fRicq&xIOx9ba#;E#HCQ0z0jW(5ZywB~DmqX03}qcik_N2l)#ke#4B zpY-Mb|L)Qs-L8Ljf->7K5Yc)3#qH1F9RE!ilH+y0KythZhz8jO*5L>)q&+(?plAiv zy-;s>G`}(EtbNm2`l2)RNvH1vpH9~sE}gztx>VJi1*!bP7PZpaAIqr` z_2_0TH3B8SgS$YD{(WGBdRYa9Kw`&Vto-!<|LeHpu0KFQ{8|pCwLA2ONAe|)gO8Xz z7!QFG0#mc=55{iSKj47)QF9%k@DEI3^D7n)#tX;69mj6hKak?=MQ4Bjyf_koH8?%G z!LBQj0aa*VPUrC#aUfrGyZ-Pv?f~lHGC)&Zut)P73sBY8S$YJyvH8OA0I2xub`Y?1 zJyOaA&ZaNBK~1;XBMcRyU^!5jp6GU9;a`8q()CCUJ6O@{Ot4%5i$|~T9gp778{Mu) zI*-4Q`U`GSo#-wAh5w0e2LX>>-zOfup$|HbzxewH)MmQT9r{4?Lg(=p&sZ23IuCcd z-sui~0v5Q+!oa|IqxlD8DN3<{-uyoO0b~cf`Q7{mTtIi0KIsm90t!(`R%ZJTDym^# znh&XPUVwrLqzo1<7rGgssmG%m66YW%&j6>1ULH`x2t&)EZpKci1iB7TEdPN>f)Zl@ zDC9u;B|IRt94KK)fSd?QZ=eAJkk>k$6u^ZfG=e*8!R28$ST7{h;VyLG=nh3oDcuas zKmM0M{sB`ff|?f3f!zSlXy9fLT3Y#Gc;L7zc!cJ->lJWH zj{~Oxa8^6fZ2;zgBODajj=w=g=?zfPdi;e5sAV^!+oknEr|X^O+8c~@9Nn&WtX(gZ z-0u#(1JVeIH0^(&6mqB2^+L1j6~=DYE7q<@YG#4tk#h2h;|}2QON@rxrgyN094NVa zcy!k8=q%lWmfVlK9(czDYTX|>1Zr#5Zege}Zm!+JRIl6Zx&>TN9tHW$qnA}!57ZoG zVe;q=J>b!Nh{L1vm`CUJ7cuYt|9>sz(ari<7u0J+k#l$lN}8@a2zGHn;BF2`gyH291_p-xCJYP= zFLu8H6@;!oJU}%{sdRVf190U8?$Cq!QQ-Xlatb6z{qX1wmGFSXo)gHvZcxSeqB8*0 zUHH)*`ld5Lr`z=o|9aOK;7aaCXMjSt>ka<(u5Vy`6;SyFF0&1~T^}GtLAUD%4@OXd z{KKP@soC`bBdBEzPB$m`dq6{V&8{~XyIpTsyPo0iF@bdEK0vb(qEzr`u6@B!QhD6< z56I82qacNTuLvZXyIo&+FkbNJ29H}>;gah-{(|)lC~1P~3pA~eet)y;A5h6|?fRr< z9w=Ht;eYA%|NroYWM}OkP_1F0M|Y z?p6w3sig`9MTb|F=qb1tfz}r)sHP}XfQa1GoW#8J)KonMpTxZ6)ZEm(5`~mhg`7l% zr2Nw4oKz4eE45TlPY*O{%21vGT0U2ln!=EjlbD>%kdj!Gt&m=nSjmuHl$x5y;Oy_` z=II_9K!Ey^t|fv{7PGxAGQ zQ}wt|++zrK4zdf4Fhq>OA`Fbu%+{c_?Vt($4fp>42MszkJox_~)G4fd`2Rm>l&k0Q z|NkD03=D@J|No!C$iNW({Qv(B&}8w;|NmDoGBD)4`v3m~BLl;pSO5RNU}Ru0e*OPH zXxxAI>;L~Xm>3w|y#D{+gNcFR>zn`oGng0{e!l(xzk`W^!SLPx|0|dn7`Wg6|9^&w zf#KHs|Nq}GF)+k^`2U}WnSnv!|2sf~vJ4Cipal$|2w=?sAR>274)MEn^k%ay*c_7zPH0zz6^T3xg(v9Qg#= zn4EdpJerxA*_e3PLEU2p1_qEFpcM)>kN*ER1K9&pR|ru8k_UB)gC70=KNaL=m^||Y zW{?VyJSZNHKSi^LnGb9UNd5_E?(zBm|Dd(a3^4sne?i*8_OmcDFwA-J|37#M7F^yN zF0aDKz;Ncp|NrI4?qe!~%eyc#FetzL|Gxu8z8Nl`0-E%B`Tsw7$t2AD9I!Ol{uYq^ zFaQ7N1cfI|o|%OaqypsrC7>yiSO5Qm+=+1ie~>g-{}Dz8hRoOh|ARIRz~zg<(%?1f zptYloumArCEewInyEZd3U4Wss%GLStJm>3v(-~In@ zff5$R;IIIhv4M$!Vd?w-|0f}v!PE;e0GghzFflL)fB63&w3r6&))0sikR4x`7#Mgy z{Qs|tY(@e^9wao1M?+vV1V%$(Gz3ONU^E0qLx3J30Ncki0kq;6X)nrlP&){T5868f zau0YFBZvWRl`}Aa7CwWxDd0v80|U72!@$4*+b;xKI1G}9HoF<5KpfCM9q7IxP`d~u z1e5>z?|(jse*o0xW?*0dE$jyIGe9f285qF(#X78*%b@f&D18h{UxU)mp!7E=%?4T_&%nSS2Bp=Yv>B9kgVJG8It@yfLFqOq zJq=1PgVNie^f4%X4N5M9Kpva<-ca@0&`m|)z9RzzLo`%81}YBjGcqtR6oU7nW4gZz zTy{t>!1nvW@&jmLWX2a;eAgzxhQa~T*IK>M#58N}iF7$&|QY_BK-dU_RP z0_~fYV0Zuv0H}rlChYsuL6hUqA`z+*LS4kMzZf))F2umca0^<%f&2WR@&{}_9|P<> z4Dgr+0|UbwusM7Tnb6IJ;65}11H(6HTtaL^kgPcN7YpGKR|knR@iV~6Wtd62AaMph zhKZno5(WkaaDSG8fx#Xs9tqu~2<`_nFfjOl#bLS;bOa9ZY#id1IK=yKh|j|zz8Z%( zXaOLopN?=Lgmo3XpIU$ccJ2mf;}A#&G&X@Pe!nt;(g{cfD&}Vb?VZI;KQhqxJq}Ia z;4vo#1_l!*?ECTk!Rk@X2Jw<{h!-<4FbFb9FmOQk!GhF+a6MEURxW|WK)45oIg`QS zd$hBZ+2Hqd$j=$F)%QAgT-OG5p*nAoR47wc+`=B0X(+E zz`&3P7DuRqv8r*1_c4Rgl_Wy}TKrCChMXG!+gA)rx6`2Fuzkg#dIDs}O0fBS3`Wof z4|vRyfq`KwSRAAR6(7YRu8l+d2H2gL>F_=d^?$(Pd<+Yrd|75{xn43uN>O5Yd{Svi zNq!!LU6NW+5}yn@rT{d-kXam`nHOJ_nq0z=o|u~&pOc@SnXH%0keQc~S`lB8AD^6` zUzAeJkd~R35}%lol?c)qpP84EnVee80G?1N)=Osa^mTN1jSp}P@d#!pEy>IQiN(je z`-R54dc?a0Ir_TBd$b#xumbMEW`UdOBk{7y)s_ z0@zO(iFqkGsqxvVl@Qm0k1aqu90KLM1FVNBfX*$*gt|Q*WJG*PW)9pp@x_qyACOLq zfSifo06Vt;bVLFA84Fm>hk%^WfH)KauT6EJ=i%;Q&b!(D2L6FD*`uPtM6q&PF@Q0mWqKsSYS&=qFpm$A|bj$GiHu zfR5#ePbtoihu8r<5(5%VnR%JeFTI%)Aol(HqW4hjGM5FvQ0v z6&EAB9c)NqQgM7)Vh+Xu7H~J3Kx{0|C{0VtNsTW~OoJVI0apTwKJY0PC?eq0pIIDV zoS##cn!#AmRM0^gk6{Y4Rf;2!`1vw=Qdf+J60~J^d zdTE(?nGAYG`QVVyOU;N+D*}~Q87V~!a2`ZQd}0x3suZjP#!jisOU%toX3$H|F98#J zU<)9IB^4Jl=q2apf~I8=Whn(LPIf1@}22BCzom7!4b5f!UAl|LIWuP7v)3u<;uh4IA$P z=?9JRpzDY9FA?KS@Pl)p;}M|r4K*4}p{F0v9yd^!g3JdgP=M-#(cn33kOUM%rQy~r z2lrzU_QU#*FuD+QA^=n`h=S<{u|aq(ntoV65Jtns?LcZl7~TDwq55I*2kSq<=zNgp zKpLSK7Jg7J18DafNC`|ou5e1~7wWpEwTYz?6GB7Z}XwaSlm|hT#Za-*uB502V zG~2?*BVp(Gp{s}SVf1|l1_scf4KV$%bB<1cjuU_l=7B7RVwgS{{Tez}3DXZ7kAR)a z2+Mz<^baxurVkd6piNyM|HJgd&O16_4^qv*0NRKIVL?ckei;1|8h{qJ2#2L5uyTZ7zVsv03rh+ zc^M&R62i(!h$sUCOh0=51GyEX2APJXJ&-sIYe4OXm4l$+GLYM0{)UyGpy5}T+hKY^ m^aKwO$-tn8mSAD_LS#XGH_&NXFdl;5=L2Djp=m(lG5`R?lcxCq