Files
PicoCalc/Bin/PicoCalc SD/lua/boxworld.lua
2026-03-01 15:25:55 +08:00

449 lines
24 KiB
Lua

-- BOXWORLD
-- original game and sprites by Jeng-Long Jiang, 1992
-- picocalc lua conversion by maple "mavica" syrup, 2025
local sprite_size = 20
local sprites = draw.loadBMPSprites("lua/boxworld.bmp", sprite_size, sprite_size)
local fg,bg = colors.fromRGB(255,255,255),colors.fromRGB(0,0,0)
local screen = nil
local quit = false
local function switch_screen(to)
screen = to
if screen.entry then screen.entry() end
end
local music = {
tick = 0.10,
instrument = sound.instrument(sound.presets.square),
notes = {
c = 0,
C = 1,
d = 2,
D = 3,
e = 4,
f = 5,
F = 6,
g = 7,
G = 8,
a = 9,
A = 10,
b = 11
},
tracks = {
intro = {
"l2o3el1<el2gl1el2>cl1<el2>el3dl1c<bafl3>c<bl2al1dl2fl1el2gl1fl2b>c",
"l3o1cga>cel2dl3c<l4bl3fa>cl2<a>c"
},
victory = {
"l2o2el1Gl2al3bl1>dl2ee",
"l3o1aGel1gl2de"
}
},
playing = nil
}
music.instrument.decay = 250
function music.perform()
if not music.playing then return end
local done_playing = true
for k,v in pairs(music.playing) do
local ch = music.channels[k]
local track = music.playing[k]
if ch.cursor <= #track then done_playing = false end
if ch.timer > 0 then ch.timer = ch.timer - 1 end
if ch.timer == 0 then
while ch.cursor <= #track do
local input = string.sub(track, ch.cursor, ch.cursor)
ch.cursor = ch.cursor + 1
if input == 'l' then
input = string.sub(track, ch.cursor, ch.cursor)
ch.cursor = ch.cursor + 1
ch.length = tonumber(input)
elseif input == 'o' then
input = string.sub(track, ch.cursor, ch.cursor)
ch.cursor = ch.cursor + 1
ch.octave = tonumber(input)
elseif input == '<' then
ch.octave = ch.octave - 1
elseif input == '>' then
ch.octave = ch.octave + 1
elseif music.notes[input] then
ch.timer = ch.length
sound.play(k-1, music.notes[input] + (ch.octave+2) * 12, music.instrument)
break
end
end
end
end
if done_playing then music.playing = nil sys.stopTimer() end
end
function music.play(track)
music.playing = track
music.channels = {}
for k,v in pairs(track) do
music.channels[k] = {}
music.channels[k].cursor = 1
music.channels[k].length = 4
music.channels[k].octave = 3
music.channels[k].timer = 0
end
sys.repeatTimer(music.tick * 1000, music.perform)
end
local game = {
level = 1,
levelstrings = {
"00111\n00131\n00121111\n11142431\n13246111\n111141\n000131\n000111\n",
"11111\n16221\n124410111\n124210131\n111211131\n011222231\n012221221\n012221111\n011111\n",
"01111111\n0122222111\n1141112221\n1262422421\n1233124211\n113312221\n011111111\n",
"01111\n11221\n16421\n114211\n112421\n134221\n133531\n111111\n",
"011111\n0162111\n0124221\n11121211\n13121221\n13422121\n13222421\n11111111\n",
"0001111111\n1111222221\n1222311121\n12121222211\n12124241321\n12122522121\n12314242121\n1122221212111\n0121113222261\n0122222112221\n0111111111111\n",
"0001111111\n0011221261\n0012221221\n0014242421\n0012411221\n1112421211\n133333221\n111111111\n",
"000111111\n011122221\n1132411211\n1334242261\n1332424211\n111111221\n000001111\n",
"0111111111\n0122112221\n0122242221\n0142111241\n0121333121\n11213331211\n12422422421\n12222212621\n11111111111\n",
"00111111\n00122221\n11144421\n16243321\n12433311\n1111221\n0001111\n",
"011110011111\n112210012221\n124211114221\n122433332421\n112222126211\n01111111111\n",
"0011111\n1112261\n12243211\n12234321\n11125421\n00122211\n0011111\n",
"001111\n001331\n0112311\n0122431\n11242211\n12214421\n12262221\n11111111\n",
"11111111\n12212221\n12433421\n16435211\n12433421\n12212221\n11111111\n",
"0111111\n11222211\n12424421\n13333331\n12442421\n11126111\n001111\n",
"00111111\n0012222111\n0012422221\n1112421121\n1333242221\n1333414211\n1111212421\n0001226221\n0001111111\n",
"111111\n122221\n1244411\n122133111\n112233421\n012622221\n011111111\n",
"0011111111\n0012221321\n0112243331\n0122421531\n1121141211\n1222422421\n1222122221\n1111111621\n0000001111\n",
"01111111\n01333321\n1113334111\n1224142421\n1244221421\n1222212221\n1111262111\n00011111\n",
"1111111\n1334331\n1331331\n1244421\n1224221\n1244421\n1221621\n1111111\n",
"000111111\n000123331\n111133331\n12211142111\n12424224421\n16242422221\n12221112221\n11111011111\n",
"11111111\n12222221\n12144221\n12333121\n113334211\n012112421\n014224221\n012212261\n011111111\n",
"0011111\n1112221111\n1222424221\n1242224261\n1114411111\n00122331\n00133331\n00111111\n",
"11111100011111\n12222111012231\n12242421013331\n12122421112231\n12244422242631\n11122422412231\n00122414213331\n00112222212231\n00011111111111\n",
"00000111111\n01111132221\n01221331121\n01224332221\n01221231211\n11121141221\n12422224421\n12141221221\n16221111111\n11111\n",
"0111111111\n0122211221111\n0124222222221\n0114111211221\n0122112521211\n012433333321\n112111232121\n122222411141\n122212222461\n111114121111\n000012221\n000011111\n",
"000000111111111\n000000122222221\n000000121212121\n000000122424121\n111111122242221\n133122112424121\n133222112424221\n133122112111111\n133121242421\n133222224221\n122111262111\n1111011111\n",
"00001111\n11111221\n1224242101111111\n1222422101535351\n1124242111353531\n0142422122535351\n0164242222353511\n0142422122535351\n1124242111353531\n1222422101535351\n1224242101111111\n11111221\n00001111\n",
"11111111\n13333331\n122421211\n124212421\n114242421\n012262221\n011111111\n",
"001111111111\n111222322221\n122211411221\n126432323411\n11241141121\n01222232221\n01111111111\n",
"000111111\n111132261\n122444221\n131131131\n122242221\n122431211\n11112221\n00011111\n",
"0111111\n0132331\n0132431\n11122411\n12422421\n12141121\n12226221\n11111111\n",
"0000111111\n001112222111\n00122214222111\n00122242224421\n00124421422221\n00112224222421\n11111121411111\n1336214221\n1313322411\n133334121\n133332221\n111111111\n",
"111111111111111\n122222212222221\n124214212411421\n121224212222221\n122211414114421\n121212333212221\n124223212342121\n124164333121221\n122223212322421\n121134111432121\n121243333321121\n122222222222221\n111111111111111\n",
"111111111\n122211221\n121242421\n122531221\n112136311\n1141115111\n1222222221\n1222112121\n1111112221\n0000011111\n",
"11111111\n12222221\n1244222111\n12242444211111\n112112333222211\n012161333111421\n012124333222221\n112124333421211\n12211111211121\n12222224222421\n11111111111221\n00000000001111\n",
"00011111\n00012621\n00014441\n11112221\n122231411\n124343231\n122131311\n11111111\n",
"111111111111\n133321222221\n133221211221\n133222221221\n133221241121\n133321424221\n111111224421\n011224244221\n016244422121\n011242112221\n001222222221\n001111111111\n",
"111111111\n122222221\n122424241\n112141121\n0123323311\n0113323321\n00121141211\n00142424221\n00122222261\n00111111111\n",
"111110000001111\n162211111111221\n112422222224221\n012121221111221\n012242221111411\n01421121242421\n11242241222221\n12221222222121\n12221111141111\n1111122212221\n0000133322421\n0000133331221\n0000133331111\n0000111111\n",
"0000011111\n0111112221\n0123324121\n0121352221\n1125314211\n124224221\n122211261\n111111111\n",
"1111101111111\n1222111221221\n1242222242621\n1121411311221\n0122333532421\n0124121312121\n0112222422221\n0012211111111\n001111\n",
"000000000111\n0000111111611\n00001333314211\n00001333312421\n00001333324221\n00001233312221\n111111211111211\n124242224221221\n122224422242421\n111242424221111\n001122242421\n000122111111\n0001111\n",
"00011111\n0111222111\n1122642421\n12211211211\n12431342221\n12131512221\n12433322111\n111412111\n0012221\n0011111\n",
"0000001111\n000000122111111\n000000122221221\n000000124422221\n111111141221221\n122132332111411\n122131534222221\n122131351212221\n124433331211111\n12642121121\n12444122221\n12222111111\n111111\n",
"1111\n122111\n12422111\n1242422111\n124242422111\n124242422221\n1242422122211\n1242211244421\n16211112222211\n11210134444431\n012111333333311\n012223555555531\n011113333333331\n000011111111111\n",
"1111111\n12612211111\n12442242221\n12213114121\n11413332221\n11233311411\n12211311221\n12242242221\n12212221221\n11111111111\n",
"00011111\n00012621\n00012421\n00014341\n011134311\n11234343111\n12243434221\n12222322221\n11111111111\n",
"1111111111111\n1224242435331\n1242424253331\n1224242435331\n1242424253331\n1224242435331\n1242424253331\n1224242435331\n1242424253331\n1224242435331\n1642424253331\n1111111111111\n",
"00000000000001\n00000000000011\n00000000000111\n000000000012221\n000111111112121\n001242424242221\n01121313131641\n111333333322211\n01121212121411\n001242424242221\n000111111112121\n000000000012221\n00000000000111\n00000000000011\n",
"1111111\n122342111\n123434221\n154343621\n123434211\n12234221\n11111111\n",
"00000000011111\n00000000012221\n1111111111252111\n1222222222232221\n1244445555433361\n1222222222232221\n1111111111252111\n00000000012221\n00000000011111\n",
"000001111\n1111112211111\n1642222422421\n1411124212121\n1221221242221\n1241222212111\n122421412221\n133333333321\n111111112221\n000000011111\n",
"0111111111\n0122211221111\n0124222222221\n0114111211221\n0122113421211\n012433333321\n112111322121\n122222411141\n122212222461\n111114121111\n000012221\n000011111\n",
"11111111111\n12222122221\n12464444421\n12222222221\n11111211111\n00013221\n00013221\n00013331\n00013221\n00011111\n",
"0011111\n0012621\n0012421\n111232111\n122252221\n125555521\n122252221\n111454111\n0012321\n0012521\n0012321\n0011111\n",
"11111111111111\n13222222222221\n13424242424221\n13111111111221\n13135242334511\n1312424253461\n1313224233441\n1311111111131\n1322222222221\n1314141414141\n1322222222221\n1111111111111\n",
"111111111111\n13322122222111\n13322124224221\n13322141111221\n13322226211221\n13322121224211\n11111121142421\n00124224242421\n00122221222221\n00111111111111\n",
"00000001111\n11111111221111\n12221133333221\n12242211333121\n11224221112121\n01212422122221\n01221242212221\n01222124221221\n01222212421211\n0111122124221\n0000112212421\n0000011612221\n0000001111111\n",
"11110000001111\n13311111111331\n15353333353531\n12424242424241\n14242464242421\n12424242424241\n14242424242421\n13535333335351\n13311111111331\n11110000001111\n",
"000011111\n000112221111\n000123352421\n111121312221\n122223531611\n12141141121\n12222242421\n11221222111\n011111111\n",
"111111\n122221\n124221111\n124533521\n125335421\n111122421\n000126221\n000111111\n",
"00011111\n111132211\n124343221\n164121421\n124323221\n111141421\n001323221\n001111111\n",
"111111111111\n122223332421\n124445552461\n122223332421\n111111111111\n",
"1111111111\n1122222221\n1222141421\n1244223431\n1261113331\n1111111111\n",
"01111\n012211111\n114211221\n122464221\n122211421\n1113112111\n0133342421\n0113322221\n0011111111\n",
"1111101111\n1333101221111\n1333111224221\n133331124224111\n113333112224221\n111333211242421\n121122221224221\n1221121211121111\n1242121422422221\n1224262422224221\n1222124244242111\n12211111122111\n121100001111\n111\n",
"1111111\n1323231\n1244421\n1346431\n1244421\n1323231\n1111111\n",
"0000001111\n1111111221\n1222224221\n1222411641\n1141333121\n0124333221\n01213231211\n01222121421\n01422422221\n01221111111\n01111\n",
"000111111111\n000122212221\n000122222221\n111115111211\n12223332221\n121215111411\n124222242221\n111116212221\n000011111111\n",
"11111\n13331011111\n13331112221\n133332224411111\n1333322122122211\n1331411112141221\n1124221222224421\n1224126242441221\n1242424212224211\n122212242112221\n111111222111111\n0000011111\n",
"111111111111111\n111312222221111\n113312422421221\n133312112421221\n133333221442221\n113333422221421\n111121111111221\n122242222222211\n122421224124211\n124111242124421\n122261221122221\n111111111111111\n",
"000000011111111\n000000012212221\n011111112443331\n012222222213331\n012111111413331\n112122222213331\n122121424211111\n12124242421\n12622421221\n11111424421\n00001222221\n00001111111\n",
"000000011111\n001111112221\n111222232421\n124221431411\n122122631221\n112111132221\n012422151111\n01211213221\n01222223121\n01114222221\n00012211111\n0001111\n",
"00001111\n111112211111\n122224222421\n122414112221\n111213532111\n0012333261\n0011214111\n00012221\n00011111\n",
"00011111111\n11112222321\n12242424321\n12231111311\n1243424261\n1223221111\n1111111\n",
"0011111\n0012221\n11143411111\n12223242221\n12114112621\n12223211111\n1112321\n0012221\n0011111\n",
"011111\n01262111111\n01213352221\n01233312221\n11411242421\n12221411111\n122242221\n111112121\n000012221\n000011111\n",
"00000111111\n000111222211\n000122211221\n011141122121\n112222233121\n122414153121\n12446213512111\n12244213312221\n11222213342221\n01114113212111\n000122111221\n000112222211\n00001111111\n",
"000001111111\n000001221221\n000001224421\n111111241221\n1333111212211\n1322122421221\n1322224242421\n1322122421221\n1333111212211\n111111242221\n000001621221\n000001111111\n",
"0000000000111111\n0000000000122221\n1111100011121121\n1332111112422121\n1332222242224121\n1332211211222121\n1332112421424121\n1332122222422121\n1332122421114221\n1332124242242111\n111211212422221\n001222216112421\n001111111112211\n00000000001111\n",
"00000001\n0000011111\n000111262111\n000122424221\n000125353521\n0011234243211\n01112535352111\n111122424221111\n000111111221\n00001100011\n",
"011111111111111\n0126252525212211\n0141225252212221\n0121252525222221\n0121225252211211\n012125252521121\n012122525221121\n012125252521121\n012122525221121\n0121252325211211\n1121111111111221\n1222222222222221\n1222111111111221\n1111100000001111\n",
"01111111111111\n01222212211221\n014442124422411\n012422122333321\n012242214311321\n012212412333311\n114242214311321\n124224264333321\n122211122111111\n1111101111\n",
"00000111111111\n00000122222221\n00000122414121\n01111112212421\n01222124224221\n11242222211121\n12221411112221\n12222421112111\n1111133261211\n0001333424421\n0001333122221\n0001333111111\n00011111\n",
"1111000001111\n122111111133111\n124242422133331\n124222442155531\n124242422133531\n122424242153531\n1124242423535311\n1224242423535361\n1224242421535311\n124242422133531\n124222442155531\n124242422133331\n122111111133111\n1111000001111\n",
"00000011111\n11111112221\n12221132221\n122413322111\n1122333144211111\n0124313422222221\n0124111411212421\n0122212222244121\n0114412114142221\n0133324624222111\n01333141222111\n013332211111\n01111111\n",
"0111100111111\n0122111122221\n1152225255221\n1242522225121\n1232221112221\n1111112221611\n1252325225521\n1222122212221\n1152225214121\n0122111112221\n0111100011111\n",
"0111111111\n0122212221\n0124444421\n1124242421\n1242262221\n12421111211\n12213333321\n11223333321\n01111111111\n",
"0001111111\n0001222221\n00012424211\n000111113311111\n111111335322421\n122464333314421\n122242141112221\n111112222222111\n0000111221111\n0000001221\n0000001111\n",
"11111\n1222111111\n1242332421\n1142334461\n0122332421\n0111111111\n",
"0011111\n001222111111\n111413222221\n124233312421\n162431542221\n111122221111\n000111111\n",
"000011111\n111112221\n122242621\n122421311111\n114211311221111\n012233333241221\n012411311221421\n012221311222221\n011124211111211\n000121422222421\n000122221112221\n000111111011111\n",
"1111111\n1225221\n1263421\n1243221\n1535551\n1225221\n1245421\n1223221\n1111111\n",
"00111111111\n00122221221\n11121422421111\n1224221133122111\n1212242133424221\n1244224133221221\n1122122333142221\n0142621333124221\n0122221333422211\n012114211122211\n01222422222111\n012211111111\n01111\n",
"0001111111111\n1111333333221\n1222333331221\n1221333333211\n112111141141\n16422424222111\n12442222112221\n12122441122121\n12224221244221\n12242242221421\n11112221242421\n00012221222221\n00011111111111\n",
"000000111111111\n000000122222221\n000000142444221\n000000122212421\n000000122246421\n000011142421211\n00001222414121\n11111212212221\n13332212412111\n133333222121\n133333124121\n111111112221\n000000011111\n",
"0111110111111\n0122211122221\n1124242142141\n12242624224211\n12122112133331\n12211242131131\n11224222233331\n01244214133331\n01222122214211\n0111112422221\n0000011112211\n000000001111\n",
"1111\n1221\n1221111111111\n1222211222221\n1331222244121\n133221122242111\n133122114124221\n133222126424221\n133122124242221\n123222124242111\n1221221222111\n12212222111\n111111111\n",
"00000000011111\n000000001222221\n0000000122411221\n0000001221222421\n1001001212212121\n0101001242422421\n0011111112141221\n001224242222221\n00163342553111\n000133333311111\n0000111111111111\n"
},
anim_timer = 0,
player_flip = 0,
player_sprites = {
U = {7, 8},
D = {5, 6},
L = {11, 12},
R = {9, 10},
W = {13, 13}
}
}
game.push_sound = sound.instrument(sound.drums.tom)
game.push_sound.volume = 0.5
game.push_sound.decay = 150
game.push_sound.sustain = 0
local title = {}
function title.input()
local state, _, code = keys.poll()
if state == keys.states.pressed then
if code == keys.left then
game.level = ((game.level - 2) % #game.levelstrings) + 1
screen.redraw = true
elseif code == keys.right then
game.level = ((game.level) % #game.levelstrings) + 1
screen.redraw = true
elseif code == keys.enter then
switch_screen(game)
elseif code == keys.esc then
quit = true
end
end
end
function title.entry()
draw.enableBuffer(false)
music.play(music.tracks.intro)
draw.clear()
screen.redraw = true
end
function title.draw()
-- boxworld logo
for j = 0, 1 do
for i = 0, 6 do
sprites:blit(160 - 70 + i * sprite_size, 80 + j * sprite_size, 14 + i + j * 7)
end
end
draw.text(160, 140, "Original by Jeng-Long Jiang, 1992",fg,bg,draw.align_center)
draw.text(160, 160, "Reprogram by maple \"mavica\" syrup, 2025",fg,bg,draw.align_center)
draw.text(160, 180, "Select level",fg,bg,draw.align_center)
draw.text(160, 190, " < " .. game.level .. " > ",fg,bg,draw.align_center)
end
function game.entry()
-- load level
game.leveltable = {}
local row = {}
local longest = 0
local str = game.levelstrings[game.level]
for i = 1, #str do
if str:sub(i,i) == '\n' then
table.insert(game.leveltable, row)
if #row > longest then longest = #row end
row = {}
elseif str:sub(i,i) == '6' then -- player
game.player_pos = {#row + 1, #game.leveltable + 1}
game.player_direction = "D"
table.insert(row, '2') -- empty floor under player
else
table.insert(row, str:sub(i,i))
end
end
game.draw_offset = {140 - longest/2*sprite_size, 140 - #game.leveltable/2*sprite_size}
game.moves = {}
collectgarbage()
draw.enableBuffer(1)
draw.clear()
screen.redraw = true
end
function game.draw()
for j = 1, #game.leveltable do
local row = game.leveltable[j]
for i = 1, #row do
local pos = {game.draw_offset[1] + i * sprite_size, game.draw_offset[2] + j * sprite_size}
if row[i] == "1" then -- wall
sprites:blit(pos[1], pos[2], 0)
elseif row[i] == "2" then -- floor
sprites:blit(pos[1], pos[2], 1)
elseif row[i] == "3" then -- floor with goal
sprites:blit(pos[1], pos[2], 1)
sprites:blit(pos[1], pos[2], 4)
elseif row[i] == "4" then -- box
sprites:blit(pos[1], pos[2], 2)
elseif row[i] == "5" then -- box on goal
sprites:blit(pos[1], pos[2], 3)
end
end
end
local pos = {
game.draw_offset[1] + game.player_pos[1] * sprite_size,
game.draw_offset[2] + game.player_pos[2] * sprite_size
}
sprites:blit(pos[1], pos[2], game.player_sprites[game.player_direction][game.player_flip+1])
if game.player_direction == "W" then
draw.text(160, 160, "You win !!!",fg,bg,draw.align_center)
draw.text(160, 170, "Press ENTER for next level",fg,bg,draw.align_center)
end
draw.text(0, 300, "Box World! #" .. game.level .. " - Moves: " .. #game.moves .. " ")
draw.text(0, 310, "(U)ndo, (R)estart, (ESC) Quit")
draw.blitBuffer()
end
function game.check_win()
for j = 1, #game.leveltable do
local row = game.leveltable[j]
for i = 1, #row do
if row[i] == "4" then -- box not on goal
return false -- quit as soon as found any
end
end
end
-- didn't quit? must mean we won
game.player_direction = "W"
music.play(music.tracks.victory)
end
function game.process_push(code)
if game.player_direction == "W" then return end -- don't move if we've already won
local ahead, ahead2
if code == keys.up then
game.player_direction = "U"
ahead = {game.player_pos[1], game.player_pos[2]-1}
ahead2 = {game.player_pos[1], game.player_pos[2]-2}
elseif code == keys.down then
game.player_direction = "D"
ahead = {game.player_pos[1], game.player_pos[2]+1}
ahead2 = {game.player_pos[1], game.player_pos[2]+2}
elseif code == keys.left then
game.player_direction = "L"
ahead = {game.player_pos[1]-1, game.player_pos[2]}
ahead2 = {game.player_pos[1]-2, game.player_pos[2]}
elseif code == keys.right then
game.player_direction = "R"
ahead = {game.player_pos[1]+1, game.player_pos[2]}
ahead2 = {game.player_pos[1]+2, game.player_pos[2]}
end
local whats_ahead = game.leveltable[ahead[2]]
if whats_ahead ~= nil then whats_ahead = whats_ahead[ahead[1]] end
local whats_ahead2 = game.leveltable[ahead2[2]]
if whats_ahead2 ~= nil then whats_ahead2 = whats_ahead2[ahead2[1]] end
if whats_ahead == '2' or whats_ahead == '3' then -- ahead is floor or empty goal
game.player_pos = ahead
table.insert(game.moves, string.lower(game.player_direction))
elseif whats_ahead == '4' or whats_ahead == '5' then -- ahead is box, whether or not on a goal
if whats_ahead2 == '2' or whats_ahead2 == '3' then -- box pushed onto floor or goal
sound.playPitch(2,1,game.push_sound)
local box_leaves = whats_ahead == '4' and '2' or '3'
local box_becomes = whats_ahead2 == '2' and '4' or '5'
game.player_pos = ahead
game.leveltable[ahead[2]][ahead[1]] = box_leaves
game.leveltable[ahead2[2]][ahead2[1]] = box_becomes
table.insert(game.moves, game.player_direction)
game.check_win()
end
end
screen.redraw = true
end
function game.process_undo()
if #game.moves < 1 then return false end
local return_to, pushed
local move = table.remove(game.moves)
game.player_direction = string.upper(move)
if string.upper(move) == 'D' then
return_to = {game.player_pos[1], game.player_pos[2]-1}
pushed = {game.player_pos[1], game.player_pos[2]+1}
elseif string.upper(move) == 'U' then
return_to = {game.player_pos[1], game.player_pos[2]+1}
pushed = {game.player_pos[1], game.player_pos[2]-1}
elseif string.upper(move) == 'R' then
return_to = {game.player_pos[1]-1, game.player_pos[2]}
pushed = {game.player_pos[1]+1, game.player_pos[2]}
elseif string.upper(move) == 'L' then
return_to = {game.player_pos[1]+1, game.player_pos[2]}
pushed = {game.player_pos[1]-1, game.player_pos[2]}
end
if move == string.upper(move) then -- if move was recorded upper means we moved a box
local what_box_became = game.leveltable[pushed[2]][pushed[1]]
local box_leaves = what_box_became == '4' and '2' or '3'
local box_becomes = game.leveltable[game.player_pos[2]][game.player_pos[1]] == '2' and '4' or '5'
game.leveltable[pushed[2]][pushed[1]] = box_leaves
game.leveltable[game.player_pos[2]][game.player_pos[1]] = box_becomes
end
game.player_pos = return_to
screen.redraw = true
end
function game.input()
local state, _, code = keys.poll()
if state == keys.states.pressed then
if code == keys.up or code == keys.down or code == keys.left or code == keys.right then
game.process_push(code)
elseif code == 'u' then
game.process_undo()
elseif code == 'r' then
game.entry()
elseif code == keys.esc then
switch_screen(title)
elseif game.player_direction == "W" and code == keys.enter then
-- go to next level when won and pressed enter
game.level = ((game.level) % #game.levelstrings) + 1
game.entry()
end
end
collectgarbage()
end
function game.update(now)
if game.player_direction ~= 'W' and now > game.anim_timer then
game.player_flip = (game.player_flip + 1) % 2
game.anim_timer = now + 1
screen.redraw = true
end
end
switch_screen(title)
while true do
now = os.clock()
if screen.input then screen.input() end
if quit then break end
if screen.update then screen.update(now) end
if screen.redraw and screen.draw then screen.draw() screen.redraw = false end
end