Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------------
- -- TURTLE-BASED SOKOBAN --
- ----------------------------
- --[[
- This file will print a standard sokoban level to
- a computer screen, or, if run on a turtle, will
- build the level, then leave the turtle in the
- starting position, allowing the turtle to be
- controlled remotely with buttons and a synced
- computer to play and solve the level. A level can
- be built horizontally (top-down), or vertically.
- Optimizations for building are close to maxed,
- vertical building is slower than horizontally.
- Currently turtles themselves check the level for
- valid moves by comparing blocks, but a faster
- gameplay will be created by storing logic internally
- based on the game board loaded. Using this same
- logic will also allow sokoban to be played text-based
- on any computer (with color if on an advanced computer).
- Please report any bugs found.
- Usage: Place this file in a location of your choosing.
- Place the file 'sokoban_levels.sok' in the directory
- listed below (default = ...), or change that path to
- the directory you placed the file into.
- --]]
- local args = { ... }
- --path where default levels are located
- local default = "rom/programs/sokoban/default.sok"
- local isTurtle = (turtle ~= nil)
- if #args < 1 then
- print("Usage: sokoban <level> [path] [-v]")
- print("Path is for custom levels.")
- print("Use -v to build a level vertically instead of horizontally.")
- print("If level doesn't exist in path, default level is loaded instead, located at:")
- print(default)
- return
- end
- local level = tonumber(args[1]) --level number
- local path, vert
- if #args > 1 then
- if args[2] == "-v" then vert = true
- else path = args[2] end
- if args[3] then
- if args[3] == "-v" and not vert then vert = true
- elseif args[3] ~= "-v" and not path then path = args[3]
- else print("args[3] ignored.") end
- end
- end
- lvl = { } --actual level data
- function isnumber(arg)
- local tot = 0
- if not arg then return false end
- for c in arg:gmatch("%d") do
- tot = tot + 1
- end
- if tot ~= #arg then return false
- else return true end
- end
- -------------------------------
- -- LEVEL LOADING / PARSING --
- -------------------------------
- function loadsok(lvl)
- if not fs.exists(default) then
- print("Default level pack missing!")
- return
- else
- f = io.open(default)
- local linetot = 0
- local levels = { }
- for line in f:lines() do
- linetot = linetot + 1
- levels[linetot] = line
- end
- f:close()
- if linetot == 0 then
- print("Default level pack is blank!")
- return
- elseif level < 1 or level > linetot then
- print("Level "..level.." doesn't exist!")
- return
- else
- local tmp = splitdata(levels[level])
- tmp = parsesok(tmp)
- return tmp
- end
- end
- end
- function splitdata(data)
- --split the level into multiple lines
- local tot = 0
- local split = { }
- for part in data:gmatch("[^|]+") do
- tot = tot + 1
- split[tot] = part
- end
- return split
- end
- function parsesok(data)
- local extended = { } --store the level in its full form
- for i = 1, #data do --for each line in puzzle
- local cur = nil --store numbers preceding symbols
- extended[i] = "" --initialize a new line in the extended array
- for c in data[i]:gmatch(".") do --for each character in the line
- if cur == nil and isnumber(c) then cur = c
- elseif isnumber(cur) and isnumber(c) then
- cur = cur..c --combine the two digits
- elseif isnumber(cur) and not isnumber(c) then
- --a number before a symbol, repeat the symbol
- local rep = ""
- if c == "-" then c = " " end
- for j = 1, tonumber(cur) do rep = rep..c end
- extended[i] = extended[i]..rep
- cur = nil
- else
- --a symbol with no number
- if c == "-" then c = " " end
- extended[i] = extended[i]..c
- end
- end
- end
- if not isTurtle then
- for i = 1, #extended do
- print(extended[i])
- end
- return
- else return extended end
- end
- if path then
- if not fs.exists(path) then
- print(path.." doesn't exist!")
- print("Loading default level "..level..".")
- loadsok(level)
- else
- f = io.open(path, "r")
- local linetot = 0
- local levels = { }
- for line in f:lines() do
- linetot = linetot + 1
- levels[linetot] = line
- end
- f:close()
- if linetot == 0 then
- print(path.." is blank!")
- print("Loading default level "..level..".")
- return loadsok(level)
- elseif level < 1 or level > linetot then
- print("Level "..level.." doesn't exist in "..args[2].."!")
- print("Loading default level "..level..".")
- loadsok(level)
- else
- lvl = splitdata(levels[level])
- parsesok(lvl)
- end
- end
- else
- lvl = loadsok(level)
- end
- if not isTurtle then return end
- ---------------------------
- -- NAVIGATION ROUTINES --
- ---------------------------
- posx = 0
- posy = 0
- posz = 0
- dir = 0
- path = 1
- function getInput()
- local input = io.read()
- if input == "exit" or input == "end" or input == "close" or input == "cancel" then
- return false
- end
- return true
- end
- function checkFuel()
- while turtle.getFuelLevel() == 0 do
- print("Out of fuel!")
- print("Please refuel and press enter to continue.")
- getInput()
- for i=1, 12 do
- turtle.select(i)
- if turtle.refuel() then break end
- end
- end
- end
- function turnR()
- turtle.turnRight()
- dir = dir + 1
- if dir >= 4 then dir = 0 end
- end
- function turnL()
- turtle.turnLeft()
- dir = dir - 1
- if dir < 0 then dir = 3 end
- end
- function efficTurn(destDir)
- --print("Current dir: "..dir)
- --print("Dest dir: "..destDir)
- if dir == destDir then return end
- if dir == destDir + 2 or dir == destDir - 2 then
- --print("turn 180")
- turnAround()
- elseif dir == destDir + 1 or dir == destDir - 3 then
- --print("turn left")
- turnL()
- elseif dir == destDir - 1 or dir == destDir + 3 then
- --print("turn right")
- turnR()
- end
- end
- function turnAround()
- turnR()
- turnR()
- end
- function safeForward()
- success = false
- while not success do
- success = turtle.forward()
- if not success then
- if turtle.getFuelLevel() > 0 then
- if path == 0 then
- print("Blocked attempting to move forward.")
- print("Please clear and press enter to continue.")
- elseif path == 1 and not turtle.dig() then
- print("Can't dig block to move forward.")
- print("Please clear and press enter to continue.")
- elseif path == 2 then
- print("Pausing current direction.")
- return false
- elseif path == 3 then
- print("Stopping current direction.")
- return true
- end
- if path ~= 1 then getInput() end
- else checkFuel() end
- end
- end
- return true
- end
- function safeBack()
- success = false
- while not success do
- success = turtle.back()
- if not success then
- if turtle.getFuelLevel() > 0 then
- if path == 0 then
- print("Blocked attempting to move back.")
- print("Please clear and press enter to continue.")
- elseif path == 1 then
- turnR()
- turnR()
- if not turtle.dig() then
- print("Can't dig block behind to move back.")
- print("Please clear and press enter to continue.")
- else return end
- elseif path == 2 then
- print("Pausing current direction.")
- return false
- elseif path == 3 then
- print("Stopping current direction.")
- return true
- end
- if path ~= 1 then getInput() end
- else checkFuel() end
- end
- end
- return true
- end
- function safeUp()
- success = false
- while not success do
- success = turtle.up()
- if not success then
- if turtle.getFuelLevel() > 0 then
- if path == 0 then
- print("Blocked attempting to move up.")
- print("Please clear and press enter to continue.")
- elseif path == 1 and not turtle.digUp() then
- print("Can't dig block to move up.")
- print("Please clear and press enter to continue.")
- elseif path == 2 then
- print("Pausing current direction.")
- return false
- elseif path == 3 then
- print("Stopping current direction.")
- return true
- end
- if path ~= 1 then getInput() end
- else checkFuel() end
- end
- end
- return true
- end
- function safeDown()
- success = false
- while not success do
- success = turtle.down()
- if not success then
- if turtle.getFuelLevel() > 0 then
- if path == 0 then
- print("Blocked attempting to move down.")
- print("Please clear and press enter to continue.")
- elseif path == 1 and not turtle.digDown() then
- print("Can't dig block to move down.")
- print("Please clear and press enter to continue.")
- elseif path == 2 then
- print("Pausing current direction.")
- return false
- elseif path == 3 then
- print("Stopping current direction.")
- return true
- end
- if path ~= 1 then getInput() end
- else checkFuel() end
- end
- end
- return true
- end
- function moveX(targetx)
- if targetx == posx then
- return true
- end
- if (dir ~= 1 and dir ~= 3) then -- check axis
- turnR()
- end
- while targetx > posx do
- if dir == 1 then
- if not safeForward() then return false end
- else
- if not safeBack() then return false end
- end
- posx = posx + 1
- end
- while targetx < posx do
- if dir == 3 then
- if not safeForward() then return false end
- else
- if not safeBack() then return false end
- end
- posx = posx - 1
- end
- return true
- end
- function moveY(targety)
- if targety == posy then
- return true
- end
- --don't need to change direction
- while targety > posy do
- if not safeUp() then return false end
- posy = posy + 1
- end
- while targety < posy do
- if not safeDown() then return false end
- posy = posy - 1
- end
- return true
- end
- function moveZ(targetz)
- if targetz == posz then
- return true
- end
- if (dir ~= 0 and dir ~= 2) then -- check axis
- turnR()
- end
- while targetz > posz do
- if dir == 0 then
- if not safeForward() then return false end
- else
- if not safeBack() then return false end
- end
- posz = posz + 1
- end
- while targetz < posz do
- if dir == 2 then
- if not safeForward() then return false end
- else
- if not safeBack() then return false end
- end
- posz = posz - 1
- end
- return true
- end
- function gototarg(targx, targy, targz)
- local startDir = dir
- local finishX, finishY, finishZ = false, false, false
- local attempts = 0
- while not finishX or not finishY or not finishZ do
- if dir == 0 or dir == 2 then
- if not finishZ then finishZ = moveZ(targz) end
- if not finishX then finishX = moveX(targx) end
- elseif dir == 1 or dir == 3 then
- if not finishX then finishX = moveX(targx) end
- if not finishZ then finishZ = moveZ(targz) end
- end
- if not finishY then finishY = moveY(targy) end
- if path == 3 then break end --only run once when in 'dumb' mode
- if path == 2 then attempts = attempts + 1 end
- if (not finishX or not finishY or not finishZ) and path == 2 and attempts > 3 then
- print("Could not find a safe path to destination.")
- return
- end
- end
- efficTurn(startDir)
- --print("Arrived at destination.")
- end
- ----------------------
- -- LEVEL BUILDING --
- ----------------------
- local SWALL, SPLAYER, SPLAYERGOAL, SBOX, SBOXGOAL, SGOAL, SFLOOR = "#", "@", "+", "$", "*", ".", "-"
- local WALL, BOX, GOAL, BOXGOAL = 1, 2, 3, 4 --if more blocks are needed, add 4
- local maxSlots = 16
- local startx, starty, startz = 0, 0, 0
- local numGoals, numSolved = 0, 0
- function selnextslot(slot)
- tmp = slot
- while turtle.getItemCount(tmp) == 0 do
- tmp = tmp + 4
- if tmp > maxSlots then
- print("Out of materials! Refill and press enter or type cancel to abort.")
- if not getInput() then return end
- tmp = slot
- end
- end
- turtle.select(tmp)
- end
- function selslot(symb)
- if symb == SWALL then selnextslot(WALL); return 1
- elseif symb == SBOX then selnextslot(BOX); return 1
- elseif symb == SGOAL then selnextslot(GOAL); return 2
- elseif symb == SBOXGOAL then selnextslot(GOAL); return 3
- elseif symb == SPLAYER then return 4
- elseif symb == SPLAYERGOAL then selnextslot(GOAL); return 5
- else return 0 end
- end
- function efficPlaceDown()
- if turtle.detectDown() then
- if turtle.compareDown() then return
- else
- turtle.digDown()
- turtle.placeDown()
- end
- else turtle.placeDown() end
- end
- function build()
- for i = 1, #lvl do --read each row in the level
- if i % 2 == 0 then
- lvl[i] = lvl[i]:reverse()
- if not vert then moveZ(#lvl[i] - 1)
- else moveZ(#lvl[i] - 2) end
- else
- if not vert then moveZ(0)
- else moveZ(1) end
- end
- for c in lvl[i]:gmatch(".") do --read each char in the row
- ret = selslot(c)
- if ret == 1 then
- if not vert then efficPlaceDown()
- else turtle.place() end
- if i % 2 == 0 then moveZ(posz - 1)
- else moveZ(posz + 1) end
- elseif ret == 2 then
- numGoals = numGoals + 1
- if not vert then
- moveY(posy - 1)
- efficPlaceDown()
- moveY(posy + 1)
- else
- if i % 2 == 0 then
- moveZ(posz + 1)
- turnL()
- turtle.place()
- turnR()
- moveZ(posz - 1)
- else
- moveZ(posz - 1)
- turnR()
- turtle.place()
- turnL()
- moveZ(posz + 1)
- end
- end
- if i % 2 == 0 then moveZ(posz - 1)
- else moveZ(posz + 1) end
- elseif ret == 3 then
- numGoals = numGoals + 1
- numSolved = numSolved + 1
- if not vert then
- moveY(posy - 1)
- efficPlaceDown()
- moveY(posy + 1)
- turtle.select(BOXGOAL)
- efficPlaceDown()
- else
- if i % 2 == 0 then
- moveZ(posz + 1)
- turnL()
- turtle.place()
- turnR()
- moveZ(posz - 1)
- else
- moveZ(posz - 1)
- turnR()
- turtle.place()
- turnL()
- moveZ(posz + 1)
- end
- turtle.select(BOXGOAL)
- turtle.place()
- end
- if i % 2 == 0 then moveZ(posz - 1)
- else moveZ(posz + 1) end
- elseif ret == 4 or ret == 5 then
- if not vert then
- startx = posx
- startz = posz
- else
- starty = posy
- if i % 2 == 0 then startz = posz + 1
- else startz = posz - 1 end
- end
- if ret == 5 then
- numGoals = numGoals + 1
- if not vert then
- moveY(posy - 1)
- efficPlaceDown()
- moveY(posy + 1)
- else
- if i % 2 == 0 then
- moveZ(posz + 1)
- turnL()
- turtle.place()
- turnR()
- moveZ(posz - 1)
- else
- moveZ(posz - 1)
- turnR()
- turtle.place()
- turnL()
- moveZ(posz + 1)
- end
- end
- end
- if i % 2 == 0 then moveZ(posz - 1)
- else moveZ(posz + 1) end
- else
- if i % 2 == 0 then moveZ(posz - 1)
- else moveZ(posz + 1) end
- end
- end
- if vert then
- moveY(-i)
- turnAround()
- --moveZ(1)
- else
- moveX(i)
- --gototarg(i, 1, 0)
- end
- end
- end
- ------------------------
- -- GAMEPLAY CONTROL --
- ------------------------
- function sokoUp()
- if not vert then
- --top-down movement up
- efficTurn(3)
- if turtle.detect() then
- --check if the block is a wall
- selnextslot(WALL)
- if turtle.compare() then return true end
- --box, go check if there's something behind it
- moveY(posy + 1)
- moveX(posx - 2)
- if turtle.detectDown() then --there is
- moveX(posx + 2)
- moveY(posy - 1)
- return true
- else
- --there's not, check if the space is a goal
- moveY(posy - 1)
- selnextslot(GOAL)
- if turtle.compareDown() then
- selnextslot(BOX)
- turnAround()
- --if the box to push is not solved, it is now being solved,
- --so add one to the count of solved boxes
- if turtle.compare() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- selnextslot(BOXGOAL)
- turnAround()
- --if the box to push is solved, it is now being unsolved,
- --so subtract one from the count of solved boxes
- if turtle.compare() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box and place the new box (selected above)
- turtle.dig()
- moveX(posx + 1)
- turnAround()
- turtle.place()
- end
- else moveX(posx - 1) end
- else
- --vertical movement up
- --check if anything is in path
- if turtle.detectUp() then
- selnextslot(WALL)
- if turtle.compareUp() then return true end
- --check if anything is behind the box
- moveX(posx + 1)
- moveY(posy + 2)
- efficTurn(3)
- if turtle.detect() then
- moveY(posy - 2)
- moveX(posx - 1)
- return true
- else
- --there's not, check if there's a goal
- moveX(posx - 1)
- selnextslot(GOAL)
- if turtle.compare() then
- --there's a goal, check if the box being pushed will
- --contribute to an additional goal, or if it's just
- --swapping goal spaces
- selnextslot(BOX)
- if turtle.compareDown() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- --there's no goal, check if the box being pushed will
- --be pushed off of a goal, subtracting from the number
- --of solved boxes
- selnextslot(BOXGOAL)
- if turtle.compareDown() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box (replacing with the box selected above)
- turtle.digDown()
- moveY(posy - 1)
- turtle.placeUp()
- end
- else moveY(posy + 1) end
- end
- return false
- end
- function sokoDown()
- if not vert then
- --top-down movement down
- efficTurn(1)
- if turtle.detect() then
- --check if the block is a wall
- selnextslot(WALL)
- if turtle.compare() then return true end
- --box, go check if there's something behind it
- moveY(posy + 1)
- moveX(posx + 2)
- if turtle.detectDown() then --there is
- moveX(posx - 2)
- movY(posy - 1)
- return true
- else
- --there's not, check if the space is a goal
- moveY(posy - 1)
- selnextslot(GOAL)
- if turtle.compareDown() then
- selnextslot(BOX)
- turnAround()
- --if the box to push is not solved, it is now being solved,
- --so add one to the count of solved boxes
- if turtle.compare() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- selnextslot(BOXGOAL)
- turnAround()
- --if the box to push is solved, it is now being unsolved,
- --so subtract one from the count of solved boxes
- if turtle.compare() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box and place the new box (selected above)
- turtle.dig()
- moveX(posx - 1)
- turnAround()
- turtle.place()
- end
- else moveX(posx + 1) end
- else
- --vertical movement down
- --check if anything is in path
- if turtle.detectDown() then
- selnextslot(WALL)
- if turtle.compareDown() then return true end
- --check if anything is behind the box
- moveX(posx + 1)
- moveY(posy - 2)
- efficTurn(3)
- if turtle.detect() then
- moveY(posy + 2)
- moveX(posx - 1)
- return true
- else
- --there's not, check if there's a goal
- moveX(posx - 1)
- selnextslot(GOAL)
- if turtle.compare() then
- --there's a goal, check if the box being pushed will
- --contribute to an additional goal, or if it's just
- --swapping goal spaces
- selnextslot(BOX)
- if turtle.compareUp() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- --there's no goal, check if the box being pushed will
- --be pushed off of a goal, subtracting from the number
- --of solved boxes
- selnextslot(BOXGOAL)
- if turtle.compareUp() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box (replacing with the box selected above)
- turtle.digUp()
- moveY(posy + 1)
- turtle.placeDown()
- end
- else moveY(posy - 1) end
- end
- end
- function sokoRight()
- efficTurn(0)
- if turtle.detect() then
- --check if the block is a wall
- selnextslot(WALL)
- if turtle.compare() then return true end
- --box, go check if anything is behind it
- if not vert then
- --top-down movement
- moveY(posy + 1)
- moveZ(posz + 2)
- if turtle.detectDown() then --there is
- moveZ(posz - 2)
- movY(posy - 1)
- return true
- else
- --there's not, check if the space is a goal
- moveY(posy - 1)
- selnextslot(GOAL)
- if turtle.compareDown() then
- selnextslot(BOX)
- turnAround()
- --if the box to push is not solved, it is now being solved,
- --so add one to the count of solved boxes
- if turtle.compare() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- selnextslot(BOXGOAL)
- turnAround()
- --if the box to push is solved, it is now being unsolved,
- --so subtract one from the count of solved boxes
- if turtle.compare() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box and place the new box (selected above)
- turtle.dig()
- moveZ(posz - 1)
- turnAround()
- turtle.place()
- end
- else
- --vertical movement
- --check if anything is behind the box
- moveX(posx + 1)
- moveZ(posz + 2)
- efficTurn(3)
- if turtle.detect() then --there is
- moveZ(posz - 2)
- moveX(posx - 1)
- return true
- else
- --there's not, check if there's a goal
- moveX(posx - 1)
- selnextslot(GOAL)
- if turtle.compare() then
- --there's a goal, check if the box being pushed will
- --contribute to an additional goal, or if it's just
- --swapping goal spaces
- turnL()
- selnextslot(BOX)
- if turtle.compare() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- --there's no goal, check if the box being pushed will
- --be pushed off of a goal, subtracting from the number
- --of solved boxes
- turnL()
- selnextslot(BOXGOAL)
- if turtle.compare() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box (replacing with the box selected above)
- turtle.dig()
- moveZ(posz - 1)
- turnAround()
- turtle.place()
- end
- end
- else moveZ(posz + 1) end
- end
- function sokoLeft()
- efficTurn(2)
- if turtle.detect() then
- --check if the block is a wall
- selnextslot(WALL)
- if turtle.compare() then return true end
- --box, go check if anything is behind it
- if not vert then
- --top-down movement
- moveY(posy + 1)
- moveZ(posz - 2)
- if turtle.detectDown() then --there is
- moveZ(posz + 2)
- movY(posy - 1)
- return true
- else
- --there's not, check if the space is a goal
- moveY(posy - 1)
- selnextslot(GOAL)
- if turtle.compareDown() then
- selnextslot(BOX)
- turnAround()
- --if the box to push is not solved, it is now being solved,
- --so add one to the count of solved boxes
- if turtle.compare() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- selnextslot(BOXGOAL)
- turnAround()
- --if the box to push is solved, it is now being unsolved,
- --so subtract one from the count of solved boxes
- if turtle.compare() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box and place the new box (selected above)
- turtle.dig()
- moveZ(posz + 1)
- turnAround()
- turtle.place()
- end
- else
- --vertical movement
- --check if anything is behind the box
- moveX(posx + 1)
- moveZ(posz - 2)
- efficTurn(3)
- if turtle.detect() then --there is
- moveZ(posz + 2)
- moveX(posx - 1)
- return true
- else
- --there's not, check if there's a goal
- moveX(posx - 1)
- selnextslot(GOAL)
- if turtle.compare() then
- --there's a goal, check if the box being pushed will
- --contribute to an additional goal, or if it's just
- --swapping goal spaces
- turnR()
- selnextslot(BOX)
- if turtle.compare() then numSolved = numSolved + 1 end
- selnextslot(BOXGOAL)
- else
- --there's no goal, check if the box being pushed will
- --be pushed off of a goal, subtracting from the number
- --of solved boxes
- turnR()
- selnextslot(BOXGOAL)
- if turtle.compare() then numSolved = numSolved - 1 end
- selnextslot(BOX)
- end
- --now move the box (replacing with the box selected above)
- turtle.dig()
- moveZ(posz + 1)
- turnAround()
- turtle.place()
- end
- end
- else moveZ(posz - 1) end
- end
- function sync()
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- shell.run("id")
- print("Send the message 'sync' to this turtle using the ID above.")
- print("Waiting for computer sync...")
- id, message = rednet.receive()
- if message == "sync" then
- print("Received input from @"..id..", sync with this computer?")
- print(" (Enter yes or no)")
- local input = io.read()
- if input == "y" or input == "yes" or input == "ok" then
- print("Sync complete.")
- rednet.send(id, "true")
- return id --return computer ID that sent the message
- elseif input == "cancel" or input == "quit" or input == "exit" then
- rednet.send(id, "false")
- return -1 -- don't sync
- end
- end
- end
- end
- function run()
- rednet.open("right")
- local synced = sync()
- if synced == -1 then return end
- local continue = true
- local lastCmd = "" --store the last command sent to the turtle
- local lastFailed = false --store whether the last command succeeded
- local moves = 0
- local firstMove = true
- local delta = 0
- while continue do
- print("Awaiting command...")
- id, message = rednet.receive()
- print("@"..id..": "..message)
- if id == synced and not (lastCmd == message and lastFailed) then
- --received message from synced computer, read the message
- --don't waste time attempting to complete the same move that
- --was just tried and failed
- if message == "up" then
- lastFailed = sokoUp()
- elseif message == "down" then
- lastFailed = sokoDown()
- elseif message == "right" then
- lastFailed = sokoRight()
- elseif message == "left" then
- lastFailed = sokoLeft()
- elseif message == "end" then
- print("User control terminated.")
- return
- elseif message == "sync" then
- local newSync = sync()
- else
- print("Unknown command: "..message) --shouldn't happen
- print("Expected: up, down, right, left, or end")
- lastFailed = false
- end
- if not lastFailed then
- print("Last move succeeded.")
- else print("Last move failed.") end
- if not lastFailed and (message == "up" or
- message == "down" or message == "right" or
- message == "left") then
- moves = moves + 1
- if firstMove then
- delta = os.clock()
- firstMove = false
- end
- end
- if numSolved == numGoals then
- delta = os.clock() - delta
- --local days, hours, minutes, seconds
- --convert to a meaningful time format
- print("You solved the puzzle!")
- print("It took "..moves.." moves and "..delta.." seconds!")
- print("User control terminated.")
- rednet.send(id, "end")
- return
- end
- lastCmd = message
- end
- end
- end
- -------------------------
- -- BEGINNING THE END --
- -------------------------
- function start()
- if vert then
- posy = -#lvl - 1
- gototarg(0, 0, 1)
- turnL()
- turnL()
- else gototarg(0, 1, 0) end
- build()
- if vert then
- moveX(1)
- gototarg(1, starty, startz)
- moveX(0)
- else gototarg(startx, starty, startz) end
- run()
- end
- start()
Advertisement
Add Comment
Please, Sign In to add comment