SHOW:
|
|
- or go back to the newest paste.
1 | --[[ Header | |
2 | ColorWars algorithm for LUA | |
3 | Authors: Akuukis, Hugo, LatvianModder, TomsG | |
4 | Started: May 1, 2014 | |
5 | - | local i=0 |
5 | + | First Beta release: - |
6 | - | local j=0 |
6 | + | First Alpha release: - |
7 | Github address: https://github.com/Akuukis/TurtleColorWars | |
8 | - | function hugoDebug() |
8 | + | --]] |
9 | - | modem.transmit(3, 1337, x.." "..y) |
9 | + | --[[Structure |
10 | Main - Starts Init. and afterwards runs Job,Supp,Comm in paralel. Subclasses Nav,Debug,Stats are present. | |
11 | - | function hugoSurfaceMove() |
11 | + | Init.## Initiation - Initiates the turtle so it could operate |
12 | - | hugoDebug() |
12 | + | Job.### Decision Making - Turtle weights alternatives, chooses his next AIM (strategy level) and does it (tactical level) |
13 | - | if turtle.forward() then |
13 | + | Supp.## Maintance - Turtle's AIM can be interrupted by inside events, like low on fuel, full backpack or afraid of night. Overrides AIM & does it. |
14 | - | while turtle.detectDown()~=true do |
14 | + | Comm.## Communication - Turtle's AIM can be interrupted by outside events, like call for help or direct command. Sets AIM & does Job##. |
15 | - | if turtle.down() then z=z-1 end |
15 | + | Nav.### Navigation - Turtle goes to point XYZ (sub-tactical level) and constantly updates internal map. |
16 | Debug.# Debug - (sub-tactical level) | |
17 | - | if dir%4==0 then x=x+1 end |
17 | + | Stats.# Statistics - Turtle collents & stores individual statistics for fun purposes only. |
18 | - | if dir%4==1 then y=y+1 end |
18 | + | --]] |
19 | - | if dir%4==2 then x=x-1 end |
19 | + | |
20 | - | if dir%4==3 then y=y-1 end |
20 | + | Supp = { |
21 | - | else |
21 | + | Refuel = function(self) |
22 | - | while turtle.detect() do |
22 | + | if turtle.refuel()then |
23 | - | if turtle.up() then z=z+1 end |
23 | + | write("Refueled!\n") |
24 | else | |
25 | write("Fuel me!\n") | |
26 | end | |
27 | - | |
27 | + | |
28 | - | |
28 | + | } |
29 | - | turtle.refuel() |
29 | + | Nav = { |
30 | - | for i=0,math.random(3,5) do |
30 | + | SurfaceMove = function(self) |
31 | - | for j=0,math.random(0,3) do |
31 | + | Debug:Hugo(x,y) |
32 | - | turtle.turnRight() |
32 | + | if turtle.forward() then |
33 | - | dir=dir+1 |
33 | + | while turtle.detectDown()~=true do |
34 | if turtle.down() then z=z-1 end | |
35 | - | for j=0,math.random(5,10) do |
35 | + | end |
36 | - | hugoSurfaceMove() |
36 | + | Stats:Step() |
37 | if dir%4==0 then x=x+1 end | |
38 | if dir%4==1 then y=y+1 end | |
39 | - | |
39 | + | if dir%4==2 then x=x-1 end |
40 | - | |
40 | + | if dir%4==3 then y=y-1 end |
41 | - | turtle.up() |
41 | + | else |
42 | - | turtle.down() |
42 | + | while turtle.detect() do |
43 | - | if y<0 then |
43 | + | if turtle.up() then z=z+1 end |
44 | - | while dir%4~=1 do |
44 | + | end |
45 | - | turtle.turnRight() |
45 | + | |
46 | - | dir=dir+1 |
46 | + | end, |
47 | GetLost1 = function(self) | |
48 | - | while y<0 do hugoSurfaceMove() end |
48 | + | for i=0,math.random(3,5) do |
49 | write("GetLost No." .. i .. ": ") | |
50 | - | if y>0 then |
50 | + | for j=0,math.random(0,3) do |
51 | - | while dir%4~=3 do |
51 | + | turtle.turnRight() |
52 | - | turtle.turnRight() |
52 | + | dir=dir+1 |
53 | - | dir=dir+1 |
53 | + | end |
54 | write("Turned to " .. dir%4 .. ", ") | |
55 | - | while y>0 do hugoSurfaceMove() end |
55 | + | for j=0,math.random(5,10) do |
56 | Nav:SurfaceMove() | |
57 | - | if x<0 then |
57 | + | end |
58 | - | while dir%4~=0 do |
58 | + | write("Went " .. Stats:GetCountedSteps() .. "sq\n") |
59 | - | turtle.turnRight() |
59 | + | Stats:ResetCountedSteps() |
60 | - | dir=dir+1 |
60 | + | |
61 | end, | |
62 | - | while x<0 do hugoSurfaceMove() end |
62 | + | GoToStupid = function(self) |
63 | write("I am at (" .. x .. "," .. y .. "). Going home!\n") | |
64 | - | if x>0 then |
64 | + | turtle.up() |
65 | - | while dir%4~=2 do |
65 | + | turtle.down() |
66 | - | turtle.turnRight() |
66 | + | if y<0 then |
67 | - | dir=dir+1 |
67 | + | while dir%4~=1 do |
68 | turtle.turnRight() | |
69 | - | while x>0 do hugoSurfaceMove() end |
69 | + | dir=dir+1 |
70 | - | end |
70 | + | end |
71 | while y<0 do Nav:SurfaceMove() end | |
72 | end | |
73 | if y>0 then | |
74 | while dir%4~=3 do | |
75 | turtle.turnRight() | |
76 | dir=dir+1 | |
77 | end | |
78 | while y>0 do Nav:SurfaceMove() end | |
79 | end | |
80 | if x<0 then | |
81 | while dir%4~=0 do | |
82 | turtle.turnRight() | |
83 | dir=dir+1 | |
84 | end | |
85 | while x<0 do Nav:SurfaceMove() end | |
86 | end | |
87 | if x>0 then | |
88 | while dir%4~=2 do | |
89 | turtle.turnRight() | |
90 | dir=dir+1 | |
91 | end | |
92 | while x>0 do Nav:SurfaceMove() end | |
93 | end | |
94 | write("I am home!\n") | |
95 | end, | |
96 | CalcMoves = function(mapmat, px, py, tx, ty) -- Based on some code of LMelior but made it work and improved way beyond his code. | |
97 | --[[ | |
98 | A* algorithm for LUA | |
99 | Ported to LUA by Altair | |
100 | 21 septembre 2006 | |
101 | --]] | |
102 | --[[ PRE: | |
103 | mapmat is a 2d array | |
104 | px is the player's current x | |
105 | py is the player's current y | |
106 | tx is the target x | |
107 | ty is the target y | |
108 | ||
109 | Note: all the x and y are the x and y to be used in the table. | |
110 | By this I mean, if the table is 3 by 2, the x can be 1,2,3 and the y can be 1 or 2. | |
111 | --]] | |
112 | ||
113 | --[[ POST: | |
114 | closedlist is a list with the checked nodes. | |
115 | It will return nil if all the available nodes have been checked but the target hasn't been found. | |
116 | --]] | |
117 | ||
118 | -- variables | |
119 | local openlist={} -- Initialize table to store possible moves | |
120 | local closedlist={} -- Initialize table to store checked gridsquares | |
121 | local listk=1 -- List counter | |
122 | local closedk=0 -- Closedlist counter | |
123 | local tempH=math.abs(px-tx)+math.abs(py-ty) | |
124 | local tempG=0 | |
125 | openlist[1]={x=px, y=py, g=0, h=tempH, f=0+tempH ,par=1} -- Make starting point in list | |
126 | local xsize=table.getn(mapmat[1]) -- horizontal map size | |
127 | local ysize=table.getn(mapmat) -- vertical map size | |
128 | local curbase={} -- Current square from which to check possible moves | |
129 | local basis=1 -- Index of current base | |
130 | ||
131 | -- Growing loop | |
132 | while listk>0 do | |
133 | ||
134 | -- Get the lowest f of the openlist | |
135 | local lowestF=openlist[listk].f | |
136 | basis=listk | |
137 | for k=listk,1,-1 do | |
138 | if openlist[k].f<lowestF then | |
139 | lowestF=openlist[k].f | |
140 | basis=k | |
141 | end | |
142 | end | |
143 | ||
144 | closedk=closedk+1 | |
145 | table.insert(closedlist,closedk,openlist[basis]) | |
146 | ||
147 | curbase=closedlist[closedk] -- define current base from which to grow list | |
148 | ||
149 | local rightOK=true | |
150 | local leftOK=true -- Booleans defining if they're OK to add | |
151 | local downOK=true -- (must be reset for each while loop) | |
152 | local upOK=true | |
153 | ||
154 | -- Look through closedlist | |
155 | if closedk>0 then | |
156 | for k=1,closedk do | |
157 | if closedlist[k].x==curbase.x+1 and closedlist[k].y==curbase.y then | |
158 | rightOK=false | |
159 | end | |
160 | if closedlist[k].x==curbase.x-1 and closedlist[k].y==curbase.y then | |
161 | leftOK=false | |
162 | end | |
163 | if closedlist[k].x==curbase.x and closedlist[k].y==curbase.y+1 then | |
164 | downOK=false | |
165 | end | |
166 | if closedlist[k].x==curbase.x and closedlist[k].y==curbase.y-1 then | |
167 | upOK=false | |
168 | end | |
169 | end | |
170 | end | |
171 | ||
172 | -- Check if next points are on the map and within moving distance | |
173 | if curbase.x+1>xsize then | |
174 | rightOK=false | |
175 | end | |
176 | if curbase.x-1<1 then | |
177 | leftOK=false | |
178 | end | |
179 | if curbase.y+1>ysize then | |
180 | downOK=false | |
181 | end | |
182 | if curbase.y-1<1 then | |
183 | upOK=false | |
184 | end | |
185 | ||
186 | -- If it IS on the map, check map for obstacles | |
187 | --(Lua returns an error if you try to access a table position that doesn't exist, so you can't combine it with above) | |
188 | if curbase.x+1<=xsize and mapmat[curbase.y][curbase.x+1]~=0 then | |
189 | rightOK=false | |
190 | end | |
191 | if curbase.x-1>=1 and mapmat[curbase.y][curbase.x-1]~=0 then | |
192 | leftOK=false | |
193 | end | |
194 | if curbase.y+1<=ysize and mapmat[curbase.y+1][curbase.x]~=0 then | |
195 | downOK=false | |
196 | end | |
197 | if curbase.y-1>=1 and mapmat[curbase.y-1][curbase.x]~=0 then | |
198 | upOK=false | |
199 | end | |
200 | ||
201 | -- check if the move from the current base is shorter then from the former parrent | |
202 | tempG=curbase.g+1 | |
203 | for k=1,listk do | |
204 | if rightOK and openlist[k].x==curbase.x+1 and openlist[k].y==curbase.y and openlist[k].g>tempG then | |
205 | tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty) | |
206 | table.insert(openlist,k,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
207 | rightOK=false | |
208 | end | |
209 | ||
210 | if leftOK and openlist[k].x==curbase.x-1 and openlist[k].y==curbase.y and openlist[k].g>tempG then | |
211 | tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty) | |
212 | table.insert(openlist,k,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
213 | leftOK=false | |
214 | end | |
215 | ||
216 | if downOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y+1 and openlist[k].g>tempG then | |
217 | tempH=math.abs((curbase.x)-tx)+math.abs(curbase.y+1-ty) | |
218 | table.insert(openlist,k,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
219 | downOK=false | |
220 | end | |
221 | ||
222 | if upOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y-1 and openlist[k].g>tempG then | |
223 | tempH=math.abs((curbase.x)-tx)+math.abs(curbase.y-1-ty) | |
224 | table.insert(openlist,k,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
225 | upOK=false | |
226 | end | |
227 | end | |
228 | ||
229 | -- Add points to openlist | |
230 | -- Add point to the right of current base point | |
231 | if rightOK then | |
232 | listk=listk+1 | |
233 | tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty) | |
234 | table.insert(openlist,listk,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
235 | end | |
236 | ||
237 | -- Add point to the left of current base point | |
238 | if leftOK then | |
239 | listk=listk+1 | |
240 | tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty) | |
241 | table.insert(openlist,listk,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
242 | end | |
243 | ||
244 | -- Add point on the top of current base point | |
245 | if downOK then | |
246 | listk=listk+1 | |
247 | tempH=math.abs(curbase.x-tx)+math.abs((curbase.y+1)-ty) | |
248 | table.insert(openlist,listk,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
249 | end | |
250 | ||
251 | -- Add point on the bottom of current base point | |
252 | if upOK then | |
253 | listk=listk+1 | |
254 | tempH=math.abs(curbase.x-tx)+math.abs((curbase.y-1)-ty) | |
255 | table.insert(openlist,listk,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) | |
256 | end | |
257 | ||
258 | table.remove(openlist,basis) | |
259 | listk=listk-1 | |
260 | ||
261 | if closedlist[closedk].x==tx and closedlist[closedk].y==ty then | |
262 | return closedlist | |
263 | end | |
264 | end | |
265 | ||
266 | return nil | |
267 | end, | |
268 | CalcPath = function(closedlist) | |
269 | --[[ PRE: | |
270 | closedlist is a list with the checked nodes. | |
271 | OR nil if all the available nodes have been checked but the target hasn't been found. | |
272 | --]] | |
273 | ||
274 | --[[ POST: | |
275 | path is a list with all the x and y coords of the nodes of the path to the target. | |
276 | OR nil if closedlist==nil | |
277 | --]] | |
278 | ||
279 | if closedlist==nil then | |
280 | return nil | |
281 | end | |
282 | local path={} | |
283 | local pathIndex={} | |
284 | local last=table.getn(closedlist) | |
285 | table.insert(pathIndex,1,last) | |
286 | ||
287 | local i=1 | |
288 | while pathIndex[i]>1 do | |
289 | i=i+1 | |
290 | table.insert(pathIndex,i,closedlist[pathIndex[i-1]].par) | |
291 | end | |
292 | ||
293 | for n=table.getn(pathIndex),1,-1 do | |
294 | table.insert(path,{x=closedlist[pathIndex[n]].x, y=closedlist[pathIndex[n]].y}) | |
295 | end | |
296 | ||
297 | closedlist=nil | |
298 | return path | |
299 | end | |
300 | } | |
301 | Debug = { | |
302 | Hugo = function(self, x, y) | |
303 | modem.transmit(3, 1337, x.." "..y) | |
304 | end | |
305 | } | |
306 | Stats = { | |
307 | GlobalSteps = 0, | |
308 | CountedSteps = 0, | |
309 | Step = function(self, x) | |
310 | x = x or 1 -- create object if user does not provide one | |
311 | Stats.GlobalSteps = Stats.GlobalSteps + 1 | |
312 | Stats.CountedSteps = Stats.CountedSteps + 1 | |
313 | end, | |
314 | GetGlobalSteps = function(self) | |
315 | return Stats.GlobalSteps | |
316 | end, | |
317 | GetCountedSteps = function(self) | |
318 | return Stats.CountedSteps | |
319 | end, | |
320 | ResetCountedSteps = function(self) | |
321 | Stats.CountedSteps = 0 | |
322 | end | |
323 | } | |
324 | ||
325 | dir=0 | |
326 | x=0 | |
327 | y=0 | |
328 | z=0 | |
329 | modem = peripheral.wrap("left") | |
330 | ||
331 | Supp:Refuel() | |
332 | Nav:GetLost1() | |
333 | Nav:GoToStupid() |