Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- experimental version of theinsektAPIs/poz3
- -- use poz3 instead, this is the more experimental version
- --(fixed some bugs here but not in original poz3...)
- -- pastebin get qyEYFZW0 theinsektAPIs/poz3
- -- poz3 is a turtle API for going in different directions while keeping track of the changes
- -- in position and direction, compared to a starting point.
- -- Stores position internally in a table called posT to simplify the usage of the functions.
- -- Also keeps track of the number of steps and turns that have been performed
- -- poz3 can be useful when digging, building etc.
- -- Another advantage is that you can write functions that take direction as a parameter, and therefore
- -- can work in any direction. This can make the code more reusable. Only write digLoop once!
- -- look in poz3a for an exmaple on how to make a digLoop.
- -- Some techniques that were used to reduce the amount of code:
- -- The code uses lua tables as lookup tables in many situation.
- -- The amount of code has greatly been reduced by making the function turnDo, that turns if necessary
- -- and then does an action in one of three directions (up, forward or down).
- -- This makes it so only 3 function has to be in the lookup table for most actions,
- -- see detectT or goT. Only turnT needs lots of directions (but these are also reduced by
- -- translating north, east, west or south to a turn direction).
- -- Replaced repeated code with functions in many cases, also replaced some code with a function if it
- -- was potentially useful outside this file.
- -- New feature: enterSimulationMode(), disables all actions, but still returns true (and false for some) and
- -- changes position, steps and turns, exitSimulationMode() to restore everything and
- -- be able to move again.
- -- To start a new simulation while in simulation you have to exit simulation mode then enter
- -- again.
- -- Warning: Many programs will not work in simulation mode because they might depend on finding a certain block
- -- or mining until the inventory is full etc.
- -- But if the program for example only depends on position then simulation mode might work.
- -- Simulation mode was created so that it's possible to simulate two different digging strategies and then
- -- choosing the fastest of them.
- -- this api has the following useful functions
- --using wtf style:
- --manipulate position manually
- --setPos(x0,y0,z0,f0)
- --getpos()->(x,y,z,f)
- --resetpos()
- --test properties of the direction
- --validFacing(direction)->(result)
- --validDirection(direction)->(result)
- --validAbsoluteDirection(direction)->(result)
- --manipulate directions
- --getReverse(direction)->(reverseDirection)
- --getAbsoluteDirection(direction)->(absoluteDirection)
- --do actions (valid direction usually: n,s,)
- --valid direction for most are: f,b,r,l,u,d,n,s,e,w
- --(forward, back, right, left, up ,down, north, south, east, west)
- --go(direction)->(succes)
- --turn(direction)->(succes)
- --etc...
- --the current position!!!
- --and stats!
- --can be changed with setPos, getPos and resetPos
- local posT={x=0,y=0,z=0,f="n"}
- local statsT={steps=0,turns=0}
- --simulation, is probably to simple
- --Does not work very well for more advanced programs
- inSimulation=false
- local backupPosT=nil
- local backupStatsT=nil
- --in simulation mode will pretend to do the action
- --then return true (or in some cases false, see detectT)
- --work in progress
- function enterSimulationMode()
- --code to enter simulation code
- if not inSimulation then
- print("Entered simulation mode")
- inSimulation=true
- backupPosT=copyTable(posT)
- backupStatsT=copyTable(statsT)
- end
- end
- function exitSimulationMode()
- if inSimulation then
- print("Exited simulation mode")
- inSimulation=false
- posT=copyTable(backupPosT)
- --check posT just to be safe
- if posT==nil then error("Internal error: posT is nil (this should never happen!)") end
- statsT=copyTable(backupStatsT)
- end
- end
- function incrementSteps()
- statsT["steps"]=statsT["steps"]+1
- end
- function incrementTurns()
- statsT["turns"]=statsT["turns"]+1
- end
- function getStats()
- return statsT["steps"], statsT["turns"]
- end
- function setStats(steps,turns)
- statsT["steps"]=steps
- statsT["turns"]=turns
- end
- function resetStats()
- statsT["steps"]=0
- statsT["turns"]=0
- end
- --change coordinates
- --sets the position values
- function setPos(x0,y0,z0,f0)
- --check that none of the inputs are nil
- if(x0==nil) then error("Error: x0 is nil") end
- if(y0==nil) then error("Error: y0 is nil") end
- if(z0==nil) then error("Error: z0 is nil") end
- if(f0==nil) then error("Error: f0 is nil") end
- --check that the f0 direction is recognized
- if(not validFacing(f0)) then error("Error: f0 isn't a valid facing (valid: n,s,w,e)") end
- --check that coordinates are numbers
- if(type(x0) ~= "number") then error("Error: x0 isn't a number") end
- if(type(y0) ~= "number") then error("Error: y0 isn't a number") end
- if(type(z0) ~= "number") then error("Error: z0 isn't a number") end
- --set the position
- posT["x"]=x0
- posT["y"]=y0
- posT["z"]=z0
- posT["f"]=f0
- end
- --sets the position values using a pos table
- function setPos2(posT)
- setPos(posT["x"],posT["y"],posT["z"],posT["f"])
- end
- function resetPos()
- setPos(0,0,0,"n")
- end
- --return x,y,z,f
- --uses the same conventions as minecraft
- --but the facing north is determined by the starting direction
- function getPos()
- return posT["x"],posT["y"],posT["z"],posT["f"]
- end
- function copyTable(inTable)
- local outTable={}
- for k,v in pairs(inTable) do
- outTable[k]=v
- end
- return outTable
- end
- function getPos2()
- return copyPos(posT)
- --return {x=posT["x"],y=posT["y"],z=posT["z"],f=posT["f"]}
- end
- function getPosField(fieldName)
- return posT[fieldName]
- end
- function copyPos(aPosT)
- if aPosT==nil then error("Error: aPosT is nil") end
- return {x=aPosT["x"],y=aPosT["y"],z=aPosT["z"],f=aPosT["f"]}
- end
- --check directions
- function validFacing(direction)
- return faceT[direction]~=nil
- end
- function validDirection(direction)
- return reverseT[direction]~=nil
- end
- function validAbsoluteDirection(direction)
- return goUpdateT[direction]~=nil
- end
- function isHorizontal(direction)
- return not isVertical(direction)
- end
- function isVertical(direction)
- direction=getAbsoluteDirection(direction)
- return direction=="u" or direction=="d"
- end
- --various direction calculations
- --directions: n,s,e,w,u,d
- --returns which coordinate would be changed and by how much
- function getCoordinateChange(direction,length)
- local tmp=goUpdateT[direction]
- if tmp==nil then Error("Error: unrecognised direction (valid: n,s,e,w,u,d)") end
- local posTFieldName, change = unpack(tmp)
- return posTFieldName,change*length
- end
- --return the resulting facing after doing a turn in the given direction
- --returns nil if the direction is not valid/recognized
- --directions: n,s,e,w,u,d,f,b,l,r
- --throws and error if invalid direction
- function getTurnRes(direction)
- --check inputs
- typeErrorIf("direction",direction,"string",2)
- --u or d doesn’t change so return old facing
- if direction=="u" or direction=="d" then
- return posT["f"]
- end
- --n,e,s,w are already facings
- if turnResT[direction] ~= nil then
- return direction --direction is one of n,e,s,w
- end
- --convert f,b,r,l to facing (n,e,s,w)
- local res = turnResT[posT["f"]][direction]
- --check if res is nil through error
- if res==nil then
- if not validDirection(direction) then error("Error: invalid direction (valid: n,s,e,w,u,d,f,b,l,r).") end
- error("Error: internal bug")
- end
- return res
- end
- --to get the resulting facing (n,e,s,w)
- --converts wanted facing (n,e,s,w) to
- --needed turn direction (r,l,b,f)
- function getFacingToTurnDirection(facing)
- return faceT[posT["f"]][facing]
- end
- --turns: n,s,e,w,u,d,f,b,l,r into n,s,e,w,u,d
- --directions: n,s,e,w,u,d,f,b,l,r
- --returns nil if the direction isn't recognized
- function getAbsoluteDirection(direction)
- --check input
- typeErrorIf("direction",direction,"string",2)
- --u and d are already absolute direction
- if direction=="u" or direction=="d" then
- return direction
- end
- --get the cardinal direction
- return getTurnRes(direction)
- end
- --get the reverse direction
- --directions:
- --works best for n,s,e,w,u,d, because if you use go on the reverse of those you will go to your
- --previous position
- --also works for f,b,l,r
- function getReverse(direction)
- return reverseT[direction]
- end
- --get a new table with position 0
- --all the parameters are optional, just use nil to
- --to set the default value
- --x0,y0,z0 are integer number
- --f0 is a string that can be n,e,s,w
- function getNewPos(x0,y0,z0,f0)
- --replace nil with default value
- if x0==nil then x0=0 end
- if y0==nil then y0=0 end
- if z0==nil then z0=0 end
- if f0==nil then f0="n" end
- --check that the f0 direction is recognized
- if(not validFacing(f0)) then error("Error: f0 isn't a valid facing (valid: n,s,w,e)") end
- --check that coordinates are numbers
- if(type(x0) ~= "number") then error("Error: x0 isn't a number") end
- if(type(y0) ~= "number") then error("Error: y0 isn't a number") end
- if(type(z0) ~= "number") then error("Error: z0 isn't a number") end
- --return new posT
- return {x=x0,y=y0,z=z0,f=f0}
- end
- --get the direction and distance needed to get to a coord value
- function coordToGoValues(coordName,wantedCoordValue)
- return coordChangeToDirection(coordName, wantedCoordValue-posT[coordName])
- end
- --turns x,y,z into s,e,u
- --negative length reverses the direction
- --can be used to get the direction and distance if you want to
- --go to a certain coordinate
- function coordChangeToDirection(coordName, length)
- --check input
- typeErrorIf("coordName",coordName,"string",2)
- --get direction to increase coordinate
- local direction=fieldToDirectionT[coordName]
- --check if invalid coordName
- if direction==nil then
- error("Error: invalid coordinate name (valid names: x, y, x, f)")
- end
- --invert direction if length is negative
- if length<0 then
- direction=getReverse(direction)
- length=-length
- end
- --return direction and change
- return direction, length
- end
- --turn, go, detect etc...
- --turn in/to the given direction
- --directions: n,s,e,w,u,d,f,b,l,r
- --Has simulation mode!
- function turn(direction)
- --check input
- typeErrorIf("direction",direction,"string",2)
- --convert n,e,s,w if neccesary
- if turnT[direction]==nil then
- direction=getFacingToTurnDirection(direction)
- --faceT[posT["f"]][direction] -- translates n,s,e,w into equivalent r,l,u,d,f,b
- end
- --check if unrecognised direction
- if direction==nil then
- error("Error: unrecognised direction (recognized directions: n,s,e,w,u,d,f,b,l,r)")
- end
- --turn and return turn result
- return turnT[direction]() -- r,l,u,d,f,b
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function go(direction)
- return turnDo(goT,direction)
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function attack(direction)
- return turnDo(attackT,direction)
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function dig(direction)
- return turnDo(digT,direction)
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- --sign text should be nil, or not specified if direction is u or d
- function place(direction,signText)
- return turnDo(placeT,direction,signText)
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function detect(direction)
- return turnDo(detectT,direction)
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function compare(direction)
- return turnDo(compareT,direction)
- end
- --syntax: drop(string direction, [number count])
- --uses: turtle.drop([number count])
- --directions: n,s,e,w,u,d,f,b,l,r
- --returns: boolean true if an item was dropped; false otherwise.
- --Supports simulation mode!
- --... captures zero or more optional parameters
- function drop(direction, amount)
- return turnDo(dropT,direction, amount)
- end
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function suck(direction,amount)
- return turnDo(suckT,direction,amount)
- end
- --available in cc1.64 and later
- --directions: n,s,e,w,u,d,f,b,l,r
- --Supports simulation mode!
- function inspect(direction)
- return turnDo(inspectT,direction)
- end
- --help functions
- --help function, turns if necessary, then looks up an action in the doT (f,u or d) and does the action.
- --The do table (doT) should have f,u and d
- --turn do returns the result of the do action
- function turnDo(doT,direction, ...)--... are variable amount of arguments passed to the do function
- --check input
- typeErrorIf("direction",direction,"string",2)
- typeErrorIf("doT",doT,"table",2)
- --turn if neccesary
- if doT[direction] == nil then -- if does not have action in that direction then turn
- direction=turn2(direction) -- turn and get "after turn action direction"
- end
- --special case code if in simulation
- if inSimulation then
- if not doT["simSupport"] then
- error("Error: is in simulation mode but the given action does not support simulation")
- end
- if doT["simReturn"] then
- --sim return is a table with one or more return values
- return unpack(doT["simReturn"])
- end
- --if has no sim return the original code is supposed to be run
- --the original code could change position and statistics but should not move or move items.
- end
- --do function and return result
- --have to do this because turtle.suck() works but not turtle.suck(nil)
- --so if someone did poz3.suck(amount) without checking if amount isn't nil, then it wouldn't work before.
- if ... then
- --print("debug: optional is not nil")--DEBUG
- return doT[direction](...)--do the function
- else
- --print("debug: optional is nil")--DEBUG
- return doT[direction]()
- end
- end
- --checks if variable is the wantedType, else throws an error saying it's not correct type
- --has standardised error message
- function typeErrorIf(name,variable,wantedType,responsibleNumber)
- if responsibleNumber==nil then responsibleNumber=1 end
- if type(variable)~=wantedType then
- error("Error: param called "..name.." should be a "..wantedType.." not a "..type(variable),responsibleNumber+1)
- end
- end
- -- turns and then return the "after turn action direction" (f, u or d)
- function turn2(direction)
- turn(direction)
- return getTurnDoDirection(direction)
- end
- function getTurnDoDirection(direction)
- if direction=="u" or direction=="d" then
- return direction --up or down
- else
- return "f"--forward
- end
- end
- --updates the coordinate as if went in the given direction
- --only works for absolute directions
- --directions: n,s,e,w,u,d
- function goUpdate(direction)
- local posTFieldName, change = getCoordinateChange(direction,1)
- posT[posTFieldName]=posT[posTFieldName]+change
- return true
- end
- --updates the facing in pos if it’s a valid turn direction
- --returns true if it was a valid turn direction, and posT was updated
- --directions: n,s,e,w,u,d,f,b,l,r
- function turnUpdate(direction)
- local facing=getTurnRes(direction)
- posT["f"]=facing
- return true
- end
- function doCommand(commandName,direction,optional)
- return commandNameT[commandName](direction,optional)
- end
- commandNameT={
- ["turn"]=turn,
- ["go"]=go,
- ["attack"]=attack,
- ["dig"]=dig,
- ["place"]=place,
- ["detect"]=detect,
- ["compare"]=compare,
- ["drop"]=drop,
- ["suck"]=suck,
- ["ddgloop"]=function(direction,optional) return doLoop(tonumber(optional),detectDigGo,direction,nil) end,
- }
- commandUsageT={
- ["turn"]="usage: turn <direction> a \nexplanation: turns in the given direction",
- ["go"]="usage: go <direction> a \nexplanation: tries to go in the given direction",
- ["attack"]="usage: attack <direction> a \nexplanation: tries to attack in the given direction",
- ["dig"]="usage: dig <direction> a \nexplanation: tries to dig a block in the given direction",
- ["place"]="usage: place <direction> <optionalSignText> \nexplanation: places an item from the selected slot in the given direction",
- ["detect"]="usage: detect <direction> a \nexplanation: returns true if there is a block in the given direction else false",
- ["compare"]="usage: compare <direction> a \nexplanation: compares the block in the given direction to the item in the selected slot",
- ["drop"]="usage: drop <direction> <count> \nexplanation: drops count items in the given direction",
- ["suck"]="usage: suck <direction> a \nexplanation:",
- ["ddgloop"]="usage: ddgloop <direction> <length> \nexplanation: digs and moves in the given direction for the given length",
- }
- -- reverse: return the reverse of the given action, useful you want to move in one direction and then back
- --this table is used look up the reverse action
- --the reverse function uses this table to look up what the reverse action is
- --is also used to check valid direction, because it contains all directions
- reverseT={
- f="b",
- b="f",
- n="s", --turn north, reverse: turn south
- s="n", --turn south, reverse: turn north
- e="w", --turn east, reverse: turn west
- w="e", --turn west, reverse: turn east
- u="d", --turn up, reverse: turn down (tu does nothing)
- d="u", --turn down, reverse: turn up (td does nothing)
- r="l", --turn right, reverse: turn left
- l="r", --turn left, reverse: turn right
- }
- -- This is a lookup table containing functions
- -- go uses this table to simply look up what function is needed to do the given action
- -- these functions update positions but does not move if in simulation mode
- goT={
- simSupport=true,--in simulation: will update position without moving
- --go forward then update position
- f=function()
- if(inSimulation or turtle.forward()) then
- incrementSteps()
- goUpdate(posT["f"])
- return true
- end
- return false
- end,
- --go up then update position
- u=function()
- if(inSimulation or turtle.up()) then
- incrementSteps()
- goUpdate("u")
- return true
- end
- return false
- end,
- --go down then update position
- d=function()
- if(inSimulation or turtle.down()) then
- incrementSteps()
- goUpdate("d")
- return true
- end
- return false
- end,
- }
- -- these functions update positions but does not move if in simulation mode
- turnT={
- simSupport=true,--in simulation: will update position without moving
- --turn right and then update position
- r=function()
- if(inSimulation or turtle.turnRight()) then
- incrementTurns()
- turnUpdate("r")
- return true
- end
- return false
- end,
- --turn left and then update position
- l=function()
- if(inSimulation or turtle.turnLeft()) then
- incrementTurns()
- turnUpdate("l")
- return true
- end
- return false
- end,
- --does nothing, but may avoid special case in your code
- u=function() return true end,
- --does nothing, but may avoid special case in your code
- d=function() return true end,
- --does nothing, keeps facing forward
- f=function() return true end,
- --calls turn right twice, used to turn 180 degrees
- b=function()
- return turn("r") and turn("r")
- end,
- }
- --given current facing and wanted facing
- --used to look up the needed turn action
- faceT={
- n={
- n="f",
- s="b",
- e="r",
- w="l",
- },
- s={
- s="f",
- n="b",
- w="r",
- e="l",
- },
- e={
- e="f",
- w="b",
- s="r",
- n="l",
- },
- w={
- w="f",
- e="b",
- n="r",
- s="l",
- },
- }
- -- Creates an inverted table, were keys become values and values become keys.
- -- http://stackoverflow.com/questions/7925090/lua-find-a-key-from-a-value
- function table_invert(t)
- local s={}
- for k,v in pairs(t) do
- s[v]=k
- end
- return s
- end
- --lookup table to se what the resulting facing is after doing a turn in the given direction
- --does not include u or d, because they don’t change the facing
- --does not include n,e,s,w becuase they are alredy facings
- --each subtable is the inverse of the corresponding subtable in faceT
- turnResT={
- n=table_invert(faceT["n"]),
- s=table_invert(faceT["s"]),
- e=table_invert(faceT["e"]),
- w=table_invert(faceT["w"]),
- }
- --use to look up the coordinate change
- --going one step in the given direction
- goUpdateT={
- n={"z",-1},
- s={"z",1},
- e={"x",1},
- w={"x",-1},
- u={"y",1},
- d={"y",-1},
- }
- --used to look up the direction
- --to increase the given coordinate
- fieldToDirectionT={
- x="e",
- y="u",
- z="s",
- }
- attackT={
- simReturn={false},
- simSupport=true,
- f=function() return turtle.attack() end,
- u=function() return turtle.attackUp() end,
- d=function() return turtle.attackDown() end,
- }
- digT={
- simReturn={false},
- simSupport=true,
- f=function() return turtle.dig() end,
- u=function() return turtle.digUp() end,
- d=function() return turtle.digDown() end,
- }
- placeT={
- simReturn={false},
- simSupport=true,
- --turtle.place(nil) works
- f=function(signText) return turtle.place(signText) end,--TEST
- u=function() return turtle.placeUp() end,
- d=function() return turtle.placeDown() end,
- }
- detectT={
- simReturn={false},--this data is used by turnDo if inSimulation is true
- simSupport=true,--this data is used by turnDo if inSimulation is true
- f=function() return turtle.detect() end,
- u=function() return turtle.detectUp() end,
- d=function() return turtle.detectDown() end,
- }
- compareT={
- simReturn={false},
- simSupport=true,
- f=function() return turtle.compare() end,
- u=function() return turtle.compareUp() end,
- d=function() return turtle.compareDown() end,
- }
- dropT={
- simReturn={false},
- simSupport=true,
- --For some reason turtle.drop(nil) does not work, so these three does not work for all cases.
- --f=function(amount) return turtle.drop(amount) end,
- --u=function(amount) return turtle.dropUp(amount) end,
- --d=function(amount) return turtle.dropDown(amount) end,
- --these three works for all cases
- -- ... captures a variable amount of arguments
- f=function(...) return turtle.drop(...) end,
- u=function(...) return turtle.dropUp(...) end,
- d=function(...) return turtle.dropDown(...) end,
- }
- suckT={
- simReturn={true},
- simSupport=true,
- f=function(...) return turtle.suck(...) end,
- u=function(...) return turtle.suckUp(...) end,
- d=function(...) return turtle.suckDown(...) end,
- }
- inspectT={
- simReturn={false,"No block to inspect"},
- simSupport=true,
- f=function() return turtle.inspect() end,
- u=function() return turtle.inspectUp() end,
- d=function() return turtle.inspectDown() end,
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement