Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- is_test = false
- Coord = {}
- function Coord:new(x, y, z)
- local o = {x = x, y = y, z = z}
- self.__index = self
- return setmetatable(o, self)
- end
- Box = {}
- function Box:new(coord1, coord2)
- local o = {coord1 = coord1, coord2 = coord2}
- o = setmetatable(o, self)
- self.__index = self
- return o
- end
- function Box:contains(coord)
- local max_x, min_x = math.max(self.coord1.x, self.coord2.x), math.min(self.coord1.x, self.coord2.x)
- local max_y, min_y = math.max(self.coord1.y, self.coord2.y), math.min(self.coord1.y, self.coord2.y)
- local max_z, min_z = math.max(self.coord1.z, self.coord2.z), math.min(self.coord1.z, self.coord2.z)
- return coord.x <= max_x and coord.x >= min_x and coord.y <= max_y and coord.y >= min_y and coord.z <= max_z and coord.z >= min_z
- end
- Set = {}
- function Set:new()
- local o = {}
- self.__index = self
- return setmetatable(o, self)
- end
- function Set:of_list(list)
- local o = Set:new()
- for _, val in ipairs(list) do
- o:add(val)
- end
- return o
- end
- function Set:add(val)
- self[val] = true
- end
- function Set:mem(val)
- return self[val] ~= nil
- end
- function Set:remove(val)
- self[val] = nil
- end
- function Set:union(other)
- local new_set = Set:new()
- for k, _ in pairs(self) do
- new_set:add(k)
- end
- for k, _ in pairs(other) do
- new_set:add(k)
- end
- return new_set
- end
- base_box = Box:new(Coord:new(34, 62, -1617), Coord:new(45, 70, -1623))
- non_veins = Set:of_list{"minecraft:stone", "minecraft:cobblestone", "minecraft:diorite", "minecraft:gravel", "minecraft:dirt", "minecraft:andesite", "minecraft:granite", "minecraft:lava", "minecraft:obsidian", "minecraft:water", "minecraft:chest", "minecraft:base_stone_nether", "minecraft:basalt", "minecraft:netherrack", "minecraft:blackstone", "minecraft:nether_quartz_ore"}
- function should_mine(block)
- return non_veins[block] ~= nil
- end
- function test()
- local first = Coord:new(1, 2, 3)
- local second = Coord:new(6, 7, 8)
- local box = Box:new(first, second)
- print(box:contains(second)) -- true
- print(box:contains(Coord:new(8, 9, 10))) -- false
- print(box:contains(Coord:new(4, 5, 6))) -- true
- end
- Movement = {
- Forward = {},
- Backward = {},
- Up = {},
- Down = {},
- Left = {},
- Right = {}
- }
- function Movement:opposite(movement)
- if movement == self.Forward then
- return self.Backward
- elseif movement == self.Backward then
- return self.Forward
- elseif movement == self.Up then
- return self.Down
- elseif movement == self.Down then
- return self.Up
- elseif movement == self.Left then
- return self.Right
- elseif movement == self.Right then
- return self.Left
- end
- end
- function Movement:execute(movement)
- if is_test then
- return true
- end
- if movement == self.Forward then
- return turtle.forward()
- elseif movement == self.Backward then
- return turtle.back()
- elseif movement == self.Up then
- return turtle.up()
- elseif movement == self.Down then
- return turtle.down()
- elseif movement == self.Left then
- turtle.turnLeft()
- return true
- elseif movement == self.Right then
- turtle.turnRight()
- return true
- end
- end
- Cardinal = {
- North = {},
- East = {},
- South = {},
- West = {}
- }
- function Cardinal:read()
- local cardinal = io.read()
- if cardinal == "north" then
- return Cardinal.North
- elseif cardinal == "east" then
- return Cardinal.East
- elseif cardinal == "south" then
- return Cardinal.South
- elseif cardinal == "west" then
- return Cardinal.West
- else
- error("Invalid cardinal direction")
- end
- end
- function Cardinal:right(cardinal)
- if cardinal == self.North then
- return self.East
- elseif cardinal == self.East then
- return self.South
- elseif cardinal == self.South then
- return self.West
- elseif cardinal == self.West then
- return self.North
- end
- end
- function Cardinal:left(cardinal)
- if cardinal == self.North then
- return self.West
- elseif cardinal == self.West then
- return self.South
- elseif cardinal == self.South then
- return self.East
- elseif cardinal == self.East then
- return self.North
- end
- end
- function Cardinal:update_forward(coord)
- if self.facing == self.North then
- coord.z = coord.z - 1
- elseif self.facing == self.East then
- coord.x = coord.x + 1
- elseif self.facing == self.South then
- coord.z = coord.z + 1
- elseif self.facing == self.West then
- coord.x = coord.x - 1
- end
- end
- function Cardinal:update_backward(coord)
- if self.facing == self.North then
- coord.z = coord.z + 1
- elseif self.facing == self.East then
- coord.x = coord.x - 1
- elseif self.facing == self.South then
- coord.z = coord.z - 1
- elseif self.facing == self.West then
- coord.x = coord.x + 1
- end
- end
- Robot = {}
- function Robot:new(start, facing)
- local o = { log = {}, start = start, current_coord = start, facing = facing }
- self.__index = self
- return setmetatable(o, self)
- end
- function Robot:execute(movement)
- if not Movement:execute(movement) then
- return false
- end
- if movement == Movement.Forward then
- Cardinal:update_forward(self.current_coord)
- elseif movement == Movement.Backward then
- Cardinal:update_backward(self.current_coord)
- elseif movement == Movement.Left then
- self.facing = Cardinal:left(self.facing)
- elseif movement == Movement.Right then
- self.facing = Cardinal:right(self.facing)
- elseif movement == Movement.Up then
- self.current_coord.y = self.current_coord.y + 1
- elseif movement == Movement.Down then
- self.current_coord.y = self.current_coord.y - 1
- end
- return true
- end
- function Robot:execute_and_log(movement)
- if not self:execute(movement) then
- return false
- end
- table.insert(self.log, movement)
- return true
- end
- function Robot:backtrack_once()
- local last_movement = self.log[#self.log]
- if not self:execute(Movement:opposite(last_movement)) then
- return false
- end
- table.remove(self.log)
- return true
- end
- function Robot:move_x(x_diff)
- if x_diff == 0 then
- return 0
- end
- if self.facing == Cardinal.East then
- if x_diff > 0 then
- if not self:execute_and_log(Movement.Forward) then return x_diff end
- return self:move_x(x_diff - 1)
- else
- if not self:execute_and_log(Movement.Backward) then return x_diff end
- return self:move_x(x_diff + 1)
- end
- elseif self.facing == Cardinal.West then
- if x_diff > 0 then
- if not self:execute_and_log(Movement.Backward) then return x_diff end
- return self:move_x(x_diff - 1)
- else
- if not self:execute_and_log(Movement.Forward) then return x_diff end
- return self:move_x(x_diff + 1)
- end
- elseif self.facing == Cardinal.North or self.facing == Cardinal.South then
- self:execute_and_log(Movement.Right)
- return self:move_x(x_diff)
- end
- end
- function Robot:move_z(z_diff)
- if z_diff == 0 then
- return 0
- end
- if self.facing == Cardinal.South then
- if z_diff > 0 then
- if not self:execute_and_log(Movement.Forward) then return z_diff end
- return self:move_z(z_diff - 1)
- else
- if not self:execute_and_log(Movement.Backward) then return z_diff end
- return self:move_z(z_diff + 1)
- end
- elseif self.facing == Cardinal.North then
- if z_diff > 0 then
- if not self:execute_and_log(Movement.Backward) then return z_diff end
- return self:move_z(z_diff - 1)
- else
- if not self:execute_and_log(Movement.Forward) then return z_diff end
- return self:move_z(z_diff + 1)
- end
- elseif self.facing == Cardinal.East or self.facing == Cardinal.West then
- self:execute_and_log(Movement.Right)
- return self:move_z(z_diff)
- end
- end
- function Robot:move_to_coord(coord)
- local x_diff = coord.x - self.current_coord.x
- local y_diff = coord.y - self.current_coord.y
- local z_diff = coord.z - self.current_coord.z
- while y_diff ~= 0 do
- if y_diff > 0 then
- if not self:execute_and_log(Movement.Up) then break end
- y_diff = y_diff - 1
- elseif y_diff < 0 then
- if not self:execute_and_log(Movement.Down) then break end
- y_diff = y_diff + 1
- end
- end
- if y_diff ~= 0 then
- return false
- end
- if self:move_x(x_diff) ~= 0 then return false end
- if self:move_z(z_diff) ~= 0 then return false end
- return true
- end
- function Robot:backtrack_all()
- while #self.log > 0 do
- if not self:backtrack_once() then return false end
- end
- return true
- end
- function Robot:move_test()
- write("Enter the ending x coordinate: ")
- local x = tonumber(io.read())
- write("Enter the ending y coordinate: ")
- local y = tonumber(io.read())
- write("Enter the ending z coordinate: ")
- local z = tonumber(io.read())
- local end_ = Coord:new(x, y, z)
- self:move_to_coord(end_)
- self:backtrack_all()
- end
- function main()
- os.loadAPI("spec.lua")
- local start = Coord:new(spec.start_x, spec.start_y, spec.start_z)
- local robot = Robot:new(start, spec.start_facing)
- robot:move_test()
- end
- if is_test then test() else main() end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement