Created
August 9, 2019 22:14
-
-
Save UlisseMini/0f6e6ff7047ab8edd8da9236ec5ba7e9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--------- | |
-- Module for managing coordanites in opencomputers. | |
-- @module coords | |
-- @author Ulisse Mini | |
-- @license MIT | |
local r = require('robot') | |
--- The entire API lives in here. | |
local t = {} | |
--- Our current coordanites. | |
local c = { | |
x = 0, -- Current X | |
y = 0, -- Current Y | |
z = 0, -- Current Z | |
ori = 0, -- Current orientation, 0-3 | |
} | |
-- The delta for different orientations. | |
local delta = { | |
[0] = function() c.z = c.z - 1 end, | |
[1] = function() c.x = c.x + 1 end, | |
[2] = function() c.z = c.z + 1 end, | |
[3] = function() c.x = c.x - 1 end | |
} | |
function t.turnRight() | |
r.turnRight() | |
c.ori = (c.ori + 1) % 4 | |
end | |
function t.turnLeft() | |
r.turnLeft() | |
c.ori = (c.ori - 1) % 4 | |
end | |
--- Create a new move function. | |
-- Afterwards the return value of moveFn will be returned. | |
-- @tparam function moveFn A function that returns a bool after moving the t. | |
-- @tparam function fn The function to be called if moveFn returns true. | |
local function move(moveFn, fn) | |
return function(...) | |
local b = moveFn(...) | |
if b then fn() end | |
return b | |
end | |
end | |
--- Move the r forward. | |
-- @treturn bool success | |
-- @function t.forward | |
t.forward = move(r.forward, function() | |
delta[c.ori]() | |
end) | |
--- Move the r backward. | |
-- @treturn bool success | |
-- @function t.back | |
t.back = move(r.back, function() | |
delta[(c.ori + 2) % 4]() | |
end) | |
--- Move the r upwards. | |
-- @treturn bool success | |
-- @function t.up | |
t.up = move(r.up, function() c.y = c.y + 1 end) | |
--- Move the r upwards. | |
-- if it succeeds, increment our y coordanite. | |
-- @treturn bool success | |
-- @function t.down | |
t.down = move(r.down, function() c.y = c.y - 1 end) | |
--- Needed for converting the orientation back and forth to strings. | |
-- if a key does not exist an error is thrown. | |
local oris = { | |
["north"] = 0, | |
["east"] = 1, | |
["south"] = 2, | |
["west"] = 3 | |
} | |
--- Look a direction, | |
-- @param direction can be a string or number | |
-- if it is a string then it will be converted to a number based | |
-- on the oris table. | |
function t.look(direction) | |
if type(direction) == "string" then | |
if oris[direction] == nil then | |
error(direction .. ' is not in the orientations table') | |
end | |
direction = oris[direction] | |
end | |
-- Now we turn to the correct orientation | |
if direction == c.ori then return end | |
if (direction - c.ori) % 2 == 0 then | |
t.turnLeft() | |
t.turnLeft() | |
elseif (direction - c.ori) % 4 == 1 then | |
t.turnRight() | |
else | |
t.turnLeft() | |
end | |
end | |
--- Helper for t.moveTo, | |
-- move will be called, every time it fails | |
-- swing will be called until its return value is false. | |
local function moveWith(move, swing) | |
while not move() do | |
while swing() do end | |
end | |
end | |
--- Helper for t.moveTo. is the same as | |
-- moveWith(t.forward, r.swing) | |
local function moveForward() | |
moveWith(t.forward, r.swing) | |
end | |
--- Move to a set of coordanites. | |
-- TODO: More efficent, turns when it could just move back. | |
-- @tparam number xT Target X coordanite | |
-- @tparam number yT Target Y coordanite | |
-- @tparam number zT Target Z coordanite | |
-- @tparam number,string oriT orientation target [optional]. | |
function t.moveTo(xT, yT, zT, oriT) | |
oriT = oriT or c.ori | |
-- check for nil arguments | |
if (not xT or not yT or not zT) then | |
error( | |
([[t.moveTo Invalid arguments | |
xT = %q (want number) | |
yT = %q (want number) | |
zT = %q (want number) | |
oriT = %q (want number or string) | |
]]):format(xT, yT, zT, oriT)) | |
end | |
while yT < c.y do | |
moveWith(t.down, r.swingDown) | |
end | |
while yT > c.y do | |
moveWith(t.up, r.swingUp) | |
end | |
if xT < c.x then | |
t.look('west') | |
while xT < c.x do moveForward() end | |
end | |
if xT > c.x then | |
t.look('east') | |
while xT > c.x do moveForward() end | |
end | |
if zT < c.z then | |
t.look('north') | |
while zT < c.z do moveForward() end | |
end | |
if zT > c.z then | |
t.look('south') | |
while zT > c.z do moveForward() end | |
end | |
t.look(oriT) | |
end | |
t.c = c | |
return t |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment