`u$U4UH]UUUUUUUu@HLqYLUUUUUUUUUUUUUUUUUU !BY#ATUW#2ͫyDDDD߻!񽫪2Tv4gE3޼``pffwwffwwffp`ww`wwffwwffwwffp`ww`wwffwwffhhqffwwffwwff``ffpffpww`ww`qhwwhwwffwwffp`ww`wwffwwffwwffvgeVffUUvgeVffUUeffavgeVffUUfffavgeUffUfVVQxhwwhwwffwwffwwffqhwwhwwffwwffwwffqhwwhwwffwwffwwff``ffpffwwffwwffwweVwwUUwwffwwffwweVwwUUvgfffffwwffwwffvgffffffffeVfUUapwwww`wwfwwffvgfffffffffavgfffffaaffeVfUUa  yiwwiwwffwwffwwffxiwwiwwffwwffwwffxiwwiwwffwwffwwff  aaffqffwwffwwffwweVwwUUhhffxffqwwawwaxwwwwhwwfwwffvgffffff pppppp`gpghwwhwwffwwffwwffff`ffvvf`gggVUUfV UPV`eeVVVPeeU`qgqvVeeVVUUUvvvggvvwVeegVVVeeePVVaPeU_QUwwgfff_UfVUfUufawwvvwggwwww`ggvvaggvfofffffVggvgPPVQeeUPVVf`effVVffwwgfafffaffffffQaffaffffffvvvfggfffffffffVwQQQMDxqxDݘywhQxxaDwD f`f`Vff`oQeefVffffffufffffffpofaVXUxQUUQxQUUUUUUUUUUUUUUPxqxywhQxxawwyxqxawahQxpwfffwffffpww`hwhwwwwf                   QpQQxppPywwyxawawapiwwwgwwffwwffwwffxawawwawwffwwffwwff wpogwwfVwwffwwffwwffWWWwwowwfVwwffwwffwwffoUUYefYVfXefYefUUUUUUVUeUefVfffffUUVUeUꪪꪪꪪoڙUUYef]Vf]efYefUUUUUUVUeUefVfffffꏪUUVUeUODDBD"BDI"DD$D)DD$HD$"D")BD🩫 ffffffeffffeffUUffUfVeffVffffffffVfffefVfUfffhVffPeVfXefYVfUfeeXYUfYeeUfUfYefffoaaeaVaPVhfffUfUVV fU VUfUeUfVffffffeffffeffUUffUfVeffVffffffffVfffefVfUfffhVffPeVfXefYVfUfeeZYUfYeeUfUfYeffffffffffffffffffffffffffffffffffUfUVV fU VUfUeUfVODDODDODDD$DIBD"D"ODDDDD)DDDBDD$D)""H/ DwgPwVUUwUWWWvgWUvWvWWQWfUfffU YfVVVfVYfeUUffffYYffUffYeefVeffUVfffefeffffffffYUfeeYU_U ffffffeeVVUUUUUUYU VV eUU fUfffU ]fVVVfVYfeUUffffZYffUffYeefVeffUVfffefeffffffffYUfޙeeژYU_Uꐙ ݪꪮffffffeeVVUUUUUUYU ݭVV eUUЪ ꪪ꾪몪껪껪ꪪ껪몪몪몪       1?0 3+1## 1 !/1  ppppggggVVVVB?3$3333! 66 6 6 6 6>c 3 >h .>fc. > "`0> >  >?spp{>>wpsp>>8~<p:89pwww8>> ww >ww~ wp >? > > 30 > > > ?~swm?=>w1w~q?~?|wwwwwww?~wpwwpwpwwwwwww>wcg>wowwkwk{wcs>?>?~wwwwww>??pwwp^w?wwcwwkwwkwww6w>cww>wx><>w6 0`>>?~7w7www~?~p~>|~wgww?ww~~>p>pw?pwwpwwwwww>?>>wwkwwkwwkw>?~w~wwww>?~pp?pwwcwwkwww6wx>cww>wx>>>w   06 0        "0?3˼ ˼  UUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU[UUUUUUUUUUUUUUUUUUUUUUUUUUUU[UUUUUUUUUUUUUUZUUUUUU[ UUUUUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUU[UUUUU[˥UUUUUUUUU DDXUUUUUUUUUUUUDDXUUUUUUUUUUUUUDDXUUUUUUUUUU[UUZ[UUﺪﺻﻻUUUUUZUUUUDDDDDHDDXUUU[UUUUUUUUUUUUU DDDX]ޥUUUUUUUUUOHDDXUUUUUUUUUU ϻDDXU^UUXUUUUUUUUUUUUUUUU3UU53ZUZUUZZUUZUUU^UU#"UU33"RUUUUUUZUUUZUUU^UU53UU33ZUUZUUUUUZUUUUUUU^UU%"UU3#"RUUUUUUZUUUZUUU^UU53UU33ZUUZUUUUUZUUUU%RU."UU"RU3SUUUUUU[U53U333[[Z[U[UU3#"UUUޫUUUޥUUUUUU3UU53UUU5[U[[[]UU#"UU3"RU3#"RUU索^RU%U"UU"UU%RUUވ]U5ZU3U3SU>3UU5SUUUUUUUUUUUUUUUU%UU%3UUU"UUU%UUUUUUZUUUUU3UUU""UU2UUUUՍUުUURU%U2U%3UU2UUU^UU%%"U.RU"UU%"UUURUUUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUUU[UUUUZ[UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU[UUUUUU[U\UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU[ZUUUUUU[U\UUUUUUUUUUUUUUUUUUU[UUUUZZ[UUUUUUUUUUUUUUUUU[UUUUZZ[UUżߥUUUUUXUOUDDUHDXDDXHDDXHDDXUUUUUUUUU3OHDDXUUUUUUUUUUOHDDXU3UUUUUUUUUUUUUUUUUUݍUUUD3\U PU PU PU ]UPUDUUXUUUUUUUUUUUUUUUUUUݍUUUD\U PU PU PU ]UPUDUUXUUUUUUUUUUUDDDXUުUUUUUUUU厈DDDXU޵ZUUZUHDDXDUXUQUQUXUQUUU533U33535UU5UUUUUUUUU"UU%"U*]UZRUURUZ%RU%"UU"RUU"UUUUUUR%R%"ZU"UUU"RUU%RUUU""3U:SU:SU;SUU3SUU5UUUUUUUUUUUUU"UU%"UU%"UU%RUU%RUU%RUUURUUUUS::U[:UU3U:3U333533UUUUUUUUUSUUUSUUUSUUUSUUUUUUUUUUUUUU3UUUSUU5UU5UU53UUU3UUU5UUUU**U"ZUU"[UU3UUU333SRUUURUUURUUURUUUUUUUUUUUUUUUUUUUUU索^UUUUUUUUUUUUUUUUUވ]U5U#U[:#U3RU53RUUSRXU^UUUUUUUUUUUUUUUUUUUވ]UR*2U+"3U>SUU3SUU5UUUUUUUUUUUU%UUU%UUU%UUUUUUUUݫUߪUUUU^UU3"UU3"UU2!UU2UUUUUUUUUUUUUUUZUUZUUϫUZϻZZUUUUUU[UUUU[UU̼5%̼UUUUU[UU[UUUU˯[U[[ϫ[[UUUUUU5"U53U3UU5̼5̻UUUU2UUUUU̺[U[UU[̯[˫UUUUUUU53UUU5UUUUUU3UUU3SU3U?0%%%%%%%%[\]^_10%%0=0%%%%%%%MNklmnoMN!%0<0%%%%%%[\]^_{|}~[\]^_!%0;0%%%%%%klmnoklmno!%#!%%%%%%{|}~MNK{|}~!%#!%%%%%%[\]^_MNK123!%%%%%%Kklmno[\]^_KK0%%%%%%MNK{|}~klmnoKKpqrs0%%%%%%[\]^_MNK{|}~KK 0%%%%%%%klmno[\]^_KKMNLL 0%%%%%%%%{|}~MNklmnoKKKMN[\]^_MN00%%%%%%%%%[\]^_{|}~KKK[\]^_klmno[\]^_!%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%KklmnoLLKklmno{|}~klmno!%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%K{|}~KK{|}~{|}~MN!%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%KK$%%%%%%%%&KK[\]^_!%%%%%%%%%%%%%%#120%%%%%%%%%%%%KKK$%%%%%%%%&KKKKklmno!%%%%%%%%%%%%%%#920%%%%%%%%%%L KpqrsK$%%%%%%%%&KpqrsKKK{|}~!%%%%%%%%%%%%%%#920%%%%%%%% KK$%%%%%%%%&L ӂKKK0%%%%%%%%%%%%%%#922222222'(%%%%%%%)*LL4555555556L KKpqrsK0%%%%%%%%%%%%%%#!%%%%%%%%%%%%%)*'(%%%%)* KKK 0%%%%%%%%%%%%%%%0+!%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)* KKK 0%%%%%%%%%%%%%%%%0,!%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*LKL00%%%%%%%%%%%%%%%%%%0-!%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*K'(%%%%%%%%%%%%%%%%%%%%%0./BMN!%%%%%%%%%%%%%%%%#120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#L!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%00CB[\]^_!%%%%%%%%%%%%%%%%#12220%%%%%%%%%0222220%%%%%%%%%%%%%%03!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*CBklmnoMNMN1222220%%%%%%%%%%#10%%%%0222310%%%%%%%%%%%%03$%%%%%%%&!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*CBMN{|}~[\]^_MN[\]^_1222222222231222231220%%%%%02223$%%%%%%%&!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*C[\]^_klmno[\]^_klmno1222223$%%%%%%%&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*klmnoKMN{|}~klmno{|}~$%%%%%%%&!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%MNMN{|}~K[\]^_{|}~MNMN$%%%%%%%&!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0[\]^_[\]^_KklmnoK[\]^_Kմ[\]^_$%%%%%%%&!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%klmnoklmnoKK{|}~KKklmnoKpqrsklmnoMNMN455555556!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{|}~{|}~MNKKKK{|}~K{|}~[\]^_[\]^_%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%MN[\]^_KpqrsKKpqrsKKK0000000#klmnoklmno!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%K[\]^_KklmnoKKKKKKK0000000#K{|}~{|}~!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%KklmnoK{|}~LLKKKKK 0%%%%%%%#K!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%K{|}~pqrsKKKLLL0%%%%%%%%#L KK!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%KKK$%%%%%%%%%&KL'(%%%%%%%%%#  KK!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%KKKK$%%%%%%%%%&L'(%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%# '(%%%%%%)* KK'(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%pqrsKKKK$%%%%%%%%%&'(%%%%%%%%%%0310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*'(%%%%%%%%%%)*LL'(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%KKKL $%%%%%%%%%&'(%%%%%%%%%%%%%%%031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*'(%%%%%%%%%%%%%%)*'(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%LLL45555555556'(%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%' (%%%%%)*'(%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%02222223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%03%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%03MN%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%023MN[\]^_%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0222222223[\]^_klmno%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%03klmnoMN{|}~MN%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%02222223{|}~[\]^_MN[\]^_MN%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%02222222220%%%%%%%%%03MNklmno[\]^_Kklmno[\]^_%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%022392220%%%%03K[\]^_{|}~klmnoK{|}~klmno%%%%%%%%%%%%%%%%%%%%%%%%%%%%%03922223Kklmno{|}~MNK{|}~%%%%%%%%%%%%%%%%%%%%%%%%%%%023K{|}~K[\]^_[\]^_KKMN%%%%%%%%%%%%%%%%%%%%%%%%%%03KpqrsKKklmnoklmnoKKKMN[\]^_%%%%%%%%%%%%%%%%%%%%%%%%%%#KKKK{|}~MN{|}~KKK[\]^_klmno%%%%%%%%%%%%%%%%%%%%%%%%%03LpqrsKKK[\]^LLKklmno{|}~%%%%%%%%%%%%%%%%%%%%%%%%03KKL KklmnKK{|}~%%%%%%%%%%%%%%%%%%%%%%%%#'(%%%#!%%%#LK K{|}~K$%%%%%%%%&KK%%%%%%%%%%%%%%%%%%%%%%%03B'(%%%%%#!%%%#K!%%%%%%)* KK$%%%%%%%%&KKK%%%%%%%%%%%0222222222223CB!%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%#L!%%%%%%%%)* KKpqrsK$%%%%%%%%&KpqrsKK%%%%%%%%%%03!%%%%%%)*CB!%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%#!%%%%%%%%%%)* L KK$%%%%%%%%&L ӂKK%%%%%%%%%03!%%%%%%%%)*C!%%%%%%%%%%%%%%%03!%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%)* KL4555555556L K0222222223!%%%%%%%%%%)*12222222222222223!%%%%%%%%%%%%%%%#12222222220%%%%%%%%%%%%)*'(%%%%%%%)*L'(%%%%)* K3!%%%%%%%%%%%%%%%%#$%%%%%%%%%%%%%&!%%%%%%%%%%%%%%%#1222222222222222!%%%%%%%%%%%%%)**!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)* K!%%%%%%%%%%%%%%%%#$%%%%%%%%%%%%%&!%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%#%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*L!%%%%%%%%%%%%%%%%#455555555555556!%%%%%%%%%%022223!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)*!%%%%%%%%%%%%%%%%#""""""""""""""""""""""""""""0%%%02222223120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0312220%%%%%%%%%0222220%%%%%%%%%%%%%%030%%%%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0310%%%%0222310%%%%%%%%%%%%030%%%%%%%%%%%%%%%%#!%%%%0022200%%%%%%%%%%%%%%%%%%031222231220%%%%%02223pqrs 0%%%%%%%%%%%%%%%%%#!%%%0>?0%%%%%%%%0222222223MN1222223 0%%%%%%%%%%%%%%%%%%#!%%0=0%%%%%%03[\]^_0%%%%%%%%%%%%%%%%%%%#!%0<0%%%%03klmno'(%%%%%%%%%%%%%%%%%%%%#!%0;0%%%%#{|}~MNMNMN%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%#!%%%%#MNMN[\]^_MN[\]^_[\]^_%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%#!%%%%#[\]^_[\]^_Kklmno[\]^_klmnoklmno%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%#123!%%%%#klmnoklmnoK{|}~klmnoMN{|}~{|}~%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%0+0%%%03{|}~{|}~K{|}~[\]^_MNMN%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%0,0%%03KKklmnoKMNK[\]^_[\]^_%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0- 0%%03KpqrsKKKK{|}~K[\]^_KklmnoMNklmnoMN%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0./ 0%%%#MNKKKKKKklmnoK{|}~[\]^_{|}~[\]^_%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0000%%%%#[\]^_KKKKKKK{|}~Kklmnoklmno%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%%%%%%03klmnoKLL KKKKKK{|}~K{|}~%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#1222222223{|}~K KKKKKKKK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0+L!%%%#!%%%#!%%%%%%%%)*L KKKKKKKKK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0,K!%%%#!%%%#!%%%%%%%%%%)* KKKKKKKKK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0-K'(%%%%%%%%%#!%%%#!%%%%%%%%%%%%%#!%%%%%%%)* KKKKKKKKK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0./L'(%%%%%%%%%%%#!%%%#!%%%%%%%%%%%%%#!%%%%%%%%%)* KKKKKKKKK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%00'(%%%%%%%%%%%%%#!%%%#!%%%%%%%%%%%%%#!%%%%%%%%%%%)* KKKKKKKKK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%#!%%%%%%%%%%%%%#!%%%%%%%%%%%%%)*LLLLLLLLL%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%#!%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%)*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#!%%%#!%%%%%%%%%%%%%#!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%`cPS`cPS`cPS`c`cPS`cPS`cPS`cPQRS`abcPQRS`abcPQRS`abcPQRS`abc`c`c`c`c`c`c`abc`abc`abc`abcPQRSPQRSPQRSPQRSFGIJFGIJ12223PQRS`abcPQRS`abcPQRS`abcPQRS`abcFGIJUVWXYZFGIJFGIJUVWXYZFGIJ`abc`abc`abc`abcUVWXYZdeghiFUVWXYZUVWXYZdeghiFUVWXYZ%deghiFvwxyVdeghiFdeghiFvwxyVdeghiF%%FGIJFGIJvwxyVvwxyVvwxyVvwxyVUVWXYZFGIJUVWXYZFGIJEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFGIJdeIhiFUVWXYZFGIJdeIhiFUVWXYZUVWXYZXYxyUVdeIhiFUVWXYZXYxyUVdeIhiFdeIhiFghideXYxyVdeIhiFghideXYxyVvwxyUVvwxyghivwxyUVvwxyghi%devwxydevwxyEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE 4 %%&&'''((((())))***********+GO@@@AABBCCDDEEFFFFFFFFFFFFFFF pppPPPppppppPP P Q R S TTUVWXXYZ[[\]]^_߻ ppppppppprstuvwwxxyyzzz{{||}}~xsw|  $$%%%%%%&&&&''''''''''''''''t $$((**,,$$((**,,..........-- ! " #$&/(?*O,_-o../    //  ! " # & ( ) *+,-..///////////ige dcb!a``"```#```$`ab%cde&fgh'ijk(l mo)}   //               /.  "$&(*,.////////////////////~     %% %'' ')) ),, ,-- -.. ./v%%%/%%%%%%%%%%%%%/////////////spswywus q p p q r s t u vwxyzz{{|}~~ pqrst|IpDzpx+sw q{x9sKw{x{z&}y{y-{}2~ {{{|||}}}~~~/. - - , +)'&%#"! !!#$"&3(3)5*F+W,X,Y-j-l.~/  + ' #( * ++)+;,^-/q///////////////// %,     0      ! A !!A!Abbbb@@@@@@@@@k4d=k4d=k4d=k4d=k4d=k4d=k4d=k4d=AAAAAAAAAAAAAAAAAAAAAAAAAA ! !!!!!bbbbbbbbbbbbbbbbbbbbbbbb@@@@@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbbbbbbbbbbbbbbbbbbbb   @ F@  ` ` ` ``` `   ` ` ` ``` `  A A a A A A a AAAaAAAAA A A a A A A a AAAaAAAAA@   @   ` ` ` ``` `   ` ` ` ````  A A a A A A a AAAaAAAaAAAaAAAaAAAaAAAAA d4i 4d9 o;f =m; d4i 4d9 o;f =m;@   @   d4i 4d9 o;f =m; d4i 4dh  A A a A A A a AAAaAAAaAAAaAAAaAAAaAAAAA  n9f >i6 n9f >i6m8d=h4m8d=h4A A A AAA !!AAA A  00l7d<g4l7d<g4 d=h 4m8 d=h 4m8 A A AAAA AA A AAA A A A A A  ƀƀAAaAAAAaAAAaAAAAaAbbbbbb  AAaAAAAaAAAaAAAAaA   ƀƀAAaAAAAaAAAaAAAAaA 0ƀƀƀƀƀAAaAAAAaAAAaAAAAaAbbbbb@0 @ AAAA!!!AAAAAA!!!AAbbbbbbbbbbbbbbbbbbbbbbbb     0@@ A A A A AA A A A A A A A AA A A A @ ` D ` ` ` @ ` D ` ` `0 ` ` ` ` ` ` ` ` ` ` ``` A A ! ! ! ! ! ! ! A A ! ! ! !!!AAbbbbbbbbbbbbbbb    ? h hh  A !!AAA A A A !!bbbb$bHhbb    M-?     E% ! !!! ! ! ! ! ! !!!AAAA   ! ! bbbbbbbbbbbbb0q ,L - U-օ!-\}`~H~yp,tmx#$"!#$,+ST!,+\[#+!? 񟙙ݙ񟙙ߝ񟙙ߝ񙙙ݙ񟙙񙙙ݙݝߝݙߙߝݙݙݝ񙙙񙙙񙙙񙙙8333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333303333333333333333333333333333333333333333333333333333333333331333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333330333333333333333333333333333333333333333333333333333333330333333333333333333333333333333333333333333333333333333      ꮪꮪ:333333333333333333333333333333333333333333333333333333ݪꪪ:33333333333333333333333333333333333333333333333333333333ꮪ3333333333333333333333333333333333333333333333333333333333VUUUfꪪ:3333333333333333333333333333333333333333333333333333333333SUfVU:333333333333333333333333333333333333333333333333333333333333cfVUU33333333333333333333333333333333333333333333333333333333333333UUUUUЪꮪꪪ:33333333333333333333333333333333333333333333333333333333333333cfUUUUU fffffffffffffVeUꮪ VefffffffUfffUfUUUꮪꮪ 񙙙fffVUfUUfffffffVfVUUU 񙙙PUUUUU^uUUfffffffVUUUUݪꮪXUefefffffVUUU  UUUffffffVUfUU ꪪ 񙙙UUUUUefffffUUUUU ꮪ 񙙙ݙݝXUUUUefffUVUUUUЭߝݙYUeffffffVUUUUꮪݙݪݝߙ UUfUeffffffeVUꮪݭ]UUݯUUߝݙeffffffffffVfVUUUUUeffVUUUUVݙݝXeUeffffffffffVUUPfVffffffUYUUUUfVf񙙙YUUeffffffffffVfVUUݝޙUUUUfUefffffVUUUUUUUUUUUUfUfffYUUeffffffffffVUUUU ݝUUYUUeffVefffffffUffffeffffffffffff񙙙UUUUffffffVUfVUfVi UUUfVfffffffffffffffffffffffffffffffYUUUfffffVfVUUݪ_Ufefffffffffffffffffffffffffffffffff񟙙YUUUffffffUU  UUUeffffffffffffffffffffffffffffffffff񙙙ݙ hVUffffffffU YUfefffffffffffffffffffffffffffffffffߝUeVfffffffffVUUUU UUffffffffffffffffffffffffffffffffffff񟙙XYUfffffefffffUeUUUꪪ]Uffffffffffffffffffffffffffffffffffffff񟙙ߝPeffVefffffffffVUUݙXeffffVUfffffffffffffffffffffffffffffVfff񟙙ݙUYUUUfUeffffffVefUefUUfUUeUefffffffffffffffffffffffffffUfffUUUUU`UeUUUUUUUUUefeVefffffffffVUUЭꪪifefffffffffffffffffffffffffffffUUUUUffefUffefffVffffffffffffffU鮪ݙYUUUfffffffffffffffffffffffffffUfVUUUUݭ`fffVfffffffffffffffffffffVUUꮪUefffffffffffffffffffffVUfVUffUYU `ffffffffffffffffffffffffffffUUUYꮪUUffffffffffffffffffffffVU ݭꮪ UUffffVefffffffffffffffffffffVfVUU UUUUUUfffffffffffffffffVU UUUUffffffffffffffffffffffffffffUUꮪUUUUUUefffffffffffffffUUXXUUUfffffffffffffffffffffffVUUUUUU UUUfffffffffffffffffVUUVUUU YUeUfffffffffffffffffVefVUUUUUU YUUefffffffffffffffffeVUUUU ݪ hVUffffffffffffffffffffVUUUUޭ UUUVefeffffffffffffffffVUUUUꪪݝݭUeVffffffffffffffffVffUUUUUYUUUUffffffffffffffffffffVUݪݙݙYUfffffeffffffffffffUU ꪪꪪUUUeffffffffffffffffffUUUefYYUUfVeUe YUUfVefffffffffffUVUݪ YUffffffffffffffffffffffUUUUeUUfUefUffUU UfffffffffffffffffUUQUݍUeffffffffffffffffffffffUUUfVUffffffffUUU ݐUUUfffffffffffffffffVUY]UffffffffffffffffffffffffffffffffffffUVUUUUЭYUffffffffffffffffffffVUUꪪݙhfUffVUffffffUeffffffffffffVUfffffffffffUUUU݀UeffffffffffffffffffffUUUYUUUVefffffffffffffefVeffffffffffffffffffffefUUUffffffffffffffffffffUUUU YfUeffffffffffVUUeVUUUUUUeffffffffffffUUffffVUUfYefeffUUfffffffffUefVUfꪪYUUUUffffffVefVUeUUffaffffQUUefQݪꪪ UUeffffVUUUU uWUffffffffUUUfffffUU Ufffffff UUUUeUfffVUYUaffffffffꪪUUUUUVeffVUfV QefffVffUUUح UUUffffffVUUefUUUYUfefffffUUefffUU  hUefffffffUUefeffUUUꪪUeffffffffffffVUUUU UeffffffffffVUYfYXfVffVUeffffVefUUݙXeffffUeffffffUVUUUUeVUffVefffffVfffUUUUVUeVUVUffffffffffVUUꮪYUUVUeffffffffffffUUUUXUPUUeVffffffffffffVUUefVUffffffffffffefUUUꪪꪪefeffffffffffffffffeVUYUUUUUffffffffffffffffffffffffffffffffVUeꮪꮪݙYUUUffffffffffffffffffVUUfYYUUUeVeffffffffffffffffffUefffffffffUUUUޭꪪ YUefffffffffffffffffffffVUUUUUUeUUUUeUeffffffffffffffffffffffffffffffffVUUYUUffffffffffffffffffffUeUfVUefffffffffffffffffffffffffffffffffffffffffVUU YUUUUUUffffffffffffffffffffffffffffVefffffffeffffffffffffffffffffffffffffeVUUꮪUUUUUUfffVUfffffffffffffUfffffffffffVefUUfffffffffffffffffffffffffffffffVUUꪪ UUUVefffffVffUffffffffffffVUUUUUUUUUUUUfffffffffffffVUfffffffffVUfUUUUU UUUfUfVUfUUUUUUUffffVefVUUUUUUUUfVefffVUUUUfeffffVUfVUUeVUUUe ꮪXUYyUUUUVUefUUUU XUUYUwWUefUeVffUUUUݭꮪ XUUUUUU UXUVefUUUUUݪڭꪪꪪݪ Эꮪ ݮXY Ъ ݭݪݪꮪꪪꮪڭꮪꪪݭڭ$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB)=-- title: Sonic Mini -- author: Weeppiko -- desc: A Mini Sonic Game -- license: MIT License -- version: 1.2 -- script: lua -- saveid: Sonic_Mini -- menu: Toggle HUD Style - Clear Score Data Enable Debug --pmem ids HUD_STYLE=0 HI_SCORE=1 BEST_TIME=2 --general SCR_X=0 SCR_Y=0 SCR_X_MAX=0 SCR_Y_MAX=0 TILEMAP={} TILEMAP_WID=0 TILEMAP_HEI=0 SCORE_RWD={100,200,500,1000} --flags: hhhxyfcw --hhh: height table index --xy: flip flags --fcw: floor/ceiling/walls mask MASK_FLOOR=1 MASK_CEIL=2 MASK_WALL=4 --collision HEIGHT_TABLE={ 0x88888888,0x88888888,0, --001 0x44444444,0x00008888,0, --010 0x11223344,0x00002468,-22.5,--011 0x55667788,0x24688888,-22.5,--100 0x12345678,0x12345678,-45, --101 0x24688888,0x55667788,-67.5,--110 0x00002468,0x11223344,-67.5,--111 } --special tiles T_RING=208 T_MOTOBUG=211 T_CHOPPER=212 T_CRABMEAT=213 T_BUZZBOMBER=214 T_BRIDGE=215 T_PLATFORM=216 T_SPIKES=217 T_WATERFALL=137 T_SEA=192 T_MONITOR=248 --physics PHYS_ACC=0.03 --acceleration PHYS_DEC=0.2 --deceleration PHYS_FRI=0.03 --friction PHYS_TOP=4 --top speed PHYS_MAX=7 --max speed PHYS_SLF=0.06 --slope factor PHYS_SRP=0.04 --slope roll up PHYS_SRD=0.16 --slope roll down PHYS_RDC=0.06 --roll deceleration PHYS_RFR=0.01 --roll friction PHYS_FLL=1.5 --slope slip tolerance PHYS_AAC=0.05 --air acceleration PHYS_ADR=0.12 --air drag PHYS_JMP=3.5 --jump force PHYS_JPR=1.75 --jump release PHYS_GRV=0.11 --gravity --player size NORMAL_WALL_R=7 NORMAL_FLOOR_W=6 NORMAL_FLOOR_H=9 ROLL_WALL_R=6 ROLL_FLOOR_W=5 ROLL_FLOOR_H=7 --player animations P_ANIM_STAND={ {256,2,3,8,14} } P_ANIM_WALK={ {266,2,3,8,14}, {268,2,3,8,14}, {270,2,3,8,14}, {268,2,3,8,14}, } P_ANIM_RUN={ {304,2,3,8,14}, {306,2,3,8,14}, } P_ANIM_DASH={ {308,3,3,12,14}, {311,3,3,12,14}, } P_ANIM_ROLL={ {352,2,2,8,8}, {354,2,2,8,8}, {352,2,2,8,8}, {356,2,2,8,8}, {352,2,2,8,8}, {358,2,2,8,8}, {352,2,2,8,8}, {360,2,2,8,8}, } P_ANIM_CROUCH={ {262,2,3,8,16} } P_ANIM_LOOKUP={ {264,2,3,8,14} } P_ANIM_SKID={ {314,2,3,8,14}, {316,2,3,8,14}, } P_ANIM_HURT={ {384,4,3,16,12} } P_ANIM_WAIT={ {258,2,3,8,14}, {260,2,3,8,14}, } --meta sprites S_CRABMEAT={ --plus 400 {32,33,32,48,49,48,64,65,64}, {32,35,34,51,49,50,67,65,66}, {34,35,32,50,49,51,66,65,67}, {34,33,34,48,49,48,64,65,64}, } S_BUZZBOMBER={ {469,484,485,0,0,0}, {0,484,485,0,500,501}, } S_WRECKBALL={ {197,198,197,198,199,198,197,198,197}, {0,0,1,3,0,1,3,2,2}, } S_ANIMAL={ {388,389,405}, {420,421,437}, } --level cards LVL_CARDS={ {'GREEN HILL',true,nil}, } --short pi=math.pi deg=math.deg rad=math.rad sin=math.sin cos=math.cos abs=math.abs min=math.min max=math.max rand=math.random atan2=math.atan2 floor=math.floor ceil=math.ceil sort=table.sort insert=table.insert remove=table.remove concat=table.concat unpack=table.unpack char=string.char byte=string.byte sub=string.sub crtcreate=coroutine.create crtresume=coroutine.resume crtyield=coroutine.yield crtstate=coroutine.state --time helpers do local lt,ct,dt,fr,tk,ts,tm=time(),0,0,0,0,0,0 function step() tm,dt,lt,ct,tk,ts=time(),(tm-lt)/1000,tm,ct+dt,tk+1,ts+1 if ct>=1 then ct,fr,tk=ct%1,tk,0 end end function tick() return ts end function delta() return dt end function fps() return fr end end --helpers function sin2(x) return sin(rad(x)) end function cos2(x) return cos(rad(x)) end function sign(x) return x>0 and 1 or x<0 and -1 or 0 end function clamp(x,a,b) return max(a,min(b,x)) end function appr(a,b,s) if abs(b-a)<=1e-10 then return b elseif ab then return max(a-s,b) else return b end end function angdiff(a,b) return deg(atan2(sin(b-a),cos(b-a))) end function angappr(a,b,s) return appr(a,a+angdiff(a,b),s) end function angdiff2(a,b) return deg(atan2(sin2(b-a),cos2(b-a))) end function angappr2(a,b,s) return appr(a,a+angdiff2(a,b),s) end function vector(a) return cos(a),sin(a) end function lerp(a,b,s) return a+(b-a)*clamp(s,0,1) end function randsign() return rand()>0.5 and 1 or -1 end function flag(id,fl) if fl then poke(0x14404+id,fl) end;return peek(0x14404+id) end function fontset(spr_id,w,h,alt) local d=alt and 160 or 32 for c=0,95 do for i=0,7 do local v=peek(0x4000+spr_id*32+c//4*32+c%4+i*4) poke(0x14604+(d+c)*8+i,v) end end w=min(8,max(1,w or 8)) h=min(8,max(1,h or 8)) poke(0x149FC,w) poke(0x149FD,h) end function pal(i,c) if i then poke4(0x03FF0*2+i,c or i) else for i=0,15 do poke4(0x03FF0*2+i,i) end end end --sort functions function priority_sort(a,b) return (a.priority or 0)<(b.priority or 0) end function draw_sort(a,b) return (a.z or 0)>(b.z or 0) end --transformation and related stuff function transform(px,py,x,y,r,sx,sy,ox,oy) x,y,r,sx,sy,ox,oy=x or 0,y or 0,r or 0,sx or 1,sy or 1,ox or 0,oy or 0 local c,s=cos(r),sin(r) px,py=(px-ox)*sx,(py-oy)*sy return (px*c-py*s)+x,(px*s+py*c)+y end function tilt(x,y,r,t) local c,s=cos(r),sin(r) local x,y=x*c-y*s,x*s+y*c return x*3,y*(t*3) end function textsize(txt,mono,scl,alt) return print(txt,0,0xffffff,0,mono,scl or 1,alt) end --drawable stuff function xspr(id,x,y,w,h,r,sx,sy,ox,oy,tc) id,w,h=id%512,(w or 1)//1,(h or 1)//1 local u1,v1=(id%16)*8,(id//16)*8 local u2,v2=u1+w*8,v1 local u3,v3=u2,v2+h*8 local u4,v4=u1,v3 local x1,y1=transform(0,0,x,y,r,sx,sy,ox,oy) local x2,y2=transform(w*8,0,x,y,r,sx,sy,ox,oy) local x3,y3=transform(w*8,h*8,x,y,r,sx,sy,ox,oy) local x4,y4=transform(0,h*8,x,y,r,sx,sy,ox,oy) ttri(x1,y1,x2,y2,x3,y3,u1,v1,u2,v2,u3,v3,nil,tc) ttri(x3,y3,x4,y4,x1,y1,u3,v3,u4,v4,u1,v1,nil,tc) end function patr(tx,ty,w,h,x,y,r,sx,sy,ox,oy,tc) w,h=(w or 1)//1,(h or 1)//1 local u1,v1=tx*8,ty*8 local u2,v2=u1+w*8,v1 local u3,v3=u2,v2+h*8 local u4,v4=u1,v3 local x1,y1=transform(0,0,x,y,r,sx,sy,ox,oy) local x2,y2=transform(w*8,0,x,y,r,sx,sy,ox,oy) local x3,y3=transform(w*8,h*8,x,y,r,sx,sy,ox,oy) local x4,y4=transform(0,h*8,x,y,r,sx,sy,ox,oy) ttri(x1,y1,x2,y2,x3,y3,u1,v1,u2,v2,u3,v3,1,tc) ttri(x3,y3,x4,y4,x1,y1,u3,v3,u4,v4,u1,v1,1,tc) end function printb(txt,x,y,c1,c2,ms,sc,alt,th) x,y,th=x or 0,y or 0,th or 1 for yy=-th,th do for xx=-th,th do if xx~=0 or yy~=0 then print(txt,x+xx,y+yy,c2,ms,sc,alt) end end end return print(txt,x,y,c1,ms,sc,alt) end function texquad(tx,ty,tw,th,x1,y1,x2,y2,x3,y3,x4,y4,src,clr) ttri(x1,y1,x2,y2,x3,y3,tx,ty,tx+tw,ty,tx+tw,ty+th,src,clr) ttri(x3,y3,x4,y4,x1,y1,tx+tw,ty+th,tx,ty+th,tx,ty,src,clr) end function quad(x1,y1,x2,y2,x3,y3,x4,y4,clr) tri(x1,y1,x2,y2,x3,y3,clr) tri(x1,y1,x3,y3,x4,y4,clr) end function rectskew(x,y,w,h,sx,sy,clr) local kx,ky=h*sx,w*sy quad(x,y,x+w,y+ky,x+kx+w,y+ky+h,x+kx,y+h,clr) end function hitbox(x,y,w,h,c) rectb(x-SCR_X-w,y-SCR_Y-h,w*2+1,h*2+1,c) pix(x-SCR_X,y-SCR_Y,13) pix(x-SCR_X-1,y-SCR_Y,15) pix(x-SCR_X+1,y-SCR_Y,15) pix(x-SCR_X,y-SCR_Y-1,15) pix(x-SCR_X,y-SCR_Y+1,15) end function fadeout(step,alt) local t=clamp(step/60,0,1) vbank(1) if alt then rect(0,0,240,68*(1-t),0) rect(0,68+68*t,240,68*(1-t)+1,0) else cls();circ(120,68,160*t,14) end for i=0,3 do local v=peek(0xFF9C+i*18+1) local f=v&15 v=ceil((v>>4)*t)<<4 poke(0xFF9C+i*18+1,v|f) end poke(0x3FF8,step>=0 and 14 or 0) vbank(0) return max(0,step-1) end function anim_tile(t,x,y) if t==T_RING then local f=tick()%24 if f<6 then return t elseif f<12 then return t+1 elseif f<18 then return t+2 else return t+1,1 end elseif t==T_WATERFALL or t==T_SEA then local f=tick()%12 if f<4 then return t elseif f<8 then return t+1 else return t+2 end end return t end --audio stuff function get_sound_state() return peek(0x13FFC),peek(0x13FFD),peek(0x13FFE) end function play_lvlmusic(fast) music(0,0,0,true,true) end function play_invcmusic() music(1,0,0,true,true) end function play_bossmusic() music(2,0,0,true,true) end function play_clearmusic() music(3,0,0,false,true) end function play_titlemusic() music(4,0,0,false,true) end function update_music() local t,f,r=get_sound_state() if t==0 and g_player.t_invc>0 then play_invcmusic() t,f,r=get_sound_state() elseif t==1 and g_player.t_invc<=0 then play_lvlmusic() t,f,r=get_sound_state() end if t<2 then local v=g_player.t_turbo>0 and 30 or 0 poke(0x13E64+(t*51)+48,v) end if g_player.t_invc>=0 and g_player.t_invc<120 and t==1 then for i=0,3 do if peek(0x0FF8C+4*i)>=29 then local t=g_player.t_invc/120 local v=peek(0xFF9C+i*18+1) local f=v&15 v=ceil((v>>4)*t)<<4 poke(0xFF9C+i*18+1,v|f) end end end end --input function INPUT(lock) HOLD_U=btn(0) and not lock HOLD_D=btn(1) and not lock HOLD_L=btn(2) and not lock HOLD_R=btn(3) and not lock HOLD_A=btn(4) and not lock HOLD_B=btn(5) and not lock PRESS_A=btnp(4) and not lock PRESS_B=btnp(5) and not lock end --collision system function tmget(x,y) if x<0 or x>=TILEMAP_WID then return 0 end if y<0 or y>=TILEMAP_HEI then return 0 end return TILEMAP[1+x+y*TILEMAP_WID] end function tmset(x,y,v) if x<0 or x>=TILEMAP_WID then return end if y<0 or y>=TILEMAP_HEI then return end TILEMAP[1+x+y*TILEMAP_WID]=v end function tmap(x,y,w,h,sx,sy,ck,sc,remap) for yy=0,h-1 do for xx=0,w-1 do local i,f,r=tmget(xx+(x//1),yy+(y//1)) if remap then i,f,r=remap(i,xx+(x//1),yy+(y//1)) end spr(i,xx*8+sx,yy*8+sy,ck,sc,f,r) end end end function get_tile_slope(x,y) local val,slp,xfl,yfl,msk val=peek(0x14404+tmget(x//8,y//8)) slp,xfl,yfl,msk=(val&7),(val>>3)&1,(val>>4)&1,(val>>5)&7 if slp==0 then return 0,0,0,false,false,0 end slp=(slp-1)*3+1 local h=HEIGHT_TABLE return h[slp],h[slp+1],h[slp+2],xfl==1,yfl==1,msk end function get_slope(slp,x,xfl) if xfl then return (slp>>((x//1)*4))&15 else return (slp>>((7-(x//1))*4))&15 end end function collision_down(x,y,m) if DEBUG then insert(COL_LIST,{x,y,15}) end local slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) local h=yfl and 8 or get_slope(slp,x%8,xfl) if msk&m==0 then h=0 end if h==0 or h==8 then y=y+(h==0 and 8 or -8) slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) h=yfl and 8 or get_slope(slp,x%8,xfl) if msk&m==0 then h=0 end end y=y-((y%8)-(8-h)) if xfl then ang=-ang end if yfl then ang=(180-abs(ang))*sign(ang) end return y-0.5,ang end function collision_right(x,y,m) if DEBUG then insert(COL_LIST,{x,y,15}) end local slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) local w=xfl and 8 or get_slope(wll,y%8,yfl) if msk&m==0 then w=0 end if w==0 or w==8 then x=x+(w==0 and 8 or -8) slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) w=xfl and 8 or get_slope(wll,y%8,yfl) if msk&m==0 then w=0 end end x=x-((x%8)-(8-w)) if xfl then ang=-ang end if yfl then ang=(180-abs(ang))*sign(ang) end return x-0.5,ang end function collision_up(x,y,m) if DEBUG then insert(COL_LIST,{x,y,15}) end local slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) local h=get_slope(slp,x%8,xfl) if (not yfl) and h~=0 then h=8 end if msk&m==0 then h=0 end if h==0 or h==8 then y=y+(h==0 and -8 or 8) slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) h=get_slope(slp,x%8,xfl) if (not yfl) and h~=0 then h=8 end if msk&m==0 then h=0 end end y=y-((y%8)-h) if xfl then ang=-ang end if yfl then ang=(180-abs(ang))*sign(ang) end return y+0.5,ang end function collision_left(x,y,m) if DEBUG then insert(COL_LIST,{x,y,15}) end local slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) local w=get_slope(wll,y%8,yfl) if (not xfl) and w~=0 then w=8 end if msk&m==0 then w=0 end if w==0 or w==8 then x=x+(w==0 and -8 or 8) slp,wll,ang,xfl,yfl,msk=get_tile_slope(x,y) w=get_slope(wll,y%8,yfl) if (not xfl) and w~=0 then w=8 end if msk&m==0 then w=0 end end x=x-((x%8)-w) if xfl then ang=-ang end if yfl then ang=(180-abs(ang))*sign(ang) end return x+0.5,ang end function collision_rect(ax,ay,aw,ah,bx,by,bw,bh,clr) local cw,ch=aw+bw,ah+bh if DEBUG then insert(COL_LIST,{bx,by,bw,bh,clr or 15}) end if ax>=bx-cw and ax<=bx+cw and ay>=by-ch and ay<=by+ch then local x_diff,y_diff=ax-bx,ay-by if abs(x_diff)-cw>=abs(y_diff)-ch then if x_diff>0 then return true,bx+cw,nil else return true,bx-cw,nil end else if y_diff>0 then return true,nil,by+ch else return true,nil,by-ch end end end end function collision_vert(ax,ay,aw,ah,bx,by,bw,bh,clr) local cw,ch=aw+bw,ah+bh if DEBUG then insert(COL_LIST,{bx,by,bw,bh,clr or 15}) end if ax>=bx-cw and ax<=bx+cw and ay>=by-ch and ay<=by+ch then local y_diff=ay-by if y_diff>0 then return true,by+ch else return true,by-ch end end end function collision_horz(ax,ay,aw,ah,bx,by,bw,bh,clr) local cw,ch=aw+bw,ah+bh if DEBUG then insert(COL_LIST,{bx,by,bw,bh,clr or 15}) end if ax>=bx-cw and ax<=bx+cw and ay>=by-ch and ay<=by+ch then local x_diff=ax-bx if x_diff>0 then return true,bx+cw else return true,bx-cw end end end --animation function new_anim(seq,dur) return {seq=seq,cnt=0,frm=0,dur=dur or 0} end function anim_step(a) a.cnt=a.cnt+1 if a.cnt>=a.dur then a.cnt=0 a.frm=(a.frm+1)%#a.seq end end function anim_draw(a,x,y,r,sx,sy,c) q=a.seq[a.frm+1] x,y=(x-SCR_X)//1,(y-SCR_Y)//1 xspr(q[1],x,y,q[2],q[3],r,sx,sy,q[4],q[5],c) end function anim_set(a,s,d) a.dur=d if a.seq~=s then a.seq=s;anim_reset(a) end end function anim_reset(a) a.frm,a.cnt=0,0 end --player function p_create(x,y,f) local p={x=x or 0,y=y or 0,flip=f or 1,z=1} p_reset(p) insert(g_objects,p) return p end function p_reset(p) p.type,p.priority,p.t_wait='p',10,0 p.anim=new_anim(P_ANIM_RUN) p.state,p.substate=p_normal p.g_ang,p.gsp,p.xsp,p.ysp=0,0,0,0 p.mode,p.t_skid,p.t_lock,p.s_ang=0,0,0,0 p.dash,p.land,p.jump,p.shield=0 p.t_blink,p.t_invc,p.t_turbo=0,-1,-1 p.wll_r=NORMAL_WALL_R p.flr_w=NORMAL_FLOOR_W p.flr_h=NORMAL_FLOOR_H end function p_check_landed(p) local o=p.land if o.delete then p.land=true; return end local x,y,w,h=p_colbox(p) local cw,ch=o.w+w,o.h+h if xo.x+cw+1 then p.land=true else p.y=o.y-ch end end function p_check_floor(p) if p.mode==0 then if type(p.land)=='table' then p_check_landed(p) return true end local sy=p.y+p.flr_h local y1,a1=collision_down(p.x-p.flr_w,sy,MASK_FLOOR) local y2,a2=collision_down(p.x+p.flr_w,sy,MASK_FLOOR) if y2y1 then y1,a1=y2,a2 end if a1==0 then a1=180 end if y1>sy or (abs(y1-sy)<=7 and p.land) then p.y,p.g_ang,p.land,p.jump=y1+p.flr_h,a1,true,false return true end elseif p.mode==3 then local sx=p.x-p.flr_h local x1,a1=collision_left(sx,p.y-p.flr_w,MASK_WALL) local x2,a2=collision_left(sx,p.y+p.flr_w,MASK_WALL) if x2>x1 then x1,a1=x2,a2 end if a1==0 then a1=90 end if x1>sx or (abs(x1-sx)<=7 and p.land) then p.x,p.g_ang,p.land,p.jump=x1+p.flr_h,a1,true,false return true end end p.land=false end function p_check_wall(p) if p.land and abs(p.g_ang)%90==45 then return end local o=(p.land and p.g_ang~=0) and -6 or 0 if p.mode%2==0 then if p.mode==2 then o=-o end if p.xsp>0 then local x,a=collision_right(p.x+p.wll_r,p.y+o,MASK_WALL) if xp.x-p.wll_r then p.x,p.xsp=x+p.wll_r,0 if p.land then p.gsp=0 end end end else if p.mode==3 then o=-o end if p.ysp>0 then local y,a=collision_down(p.x+o,p.y+p.wll_r,MASK_FLOOR) if yp.y-p.wll_r then p.y,p.ysp,p.gsp=y+p.wll_r,0,0 end end end end function p_check_ceil(p) local sy=p.y-p.flr_h local y1,a1=collision_up(p.x-p.flr_w,sy,MASK_CEIL) local y2,a2=collision_up(p.x+p.flr_w,sy,MASK_CEIL) if y2>y1 then y1,a1=y2,a2 end if y1>sy then p.y,p.g_ang=y1+p.flr_h,a1 return true end end function p_check_touches(p) local tx,ty=p.x//8,p.y//8 for y=ty-2,ty+2 do for x=tx-2,tx+2 do local t=tmget(x,y) if t==T_RING then if p_touch(p,x*8+4,y*8+4,4,4,7) then tmset(x,y,0) g_rings=g_rings+1 g_lvlrings=g_lvlrings-1 sparkle_create(x*8+4,y*8+4) sfx(20,75,-1,1) end end end end end function p_update_mode(p) if p.state==p_airborne then p.mode=0; return end local a=p.g_ang if p.state==p_airborne then p.mode=0 elseif a>=-45 and a<=45 then p.mode=0 elseif a<-45 and a>-135 then p.mode=1 elseif a>45 and a<135 then p.mode=3 else p.mode=2 end end function p_update_ground(p) p.gsp=clamp(p.gsp,-PHYS_MAX,PHYS_MAX) p.xsp=cos2(p.g_ang)*p.gsp p.ysp=sin2(p.g_ang)*p.gsp p.x=p.x+p.xsp p.y=p.y+p.ysp p_check_wall(p) p_check_floor(p) if not p.land then p.state=p_airborne else if p.t_lock<=0 and abs(p.g_ang)>45 and abs(p.gsp)=80 then p.land=false p.state=p_airborne end p_adjsensor(p) end end end function p_check_jump(p) if PRESS_A then p.substate='roll' p.jump=true p.land=false p.xsp=p.xsp-sin2(p.g_ang)*-PHYS_JMP p.ysp=p.ysp+cos2(p.g_ang)*-PHYS_JMP p.t_lock=0 p.state=p_airborne p_adjsensor(p) sfx(16,64,-1,1) return true end end function p_normal(p) p.t_wait=p.t_wait+1 if p.gsp~=0 or p.substate then p.t_wait=0 end if p.substate=='crouch' and PRESS_A then p.state=p_dash p.substate='roll' p_adjsensor(p) p.dash=0 sfx(18,68,-1,1) return p:state() end if p.substate=='lookup' and PRESS_A then p.state=p_dash p.substate=nil p_adjsensor(p) p.dash=0 sfx(18,68,-1,1) return p:state() end if HOLD_D and abs(p.gsp)>0.4 then p.t_skid=0 p.state=p_roll p.substate='roll' p_adjsensor(p) sfx(18,64,-1,1) return p:state() end if p_check_jump(p) then return p:state() end if abs(p.gsp)<0.15 and abs(p.g_ang)<45 then if HOLD_D or HOLD_U then p.substate=HOLD_D and 'crouch' or 'lookup' p.gsp,p.xsp,p.t_skid=0,0,0 p_adjsensor(p) return p_update_ground(p) else if p.substate=='crouch' or p.substate=='lookup' then p.substate=nil p_adjsensor(p) end end end local mul=p.t_turbo>0 and 2 or 1 p.gsp=p.gsp+sin2(p.g_ang)*PHYS_SLF*mul if HOLD_L and p.t_lock<=0 then if p.gsp>0 then p.gsp=p.gsp-PHYS_DEC if p.gsp<=0 then p.gsp=-0.3 p.t_skid=0 end elseif p.gsp>-PHYS_TOP*mul then p.gsp=p.gsp-PHYS_ACC*mul if p.gsp<=-PHYS_TOP*mul then p.gsp=-PHYS_TOP*mul end end if p.gsp<0 then p.flip=-1 p.t_skid=0 elseif p.gsp>=2.5 and p.mode==0 then p.flip=1 if p.t_skid<=0 then sfx(19,70,-1,1) end p.t_skid=60 end elseif HOLD_R and p.t_lock<=0 then if p.gsp<0 then p.gsp=p.gsp+PHYS_DEC if p.gsp>=0 then p.gsp=0.3 p.t_skid=0 end elseif p.gsp=PHYS_TOP*mul then p.gsp=PHYS_TOP*mul end end if p.gsp>0 then p.flip=1 p.t_skid=0 elseif p.gsp<=-2.5 and p.mode==0 then p.flip=-1 if p.t_skid<=0 then sfx(19,70,-1,1) end p.t_skid=60 end else p.gsp=p.gsp-min(abs(p.gsp),PHYS_FRI*mul)*sign(p.gsp) end p_update_ground(p) end function p_roll(p) local mul=p.t_turbo>0 and 2 or 1 if p.g_ang<0 then if p.gsp>0 then p.gsp=p.gsp+PHYS_SRP*sin2(p.g_ang) elseif p.gsp<0 then p.gsp=p.gsp+PHYS_SRD*sin2(p.g_ang) else p.gsp=p.gsp+PHYS_SLF*sin2(p.g_ang) end elseif p.g_ang>0 then if p.gsp<0 then p.gsp=p.gsp+PHYS_SRP*sin2(p.g_ang) elseif p.gsp>0 then p.gsp=p.gsp+PHYS_SRD*sin2(p.g_ang) else p.gsp=p.gsp+PHYS_SLF*sin2(p.g_ang) end else p.gsp=p.gsp+PHYS_SLF*sin2(p.g_ang) end if p_check_jump(p) then return p:state() end if HOLD_L and p.t_lock<=0 and p.gsp>0 then p.gsp=p.gsp-PHYS_RDC elseif HOLD_R and p.t_lock<=0 and p.gsp<0 then p.gsp=p.gsp+PHYS_RDC end p.gsp=p.gsp-min(abs(p.gsp),PHYS_RFR*mul)*sign(p.gsp) p_update_ground(p) if not p.land then return end if abs(p.gsp)<0.1 then p.state=p_normal p.substate=nil p_adjsensor(p) end end function p_airborne(p) local mul=p.t_turbo>0 and 2 or 1 if p.substate=='roll' then if p.ysp<-PHYS_JPR and (not HOLD_A and p.jump) then p.jump=false p.ysp=-PHYS_JPR end end if p.substate~='hurt' then if HOLD_L then p.flip=-1 if p.xsp>-PHYS_TOP*mul then p.xsp=p.xsp-PHYS_AAC*mul if p.xsp<=-PHYS_TOP*mul then p.xsp=-PHYS_TOP*mul end end elseif HOLD_R then p.flip=1 if p.xsp=PHYS_TOP*mul then p.xsp=PHYS_TOP*mul end end end end p.xsp=clamp(p.xsp,-PHYS_MAX,PHYS_MAX) p.ysp=clamp(p.ysp,-PHYS_MAX,PHYS_MAX) p.x,p.y=p.x+p.xsp,p.y+p.ysp if p.ysp<0 and p.ysp>-1.0 then p.xsp=p.xsp-((p.xsp/PHYS_ADR)/256) end p.ysp=clamp(p.ysp+PHYS_GRV,-PHYS_MAX,PHYS_MAX) p.g_ang=angappr2(p.g_ang,0,3) p_check_wall(p) if p.ysp<=0 then if p_check_ceil(p) then if abs(p.g_ang)>=90 and abs(p.g_ang)<=135 then p.gsp=p.ysp*sign(sin2(p.g_ang)) p.xsp=cos2(p.g_ang)*p.gsp p.ysp=sin2(p.g_ang)*p.gsp p.mode=2 p.substate=nil p.state=p_normal p.jump=false p.land=true p_adjsensor(p) p_update_mode(p) else p.ysp=0 end end end if p.ysp>=0 and not p.land then p_check_floor(p) if p.land then if abs(p.xsp)>p.ysp then p.gsp=p.xsp elseif abs(p.g_ang)>=45 then p.gsp=p.ysp*sign(sin2(p.g_ang)) elseif abs(p.g_ang)>=22.5 then p.gsp=p.ysp*sign(sin2(p.g_ang))*0.5 else p.gsp=p.xsp end if abs(p.g_ang)<22.5 then p.t_lock=0 end p.xsp=cos2(p.g_ang)*p.gsp p.ysp=sin2(p.g_ang)*p.gsp p.state=p_normal p.substate=nil p_adjsensor(p) p_update_mode(p) end end end function p_dash(p) local spin=HOLD_D and p.substate=='roll' local dash=HOLD_U and p.substate==nil local rel=spin and 45 or 30 if spin or dash then p.dash=min(rel,p.dash+1) else if p.dashSCR_Y+300 then p.delete=true g_fadeout=60 end end function p_hit(p,forced) if p.state==p_death then return end if (p.t_blink>0 or p.t_invc>0) and not forced then return end p.state,p.substate=p_airborne,'hurt' p.t_invc,p.land,p.jump=0 p.gsp,p.xsp,p.ysp=0,-p.flip*2,-2 sfx(22,22,-1,2) if not forced then if p.shield then p.shield=nil p.t_blink=180 elseif g_rings>0 then sfx(21,74,-1,1) ring_scatter(g_rings,p.x,p.y,p.flip) p.t_blink,g_rings=180,0 else p_kill(p) end end end function p_kill(p) if p.state==p_death then return end p.state,p.substate=p_death,'hurt' p.land,p.jump=nil p.gsp,p.xsp,p.ysp=0,-p.flip,-3 p.t_blink=0 sfx(22,22,-1,2) end function p_rebound(p,x,y) if p.state~=p_airborne then return end if p.y>y or p.ysp<0 then return end p.ysp=-p.ysp*(PRESS_J and 2 or 1) p.ysp=clamp(p.ysp,-PHYS_MAX,PHYS_MAX) end function p_hitbox(p) if p.substate=='roll' or p.substate=='crouch' then return p.x,p.y,5,5 else return p.x,p.y,6,8 end end function p_colbox(p) return p.x,p.y,p.wll_r,p.flr_h end function p_touch(p,rx,ry,rw,rh,clr) local x,y,w,h=p_hitbox(p) return collision_rect(x,y,w,h,rx,ry,rw,rh,clr) end function p_collide(p,o,t) if p.state==p_death then return end if p.land==o then return end local vx,vy,cl,nx,ny=0,0 local x,y,w,h=p_colbox(p) if t=='vert' then cl,ny=collision_vert(x,y,w,h,o.x,o.y,o.w,o.h,15) elseif t=='horz' then cl,nx=collision_horz(x,y,w,h,o.x,o.y,o.w,o.h,15) else cl,nx,ny=collision_rect(x,y,w,h,o.x,o.y,o.w,o.h,15) end if not cl then return end if ny then if ny>o.y and p.ysp<=0 then p.y,p.ysp,p.g_ang,vy=ny,0,0,1 elseif ny<=o.y and p.ysp>=0 then p.y,p.ysp,p.g_ang,vy=ny,0,0,-1 p_objland(p,o) end end if nx then if nx>o.x and p.xsp<=0 then p.x,p.xsp,vx=nx,0,1 if p.land then p.gsp=p.xsp end elseif nx=0 then p.x,p.xsp,vx=nx,0,-1 if p.land then p.gsp=p.xsp end end end return cl,vx,vy end function p_draw(p) local d anim_step(p.anim) if p.state==p_dash then if p.substate=='roll' then d=max(0,(35-abs(p.dash))/10) anim_set(p.anim,P_ANIM_ROLL,d) else d=max(0,(45-abs(p.dash))/10) anim_set(p.anim,P_ANIM_DASH,d) end elseif p.substate=='roll' then d=max(0,4-abs(p.gsp)) anim_set(p.anim,P_ANIM_ROLL,d) elseif p.substate=='crouch' then anim_set(p.anim,P_ANIM_CROUCH,0) elseif p.substate=='lookup' then anim_set(p.anim,P_ANIM_LOOKUP,0) elseif p.substate=='hurt' then anim_set(p.anim,P_ANIM_HURT,0) else if p.t_skid>0 and abs(p.g_ang)<=45 then anim_set(p.anim,P_ANIM_SKID,4) elseif abs(p.gsp)>PHYS_TOP+1 then d=max(0,8-abs(p.gsp)) anim_set(p.anim,P_ANIM_DASH,d) elseif abs(p.gsp)>=3.5 then d=max(0,8-abs(p.gsp)) anim_set(p.anim,P_ANIM_RUN,d) elseif abs(p.gsp)>0 then d=max(0,8-abs(p.gsp)) anim_set(p.anim,P_ANIM_WALK,d) elseif p.t_wait>180 then anim_set(p.anim,P_ANIM_WAIT,16) else anim_set(p.anim,P_ANIM_STAND,0) end end if p.substate=='roll' or p.substate=='hurt' then p.s_ang=0 elseif abs(angdiff2(p.s_ang,p.g_ang))>45 then p.s_ang=p.g_ang elseif abs(p.g_ang)>=45 then p.s_ang=angappr2(p.s_ang,p.g_ang,8) else p.s_ang=angappr2(p.s_ang,0,8) end if p.t_blink==0 or p.t_blink%2<1 then anim_draw(p.anim,p.x,p.y,rad(p.s_ang),p.flip,1,5) end if p.shield and tick()%4<2 and p.t_invc<=0 then if tick()%2==0 then circ(p.x-SCR_X,p.y-SCR_Y,10,11) circb(p.x-SCR_X,p.y-SCR_Y,10,10) else circ(p.x-SCR_X,p.y-SCR_Y,tick()%10+1,12) circb(p.x-SCR_X,p.y-SCR_Y,tick()%10+1,15) end end end function p_update_view(p) if p.state==p_death then return end local dx=clamp(p.x-(SCR_X+120),-16,16) local dy=clamp(p.y-(SCR_Y+68),-24,24) if dx>8 then SCR_X=SCR_X+(dx-8) end if dx<-8 then SCR_X=SCR_X+(dx+8) end if dy>16 then SCR_Y=SCR_Y+(dy-16) end if dy<-16 then SCR_Y=SCR_Y+(dy+16) end if p.land then SCR_Y=appr(SCR_Y,p.y-68,1) end SCR_X=clamp(SCR_X,SCR_X_MIN,SCR_X_MAX-240)//1 SCR_Y=clamp(SCR_Y,SCR_Y_MIN,SCR_Y_MAX-136)//1 if g_bossdefeated then SCR_X_MIN=SCR_X end end function p_adjsensor(p) local d,s=0,p.substate if s=='roll' or s=='jump' or s=='crouch' then d=p.flr_h-ROLL_FLOOR_H p.flr_w=ROLL_FLOOR_W p.flr_h=ROLL_FLOOR_H p.wll_r=ROLL_WALL_R else d=p.flr_h-NORMAL_FLOOR_H p.flr_w=NORMAL_FLOOR_W p.flr_h=NORMAL_FLOOR_H p.wll_r=NORMAL_WALL_R end if p.mode==0 then p.y=p.y+d elseif p.mode==1 then p.x=p.x+d elseif p.mode==2 then p.y=p.y-d elseif p.mode==3 then p.x=p.x-d end end function p_objland(p,o) if not p.land then if p.state==p_airborne then p.substate=nil p.gsp=p.xsp p.ysp=0 end p.state=p_normal p.jump=false end p.land=o p_adjsensor(p) end function p_update(p) if p.t_lock>0 and p.land then p.t_lock=p.t_lock-1 end if p.t_skid>0 then p.t_skid=p.t_skid-1 end if p.t_blink>0 and p.substate~='hurt' then p.t_blink=p.t_blink-1 end if p.t_invc>=0 then p.t_invc=p.t_invc-1 end if p.t_turbo>=0 then p.t_turbo=p.t_turbo-1 end if abs(p.g_ang)>=45 or p.state==p_airborne or p.gsp==0 then p.t_skid=0 end p:state();p_update_mode(p) if p.xSCR_X_MAX-p.wll_r then p.x,p.xsp,p.gsp=SCR_X_MAX-p.wll_r,0,0 end if p.substate~='hurt' then p_check_touches(p) end if p.land then g_mulscore=1 end if p.y>SCR_Y+136+16 then p_kill(p) end if p.t_invc>0 and tick()%4==0 then local r=rad(tick()%360) local ox,oy=transform(10,0,0,0,r*10*p.flip) sparkle_create(p.x+ox,p.y+oy,1) sparkle_create(p.x-ox,p.y-oy,1) end end --scattered rings function ring_create(x,y,xsp,ysp,sp) insert(g_objects,{ type='ring',special=sp, x=x,y=y,z=2,sc=1,w=4,h=4, xsp=xsp,ysp=ysp,life=384, }) end function ring_update(o) local x,y if not o.special then if o.xsp>0 then x=collision_right(o.x+4,o.y,MASK_WALL) if xo.x-4 then o.x,o.xsp=x+4,abs(o.xsp) end end if o.ysp>0 then y=collision_down(o.x,o.y+4,MASK_FLOOR) if yo.y-4 then o.y,o.ysp=y+4,0 end end end o.ysp,o.x,o.y=o.ysp+0.1,o.x+o.xsp,o.y+o.ysp if o.special then o.sc=o.sc+0.05 end o.life=o.life-1 if o.life<=0 then o.delete=true end if o.special and o.sc>=5 then o.delete=true end if (not o.special) and g_player.substate~='hurt' and o.life<=354 then if p_touch(g_player,o.x,o.y,o.w,o.h,7) then o.delete=true g_rings=g_rings+1 sparkle_create(o.x,o.y) sfx(20,75,-1,1) end end end function ring_scatter(amnt,x,y,f) local r,s,f=min(amnt,32),min(amnt-32,16),f or 1 if r>8 then local a,b=ceil(r//2),floor(r//2) for i=0,a-1 do local xs,ys=vector((i/a)*(pi*2)-pi/2) ring_create(x,y,xs*3*f,ys*3) end for i=0,b-1 do local xs,ys=vector(((i+0.5)/b)*(pi*2)-pi/2) ring_create(x,y,xs*2*f,ys*2) end elseif r==2 then ring_create(x,y,-2,0) ring_create(x,y,2,0) else for i=0,r-1 do local xs,ys=vector((i/r)*(pi*2)-pi*2) ring_create(x,y,xs*2*f,ys*2) end end if s>0 then for i=0,s-1 do local xs,ys=vector((i/s)*(pi*2)-pi/2) ring_create(x,y,xs*4*f,ys*4,true) end end end function ring_draw(o) local i,f=0,1 local t,sx,sy=tick()%24,o.x-SCR_X,o.y-SCR_Y if (o.life>120 and o.sc<2.5) or t%8<4 then if t<6 then i=T_RING elseif t<12 then i=T_RING+1 elseif t<18 then i=T_RING+2 else i,f=T_RING+1,-1 end if o.special then vbank(1) end xspr(i,sx,sy,1,1,0,f*o.sc,o.sc,4,4,0) if o.special then vbank(0) end end end --shared badniks code function badnik_check(o) if p_touch(g_player,o.x,o.y,o.w,o.h,9) then if g_player.substate=='roll' or g_player.t_invc>0 then o.delete=true sfx(17,48,-1,1) puff_create(o.x,o.y) --ring_create(o.x,o.y,0,-2.25,false) animal_create(o.x,o.y,-1) p_rebound(g_player,o.x,o.y) points_create(o.x,o.y-8,SCORE_RWD[g_mulscore]) g_score=g_score+SCORE_RWD[g_mulscore] g_mulscore=min(g_mulscore+1,#SCORE_RWD) return 1 else p_hit(g_player) return 0 end end end function on_screen(x,y,ov) ov=ov or 16 return x>=SCR_X-ov and x<=SCR_X+240+ov and y>=SCR_Y-ov and y<=SCR_Y+136+ov end --motobug function motobug_create(x,y,f) insert(g_objects,{type='motobug',ysp=0, x=x,y=y,w=5,h=5,flip=-1, wait=false,count=0,frame=0 }) end function motobug_update(o) if o.wait then o.count,o.frame=o.count-1,0 if o.count<=0 then o.flip,o.wait=-o.flip,false end elseif on_screen(o.x,o.y,256) then if o.flip<0 then local y=collision_down(o.x-3,o.y+8,MASK_FLOOR) if abs(y-(o.y+8))>=6 then o.wait,o.count=true,60 else o.x=o.x-0.5 local x=collision_left(o.x-3,o.y,MASK_WALL) if x>o.x then o.x,o.wait,o.count=x+3,true,60 end if o.x<0 then o.x,o.wait,o.count=0,true,60 end end else local y=collision_down(o.x+3,o.y+8,MASK_FLOOR) if abs(y-(o.y+8))>=6 then o.wait,o.count=true,60 else o.x=o.x+0.5 local x=collision_right(o.x+3,o.y,MASK_WALL) if xTILEMAP_WID*8 then o.x,o.wait,o.count=TILEMAP_WID*8,true,60 end end end end o.ysp=o.ysp+PHYS_GRV o.y=o.y+o.ysp local y=collision_down(o.x,o.y+8,MASK_FLOOR) if y=o.oy then o.y,o.ysp=o.oy,-3.5 end badnik_check(o) end function chopper_draw(o) local dur,frm=9,0 if abs(o.y-o.oy)>=64 then dur=4 elseif o.ysp<=0 then dur=8 else o.frame,dur=0,9 end o.frame=(o.frame+1)%(dur*2) frm=o.frame//dur local x,y=o.x-SCR_X-8,o.y-SCR_Y-8 spr(486+2*frm,x,y,5,1,0,0,2,2) end --crabmeat function crabmeat_create(x,y) insert(g_objects,{ type='crabmeat',x=x,y=y,w=10,h=8, wait=160,mode=0,flip=-1, }) end function crabmeat_update(o) if not on_screen(o.x,o.y,256) then return end if o.wait>0 then o.wait=o.wait-1 if o.wait<=0 then o.mode=(o.mode+1)%3 if o.mode==0 then o.wait=160 elseif o.mode==1 then o.wait,o.flip=90,-o.flip elseif o.mode==2 then o.wait=60 bullet_create(o.x-o.w,o.y-o.h-2,-1,-2,PHYS_GRV) bullet_create(o.x+o.w,o.y-o.h-2, 1,-2,PHYS_GRV) end end end if o.mode==0 then local ox=o.w*o.flip o.x=o.x+0.2*o.flip local y=collision_down(o.x+ox,o.y+8,MASK_FLOOR) if abs(y-(o.y+8))>=6 then o.wait,o.mode,o.flip=90,1,-o.flip end end o.y=collision_down(o.x,o.y+o.h,MASK_FLOOR)-o.h badnik_check(o) end function crabmeat_draw(o) local frm=0 if o.mode==0 then frm=(160-o.wait)//16;frm=(frm%2)+((frm%4)//3) elseif o.mode==1 then frm=0 elseif o.mode==2 then frm=3 end local sx,sy=o.x-SCR_X-4,o.y-SCR_Y-4 for y=0,2 do for x=0,2 do local i,f=x+3*y+1,(x==2 or (frm==2 and x>0)) and 1 or 0 i=S_CRABMEAT[frm+1][i]+400 spr(i,sx+(x-1)*8,sy+(y-1)*8,5,1,f) end end end --buzzbomber function buzzbomber_create(x,y) insert(g_objects,{ type='buzzbomber',x=x,y=y,w=10,h=4, wait=0,mode=0,flip=-1,ox=x,xsp=3,fire=true }) end function buzzbomber_update(o) if o.wait>0 then o.wait=o.wait-1 elseif o.mode==0 then if abs(g_player.x-o.x)<96 and o.mode==0 and o.fire then o.mode,o.wait,o.fire=1,30,false end o.x=o.x+o.xsp*o.flip if o.flip==-1 and o.xo.ox+128 then o.flip,o.wait,o.fire=-1,60,true end elseif o.mode==1 then o.mode,o.wait=2,30 elseif o.mode==2 then bullet_create(o.x+10*o.flip,o.y+14,o.flip,1) o.mode,o.wait=3,30 elseif o.mode==3 then o.mode=0 end badnik_check(o) end function buzzbomber_draw(o) local flm=(tick()%8)//4 local frm=o.mode<2 and 1 or 2 local sx,sy=o.x-SCR_X-4,o.y-SCR_Y+4 for y=0,1 do for x=0,2 do local i=(o.flip==-1 and 2-x or x)+y*3 i=S_BUZZBOMBER[frm][i+1] if i>0 then spr(i,sx+(x-1)*8,sy+(y-1)*8,5,1,o.flip==-1 and 1 or 0) end end end if tick()%4<2 then spr(468,sx,sy-16,5,1,o.flip==-1 and 1 or 0) end spr(452+flm,sx-8*o.flip,sy-8,5,1,o.flip==-1 and 1 or 0) end --bullet function bullet_create(x,y,xsp,ysp,grv) insert(g_objects,{ type='bullet',x=x,y=y,z=2,w=4,h=4, xsp=xsp,ysp=ysp,grv=grv or 0, }) end function bullet_update(o) if not on_screen(o.x,o.y,64) then o.delete=true; return end o.ysp=o.ysp+o.grv o.x,o.y=o.x+o.xsp,o.y+o.ysp if p_touch(g_player,o.x,o.y,o.w,o.h,2) then p_hit(g_player) end end function bullet_draw(o) if tick()%2==1 then return end spr(390,o.x-SCR_X-4,o.y-SCR_Y-4,5) end --animal function animal_create(x,y,flip,spec) insert(g_objects,{ type='animal',x=x,y=y,w=4,h=4,z=-2, ysp=-2,flip=flip,land=false,xsp=2,spec=spec or rand(2) }) end function animal_update(o) o.ysp,o.y=o.ysp+PHYS_GRV,o.y+o.ysp if o.land then o.x=o.x+o.xsp*o.flip end if o.land or o.ysp>0 then o.z=0 end local ny=collision_down(o.x,o.y+o.h,MASK_FLOOR)-o.h if ny<=o.y then o.y,o.ysp,o.land=ny,-2,true end if not on_screen(o.x,o.y,64) then o.delete=true end end function animal_draw(o) local x,y,h=o.x-SCR_X-4,o.y-SCR_Y-4,1 local i=o.land and (o.ysp<0 and 3 or 2) or 1 if i==1 then y,h=y-4,2 end local f=o.flip==-1 and 1 or 0 spr(S_ANIMAL[o.spec][i],x,y,5,1,f,0,1,h) end --puff smoke function puff_create(x,y) insert(g_objects,{type='puff',x=x,y=y,z=1,life=15}) end function puff_update(o) local i o.life=o.life-1 if o.life<=0 then o.delete=true end end function puff_draw(o) if o.life>10 then i=490 elseif o.life>5 then i=492 else i=494 end spr(i,o.x-SCR_X-8,o.y-SCR_Y-8,5,1,0,0,2,2) end --eggman function eggman_create(x,y) insert(g_objects,{type='eggman', x=x,y=y,z=0,w=14,h=10,mode=0, flip=-1,t_invc=0,priority=-1,move=70, ball={x=0,y=-16,w=8,h=8,p=0},life=8, wait=180,xsp=0,ysp=0 }) end function eggman_update(o) if o.t_invc>0 then o.t_invc=o.t_invc-1 end if o.mode<3 then if p_touch(g_player,o.x,o.y,o.w,o.h,9) and o.t_invc<=0 then if g_player.substate=='roll' or g_player.t_invc>0 then o.life=o.life-1 sfx(24,34,-1,3) g_player.xsp=-g_player.xsp*0.75 if not g_player.land then g_player.ysp=-g_player.ysp*0.75 end if o.life==0 then o.mode,g_score=3,g_score+1000 else o.t_invc=60 end else p_hit(g_player) end end end if o.mode==0 then o.y,o.move=o.y+0.5,o.move-0.5 if o.move==0 then o.mode=1 end elseif o.mode==1 then o.ball.y=o.ball.y+0.5 if o.ball.y==64 then o.mode=2 end elseif o.mode==2 then local spd=1 if o.life<=5 then spd=spd*1.5 end if o.life<=2 then spd=spd*1.5 end o.ball.p=o.ball.p+0.025*spd local x,y=vector(-sin(o.ball.p)*pi/2+pi/2) o.ball.x,o.ball.y=x*64,y*64 o.x=o.x+0.5*o.flip o.move=o.move+0.5*o.flip if abs(o.move)>=abs(64*o.flip) then o.flip=-o.flip end elseif o.mode==3 then if o.wait%8==0 then sfx(17,48,-1,1) puff_create(rand(o.x//1-o.w,o.x//1+o.w),rand(o.y//1-o.h,o.y//1+o.h)) end o.wait=o.wait-1 if o.wait==0 then o.mode=4 play_lvlmusic() SCR_X_MAX=1920*2 g_bossdefeated=true end elseif o.mode==4 then o.flip=1 o.xsp,o.ysp=o.xsp+0.025,o.ysp-0.01 o.x,o.y=o.x+o.xsp,o.y+o.ysp if not on_screen(o.x,o.y,128) then o.delete=true end end if o.mode>0 and o.mode<3 then if p_touch(g_player,o.x+o.ball.x,o.y+o.ball.y+16,o.ball.w,o.ball.h,2) then p_hit(g_player) end end end function eggman_draw(o) if o.t_invc%2==1 then pal(0,15) end local x,y=(o.x-SCR_X)//1,(o.y-SCR_Y)//1 y=y+sin(tick()/30*pi)*1 if o.mode>0 and o.mode<4 then if o.mode<3 or tick()%2==0 then for i=0,4 do local rx=lerp(x,x+o.ball.x,i/5) local ry=lerp(y+16,y+o.ball.y+16,i/5) spr(426,rx-4,ry-4,5) end for sy=0,2 do for sx=0,2 do local i=1+sx+sy*3 local s=S_WRECKBALL[1][i] local r=S_WRECKBALL[2][i] spr(s,x+o.ball.x-12+sx*8,y+o.ball.y+4+sy*8,0,1,0,r) end end end end xspr(427,x,y,1,1,0,o.flip,1,11,16,5) if o.t_invc>0 then xspr(394,x,y,3,2,0,o.flip,1,9,20,5) elseif g_player.substate=='hurt' then xspr(365,x,y,3,2,0,o.flip,1,9,20,5) elseif o.mode==3 then xspr(397,x,y,3,2,0,o.flip,1,9,20,5) else xspr(362,x,y,3,2,0,o.flip,1,9,20,5) end xspr(428,x,y,4,3,0,o.flip,1,16,12,5) pal(0,0) end --capsule function capsule_create(x,y) insert(g_objects,{type='capsule', x=x,y=y,z=-1,w=16,h=16, broken=false,timer=0,acount=48, button=button_create(x,y-24), }) end function capsule_update(o) if o.button and o.button.pressed then g_finished=true o.broken=true end if not o.broken then return p_collide(g_player,o) end if o.timer<120 then o.timer=o.timer+1 if o.timer%5==0 then for i=1,3 do local x=o.x+rand(-12,12) local y=o.y+rand(-12,12) puff_create(x,y) end sfx(17,48,-1,1) end if o.timer==120 then o.w,o.h=-99,-99 o.button.delete=true;o.button=nil end elseif o.acount>0 then if tick()%4==0 then local x=o.x+rand(-12,12) local y=o.y+6-rand(0,4) local f=tick()%8==0 and 1 or -1 animal_create(x,y,f) o.acount=o.acount-1 end if o.acount==0 then make_reward() end end if o.button then p_collide(g_player,o) end end function capsule_draw(o) local x,y=o.x-SCR_X,o.y-SCR_Y xspr(470,x,y,4,1,0,1,1,16,-8,5) if o.broken and o.timer>=120 then xspr(476,x,y,4,1,0,1,1,16,0,5) else xspr(406,x,y,4,4,0,1,1,16,24,5) end end --button function button_create(x,y) insert(g_objects,{type='button', x=x,y=y,w=8,h=4,oy=y }); return g_objects[#g_objects] end function button_update(o) p_collide(g_player,o) if g_player.land==o then o.pressed,o.y=true,o.oy+2 else o.pressed,o.y=nil,o.oy end end function button_draw(o) local x,y=o.x-SCR_X,o.y-SCR_Y spr(391,x-8,y-8,5,1,0,0,2,1) end --platform function platform_create(x,y) insert(g_objects,{type='platform', x=x,y=y,z=-1,w=20,h=8,bx=x,by=y, }) end function platform_update(o) local px,py,pw,ph=p_colbox(g_player) if py+ph=0 then p_collide(g_player,o,'vert') end if g_player.land==o then o.y=appr(o.y,o.by+4,1) else o.y=appr(o.y,o.by,1) end end function platform_draw(o) patr(227,119,5,3,o.x-SCR_X,o.y-SCR_Y,0,1,1,20,16) end --spikes function spikes_create(x,y) insert(g_objects,{type='spikes', x=x,y=y,z=0,w=20,h=5, }) end function spikes_update(o) p_collide(g_player,o) if p_touch(g_player,o.x,o.y-2,o.w,o.h,2) then p_hit(g_player) end end function spikes_draw(o) xspr(127,o.x-SCR_X,o.y-SCR_Y,1,2,0,1,1,20,10) xspr(127,o.x-SCR_X,o.y-SCR_Y,1,2,0,1,1,12,10) xspr(127,o.x-SCR_X,o.y-SCR_Y,1,2,0,1,1,4,10) xspr(127,o.x-SCR_X,o.y-SCR_Y,1,2,0,1,1,-4,10) xspr(127,o.x-SCR_X,o.y-SCR_Y,1,2,0,1,1,-12,10) end --sparkle function sparkle_create(x,y,t) insert(g_objects,{type='sparkle', x=x,y=y,z=4,w=20,h=5,t=t or 0,p=0, }) end function sparkle_update(o) o.p=o.p+1 if o.p>=19 then o.delete=true end end function sparkle_draw(o) local r=o.p//5 spr(116+o.t,o.x-4-SCR_X,o.y-4-SCR_Y,0,1,0,r) end --monitor function monitor_create(x,y,t) insert(g_objects,{type='monitor', x=x,y=y,z=0,w=8,h=8,t=t or 0,land=true,btime=0 }) end function monitor_update(o) if o.broken then if o.btime<30 then o.btime=o.btime+1 end if o.btime==30 then o.btime=99 if o.t==1 then g_rings=g_rings+10;sfx(20,75,-1,1) elseif o.t==2 then g_player.t_invc=15*60--1536 elseif o.t==3 then g_player.t_turbo=15*60--1536 elseif o.t==4 then g_player.shield=true;sfx(26,48,-1,1) end end return end if not o.land then o.ysp,o.y=o.ysp+PHYS_GRV,o.y+o.ysp if o.ysp>0 then local ny=collision_down(o.x,o.y+o.h,MASK_FLOOR) if ny=o.y+o.h then local cl,vx,vy=p_collide(g_player,o) if cl and vy>0 then o.ysp,o.land=-1,false end end if g_player.substate=='roll' then if p_touch(g_player,o.x,o.y,o.w+1,o.h+1,7) then o.broken=true puff_create(o.x,o.y);sfx(17,48,-1,1) p_rebound(g_player,o.x,o.y) points_create(o.x,o.y,T_MONITOR+o.t,true) end end end function monitor_draw(o) local x,y=o.x-SCR_X,o.y-SCR_Y if o.broken then spr(474,x-8,y,5,1,0,0,2,1) else local t=T_MONITOR+(tick()%8<4 and o.t or 0) spr(442,x-8,y-8,5,1,0,0,2,2) spr(t,x-4,y-5,0) end end --bridge bridge_dip={2,4,6,8,8,8,6,4,2} function bridge_create(x,y) insert(g_objects,{type='bridge', x=x,y=y,z=0,w=40,h=5,bx=x,by=y,dip=0 }) end function bridge_update(o) local px,py,pw,ph=p_colbox(g_player) if py=0 then p_collide(g_player,o,'vert') end if g_player.land==o then local x_diff=g_player.x-o.x local index=floor(((x_diff+o.w)/(o.w*2))*8+0.5) o.dip=appr(o.dip,bridge_dip[index+1] or 0,1) else o.dip=appr(o.dip,0,1) end o.y=o.by+o.dip end function bridge_draw(o) for i=-4,4 do local ox,oy=o.x-SCR_X,o.by-SCR_Y local dip=min(bridge_dip[i+5],o.dip) xspr(160,ox+10*i,oy+dip,2,2,0,1,1,8,8,0) end end --waterfall function waterfall_create(x,y,h,t) insert(g_objects,{ type='waterfall',x=x,y=y,z=10,h=h,t=t }) end function waterfall_draw(o) if tick()%2==1 then return end local x,y=o.x*8-SCR_X,o.y*8-SCR_Y local t,f,r=anim_tile(o.t,0,0) for i=0,2 do rect(x,y+i,8,1,12-i) end for yy=o.y,o.y+o.h-1 do spr(t,x,yy*8-SCR_Y,0,1,f,r) end end --trigger areas function trigger_create(x,y,w,h,callback) insert(g_objects,{ type='trigger',x=x,y=y, w=w,h=h,callback=callback, }) end function trigger_update(o) if p_touch(g_player,o.x,o.y,o.w,o.h) then o:callback() end end --points sprites function points_create(x,y,v,t) insert(g_objects,{type='points',x=x,y=y,z=3,ysp=-1.5,v=v,t=t}) end function points_update(o) o.ysp,o.y=min(0,o.ysp+PHYS_GRV/2),o.y+o.ysp if o.ysp>=0 then o.delete=true end end function points_draw(o) local x,y=o.x-SCR_X,o.y-SCR_Y if o.t then spr(o.v,x-4,y-4) rectb(x-5,y-5,10,10,9) rectb(x-6,y-6,12,12,0) else local ox=print(o.v,0,-999,0,true,1,true)/2 printb(o.v,x-ox,y,9,0,true,1,true,1) end end --initialization function init_title() gamestate=TITLESCREEN tt_fadeout=0 play_titlemusic() end function init_game() gamestate=GAMEPLAY g_level=1 init_level() end function init_vars() g_timer=0 g_rings=0 g_score=0 g_finished=nil g_bossdefeated=nil g_lvlrings=0 g_mulscore=1 g_lvlcard=120 g_fadeout=0 g_objects={} rw_rings=nil rw_perfect=nil rw_time=nil rw_event=nil rw_hiscore=nil end function init_level() init_vars() TILEMAP={} SCR_X,SCR_Y=0,0 SCR_X_MIN,SCR_Y_MIN=0,0 SCR_X_MAX,SCR_Y_MAX=1920*2,408 TILEMAP_WID,TILEMAP_HEI=480,51 for y=0,50 do for x=0,239 do TILEMAP[1+x+y*480]=mget(x,y) TILEMAP[1+x+240+y*480]=mget(x,y+51) end end trigger_create(1765,110,16,32,function(o) if g_player.x>o.x then SCR_Y_MAX=280 else SCR_Y_MAX=408 end end) trigger_create(2232,108,16,32,function(o) if g_player.x>o.x then SCR_Y_MAX=408 else SCR_Y_MAX=280 end end) trigger_create(3200,204,32,204,function(o) if g_player.x>o.x then SCR_X_MAX=(1920*2)-240 end end) trigger_create(3490,204,32,204,function(o) if g_player.x>o.x then o.delete=true SCR_X_MIN=(1920*2)-480 eggman_create(SCR_X_MAX-120,SCR_Y_MAX-180) play_bossmusic() end end) SCR_Y=360 g_player=p_create(52,360,1) capsule_create(1920*2-120,376) init_objects() play_lvlmusic() end function init_objects() for x=0,TILEMAP_WID-1 do for y=0,TILEMAP_HEI-1 do local t=tmget(x,y) if t==T_RING then g_lvlrings=g_lvlrings+1 elseif t==T_MOTOBUG then tmset(x,y,0) local f=rand()<0.5 and -1 or 1 motobug_create(x*8+4,y*8+4,f) elseif t==T_CHOPPER then tmset(x,y,0) chopper_create(x*8+4,y*8+4) elseif t==T_CRABMEAT then tmset(x,y,0) crabmeat_create(x*8+4,y*8+4) elseif t==T_BUZZBOMBER then tmset(x,y,0) buzzbomber_create(x*8+4,y*8+4) elseif t==T_BRIDGE then tmset(x,y,0) bridge_create(x*8+4,y*8+4) elseif t==T_PLATFORM then tmset(x,y,0) platform_create(x*8+4,y*8+4) elseif t==T_WATERFALL then tmset(x,y,0) local h=TILEMAP_HEI-y waterfall_create(x,y,h,t) elseif t==T_SPIKES then tmset(x,y,0) spikes_create(x*8+4,y*8+2) elseif t>=T_MONITOR then tmset(x,y,0) monitor_create(x*8+4,y*8+8,t-T_MONITOR) end end end end --title screen state function TITLESCREEN() if btnp(4) and tt_fadeout==0 then tt_fadeout=90 end cls(10);draw_island();draw_emblem() draw_hiscore();draw_besttime() if tt_fadeout>0 then tt_fadeout=fadeout(tt_fadeout,true) if tt_fadeout==0 then DEBUG=btn(0);init_game() end end end function draw_hiscore() local s=textsize('HIGH SCORE:',true,1,true) printb('HIGH SCORE:',120-s,122,9,1,true,1,true,1) printb(hiscore,124,122,15,13,true,1,true,1) end function draw_besttime() local w=textsize('BEST TIME:',true,1,true) local m,s,c=stamp(besttime) local v=("%d'%02d\"%02d"):format(m,s,c) printb('BEST TIME:',120-w,128,9,1,true,1,true,1) printb(v,124,128,15,13,true,1,true,1) end function draw_island() local r,t=(tick()*pi)/1024,0.25 local p=-r*256 local x1,y1=tilt(-60,-60,r,t) local x2,y2=tilt(60,-60,r,t) local x3,y3=tilt(60,60,r,t) local x4,y4=tilt(-60,60,r,t) texquad( 1680,952,136,136, 120+x1,102+y1,120+x2,102+y2, 120+x3,102+y3,120+x4,102+y4, 1,11 ) map(60+(p//16)%30,119,31,2,-((p/2)%8),0) map(60+(p//8)%30,121,31,6,-(p%8),16) end function draw_emblem() vbank(1);cls(14) poke(0x3FF8,14) local x,y=120,60 circ(x,y,43,0) circ(x,y,40,1);circb(x,y,40,8) circ(x,y,36,9);circb(x,y,36,15) circ(x,y,26,1);circb(x,y,26,8) circ(x,y,22,0);circb(x,y,22,8) for i=0,7 do local sx,sy,r=31,0,i*((pi*2)/8) local c,s=cos(r),sin(r) sx,sy=sx*c-sy*s,sx*s+sy*c circ(sx+x,sy+y,2,13) circ(sx+x,sy+y,1,15) end rect(x-64,y-12,128,24,3) rect(x-64,y-5,128,10,15) tri(x-64,y-12,x-48,y,x-64,y+12,14) tri(x+64,y-12,x+48,y,x+64,y+12,14) local xx=textsize('SONIC MINI',nil,1) printb('SONIC MINI',x-xx/2+1,y-4,9,14,nil,1,nil,1) local bl=tt_fadeout==0 and 16 or 4 if tick()%(bl*2)60 or g_lock);update_music() if g_lvlcard<=60 then update_objects() end p_update_view(g_player) map_draw();draw_objects();hud_draw();sp_draw() if DEBUG then draw_debug_info() end card_draw(unpack(LVL_CARDS[g_level])) if rw_event then crtresume(rw_event) end if g_lvlcard<=0 and g_fadeout<=0 and not g_finished then g_timer=g_timer+1 if g_timer>=36000 then g_timer=35999 end end if g_fadeout>0 then g_fadeout=fadeout(g_fadeout) if g_fadeout==0 then init_level(g_level) end end end function update_objects() sort(g_objects,priority_sort) for i=#g_objects,1,-1 do local o=g_objects[i] if o.delete then remove(g_objects,i) else local f=_G[o.type..'_update'] if f then f(o) end end end end function draw_objects() sort(g_objects,draw_sort) for i=#g_objects,1,-1 do local o=g_objects[i] local f=_G[o.type..'_draw'] if f then f(o) end end end function map_draw() local x,y=SCR_X,SCR_Y map(((x/2)//8)%30,119,31,2,-((x/2)%8),0,0,1,anim_tile) map(((x/4)//8)%30,121,31,4,-((x/4)%8),16,0,1,anim_tile) map(((x/8)//8)%30,125,31,8,-((x/8)%8),48,0,1,anim_tile) map(((x/4)//8)%30,133,31,1,-((x/4)%8),112,0,1,anim_tile) map(((x/3)//8)%30,134,31,1,-((x/3)%8),120,0,1,anim_tile) map(((x/2)//8)%30,135,31,1,-((x/2)%8),128,0,1,anim_tile) tmap(x//8,y//8,31,18,-(x%8),-(y%8),0,1,anim_tile) end function hud_draw() local f=_G['hud'..hudstyle] if f then f() end end function hud0() local x,st,alt=0,'',true local m,s,c=stamp(g_timer) x=printb('SCORE ',8,4,9,1,true,1,alt,1) printb(('%6d'):format(g_score),8+x,4,15,13,true,1,alt,1) st=("%d'%02d\"%02d"):format(m,s,c) x=printb('TIME ',8,12,9,1,true,1,alt,1) printb(st,8+x,12,15,13,true,1,alt,1) local clr=tick()%24<=12 and 3 or 9 clr=g_rings>0 and 9 or clr st=('%3d'):format(g_rings) x=printb('RINGS ',8,20,clr,1,true,1,alt,1) printb(st,8+x,20,15,13,true,1,alt,1) end function hud1() local m,s=stamp(g_timer);s=('%d:%02d'):format(m,s) spr(195,4,4,0);printb(g_score,16,4,15,13,true,1,nil,1) spr(196,4,14,0);printb(s,16,14,15,13,true,1,nil,1) spr(208,4,24,0);printb(g_rings,16,24,15,13,true,1,nil,1) end function sp_draw() if g_player.t_invc>0 then if g_player.t_invc>300 or tick()%2==0 then rectb(3,123,10,10,2) spr(T_MONITOR+2,4,124) end end if g_player.t_turbo>0 then if g_player.t_turbo>300 or tick()%2==0 then rectb(15,123,10,10,2) spr(T_MONITOR+3,16,124) end end end function stamp(t) return t//60//60,(t//60)%60,ceil(((t/60)%1)*100) end function card_draw(title,zone,act) if g_lvlcard<=0 then return end local t=(g_lvlcard-60)/60 vbank(1) cls(t>0 and 0 or 9) if t>0 then local r1=min(1,1-(t-0.7)*4) circ(120,68,160*r1,11) local r2=min(1,1-(t-0.6)*4) circ(120,68,160*r2,3) local r3=min(1,1-(t-0.5)*4) circ(120,68,160*r3,6) local r4=min(1,1-(t-0.4)*4) circ(120,68,160*r4,9) end local xt=abs(t)>0.5 and (-(abs(t)-0.5)*2) or 0 printb('SONIC MINI',168,4+xt*24,9,11,nil,1,nil,1) if t<=0 then circ(120,68,160*(-t-0.25)*4,14) end local x=xt*240 rectskew(x-12,0,48,136,0.5,0,3) rectskew(-x,76,228,24,0.5,0,15) rectskew(x+16,88,24,48,0.5,0,11) rectskew(x+40,32,24,80,0.5,0,6) rectskew(88-xt*240,92,56,16,0.5,0,3) local at=act and ('Act '..act) or 'Ready' printb(at,100-xt*240,96,15,11,true,1,nil,2) local tx=printb(title,102-xt*240,80,15,11,true,1,nil,2) if zone then printb('ZONE',102-xt*240+tx-24,80+8,15,11,true,1,nil,2) end g_lvlcard=g_lvlcard-1 poke(0x3FF8,g_lvlcard>0 and 14 or 0) if g_lvlcard<=0 then cls() end vbank(0) end function make_reward() rw_rings=g_rings*100 rw_perfect=g_lvlrings==0 and 50000 or nil local sec=g_timer//60 if sec<30 then rw_time=50000 elseif sec<45 then rw_time=10000 elseif sec<60 then rw_time=5000 elseif sec<90 then rw_time=4000 elseif sec<120 then rw_time=3000 elseif sec<180 then rw_time=2000 elseif sec<240 then rw_time=1000 elseif sec<300 then rw_time=500 else rw_time=0 end rw_event=crtcreate(function() local t1,t2='SONIC GOT THROUGH',LVL_CARDS[g_level][1]..' ZONE' local t3,t4='TIME BONUS','RING BONUS' local t5,t6='PERFECT BONUS','TOTAL SCORE' local w1,w2=textsize(t1),textsize(t2) local w3,w4=textsize(t3),textsize(t4) local w5,w6=textsize(t5),textsize(t6) local x,y,str,wait,fade,high=360,68,'',240,60 play_clearmusic() while true do if x>120 then x=max(x-8,120) elseif wait>0 then wait=wait-1 elseif rw_time>0 then rw_time=rw_time-100 g_score=g_score+100 sfx(27,64,-1,0);wait=1 if rw_time<=0 then wait=30 end elseif rw_rings>0 then rw_rings=rw_rings-100 g_score=g_score+100 sfx(27,64,-1,0);wait=1 if rw_rings<=0 then wait=30 end elseif (rw_perfect or 0)>0 then rw_perfect=rw_perfect-100 g_score=g_score+100 sfx(27,64,-1,0);wait=1 if rw_perfect<=0 then wait=30 end elseif not high then high,wait=true,60 if g_score>hiscore then rw_hiscore,hiscore=true,g_score pmem(HI_SCORE,hiscore) end if g_timer=0 then fadeout(max(fade,0)) end crtyield() end end) end --gameend function GAMEEND() sync(1<<4);cls(10);draw_island() local t='THANK YOU FOR PLAYING' local w,c=textsize(t),15 printb(t,120-w/2,64-24,9,1,nil,1,nil,1) local rc=({3,6,9,11})[1+(tick()%16)//4] t='NEW HIGH SCORE';w=textsize(t);c=rc if not rw_hiscore then t='SCORE';w=textsize(t);c=13 end printb(t,120-w/2,64,15,c,nil,1,nil,1) printb(g_score,120-textsize(g_score)/2,76,15,c,nil,1,nil,1) t='NEW BEST TIME';w=textsize(t);c=rc if not rw_besttime then t='TIME';w=textsize(t);c=13 end local min,sec,cen=stamp(g_timer) local v=("%d'%02d\"%02d"):format(min,sec,cen) printb(t,120-w/2,96,15,c,nil,1,nil,1) printb(v,120-textsize(v)/2,108,15,c,nil,1,nil,1) end --main function _BOOT() menu_call=nil hudstyle=pmem(HUD_STYLE) hiscore=max(pmem(HI_SCORE),5000) besttime=pmem(BEST_TIME) if besttime==0 then besttime=35999 end g_reset,g_lock,g_hiscore,g_besttime=nil fontset(224,8,8) COL_LIST={} init_title() end function TIC() poke(0x3FFB,0) if menu_call then menu_call();menu_call=nil end for i=1,0,-1 do vbank(i);poke(0x3FF8,0);cls() end gamestate() step() if g_reset then _BOOT() end end function MENU(i) if i==0 then menu_call=menu_toggle_hud elseif i==2 then menu_call=menu_clear_data elseif i==3 then DEBUG=not DEBUG end end function menu_toggle_hud() pmem(HUD_STYLE,(pmem(HUD_STYLE)+1)%2) hudstyle=pmem(HUD_STYLE) end function menu_clear_data() pmem(HI_SCORE,0) pmem(BEST_TIME,0) hiscore=max(pmem(HI_SCORE),5000) besttime=pmem(BEST_TIME) if besttime==0 then besttime=35999 end end --debug stuff function draw_debug_info() vbank(1) local p=g_player local _,_,hw,hh=p_hitbox(p); local _,_,cw,ch=p_colbox(p); if type(p.land)=='table' then local lx,lw=p.land.x-SCR_X,cw+p.land.w local ly=p.land.y-p.land.h-ch-SCR_Y line(lx-lw,ly,lx+lw,ly,7) end hitbox(p.x,p.y,hw,hh,3);hitbox(p.x,p.y,cw,ch,13) local s='gsp:%0.2f xsp:%0.2f ysp:%0.2f ang:%0.2f mode:%d' s=s:format(p.gsp,p.xsp,p.ysp,p.g_ang,p.mode) printb(s,1,128,15,13,false,1,true) s=('%4d'):format(p.x//1) printb(s,200,4,15,13,true,1) s=('%4d'):format(p.y//1) printb(s,200,12,15,13,true,1) printb(fps(),224,128,15,13,true,1,false) printb(#g_objects,216,120,15,13,true,1,false) for _,r in ipairs(COL_LIST) do if #r<4 then pix(r[1]-SCR_X,r[2]-SCR_Y,r[3]) else hitbox(unpack(r)) end end COL_LIST={} vbank(0) end _BOOT()