From 546f891acd0661feefbad517cd1c4508e75c937d Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sat, 30 Nov 2019 14:44:04 +0200 Subject: [PATCH] TNT and change goal calculation --- src/game.js | 20 +++++--- src/index.js | 3 +- src/level.js | 99 +++++++++++++++++++++++++++++++++++----- src/player.js | 7 +++ src/utils.js | 4 ++ static/barrel_piece.png | Bin 0 -> 1250 bytes static/explosion.png | Bin 0 -> 8768 bytes static/tnt.png | Bin 0 -> 5300 bytes 8 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 static/barrel_piece.png create mode 100644 static/explosion.png create mode 100644 static/tnt.png diff --git a/src/game.js b/src/game.js index f0c532e..2051aec 100644 --- a/src/game.js +++ b/src/game.js @@ -1,13 +1,13 @@ import { canvas, ctx } from './canvas' -import { Level, Rock, Gold, Diamond, Lootbag } from './level' +import { Level, Rock, Gold, Diamond, Lootbag, BarrelPiece } from './level' import { randomi } from './utils' -const MAP_CLEARANCE_PERCENTAGE = 80 +const MAP_CLEARANCE_PERCENTAGE = 90 const REWARD_TABLE = { rock: 16, - gold: [129, 543, 2399], - diamond: 599, + gold: [229, 843, 1299], + diamond: 1000, lootbag: [5, 5000] } @@ -32,7 +32,7 @@ export class Game { this.wait = 0 } - static calculateScore (obj, skipLoot) { + static calculateScore (obj) { if (obj instanceof Rock) { return REWARD_TABLE.rock * obj.size } @@ -45,7 +45,9 @@ export class Game { return REWARD_TABLE.diamond } - if (skipLoot) return 0 + if (obj instanceof BarrelPiece) { + return 1 + } if (obj instanceof Lootbag) { let ssChance = randomi(0, 3) @@ -61,7 +63,10 @@ export class Game { static calculateLevelScore (level) { let total = 0 for (let i in level.objects) { - total += Game.calculateScore(level.objects[i], true) + let obj = level.objects[i] + if (obj instanceof Gold) { + total += REWARD_TABLE.gold[obj.size - 1] + } } return total } @@ -125,6 +130,7 @@ export class Game { return } + this.level.update() this.player.update(this.level) } diff --git a/src/index.js b/src/index.js index d1ec907..fe18027 100644 --- a/src/index.js +++ b/src/index.js @@ -35,7 +35,8 @@ function start () { async function loadAll () { let images = ['static/hook_open.png', 'static/gold_1.png', 'static/gold_2.png', 'static/gold_3.png', - 'static/rock_1.png', 'static/rock_2.png', 'static/rock_3.png', 'static/diamond.png', 'static/loot.png'] + 'static/rock_1.png', 'static/rock_2.png', 'static/rock_3.png', 'static/diamond.png', 'static/loot.png', + 'static/tnt.png', 'static/barrel_piece.png', 'static/explosion.png'] for (let i in images) { await RES.loadImage(images[i]) } diff --git a/src/level.js b/src/level.js index ab87dfc..28ce75e 100644 --- a/src/level.js +++ b/src/level.js @@ -1,8 +1,10 @@ import { ctx } from './canvas' -import { randomi } from './utils' +import { randomi, distanceTo } from './utils' import RES from './resource' -const offset = 50 +const OFFSET = 50 +const TNT_START = 5 +const DIAMOND_START = 3 // Objects @@ -75,7 +77,46 @@ export class Lootbag extends GameObject { } get weight () { - return 0.56 + return 0.45 + } +} + +export class BarrelPiece extends GameObject { + constructor (x, y) { + super(x, y, 30, 18, 'static/barrel_piece.png') + } + + get weight () { + return 0.05 + } +} + +export class TNTBarrel extends GameObject { + constructor (x, y) { + super(x, y, 40, 55, 'static/tnt.png') + this.radius = 156 + } + + get weight () { + return 0.0 + } + + explode (level) { + for (let i in level.objects) { + let obj = level.objects[i] + if (distanceTo(obj, this) < this.radius) { + if (obj instanceof TNTBarrel && obj !== this && obj.physical) { + obj.explode(level) + continue + } + obj.destroy() + } + } + this.destroy() + level.placeExplosion(this.x, this.y, this.radius) + let b = new BarrelPiece(this.x, this.y) + level.objects.push(b) + return b } } @@ -85,51 +126,85 @@ export class Level { constructor (id, objects) { this.id = id this.objects = objects || [] + this.explosions = [] + } + + placeExplosion (x, y, r) { + this.explosions.push({ x, y, time: 30, r }) } draw () { for (let i in this.objects) { this.objects[i].draw() } + + let expl = RES.loadImage('static/explosion.png', true) + for (let i in this.explosions) { + let ex = this.explosions[i] + let r = ex.r * 1.5 + ctx.drawImage(expl, ctx.oX + ex.x - r / 2, ctx.oY + ex.y - r / 2, r, r) + } + } + + update () { + let toKeep = [] + for (let i in this.explosions) { + let ex = this.explosions[i] + if (ex.time > 0) { + ex.time-- + ex.r -= randomi(-10, 10) + toKeep.push(ex) + continue + } + } + this.explosions = toKeep } static create (index, my, width, height) { let objects = [] let rocks = randomi(4, 12) let gold = randomi(4, 12) - let diamond = randomi(0, 2) + let diamond = index >= DIAMOND_START ? randomi(0, 2) : 0 let loot = randomi(0, 2) + let tnt = index >= TNT_START ? randomi(0, 4) : 0 // Add rocks for (let r = 0; r < rocks; r++) { - let x = randomi(offset, width - offset) - let y = randomi(offset + my, height - (offset + my)) + let x = randomi(OFFSET, width - OFFSET) + let y = randomi(OFFSET + my, height - (OFFSET + my)) let size = randomi(1, 4) objects.push(new Rock(x, y, size)) } // Add gold for (let r = 0; r < gold; r++) { - let x = randomi(offset, width - offset) - let y = randomi(offset + my, height - (offset + my)) + let x = randomi(OFFSET, width - OFFSET) + let y = randomi(OFFSET + my, height - (OFFSET + my)) let size = randomi(1, 4) objects.push(new Gold(x, y, size)) } // Add diamonds for (let r = 0; r < diamond; r++) { - let x = randomi(offset, width - offset) - let y = randomi(offset + my, height - (offset + my)) + let x = randomi(OFFSET, width - OFFSET) + let y = randomi(OFFSET + my, height - (OFFSET + my)) objects.push(new Diamond(x, y)) } // Add loot for (let r = 0; r < loot; r++) { - let x = randomi(offset, width - offset) - let y = randomi(offset + my, height - (offset + my)) + let x = randomi(OFFSET, width - OFFSET) + let y = randomi(OFFSET + my, height - (OFFSET + my)) objects.push(new Lootbag(x, y)) } + // Add TNT + for (let r = 0; r < tnt; r++) { + let x = randomi(OFFSET, width - OFFSET) + let y = randomi(OFFSET + my + 10, height - (OFFSET + my) - 10) + objects.push(new TNTBarrel(x, y)) + } + let n = new Level(index, objects) return n } diff --git a/src/player.js b/src/player.js index 3c52906..8921030 100644 --- a/src/player.js +++ b/src/player.js @@ -127,6 +127,13 @@ class Hook extends GameObject { } if (firstIntersect) { + if (firstIntersect.explode) { + let obj = firstIntersect.explode(level) + this.obj = obj + this.md = 0 + return + } + this.obj = firstIntersect this.md = 0 return diff --git a/src/utils.js b/src/utils.js index 42542ec..31a2b98 100644 --- a/src/utils.js +++ b/src/utils.js @@ -19,3 +19,7 @@ export function intersectRect (r1, r2) { r2.y > r1.h + r1.y || r2.h + r2.y < r1.y) } + +export function distanceTo (o1, o2) { + return Math.sqrt(Math.pow(o2.x - o1.x, 2) + Math.pow(o2.y - o1.y, 2)) +} diff --git a/static/barrel_piece.png b/static/barrel_piece.png new file mode 100644 index 0000000000000000000000000000000000000000..d81fee7a61c02e6d3961aff2b3ea2309c06d1b61 GIT binary patch literal 1250 zcmV<81ReW{P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jdGK z3pg>+27wU(0013nR9JLFZ*6U5Zgc_CX>@2HM@dakWG-a~000Cz zNkl>4MVtq^t3I!*E181UG2afy${4+#w=FEvW z6UDI)d?BcKEUqDH72q^LufHlDV59y!CW8dC=!>*OC& zVhOthgJh5pR%3lN_q2D7?!jl$ZdPbAZu)j;4@)pLlfsmW2yj|4yl`!^XY7mEZz}Ow za<()UQc~zc?p=`J`Zn6msy1~H3KfC|a5o8W9Zp6zNE0s8+-%W7(gZ=L7FXB4KRh+L ztWHrVhDlIQA#4(~18ZUNI!6vpE7R)%#6}BOm;J!pbUhQm9n6HqszMkcm2r}oU4f6< z`NmHBaClLb5igK@h{!=;(fD_v%fK~Y#r76<0gjl|XY}oXVkICsrR{Qy3j9g(Ig&4d@5k)VfD@vdtN7o*6{KaLv`r2!7dwv$ zd?f3wQ&BM-PzVPU1BwCL5ST?e27bc!^N1eMLBzp&pmoF&K^GOm$G~@Xx}qYiV!I*{ z6=UJ4+1AiQyJ-sdozk!oZBeD#i5+1Ke=E;GII5_}h&lz#OYxk{J1)y#oLmAf#>j>v z*|wdFs2cN52^=zsW2|b1-;0Y3Bt*c48hJ7bh}}?M!o}Z z1W#h(KzdAc2s{J41iXvcDsI`38j@0Gcvm(8vjJQIR&#Y-1TO8g#bLN7c20TB04EU- z=jvOx4STSKISrfzelBjr;7tu#OQJ%toq??iz5+hLUd?lBxh<$#;yU_4&(!*V1pK7! zjr<+JL$+sJmI-)VFkiG-?&e9aU*j>9;AP-^F8>R_m%u+2HW#1>n%b$0k}*k27u*! zWhCw9bT-ju)@Uyu*#hYNz}f1?`CSe3-Fl&Lt7MzN4J-i{^U;3|e0Y;gFbGN>Y|=E! zLTPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2jdGK z3=uToW&H2}03ZNKL_t(|+U=crcvaQa#((=JArL@f5D-LAR79LB1*{dMRUE0dT8CQa zD%z^8)(+S@QR~pwYA5SZ73aAhN}a7%1O=fegEA>H%P2!214-`s{@Cw1ci)?vgg_FK z@5_3gJh|uGbIv_yueI0kuC>>3W=4x6=T6xIW7{;xdru_VkxZ7hl%Y(}GU@m>a7nYf ztDKy+nEkOO4P;9dfCO+S&h=|nca=>38R*+80F6)OKmqVHiA1|*VwTPWE(Shp6@bR4 zHTr)LX1{F)%>N4T_ec-43P9u2`rz|bICuOGbovT`=YdEQ&21Hc#;460+hcHU*QUM+ za}La&1ojAam$V8%Q{8tDpc4RHfiY{H+g266*EXF7Hvz|G>|Wg}0F6&uA`Wn5yzkh~ z@Uv~a-knxo;c@O*;CcYQn)c0-Rsm=#A7GiZz@T{l%{X^RJsG(#Fv3CqdYrQd@J!77 zzSSa>Rsm>aTAQ}DKd?IhZGdM;Bns+rt&8;k$gOnx+5`Utc4AN9zznPJ+=5mCXnZP8 z+sXyL7H{o?*))5<^mxiZMLaZ0CvQEcLIjTTNmKm zX?0$uqGANlMO$Bgr!GI>!V52r1?C$-`)W#mH7zW+(ozMWBEuc@)LZ7j(*royd#lvH z=XDbZL zz|dWR6JmyXI--XA+XZ+IXv=}XK9LF0|72EiY!!fdP?E~ZaU>F5w$ck(+5 zVF5!oZMva`tDFxc7zm^wq@mT0DkyN6Jq7GeSKu&>+8IEVj@b|&{b{QJY!myFn}Btg zO~tuEbslfFxw=CKd>`l_tDc(6*WujP(@yuc-mCv!I>*%z36z%J415zLSZ#oT5|yfI z8la?A0JfbT5j)<-xeIIMe@)O(A#j1V`vHC8XMBuAVy9Svc#nT?x&u4wh=Tw)fJ9>F zK+~KITpMecPIxcj%nVk4890IUrM7JotpeaD(QCj8d{X5BoV$;locyd7zLbCfi%BNm#<^ZKoKlkJ1cuS~x8xLdAVlg< z9RL@QNOT0g3qbeC&J*Pnyx-t~q!)n>>?PkKG8#QH;*j*@Z)IK2xxqPb?sUxN0{NJI z-m(N>#teY3ejh%Z9X^0DDTk_l+IFGh?T(K>J5*l|xdI^_ZNTHaK@3Fg<{)?k1UB)euY^5t%IKu1xb` z8r26dyH^4b4ddT1TZwc3!nw0aBs$dhl23Ru;I+UKdGjNHKI8y*?d+Yo_G$NS*@pgH zV*N2d8sVtm>y8qLT*5p;O1($S@1kQb*0Eu}XiZiPur$l8A4W1c9T<%x%2BMxxm&h} z>F;<`G63gBk8^G|Fa!9AWO7~8Ie})^0{_Uk-ig3tn61LOXK?Oha&p>i^);P)6fmZW zsRd%*007R$Y=RIzOJhJE!?|N{?yjL;*rov2;R{ku#%z4k zM*(?xBY{`q?SX*z3fjrp8cQ;{0_XmLb4OEDOAsV!aV+0#OUt&oB+-aOa)`)Fl1nnDc_@P;<9BPV{q;Vn9T>y zWiQ}#ojOyYqH}+)N3_rm=T5=7M=2{?1H2CWICzQ*;JcW;xnsh>EnAXGyiABy<1s?Y zhRBxtX!|1I4c4t&j&py+xq+K&jwBuhAWE#}h#7kVrvW?DDGuDKviaXm)A&KZxwlM7 zLZRVKQukqev6oCm1oouO*lTnHLF~6GLl9uz5paNm_kjD!qmW~Dy+UA7ETp4JCQIsI zdS{$F7w5)e_9gH?g1L$`o}mYF0cQW&R`%sK5Rz9yBJnNECb59NYJ`VVV zRMGY~qjQD;<5PY>2kDm6qwkN>59g)}K(d+>xHm8j$m3Aq5$ytyYO-*GMB=_0OkYoF z%oD=96N=%lzKh0jLj27|m_6P+fFSRD3~2-QV^30H+Z2;(&SF z7k~t7Qa|x&H4RWeH}W_|rlpUV2Jm?tv)o8k)fRv%Zz}rZ-1Rv3U%9=11dawAeHD71 z4IC>CwK9$QBQbkud)bytLz3AdoI4Jf%rrXERx=^;2#Tc6yU6=qBkXK?Y}*e3Zo|2E zVvl;Z26LMD+6liX>{SWTMqPhncq8Q*@!%uCH~jCO3w#_pc7wf?To&4f~!h5dk8Uh9%4r|VGJ)X!rmC6$$1hOYoD)Oknfu1}Jx zeo%wFw6<`37;roA3qL#KVZTA6-9LpOM(7}S5LTEFs-x13kn$}3kF;DD;AP3-f>=9M zQe3=3F-J;49g5dJowXfZvp9qKZ^v6dY$)b8jsSQen1FL<0b_X!N4}W#jKZqnaugQ> zA8CfPk%~VIpHi6%EDVI8P=gR>`SRi5a`+{1KN+>S*(}>-z#G7u5hx@nA{Fz+%s*c@ znn|UZYTs+JP9DXI5y$lcl1tK5wl7ubEWfC`o++w==ql~AzXW|;R_0%W+20$IRgEJ6 zUI<>qxskwqyaJq}hrC-ZU_UuGy@ebsl$sweC$G2c<_c+seq!>nC;+<0+mP-*^Je_X zx*++Ez+Zz22PfPHBGZ8+8;T4 z(<1?RRwK1P6r7MM?X2z)1hlWz(CM1tp`krp0`Qkm6=cxD)C}KKsz1)<4f3x38u=$> zV)j{Sc?Rzj4bZI=WnBJEe7$jmDZUYZa~BUkd_!Zf$TfC@h;rx1_tSMGg_j|^ zw1~rnaRgK%pJ1v40uAb|k?NeIk(@2peWDH;D@n>m6-ozO6>?92-KsbZkezUNS>yk;Yv&AJFfi+a z*}0fqg4qq26-S4iZ)TsF*=uHYVfD*w!0dg@{(#xMX#YKyqP1o=Qv08>+Ud(0_Epqz z-T@i+^%pZ+Z)VH<_HsSfm6$z+*~gfbW*d?bW_EaLd$P{E1hZ2xBmTR;vXObzGy-6T zIagpX-oR{6%+A*X--6lZ=&-BItXzY=)XZKqvs0^It}Obzx0#g$4BBF5cbnO>);JXX z?pbE`NwEKSe*Z_9eTLbVY(wyUGkd|z7MR(4sr?@X%s)Ae`S&K9V1m~Fq(ma$V4y*N z%gM>DmxMak$zZmDSzpX9(u3cFSw(c%Em>ybXJ+<DPsjBLi17$cjPr=b# zS?)QCnPvl}I5+#QWU}-p$>atBMdO)AFFGjkGEM&2IY7>}!aOeyezcGN&QM%5UP;Ig z&BZZOs zWyFIaO%uqWoW!5Bd##x7BiENnBu=5Ks-mf$VEdy0=lTne8$?HexxF<1lVW$3VB8Af z*(neBnufoJCuSEVNoM3~PU#5q3?!=~UG1o9*;4#O* zn{QqY+y=B~KM8w59TT`xaOsweaU4lde>XKXb6O;Q;`0!!^qI&%>bZ-7mtx4`U7S01 zNAwqLSRBB)-39ZU2+C{iA!N2l7(joehs*W9L~3xo!tmv?i$9Ja`fdRt)Y9lvr9WqR z6!Q<7?Zx;Kn)NZd^gZF8N&Q*yxl+2b66Y%8ZRaY<&8=k1mSmKsa@)Ym1_y#xIY(D- zy#ESxrH`zAlu`Y7Igs|S-TM+XXiTNLTq5i#|Ym*X1>l^HcW&pR* zz5A0aU*3$6z(k@Dvpb1E+9PG>bLA&}Pntb0dl)5EQ3~8k^*&I;B?Lt+fcZ=1z)te0 z-tYA|CJk2+%yA=?WwwlfBBadu|Cs*es2}79} zKY=Lw_#SY5CHy4JQC?+a@S4KU9p4n7vPRp^&!U zMM6+WdQy6XqJ7OME6o>@8sYLRhv(lbe76zZPjjBfAaqpl?MVb5swL%WfzD@L(C+-+Bp=6Wu$5j z(`lg$%p1VFWw5wyEn420XYEi0;75^OC*|p@^3Hdv!71Mbzj&dS?0r_py)SSzKIOL? ztrP|L^A+0PShFPw1!75tKom(>L?V5<@juMby^$<#D8ja0!y8v zouB(hN^cJ(y*Iws;JZr;)TAK}lBXYOh-%dXKas5MtAh&upD=x$bo>H^0sp{b#~~B& zrSZ!oA2Y~a^jv{Q9wR66Q?lh7N`+EQ5w`e2{ldVxbD>|q-6aUa^q0Q8X%F$RNTFY* zKp1`rRDT^?qd*)fxUl#C5rHTZ7Z>7F#IFMxi+Up{c)1k!Z2c$87;e&RU#H`7Q}4B7mF;$ zSIJGnuZYQ@4Vv&#$oCQ1d*DSWWtZ+1mpQdlLMsobHwzar22I;LJs2LEsXIY_uc?5 z^|L>TPvN{@1E^yH3X5g0zo-%XnXju%1}2lA{~={%4f1xf#u0!-VpsJKx(L5+-XnlL zgdH3!V-Xj8oG8zCPzzJ_HPLE(WAR(POpM1jhKs!T)%u%7MqdMvUYH!KbLS?JOs;RN zJ8kHauX@+0_)Fl|Rb5Oi_;EAy114xVCVDmg zgxs=4cp%r$;VR%EA$gMxK66d@&Vhyz0N=H16u$Z=KW6-{;#)s4zbFfj!_SG}e?nFu z&J+&9cWm$3!nDB#@%Jjv@DHR7*5GS;J^?BI%eJ-A(~c7W|MH}3#rQmS$FGs^%Jw&( zIYb7e4U(pRW(6smA5|z=kJ@}h<<2u?=3epk{-1K;mg95(KDHl&b63~5*I&~MfPd50 zDEx{H&+7f~g}XUHDC4qd^Kh1juZTzlfM9?5QTfrvxN6a5^QJdQ?=I3_ez4)YS%_xh zyVpeiz<*;0;z#S@*}^6;1@#jE&-h>A+ix{osxDkM-UnY5R)AE=+tlZcZq0|D!Iy`L z){q@3Ey0(8y{T|-B2m-%mt+=}Gz$SR=WxD`w~bu&yc#~|W|{w){|kWM0tFN(`s*Z2 z@pAckw9{xD+Cn1%6Zmtv-<$#bO<(nqFm%&M6p>o;Sb@*-`Bn#;fl>7B`xoZUZ3Y^k zVM4@qn7srHBL}~`kGrV#aqZC>=T?0eU(^ap+~rHN0$Jh_!Wvra>>5EK$# zh}kC%&WyPTXn%$@^=;qVJYvNC^aEzCDk$&(#HC7QZd;}dGNwfxP)L)mILbrgQB zNEH0dlxCQ(&~TN|zY=MNqwzUe9|BFoxtqwzY1^=hs;L@8TZn?qF4Sr>CpTTnm zQw$auBr}BLZgZ|fvljp@dbzh6^M9@Zj1PUw%r=_Y1T*`6`el-sZ3>TF7!2%YGkYZX z?(%vvbF-PPs^>X#{BO<0>~hSW#%w-jmEk=eXl8#`E19U{$zn4b?7uI?>~@XCX=#id zZ_X8D9Y^O14GuLJW^j?g>6S?3H(LRy^vu6Mez^ri}28+&1_Wq=@sg?^CD)~ zVzw&!?)Hp!E5rT%c<_H!PiDSjW>;=SgQ&{jbCsE$Z=rmM5xUyRw!SzE-6wSs~sX%W+CQ9y}v6!9w5J@spOLMo+~>U)$~l@y zs^n=naB6hW7ebKk25$7pm6zpUbpyY?@alTp=@s~e%yo4nc@keQ8`Zx&51i&}I>yPV z3xTaJ_)O>iWOS_gwhnwQmHN3=NutI09)q6lEr(0<8#zjAoJNt4JVJp_hg}*ou%`gA zYciO>S#j?yF+JP!ek1yDry_(aAi28HBn!D zCC@MkgCOg1dWKR`^^&W_hlEyEPja(to2 zb-})OGvwk*ajatvAzh^&=pOv52QP)5_xKW+4Z5eP8r1<3hC+PB?&E6w9zls_=8oq#^-C?eJ}T zqk$?{=si~3#R0GGjV|^czMv$eQhc-Mhjo!Q_$u6^Ve`9w)z+v8e!dOg_bQW~CcTU3 z5A{3eq`G{*O!zW8FNsBBcClDmhZ2kh^++{??Z{MKi zt}doow_1tN%=c{`Cv_M$jGCiCUM(&0vFz?Z&Hg)TLJ$qV2;&-U&)1E8=(CKIl&u{? zRJSB48Z9i%GPYsSB?Yb=$o zP)w?USlVx8s_)kW=7V2@wYPFD;x)qI_l;!dLXG}z85upz>syqnK3HAJcg9ybr|R^- zgV}Mw6C@J5V0IdCCSNc#uKMmJVd$buzpKBfASy=+rUF<%0q`=;4Z>`8^Mist^Su%t zLi7Sguku$5?tDzy}wCz+!2;7oRbB2UncnHE1Lhm0TwV1 z-&^8g3H$Ou5ZcNN7RGwx_4>XYwDAPMxwDDhrkIc;_b@&-o*Mh~F97G^To=ra!R*eo zCC$0Hxtixb^BdjKTA7O%V}AV$H~_QT<6tq$t*5Ol+gThO?e%)G(y-G*YjdV&_S<6o z41B3pQa(x4t%D0=Sxb9Mbf>_*_(*a58kwY2lJNV_*Y<*Kk0V~c*_X`^QjEKTnR?QP zG>KNqIXxyGo4%Nh(+jS5pa3{`l5W$*z1+9Y<20Qk;d&jzEi4Br5CIBnbRqCD5wIy+w`67A#%_@(7hruT7RCI;Mv zbNw)TK6=OF;2u3vEN>ftDKW}63IBdL`3uv7-wUIS2@=|m#Cz)I{K3*|ZNv(L71 zrmCt!nUK?Qt}DI_?~YLa!ntljp`tEBztqdQnm_=O$#t0h8MDvE zZSO;w{e)waBoLefBvX_$^<`FW5k|jNxQyyM`x)m7~0SIE4caXdwb%_G>Bdn{n_&Or$zY*|KY9aMYZhF(hWixf z29U~Iep8J!S_Ob)a@BS=J1$6z0227tI>n^WJx~9pUAtdXSU3&X%yK!1l|*UQ`Ii2Q z$4oOdL2#mnrOV_KJQg^AX^UH3`;6z@Y#x{xC6PI|RR9`>_D=J_XG={d<<+m2SMJ=I zl$03j)>-TsY#^0Rh6n3hhTXB_Xka4iBs3=9Vth3x5X`C-xjAo}Z^NgyPF&zzs{k|r z`MIC@3f6hCjV=RDBbi(ieES{<`0)^L66YSO^OrVmG<;5fBeMcCvZ|VP8fF&&00Fc~ zL_t&&nC*^2;dlc$yN`24tpc$9)T`Q_m4wRtD$G8}IAUUq4*G2ROC*ykx9Zn?W5o+& zM{q+O(MfIBNhZH+6@cw?AX83Y6#GZbxIK+w%$R$!;0_-7Pc>S3pq^pt^RdJDKIu98 z!0NZa$<*QmAf;w=D@Ya4$13Sd5qNiRkXJcd>Q zXnX*vPnrPCAWHCT1inKuSyIc{@5WkU%a*Ebh+azYwc}fujE9HQmHsZR0?_!Ba=X4D zRnY^dW45r4b0^js`){29eiY*h?~vKyt5d50G(M#=?WyeSO;w6NAM z_BT|=)?N_bFKI_#~_!_bo{MU;*d+gwRU{yvp?p7zT2`EI{7UJAl z_3Ei-HnD+xkrl+1Ct2^URR9`^qJr~M;MB(Kpt%)7@Cv?GETY0z0cg7Wy$rKy%^)oO zwPKOhD4>aGZ{U8+9&Q$QPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jdGK z3_CX>@2HM@dakWG-a~000yV zNklPw)qLtOoe!W0SXw2JGpuiwH@#Mi&x1;<0Mi2U-VIk9@T$PI zLEX@%Rnn&0Sm%^sO%LS$xhi)MTd8CJ@}&7ZbI{YlcVz&i_r;*>dz%IBES!=*`tzUu zSZJN`!S~!RuFQI4VDli_?dxy8E$>6)6ZHpux{sW2Rn5NNSzzXyQ|6$P=JUi-`-8qc zMBX$Ft++Wh+KW7;S(bVq zt+gtvoMoL8Lq0xeSzzyj8>k|{EDGjSAG!>%`E#rT*s85>Q4mW9rP}~I?}o~DY@us3 zS7+&VfA`5@0O)W?OVOr9{p)RjzHco9B&5lmcsUD=ns>u0@g9QWXO)8_(YxYh1=EO9M)TMv)@lnDqi^5lNBOcHVb+$YvNz63fg_F$2uVas4&j1R#a3*7 zvIZ*o6j>)TR1iV=p&r8aNT{w606KI%u8uYlmG)6_ABdo>F#b?Fq$dDUYydC#j;v3n zFO=Y);>-HMlx+Ku=pb5yg>G8KQGSueGkmes&yIuuN&R7F{YVpwH&#W(3?uoavG~|e zYB!-kj?lxLXl*`oVL-XSS7v=z!FTy+#yOXfiP{Cej;BOKHq-+GBuVGQ$!Vo#B~g_1 z=2G??c5>2NdMed3%>cd#frwPmAcnTsk1t{j*0Z6oFKxfg90w2msO$=o! zc|MAt5Y4i#VoJo!;3z7%UI{#@yfx4A(Hq*ds!VB_B_)((MX|3GC78pMsZu6Yog1ta zPcj5fS%ZocRGcxD8uI0Df0me1VNl}PJ}#kDJog5OXpXPU-dN0WGcDq|-s&Dk`RpCf z^zB^aPie`ye4OU~w-zDpEp4*F;Ve+ZlQJO9ih)yd`Gqnx%3Aw_0@OrhqBy-QBHuLM zjEy>lWilP2Nw@KE0JXwPUIohYasx660)uo0NqIV=09K2S*u1Y*3Tn~wP&HnnTG~`5 zSQ3GVGI5EOO2NF%P33f0+ov9S9?t#o+Q|Kehu$|Idg%ar0Tv%#wmB=lU0~)k=s_`< z7(_;FrbX4AH377?4Hcr82S`&2S9`zlhV*AQKo{&vn zj}*=u5~GGJ-IY?)8K;fRohTZlBS^5eu2PkEw!$&8rX;<}@9nt**_70)Q_F zKeQYS9f9MK!sln2;qROWU?LDR{HB02h>}1~49JkNedeQm?&C>Q;^x2u0GuAx(F++= zI6)@|R6&hHFyKWDiWno~%p##5j8u$vsPLp0;8;0V5CBp@y&Iv{9RdLM&c=uy3A{LB_=4tl z%9;lt7}y_2cy>NUv+LvML;a9mw>@k}jL!!FK0g^^_e}t2p#M&J1m(pOCxDp?`3LyQ- z+Dx;raMTZRQxlL1c-qx&XL@el&{kh;&eE*vU zcE$?FZ%1%_g?cwkf|=_B+rtP>1niF@eDPyX`{mbTe9{!y{lhl?aa_-MJSSp2zVgv} z8$k9M!9g0;8(ou)NjhGxikcCIr^JaBk_kX9U`>4#pd{h-uD&%d(u{%}f!>aTokjq6WGW2=xMKxJF{)CfoMi?0 zq6feL0*9akK?V$pEVi#0ApyP=7zp6TBlMo?ZnO_PoZNKbHXRTEM{(-&%y9JHM)n$>o*Ge%%~vKb+DD1|mlLwU7U3I(TuUzw?QpBqa_^M4b4tOHbe&5(l2dcAyYR zi*BtzE3GCdQCwxr3K|4so%YPQ0+UGSBxUE5IEqt>MJY!UBgSt}1JJQ%06*<{2ps`- zG(~p;pc(2jU9i4915iW=o!p!&Rc#=tF3OWtmpAj|i*#L5KrM`UB26E53Jo}5aRJ0^{Nm)iUlv*EiMZNvUm>8dX5VpUDyMx@GGMev5hP=} zgcn=OKz19mA%S&0ER)E8!RB8nKU`6N;z2ucEx`PdHhuD@H8~{oJBO`VzYq;>lq&3bgK;sJdeYF;9fRRM-6zghdZi!59&&65W zLsX<(o5i$35Vm}VGf0ObOTw@radP0H)vaNFID#`Ilih&KKfFd&sPZeLg9x5DN`k-+d;aC!` zw;c>z;C$P~@s@<>YD9$q$k!B$9YS}X^D#*C>u@N(_9iUey^y*|pll1&s zg9x5d@RYJf07C&7cmhfqxzBJ`1+Hubb9J=Iq65T$h;sgeVr6OeVuCs|cCSK^p*_me z2cGTMF?K|<+d~A#&_TigRE;3Vnx1uAPGK231n{Qi;G=#0huiN0^!8i~mNzT4JfJk` z9}^$Q3>lj2LjcOr9{^BuIxiWJkrpZ01^UO@^j_~c2$9y|6@Y=GPZl{0su9#7q4T7M ze?G2ZC?_cr8zukm&-6}_Pxb=5+V{|xv}`WV%LB^Of1yPS{qM*l1QJlD&OUM}oqbqf zrGkObC4?=3pe6BtpS1u0*Ph5+Ga|xSLjyY4C2S$Y<)a$@{(`R4u+!u%@`Qw z$AXY7Ikv$w0-VCp(16in$q!5{N)j z2P{?$AB;YGskcmnjP7EUxt8gca;QR+$f-^@lWTH!_O1)IhStP!UgEVN9av zT$T@EfK`+%~)65u9h6UvIqSJnvbBE}EzrDE9JKJWW8BJHUgjLI+X+d#DB$yZC zZ&4MQy9aaSjTr<1CZ0d?inh>*CxHo?x}$Jesgds@$}ioh*zEO20c!pqW+tF%-#}!F zYRcXkZpL|*t?4Xaz0N$7o`r8M)e1GQ2qrY^q?hJhr_CEi}?^YbP7p zgf$QOl`^MfVipw-gLpUFf-T=TVw18KI8n|9IuvOME8O8>{j=|wweRFKwV}MCROTfB zcIH&HzbR$3zO@0m@*&SQkyo5X>ioXU_O6U`shZw=fQ0>~hAAX9uXl1enQxyYIviCG zC@bKmRvgo)2t6(^24j^xXQQiBNusGzpSEbT!+4~CNTtgZGxHkEhFhE$V5W=8L`V~f zIU>vjCv^vW_2pjqSNSru2HW)tK&7Hou~;T6CH|64)@Qg3drP;(ud3WG<(Adk`N52> zk6~>IKTC+ozd*n)(oOi#qL=ke!(w8}LjI`=0ih<*nW5Fh=BC4=b>5B(q5T&jdOlSoL(D`6)c<3Fz&)HT*Rj-0ZLdKVo5Us%;Z_k0))jLFtINw3H=Tz;Yo8WaPE(j z&$Kq{&5sN5Q2Xs&9}m9+7`SwSy|9=(Yl?()v*{w|%f*30-yo+ONK*8(x3nI$5N~}e!<_MdujL1UtQ-US{SW^we~v803nK0DT^efna$MXAb$Vzxj3{UFM|u zeBz?#VW2;OKY=1)v8{X)@}3|5Jd3`G?6DD>O$~iqgg(xLu?BO&`?_`N8G~BZTJujb z|AxY|em}9Wqh>Qp-bINjrf~sDVnDWo#zc+&?R9UG&r-FPxTp%1v_(KIY7?)2jLRTq zrs(m(Zqkjn7ne9b*qbe=F!1a7WdZ-?%&uS)`#=-nwDsSWNA>)O-q5D1W!|y}E^Dc? zt=3ZIZ=)lcyEtwC&)R^S7HbwR3{(khX~0+D>#78CDM0T6;Ja>%FrP|FSML+3i_*rG z0Qyh?UKYHy0eT+*UIke92GCUjepjGXqBd>Xrfu5$(EcBO2b9hqwl)#~0000