═нлллл┬┬┬╛╙╙╙╛┬┬┬╛ллл╛люл╛люл╛люлллЛН┬┬лН╙╙юН┬╗юНл╛юлю╛ююю╛ююю╛ююнлллл┬┬┬╛╙╙╙╛┬┬┬╛ллл╛ллл╛люл╛люлллЛН┬┬лН╙╙юН┬╗юНл╛юлл╛ююю╛ююю╛юю╛ллл╛╙╙╙╛╙╛╙╛╙йл╛╙╙╙▄┬┬┬люлнллнл╛л╙╙юЛ╛╙юН╙╙юН╙╙юН┬┬лНюЛНллНН╛ллл╛╙╙╙╛╙╛╙╛╙йл╛╙╙╙▄┬┬┬люлнллнл╛л╙╙юЛ╛╙юН╙╙юН╙╙юН┬┬лНюЛНллНН >H?П┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬░≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥─≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┬≤┬≥┬≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┬┬┬≥≥┬┴┬≥┬≤┴┬≤≥≥─≥┴·≥И"·≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┴ы┴²┬²≤≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┴ыщщ≥┴ы≤щ┬ы█≤щ█≥≥─И2#▓>3Д≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬≤л█²ь²≤≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┴ыщл┴≤щыл≤м▄ыэ█≥≥─ИCD▓N#3≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥Ъ─≥л█┬щ┴≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┬ыэ┴ы█ыл≤м▄иэ█≥≥─≥>3≥NЦ>≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥8─┴м█ь²┬≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┴ыыэ≤щ≤≤л┬и▄иэщ≤≥─≥НХ≥>#Ц≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥8─ыл°щ┴²≤≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┴ыщэы█┬ыл²мэыэщ≤≥─≥≥≥≥┴"·≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥Ъ─≥щ²≥┬²≤≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≤щ█ы┬┴ыщ²щщ≤щ┴≥≥─≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┴┬┬┬≥┬≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥┴┬≤┬≥≥┬┬┬┬┬┴┬≤≥≥─≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥─┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬ъщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщщолллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллэиэл²иэлэллэи²л≥и°мэ°мм≥ылллллллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл°ь°щыщ°щ°лл°≤≤°ыщ°ь°█ыищ≤лллллллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл°≤≥²х°²≥≥лл°┬≤°и°²┬≥█≥и°ылллллллл олллллллллллллллллллллллллллллл<<ллл<<лллллллллллллллллллллллллллллллллллллллллллллллл°ь²²ь°²┬≤лл°²²²≥≥°ы≤э≤мэмлллллллл олллллллллллллллллллллллллллллл##блл##цллээллллллллллллллллллллллллллллллллллллллллллл°ь°щ≥ы°ь≥лл°э°²ы²²и²л≤л°млллллллл олллллллллллллллллллллллллллллл#"блл#"бллэщмллллллллллллллллллллллллллллллллллллллллллэмэлщмэмщллэлээмээмэлщлэмлллллллл олллллллллллллллллллллллллллллл<"длл,"длллщлллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллCллллBллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙йллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл╙╙з╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙з╙╙йллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл╙╙з╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙з╙╙йллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл╙╙з╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙з╙╙йллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙й╙╙з╙╙йллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллDDдDDдDDдDDдDDдDDдDDдDDдллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллDDдDDдDDдDDдDDдDDдDDдDDдщщллщлллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллDDдDDдDDдDDдDDдDDдDDдDDдщщлщмлллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллDDдDDдDDдDDдDDдDDдDDдDDдщщлщллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллDDдDDдDDдDDдDDдDDдDDдDDдллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллэмэщмлэлэщллэлэщллэлэщллщлщщлллл оллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллэмэщмлэмэщллэлэщллщлщщллщлщщлллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллэмлэщмэмлэщлэмлэщлщмлщщлщллщщлллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллэмлэщмэмлэщмэмлщщлщллщщлщллщщлллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмлэмэщмлщлэщллщлщщллщлщщлмщлллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмлэмэщмлэлэщллщлщщллщлщщллщлллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмэмлэщмэмлэщлэмлщщлщллщщлщллллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмэмлэщмэмлэщлщллщщлщллщщлщллллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллэ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥млллллллллллллллллллэмэщмлщмэщмлщлщщллщлщщллщлщщлллл оллллллллщщщщщщщщщщщ²≥≥≥≥≥≥≥ыллллллллллллллллллллллэщщщ²≥≥≥ыщщщщщщщмлллллллллллллллллллэмэщмлэмэщллэлэщллщлщщллщлщщлллл олллллллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллллллллллллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллэмлэщмэмлэщлэмлэщлщллщщлщллщщлллл олллллллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллллллллллллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллэмлэщмэмлэщмэмлщщлщллщщлщллщщлллл олллллллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллллллллллллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллллллллллллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллллллллллллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллэщмлэмэщмлщмэщллщлщщллщлщщллщлллл олллллллллллллллллллэ≥≥≥≥≥≥≥ылллллLDDDDдллDDDDDлллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллэщмлэмэщмлэлэщллщлщщллщлщщллщлллл олллллллллллллллллллэ≥≥≥≥≥≥≥ыллллл<3333цлл33333лллл°≥≥≥≥≥≥≥иллллллллллллллллллллллллллэщмэмлэщмэмлэщлэллщщлщллщщлщллллл оллллллллллллллллщщщ²≥≥≥╘щщщмллллл<3333цлл33333лллл°≥≥≥≥≥≥≥ыщщщщщщщмллллллллллллллллллэщмэмлэщмэмлэщлщмлщщлщллщщлщллллл олллллллллллллллэ≥≥≥≥≥≥≥ыллллллллл<3333цлл33333лллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллэ≥≥≥≥≥≥≥ыллллллллл<3333цлл33333лллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллэ≥≥≥≥≥≥≥ылллллллллLDD3333333CDDлллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥млллллллллллллллллллэмэщмлэмэщмлщлщщллщлщщллщлщщлллл олллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллл3333333цлллллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥млллллллллллллллллллэмэщмлэмэщллщлэщллщлщщллщлщщлллл олллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллл3333333цлллллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэмлэщмэмлэщлэмлэщлщллщщлщллщщлллл олллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллл3333333цлллллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэмлэщмэмлэщмэмлщщлщмлщщлщллщщлллл олллллллллллллллэ≥≥≥≥≥≥≥ылллллллллллл3333333цлллллл°≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллл≥≥≥ыллллщщщ╜≥≥≥≥≥≥≥илллллллл3333333цлллллл°≥≥≥≥≥≥≥ыщщщщщщщ²≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллл олллллллэ≥≥≥╘лллллллэ≥≥≥≥≥≥≥ылллллллл3333333цлллллл°≥≥≥≥≥≥≥иллллллл²≥≥≥мллллллллллллллэщмлэмэщмлэмэщллщлщщллщлщщллщлллл олллллллэ≥≥≥ылллллллэ≥≥≥≥≥≥≥ылллллллл3333333цлллллл°≥≥≥≥≥≥≥иллллллл²≥≥≥мллллллллллллллэщмлэмэщмлщлэщллщлщщллщлщщллщлллл олллллллэ≥≥≥ылллллллэ≥≥≥≥≥≥≥ылллллллл3333333цлллллл°≥≥≥≥≥≥≥иллллллл²≥≥≥мллллллллллллллэщмэмлэщмэмлэщлэллщщлщллщщлщллллл олллллллэ≥≥≥ылллллллэ≥≥≥≥≥≥≥ылллллллл3333333цлллллл°≥≥≥≥≥≥≥иллллллл²≥≥≥мллллллллллллллэщмэммэщмэмлэщлэмлщщлщмлщщлщллллл олллллллэ≥≥≥ылллллллэ≥≥≥≥≥≥≥ыллллл<3333Cлл33333лллл°≥≥≥≥≥≥≥иллллллл²≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллл олллллллэ≥≥≥ылллллллэ≥≥≥≥≥≥≥ыллллл<3333цлл33333лллл°≥≥≥≥≥≥≥иллллллл²≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллл олллллллэ≥≥≥ылллллллэ≥≥≥≥≥≥≥ыллллл<3333цлл33333лллл°≥≥≥≥≥≥≥иллллллл²≥≥≥млллллллллллллллэмэщмлэмэщмлэлщщллщлщщллщлщщлллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ыллллллллл<3333цлл33333лллллллл²≥≥≥≥≥≥≥≥≥≥≥млллллллллллллллллллщмэщмлщмэщллщлэщллщлщщлмщлщщлллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ыллллллллл<3333цлл33333лллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэмлэщмэмлэщлэмлэщлщллщщлщллщщлллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэмлэщмэллэщлэллэщлэллэщлщллщщлллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмлэмэщмлэлэщллщлщщллщлщщллщлллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмэммэщмлмлэщллмлщщлмщлщщлмщлллл олллллллллллэ≥≥≥≥≥≥≥≥≥≥≥ылллллллллллллллллллллллллллллл°≥≥≥≥≥≥≥≥≥≥≥мллллллллллллллллллэщмэмлэщмэмлэщлэллщщлщллщщлщллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл олллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл `fffffffffffffffffffffffffffff·╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙╙ нллллллллллллллллллллллллллллЛННННННННННННННННННННННННННННч`фmmffffffffffffffffffffffffff░к ╜≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥оллллллллллллллллллллллллллллЭялЛ`фllffffffffffffffffffffffffff░л ╛≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ олC<333333333333333333333333цЭаэм!`флlfffffffлэffVллэfffffffffff░йл ≥≥≥≥≥≥ил╛≥≥йлл╛≥≥≥≥≥≥≥≥≥≥ оLC4333333CлL33CлL3333333333цЭалэ!лл!ллллл!`VлfffffffVлэffжллэfffffffffff░к╜╜≥≥≥≥≥≥йл╛≥≥йлл╛≥≥≥≥≥≥≥≥≥≥ олл4333333CлL33CлL3333333333цЭаэм!ллАллллл!`fлfffffffллэfVлэfжэffffffffff░л ╛≥≥≥≥≥илл╛≥йл╛╙ ≥≥≥≥≥≥≥≥≥≥ олC433333CллL3CллL3333333333цЭалэ!лллННрлл!`ffffffffVллэfVлэfжэffffffffff░╙≥ ≥≥≥≥≥илл╛≥йл╛≥≥≥≥≥≥≥≥≥≥≥≥ н33333333CллL3CллL3333333333цЭ!Н!лллАлл!`fffffffffжлэffжллэfffffffffff░≥≥≥≥≥≥≥≥╘йл╛≥йллл╛≥≥≥≥≥≥≥≥≥≥ н333333333CлL33CлL3333333333цЭБлл!лл.!`fffffffffVлэffжллэfffffffffff░ ≥≥≥≥≥≥≥≥ил╛≥йллл╛ ≥≥≥≥≥≥≥≥≥ н333333333CлL33CлL3333333333цЭ!ллрлл!`fffffffffVлэfVлэfжэffffffffff░ ≥≥≥≥≥≥≥≥ил╛≥йл╛╙й╛≥≥≥≥≥≥≥≥≥ н333333333CлL33CлL3333333333цЭ!лл!лл"!`fffffffffVлэfVлэfжэffffffffff░ ≥≥≥≥≥≥≥╘йл╛ йл╛╙й╛≥≥≥≥≥≥≥≥≥ н333333333CлL33CлL3333333333цЭБлл.рлл!`ffffffffVлллэfжллэfffffffffff░ ≥≥≥≥≥≥≥иллл╛╘йлл╛ ≥≥≥≥≥≥≥≥≥ н33333333CлллLCлллL333333333цЭ!лллл"лл"!`fffffffffлллэfVллэfffffffffff░ ≥≥≥≥≥≥≥иллл╛≥йлл╛≥≥≥≥≥≥≥≥≥≥ н33333333CлллLCлллL333333333цЭ!лллл"лл!`fffffffffffffffffffffffffffff░ ≥≥≥≥≥≥≥≥╙╙╙ ≥╘╙╙ ≥≥≥≥≥≥≥≥≥≥ н333333333333333333333333333цЭ""""""!`fffffffffffffffffffffffffffff░ ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥ оллллллллллллллллллллллллллллЭ!!`fffffffffffffffffffffffffffffp≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥yоллллллллллллллллллллллллллллЭ▒└-- title: Multiply -- author: Leslie Clemence e Camila -- desc: Multiply is an educational game designed to teach children multiplication tables from 0 to 10. It works progressively, allowing parents or teachers to track the child's development until they fully master the tables. -- script: lua -- ============================== -- CONSTANTES -- ============================== local W,H=240,136 -- Estados de tela local ST={SP=1,MN=2,MD=3,PL=4,WN=5,SC=6,RC=7,US=8,NE=9,PG=10,CF=11,LG=12} -- Botoes TIC-80 -- No Trimui os botoes fisicos mapeiam invertidos: -- Fisico A Б├▓ TIC-80 btn(5) (B) -- Fisico B Б├▓ TIC-80 btn(4) (A) -- Fisico X Б├▓ TIC-80 btn(7) (Y) -- Fisico Y Б├▓ TIC-80 btn(6) (X) local B={UP=0,DN=1,LT=2,RT=3,A=5,B=4,X=7,Y=6} -- Labels dos botoes fisicos para as 4 respostas -- Layout Trimui: Y(esq) X(cima) A(dir) B(baixo) -- Mapeamento: YБ├▓resp1 XБ├▓resp2 AБ├▓resp3 BБ├▓resp4 local BMAP={B.Y,B.X,B.A,B.B} -- btn id por opcao local BLBL={"Y","X","A","B"} -- label por opcao -- Cores (indices da paleta customizada) local C={ BG=0, -- azul meia-noite (fundo escuro) PURP=1, -- roxo header BLDK=2, -- azul escuro (numeros) BLUE=3, -- azul blocos GRN=4, -- verde (acerto, botao A) GOLD=5, -- dourado (pontos, estrelas) ORA=6, -- laranja (operador x) PINK=7, -- rosa (vidas, erro) PRPL=8, -- roxo claro (botao D) BGLT=9, -- fundo claro pergunta LAV=10, -- lavanda (fundo grade) GRLT=11, -- cinza claro (blocos vazios) WHT=12, -- branco GRAY=13, -- cinza texto AMB=14, -- ambar (botao C) BLBT=15 -- azul botao B } -- Cores por faixa de 10 blocos na grade (10 faixas) local BANDS={C.BLUE,C.GOLD,C.GRN,C.ORA,C.PINK, C.PRPL,C.BLBT,C.AMB,C.GRAY,C.GOLD} -- Cores dos 4 botoes de resposta local ABTN={C.GRN,C.BLBT,C.AMB,C.PRPL} -- Mensagens de vitoria (rotativas) local WMSGS={ pt={"INCRIVEL!","MUITO BEM!","ARRASOU!","GENIAL!","UAU!","OTIMO!","SHOW!"}, en={"AWESOME!","GREAT JOB!","YOU ROCK!","GENIUS!","WOW!","NICE!","SUPER!"} } local PM={ MAGIC=250, VER=251, COUNT=252, ACTIVE=253, LANG=254, MAX=4, META0=0, META_STEP=12, PROG0=64, PROG_STEP=25, NAME_LEN=8, TOTAL_Q=121 } local CHS=" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" local POW3={1,3,9,27,81} -- ============================== -- PALETA CUSTOMIZADA (16 cores) -- ============================== local function setPalette() local p={ 0x1A,0x1A,0x2E, 0x4A,0x30,0xB0, 0x15,0x65,0xC0, 0x21,0x96,0xF3, 0x4C,0xAF,0x50, 0xFF,0xD7,0x00, 0xFF,0x6B,0x00, 0xE9,0x1E,0x63, 0x9C,0x27,0xB0, 0xFD,0xFC,0xFF, 0xE8,0xE3,0xF8, 0xCF,0xC9,0xE8, 0xFF,0xFF,0xFF, 0x55,0x55,0x55, 0xFF,0x98,0x00, 0x1E,0x88,0xE5 } for i=0,47 do poke(0x3FC0+i,p[i+1]) end end -- ============================== -- ESTADO GLOBAL -- ============================== local state=ST.LG local tick=0 local splashT=0 local menuIdx=1 local modeIdx=1 local langIdx=1 local langSel=1 local langFirst=true local G={ mode="SEQ",order={},qPos=1,total=121, a=0,b=0,ans=0, opts={0,0,0,0},cOpt=1,sel=1, lives=3,score=0,correct=0,errors=0, aFill=0,aSpd=1, fbT=0,fbOk=false, shX=0,shT=0, hi=0,done=false } local conf={} local winT=0 local dStars={} local scInit=false local usel=1 local nbuf={} local ncur=1 local nmode="NEW" local cAct="" local nErr="" local nErrT=0 local U={ count=0, active=1, users={}, prog={} } local LANGS={"pt","en"} local LANG={ cur="pt" } local L={ pt={ splash_subtitle="TABUADA 0 A 10", splash_press="APERTE A", user_select_title="SELECIONE USUARIO", user_new="+ NOVO USUARIO", user_hi="HI:%d", user_select_hint="A CONFIRMA B MENU", name_new_title="NOVO USUARIO", name_edit_updown="UP/DOWN MUDA LETRA", name_edit_lr="LEFT/RIGHT MUDA POS", name_edit_max="MAX 8 CHARS", name_label="NOME: %s", name_save_hint="A SALVA B VOLTA", err_limit_users="LIMITE DE USUARIOS", err_name_empty="NOME VAZIO", err_name_exists="NOME JA EXISTE", err_no_space="SEM ESPACO", err_generic="ERRO", progress_title="PROGRESSO", progress_done="ACERTOS JA FEITOS: %d", progress_pending="ERROS PARA REVER: %d", progress_new="NAO RESPONDIDAS: %d", hint_back="B VOLTA", confirm_title="CONFIRMACAO", confirm_reset_all="APAGAR TODOS OS PROGRESSOS?", confirm_reset_user="REINICIAR ESTE USUARIO?", confirm_yes_no="A SIM B NAO", menu_title_1="MULTIPLICANDO", menu_title_2="COM MAGIA", menu_play="JOGAR", menu_switch_user="TROCAR USUARIO", menu_progress="PROGRESSO", menu_reset_user="REINICIAR USUARIO", menu_reset_all="REINICIAR TUDO", menu_language="IDIOMA", menu_records="RECORDES", menu_user="USUARIO: %s", menu_confirm_back="A CONFIRMA B VOLTA", mode_title="COMO QUER JOGAR?", mode_seq="SEQUENCIAL", mode_seq_hint1="1 2 3 ...", mode_seq_hint2="0x0 A 10x10", mode_seq_hint3="EM ORDEM", mode_rnd="ALEATORIO", mode_rnd_hint1="? ? ?", mode_rnd_hint2="ORDEM MISTA", mode_rnd_hint3="SURPRESA!", mode_select_hint="Y/LEFT SEQ X/RIGHT RND", mode_confirm_back="A CONFIRMA B VOLTA", q_howmany="QUANTOS?", q_wait="= ?", q_try_again="TENTE DE NOVO!", q_was="ERA %d", win_correct="VOCE ACERTOU!", win_points="+%d PONTOS", win_bonus="BONUS VIDAS +%d", win_next="A PROXIMA", score_title="FIM DE JOGO", score_points="PONTOS: %d", score_hits="ACERTOS: %d", score_errors="ERROS: %d", score_record="RECORDE: %d", score_any="QUALQUER BOTAO", records_title="RECORDES", records_best="MELHOR PLACAR", records_any="QUALQUER BOTAO P/ VOLTAR", lang_title="IDIOMA", lang_pt="PORTUGUES", lang_en="INGLES", lang_saved="SALVO" }, en={ splash_subtitle="TIMES TABLE 0 TO 10", splash_press="PRESS A", user_select_title="SELECT USER", user_new="+ NEW USER", user_hi="HI:%d", user_select_hint="A CONFIRM B MENU", name_new_title="NEW USER", name_edit_updown="UP/DOWN CHANGE LETTER", name_edit_lr="LEFT/RIGHT MOVE POS", name_edit_max="MAX 8 CHARS", name_label="NAME: %s", name_save_hint="A SAVE B BACK", err_limit_users="USER LIMIT", err_name_empty="EMPTY NAME", err_name_exists="NAME EXISTS", err_no_space="NO SPACE", err_generic="ERROR", progress_title="PROGRESS", progress_done="CORRECT DONE: %d", progress_pending="ERRORS TO REVIEW: %d", progress_new="NOT ANSWERED: %d", hint_back="B BACK", confirm_title="CONFIRM", confirm_reset_all="DELETE ALL PROGRESS?", confirm_reset_user="RESET THIS USER?", confirm_yes_no="A YES B NO", menu_title_1="MULTIPLY", menu_title_2="WITH MAGIC", menu_play="PLAY", menu_switch_user="SWITCH USER", menu_progress="PROGRESS", menu_reset_user="RESET USER", menu_reset_all="RESET ALL", menu_language="LANGUAGE", menu_records="RECORDS", menu_user="USER: %s", menu_confirm_back="A CONFIRM B BACK", mode_title="HOW DO YOU WANT TO PLAY?", mode_seq="SEQUENTIAL", mode_seq_hint1="1 2 3 ...", mode_seq_hint2="0x0 TO 10x10", mode_seq_hint3="IN ORDER", mode_rnd="RANDOM", mode_rnd_hint1="? ? ?", mode_rnd_hint2="MIXED ORDER", mode_rnd_hint3="SURPRISE!", mode_select_hint="Y/LEFT SEQ X/RIGHT RND", mode_confirm_back="A CONFIRM B BACK", q_howmany="HOW MANY?", q_wait="= ?", q_try_again="TRY AGAIN!", q_was="IT WAS %d", win_correct="YOU GOT IT!", win_points="+%d POINTS", win_bonus="LIFE BONUS +%d", win_next="A NEXT", score_title="GAME OVER", score_points="POINTS: %d", score_hits="HITS: %d", score_errors="ERRORS: %d", score_record="HIGH SCORE: %d", score_any="ANY BUTTON", records_title="RECORDS", records_best="BEST SCORE", records_any="ANY BUTTON TO RETURN", lang_title="LANGUAGE", lang_pt="PORTUGUESE", lang_en="ENGLISH", lang_saved="SAVED" } } -- ============================== -- UTILIDADES -- ============================== local function cl(v,lo,hi) if vhi then return hi end return v end local function has(t,v) for i=1,#t do if t[i]==v then return true end end return false end local function shuf(t) for i=#t,2,-1 do local j=math.random(1,i) t[i],t[j]=t[j],t[i] end end local function metaBase(slot) return PM.META0+(slot-1)*PM.META_STEP end local function progBase(slot) return PM.PROG0+(slot-1)*PM.PROG_STEP end local function qid(a,b) return a*11+b+1 end local function qfromid(id) local i=id-1 return i//11,i%11 end local function trimName(s) return (s:gsub("^%s+",""):gsub("%s+$","")) end local function chPos(ch) local p=CHS:find(ch,1,true) return p or 1 end local function nameToCodes(name) local t={} name=trimName((name or ""):upper()) for i=1,PM.NAME_LEN do local c=name:sub(i,i) t[i]=chPos(c) end return t end local function codesToName(t) local s="" for i=1,PM.NAME_LEN do local p=cl(t[i] or 1,1,#CHS) s=s..CHS:sub(p,p) end return trimName(s) end local function canonName(s) return codesToName(nameToCodes(s or "")) end local function isProgDone(p) for i=1,PM.TOTAL_Q do if p[i]~=1 then return false end end return true end local function decodeProg(slot) local out={} local pb=progBase(slot) for g=0,24 do local v=pmem(pb+g) for k=1,5 do local idx=g*5+k if idx<=PM.TOTAL_Q then local st=v%3 out[idx]=st v=(v-st)//3 end end end return out end local function encodeProg(slot,p) local pb=progBase(slot) for g=0,24 do local v=0 for k=5,1,-1 do local idx=g*5+k local st=(idx<=PM.TOTAL_Q) and cl(p[idx] or 0,0,2) or 0 v=v*3+st end pmem(pb+g,v) end end local function resetProg(slot) local p={} for i=1,PM.TOTAL_Q do p[i]=0 end encodeProg(slot,p) end local function saveUserMeta(slot,u) local b=metaBase(slot) pmem(b,1) local nm=nameToCodes(u.name or "") local n=codesToName(nm) pmem(b+1,#n) for i=1,PM.NAME_LEN do pmem(b+1+i,nm[i]) end pmem(b+10,u.hi or 0) end local function loadUsers() U.users={} if pmem(PM.MAGIC)~=20260411 then for slot=1,PM.MAX do local b=metaBase(slot) for i=0,PM.META_STEP-1 do pmem(b+i,0) end local pb=progBase(slot) for i=0,PM.PROG_STEP-1 do pmem(pb+i,0) end end pmem(PM.MAGIC,20260411) pmem(PM.VER,1) pmem(PM.COUNT,0) pmem(PM.ACTIVE,1) pmem(PM.LANG,1) end U.count=cl(pmem(PM.COUNT),0,PM.MAX) U.active=cl(pmem(PM.ACTIVE),1,PM.MAX) local c=0 for slot=1,PM.MAX do local b=metaBase(slot) local used=pmem(b) if used==1 then local nm={} for i=1,PM.NAME_LEN do nm[i]=cl(pmem(b+1+i),1,#CHS) end local name=codesToName(nm) if name=="" then name="ALUNO "..slot end U.users[#U.users+1]={slot=slot,name=name,hi=pmem(b+10)} c=c+1 end end U.count=c if U.count==0 then U.active=1 end end local function saveUsersMeta() pmem(PM.COUNT,U.count) pmem(PM.ACTIVE,U.active) end local function activeUser() for i=1,#U.users do if U.users[i].slot==U.active then return U.users[i],i end end if #U.users>0 then U.active=U.users[1].slot saveUsersMeta() return U.users[1],1 end return nil,nil end local function findByName(name) local nn=canonName(name) for i=1,#U.users do if canonName(U.users[i].name)==nn then return i end end return nil end local function createUser(name) if U.count>=PM.MAX then return nil,"err_limit_users" end local n=canonName(name) if n=="" then return nil,"err_name_empty" end if findByName(n) then return nil,"err_name_exists" end local free=nil for slot=1,PM.MAX do if pmem(metaBase(slot))~=1 then free=slot break end end if not free then return nil,"err_no_space" end local u={slot=free,name=n,hi=0} saveUserMeta(free,u) resetProg(free) U.users[#U.users+1]=u U.count=#U.users U.active=free saveUsersMeta() U.prog=decodeProg(free) return u,nil end local function saveActiveProg() local u=activeUser() if not u then return end encodeProg(u.slot,U.prog) end local function loadActiveProg() local u=activeUser() if not u then U.prog={} for i=1,PM.TOTAL_Q do U.prog[i]=0 end return end U.prog=decodeProg(u.slot) end local function resetActiveProgress() local u=activeUser() if not u then return end for i=1,PM.TOTAL_Q do U.prog[i]=0 end encodeProg(u.slot,U.prog) u.hi=0 saveUserMeta(u.slot,u) end local function resetAllUsers() for slot=1,PM.MAX do local b=metaBase(slot) for i=0,PM.META_STEP-1 do pmem(b+i,0) end local pb=progBase(slot) for i=0,PM.PROG_STEP-1 do pmem(pb+i,0) end end U.users={} U.prog={} U.count=0 U.active=1 saveUsersMeta() end local function tr(k) local d=L[LANG.cur] or L.pt return (d and d[k]) or (L.pt and L.pt[k]) or k end local function trf(k,...) return string.format(tr(k),...) end local function loadLang() local v=pmem(PM.LANG) if v>=1 and v<=#LANGS then langIdx=v else langIdx=1 end LANG.cur=LANGS[langIdx] end local function saveLang() pmem(PM.LANG,langIdx) end local function setLang(i) langIdx=cl(i,1,#LANGS) LANG.cur=LANGS[langIdx] end -- Mede largura de texto sem desenhar (fora da tela) local function tw(s,sc) return print(s,0,-200,0,false,sc or 1) end -- Print centralizado na tela inteira local function pc(s,y,c,sc) sc=sc or 1 print(s,(W-tw(s,sc))//2,y,c,false,sc) end -- Print centralizado em regiao [rx, rx+rw] local function pcr(s,rx,rw,y,c,sc) sc=sc or 1 print(s,rx+(rw-tw(s,sc))//2,y,c,false,sc) end -- Print com sombra local function ps(s,x,y,c,sc) sc=sc or 1 print(s,x+1,y+1,C.BG,false,sc) print(s,x,y,c,false,sc) end -- Print centralizado com sombra local function pcs(s,y,c,sc) sc=sc or 1 local x=(W-tw(s,sc))//2 ps(s,x,y,c,sc) end -- Retangulo com cantos arredondados (1px) local function rr(x,y,w,h,c) rect(x+1,y,w-2,h,c) rect(x,y+1,w,h-2,c) end -- ============================== -- ESTRELAS DECORATIVAS -- ============================== local function initStars(n) dStars={} for i=1,n do dStars[i]={ x=math.random(4,W-4), y=math.random(4,H-4), ph=math.random(0,628)/100, sp=math.random(30,100)/100 } end end local function drawStars(bc) bc=bc or C.PURP for _,s in ipairs(dStars) do local b=math.sin(tick*0.04*s.sp+s.ph) local c=b>0.3 and C.GOLD or (b>-0.3 and C.WHT or bc) pix(s.x,s.y,c) end end -- ============================== -- ICONES DESENHADOS POR PIXEL -- ============================== local function drawHeart(cx,cy,c) pix(cx-1,cy-2,c) pix(cx+1,cy-2,c) for dx=-2,2 do pix(cx+dx,cy-1,c) end for dx=-2,2 do pix(cx+dx,cy,c) end for dx=-1,1 do pix(cx+dx,cy+1,c) end pix(cx,cy+2,c) end local function drawStar5(cx,cy,c) pix(cx,cy-2,c) for dx=-2,2 do pix(cx+dx,cy-1,c) end for dx=-1,1 do pix(cx+dx,cy,c) end pix(cx-1,cy+1,c) pix(cx+1,cy+1,c) end -- ============================== -- PERSISTENCIA DE RECORDES -- ============================== local function loadRec() local u=activeUser() G.hi=u and (u.hi or 0) or 0 end local function saveRec() if G.score>G.hi then G.hi=G.score local u=activeUser() if u then u.hi=G.hi saveUserMeta(u.slot,u) end end end -- ============================== -- GERACAO DE PERGUNTAS -- ============================== local function buildOrder(m) local pend={} local fresh={} local all={} for a=0,10 do for b=0,10 do local id=qid(a,b) local q={a=a,b=b,id=id} all[#all+1]=q local st=U.prog[id] or 0 if st==2 then pend[#pend+1]=q elseif st~=1 then fresh[#fresh+1]=q end end end if #pend==0 and #fresh==0 then for i=1,#all do fresh[i]=all[i] end end if m=="RND" then shuf(pend) shuf(fresh) end local l={} for i=1,#pend do l[#l+1]=pend[i] end for i=1,#fresh do l[#l+1]=fresh[i] end return l end local function genOpts(ans) local o={ans} -- Distratores proximos ao resultado (mais desafiador) local r=math.max(4,math.floor(ans*0.3)+2) local att=0 while #o<4 and att<80 do att=att+1 local d=math.random(-r,r) if d==0 then d=(math.random()>0.5) and 1 or -1 end local v=cl(ans+d,0,100) if not has(o,v) then o[#o+1]=v end end -- Fallback garantir 4 opcoes local fb=0 while #o<4 do if not has(o,fb) then o[#o+1]=fb end fb=fb+1 end shuf(o) local ci=1 for i=1,4 do if o[i]==ans then ci=i break end end return o,ci end local function loadQ() if G.qPos>G.total then G.done=true saveRec() state=ST.SC scInit=false return end local q=G.order[G.qPos] G.a=q.a G.b=q.b G.ans=q.a*q.b G.opts,G.cOpt=genOpts(G.ans) G.sel=1 G.lives=3 G.aFill=0 -- Velocidade da animacao: ~0.75s para qualquer resultado G.aSpd=math.max(0.5,G.ans/45) G.fbT=0 G.fbOk=false G.shX=0 G.shT=0 end local function resetGame(m) G.mode=m G.order=buildOrder(m) G.qPos=1 G.total=#G.order G.score=0 G.correct=0 G.errors=0 G.done=false loadQ() state=ST.PL end -- ============================== -- CONFETES (particulas) -- ============================== local function addConf() conf={} for i=1,60 do conf[i]={ x=W/2+math.random(-40,40), y=H/2+math.random(-10,10), vx=math.random(-40,40)/10, vy=math.random(-35,-8)/10, c=({C.GOLD,C.GRN,C.ORA,C.PINK,C.PRPL,C.BLUE,C.AMB})[math.random(1,7)], s=math.random(1,2), life=math.random(60,140) } end end local function updConf() for i=#conf,1,-1 do local p=conf[i] p.x=p.x+p.vx p.y=p.y+p.vy p.vy=p.vy+0.12 p.vx=p.vx*0.98 p.life=p.life-1 if p.life<=0 or p.y>H+4 then table.remove(conf,i) end end end local function drawConf() for _,p in ipairs(conf) do rect(p.x,p.y,p.s,p.s,p.c) end end -- ============================== -- TELA: HEADER (12px topo) -- ============================== local function drawHeader() rect(0,0,W,12,C.PURP) -- Estrela + pontos (esquerda) drawStar5(5,5,C.GOLD) print(tostring(G.score),10,3,C.GOLD) -- Barra de progresso (centro) local bx,bw=56,100 rect(bx,4,bw,5,C.BG) local pct=(G.qPos-1)/G.total local fw=math.floor((bw-2)*pct) if fw>0 then rect(bx+1,5,fw,3,C.GOLD) end -- Percentual local ptxt=math.floor(pct*100).."%" print(ptxt,bx+bw+2,3,C.WHT) -- Contador pergunta (direita) local ql=G.qPos.."/"..G.total print(ql,W-tw(ql)-4,3,C.WHT) end -- ============================== -- TELA: AREA DA PERGUNTA (esquerda 168px) -- ============================== local function drawQuestionArea() local ox=math.floor(G.shX+0.5) -- offset do shake rect(0,12,168,108,C.BGLT) line(168,12,168,119,C.LAV) -- Coracoes (vidas) centralizados for i=1,3 do drawHeart(74+(i-2)*10+ox,19,i<=G.lives and C.PINK or C.GRLT) end -- A x B centralizado no painel esquerdo (scale 8 = ~48px) local as=tostring(G.a) local bs=tostring(G.b) local nsc=8 -- escala dos numeros local xsc=5 -- escala do operador local aw=tw(as,nsc) local xw=tw("x",xsc) local bw=tw(bs,nsc) local sp=4 local totalW=aw+sp+xw+sp+bw local sx=(168-totalW)//2+ox -- Numeros verticalmente centrados no painel (y12-y120 = 108px) local ny=12+(108-6*nsc)//2 -- centro vertical local xy=12+(108-6*xsc)//2 print(as,sx,ny,C.BLDK,false,nsc) print("x",sx+aw+sp,xy,C.ORA,false,xsc) print(bs,sx+aw+sp+xw+sp,ny,C.BLDK,false,nsc) -- Pulsacao do "=?" quando grade ainda animando if G.aFill0.2) and C.PRPL or C.GRAY pcr(tr("q_wait"),0,168,100,pulse) end -- Mensagem de feedback (erro) if G.fbT>0 and not G.fbOk then local msg=G.lives>0 and tr("q_try_again") or trf("q_was",G.ans) if G.fbT%8<5 then pcr(msg,0,168,106,C.PINK) end end end -- ============================== -- TELA: GRADE VISUAL (direita 72px) -- ============================== local function drawGridArea() rect(168,12,72,108,C.LAV) print(tr("q_howmany"),174,14,C.PURP) local gx,gy=173,24 local sz,gp=5,1 local fill=math.floor(G.aFill) for i=0,99 do local r=i//10 local co=i%10 local x=gx+co*(sz+gp) local y=gy+r*(sz+gp) if i0 and fill%10==0 and G.aFill1 then line(x,y,x,y+15,C.BG) end -- Letra do botao fisico (Y/X/A/B) print(BLBL[i],x+2,y+1,C.WHT) -- Numero da opcao centralizado local nt=tostring(G.opts[i]) local nw=tw(nt,2) print(nt,x+(bw-nw)//2,y+3,C.WHT,false,2) end end -- ============================== -- LOGICA: RESPOSTA -- ============================== local function startWin() winT=0 addConf() state=ST.WN end local function doAnswer() if G.fbT>0 then return end local q=G.order[G.qPos] local id=q and q.id or qid(G.a,G.b) if G.sel==G.cOpt then -- Acertou! Bonus por vidas restantes local bonus=G.lives*5 G.score=G.score+10+bonus G.correct=G.correct+1 U.prog[id]=1 saveActiveProg() G.fbOk=true startWin() else -- Errou: shake + perder vida G.errors=G.errors+1 U.prog[id]=2 saveActiveProg() G.fbOk=false G.fbT=40 G.shT=14 G.lives=G.lives-1 if G.lives<=0 then G.fbT=60 end end end -- ============================== -- UPDATE: TELA DE JOGO -- ============================== local function updatePlay() tick=tick+1 -- Animacao de preenchimento da grade if G.aFillG.ans then G.aFill=G.ans end end -- Animacao de shake (erro) if G.shT>0 then G.shT=G.shT-1 G.shX=math.sin(G.shT*1.5)*3*(G.shT/12) else G.shX=0 end -- Timer de feedback if G.fbT>0 then G.fbT=G.fbT-1 if G.fbT==0 and G.lives<=0 then -- Sem vidas: avanca para proxima G.qPos=G.qPos+1 loadQ() end end end -- ============================== -- TELA 1: SPLASH -- ============================== local function drawSplash() cls(C.BG) splashT=splashT+1 tick=tick+1 drawStars(C.PURP) -- Titulo com sombra pcs(tr("menu_title_1"),34,C.GOLD,2) pcs(tr("menu_title_2"),52,C.AMB,2) -- Linha decorativa line(60,68,180,68,C.PURP) pc(tr("splash_subtitle"),76,C.WHT) -- Prompt piscante if splashT>30 and (splashT//18)%2==0 then pc(tr("splash_press"),100,C.GRLT) end if btnp(B.A) or btnp(B.X) or btnp(B.Y) or splashT>180 then if U.count==0 then nmode="FIRST" nbuf=nameToCodes("") ncur=1 state=ST.NE else state=ST.US end end end local function drawUserSelect() cls(C.BGLT) pcs(tr("user_select_title"),8,C.PURP,2) local total=#U.users+1 usel=cl(usel,1,total) for i=1,total do local by=32+(i-1)*18 local bx,bw,bh=26,188,14 local txt if i<=#U.users then local u=U.users[i] txt=u.name.." "..trf("user_hi",u.hi) else txt=tr("user_new") end if i==usel then rr(bx,by-1,bw,bh+2,C.GRN) pcr(txt,bx,bw,by+3,C.WHT) else rr(bx,by,bw,bh,C.WHT) pcr(txt,bx,bw,by+3,C.GRAY) end end pc(tr("user_select_hint"),122,C.GRAY) if btnp(B.UP) then usel=cl(usel-1,1,total) end if btnp(B.DN) then usel=cl(usel+1,1,total) end if btnp(B.B) and U.count>0 then state=ST.MN end if btnp(B.A) or btnp(B.X) then if usel<=#U.users then U.active=U.users[usel].slot saveUsersMeta() loadActiveProg() loadRec() state=ST.MN else nmode="NEW" nbuf=nameToCodes("") ncur=1 state=ST.NE end end end local function drawNameEdit() cls(C.LAV) if nErrT>0 then nErrT=nErrT-1 end pc(tr("name_new_title"),10,C.PURP) pc(tr("name_edit_updown"),26,C.GRAY) pc(tr("name_edit_lr"),34,C.GRAY) pc(tr("name_edit_max"),42,C.GRAY) local x0=40 local curName=codesToName(nbuf) for i=1,PM.NAME_LEN do local x=x0+(i-1)*20 local ch=CHS:sub(nbuf[i],nbuf[i]) rr(x,56,16,20,i==ncur and C.GRN or C.WHT) pcr(ch,x,16,63,i==ncur and C.WHT or C.BLDK,2) end pc(trf("name_label",(curName~="" and curName or "_")),90,C.BLDK) if nErrT>0 then pc(nErr,102,C.PINK) end pc(tr("name_save_hint"),118,C.GRAY) if btnp(B.LT) then ncur=cl(ncur-1,1,PM.NAME_LEN) end if btnp(B.RT) then ncur=cl(ncur+1,1,PM.NAME_LEN) end if btnp(B.UP) then nbuf[ncur]=cl(nbuf[ncur]+1,1,#CHS) end if btnp(B.DN) then nbuf[ncur]=cl(nbuf[ncur]-1,1,#CHS) end if btnp(B.B) then if nmode=="FIRST" and U.count==0 then -- no primeiro uso nao pode voltar sem criar usuario else state=ST.US end end if btnp(B.A) or btnp(B.X) then local name=codesToName(nbuf) local u,err=createUser(name) if u then nErr="" nErrT=0 loadRec() menuIdx=1 state=ST.MN else nErr=tr(err or "err_generic") nErrT=90 end end end local function drawProgress() cls(C.BGLT) local u=activeUser() if not u then state=ST.US return end pcs(tr("progress_title"),8,C.PURP,2) pc(u.name,24,C.BLUE) local done,pending,newq=0,0,0 for i=1,PM.TOTAL_Q do local st=U.prog[i] or 0 if st==1 then done=done+1 elseif st==2 then pending=pending+1 else newq=newq+1 end end rr(28,34,184,56,C.WHT) rectb(28,34,184,56,C.GOLD) pc(trf("progress_done",done),44,C.GRN) pc(trf("progress_pending",pending),58,C.PINK) pc(trf("progress_new",newq),72,C.BLUE) pc(tr("hint_back"),118,C.GRAY) if btnp(B.B) or btnp(B.A) or btnp(B.X) or btnp(B.Y) then state=ST.MN end end local function drawConfirm() cls(C.BG) local t=(cAct=="RST_ALL") and tr("confirm_reset_all") or tr("confirm_reset_user") pcs(tr("confirm_title"),24,C.GOLD,2) pc(t,56,C.WHT) pc(tr("confirm_yes_no"),92,C.AMB) if btnp(B.B) then state=ST.MN end if btnp(B.A) or btnp(B.X) then if cAct=="RST_ALL" then resetAllUsers() nmode="FIRST" nbuf=nameToCodes("") ncur=1 state=ST.NE else resetActiveProgress() loadRec() state=ST.MN end end end -- ============================== -- TELA 2: MENU PRINCIPAL -- ============================== local function drawMenu() cls(C.BGLT) local ml={ tr("menu_play"), tr("menu_switch_user"), tr("menu_progress"), tr("menu_reset_user"), tr("menu_reset_all"), tr("menu_language"), tr("menu_records") } pcs(tr("menu_title_1"),2,C.PURP,2) pcs(tr("menu_title_2"),14,C.ORA,2) line(60,28,180,28,C.LAV) for i=1,#ml do local by=32+(i-1)*10 local bwid,bh=170,8 local bx=(W-bwid)//2 if i==menuIdx then rr(bx,by-1,bwid,bh+2,C.GRN) pcr(ml[i],bx,bwid,by+1,C.WHT) else rr(bx,by,bwid,bh,C.GRLT) pcr(ml[i],bx,bwid,by+1,C.GRAY) end end local au=activeUser() if au then pc(trf("menu_user",au.name),110,C.PURP) end pc(tr("menu_confirm_back"),122,C.GRAY) if btnp(B.UP) then menuIdx=cl(menuIdx-1,1,#ml) end if btnp(B.DN) then menuIdx=cl(menuIdx+1,1,#ml) end if btnp(B.A) or btnp(B.X) then if menuIdx==1 then state=ST.MD elseif menuIdx==2 then state=ST.US elseif menuIdx==3 then state=ST.PG elseif menuIdx==4 then cAct="RST_USER" state=ST.CF elseif menuIdx==5 then cAct="RST_ALL" state=ST.CF elseif menuIdx==6 then langSel=langIdx state=ST.LG else state=ST.RC end end end -- ============================== -- TELA 3: SELECAO DE MODO -- ============================== local function drawMode() cls(C.LAV) pc(tr("mode_title"),6,C.PURP) local cw,ch=104,76 local gap=8 local sx=(W-cw*2-gap)//2 for i=1,2 do local cx=sx+(i-1)*(cw+gap) local cy=24 local sel=(i==modeIdx) local bg=sel and C.WHT or C.BGLT local bd=sel and (i==1 and C.BLUE or C.AMB) or C.GRLT rr(cx,cy,cw,ch,bg) rectb(cx,cy,cw,ch,bd) if sel then rectb(cx-1,cy-1,cw+2,ch+2,bd) end if i==1 then pcr(tr("mode_seq"),cx,cw,cy+8,C.BLDK) pcr(tr("mode_seq_hint1"),cx,cw,cy+26,C.BLUE) pcr(tr("mode_seq_hint2"),cx,cw,cy+46,C.GRAY) pcr(tr("mode_seq_hint3"),cx,cw,cy+58,C.GRAY) else pcr(tr("mode_rnd"),cx,cw,cy+8,C.ORA) pcr(tr("mode_rnd_hint1"),cx,cw,cy+26,C.AMB) pcr(tr("mode_rnd_hint2"),cx,cw,cy+46,C.GRAY) pcr(tr("mode_rnd_hint3"),cx,cw,cy+58,C.GRAY) end end pc(tr("mode_select_hint"),112,C.GRAY) pc(tr("mode_confirm_back"),122,C.GRAY) if btnp(B.LT) or btnp(B.Y) then modeIdx=1 end if btnp(B.RT) or btnp(B.X) then modeIdx=2 end if btnp(B.B) then state=ST.MN end if btnp(B.A) then resetGame(modeIdx==1 and "SEQ" or "RND") end end -- ============================== -- TELA 4: JOGO PRINCIPAL -- ============================== local function drawPlay() cls(C.BG) updatePlay() drawHeader() drawQuestionArea() drawGridArea() drawAnswers() -- Input (bloqueado durante feedback) if G.fbT<=0 then -- D-pad: navegar + confirmar com UP if btnp(B.LT) then G.sel=cl(G.sel-1,1,4) end if btnp(B.RT) then G.sel=cl(G.sel+1,1,4) end if btnp(B.UP) then doAnswer() end -- Botoes diretos: Y=1, X=2, A=3, B=4 for i=1,4 do if btnp(BMAP[i]) then G.sel=i doAnswer() end end end if btnp(B.DN) then saveRec() state=ST.MN end end -- ============================== -- TELA 5: VITORIA (overlay) -- ============================== local function drawWin() cls(C.BG) winT=winT+1 tick=tick+1 updConf() drawConf() drawStars(C.PURP) -- Mensagem rotativa de parabens local msgs=WMSGS[LANG.cur] or WMSGS.pt local mi=((G.qPos-1)%#msgs)+1 local yy=winT<12 and 26 or 20 pcs(msgs[mi],yy,C.GOLD,2) pc(tr("win_correct"),42,C.WHT) -- Pontos ganhos com bonus local bonus=G.lives*5 local earned=10+bonus if winT>10 then pcs(trf("win_points",earned),60,C.AMB,2) end if bonus>0 and winT>20 then pc(trf("win_bonus",bonus),80,C.GRN) end -- Avanca automaticamente apos ~3s (60 FPS) if winT>=180 then G.qPos=G.qPos+1 loadQ() -- loadQ pode mudar state para ST.SC se acabaram perguntas if state~=ST.SC then state=ST.PL end end end -- ============================== -- TELA 6: PLACAR FINAL -- ============================== local function drawScore() cls(C.BG) tick=tick+1 if not scInit then initStars(20) scInit=true end drawStars(C.PURP) pcs(tr("score_title"),4,C.GOLD,2) -- Card de estatisticas rr(28,24,184,60,C.PURP) rectb(28,24,184,60,C.GOLD) pc(trf("score_points",G.score),30,C.GOLD) pc(trf("score_hits",G.correct),44,C.WHT) pc(trf("score_errors",G.errors),56,C.WHT) pc(trf("score_record",G.hi),70,C.AMB) -- Estrelas de avaliacao (0-5) local acc=G.total>0 and G.correct/G.total or 0 local ns=0 if acc>=0.95 then ns=5 elseif acc>=0.85 then ns=4 elseif acc>=0.70 then ns=3 elseif acc>=0.50 then ns=2 elseif acc>0 then ns=1 end local stX=(W-5*12)//2 for i=1,5 do drawStar5(stX+(i-1)*12+2,93,i<=ns and C.GOLD or C.GRAY) end pc(tr("score_any"),120,C.WHT) if btnp(B.A) or btnp(B.B) or btnp(B.X) or btnp(B.Y) then state=ST.MN end end -- ============================== -- TELA 7: RECORDES -- ============================== local function drawRecords() cls(C.BGLT) pcs(tr("records_title"),10,C.PURP,2) local u=activeUser() if u then pc(trf("menu_user",u.name),26,C.GRAY) end rr(44,36,152,44,C.WHT) rectb(44,36,152,44,C.GOLD) pcr(tr("records_best"),44,152,42,C.GRAY) pcr(tostring(G.hi),44,152,56,C.GOLD,2) pc(tr("records_any"),114,C.GRAY) if btnp(B.A) or btnp(B.B) or btnp(B.X) or btnp(B.Y) then state=ST.MN end end local function drawLanguage() cls(C.BGLT) pcs(tr("lang_title"),10,C.PURP,2) local opts={tr("lang_pt"),tr("lang_en")} for i=1,#opts do local by=46+(i-1)*22 local bx,bw,bh=50,140,16 local sel=(i==langSel) rr(bx,by,bw,bh,sel and C.GRN or C.WHT) pcr(opts[i],bx,bw,by+4,sel and C.WHT or C.GRAY) end pc(tr("menu_confirm_back"),114,C.GRAY) if btnp(B.UP) then langSel=cl(langSel-1,1,#LANGS) end if btnp(B.DN) then langSel=cl(langSel+1,1,#LANGS) end if btnp(B.B) and not langFirst then state=ST.MN end if btnp(B.A) or btnp(B.X) then setLang(langSel) saveLang() if langFirst then langFirst=false splashT=0 state=ST.SP else state=ST.MN end end end -- ============================== -- LOOP PRINCIPAL TIC-80 -- ============================== function TIC() if state==ST.SP then drawSplash() elseif state==ST.MN then drawMenu() elseif state==ST.MD then drawMode() elseif state==ST.PL then drawPlay() elseif state==ST.WN then drawWin() elseif state==ST.SC then drawScore() elseif state==ST.RC then drawRecords() elseif state==ST.US then drawUserSelect() elseif state==ST.NE then drawNameEdit() elseif state==ST.PG then drawProgress() elseif state==ST.CF then drawConfirm() elseif state==ST.LG then drawLanguage() end end -- ============================== -- INICIALIZACAO -- ============================== setPalette() loadUsers() loadLang() if U.count>0 then loadActiveProg() loadRec() else for i=1,PM.TOTAL_Q do U.prog[i]=0 end end initStars(15) math.randomseed(time())