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() |