Update pairingtool

This commit is contained in:
Dominic Zimmer 2020-07-10 19:30:23 +02:00
parent eee0919110
commit bdc5407326
2 changed files with 728 additions and 3 deletions

703
dominic/pairingtool.lua Normal file
View File

@ -0,0 +1,703 @@
args = {...}
x, z, direction = 0, 0, 0
turtlestate = {
fuel = "",
state = "init",
job = nil,
ores = {}
}
function noop() end
function pair(x, y)
return math.floor((x + y) * (x + y + 1)/2 + y)
end
function unpairX(z)
local j = math.floor(math.sqrt(0.25 + 2*z) - 0.5)
return j - (z - j*(j+1)/2)
end
function unpairZ(z)
local j = math.floor(math.sqrt(0.25 + 2*z) - 0.5)
return z - j * (j+1)/2;
end
lookup = {4, 1, 3, 0, 2}
local function isDiggingSpot(x, y)
local val = lookup[(y % 5) + 1]
return (x % 5) == val
end
offset = 10
function ithSpot(i)
j = offset
while true do
x, z = unpairX(j), unpairZ(j)
if isDiggingSpot(x, z) then
if i <= 1 then
return x, z
else
i = i - 1
end
end
j = j + 1
end
end
function adjustToQuadrant(i, x, z)
if i % 4 == 0 then
return x, z
elseif i % 4 == 1 then
return -z-1, x
elseif i % 4 == 2 then
return z, -x-1
elseif i % 4 == 3 then
return -z-1, -x-1
end
end
function iTo2Dcoords(j)
i = math.floor(j / 4)
quadrantI = j % 4 -- 0-3 quadrant
counter = 0 -- number of digging spots found
j = 0 -- enumerate 2D plane
while true do
x, z = unpairX(j), unpairZ(j) -- coords in first quadrant
x, z = adjustToQuadrant(quadrantI, x, z) -- map coords correctly into other quadrants
if isDiggingSpot(x, z) then
if counter == i then
return x, z
end
counter = counter + 1
end
j = j + 1
end
end
function digSafe(inspectAction, digAction)
while true do
local status, block = inspectAction()
if status then
if block["name"]:lower():find("turtle") then
-- turtle in front of me. its free space
break
else
digAction()
-- gravel may take time to fall.
sleep(1)
end
else
-- No block in front of me. good
break
end
end
end
-- move safely into the direction, not hurting other turtles, but freeing the path if needed.
function moveSafe(moveAction, inspectAction, digAction)
while true do
local status, block = inspectAction()
if status then
if block["name"]:lower():find("turtle") then
-- turtle in front of me. lets wait for it to move
sleep(0.6)
elseif block["name"]:lower():find("water") or block["name"]:lower():find("lava") then
if moveAction() then
break
else
digAction()
updateState({ state = "I am stuck trying to walk into a liquid." })
end
else
digAction()
end
else
-- nothing in the way, try to move
if moveAction() then
break
end
end
end
end
-- If the block in front of the turtle is desired, take it.
function grabOres()
local status, block = turtle.inspect()
if status and block["name"]:lower():find("ore") then
ore = block["name"]:lower()
if turtlestate["ores"][ore] then
turtlestate["ores"][ore] = turtlestate["ores"][ore] + 1
else
turtlestate["ores"][ore] = 1
end
turtle.dig()
end
end
-- dig all the way down to bedrock, collect ores
-- Parameters:
-- * moveAction: the **vertical** move action, eg turtle.down
-- * digAction: the **vertical** dig action, eg turtle.digDown
-- * inpectAction: the **vertical** inspect action, eg turtle.inspectDown
-- * limit: if >= 0 * the number of blocks to dig
-- * dig until bedrock is hit
--
--
-- Returns: the depth dug
function digDeep(moveAction, digAction, inspectAction, limit)
local depth = 0
grabOres()
while true do
-- termination condition:
-- * if limit != -1: limit > 0
-- * otherwise : bedrock beneath
if limit < 0 then
local status, nextblock = inspectAction()
if status and nextblock["name"] == "minecraft:bedrock" then
return depth
end
else
if limit == 0 then
return depth
end
end
-- Limit not reached: keep digging
depth = depth + 1
limit = limit - 1
digAction()
moveAction()
grabOres() -- inspect block in front of turtle, take if neccessary
end
end
function selectCobble()
for i = 1,16 do
turtle.select(i)
item = turtle.getItemDetail()
if item and item["name"] == "minecraft:cobblestone" then
break
end
end
end
function selectFuel()
for i = 1,16 do
turtle.select(i)
item = turtle.getItemDetail()
if item and (item["name"] == "minecraft:coal" or item["name"] == "minecraft:charcoal") then
break
end
end
end
function digShaft()
--turtle.digDown()
--selectCobble()
--turtle.placeUp()
moveSafe(turtle.down, turtle.inspectDown, turtle.digDown)
--turtle.down()
depth = digDeep(turtle.down, turtle.digDown, turtle.inspectDown, -1)
turtle.turnLeft()
digDeep(turtle.up, noop, noop, depth)
turtle.turnLeft()
digDeep(turtle.down, noop, noop, depth)
turtle.turnLeft()
digDeep(turtle.up, noop, noop, depth)
turtle.turnLeft()
selectCobble()
turtle.up()
turtle.placeDown()
--turtle.digUp()
--turtle.up()
--faceDir(0)
end
function digTo(x, z)
--print("Digging to rel. coord ("..tostring(x)..", "..tostring(z)..")")
while z > 0 do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
z = z - 1
repeat sleep(0.6)
until (not turtle.digUp())
end
turtle.turnRight()
while x > 0 do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
x = x - 1
repeat sleep(0.6)
until (not turtle.digUp())
end
end
function goToSpawn(x, z)
moveSafe(turtle.up, turtle.inspectUp, turtle.digUp)
while z > 0 do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
z = z - 1
end
turtle.turnRight()
while x > 0 do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
x = x - 1
end
end
function moveSafeForward()
moveSafe(turtle.forward, turtle.inspect, noop)
end
function goToBarrel(path)
if path == 0 then
turtle.turnLeft()
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
else
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnLeft()
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
turtle.turnRight()
end
end
function leaveBarrel(path)
if path == 0 then
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
else
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
moveSafe(turtle.forward, turtle.inspect, noop)
turtle.turnRight()
end
end
function reportDuty(id, fuelconsumed)
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafeForward()
moveSafeForward()
moveSafeForward()
moveSafeForward()
moveSafeForward()
moveSafeForward()
moveSafeForward()
moveSafeForward()
rednet.open("bottom")
--print("Proto: Sending completed Job id")
rednet.broadcast(tostring(id), "jobs")
sleep(0.6)
--print("Proto: Sending fuel status")
rednet.broadcast(tostring(fuelconsumed), "fuel")
while true do
--print("Proto: Awaiting thanks")
sender, message, proto = rednet.receive("jobcomplete")
if message == "thanks" then
break
else
sleep(1)
end
end
--print("Proto: Received thanks")
end
function enqueueTurtle()
moveSafe(turtle.up, turtle.inspectUp, noop)
moveSafe(turtle.up, turtle.inspectUp, noop)
moveSafe(turtle.up, turtle.inspectUp, noop)
turtle.turnLeft()
moveSafeForward()
moveSafeForward()
moveSafeForward()
turtle.turnRight()
while true do
local status, block = turtle.inspectDown()
if not status then
if turtle.down() then
break -- we moved in line
end
else
if turtle.forward() then
-- pass, thats ok
else
local status, block = turtle.inspect()
if status and not block["name"]:lower():find("turtle") then
turtle.dig()
turtle.forward()
turtle.digUp()
turtle.digDown()
end
end
end
end
-- we moved into line
turtle.turnLeft()
turtle.turnLeft()
end
function doRefuel()
moveSafeForward()
turtle.turnRight()
while turtle.getFuelLevel() < 1500 do
turtle.suck(4)
selectFuel()
turtle.refuel()
end
turtle.turnLeft()
end
function goToJob()
moveSafeForward()
moveSafeForward()
moveSafeForward()
end
function waitForJob()
--print("Waiting for job...")
while true do
status, block = turtle.inspectDown()
if status and block["name"] == "computercraft:wired_modem_full" then
break
else
moveSafeForward()
end
end
rednet.open("bottom")
local retrying = false
while true do
rednet.broadcast("gibjob", "jobs")
sender, message, proto = rednet.receive("newjob", 2)
if message then
job = tonumber(message)
--print("Received job "..tostring(job))
return job
else
if not retrying then
retrying = true
--print("No job received. I will keep retrying.")
turtlestate["state"] = "Waiting for job... (retrying)"
end
end
end
end
function emptyToBarrel()
sleep(0.4)
for i = 1,16 do
turtle.select(i)
sleep(0.1)
turtle.dropDown()
end
end
function drawStatus()
print("Turtle ("..tostring(turtlestate["id"])..")")
print()
print(" \""..turtlestate["name"].."\"")
print()
if turtlestate["job"] then
print("Current job: "..tostring(turtlestate["job"]))
else
print("Current job: ")
end
print()
if turtlestate["startfuel"] then
print("Starting Fuel: "..tostring(turtlestate["startfuel"]))
else
print("Starting Fuel: ")
end
if turtlestate["job"] then
print("Recent fuel usage: "..tostring(turtlestate["fuel"]))
else
print("Recent fuel usage: ")
end
print()
print("Status:")
print(" "..turtlestate["state"])
if turtlestate["morestate"] then
print(" "..turtlestate["morestate"])
else
print()
end
--print(" "..turtlestate["state"])
turtlestate["morestate"] = nil
end
function turtleAI()
while true do
turtlestate["state"] = "Waiting for job..."
drawStatus()
thejob = waitForJob()
turtlestate["job"] = thejob
turtlestate["state"] = "Refueling..."
drawStatus()
doRefuel()
fuel = turtle.getFuelLevel()
turtlestate["state"] = "Headed to the jobsite..."
drawStatus()
goToJob()
x, z = ithSpot(thejob)
digTo(x,z)
turtlestate["state"] = "Digging the Shaft..."
drawStatus()
digShaft()
turtlestate["state"] = "Returning to the station..."
drawStatus()
goToSpawn(x, z)
path = math.floor(math.random() + 0.5)
turtlestate["state"] = "Unloading Inventory..."
drawStatus()
goToBarrel(path)
emptyToBarrel()
leaveBarrel(path)
fuelconsumed = fuel - turtle.getFuelLevel()
--print("I consumed "..tostring(fuelconsumed).." fuel")
--print("Reporting Duty")
turtlestate["fuel"] = fuelconsumed
turtlestate["state"] = "Reporting duty..."
drawStatus()
reportDuty(thejob, fuelconsumed)
turtlestate["job"] = nil
turtlestate["state"] = "Going back in line..."
drawStatus()
enqueueTurtle()
end
end
function updateState(update)
for k,v in pairs(update) do
turtlestate[k] = v
end
drawStatus()
end
function enqueueForJob2()
updateState({ state = "Waiting for job..." })
while true do
status, block = turtle.inspectDown()
if status and block["name"] == "computercraft:wired_modem_full" then
break
else
moveSafeForward()
end
end
turtle.turnLeft()
rednet.open("bottom")
local retrying = false
while true do
rednet.broadcast("syn")
server, message, proto = rednet.receive(2) -- ACK
if not message then
retrying = true
else
rednet.send(server, "gibjob")
_, job, _ = rednet.receive()
if job then
if job == "nojobs" then
updateState({ state = "Waiting for job... (retrying)" })
sleep(3)
else
return tonumber(job)
end
end
end
end
end
function faceDir(dir)
if ((direction - dir) % 4 == 2) then
turtle.turnRight()
turtle.turnRight()
direction = (direction + 2) % 4
elseif ((direction - dir) % 4 == 1) then
turtle.turnLeft()
direction = (direction -1) % 4
elseif ((direction - dir) % 4 == 3) then
turtle.turnRight()
direction = (direction + 1) % 4
end
end
-- directions: 0, 1, 2, 3 -> x, z, -x, -z
function goToCoordXZ2(targetX, targetZ, extraaction)
if targetX > x then
faceDir(0)
while (targetX > x) do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
x = x + 1
extraaction()
end
end
if targetX < x then
faceDir(2)
while (targetX < x) do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
x = x - 1
extraaction()
end
end
if targetZ > z then
faceDir(1)
while (targetZ > z) do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
z = z + 1
extraaction()
end
end
if targetZ < z then
faceDir(3)
while (targetZ < z) do
moveSafe(turtle.forward, turtle.inspect, turtle.dig)
z = z - 1
extraaction()
end
end
end
function goToJob2(job)
jobX, jobZ = iTo2Dcoords(job) -- this does all the magic
updateState({ state = "Going on the job...", morestate = "Jobsite is at ("..tostring(jobX)..", "..tostring(jobZ)..")" })
-- move to hole
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
-- reset coords, descend
x, z, direction = 0, 0, 0
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
-- go to job
function extraaction()
digSafe(turtle.inspectUp, turtle.digUp)
end
goToCoordXZ2(jobX, jobZ, extraaction)
end
function unloadStuffs()
updateState({ state = "Now unloading..." })
sleep(0.4)
for i = 1,16 do
turtle.select(i)
sleep(0.1)
turtle.drop()
end
end
function doRefuel2()
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
moveSafe(turtle.forward, turtle.inspect, noop)
curfuel = turtle.getFuelLevel()
targetfuel = 1500
if turtlestate["fuel"] ~= "" then
targetfuel = 4 * turtlestate["fuel"]
end
if curfuel > targetfuel then
return
end
updateState({ state = "Refueling... "..tostring(curfuel).." -> "..tostring(targetfuel) })
coalneeded = math.ceil((targetfuel - curfuel) / 80)
turtle.select(1)
while turtle.getFuelLevel() < targetfuel do
grabnow = math.min(coalneeded, 64)
if turtle.suckDown(grabnow) then
-- turtle can grab
turtle.refuel()
coalneeded = coalneeded - grabnow
else
-- blabla error
updateState({ state = "Refueling... Error: Out of coal" })
sleep(5)
end
end
updateState({ startfuel = turtle.getFuelLevel() })
end
slots = { {7,-6}, {7, -7}, {7, -8}, {7,-5}, {7,-4} }
function goToUnloading()
updateState({ state = "Going to unload resources..." })
moveSafe(turtle.up, turtle.inspectUp, turtle.digUp)
goToCoordXZ2(7, -6, noop)
moveSafe(turtle.up, turtle.inspectUp, turtle.digUp)
slot = math.ceil(math.random()*5)
storageX, storageZ = slots[slot][1], slots[slot][2]
goToCoordXZ2(storageX, storageZ, noop)
moveSafe(turtle.up, turtle.inspectUp, turtle.digUp)
faceDir(2)
moveSafe(turtle.forward, turtle.inspect, noop)
end
function reportDuty2()
updateState({ state = "Returning to report duty..." })
moveSafe(turtle.up, turtle.inspectUp, noop)
moveSafe(turtle.up, turtle.inspectUp, noop)
moveSafe(turtle.up, turtle.inspectUp, noop)
moveSafe(turtle.up, turtle.inspectUp, noop)
for i = 1,12 do
moveSafeForward()
end
rednet.open("top")
id = turtlestate["job"]
fuelconsumed = turtlestate["startfuel"] - turtle.getFuelLevel()
turtlestate["fuel"] = fuelconsumed
rednet.broadcast("syn")
server, _, _ = rednet.receive() -- ACK
rednet.send(server, "report")
rednet.send(server, tostring(id))
rednet.send(server, tostring(fuelconsumed))
for k, v in pairs(turtlestate["ores"]) do
rednet.send(server, k)
rednet.send(server, v)
end
turtlestate["ores"] = {}
rednet.broadcast("done", "ores")
server, _, _ = rednet.receive() -- thanks
end
function turtleAI2()
while true do
local job = enqueueForJob2()
turtlestate["job"] = job
doRefuel2()
--turtlestate["startfuel"] = turtle.getFuelLevel()
goToJob2(job)
digShaft()
goToUnloading()
unloadStuffs()
reportDuty2()
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
moveSafe(turtle.down, turtle.inspectDown, noop)
turtle.turnLeft()
end
end
-- turtleAI()
for i = 1, 10 do
print(iTo2Dcoords(i))
end

View File

@ -1,4 +1,5 @@
import math
import time
def pair(x, y):
return math.floor((x + y) * (x + y + 1)/2 + y)
@ -12,6 +13,12 @@ def unpairZ(z):
j = math.floor(math.sqrt(0.25 + 2*z) - 0.5)
return z - j * (j+1)/2;
def unpair2D(j):
quadrantI = j % 4 # 0-3 quadrant
x, z = int(unpairX(j)), int(unpairZ(j)) # coords in first quadrant
x, z = adjustToQuadrant(quadrantI, x, z) # map coords correctly into other quadrants
return x, z
lookup = [-10, 4, 1, 3, 0, 2]
def isDiggingSpot(x, y):
x, y = int(x), int(y)
@ -58,7 +65,22 @@ def iTo2Dcoords(j):
counter += 1
j += 1
print(iTo2Dcoords(3))
def findIfor(coords):
j = 0
counter = 0
while True:
x, z = unpair2D(j)
print(j, x, z)
if isDiggingSpot(x, z):
if (x, z) in coords:
print(f"{j} -> {x}, {z}")
coords.remove((x,z))
counter += 1
if not coords:
break
j += 1
time.sleep(0.6)
# for i in range(10):
# print(iTo2Dcoords(i))
findIfor([
(4, 0),
])