0]$]±>Pï‘Wÿÿm®æPa¾<P4L]ÉY™öæêò¶ººDD`( 8 0ÿÿÿÿÿÿÿÿ2Tv˜ºÜþïÍ«‰gE#2Tv˜ºÜþ2Tv˜ºÜþÙDDDD4DDDDDDDDDDCDDDDDCDDDDDDDDDDDDDDDtGdDvwtDwgtDwwwFgwDtwwDDwvDDTGDDtGDDtWDDtwDDuGDDwGDDtGDDtGDdtwDDgwGtwswtvwvtwvwDwwGDtwdDDDDDDDDDDDDDDDDDD´DDD«KDD´DDDtDDDDDdtwDDgrFt'#wtvrvdwvwDwwGDtgdDDDDDDDDTDDDDGDDDGGDDGGDDDDDDDDDDDDDDDDDDDDDDÞÝDäÝÝMÄÜÜLDÏìDDDDDDDDDDDDDDDDDDDíDDDÜLDDÄMDDDDDDDDDDDDDDDÔDKDD´ÛDDD´MDDDÛDÔD´KDD´DDDDDDDDDDÌÌDÄÌÌLÄÀÀLÄìÌLDÌÌDDííDDDDD@DD@DD@DDDD@D@@@DDDDD@DDDDDDDDDDDDDDDDDD@DD@DDDDD@@DD@DDDDD@DDDDDD@@D@DDDD@DDD@DDDD@@DDfffffffffffgfffffffffgffffffffffff6fffefgFefvveVVvegVveefffffffffffffmffÖÒfmfmÖÒfgfmfgfgfffffffffffffffffgfffWfffWfefWvfffvffffffgffveffgeffgFffgfvfffVgffVvffcvffffffffffffff¶fff«kff¶fffvffffff–fffIiff†fffvfffvfffvffffffffff&bffÂ"ff""ffÆmffÆlfffffffffffffffffffÆmffÞlffÍfffffffffffffffffff"Âf&Â"bÂ"","â."&ÎìbfÆlffÆlffÆlffffffffffÜÝfæÝÝmÆÜÜlfÌìfffffffffDDDDDdFDDffDdffFdffFDffDDdFDDDDDDDDDfDdddfffffdfffffffffffffffffDDDDDDDDDDdfDDffDdffDdffDfffDfffDDDDDDDDDDDDDDDDDDDDDffDdffFffffddfFdffFDffdFffDDFfDdffFDffddffFwwwwgwwwwwwwwwwwwwwwwwwwwwwwwgwwwwwwwwwwWwwwwuwuWvguWuWvWuWwWvwwwwwwwWwwWwuwwvugwuvvwuuuwuvuwwwwwwwwgwwwwvwwwVwgwVwvwwWvwwWvwwwwwbww'#wwwbtwwGEwwgtwwewwwgwwwwwwwwwwwvwwgbwwwvwwwwwwwwgwww6vwwgwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww~wpç÷ww÷ww÷÷wwwwwwwwwwwwwwÞÝwçÝÝ}ÇÜÜ|wÏìwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwÝÜ}×ÜÝÌÝÝÌÜÜÍÜìïÌîþ÷ÿÿwwwwfffffvgffwwfvwwgvwwgfwwffvgfffffffffwfvvvwwwwwvwwwwwwwwwwwwwwwwwfffffffgffvwffwvfvwwfgwwfwwwvwwwfffffffffffffffffffffwwfvwwgwwwwvwggvwwggwwffwwvfwvfvwwggwwfvwwgÇ~ìwÜ}Þ|í|ÇwwwwçÜ×~Þçìç~ÎÍwww~,wwrCò3w3D'|$wwwwGsGò?27ò×ò÷wÇ~üw¸}ß{è~‡wwwwÞ¼÷Ïè‡ü÷ÿËwwçwpïþðwwpwwwwðàà~÷pwwWvöwoue_öWwwww÷u÷uVvWöoe÷V÷wðwqqwwwwðpññpwwÆnìfÜmÞlílÆoffffæÜÖnÞoæìænÎÍfffn,ffbCò3f3oDo&l$offffFcFò?26òÖòöfÆnüf¸mßkèn†offffÞ¼öoÏè†üöoÿËffæof`ïþðff`ffffðàànö`ffVföfetoOöFoffffödödFWFöEöGöofooðfaaoffffð`ññ`ffoÄNìDÜMÞLíLÄODDDDäÜÔNÞOäìäNÎÍDDDN$!Ãò13!!ò1212ÑòñCÄNüD¸MßKèN„ODDDDÞ¼ôOÏè„üôOÿËDDäOD@ïþðDD@DDDDðààNô@DDTFöDEuOoöTODDDDôEôEVWTögôWôODOOðDAAODDDDð@ññ@DDOwwwpUFfGfdegVVFfvwwvpwwGVVwVpfuGgV`ewfpegWeuuvpwGGveuVVffvewwgvpwwqqUQeWuqUuuuqegWwvwwVeeeUWWWuqeguWv{Veµºuqv{ggQVwfuvggvvvggggqvuueQVVuuefvvvvggQeQWevvVweqwvvaWVvWeeQWvvwqgwuWVVfuuuÀ" ,"- "" Ò""""Ü"Ì"""Ò,"""""-"""",Ì"Ò" pefeGfuwgvwWwgvvpfwww7sf2##2330303 3vvgWvwfgpwVpgw`pUQweuuuggkgq·³uw{VÌ`ÁP±uuvuVVWgeegv·WWw¶ueeuVggÆveuWVVveµuuWgkwu{www·|»±²vawwwvuu1sugggQvqeewwwwea7rV1cgV#vuccg5Wu6VVuusugggvw{ga¶¾eqwkg#u#QfeuuWÒ""""40ðBC4$äìÎNÜÎññÜÍÜÍÀ À Ð """C""0"033332##2033033pÁÀ¼Á±±»Ë¼À°¼ ÀÁ± ¼±ÀÀ  Ì ÌvvvVgg6vwwaqwqg±VQ6eb7v#q3v#q5b13#33#1#ageaW'WWqsvfQvg1f1#13À Ð À À À À À À 03 30"030323#"33Á »ÌÀ± ˱°Á À ›±1#11#313#131#1#1#3##Ì ÜÌÜÜÌÞ ÀÍî ÀÜìÍÌÜÌÎÌ ®    »ûÐûûÐûÐûûлð» ¿¿ ¿ ¿¿ ¿ð»» Û °€ " # ' ( ( * ) ' % ) $ ) * # ! ' ! ) # % $ ' ( # ( * & # ( ! " ) % ) " ) & * " & ' * #" ) " * ( ( * " ' $ ! * ' % % & * $ " ) ( ( # * & $ $ * $ $ % ! % * ! " ) % ( ) $ ' % ( # ! " % * # $ ( # ) ( " ) * # " ( # ) ( * # * ( # # * ) & ! " $ " ' * " $ % # " # ' % % " # # & # ' % % $ * ' ( ( $ " % * ' & ' ) # * # * $ & * # ( ! $ & & $ & ! ( * % % $) " " ( ) ! ( ' * ( & $ " ! # ) # # $ " ' * " * * ##) # % % $ # & % ' )( ) ( # * ' ' * ) * " ) ! ' ) ! ! # & " ' # # ! ' * ( ) & ' #( ! * % ! ! ( % ! ') ' ( * ' ) % ! # % ( $ * ' ( $ & # ) & # & " % " # " " ( % " !& & ) * % # $ ) " ' $ ( " % % # ) ! % ) $ ( # ( * ! ( ) & ' # ( * '$ ( $ #&& * " ! (& ' ! & ) ' * % & % ( % $ # ) $ " $ " ' & # & " !% ' ) # % $ * ( * $$ # & " (& & * % ( $ ( ' $ # $ ( ' " " # ! " % # $% ! * % & ) ! % ' * " * "& $ * ' ) # ! ! ' " ) " * & ) # $ % ! ' # ! * & ! ! ' ' ! % ( ' !' " ) $& ' % ! ! ) # ( ' $ * * ( " ! ! " % $ )' ' $ * ( ! % ' * ) ! $ * $ $ ' ( ( ( ' ! # " ) $ ) " & $ # % ' % & # $& ) $ ! $ * # ( " ! ' & ! & " ) " " ( * ( ' % ' ( ' ( # # # " * * " * $ " # & * $ " ' ' " $ ( & ) # * ( ( & ( * # " & * ( " " ( ! ) ! ) ( # & # %' ' # $ * " ) " # ( ' " $ $ % ' & ) ' & ! ! ' & ! $ $ & % ) & & # ( # ! ( $ * * ) ) ' # ' ! ) " % ( " $ " " ' " ) # % * * ' ' & ( " ' ' ' $ $ ( ' ! " # " * % * ) ! # ( ! ( " $ ! ) " & % $ " ' % # & # ! $ & & % % "" ( # ' * # " ! " ) ' " # ' ' * "! & ' & ) % & ' ) #' * # & # * ( * " ' & ) * ) $ # " ' * % ' ) $ * % # * ( % ! & * $ # * " & $ ' " $ " ! ' ' % ) " & & # *% ' ' " # ( ! ! # ) ! ' ( " ( ! ) & ' * " # * % $ * % " % % # * ' & & * * ' & % * # ' % '* & * " ! $ ) $ # # $ & ! ' & ) " ' % & & * $ & $ $ % % ' $ ( * & ' $ ! $' & ( % % # % & & & $ $ !( ' # $ # # * * $ %& ' * ' # % * ! # & * " * ' & # ) % # % $ ) * ' ! ( % ' % % ' % # !" *! " " $ ' & #) " ( & ) ' ( ' * " & # " ' ! $ ( & ' % ! ' * ! " % ) ( ! % $ * # ' ( ) " ! ) # # ) & ) $ " # * ! * # $ $ ! ) " * ) * ) ! & ( ' % ' # # & ( " ( & (( ) $( ' $ $ ) $ * * # ( % ( & ( ) ' ' ' ( ' % * & ! ( $( ) * ( ' & $ * ! " ! % # * ' " ) ) ) ! ' % ) ) ) " ( & ' ) ! ( $ ) ! (! ) # ' * * ! ( # ' " & % $ # " % "* # ' ( & " ' " ( # * # * & % ) $ % "# ( & % " $ * & ) # ( # " ) ) ! ! ( * %$ ) ' $ * " * $ * & # # & % $ " #) " ! * * ! " # " ' ! % ( * ( # # ' % " ) ( ! # # ( " ( % ( # ( $ % ( ' ' & ( " # ! ( ' ) $ % * * & * # # ( $ " ! ' * ) " ( * " ( & $ ! ' $ # * % ( ! & & ! ) ) ( # % " )% & ( ) ) & * %$ ( $ ) ' " " # ) ( ) " " & " " ) * ( # $ $ % #* !% % * $ ( ( * ! ' ! * % ( $ % #) $ % % * ! ( ! " * ( ( % " ! # & % ' " % ! ! ) $ & # ' ! & * & & * % # % $ ) "$ ) ' * # % $ ' * ' & ! ) ' $ $ ) ! ' ! $ " " ( % ( '( # " & &) " # ! $$ ) *) ! * ' # # " ) ) ' ! & "% % " # ) & " % $ ) ( % ' ! % ) ! #" " % ' ( & % ( * ( & % % ' & ) ! & & & ! ! * # ! ) ( )" ' ( * ( % ' ( # * & " ! * " & ( " % $ # # & & $ & ' $ $ * " ) # * ' " " )* & !* ! " $ * ( ' # ! * ' % ! * # " * " ' $ ) & " ! # ! ! ( ! & & % ' >À?wwwvvffffuuuuvv{ggggffffffffff¶lffÆ`»\WWWgg·wvvvfVWWWgg·wvvvffffffvfffffffffffvfffffffffffvfffvfVWWWVVwwwWWwwwwwwwwwwWWwwwwwffffvegWggVVgvvgffffffffffÆÀff»` WvvuvfeufgwfWvvuvfeufgwfffffffffffffffffffffffffffffffffffffvggggwwweeevwwwwwwwfeeuwwwgffffUVweuuvuveuffffffffffff¼ffË`[euWVWgWgWVgVeuWVWgWgWVgfffffffffffffcffffffffffffffffffffffggwvvveeWWWWwwwwwwwwWWWWwwwfffffuuufVVWgWVVvfffffffffgfÆkf¼`\WWgfeuuveeeWWWgfeuuveeegfÖffffffffffVfffffffffffffffffgwfvvgwwwwwWvvwvvvwwvwwwvvvvwwwvfffvfggkggeegeµuuffvffgfffff¶fÀ`{v¶vvVVvVV[Wwv¶vvVVvVV[W×f-mfffgffvffVdwfgfffffgfgffffvwvwwwwvwww#gucw·wvwwwwwwwv·wgwwgfffffv·³uvf·WWgkwfffffffffff¶°f¼lÌw;[ggv{uu¶vgw;[ggv{uu¶v'mÖfffffffffeVggffffffffffffffwvwwvwwgWWw7v6vfë[vwwwvwwwVëkvgwfffffffw{VWw¶uu{wgffffffffffff fÀÆkv·guug[W·wwfv·guug[W·wwÖfvfffffffffvVgefffffffffffffvwwwwwwww#gg5b7ww·fwwwwwwwwg¶wwwgffvfffffÌ`eeuffwwfvfffffffffvf¶l ¼fgÀ VVVgfvwgfgÆ VVVgfvwgvgvffgffvfffVWgefffffgfffffffgwwwwwwww7WW7V7v6RwwwwwwwwwwW2vvfffffffffÆPfVgg·|kfffffffvfffff¶ÀÀkfff efuvvË·ffff efuvvË·fffffffffffffffffffvfffffffvffwwwwwwwgwvvvVsUW7rwwwwwwwwwww2Wffffffffff¶lffÆ`»¶²fffffffffffffÆ »ffffËffc ¶k+kfffËfff ¶k+kffffffffffffffffffffffffffffvwwwwwwwwewwwgceueVvwwwwwwwwwVfuffffffffffÆÀff»` fkffffffffffffffÌÀffff lf¶ Æ`¶ffff lf¶ Æ`¶fffffffffffffffffffffffffffffwppwwWVvwWW7WWWwuwwwwwwwwwuWWfffffffffff¼ffË` ffffffffgfffmfff¶ ffgfÆkf¶ ¶`fffffÆkf¶ ¶`fffffffffffffffffffffffffffffgïþïpggggeueSfvVvvwwwwwwwvVvvfgfffffgffvÆkf¼`ÌgfffffgffffÖÒfmfËgffff¼fÆ Ælvffgff¼fÆ Ælfffffgffvfffvffffgfgfffffgffvwðwðppv~f#vwcwuruuwwwwwwwuurufffffffffff¶fÀ` ffffffffffffmÖÒf¶°fffff ` ¶`ffffff ` ¶`ffffffffffffffffffffffffffffwvwpww~÷owwg6r7cw7ggvwwwwwwwfg7wfffffffffff¶°f¼lÌffffffffffffgfmfÆ fffff kÆËÆlffffff kÆËÆlfffffffffffffffffffffffffffvwwwwðwwwwwvww7rW#vewwvwwgwwwgvwgefffffgffvfff gÀÆkffffgffffvffgfgfÀfffvf¶`l¼fffffff¶`l¼fvffgffvfffvffffgfffffffgfffgwwàpwðwpw#7#w#gfwwwwwwwwgf'sffvfffffffff¶l ¼ffvffffffffffffff ffffff˶Àkfffffvff˶Àkfffffffffffffffffffffvffffffwwwà~ç÷ïpþpw72sw3rwgwwwgwwwgw2sffffffffffff¶ÀÀkfffffffffffffffffffffffff ¼fffffffff ¼ffffffffffffffffffffffffffffvwww÷pwwwðpww73rw#wwwwwwwwwwww'svgwwgfffffffÆ »ffffffffffffffffffffffffff¼°kfffffffff¼°kf–ffffffffffffffffffffffffffpwwwwwpp{www3r7#wwwwwwwwwwww&3gUVVvgfffffffÌÀffgfffffffgfffgfffgfffffffÆ lfffffgfffÆ lfIiffffffffffffffffffffffffgïpçpðïþï°¹pgw3r3rwwgwwwwwwwwww2Uuuuevfffffgf¶ gfffffffgfffffffffffffgffffË`fgffffffffË`f†fgfgfffgffffvffgfffffgffvwðpðpðwðp ww32#wwwwwwwwwwwwww'VgWvVggfff¶ffËfffffffffffffffffffffffffff°lffffffffff°lfvffffffffffffffffffffffffwv~÷wwpwpww~÷ww33rwwwwwwwwwwwwwwwWwe·wvvfff«kf¶°fffffffffffffffffffffffffff kffffffffff kfvfffffffffffffffffffffffvwwwwwwwwwwwðwwwwww3#wwwgwwwwwwwgwwwwfUV«kgggfg¶ffÇ fffvffgffffvfffvfffvffffffg¼`ffffffvffg¼`fwffffffffffvffffffffgfffgwwpwðwpàpwww3rwwwwwwwwwwwwwwwwWgg·wvvvffvffÀfffffffffffffffffffffffvffflffvffffffflffffffvfffvfffffffvffffffwwwç÷ïpþpà~ç÷ww3rgwwwwwwwgwwwwwwvuvfeufgwfffff fffffffffffffffffffffffffff°`ffffffffff°`ffffffffffffffffffffffffvwwwwðpw÷pwwwðwg3rwwwwwgwwwwwwwwwwVWgWgWVgffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffvfffffvwwwww÷pwpwwwww03"wwwwwwwwwwvwwwwwfeuuveeegffffgfffffffffffffffffffgfffffffffffffffgfffffffgffffffffffffffffVgfffffwwwçpðàð~ïpçpðïþwwwWWwwwwwwwgwwwvVVvVV[WgffgfffffffgfgfffgfffgffffffffvffgffffvfffffffvffffffffgfffgfffgffVwfffgvwwwðpwpðpðpðwwwgeeuwwwwwwwwwwggv{uu¶vgfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdvfffffgwwwwpwwww~÷wwpwpwwvwWWWWwwwwwwwwwwuug[W·wwfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffgfvfffffwwwwwwàçpwwwwwwwwwðwwvvvvvgeuuuwwwwVVVgfvwgfgffffvffgffffffffffffffffvfvfffffffvfffffvfvfffffvffgfffgfffgffvefffgfffwwwðwpðpwðwpàwgwwwwwVvVVVwwwwefuvvË·fffffffffffffffvfffvfffvfffffffffffvfffffffffffffffffffffffffffffgeffffffvwwwïpþppþç÷ïpþpà~wwuuwwweeuuuuwwwfff ¶k+kffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg6ffffffvvwwpwwwpwðpw÷pwwgVVVwwwvvvvgvgwwlf¶ Æ`¶fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffifffffww÷pw÷pw÷pwww÷pwwuuuuVVgggwvvwvwkf¶ ¶`fffffffffffffffffffffffffffffffffffffffffffffffffffffffgfffgfffffff–”ffffgçpðàð~àð~àð~çpðàð~gggwgguw×Ç×wvwww¼fÆ ÆlfffgfffÝÍgfffgfffgffvffffgfffgfgfffgfffffgfffgfgfffffgfffffffffgffffhgffvwðpwpwpwpðpwpgw{w6Wv2wwwgwwww ` ¶`ffffffÖÝÝnffffffffffffffffffffffffffffffffffffffffffffffffffffffffffgfffwvwwpwwwwwwwwwwwwwwpwwwwgµ¾fwcgs}uuÖwwww kÆËÆlffffffÆÍÍlffffffffffffffffffffffffffffffffffffffffffffffffffffffffffgffvwwwwwàçpàçpàçpwwwàçpwf{wws&SÆÍ2Íwwww¶`l¼fvffffffÎÌffgfffgffvffffgfffgfffffffffffgfffgfffffffgffffvfffvffffffggffgwwðwpððððwpðww%cgsesuuÃþwwwwf˶Àkfffffvfffffffffffffffffffffffffffvfffvfffffffffffvfffffffffffffffvffffffwwwïpþppþpþpþïpþppþww'suU7egggwwwwvf ¼ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffvwwwpwwwpwwpwwppwuupwgeVWV6vwwwVwwwwf¼°kffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffvwwwwpwwpwwwp÷pWVVvwuuwuuusuuwgeuwwwfÆ lfffffgfffffffgfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwwwïþçpðïpïþàðueuuWVVVVV5VWVvvvvwwvffË`fgffffffffvffffffffgfgfffffgfÜÝgfgfffgfffffgfgfffffgffvffgfffffgfgfffgffvwwwðwðpðpPWWVvggggguUuuUu5wg2fwgwwwwff°lffffffffffffffffffffffffffffæÝÝmfffffffffffffffffffffffffffffffffffffffffgwwwpwwwwp~÷weeegUWWVvggggggggsVVWWwvwwwff kffffffffffffffffffffffffffffÆÜÜlfffffffffffffffffffffffffffffffffffffffffwwwwwðwwwwwwwWWWPVeeegewwwvwwwweeceeewwwwfg¼`ffffffvfvfffffvffgfffffffgfffÌìffffffffffgfffffffgffvffffffffgfffffffffffwwwàðwppw`vggWWW_VVewwWWww7SVVWWWwwwwfflffvfffffffffffffffffffvfffffffffffvfffvfffffffvfffffffffffvfffffffvfffvfvwwwà~ïpþpç÷`gwvfvegggwwfeeuvwggggwWWwwwff°`ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffvvww÷pwwpwwðgwwwggwvvveeWWWWgeuvvvgeeuwwffffffffffffffffffffffffffffffffffvfffffffffffffffffwwgwffffffffffffffffffffvwwwwp÷pwwpvwwgwwuswWvvvvvvVwwwwWWWWwwffffffffffffffffffffffffffffffffffVgfffffffffffffffwVVVegffffffffffffffffffffwwwïþàð~ïþï`WWçvwww#gUv·wg3e'swwvvvvvgfgffffvffffgffvffgffffvfffffffffffVwfgfffgfffffgffvfuuuUUgfgffvfffvffffgffvfvwwwðwwpðwðp#`eWWw7v6VëkV6v6wWgwwwwwVffffffffffffffffffffffffffffffffffdvffffffffffffffgWvVgWVefffffffffffffffffffgwwwpwwwwwwwpww~7WW7#>f5b7g¶wg7g2ev'uuwwwefffffffffffffffffffffffffFfffFfffgfvfffffffffffffvvv·guWWufffffffffffffffffffwwwwwðàçpwwðwwvvvV3WW7V7vV2v6R6WgVVVwwwvffffvffffgffvfffffffvffffffFfffFvefffffffffffgffvggg«[VefUgfvfffvffffgffvffffwwwàðàewwwpvvvVsUW72WWuSvvuuuuVVgffvfffffffffffffffvfffffFFDfFFDfgeffffvfffvfffffvvvv·gwWWWWfffffffffffffffffvwwwà~pþà~WVvwWe7wwgceuVfueecwgggwgguwffffffffffffffffffffffffDDDDDDDDg6ffffffffffffffvggveevvuvVgffffffffffffffffvvww÷pwwwwp÷pwwggggUVvwWW7WwuWWW7WWgw{w6Wv2fffffffffffffffffffffffDDDDDDDDDDffffffffffffffffWVgWgWWVweUff6fffffffffffffvwwwpwwpwwpwwwvfcgggeueSvVvvVc5eeµ¾fwcgsfgfffffffgfffffffffffffDDDDDD4DDDffffffffffffgffgeeuvueefWWWffeffffffffffffffwwwïpïpïp`wwgwvwf#6wcuurugsw&cf{wws&SfffffffgfffffffgffffffFDDD4DDDDDDffffgfffffgffffWW[VvVVvv¶vvgFegfffgfgfffffgvwwwðpðpðpvwwgwwg6b7cfg7gg3w2gw%cgsesffffffffffffffffffffffFDDDDDDDDDDdffffffffffffffw¶vuu{fgW;{gvveVfffffffffffffgww~÷~÷~÷wwwww&w'7"W#vugu&Sw2vw'suU7efffffffffffffffffFffffDD4DDDDDDDDDffffffffffffffvw·WWkwue·wfVvegfffffffffffffwwwwwwwwwwwwwwwàçpw77cw#2#gf'c'3'swgeVWV6fffvffgffffvffgfffffFfFDDDDDDDD4DDDDffffffgffffvffwwffWVVÌffVweefgfffffffgfffwwwpwpwpwðpww3rw32sw32sw32wwWwuuusuffffffffffffffffFFDfDDDDDDDC4DDDDDDDffvffffffffff¶Ç{vveflvfffffffffffvfffffvwwwç÷ç÷ç÷p þgw6r733rw#'sw23wggegg5VWffffffffffffffffDDDDDDDDDDDDDDDDDDDDfffffffffffff+k»lffÆkffffffffffffffffffvvwwwðwðwðw·¹pww;r3b3r7#'3w2swWW'Ww6wgfffffffffffffffDDDDDDDDDDDDDDDDDDDDDDffffffffffff¶fÀ»ff lffffffffffffffffffvwwwpww÷pwwpw pw·¹2#w3r3rw2s2swgvvsw6s'fffffffffffffffDDDDDDDDC4DDDDDDD4DDDDffffffffffffff°¼ffËffffgfffffffffffffffwwwïpàð~ïþïþgw;3bw32#ww'32swgwwVg2u'fffgfffgfgffffFDDD4DDCDDDDDDDD4DDDDDDfffffvffgffffvÌËf¶lffgfffffffgfffgfgffvwwwðpwpðwðwww3#ww33rwww23swwfv2w2s2ffffffffffffffFDDDDDDDDDDDDCDDDDDDDCDdfffffffffffff° fkffffffffffffffffffffgww~÷wwwwwpwwwpwwww3rww3#wwww'3swvw'3w7#sffffffffffffffDD4DDDDDDDDDDD4DDDDDDDDDfffffffffffffÌÆËf kffffffffffffffffffffwwwwwwwàçpwwðwwðww3rww3rwwwww2swwww2w'3sfgfffgfffffffFDDDDDDDDDDDCDDDDDDDCDDDDDfvfffffffvff¶l v°fgffffvffgfffgfffffffwwwpwðààww3rww3rwwwww2swwww2s'3wffffffffffvfDDDDDDDCDDCDDDDDDDDCDDDDDDDDffffffvfffff˰Ækffffffffffffffffffvfvwwwç÷pþà~à~w73"ww3rwwwww2swwww'3'3wffffffffffffDDDDDDDDDDDDDDDDDDDDDDDDDDDDffffffffffff¶ kffffffffffffffffffffvvwwwðwwp÷pww÷pwwwgwww73"wgww'23wwwww2#3wfffffffffffDDDDDDDDDDDDDDDDDDDDDDDDDDDDDdffffffffffff»°lffffffffffffffffffffvwwwwwwwwwwwwwwwwwwwvwwwwwwwwwwwww'33wffÖffffffffDDDDDD4DD4DDDDDDCDDDCDDDCDDDCDffffffffffff Ìffgfffffffffffffffffffwwwçpðçpðçpðgwwwwwwwwwwwwwwwwwwwgwwwg23wÖf-mffvfffFDDD4DDDDDDDDDDCDDDCDDDCDDDCDDdffffffgfgfffÀkgfffffgfffgfffffgffvfvwwwðpðpðpwwwwwwwwwwwwwwwwwwwwwwwww'3w-mÖfffffffFDDDDDDDDDDDDCDDDDDDDDDDDDDDDDDFfffffffffff¼`ffffffffffffffffffffffgwwwwpwwpwwpwwwwwwwwwwwwwwwwwwwwwwwww'3wÖfvfffffffDD4DDDDDDDDDDDDDDDDDDDDDDDDDDDDffffffffffff kffffffffffffffffffffffwwwwwwwwwwwwwwwwwwwgwwwwwwwgwwwgwwwww'3wvgvfvffffFDDDDDDDD4DDCDDDDDDDDDDDDDDDDDDDffffgfffffff°lfffvffffffffffgffvffffwwwðwpðwpðwpwwwwwwwwwwwwwwwwwwwwwwwww"3sffffffffDDDDDDDC4DDDDDDDDDCDDDCDDDCDDDCDdfffffffffvff `fffffffvfffvfffffffffvwwwïpþpïpþpïpþpwwwwgwwwwwwvgwwwgwwwwwwwwwwwffffffffDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDddfffffffffff°`fffffffffffffffffffffvvwwpwpwpwwgwwwwwwwwwwwwwwwwwWWgwwwgwwfffffffDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDdffffffff–ffffffffffffffffffffffffff÷pwpww÷pwwwwwwwwwwwwwwwvwwwwwwwgeeuwwwwvwfffffffDD4DDD4DDDDDD4DDDDDDDD4DD4DDDDDDDDfffwvwwfIiffffffffffffffgfffffffffgàð~ïpàð~wwwwwwwwwwwvwwwwwwwvwwWWWWwwwwwwfffgffFDDDDDDDDDDD4DDDDDDD4DDDDDDDDDDD4DdffvVeeew†fgffvfffvfffvffffffffgffvwwpðpwpwwwwwwwwwwwwwwwwwwwwwwvvvvvgeuuuffffffFDDDDDDDDDDDDDDDDCDDDDDDDDDDDCDDDDDFvUUWWWfwffffffffffffffffffffffffwvwwww~÷wwwwwwwwwwwwvwwwwwwwvwwwvgwwwwwVvVVVffffffDDDDDDDDDD4DDDDDDD4DDDDDDDDDDD4DDDDfVeuveguvfffffffffffffffffffffffvwwàçpwwwwàçpwwwgwwwgwwwwwwwwwwwwwwuuwwweeuuufgfffFDDDD4DDD4DDDDDDCDDDDDDDD4DDCDDDDDDDfWuuWv{gggfvfffvfffvfffffvffgfffgwwðpwðwwwwwwwwwwwwwwwwwwwwgVVVwwwvvvvgffffDDDD4DDD4DDDDDDCDDDDDDDC4DDDDDDDDDDCdvUfVeµºvvvffffffffffffffffffffffwwwpþç÷pþgwwwgwwwwwwwwwwvwwwwwuuuuVVgggwvffffDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDduuuuvv{ggggffffffffffffffffffffvwwwwwpwðwwpwwwwwwwwwwwwwwwwwwwwgggwgguwwwwwfffDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDtegWggVVgvvgffffffffffffffffffffvwww÷pwwwwwwwwwwwwwwwwwwwwwwwwwwwwwgw{w6Wv2wwwgfffD4DDD4DDDDDDC4DDDDDDCDDDCD4DDDDDCDDDDUVweuuvuveuffgfffffffffffffffffffwwwàð~wwwwwwwvgwwwgwwwgwwwwwwvgwwwgµ¾fwcgswuuvffFDDDDDDDDDDCDDDDDDDCDDDCDDDDDDDCDDDD4DuuufVVWgWVVvffffffvfffvffÜÝgfgffvwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwf{wws&SÖÜ2ÌffFDDDDCDDDCDDDDDDDCDDDDDDDDDDDDDDDDDDDDggkggeegeµuuffffffffffffæÝÝmfffffgwwwwwwwwwwvwwwwwwwwwwwwwwwvwwwwwwwww%cgsesuuÃÜffDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD4DDDt·³uvf·WWgkwffffffffffffÆÜÜlfffffwwwàçpwwwgwwwwwwwwwwwwwwwwwwwwwwwwww'suU7egggçfFDDDCDDDCDDDDDDDCDDDDDDDDDDDD4DDDDDDDDDDw{VWw¶uu{wgffvfvfffvffffÌìffffffwwwðwwwwwwwwwwwwwwwwwwwwwwwwwwwwwgeVWV6vçw~VDDDDDDDDDDDDDDCDDDDDDDCDDDCD4DDDDDCDDDDCdfÌ`eeuffwwfffffffffffffffffffvfvwwwpþgwwwwwwwwwwwwwwwwwwwwwwwwwwwwWwuuusuuwgeDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDddÆPfVgg·|kfffffffffffffffffffffvvwwwwpwwwwwwwwwgwwwgwwwgwwwwwwwgwwggegg5VWVvvvDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDff¶lffÆ`»¶²ffffffffffffffcffffffvwwwwwwwwwwwwwvwwwwwwwvwwwwwwwwwwwwwWW'Ww6wg2fwg4DDD4DDDDDDD4DDDD4DDDDDCDDDC4DDDDDDDDDDDffÆÀff»` fkffffffffffgfffVfffgfffwwwgwwwwwwwwwwwwwwvwwwwwwwwgwwwwwwwgvvsw6s'svwwDDDDDDDDDD4DDDDDDDDDDCDDDCDDDDDDDD4DDDdffff¼fgË` ffgfgfffgfffffffWdvffffvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwgwwVg2u'swwgDDDCDDDCDDDDDDDCDDDDDDDDDDDDDDDCDDDDDDfffffÆkf¼`ÌfffffffffffffffeVggfffffgwwwwwwwwwwwwwwvwwwwwwwwwwwwwwwwwwwwfv2w2s2vwwwDDDDDDDD4DDDDDDDDDDDDDDDDDDDDDDD4DDDDdfffff¶fÀ` fffffffffffffffvVgefffffwwwwwwwwwwgwwwwwwwwwwwwwwwgwwwwwwwgww'3w7#cwwwwDCDDDCDDDDDDDCDDDD4DDDDDDDDDDCDDDDDDDdfffgf¶°f¼lÌgffffffffffffvfVVgeffvffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww2w'3swwgwDDDDDDDDDDDCDDDD4DDDDDCDDDCDDDDDDDDCDfffffff fÀÆkfffffvfffvfffffffvfffffvwwwwwwwgwwwwwwvwwwwwwwvgwwwwwwwgwwwwww2c'3www·wDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDfffffff¶l ¼ffffffffffffffffffffffffvvwwwgwwwwwwwwwwwwwwwwwwwwwwwgwwwwwwwgw'3'3www›{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDdfffffff¶ÀÀkffffffffffffffffffffffffwwwwwwvwwwvwwwwwwwwwwwvwwwvwwwvwwwwwwwww2#3www·wDDDDD4DDDDDC4DDDDDDDD4DDDDDDDDDC4DDDDffffgffÆ »ffffffgfffffffffffffffffgwwwwwwwwwwwwgwwwwwwwwwwwwwwwwwwwgwwwwwwv'33wwwwwDD4DDDDDDCDDDDDDDD4DDDDDDD4DDCDDDDDDdffffffffÌÀgfgfffffffgffffvfffvfffvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww23wwwwwDDDDDDDDDDDDDDDCDDDDDDDDDDDDDDDDDDDCDFfffffff¶ fffffffffffffffffffffffwvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwvwwww'3wwwww4DDDDDDDDDDDDDDD4DDDDDDD4DDDDDDDDDDDDffffffffËffffffffffffffffffffffvwwwwwgwwwwwwwwwwwwwwwgwwwwwwwwwwwwwwwwwwwww'3wwwwgDDDDDD4DDDDDDCDDDDDDDD4DDDDDDDDDDCDDDfffffvff·°fffffffvfffffvfffvffffgwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww'3wwwwwDDDC4DDDDDCDDDDDDDDC4DDDDDDCDDCDDDDDdffffffffÆ fffvfffffffvffffffffffwwwgwwwwwwvwwwvwwwwgwwwwwwvwwwvwwwvwwwwwwwww"3sgwwwDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDddfffffffÀfffffffffffffffffffffvwwwwwwwwwwwwwwwwgwwwwwwwwwwwwwwwwwwwgwwwwwwwgwwwwwWDtEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDfffffffff fffffffffffffffffffffvwwwwbwwwwvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwfe4tGDD4DD4DDDDDDDDDDCDDDCDDDCD4DDDDDDfgfffffffffffffffffffgfffffffgfffwww'#wwwwwwwwwwwwwwwwwvgwwwgwwwwwwwwwwwgwwwuuwwwwWWDuGDDDDDDDDDDD4DDCDDDCDDDCDDDDDDDDdffffffffgfffgfffgfgfffffffffgffffvwwwwbtwwwwwwwwwwwwwwwwwwww~wwwwwwwwwwwwwwwWVVvwwwvvDwGCDDDDDDDCDDDDDDDDDDDDDDDDDDDDDDfffffffffffffffffffffffffffffffffffgwwwGEwwwwwwwwwwwwwvwwwwpwwwwwwwwwwwwwwwuuuuwwgwwDtWDDDDDDDDD4DDDDDDDDDDDDDDDDDDDDdfffffffffffffffffffffffffffffffffffwwwwgtwwwwwwwwgwwwgwwwwç÷wwwwwwwwgwWWWVvggggggwwuuDswDDD4DDCDDDDDDDDDDDDDDDDDDDD4DDdffffvffgfffgfffgffffffffvffgffffvffwwwwewwwwwwwwwwwwwwwwwww÷wwwwwwwwwweeegewwwwwvgVVVDtGD4DDDDDDDDDDCDDCDDDCDDDCD4DDDDfffffffffffffffffffffvfffffffffffffvwwwwgwwwwwvgwwwgwwwwwwww÷÷wwwwwgwwwWWWWVVwwwWWwwuuuDtGDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDffffffffffffffffffffffffffffffWWfffvvwwwgwwwwwwwwwwwwwwwwwwwgwwwgwwwwwwgvggggwwweeefggwDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDfffffffffffffffff–fffffffffffffeeeffwwwwwwwwwwvwwwwwuuwwwwwwwwwwwwwwwwwwggwvvveeWWWWgw{wDDDCDDDDD4DDDDDDDDDDD4DD4DDDDDDDfffffffffffffffffIiffffffgffffWWVWfgwwwwwwwvwwwwgwwWVVvvwwwvwwwwwwwwwwwvgwwwwwWvvwvvfµ¾fDCDDDD4DDDDDDD4DDD4DDDDDDÝíDDDdfffvffffgfffgfffgf†fgfffgffffffvvvvvgeuuuwwwwwwwwwwwuuuuwwwwwwwwwwwwwwwwwwvwww#gucw·wvf{wDDDDDDDDDDDDDDDDDDDDDDDDÔÝÝNDDfffffffffffffffffffvffffffffffffwvgwwVvVVVvwwwwWWWVvgggggwvwwwwwwwwwwwvwwwwgWWw7v6wfë[vw%cDDDD4DDDDDDD4DDD4DDDDDDDÄÍÍLDdfffffffffffffffffffvfffffffffffguuwwweeuuuuwwwweeegewwwwwvwwwwwwwgwwwgwwwwww#wg5b7ww·fww'sDDDDDDDDDD4DDDDDDDDDDD4DDÎüDDdffvffffgfffgfffgfffwfffgffffvffVVVggwvvvvgvwwwWWWWVVwwwWWwwwwwwwwwwwwwwwwwww7WW7V7v6RwwgeVDDCDDDDC4DDDDDDCDDDC4DDDDDDDDfffffffffffffffffffffffffffffffveuuuVVgggwvvwwwgvggggwwweeevwwwgwwwgwwwwwwwwwvvvVsUW7rvwWwuDDDDDDDDDDDDDDDDDDDDDDDDDDDDDffffffffffffffffffffffffffffffffggggguwwwwwvwwwggwvvveeWWWWwwwwwwwwwwwwwwwwwewwwgceueVvggegDDDDDDDDDDDDDDDDDDDDDDDDDDDDfffffffffffffffffffffffffffffffffw{w6Wv2wwwgwwwwgwwwwwWvvwvvvwwwwwvwwwvwwwwwWVvwWW7WWWwuWW'W4DDDDDDCDDDCDDDDDDDCDDDCDDDDfgfffffffffffgfffffffgfffffffffffµ¾fwcgswuuvwwwvgvwww#gucw·wvwwwwwwwwwwwgwwwggggeueSvvVvfvvsDDDDDCDDDCDDDD4DDCDDDCDDDDdffffffgfffgfffffffgffffffffvffgffff{wws&Svw2wwwwwwgWWw7v6wfë[vwwwwwwwwwwwwwwwwvwf#vwcwuruewwVDDDCDDDDDDDDDDDDDDDDDDDDDDffffffffffffffffffffffffffffffffffff%cgsesuuswvwwwww#wg5b7ww·fwwwwwwwwwwwwwwwwgwwg7r7cw7ggvfv2DDDDDDDDDDDD4DDDDDDDDDDDDdfffffffffffffffffffffffffffffffffffv'suU7egggwwwwwww7WW7V7v6Rwwwwgwwwwwwwwwwwwwvww7rW#vewwvw'3DCDDDDDDDDDDDDDDDDDDDDDDDdffffvfffffffffffvfffffffvfvffffffffgeVWV6vwwwVwwwwwvvvvVsUW7rwwwwwwwwwwwwwwwwwwwwww#7#w#gfwww2Òq-- title: TileMan -- author: ArchaicVirus -- desc: Generates infinite procedural terrain with Auto-Map -- site: https://github.com/archaicvirus -- license: MIT License -- version: 3.0 -- script: lua --load in generation settings defs ores = { [1] = { name = 'Iron', offset = 15000, id = 3, scale = 0.011, min = 15, max = 16, bmin = 45, bmax = 100, color_keys = 4, tile_id = 162, sprite_id = 178, biome_id = 2, map_cols = {8,11,12,13,14,15}, }, [2] = { name = 'Copper', offset = 10000, id = 4, scale = 0.013, min = 15, max = 16, bmin = 33, bmax = 40, color_keys = 1, tile_id = 161, sprite_id = 177, biome_id = 2, map_cols = {2,3,4,15}, }, [3] = { name = 'Coal', offset = 50000, id = 6, scale = 0.020, min = 14, max = 17, bmin = 35, bmax = 75, color_keys = 4, tile_id = 163, sprite_id = 179, biome_id = 3, map_cols = {0,14,15}, }, [4] = { name = 'Stone', offset = 22500, id = 5, scale = 0.018, min = 15, max = 16, bmin = 20, bmax = 70, color_keys = 4, tile_id = 160, sprite_id = 176, biome_id = 1, map_cols = {12,13,14,15}, }, [5] = { name = 'Oil Shale', offset = 37994, id = 8, scale = 0.019, min = 15, max = 16, bmin = 22, bmax = 29, color_keys = 4, tile_id = 165, sprite_id = 181, map_cols = {0,1,15}, }, [6] = { name = 'Uranium', offset = 76500, id = 7, scale = 0.022, min = 15, max = 16, bmin = 65, bmax = 70, color_keys = 4, tile_id = 164, sprite_id = 180, map_cols = {5,6,7,15}, }, } biomes = { [1] = { name = 'Desert', tile_id_offset = 0, min = 20, max = 30, t_min = 21, t_max = 25, tree_id = 193, tree_density = 0.05, color_key = 0, map_col = 4, clutter = 0.05 }, [2] = { name = 'Prarie', tile_id_offset = 16, min = 30, max = 45, t_min = 33, t_max = 40, tree_id = 196, tree_density = 0.05, color_key = 1, map_col = 6, clutter = 0.09 }, [3] = { name = 'Forest', tile_id_offset = 32, min = 45, max = 101, t_min = 47, t_max = 99, tree_id = 199, tree_density = 0.05, color_key = 1, map_col = 7, clutter = 0.05 }, } TileManager = {} TileManager.__index = TileManager auto_map = { --N E S W --tiles surrounding land --0 is land, 1 is water or other biome ['1000'] = {sprite_id = 1, rot = 0}, ['0100'] = {sprite_id = 1, rot = 1}, ['0010'] = {sprite_id = 1, rot = 2}, ['0001'] = {sprite_id = 1, rot = 3}, ['1100'] = {sprite_id = 2, rot = 1}, ['0110'] = {sprite_id = 2, rot = 2}, ['0011'] = {sprite_id = 2, rot = 3}, ['1001'] = {sprite_id = 2, rot = 0}, ['1101'] = {sprite_id = 3, rot = 0}, ['1110'] = {sprite_id = 3, rot = 1}, ['0111'] = {sprite_id = 3, rot = 2}, ['1011'] = {sprite_id = 3, rot = 3}, ['0101'] = {sprite_id = 4, rot = 0}, ['1010'] = {sprite_id = 4, rot = 1}, ['1111'] = {sprite_id = 0, rot = 0}, } function ore_sample(x, y, tile) local biome = tile.biome --if for i = 1, #ores do local scale = ores[i].scale -- ((4 - biome)/100) local noise = (simplex.Noise2D(x * scale + ((ores[i].offset * biome) * scale) + offset * scale, (y * scale) + ((ores[i].offset * biome) * scale) + (offset * scale)) / 2 + 0.5) * 16 --if noise >= ores[i].min and noise <= ores[i].max and ores[i].biome_id == biome then return i end if noise >= ores[i].min and noise <= ores[i].max and tile.noise >= ores[i].bmin and tile.noise <= ores[i].bmax then return i end end return false end function AutoMap(x, y) local tile = TileMan.tiles[y][x] TileMan.tiles[y][x].visited = true --Here, 'adj' is the north, east, south, and west 'neighboring' tiles (in local space) local adj = { [1] = {x = 0, y = -1}, [2] = {x = 1, y = 0}, [3] = {x = 0, y = 1}, [4] = {x = -1, y = 0}, } local key = '' for i = 1, 4 do --Grab the neighbor tile local near = TileMan.tiles[y + adj[i].y][x + adj[i].x] --Determine if neighbor is a '0' or '1', meaning 0 is land, 1 is water or a different biome if not near.is_land or near.biome < tile.biome then key = key .. '1' TileMan.tiles[y][x].border_col = biomes[near.biome].map_col else key = key .. '0' end end --Try to index the key we just created local new_tile = auto_map[key] --If key exists, then valid config detected, so set tile to the returned value, otherwise return if not new_tile then return end TileMan.tiles[y][x].sprite_id = new_tile.sprite_id + 11 + biomes[tile.biome].tile_id_offset TileMan.tiles[y][x].is_border = true --TileMan.tiles[y][x].is_tree = false TileMan.tiles[y][x].ore = false TileMan.tiles[y][x].flip = 0 --TileMan.tiles[y][x].is_tree = false TileMan.tiles[y][x].rot = new_tile.rot end function TileManager.new() --Creates a TileManager instance - cache's all the generated terrain in memory --Here, using __index metemethod, we can automatically trigger the create_tile --method whenever a non-existent value is indexed local self = setmetatable({}, TileManager) local tile_mt = { __index = function(row, x) --Here's where the magic happens, in create_tile local tile = TileManager.create_tile(x, row.y) row[x] = tile return tile end } local tiles_mt = { __index = function(tiles, y) local row = setmetatable({y = y}, tile_mt) tiles[y] = row return row end } self.tiles = setmetatable({}, tiles_mt) return self end function TileManager.create_tile(x, y) --Replace with your own function, this gets called once whenever a 'new' tile is indexed local scale = 0.0005 local scale2 = 0.025 --Here we sample 2 noise values and blend them together local base_noise = (simplex.Noise2D(x * scale + offset * scale, (y * scale) + (offset * scale)) / 2 + 0.5) * 100 local addl_noise = (simplex.Noise2D(x * scale2 + offset * scale2, (y * scale2) + (offset * scale2))) * 100 --Now base_noise is used to determine biome and land/water --base_noise = ((base_noise * 3) + addl_noise) / 4 base_noise = lerp(base_noise, addl_noise, 0.05) local tile = { noise = base_noise, is_land = base_noise >= 20 and true or false, biome = 1, --biome = base_noise < 30 and 1 or base_noise < 45 and 2 or 3, is_border = false, is_tree = false, visited = false, b_visited = false, rot = 0, offset = {x = math.random(1, 2), y = math.random(1, 4)}, } for i = 1, #biomes do if base_noise > biomes[i].min and base_noise < biomes[i].max then tile.biome = i break end end tile.flip = math.random() > 0.5 and 1 or 0 --If base_noise value is high enough, then try to generate an ore type tile.ore = tile.is_land and base_noise > 21 and ore_sample(x, y, tile) or false if not tile.is_land then --Water tile tile.color = floor(math.random(2)) + 8 tile.sprite_id = WATER_SPRITE tile.rot = floor(math.random(0,3)) else tile.sprite_id = biomes[tile.biome].tile_id_offset tile.color = biomes[tile.biome].map_col end --If ore-generation was successful, then set sprite_id and color if tile.ore then tile.color = ores[tile.ore].map_cols[floor(math.random(#ores[tile.ore].map_cols))] tile.rot = math.random(4) % 4 end if tile.is_land and not tile.ore then --Generate clutter based on biome clutter scale, ex grass, rocks, trees, etc scale = 0.001 local tree = base_noise --local tree = (simplex.Noise2D((x * scale) + (offset * scale), (y * scale) + (offset * scale)) / 2 + 0.5) * 100 local tmin = biomes[tile.biome].t_min local tmax = biomes[tile.biome].t_max --local flip = math.random(0, 1) --trace('Tspawn try: ' .. biomes[tile.biome].name .. ', tmin: ' .. tmin .. ", tmax" .. tmax .. ', tnoise: ' .. tree .. ', tflip = ' .. flip) if tree >= biomes[tile.biome].t_min and tree <= biomes[tile.biome].t_max and math.random(0, 100) < (biomes[tile.biome].tree_density * 100) then --trace('trying to spawn a tree') tile.is_tree = true --tile.flip = flip elseif math.random(100) <= (biomes[tile.biome].clutter * 100) then local rand = floor(math.random(10)) tile.sprite_id = biomes[tile.biome].tile_id_offset + rand --tile.flip = math.random(1) > 0.5 and 1 or 0 if rand == 1 then tile.rot = math.random(4) % 4 end else tile.rot = math.random(4) % 4 end end return tile end function TileManager:set_tile(x, y, tile_id) local tile = self.tiles[y][x] tile_id = tile_id or biomes[tile.biome].tile_id_offset if tile.is_land and not tile.ore and not tile.is_border then self.tiles[y][x].sprite_id = tile_id self.tiles[y][x].is_tree = false end if tile.ore then self.tiles[y][x].ore = false self.tiles[y][x].is_tree = false self.tiles[y][x].sprite_id = biomes[tile.biome].tile_id_offset end end function TileManager:draw_terrain(player, screenWidth, screenHeight) local cameraTopLeftX = player.x - 116 local cameraTopLeftY = player.y - 64 local subTileX = cameraTopLeftX % 8 local subTileY = cameraTopLeftY % 8 local startX = floor(cameraTopLeftX / 8) local startY = floor(cameraTopLeftY / 8) for screenY = 1, screenHeight do for screenX = 1, screenWidth do local worldX = startX + screenX local worldY = startY + screenY local tile = self.tiles[worldY][worldX] local sx = (screenX - 1) * 8 - subTileX local sy = (screenY - 1) * 8 - subTileY --Here, AutoMap is called once per tile during draw --AutoMap is what sets the 'border' or edge tiles if not tile.visited and tile.is_land then AutoMap(worldX, worldY) end if tile.ore then rect(sx, sy, 8, 8, biomes[tile.biome].map_col) sspr(ores[tile.ore].tile_id, sx, sy, ores[tile.ore].color_keys, 1, 0, tile.rot) elseif not tile.is_border then local id, rot, flip = tile.sprite_id, tile.rot, tile.flip if not tile.is_land then --for water tiles only if worldX % 2 == 1 and worldY % 2 == 1 then flip = 3 -- Both horizontal and vertical flip elseif worldX % 2 == 1 then flip = 1 -- Horizontal flip elseif worldY % 2 == 1 then flip = 2 -- Vertical flip end --procedural water sprite id = 224 sspr(224, sx, sy, 0, 1, flip, rot) else --else is land rect(sx, sy, 8, 8, biomes[tile.biome].map_col) sspr(biomes[tile.biome].tile_id_offset, sx, sy, biomes[tile.biome].map_col, 1, 0, tile.rot) if id ~= biomes[tile.biome].tile_id_offset then sspr(id, sx, sy, biomes[tile.biome].map_col, 1, flip) end end else if tile.biome == 1 then local flip = 0 if worldX % 2 == 1 and worldY % 2 == 1 then flip = 3 -- Both horizontal and vertical flip elseif worldX % 2 == 1 then flip = 1 -- Horizontal flip elseif worldY % 2 == 1 then flip = 2 -- Vertical flip end sspr(224, sx, sy, -1, 1, flip) sspr(tile.sprite_id, sx, sy, 0, 1, 0, tile.rot) else sspr(tile.sprite_id, sx, sy, -1, 1, 0, tile.rot) end --if tile.ore then sspr(ores[tile.ore].tile_id, sx, sy, ores[tile.ore].color_keys, 1, tile.flip, tile.rot) end end --rectb(sx, sy, 8, 8, 4) --sspr(340, sx, sy, -1) end end end function TileManager:draw_clutter(player, screenWidth, screenHeight) local cameraTopLeftX = player.x - 116 local cameraTopLeftY = player.y - 64 local subTileX = cameraTopLeftX % 8 local subTileY = cameraTopLeftY % 8 local startX = floor(cameraTopLeftX / 8) local startY = floor(cameraTopLeftY / 8) for screenY = 1, screenHeight do for screenX = 1, screenWidth do local worldX = startX + screenX local worldY = startY + screenY local tile = self.tiles[worldY][worldX] local sx = (screenX - 1) * 8 - subTileX local sy = (screenY - 1) * 8 - subTileY --Here, the 19, 25, and 41 are just randomly chosen biome tiles --picked to spawn trees on, but you can use any tiles to limit trees to certain biomes if tile.is_tree then --trace('drawing tree') sspr(biomes[tile.biome].tree_id, sx - 9 + tile.offset.x, sy - 27 + tile.offset.y, biomes[tile.biome].color_key, 1, tile.flip, 0, 3, 4) --rectb(sx, sy, 8,8,2) end -- if tile.sprite_id == 19 then -- sspr(201, sx - 9 + tile.offset.x, sy - 28 + tile.offset.y, 0, 1, tile.flip, 0, 3, 4) -- elseif tile.sprite_id == 25 then -- sspr(198, sx - 6 + tile.offset.x, sy - 28 + tile.offset.y, 0, 1, tile.flip, 0, 3, 4) -- elseif tile.sprite_id == 41 then -- sspr(201, sx - 8 + tile.offset.x, sy - 28 + tile.offset.y, 0, 1, tile.flip, 0, 3, 4) -- end end end end function TileManager:draw_worldmap(player, x, y, width, height, center) --Simple pixel map, using the tile's assigned biome in - biome[i].map_col width, height = width or 240, height or 136 x, y = x or 120 - (width/2), y or 68 - (height/2) if center then x = (240/2) - (width/2) y = (136/2) - (height/2) end local map_x, map_y = x or 120 - (width/2) + 1, y or 68 - (height/2) + 2 local startX, startY = floor(player.x/8 - (width/2) + 1), floor(player.y/8 - (height/2) + 2) local biome_col = biomes[self.tiles[startY][startX].biome].map_col local skipped = 0 rectb(map_x - 1, map_y - 1, width + 2, height + 2, 9) rect(map_x, map_y, width, height, biome_col) --rect(map_x, map_y, width, height, biome_col) local biome = self.tiles[startY][startX].biome start_col = biomes[biome].map_col for y = 0, height - 1 do if y == 0 then end for x = 0, width - 1 do local tile = self.tiles[startY + y - 1][startX + x - 1] if tile.color ~= start_col or tile.ore or tile.is_tree or not tile.is_land or not tile.biome == biome then --*** For optional fog of war effect *** --if rawget(self.tiles, startY + y - 1) and rawget(self.tiles[startY + y - 1], startX + x - 1) then --local tile = self.tiles[startY + y - 1][startX + x - 1] --if self.tiles[startY + y - 1][startX + x - 1].ore then pix(x + map_x, y + map_y, tile.is_tree and 6 or tile.color) --end --else --skipped = skipped + 1 end end end --trace('skipped drawing ' .. skipped .. ' pixels') --trace('start color: ' .. biome_col) end function TileManager:save_worldmap(player, width, height) --Simple pixel map, using the tile's assigned biome in - biome[i].map_col width, height = width or 240, height or 136 x, y = 0, 0 local map_x, map_y = x or 120 - (width/2) + 1, y or 68 - (height/2) + 2 local startX, startY = floor(player.x/8 - (width/2) + 1), floor(player.y/8 - (height/2) + 2) local biome_col = biomes[self.tiles[startY][startX].biome].map_col local skipped = 0 rectb(map_x - 1, map_y - 1, width + 2, height + 2, 9) rect(map_x, map_y, width, height, biome_col) --rect(map_x, map_y, width, height, biome_col) for y = 0, height - 1 do if y == 0 then local biome = self.tiles[startY + y - 1][startX + x - 1].biome start_col = biomes[biome].map_col end for x = 0, width - 1 do local tile = self.tiles[startY + y - 1][startX + x - 1] pix(x + map_x, y + map_y, tile.is_tree and 6 or tile.color) end end end ----------------------------------------------- ---Simplex Noise -- Original Java Source: http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf -- (most) Original comments included ----------------------------------------------- local math = math local table = table local tonumber = tonumber local ipairs = ipairs local error = error --local bit = require("bit") simplex = {} simplex.DIR_X = 0 simplex.DIR_Y = 1 simplex.DIR_Z = 2 simplex.DIR_W = 3 simplex.internalCache = false local Gradients3D = {{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0}, {1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1}, {0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}}; local Gradients4D = {{0,1,1,1}, {0,1,1,-1}, {0,1,-1,1}, {0,1,-1,-1}, {0,-1,1,1}, {0,-1,1,-1}, {0,-1,-1,1}, {0,-1,-1,-1}, {1,0,1,1}, {1,0,1,-1}, {1,0,-1,1}, {1,0,-1,-1}, {-1,0,1,1}, {-1,0,1,-1}, {-1,0,-1,1}, {-1,0,-1,-1}, {1,1,0,1}, {1,1,0,-1}, {1,-1,0,1}, {1,-1,0,-1}, {-1,1,0,1}, {-1,1,0,-1}, {-1,-1,0,1}, {-1,-1,0,-1}, {1,1,1,0}, {1,1,-1,0}, {1,-1,1,0}, {1,-1,-1,0}, {-1,1,1,0}, {-1,1,-1,0}, {-1,-1,1,0}, {-1,-1,-1,0}}; local p = {151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}; -- To remove the need for index wrapping, double the permutation table length for i=1,#p do p[i-1] = p[i] p[i] = nil end for i=1,#Gradients3D do Gradients3D[i-1] = Gradients3D[i] Gradients3D[i] = nil end for i=1,#Gradients4D do Gradients4D[i-1] = Gradients4D[i] Gradients4D[i] = nil end local perm = {} for i=0,255 do perm[i] = p[i] perm[i+256] = p[i] end -- A lookup table to traverse the sim around a given point in 4D. -- Details can be found where this table is used, in the 4D noise method. local sim = { {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; local function Dot2D(tbl, x, y) return tbl[1]*x + tbl[2]*y; end local function Dot3D(tbl, x, y, z) return tbl[1]*x + tbl[2]*y + tbl[3]*z end local function Dot4D( tbl, x,y,z,w) return tbl[1]*x + tbl[2]*y + tbl[3]*z + tbl[3]*w; end local Prev2D = {} function simplex.seed(seed) seed = seed or tstamp() math.randomseed(seed * seed) for i = 1, 256 do p[i] = math.floor(math.random()*256) end end -- 2D simplex noise function simplex.Noise2D(xin, yin) if simplex.internalCache and Prev2D[xin] and Prev2D[xin][yin] then return Prev2D[xin][yin] end local n0, n1, n2; -- Noise contributions from the three corners -- Skew the input space to determine which simplex cell we're in local F2 = 0.5*(math.sqrt(3.0)-1.0); local s = (xin+yin)*F2; -- Hairy factor for 2D local i = math.floor(xin+s); local j = math.floor(yin+s); local G2 = (3.0-math.sqrt(3.0))/6.0; local t = (i+j)*G2; local X0 = i-t; -- Unskew the cell origin back to (x,y) space local Y0 = j-t; local x0 = xin-X0; -- The x,y distances from the cell origin local y0 = yin-Y0; -- For the 2D case, the simplex shape is an equilateral triangle. -- Determine which simplex we are in. local i1, j1; -- Offsets for second (middle) corner of simplex in (i,j) coords if(x0>y0) then i1=1 j1=0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1) else i1=0 j1=1 -- upper triangle, YX order: (0,0)->(0,1)->(1,1) end -- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and -- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where -- c = (3-sqrt(3))/6 local x1 = x0 - i1 + G2; -- Offsets for middle corner in (x,y) unskewed coords local y1 = y0 - j1 + G2; local x2 = x0 - 1.0 + 2.0 * G2; -- Offsets for last corner in (x,y) unskewed coords local y2 = y0 - 1.0 + 2.0 * G2; -- Work out the hashed gradient indices of the three simplex corners local ii = i & 255 local jj = j & 255 local gi0 = perm[ii+perm[jj]] % 12; local gi1 = perm[ii+i1+perm[jj+j1]] % 12; local gi2 = perm[ii+1+perm[jj+1]] % 12; -- Calculate the contribution from the three corners local t0 = 0.5 - x0*x0-y0*y0; if t0<0 then n0 = 0.0; else t0 = t0 * t0 n0 = t0 * t0 * Dot2D(Gradients3D[gi0], x0, y0); -- (x,y) of Gradients3D used for 2D gradient end local t1 = 0.5 - x1*x1-y1*y1; if (t1<0) then n1 = 0.0; else t1 = t1*t1 n1 = t1 * t1 * Dot2D(Gradients3D[gi1], x1, y1); end local t2 = 0.5 - x2*x2-y2*y2; if (t2<0) then n2 = 0.0; else t2 = t2*t2 n2 = t2 * t2 * Dot2D(Gradients3D[gi2], x2, y2); end -- Add contributions from each corner to get the final noise value. -- The result is scaled to return values in the localerval [-1,1]. local retval = 70.0 * (n0 + n1 + n2) if simplex.internalCache then if not Prev2D[xin] then Prev2D[xin] = {} end Prev2D[xin][yin] = retval end return retval; end TileMan = TileManager.new() t = 0 m = {x = 0, y = 0, l = false} last_time = 0 fps = 60 player = {x = -1000, y = 0} sspr = spr floor = math.floor --toggle to show world-map show_map = false --toggle to show debug info debug = true --help menu show_help = true help = { [1] = 'WASD - Move player', [2] = 'SHIFT - Inspect tile (debug mode only)', [3] = 'TAB - Toggle debug mode', [4] = 'M - Toggle world map view', [5] = 'H - Toggle this menu', [6] = 'P - Save map to cart (wip)' } water_anim = 0 dir = 1 --For a SET seed --math.randomseed(666) --For RANDOM seed each re-load math.randomseed(tstamp()) offset = math.random(100000, 500000) simplex.seed() function get_sprite_pixel(sprite_id, x, y) local byte = peek(0x04000 + sprite_id * 32 + y * 4 + math.floor(x / 2)) return x % 2 == 0 and byte % 16 or byte // 16 end -- Function to set a pixel color in a sprite -- Arguments: sprite_id (0-511), x (0-7), y (0-7), color (palette index 0-15) function set_sprite_pixel(sprite_id, x, y, color) local addr = 0x04000 + sprite_id * 32 + y * 4 + math.floor(x / 2) local byte = peek(addr) if x % 2 == 0 then poke(addr, (byte - byte % 16) + color) else poke(addr, (color * 16) + byte % 16) end end --from wiki, linear interpolation function lerp(a,b,mu) return a*(1-mu)+b*mu end -- Set the size of the tiling texture local num_colors = 3 local start_color = 8 local tileSize = 8 local tileCount = 1 -- Set the water effect parameters local amplitude = num_colors local frequency = 0.22 local speed = 0.005 -- Function to update the water effect function update_water_effect(time) for sprite_id = 0, (tileCount * tileCount) - 1 do for y = 0, tileSize - 1 do for x = 0, tileSize - 1 do -- Get world coords for the current pixel local worldX = (sprite_id % tileCount) * tileSize + x local worldY = math.floor(sprite_id / tileCount) * tileSize + y -- Modulo for tiling texture local tileX = worldX % (tileSize * tileCount) local tileY = worldY % (tileSize * tileCount) -- Calculate the noise value using world coordinates and time local noiseValue = simplex.Noise2D(tileX * frequency, (tileY + time * speed) * frequency) -- Convert the noise value to a pixel color (palette index 0-15) local color = math.floor(((noiseValue + 1) / 2) * amplitude) + start_color -- Set the pixel color in the sprite set_sprite_pixel(224, x, y, color) end end end end function get_screen_cell(mouse_x, mouse_y) local cam_x, cam_y = 116 - player.x, 64 - player.y local mx = floor(cam_x) % 8 local my = floor(cam_y) % 8 return mouse_x - ((mouse_x - mx) % 8), mouse_y - ((mouse_y - my) % 8) end function get_world_cell(mouse_x, mouse_y) local cam_x = player.x - 116 local cam_y = player.y - 64 local sub_tile_x = cam_x % 8 local sub_tile_y = cam_y % 8 local sx = floor((mouse_x + sub_tile_x) / 8) local sy = floor((mouse_y + sub_tile_y) / 8) local wx = floor(cam_x / 8) + sx + 1 local wy = floor(cam_y / 8) + sy + 1 return TileMan.tiles[wy][wx], wx, wy end function clamp(value, min, max) return math.min(math.max(min, value), max) end function draw_debug(data, x, y) if debug then local width = 4 local height = #data * 7 for i = 1, #data do local length = print(data[i], 2, -10, 2, false, 1, true) if length > width then width = length + 4 end end x, y = clamp(x, 0, 240 - width), clamp(y, 0, 136 - height) rectb(x, y, width, height, 10) rect(x + 1, y + 1, width -2, height - 2, 8) for i = 1, #data do print(data[i], x + 2, i*6 - 4 + y, 11, false, 1, true) end end end function draw_tile_widget(x, y) local mx, my = mouse() local tile, wx, wy = get_world_cell(mx, my) local sx, sy = get_screen_cell(x, y) local type = tile.ore and ores[tile.ore].name or tile.is_land and 'Land' or 'Water' local biome = tile.is_land and biomes[tile.biome].name or 'Ocean' if tile.is_tree then rectb(sx + tile.offset.x - 9, sy + tile.offset.y - 26, 24, 32, 4) end local info = { 'Sprite: ' .. (tile.ore and tostring(ores[tile.ore].tile_id) or tile.is_land and tostring(tile.sprite_id) or 224), 'Type: ' .. type, 'Biome: ' .. biome, 'Coords: ' .. tostring(wx) .. ',' .. tostring(wy), } if tile.is_tree then info[4] = 'Tree' end draw_text_window(info, x, y) end function draw_text_window(data, x, y, fg, bg, text_color) fg, bg, text = fg or 9, bg or 8, text_color or 4 local width = 0 local height = #data * 7 + 3 for i = 1, #data do local string_width = print(data[i], 0, -10, 0, false, 1, true) if string_width > width then width = string_width end end width = width + 4 x, y = clamp(x, 1, 240 - width - 1), clamp(y, 1, 136 - height - 1) rectb(x, y, width, height, fg) rect(x + 1, y + 1, width - 2, height - 2, bg) for i = 1, #data do print(data[i], x + 1, y - 5 + i*7, 0, false, 1, true) print(data[i], x + 2, y - 5 + i*7, text, false, 1, true) end end function save_map() local tile1, wx, wy = get_world_cell(player.x, player.y) local start_x, start_y = wx - 120, wy - 68 for y = 0, 135 do for x = 0, 239 do local tile = TileMan.tiles[start_y + y][start_x + x] if not tile.visited and tile.is_land then AutoMap(start_x + x, start_y + y) end end end for y = 0, 135 do for x = 0, 239 do local tile = TileMan.tiles[start_y + y][start_x + x] mset(x, y, tile.sprite_id) end end sync(4, 0, true) end function TIC() local start_time = time() cls(0) if t % 2 == 0 then update_water_effect(time()) end t = t + 1 if t % 6 == 0 then water_anim = water_anim + 1 if water_anim > 3 then water_anim = 0 end end --replace mouse cursor with ours poke(0x3FFB, 341) local x, y, left = mouse() if key(23) then player.y = player.y - (show_map and 10 or 5) end if key(19) then player.y = player.y + (show_map and 10 or 5) end if key( 1) then player.x = player.x - (show_map and 10 or 5) end if key( 4) then player.x = player.x + (show_map and 10 or 5) end if keyp(49) then debug = not debug end if keyp(13) then show_map = not show_map end if keyp(37) then frequency = frequency - 0.01 end if keyp(38) then frequency = frequency + 0.01 end if keyp(8) then show_help = not show_help end if show_map then TileMan:draw_worldmap(player) else --Draw visible map TileMan:draw_terrain(player, 31, 18) TileMan:draw_clutter(player, 32, 21) end --Draw tile-grid highlight local tile, wx, wy = get_world_cell(x, y) local sx, sy = get_screen_cell(x, y) if not show_map then sspr(288, sx, sy, 0) end --Draw debug info if debug then local frame_time = floor(time() - start_time) local total_frame_time = floor(time() - last_time) draw_text_window({'Frame Time: ' .. frame_time .. 'ms', 'FPS: ' .. floor(1.0/total_frame_time * 1000)}, 2, 2) sspr(320, 116 - 8, 64, 0, 1, 0, 0, 2, 1) end if key(64) then draw_tile_widget(x + 5, y + 8) end if key(63) and keyp(20) then sync(0, 0, true) end if show_help then draw_text_window(help, 1, 25) end m.x, m.y, m.l = x, y, left if keyp(16) then save_map() end last_time = time() end