-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdig2x_controller.lua
254 lines (231 loc) · 6.37 KB
/
dig2x_controller.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
local PROTOCOL_NAME = 'remote_dig'
local status = {DISCONNECTED = 'DISCONNECTED',
CONNECTING = 'CONNECTING',
CONNECTED = 'CONNECTED',
DIGGING = 'DIGGING',
MOVING = 'MOVING'}
local utils = require('lib.utils')
local names = {
'Fenrir',
'Odin',
'Freya',
'Karthus',
'Ares',
'Apollo',
'Zeus',
'Poseidon',
'Hades',
'Chronus',
'Baco',
'Nautilus',
'Artemis',
'Ornn',
'Zed',
'Thor',
'Loki'
}
local function table_count(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
local turtles = {}
local run = true
local direction = 'left'
local depth = 60
local function send_cmd(func, args, turtle_id)
local turtle = turtles[turtle_id]
if turtle == nil then
return nil
end
local job_id = turtle.last_job_id + 1
local job = {
id = job_id,
func = func,
args = args,
ts = os.time()
}
turtle.pending_cmds[job_id] = job
rednet.send(turtle_id, job, PROTOCOL_NAME)
end
local function gen_random_name()
if table_count(turtles) >= #names then
return nil
end
while true do
local name = names[math.random(#names)]
local ok = true
for _, v in ipairs(turtles) do
if v.name == name then
ok = false
break
end
end
if ok then
return name
end
end
end
local function msg_handler(id, msg)
print(id .. ' ' .. textutils.serialise(msg))
local turtle = turtles[id]
if turtle == nil then
return
end
if msg.id == nil then
return
end
local job = turtle.pending_cmds[msg.id]
if job == nil then
return
end
local func = job.func
local args = job.args
local ret = msg.return_value
if func == 'connect' then
if turtle.status == status.CONNECTING then
turtle.status = status.CONNECTED
turtle.name = ret
table.remove(turtle.pending_cmds, msg.id)
end
elseif func == 'dig' then
if ret == nil then
turtle.status = status.DIGGING
else
turtle.status = status.CONNECTED
table.remove(turtle.pending_cmds, msg.id)
end
elseif func == 'move' then
if ret == nil then
turtle.status = status.MOVING
else
turtle.status = status.CONNECTED
table.remove(turtle.pending_cmds, msg.id)
end
end
end
local function list_turtles()
for k, v in pairs(turtles) do
print(k .. ' ' .. v.name .. ' ' .. v.status)
end
end
local function scan_mode()
while true do
utils.clearAndResetTerm()
print('Searching for turtles...')
print('Press "q" to stop')
table.sort(turtles)
list_turtles()
rednet.broadcast({
id = 0,
func = 'search',
args = nil
}, PROTOCOL_NAME)
local timer = os.startTimer(2)
local event_data = { os.pullEvent() }
local event = event_data[1]
if event == 'rednet_message' then
os.cancelTimer(timer)
local id, msg = event_data[2], event_data[3]
if id ~= nil then
if msg.id == 0 then
if msg.return_value == true then
if turtles[id] ~= nil then
send_cmd('connect', turtles[id].name, id)
else
local name = gen_random_name()
if name ~= nil then
turtles[id] = {
status = status.CONNECTING,
name = name,
last_job_id = 0,
pending_cmds = {}
}
send_cmd('connect', name, id)
end
end
end
else
msg_handler(id, msg)
end
end
elseif event == 'char' then
local character = event_data[2]
if character == 'q' then
return
end
end
end
end
local function change_direction()
if direction=='left' then
direction ='right'
else
direction = 'left'
end
end
local function set_depth()
write('depth: ')
local msg=read()
local depth_num=tonumber(msg)
if depth_num ~= nil then
depth=depth_num
end
end
local function dig()
for k, v in pairs(turtles) do
send_cmd('dig', depth, k)
end
end
local function move()
for k, v in pairs(turtles) do
send_cmd('move', {direction = direction, ammount = table_count(turtles)}, k)
end
end
local function main_menu()
while true do
utils.clearAndResetTerm()
utils.write_center('Turtle Controller')
term.setCursorPos(1,3)
print(string.format('direction: %s, depth: %d, turtles: %d', direction, depth, table_count(turtles)))
list_turtles()
print('q -> quit')
print('r -> change direction')
print('t -> set depth')
print('s -> scan mode')
print('d -> dig')
print('m -> move')
local timer = os.startTimer(2)
local event_data = { os.pullEvent() }
local event = event_data[1]
if event == 'char' then
os.cancelTimer(timer)
local character = event_data[2]
if character == 'q' then break
elseif character == 's' then scan_mode()
elseif character == 'd' then dig()
elseif character == 'm' then move()
elseif character == 'r' then change_direction()
elseif character == 't' then set_depth()
end
elseif event == 'rednet_message' then
os.cancelTimer(timer)
msg_handler(event_data[2], event_data[3])
end
end
end
local function startup()
utils.rednet_all_modems()
rednet.broadcast({ func = 'disconnect', args = {}, id = 0 }, PROTOCOL_NAME)
term.setCursorPos(1, 1)
term.clear()
term.setCursorPos(1, 1)
print('Starting...')
sleep(1)
turtles = {}
end
startup()
main_menu()
for k, _ in pairs(turtles) do
send_cmd('disconnect', nil, k)
end