Skip to content

Commit cf8aa34

Browse files
committed
add act/do scripts
1 parent f55948c commit cf8aa34

File tree

2 files changed

+303
-0
lines changed

2 files changed

+303
-0
lines changed

act.cc.lua

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
-- TODO
2+
-- history
3+
-- save
4+
-- actor (rednet)
5+
-- blueprints
6+
-- relative coords/facing
7+
-- return home
8+
-- infinite loop
9+
-- waypoints
10+
-- mini language for making scripts smaller
11+
-- and doing ad-hoc commands faster
12+
--
13+
-- look down in the handlers for all the commands
14+
-- you can put a number afterwards to repeat a single command
15+
-- you can put parenthesis around a list and a number after that to repeat several commands
16+
-- detect and compare will break out of parethesis
17+
--
18+
-- examples:
19+
-- Chop down tree to a max height of 48
20+
--
21+
-- Dff(?uDuu)48d48
22+
--
23+
-- Here is how the commands are interpreted
24+
--
25+
-- Df - turtle.dig()
26+
-- f - turtle.forward()
27+
-- ( - for i = 1, 48 do
28+
-- ?u - if not turtle.detectUp() then break end
29+
-- Du - turtle.digUp()
30+
-- u - turtle.up()
31+
-- ) 48 - end
32+
-- d 48 - for i = 1, 48 do turtle.down() end
33+
--
34+
-- You can use the language in other scripts like so
35+
--
36+
-- os.loadAPI("act")
37+
-- act.act("f5rrf5ll")
38+
39+
-- act internal functions
40+
41+
local forward = 0
42+
local up = 1
43+
local down = 2
44+
local tMove = {[forward] = turtle.forward,
45+
[up] = turtle.up,
46+
[down] = turtle.down}
47+
local tDetect = {[forward] = turtle.detect,
48+
[up] = turtle.detectUp,
49+
[down] = turtle.detectDown}
50+
local tAttack = {[forward] = turtle.attack,
51+
[up] = turtle.attackUp,
52+
[down] = turtle.attackDown}
53+
local tDig = {[forward] = turtle.dig,
54+
[up] = turtle.digUp,
55+
[down] = turtle.digDown}
56+
local tPlace = {[forward] = turtle.place,
57+
[up] = turtle.placeUp,
58+
[down] = turtle.placeDown}
59+
60+
local function tryDir(dir)
61+
while not tMove[dir]() do
62+
if tDetect[dir]() then
63+
tDig[dir]()
64+
else
65+
tAttack[dir]()
66+
end
67+
end
68+
return true
69+
end
70+
71+
-- act turtle functions
72+
73+
function try()
74+
return tryDir(forward)
75+
end
76+
77+
function tryUp()
78+
return tryDir(up)
79+
end
80+
81+
function tryDown()
82+
return tryDir(down)
83+
end
84+
85+
local currentSlot = 1
86+
function select(slot)
87+
currentSlot = slot
88+
turtle.select(slot)
89+
return true
90+
end
91+
92+
local function findSimilar()
93+
for s = 1, 16 do
94+
if s ~= currentSlot then
95+
turtle.select(s)
96+
if turtle.compareTo(currentSlot) then
97+
turtle.select(currentSlot)
98+
return s
99+
end
100+
end
101+
end
102+
turtle.select(currentSlot)
103+
return nil
104+
end
105+
106+
local function placeDir(dir)
107+
if turtle.getItemCount(currentSlot) == 1 then
108+
local resupplySlot = findSimilar()
109+
if resupplySlot then
110+
if tPlace[dir]() then
111+
turtle.select(resupplySlot)
112+
turtle.transferTo(currentSlot, turtle.getItemCount(resupplySlot))
113+
turtle.select(currentSlot)
114+
return true
115+
else
116+
return false
117+
end
118+
else
119+
return tPlace[dir]()
120+
end
121+
else
122+
return tPlace[dir]()
123+
end
124+
end
125+
126+
function place()
127+
return placeDir(forward)
128+
end
129+
130+
function placeUp()
131+
return placeDir(up)
132+
end
133+
134+
function placeDown()
135+
return placeDir(down)
136+
end
137+
138+
-- command handlers
139+
140+
local tHandlers = {
141+
-- move
142+
["f"] = turtle.forward,
143+
["b"] = turtle.back,
144+
["u"] = turtle.up,
145+
["d"] = turtle.down,
146+
["l"] = turtle.turnLeft,
147+
["r"] = turtle.turnRight,
148+
-- others
149+
["s"] = select,
150+
["t"] = turtle.transfer,
151+
["R"] = turtle.refuel,
152+
-- dig
153+
["Df"] = turtle.dig,
154+
["Du"] = turtle.digUp,
155+
["Dd"] = turtle.digDown,
156+
-- attach
157+
["Af"] = turtle.attack,
158+
["Au"] = turtle.attackUp,
159+
["Ad"] = turtle.attackDown,
160+
-- place
161+
["Pf"] = place,
162+
["Pu"] = placeUp,
163+
["Pd"] = placeDown,
164+
-- suck
165+
["Sf"] = turtle.suck,
166+
["Su"] = turtle.suckUp,
167+
["Sd"] = turtle.suckDown,
168+
-- drop (E for eject)
169+
["Ef"] = turtle.drop,
170+
["Eu"] = turtle.dropUp,
171+
["Ed"] = turtle.dropDown,
172+
-- try, dig routing with anti-gravel/sand and anti-mob logic
173+
["Tf"] = try,
174+
["Tu"] = tryUp,
175+
["Td"] = tryDown,
176+
-- detect
177+
["?f"] = turtle.detect,
178+
["?u"] = turtle.detectUp,
179+
["?d"] = turtle.detectDown,
180+
-- compare
181+
["=f"] = turtle.compare,
182+
["=u"] = turtle.compareUp,
183+
["=d"] = turtle.compareDown,
184+
["=="] = turtle.compareTo,
185+
186+
["z"] = sleep
187+
}
188+
189+
function getNumber(s, pos, max, default)
190+
if tonumber(s:sub(pos + 1, pos + 1)) == nil then
191+
return default, pos
192+
else
193+
local n = 0
194+
while pos <= max and tonumber(s:sub(pos + 1, pos + 1)) ~= nil do
195+
pos = pos + 1
196+
n = n * 10 + tonumber(s:sub(pos, pos))
197+
end
198+
return n, pos
199+
end
200+
end
201+
202+
function act(plan)
203+
local pos = 1
204+
local max = plan:len()
205+
while pos <= max do
206+
local c = plan:sub(pos, pos)
207+
if c == "(" then
208+
-- read until matching )
209+
local p = 1
210+
local sub_plan = ""
211+
while p > 0 do
212+
pos = pos + 1
213+
if plan:sub(pos, pos) == ")" then
214+
p = p - 1
215+
elseif plan:sub(pos, pos) == "(" then
216+
p = p + 1
217+
end
218+
if p > 0 then
219+
sub_plan = sub_plan .. plan:sub(pos, pos)
220+
end
221+
end
222+
-- get optional count
223+
local n = nil
224+
n, pos = getNumber(plan, pos, max, 1)
225+
-- call recursively
226+
for i = 1, n, 1 do
227+
if not act(sub_plan, n) then
228+
print("sub plan failure")
229+
return false
230+
end
231+
end
232+
else
233+
if c == "D"
234+
or c == "A"
235+
or c == "P"
236+
or c == "S"
237+
or c == "E"
238+
or c == "T"
239+
or c == "?"
240+
or c == "=" then
241+
pos = pos + 1
242+
c = c .. plan:sub(pos, pos)
243+
end
244+
-- call handler
245+
local fn = tHandlers[c]
246+
if fn then
247+
if c == "f" or c == "b" or c == "u" or c == "d" or c == "l" or c == "r" or c == "Tf" or c == "Td" or c == "Tu" then
248+
-- move handlers, number defines iterations
249+
-- get optional count
250+
local n = nil
251+
n, pos = getNumber(plan, pos, max, 1)
252+
for i = 1, n, 1 do
253+
if not fn() then
254+
if turtle.getFuelLevel() == 0 then
255+
print("Out of fuel")
256+
return false -- stop entire plan
257+
else
258+
print("Blocked: " .. plan:sub(1, pos) .. " / " .. plan:sub(pos + 1))
259+
return false -- stop entire plan
260+
end
261+
end
262+
end
263+
elseif c:sub(1,1) == "?" or c:sub(1,1) == "=" then
264+
-- detect and compare, failure will only skip out of the current block
265+
local result = nil
266+
if c == "==" then
267+
local n = nil
268+
n, pos = getNumber(plan, pos, max, 1)
269+
result = fn(n)
270+
else
271+
result = fn()
272+
end
273+
if not result then
274+
return true -- stop current plan
275+
end
276+
else
277+
-- all other handlers, number gets passed to function
278+
local n = nil
279+
n, pos = getNumber(plan, pos, max)
280+
if not fn(n) then
281+
print("Can't perform action: " .. c)
282+
-- return false
283+
end
284+
end
285+
else
286+
print("Unknown command: " .. c)
287+
return false
288+
end
289+
end
290+
pos = pos + 1
291+
end
292+
return true
293+
end

do.cc.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- command line interfact to act api
2+
-- you will need the act script
3+
local tArgs = { ... }
4+
if #tArgs ~= 1 then
5+
print( "Usage: do <list of commands>" )
6+
return
7+
end
8+
os.loadAPI("act")
9+
local plan = tArgs[1]
10+
act.act(plan)

0 commit comments

Comments
 (0)