UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU]eVUUUUUUUUUUUnUUUUUUUUU]VUUeUUUUUU]Uf^VUUUUVUUUUUReU%$UVURUUUU]UUfUUUUUeUUUUUUUeeUTUUeVUeUUUUURUe%$UUURUUUUVUUUVUUUUIYUUUUVUUeUVUUUUUUUeVeUUUUVUUUUUUeUSUU54UUUSUUUUUUUUUeeUVUUeUUUUIY5UUCcUU5eUUUUUUUUeUUUUVUUUVUUUUUeUUUVUUUVUUUUUU3"UU5"UU3"U5#"U5#"UU#"UU3"UU5""3UU"SUU"3UU"2SU"2SU"2UU"3UU"SUUUeVUUfgUUvfUefgVufvWUwwUUaUUeVUU5SUU#2UU""UU!3U!"U!fU!VUffUU5SUU#2UU""U3!3"!"f!fe!VUffUU5SUU#2UU""U3!U"!Uf!Ue!UUffUUUUUUUUUUUUUfUfffUUUU]UU]ffffUUUUUUUU]UUUV_WfffVUUUUUDDUE33TAQ%2#R%""RaeffVUDDUEC4TQQ%2#R%""RaeffV@4#4#  . Ј .  ۽ DDM    N   . .   @@C43@33C44CC233# 23@D3@4C@332#@3D04C@332#@4@3C433433C233# 3#"" +%""""b ff@"" ff`df`ff""  D @ 40 DDN> 3# "" ,","" 330""#0####3333""""33""2!2222 !""""""-" f`fff`ff`fggfvffffffVeffUUffWuffvgfwffvfffefwggvfvffff&fffffUffVUeffffVfvfffvUUSUU54UUUSUUUUUU533U#"51"5"13UUUUUUVUUeUUUeUUSUUS233#"""""""########22222222"!-" gfegfggffgfVgfvpffpvfwgwwgfffffffUffVUefvUgbfwffffffgfffvUgVfwfvffffffffgfbvfefgfgvvffvgfvvfvefvgfvfwvfffvfw5"151"e#"f6efffUUUUUeUUUUVU23R"RQfffiVUUUUZUUUUU####0#0""33""""33332222!2""33!"#23.24-C4荚حڍ؍؎wwggffwwwwpwwwfvwfavffvvvwwwwwwafwwUUUUUUUUUU3JZ5#U53UU5"UV5#Ue5"U5SU3333#""2"!"#""2#332"2#"""UUUUUUUU3UUU2SUV2SeU"SeU"SeU2SUU]""""""""""""]U!""!"""""""! о f!`f&"ff#"f6""ff32`ff3fff!f"ff"bf"cf#3f6ffffUe5"UU%Ue&5c"!e""e&"#&bvSefb!"!""""'"wwfbf"SUU"SSU!"RU"fU!'bV!r"V"bfV&"VU3!2"!fU3S"!313U"!"ff33f""UU331""!3133!""3133!!""333"""133!"!13!""3""QQ33""  331""!31""!"133#231!""!233"""1331#"c1"bf!VU3QZ5"UQZU3"3321""!33Q"QQ323Q%UUUUUUUUUUU$^R]^UU  ]UU_UUU^UUU]UU!""_onofffff!""!ffff""ffff"""]UoffffffUUUUUmUUUUUUUemeVfefefefUUfffffffffnmffffffff]UUV]UUUUU]UU]UUfeVfVfVUUfV~CDCD0D0D003CC$D"DD3 4B4DD4D4CD3333D"DDD"CDD3333D33DDD1DD43333D433 >?"3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5"123RUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU51""ReUUUeUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUe#"QUVUUUVUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf6fUVUUUVUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefffffiVUUUeUUUeUUUUU5#""2UUUU]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU33333333333333333333UUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""""""""""""""""""""SUUUUU3""SUUU]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#2UUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5!SUUUU3""SUUU!""""""""""""""""UUUUUffffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#2UUUU5""3UUU"""-"""""""""""""""""UUfffffefwgfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#2UUUU3""2SUU"""""""""""""""""""""UefVeffgvfvfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#32UUU5#""2SUU-"""""""""""""""""""UffUUffffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#D13132UeU5#""2UUU"""""""""""""""""""effWuff&fffVfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#A331312UVUU#""3UUU""""""""""""""""""efgvgfwffUfvfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#A33112UVUU3""SUUU-"""""""""""""""""gfvffvffVUeffvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#"1332UUUU5""3UUU!""""""""""""""""gfewwgffvUggfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#2UUUU3""SUUU-gfgffffVfwfvfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeU#2UUUU5""3UUU"]UUUUUUUUUUUVUUUVUUUgffffUfvfffefvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUVUUUV#2UUUU3""2SUUUUUUUUUUUUUUUVUUUVUUUgfVfVUeffffgfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUVUUUV#13133311332UUU5#""2SUUU]UUUUUUUUUUUUUUeUUUeUgfvfvUgfgfbfwvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUU#331131132UeU5#""2UUUUUUUUUUUUUUUUUUUUUVUUUVUuffbfwfvfefffWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUVUU#33113332UVUU#""3UUUUUUUU_U_U_UUUVUuvfffffgfgvfvWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUVUU#33113132UVUU3""SUUUUUUUU___UU_U__wgfgffvffvfwUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#13133311132UUUU5""3UUUUUUUU_UUUU____UwggffvffvwWUUUUUUUUUUUUUUUUUUUUUUUUUUU5SUU5SUU5SUU5SUU5SUUU#2UUUU3""SUUUUUUUU___U_UUUU_U_UwwwwwvvwwwUUUUUUUUUUUUUUUUUUUUUUUUUUUU#2UU#2UU#2UU#2UU#2UUU5!SUUUU5""3UUUUUUUUU_U_UU_UUUUuwwwwwwWUUUUUUUUUUUUUUUUUUUUUUUUUUUUU""UU""UU""UU""UU""UUUU#2UUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfvwwaUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU!33!33!33!33!UUUU5""""""""""""""""""""SUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU!""!""!""!""!UUUUU33333333333333333333UUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUaQUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU!ff!ff!ff!ff!UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUQUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU!Ve!Ve!Ve!Ve!UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffUUffUUffUUffUUffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf!!fVUUUUUUUUUUUUU]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUef&""ffUUUUUUUUUUUUU]UUUUUUUUUUUUUUUUUUUUUUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUff#""bfVUUUUUUUUUUUU^UUUUUUUUUUUUUUUUUUUUUUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf6"""cfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUff32#3fVUUUUUUUUUUUU^UUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeff36ffUUUUUUUUUUUUUNUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfffffVUUUUUUUUUUUUUTUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffUUUUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfffffefwgfUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefVeffgvfvfVUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffUUffffffffUUUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeffWuff&fffVfVUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefgvgfwffUfvfVUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUgfvffvffVUeffvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXUgfewwgffvUggfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXUUUgfgffffVfwfvfvUeUUUUUUUUUUUUUUUUUUUUUffffUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXZUgffffUfvfffefvUUVUUUUUUUUUUUUUUUUUfffffefwgfUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUgfVfVUeffffgfvUUVUUUUUUUUUUUUUUUUefVeffgvfvfVUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYUgfvfvUgfgfbfwvUUUUeUUUUUUUUUUUUUUffUUffffffffUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUuffbfwfvfefffWUUUUVUUUUUUUUUUUUUeffWuff&fffVfVUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXUuvfffffgfgvfvWUUUUVUUUUUUUUUUUUUefgvgfwffUfvfVUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXUUwgfgffvffvfwUUUUUUUUUUUUUUUUUUUgfvffvffVUeffvUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwggffvffvwWUUUUUUUUUUUUUUUUUUUgfewwgffvUggfvUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwwwwwvvwwwUUUeUUUUUUUUUUUUUUUUgfgffffVfwfvfvUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUuwwwwwwWUVUUUVUUUUUUUUUUUUUUUgffffUfvfffefvUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfvwwaUUVUUUVUUUUUUUUUUUUUUUgfVfVUeffffgfvUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffUUUUeUUUeUUUUUUUUUUUUUgfvfvUgfgfbfwvUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUaQUUUUVUUUVUUUUUUUUUUUUUuffbfwfvfefffWUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUQUUUUUVUUUVUUUUUUUUUUUUUuvfffffgfgvfvWUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwgfgffvffvfwUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUU%]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf!!fVUUUUUUUUUUUUUUUUUUUUUUUUwggffvffvwWUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUef&""ffUUUUUUUUUUUUUUUUUUUUUUUUwwwwwvvwwwUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUU]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUff#""bfVUUUUUUUUUUUUUUUUUUUUUUUUuwwwwwwWUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf6"""cfVUUUUUUUUUUUUUUUUUUUUUUUUfvwwaUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUU^UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUff32#3fVUUUUUUUUUUUUUUUUUUUUUUUUffUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUU^UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeff36ffUUUUUUUUUUUUUUUUUUUUUUUUUaQUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfffffVUUUUUUUUUUUUUUUUUUUUUUUUUUQUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf!!fVUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUef&""ffUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUff#""bfVUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUf6"""cfVUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUff32#3fVUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeff36ffUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfffffVUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUSUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU54UUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUSUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU533SUUSUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#"233#UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU51"""""UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5"13"""UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5"123RUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUffffUUUUUU51""RUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU]UU]UU]UUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUfffffefwgfUUUe#"QUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU]]]]UUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUefVeffgvfvfVUUf6fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUffUUffffffffUUefffffiVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUeffWuff&fffVfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_UUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUefgvgfwffUfvfVUUeUUUUZUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfWUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUgfvffvffVUeffvUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffffffffffffffVUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUgfewwgffvUggfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUgfgffffVfwfvfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUgffffUfvfffefvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUgfVfVUeffffgfvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUgfvfvUgfgfbfwvUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUuffbfwfvfefffWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUuvfffffgfgvfvWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUwgfgffvffvfwUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUwggffvffvwWUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5SUU5SUU5SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUwwwwwvvwwwUUUUUUU]UU]UU]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#2UU#2UU#2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUUUUUUUUUUUUUuwwwwwwWUUUUUU]]]]UUUUUUUUUUUUUUUUUUUUUUUUUUU""UU""UU""UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUfvwwaUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU!33!33!UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUffUUUUUVUUUUUUUUUUUUUUUUUUUUUUUUU!""!""!UUUUUUUUUUUUU]UUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUaQUUUUU_UUUUUUUUUUUUUUUUUUUUUUUUU!ff!ff!UUUUUUUUUUUUU]^UUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUQUUUUUUfWUUUUUUUUUUUUUUUUUUUUUUUUU!Ve!Ve!UUUUUUUUUUUUU^UUUUU_UUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffffffffffffffVUUUUUUUUUUUUUUUUUUUUUUUUUffUUffUUffUUUUUUUUUUUUU.]U_UUUUUUUUU5""3UUUUUUUUUUUUUUUUUUUf!!fVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU]UUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUef&""ffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_UUUUUUU5""3UUUUUUUUUUUUUUUUUUff#""bfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU]U_UUUUUUUU3""2SUUUUUUUUUUUUUUUUUf6"""cfVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^UUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUff32#3fVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUeff36ffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUPPUPP`ffVPPUPPUPPUUPUPUUUPUUUUPUPUPPUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUPPUPPUUPUUUUPPPUUPPUUUPPUPPUUUPUPUUUUPUPPPUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUUUUPPUUUUUUUPPUUPPUUUUUUUPPUUUPUUPUUUUUUUPPPUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUPPUPPUUUPUUUPPPUUPPPUUPUPPPUUPUPUUUUPUPPPUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5""3UUUPPUPPUUUUUUPPUUPUUUPPUUPUPPUUUPUUPUUUPPUPUPUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5#""2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#""3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU3""SUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU5"c-- title: Infinite Journey [beta] -- author: Zhailox -- desc: procedurally generated infinite scroller -- version: 0.1 -- script: lua SCREEN_W=240 SCREEN_H=136 TILE_SIZE=8 GRID_W=30 GRID_H=17 BLACK=0 WHITE=15 DARK_BLUE=8 MEDIUM_BLUE=9 LIGHT_BLUE=10 BRIGHT_BLUE=11 GREEN=3 RED=2 YELLOW=14 BROWN=6 player={x=GRID_W//2,y=GRID_H//2,sprite_front=48,sprite_right=49,sprite_left=50,sprite_back=51,direction=2,hp=100,max_hp=100,atk=10,def=5,exp=0,level=1,exp_next=100,turn=true,sword_count=0,shield_count=0,potion_count=0,coin_count=0,move_cooldown=0,move_delay=300,last_move_time=0,confused_this_turn=false,arrow_count=5,auto_target_index=nil} map_seed=math.random(9999) current_depth=0 camera_y=0 highest_generated=0 lowest_generated=0 initial_fence_placed=false FLOOR_CHANCE=95 WALL_CHANCE=1 FENCE_CHANCE=2 BRICK_WALL_CHANCE=2 BUSH_CHANCE=4 FLOWER_CHANCE=1 ENEMY_CHANCE=6 ITEM_CHANCE=2 CHEST_CHANCE=1 STRUCTURE_CHANCE=2 TREE_CHANCE=4 ALTAR_CHANCE=0.5 enemies={} items={} walls={} decorations={} chests={} particles={} trees={} houses={} projectiles={} altars={} show_stats_panel=false player_effects={burning=0,confused=0,frozen=0} SPR={FLOOR1=1,FLOOR2=2,FLOOR3=3,FLOOR4=4,FLOOR12=12,BRICK_START=5,BRICK_MIDDLE=6,BRICK_END=7,FLOWER1=8,FLOWER2=9,FLOWER3=10,FLOWER4=11,BORDER_RIGHT=13,BORDER_LEFT=14,BUSH=17,FENCE_START=18,FENCE_MIDDLE=19,FENCE_END=20,BRICKWALL_START=21,BRICKWALL_MIDDLE=22,BRICKWALL_END=23,CHEST_CLOSED=24,CHEST_OPENED=25,COIN=26,HEART_FULL=27,HEART_EMPTY=28,PLAYER_FRONT=48,PLAYER_RIGHT=49,PLAYER_LEFT=50,PLAYER_BACK=51,SLIME_FRONT=64,SLIME_RIGHT=65,SLIME_LEFT=66,SLIME_BACK=67,IRON_SLIME_FRONT=68,IRON_SLIME_RIGHT=69,IRON_SLIME_LEFT=70,IRON_SLIME_BACK=71,FIRE_SLIME_FRONT=72,FIRE_SLIME_RIGHT=73,FIRE_SLIME_LEFT=74,FIRE_SLIME_BACK=75,CHAOS_SLIME_FRONT=76,CHAOS_SLIME_RIGHT=77,CHAOS_SLIME_LEFT=78,CHAOS_SLIME_BACK=79,SWORD=80,SHIELD=81,POTION=96,DEBUFF_FIRE=179,DEBUFF_CONF=180,ARROW_PROJECTILE=27,TARGET_MARKER=28,ARROW_ICON=29} UI={TOP_LEFT=144,TOP_CENTER=145,TOP_RIGHT=146,MID_LEFT=160,MID_CENTER=161,MID_RIGHT=162,BOT_LEFT=176,BOT_CENTER=177,BOT_RIGHT=178} UI_LIFE={147,148,149,150,151,152,163,164,165,166,167,168} TREE_SPRITES={153,154,155,156,169,170,171,172,185,186,187,188,201,202,203,204} TREE_SPRITES_2={157,158,173,174} TREE_SPRITES_3={189,190,191,205,206,207} TREE_SOLID_SPRITES={[186]=true,[187]=true,[202]=true,[203]=true} house_sprites={192,193,194,195,208,209,210,211,224,225,226,227,240,241,242,243} ALTAR_SPRITES = {196,197,198,199,212,213,214,215,228,229,230,231,244,245,246,247} function noise(x,y)local fx=math.floor(x)local fy=math.floor(y)local fractX=x-fx local fractY=y-fy local v1=pseudo_random(fx,fy)local v2=pseudo_random(fx+1,fy)local v3=pseudo_random(fx,fy+1)local v4=pseudo_random(fx+1,fy+1)local i1=lerp(v1,v2,fractX)local i2=lerp(v3,v4,fractX)return lerp(i1,i2,fractY)end function pseudo_random(x,y)local value=math.sin(x*12.9898+y*78.233)*43758.5453 return value-math.floor(value)end function lerp(a,b,t)return a+(b-a)*t end function wall_exists_at(x,y)for _,wall in ipairs(walls)do if wall.x==x and wall.y==y then return true end end return false end function init() math.randomseed(map_seed) camera_y = 0 current_depth = 0 highest_generated = 0 lowest_generated = 0 initial_fence_placed = false houses = {} altars = {} -- Línea agregada player_effects = {burning = 0, confused = 0, frozen = 0} player.arrow_count = 5 player.auto_target_index = nil projectiles = {} generate_initial_area() end function place_initial_fence()local fence_y=20 for x=2,GRID_W-3 do local part="middle"if x==2 then part="start"elseif x==GRID_W-3 then part="end"end walls[#walls+1]={x=x,y=fence_y,type="fence",part=part}end initial_fence_placed=true end function generate_initial_area()enemies={}items={}walls={}decorations={}chests={}houses={}place_initial_fence()for world_y=-50,50 do generate_row(world_y)end highest_generated=-50 lowest_generated=50 end function can_place_tree(x,y) local rnd = math.random(100) local tree_type if rnd <= 40 then tree_type = 1 -- Primer tipo de árbol completo elseif rnd <= 80 then tree_type = 1 -- Segundo tipo de árbol completo (también 4x4) elseif rnd <= 95 then tree_type = 2 -- Árbol cortado else tree_type = 3 -- Tronco caído end local w, h if tree_type == 1 or tree_type == 3 then w, h = 4, 4 elseif tree_type == 2 then w, h = 2, 2 else w, h = 3, 2 end if x < 2 or x > GRID_W - (w + 1) then return false end for dy = 0, h - 1 do for dx = 0, w - 1 do local world_y = y + dy for _, wall in ipairs(walls) do if wall.x == x + dx and wall.y == world_y then return false end end for _, tree in ipairs(trees) do if tree.x <= x + dx and x + dx <= tree.x + tree.width - 1 and tree.y <= world_y and world_y <= tree.y + tree.height - 1 then return false end end end end return true, tree_type end function can_place_altar(x,y) -- Verificar que haya espacio para un altar 4x4 if x < 2 or x > GRID_W - 6 then return false end -- Verificar que no haya otros objetos en el área 4x4 for dy = 0, 3 do for dx = 0, 3 do local world_y = y + dy -- Verificar paredes for _,wall in ipairs(walls) do if wall.x == x + dx and wall.y == world_y then return false end end -- Verificar árboles for _,tree in ipairs(trees) do if tree.x <= x + dx and x + dx <= tree.x + tree.width - 1 and tree.y <= world_y and world_y <= tree.y + tree.height - 1 then return false end end -- Verificar casas for _,house in ipairs(houses) do if house.x <= x + dx and x + dx <= house.x + 3 and house.y <= world_y and world_y <= house.y + 3 then return false end end -- Verificar altares existentes for _,altar in ipairs(altars) do if altar.x <= x + dx and x + dx <= altar.x + 3 and altar.y <= world_y and world_y <= altar.y + 3 then return false end end end end return true end function can_place_house(x,y)if x<2 or x>GRID_W-6 then return false end for dy=0,3 do for dx=0,3 do local world_y=y+dy for _,wall in ipairs(walls)do if wall.x==x+dx and wall.y==world_y then return false end end for _,tree in ipairs(trees)do if tree.x<=x+dx and x+dx<=tree.x+3 and tree.y<=world_y and world_y<=tree.y+3 then return false end end for _,house in ipairs(houses)do if house.x<=x+dx and x+dx<=house.x+3 and house.y<=world_y and world_y<=house.y+3 then return false end end end end return true end function generate_house(x,y)local solid_sprites={[192]=true,[193]=true,[194]=true,[195]=true,[208]=true,[224]=true,[240]=true,[241]=true,[242]=true,[243]=true}local house={x=x,y=y,sprites={{192,193,194,195},{208,209,210,211},{224,225,226,227},{240,241,242,243}},solid_sprites=solid_sprites}houses[#houses+1]=house for dy=0,3 do for dx=0,3 do local sprite_index=house.sprites[dy+1][dx+1]if solid_sprites[sprite_index]then walls[#walls+1]={x=x+dx,y=y+dy,type="house_wall",sprite=sprite_index}end end end return house end function generate_tree(x,y,tree_type)if not tree_type then tree_type=math.random(1,4)end local tree={x=x,y=y}if tree_type==1 then tree.sprites={{153,154,155,156},{169,170,171,172},{185,186,187,188},{201,202,203,204}}tree.width=4 tree.height=4 tree.type="normal"walls[#walls+1]={x=x+1,y=y+2,type="tree_trunk",sprite=186}walls[#walls+1]={x=x+2,y=y+2,type="tree_trunk",sprite=187}walls[#walls+1]={x=x+1,y=y+3,type="tree_trunk",sprite=202}walls[#walls+1]={x=x+2,y=y+3,type="tree_trunk",sprite=203} elseif tree_type==2 then tree.sprites={{157,158},{173,174}}tree.width=2 tree.height=2 tree.type="cut"for dy=0,1 do for dx=0,1 do walls[#walls+1]={x=x+dx,y=y+dy,type="tree_trunk",sprite=tree.sprites[dy+1][dx+1]}end end else tree.sprites={{189,190,191},{205,206,207}}tree.width=3 tree.height=2 tree.type="fallen"for dy=0,1 do for dx=0,2 do walls[#walls+1]={x=x+dx,y=y+dy,type="tree_trunk",sprite=tree.sprites[dy+1][dx+1]}end end end trees[#trees+1]=tree return tree end function generate_altar(x, y) local altar = { x = x, y = y, sprites = { {196, 197, 198, 199}, {212, 213, 214, 215}, {228, 229, 230, 231}, {244, 245, 246, 247} }, solid_sprites = { -- Sprites que son sólidos/bloquean el paso [228] = true, [229] = true, [230] = true, [231] = true, [244] = true, [245] = true, [246] = true, [247] = true } } -- Agregar paredes para los sprites sólidos del altar for dy = 0, 3 do for dx = 0, 3 do local sprite_index = altar.sprites[dy + 1][dx + 1] if altar.solid_sprites[sprite_index] then walls[#walls + 1] = { x = x + dx, y = y + dy, type = "altar_wall", sprite = sprite_index } end end end altars[#altars + 1] = altar return altar end function generate_row(world_y) local density = math.min(1.0, (-world_y + 20) / 80) for x = 2, GRID_W - 3 do if wall_exists_at(x, world_y) then goto continue end -- Generación de estructuras if math.random(100) < STRUCTURE_CHANCE * density and world_y < 0 then local structure_type = math.random(1, 5) -- Cambiado de 4 a 5 local can_build = true if structure_type == 1 and x < GRID_W - 5 then local fence_length = math.random(3, 5) for i = 0, fence_length - 1 do if x + i >= GRID_W - 2 or wall_exists_at(x + i, world_y) then can_build = false break end end if can_build then for i = 0, fence_length - 1 do if x + i < GRID_W - 2 then local part = (i == 0) and "start" or (i == fence_length - 1) and "end" or "middle" walls[#walls + 1] = {x = x + i, y = world_y, type = "fence", part = part} end end x = x + fence_length - 1 end elseif structure_type == 2 and x < GRID_W - 8 then local wall_length = math.random(4, 6) for i = 0, wall_length - 1 do if x + i >= GRID_W - 2 or wall_exists_at(x + i, world_y) then can_build = false break end end if can_build then for i = 0, wall_length - 1 do if x + i < GRID_W - 2 then local part = (i == 0) and "start" or (i == wall_length - 1) and "end" or "middle" walls[#walls + 1] = {x = x + i, y = world_y, type = "brickwall", part = part} end end x = x + wall_length - 1 end elseif structure_type == 3 and x < GRID_W - 6 then local path_length = math.random(4, 6) for i = 0, path_length - 1 do if x + i >= GRID_W - 2 then can_build = false break end end if can_build then for i = 0, path_length - 1 do if x + i < GRID_W - 2 then local part = (i == 0) and "start" or (i == path_length - 1) and "end" or "middle" decorations[#decorations + 1] = {x = x + i, y = world_y, type = "brick_path", part = part} end end x = x + path_length - 1 end elseif structure_type == 4 and x < GRID_W - 6 then if can_place_house(x, world_y) then generate_house(x, world_y) x = x + 3 end elseif structure_type == 5 and x < GRID_W - 6 then -- NUEVO: Altar -- Solo generar altar si pasa la probabilidad ALTAR_CHANCE if math.random(100) < ALTAR_CHANCE * 100 then if can_place_altar(x, world_y) then generate_altar(x, world_y) x = x + 3 end end end end -- Generación de árboles if world_y < -20 and math.random(100) < TREE_CHANCE * density then local can_place, tree_type = can_place_tree(x, world_y) if can_place then generate_tree(x, world_y, tree_type) if tree_type == 1 then x = x + 3 elseif tree_type == 2 then x = x + 1 else x = x + 2 end end end -- Generación de objetos, enemigos, etc. if not wall_exists_at(x, world_y) and math.random(100) < 15 * density and world_y < -5 then local content_rnd = math.random(100) local offset = 0 if content_rnd < BUSH_CHANCE then decorations[#decorations + 1] = {x = x, y = world_y, type = "bush"} offset = 1 elseif content_rnd < BUSH_CHANCE + FLOWER_CHANCE then decorations[#decorations + 1] = {x = x, y = world_y, type = "flower", variant = math.random(1, 4)} offset = 1 elseif content_rnd < BUSH_CHANCE + FLOWER_CHANCE + ENEMY_CHANCE and world_y < -15 then spawn_enemy(x, world_y) offset = 3 elseif content_rnd < BUSH_CHANCE + FLOWER_CHANCE + ENEMY_CHANCE + ITEM_CHANCE and world_y < -20 then spawn_item(x, world_y) offset = 2 elseif content_rnd < BUSH_CHANCE + FLOWER_CHANCE + ENEMY_CHANCE + ITEM_CHANCE + CHEST_CHANCE and world_y < -25 then chests[#chests + 1] = {x = x, y = world_y, opened = false, has_item = math.random(100) < 60} offset = 3 end if offset > 0 and math.random(100) < 60 then x = x + offset end end ::continue:: end end function spawn_enemy(x,y)local enemy_type local depth_factor=math.abs(y)/50 local rnd=math.random(100)if depth_factor>0.7 and rnd<10 then enemy_type="chaos_slime"elseif depth_factor>0.5 and rnd<25 then enemy_type="fire_slime"elseif depth_factor>0.3 and rnd<40 then enemy_type="iron_slime"else enemy_type="normal_slime"end local base_hp,base_atk,base_def,base_exp,sprite_base,behavior,special_effect if enemy_type=="normal_slime"then base_hp=20 base_atk=3 base_def=2 base_exp=25 sprite_base=SPR.SLIME_FRONT behavior="random"elseif enemy_type=="iron_slime"then base_hp=40 base_atk=4 base_def=4 base_exp=40 sprite_base=SPR.IRON_SLIME_FRONT behavior="random"special_effect="armor"elseif enemy_type=="fire_slime"then base_hp=25 base_atk=6 base_def=1 base_exp=35 sprite_base=SPR.FIRE_SLIME_FRONT behavior="aggressive"special_effect="burn"elseif enemy_type=="chaos_slime"then base_hp=30 base_atk=5 base_def=3 base_exp=50 sprite_base=SPR.CHAOS_SLIME_FRONT behavior="chaotic"special_effect="confuse"end local depth_bonus=math.abs(y)*0.5 local hp=base_hp+depth_bonus local atk=base_atk+math.floor(math.abs(y)/20)local def=base_def+math.floor(math.abs(y)/40)local exp=base_exp+math.floor(math.abs(y)/2)local dir=math.random(0,3)local sprite=sprite_base+dir enemies[#enemies+1]={x=x,y=y,sprite=sprite,direction=dir,type=enemy_type,hp=hp,max_hp=hp,atk=atk,def=def,exp=exp,alive=true,behavior=behavior,special_effect=special_effect,move_timer=math.random(300,600),effect_timer=0,burn_damage=(enemy_type=="fire_slime")and 1 or 0}end function spawn_item(x,y)local item_types={"sword","shield","potion","coin","arrow"}local weights={10,10,20,60,15}local total=0 for _,w in ipairs(weights)do total=total+w end local rnd=math.random(total)local cumulative=0 local item_type for i,w in ipairs(weights)do cumulative=cumulative+w if rnd<=cumulative then item_type=item_types[i]break end end local item={x=x,y=y,type=item_type}if item_type=="sword"then item.sprite=SPR.SWORD item.value="sword"elseif item_type=="shield"then item.sprite=SPR.SHIELD item.value="shield"elseif item_type=="potion"then item.sprite=SPR.POTION item.value="potion"elseif item_type=="arrow"then item.sprite=SPR.ARROW_ICON item.value="arrow"else item.sprite=SPR.COIN item.value="coin"end items[#items+1]=item end function is_walkable(x, world_y) for _, wall in ipairs(walls) do if wall.x == x and wall.y == world_y then if wall.type == "tree_trunk" or wall.type == "house_wall" or wall.type == "altar_wall" then return false end return false end end if x <= 1 or x >= GRID_W - 2 then return false end return true end function world_to_screen_y(world_y)return world_y-camera_y end function screen_to_world_y(screen_y)return screen_y+camera_y end function draw_map()cls(BLACK)for screen_y=0,GRID_H-1 do spr(SPR.BORDER_LEFT,0,screen_y*TILE_SIZE,BLACK,1,0,0,1,1)spr(SPR.BORDER_RIGHT,(GRID_W-1)*TILE_SIZE,screen_y*TILE_SIZE,BLACK,1,0,0,1,1)end for x=1,GRID_W-2 do for screen_y=0,GRID_H-1 do local world_y=screen_to_world_y(screen_y)local px=x*TILE_SIZE local py=screen_y*TILE_SIZE local noise_value=noise(x*0.2,world_y*0.2+map_seed*0.01)local floor_type=math.floor(noise_value*12)local floor_sprite=SPR.FLOOR1 if floor_type==0 or floor_type==1 or floor_type==2 then floor_sprite=SPR.FLOOR1 elseif floor_type==3 or floor_type==4 then floor_sprite=SPR.FLOOR2 elseif floor_type==5 or floor_type==6 then floor_sprite=SPR.FLOOR3 elseif floor_type==7 or floor_type==8 then floor_sprite=SPR.FLOOR4 else floor_sprite=SPR.FLOOR12 end spr(floor_sprite,px,py,BLACK,1,0,0,1,1)end end end function draw_walls()for _,wall in ipairs(walls)do local screen_y=world_to_screen_y(wall.y)if screen_y>=0 and screen_y=0 and screen_y=0 and screen_y0 then local bar_color=RED if e.type=="iron_slime"then bar_color=12 elseif e.type=="fire_slime"then bar_color=2 elseif e.type=="chaos_slime"then bar_color=5 end rect(px,py-3,bar_w,2,bar_color)end end end end end end function draw_items()for _,item in ipairs(items)do local screen_y=world_to_screen_y(item.y)if screen_y>=0 and screen_y=0 and screen_y-tree.height then for row=0,tree.height-1 do local screen_y=world_to_screen_y(tree.y+row) if screen_y>=-1 and screen_y-4 then for row=0,3 do local screen_y=world_to_screen_y(house.y+row)if screen_y>=-1 and screen_y -4 then for row = 0, 3 do local screen_y = world_to_screen_y(altar.y + row) if screen_y >= -1 and screen_y < GRID_H then for col = 0, 3 do local sprite = altar.sprites[row + 1][col + 1] spr(sprite, (altar.x + col) * TILE_SIZE, screen_y * TILE_SIZE, BLACK, 1, 0, 0, 1, 1) end end end end end end function draw_target()update_auto_aim()if player.auto_target_index then local e=enemies[player.auto_target_index]if e and e.alive then local screen_y=world_to_screen_y(e.y)if screen_y>=0 and screen_y0 then rect(hp_x+7,hp_y+4,current_hp_width,8,RED)end for i=1,6 do local sprite_index=147+(i-1)spr(sprite_index,hp_x+((i-1)*8),hp_y,BLACK,1,0,0,1,1)spr(sprite_index+16,hp_x+((i-1)*8),hp_y+8,BLACK,1,0,0,1,1)end local hp_text=math.floor(player.hp).."/"..player.max_hp local text_x=hp_x+24-(string.len(hp_text)*2)print(hp_text,text_x,hp_y+17,WHITE)local debuff_x=hp_x+48 local debuff_y=hp_y local debuff_spacing=10 if player_effects.burning>0 then spr(SPR.DEBUFF_FIRE,debuff_x,debuff_y,BLACK,1,0,0,1,1)print(""..player_effects.burning,debuff_x+8,debuff_y+1,2)debuff_x=debuff_x+debuff_spacing end if player_effects.confused>0 then spr(SPR.DEBUFF_CONF,debuff_x,debuff_y,BLACK,1,0,0,1,1)print(""..player_effects.confused,debuff_x+8,debuff_y+1,5)debuff_x=debuff_x+debuff_spacing end local coin_x=SCREEN_W-60 local coin_y=5 local coin_panel_w=45 local coin_panel_h=20 draw_ui_panel(coin_x,coin_y,coin_panel_w,coin_panel_h)spr(26,coin_x+5,coin_y+5,BLACK,1,0,0,1,1)print("x"..player.coin_count,coin_x+15,coin_y+6,3)print("COINS",coin_x+10,coin_y+14,3)local arrow_x=SCREEN_W-40 local arrow_y=SCREEN_H-20 spr(SPR.ARROW_ICON,arrow_x,arrow_y,BLACK,1,0,0,1,1)local arrow_color=WHITE if player.arrow_count<=2 then arrow_color=YELLOW end if player.arrow_count==0 then arrow_color=RED end print("x"..player.arrow_count,arrow_x+10,arrow_y+2,arrow_color) if show_stats_panel then draw_stats_panel()else draw_basic_info()end end function draw_stats_panel()local panel_x=0 local panel_y=0 local panel_w=SCREEN_W local panel_h=SCREEN_H rect(0,0,SCREEN_W,SCREEN_H,0)rectb(0,0,SCREEN_W,SCREEN_H,0)draw_ui_panel(panel_x,panel_y,panel_w,panel_h)print("CHARACTER STATS",panel_x+(panel_w//2)-40,panel_y+10,3)line(panel_x+10,panel_y+25,panel_x+panel_w-10,panel_y+25,3)local stats_x=panel_x+20 local stats_y=panel_y+35 print("LEVEL",stats_x,stats_y,3)print(""..player.level,stats_x+60,stats_y,3)print("EXP",stats_x,stats_y+15,3)print(player.exp.."/"..player.exp_next,stats_x+60,stats_y+15,3)print("ATTACK",stats_x,stats_y+30,3)print(""..player.atk,stats_x+60,stats_y+30,3)print("DEFENSE",stats_x,stats_y+45,3)print(""..player.def,stats_x+60,stats_y+45,3)print("MAX HP",stats_x,stats_y+60,3)print(""..player.max_hp,stats_x+60,stats_y+60,3)print("DEPTH",stats_x,stats_y+75,3)local display_depth=math.abs(math.floor(camera_y/4))print(""..display_depth,stats_x+60,stats_y+75,3)local inv_x=panel_x+150 local inv_y=panel_y+35 print("INVENTORY",inv_x,inv_y,BRIGHT_BLUE)spr(80,inv_x,inv_y+15,BLACK,1,0,0,1,1)print("SWORDS",inv_x+15,inv_y+15,12)print("x"..player.sword_count,inv_x+70,inv_y+15,YELLOW)print("+"..(player.sword_count*3).." ATK",inv_x+15,inv_y+25,RED)spr(81,inv_x,inv_y+40,BLACK,1,0,0,1,1)print("SHIELDS",inv_x+15,inv_y+40,12)print("x"..player.shield_count,inv_x+70,inv_y+40,YELLOW)print("+"..(player.shield_count*2).." DEF",inv_x+15,inv_y+50,LIGHT_BLUE)spr(96,inv_x,inv_y+65,BLACK,1,0,0,1,1)print("POTIONS",inv_x+15,inv_y+65,12)print("x"..player.potion_count,inv_x+70,inv_y+65,YELLOW)print("+30 HP EACH",inv_x+15,inv_y+75,GREEN)local controls_y=panel_y+panel_h-10 print("PRESS Y TO CLOSE",panel_x+(panel_w//2)-50,controls_y,2)end function draw_basic_info()local controls_y=SCREEN_H-10 print("Y:STATS X:POTION Z:ATTACK C:SHOOT",10,controls_y,0)end function draw_ui_panel(x,y,width,height)local w_tiles=math.ceil(width/8)local h_tiles=math.ceil(height/8)for ty=0,h_tiles-1 do for tx=0,w_tiles-1 do local sprite=UI.MID_CENTER if ty==0 then if tx==0 then sprite=UI.TOP_LEFT elseif tx==w_tiles-1 then sprite=UI.TOP_RIGHT else sprite=UI.TOP_CENTER end elseif ty==h_tiles-1 then if tx==0 then sprite=UI.BOT_LEFT elseif tx==w_tiles-1 then sprite=UI.BOT_RIGHT else sprite=UI.BOT_CENTER end else if tx==0 then sprite=UI.MID_LEFT elseif tx==w_tiles-1 then sprite=UI.MID_RIGHT else sprite=UI.MID_CENTER end end spr(sprite,x+tx*8,y+ty*8,BLACK,1,0,0,1,1)end end end function draw_particles()for i=#particles,1,-1 do particles[i].timer=particles[i].timer-1 local screen_y=world_to_screen_y(particles[i].world_y or 0)if screen_y>=0 and screen_yplayer.move_delay then if player_effects.burning>0 then local burn_damage=2 player.hp=player.hp-burn_damage player_effects.burning=player_effects.burning-1 table.insert(particles,{x=player.x*TILE_SIZE+math.random(-4,4),world_y=screen_to_world_y(player.y),text="-"..burn_damage,color=2,timer=30,y=player.y*TILE_SIZE-5})if math.random(100)<50 then table.insert(particles,{x=player.x*TILE_SIZE+math.random(-8,8),world_y=screen_to_world_y(player.y),text="~",color=math.random(2,3),timer=20,y=player.y*TILE_SIZE+math.random(0,8)})end check_game_over()end if player_effects.confused>0 then if math.random(100)<25 then player.confused_this_turn=true else player.confused_this_turn=false end player_effects.confused=player_effects.confused-1 if math.random(100)<30 then table.insert(particles,{x=player.x*TILE_SIZE+math.random(-4,4),world_y=screen_to_world_y(player.y),text="?",color=5,timer=20,y=player.y*TILE_SIZE+math.random(0,8)})end else player.confused_this_turn=false end end if btn(0)then dy=-1 player.direction=0 end if btn(1)then dy=1 player.direction=2 end if btn(2)then dx=-1 player.direction=3 end if btn(3)then dx=1 player.direction=1 end if btnp(4)then try_attack()player.turn=false player.last_move_time=current_time return end if btnp(5)then pickup_item()player.turn=false player.last_move_time=current_time return end if btnp(7)then show_stats_panel=not show_stats_panel return end if btnp(6)then if player.arrow_count<=0 then table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="NO SHURIKEN",color=RED,timer=30,y=player.y*TILE_SIZE})return end update_auto_aim()if player.auto_target_index then local target=enemies[player.auto_target_index]if target and target.alive then projectiles[#projectiles+1]={x=player.x*TILE_SIZE+4,y=player.y*TILE_SIZE+4,target_x=target.x*TILE_SIZE+4,target_y=world_to_screen_y(target.y)*TILE_SIZE+4,speed=4,damage=player.atk+2,arrived=false,enemy_index=player.auto_target_index}player.arrow_count=player.arrow_count-1 table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="SHOOT!",color=YELLOW,timer=30,y=player.y*TILE_SIZE})end else table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="NO TARGET",color=WHITE,timer=30,y=player.y*TILE_SIZE})end player.turn=false player.last_move_time=current_time return end if (dx~=0 or dy~=0)and current_time-player.last_move_time>player.move_delay then local new_x=player.x+dx local new_y=player.y+dy if player.confused_this_turn then dx=-dx dy=-dy new_x=player.x+dx new_y=player.y+dy table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="CONFUSED!",color=5,timer=30,y=player.y*TILE_SIZE-10})end new_x=math.max(2,math.min(GRID_W-3,new_x))new_y=math.max(0,math.min(GRID_H-1,new_y))local world_player_y=screen_to_world_y(new_y)if is_walkable(new_x,world_player_y)then local enemy_hit=false for i,e in ipairs(enemies)do if e.alive and e.x==new_x and e.y==world_player_y then attack_enemy(i)enemy_hit=true break end end if not enemy_hit then player.x=new_x player.y=new_y player.turn=false player.last_move_time=current_time check_chest()if dy<0 and player.y<4 then camera_y=camera_y-1 player.y=player.y+1 update_depth()check_map_generation()elseif dy>0 and player.y>GRID_H-5 then camera_y=camera_y+1 player.y=player.y-1 update_depth()check_map_generation()end else player.last_move_time=current_time-player.move_delay+5 end else if (current_time-player.last_move_time)>player.move_delay+5 then table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="BLOCKED",color=RED,timer=15,y=player.y*TILE_SIZE})player.last_move_time=current_time end end end end function check_map_generation()local buffer=20 local highest_visible=camera_y if highest_visiblelowest_generated-buffer then generate_downward()end end function generate_upward()local start_y=highest_generated-20 local end_y=highest_generated-1 for y=start_y,end_y do generate_row(y)end highest_generated=start_y end function generate_downward()local start_y=lowest_generated+1 local end_y=lowest_generated+20 for y=start_y,end_y do generate_row(y)end lowest_generated=end_y end function use_potion()if player.potion_count>0 then player.hp=math.min(player.max_hp,player.hp+30)player.potion_count=player.potion_count-1 table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="+30 HP",color=GREEN,timer=40,y=player.y*TILE_SIZE})else table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="NO POTIONS",color=RED,timer=30,y=player.y*TILE_SIZE})end end function check_chest()local player_world_y=screen_to_world_y(player.y)for _,chest in ipairs(chests)do if not chest.opened and chest.x==player.x and chest.y==player_world_y then chest.opened=true if chest.has_item then spawn_item(chest.x,chest.y)table.insert(particles,{x=chest.x*TILE_SIZE,world_y=chest.y,text="TREASURE!",color=YELLOW,timer=40,y=world_to_screen_y(chest.y)*TILE_SIZE})else table.insert(particles,{x=chest.x*TILE_SIZE,world_y=chest.y,text="EMPTY",color=WHITE,timer=30,y=world_to_screen_y(chest.y)*TILE_SIZE})end end end end function update_depth()local new_depth=math.abs(math.floor(camera_y/4))if new_depth~=current_depth then current_depth=new_depth end end function try_attack()local target_x,target_y=player.x,screen_to_world_y(player.y)if player.direction==0 then target_y=target_y-1 elseif player.direction==1 then target_x=target_x+1 elseif player.direction==2 then target_y=target_y+1 else target_x=target_x-1 end for i,e in ipairs(enemies)do if e.alive and e.x==target_x and e.y==target_y then attack_enemy(i)return end end table.insert(particles,{x=target_x*TILE_SIZE,world_y=target_y,text="MISS",color=WHITE,timer=20,y=world_to_screen_y(target_y)*TILE_SIZE})end function attack_enemy(index)local e=enemies[index]local base_dmg=math.max(1,player.atk-e.def)local final_dmg=base_dmg if e.type=="iron_slime"then final_dmg=math.max(1,math.floor(base_dmg*0.5))end e.hp=e.hp-final_dmg local dmg_color=RED if e.type=="iron_slime"then dmg_color=12 elseif e.type=="fire_slime"then dmg_color=2 elseif e.type=="chaos_slime"then dmg_color=5 end table.insert(particles,{x=e.x*TILE_SIZE,world_y=e.y,text="-"..final_dmg,color=dmg_color,timer=30,y=world_to_screen_y(e.y)*TILE_SIZE})if e.hp<=0 then e.alive=false player.exp=player.exp+e.exp check_level_up()local drop_chance=30 if e.type=="iron_slime"then drop_chance=40 end if e.type=="fire_slime"then drop_chance=35 end if e.type=="chaos_slime"then drop_chance=50 end if math.random(100)=player.exp_next then player.level=player.level+1 player.exp=player.exp-player.exp_next player.exp_next=math.floor(player.exp_next*1.5)player.max_hp=player.max_hp+20 player.hp=player.max_hp player.atk=player.atk+2 player.def=player.def+1 if player.level%10==0 then player.max_hp=player.max_hp+50 player.hp=player.max_hp table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="10 LVL BONUS +50 HP!",color=GREEN,timer=60,y=player.y*TILE_SIZE})end table.insert(particles,{x=player.x*TILE_SIZE,world_y=screen_to_world_y(player.y),text="LEVEL UP!",color=BRIGHT_BLUE,timer=60,y=player.y*TILE_SIZE})for i=1,8 do table.insert(particles,{x=player.x*TILE_SIZE+math.random(-8,8),world_y=screen_to_world_y(player.y),text="+",color=GREEN,timer=40,y=player.y*TILE_SIZE+math.random(-10,5)})end end end function move_enemies()for _,e in ipairs(enemies)do if e.alive then local screen_y=world_to_screen_y(e.y)if screen_y>=-3 and screen_ymath.abs(dy)then move_x=dx>0 and 1 or -1 else move_y=dy>0 and 1 or -1 end if move_x>0 then e.direction=1 elseif move_x<0 then e.direction=3 elseif move_y>0 then e.direction=2 elseif move_y<0 then e.direction=0 end local nx,ny=e.x+move_x,e.y+move_y attempt_enemy_move(e,nx,ny)end elseif e.behavior=="chaotic"then if math.random(100)<30 then local nx,ny=e.x,e.y local dir=math.random(0,3)if dir==0 then ny=ny-1 elseif dir==1 then nx=nx+1 elseif dir==2 then ny=ny+1 else nx=nx-1 end e.direction=dir attempt_enemy_move(e,nx,ny)end else if math.random(100)<25 then local nx,ny=e.x,e.y if e.behavior=="random"then if math.random(100)<20 then e.direction=math.random(0,3)end end if e.direction==0 then ny=ny-1 elseif e.direction==1 then nx=nx+1 elseif e.direction==2 then ny=ny+1 else nx=nx-1 end attempt_enemy_move(e,nx,ny)end end end end end for i=#enemies,1,-1 do if not enemies[i].alive then table.remove(enemies,i)end end player.turn=true player.last_move_time=time()end function attempt_enemy_move(e,nx,ny)if is_walkable(nx,ny)then local player_world_y=screen_to_world_y(player.y)if nx==player.x and ny==player_world_y then local dmg=math.max(1,e.atk-player.def)if e.type=="fire_slime"then dmg=dmg+e.burn_damage player_effects.burning=math.max(player_effects.burning,8)for i=1,3 do table.insert(particles,{x=player.x*TILE_SIZE+math.random(-8,8),world_y=player_world_y,text="~",color=math.random(2,3),timer=30,y=player.y*TILE_SIZE+math.random(-5,5)})end elseif e.type=="chaos_slime"and math.random(100)<30 then player_effects.confused=math.max(player_effects.confused,5)for i=1,2 do table.insert(particles,{x=player.x*TILE_SIZE+math.random(-8,8),world_y=player_world_y,text="?",color=5,timer=30,y=player.y*TILE_SIZE+math.random(-5,5)})end end player.hp=player.hp-dmg table.insert(particles,{x=player.x*TILE_SIZE,world_y=player_world_y,text="-"..dmg,color=RED,timer=30,y=player.y*TILE_SIZE})check_game_over()else local blocked=false for _,other in ipairs(enemies)do if other~=e and other.alive and other.x==nx and other.y==ny then blocked=true break end end if not blocked then e.x=nx e.y=ny end end end end function update_auto_aim()local range=4 local player_world_y=screen_to_world_y(player.y)player.auto_target_index=nil local closest_dist=range*range+1 for i,e in ipairs(enemies)do if e.alive then local dx=e.x-player.x local dy=e.y-player_world_y local dist_sq=dx*dx+dy*dy if dist_sq<=closest_dist then player.auto_target_index=i closest_dist=dist_sq end end end end function update_projectiles()for i=#projectiles,1,-1 do local p=projectiles[i]if not p.arrived then local dx=p.target_x-p.x local dy=p.target_y-p.y local dist=math.sqrt(dx*dx+dy*dy)if dist