commit 4f84fa8348c7abba9a289b02b6b8220ff2d7cf0a Author: Christian Nelson Date: Sat Jan 9 11:09:22 2010 -0500 First commit diff --git a/A-star algorithm release.lua b/A-star algorithm release.lua new file mode 100644 index 0000000..5c5c9f6 --- /dev/null +++ b/A-star algorithm release.lua @@ -0,0 +1,206 @@ +--[[ +A* algorithm for LUA +Ported to LUA by Altair +21 septembre 2006 +--]] + +function CalcMoves(mapmat, px, py, tx, ty) -- Based on some code of LMelior but made it work and improved way beyond his code, still thx LMelior! +--[[ PRE: +mapmat is a 2d array +px is the player's current x +py is the player's current y +tx is the target x +ty is the target y + +Note: all the x and y are the x and y to be used in the table. +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. +--]] + +--[[ POST: +closedlist is a list with the checked nodes. +It will return nil if all the available nodes have been checked but the target hasn't been found. +--]] + + -- variables + local openlist={} -- Initialize table to store possible moves + local closedlist={} -- Initialize table to store checked gridsquares + local listk=1 -- List counter + local closedk=0 -- Closedlist counter + local tempH=math.abs(px-tx)+math.abs(py-ty) + local tempG=0 + openlist[1]={x=px, y=py, g=0, h=tempH, f=0+tempH ,par=1} -- Make starting point in list + local xsize=table.getn(mapmat[1]) -- horizontal map size + local ysize=table.getn(mapmat) -- vertical map size + local curbase={} -- Current square from which to check possible moves + local basis=1 -- Index of current base + + -- Growing loop + while listk>0 do + + -- Get the lowest f of the openlist + local lowestF=openlist[listk].f + basis=listk + for k=listk,1,-1 do + if openlist[k].f0 then + for k=1,closedk do + if closedlist[k].x==curbase.x+1 and closedlist[k].y==curbase.y then + rightOK=false + end + if closedlist[k].x==curbase.x-1 and closedlist[k].y==curbase.y then + leftOK=false + end + if closedlist[k].x==curbase.x and closedlist[k].y==curbase.y+1 then + downOK=false + end + if closedlist[k].x==curbase.x and closedlist[k].y==curbase.y-1 then + upOK=false + end + end + end + + -- Check if next points are on the map and within moving distance + if curbase.x+1>xsize then + rightOK=false + end + if curbase.x-1<1 then + leftOK=false + end + if curbase.y+1>ysize then + downOK=false + end + if curbase.y-1<1 then + upOK=false + end + + -- If it IS on the map, check map for obstacles + --(Lua returns an error if you try to access a table position that doesn't exist, so you can't combine it with above) + if curbase.x+1<=xsize and mapmat[curbase.y][curbase.x+1]~=0 then + rightOK=false + end + if curbase.x-1>=1 and mapmat[curbase.y][curbase.x-1]~=0 then + leftOK=false + end + if curbase.y+1<=ysize and mapmat[curbase.y+1][curbase.x]~=0 then + downOK=false + end + if curbase.y-1>=1 and mapmat[curbase.y-1][curbase.x]~=0 then + upOK=false + end + + -- check if the move from the current base is shorter then from the former parrent + tempG=curbase.g+1 + for k=1,listk do + if rightOK and openlist[k].x==curbase.x+1 and openlist[k].y==curbase.y and openlist[k].g>tempG then + tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty) + table.insert(openlist,k,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + rightOK=false + end + + if leftOK and openlist[k].x==curbase.x-1 and openlist[k].y==curbase.y and openlist[k].g>tempG then + tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty) + table.insert(openlist,k,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + leftOK=false + end + + if downOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y+1 and openlist[k].g>tempG then + tempH=math.abs((curbase.x)-tx)+math.abs(curbase.y+1-ty) + table.insert(openlist,k,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + downOK=false + end + + if upOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y-1 and openlist[k].g>tempG then + tempH=math.abs((curbase.x)-tx)+math.abs(curbase.y-1-ty) + table.insert(openlist,k,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + upOK=false + end + end + + -- Add points to openlist + -- Add point to the right of current base point + if rightOK then + listk=listk+1 + tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty) + table.insert(openlist,listk,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + end + + -- Add point to the left of current base point + if leftOK then + listk=listk+1 + tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty) + table.insert(openlist,listk,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + end + + -- Add point on the top of current base point + if downOK then + listk=listk+1 + tempH=math.abs(curbase.x-tx)+math.abs((curbase.y+1)-ty) + table.insert(openlist,listk,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + end + + -- Add point on the bottom of current base point + if upOK then + listk=listk+1 + tempH=math.abs(curbase.x-tx)+math.abs((curbase.y-1)-ty) + table.insert(openlist,listk,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk}) + end + + table.remove(openlist,basis) + listk=listk-1 + + if closedlist[closedk].x==tx and closedlist[closedk].y==ty then + return closedlist + end + end + + return nil +end + +function CalcPath(closedlist) +--[[ PRE: +closedlist is a list with the checked nodes. +OR nil if all the available nodes have been checked but the target hasn't been found. +--]] + +--[[ POST: +path is a list with all the x and y coords of the nodes of the path to the target. +OR nil if closedlist==nil +--]] + + if closedlist==nil then + return nil + end + local path={} + local pathIndex={} + local last=table.getn(closedlist) + table.insert(pathIndex,1,last) + + local i=1 + while pathIndex[i]>1 do + i=i+1 + table.insert(pathIndex,i,closedlist[pathIndex[i-1]].par) + end + + for n=table.getn(pathIndex),1,-1 do + table.insert(path,{x=closedlist[pathIndex[n]].x, y=closedlist[pathIndex[n]].y}) + end + + closedlist=nil + return path +end \ No newline at end of file diff --git a/A-star test release.lua b/A-star test release.lua new file mode 100644 index 0000000..fb32e49 --- /dev/null +++ b/A-star test release.lua @@ -0,0 +1,172 @@ +--[[ +This a little program to test my A* algorithm for LUA +Made by Altair +21 septembre 2006 +--]] + +dofile("A-star algorithm release.lua") + +wit=Color.new(255,255,255) +rood=Color.new(255,0,0) +groen=Color.new(0,255,0) +grijs=Color.new(100,100,100) +blauw=Color.new(0,0,255) + +x=100 +y=100 +player={x=0, y=0, xmove=0, ymove=0, speed=5, path={}, cur=1, pathLength=0, move=false} +orderMove=false +deler=16 +xInterval=50 +yInterval=50 + +Player=Image.createEmpty(xInterval-1, yInterval-1) +Player:clear(groen) + +map= { + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + } + +function drawGrid(map,xInterval,yInterval,color) + local w=table.getn(map[1]) + local h=table.getn(map) + for n=1,w do + if n*xInterval<480 then + screen:drawLine(n*xInterval,0,n*xInterval,h*yInterval,color) + end + end + for n=1,h do + if n*yInterval<272 then + screen:drawLine(0,n*yInterval,w*xInterval,n*yInterval,color) + end + end +end + +function drawBlock(map,xInterval,yInterval,color) + local w=table.getn(map[1]) + local h=table.getn(map) + for n=1,w do + for i=1,h do + if map[i][n]==1 then + screen:fillRect((n-1)*xInterval+1, (i-1)*yInterval+1, xInterval-1, yInterval-1, color) + end + end + end +end + +while true do + + screen:clear() + + drawGrid(map,xInterval,yInterval,grijs) + drawBlock(map,xInterval,yInterval,blauw) + + screen:blit(player.x+1,player.y+1,Player) + screen:drawLine(x-5, y, x+5, y, wit) + screen:drawLine(x, y-5, x, y+5, wit) + + pad = Controls.read() + + dx = pad:analogX() + if math.abs(dx) > 32 then + x = x + dx / deler + end + + dy = pad:analogY() + if math.abs(dy) > 32 then + y = y + dy / deler + end + + if x<0 then + x=0 + end + + if y<0 then + y=0 + end + + if x>=table.getn(map[1])*xInterval then + x=table.getn(map[1])*xInterval-1 + end + + if y>=table.getn(map)*yInterval then + y=table.getn(map)*yInterval-1 + end + + local mapx=math.floor(x/xInterval)+1 + local mapy=math.floor(y/yInterval)+1 + +if pad~=oldpad then + if pad:cross() then + orderMove=true + end + + if pad:square() then + if map[mapy][mapx]==0 then + map[mapy][mapx]=1 + elseif map[mapy][mapx]==1 then + map[mapy][mapx]=0 + end + end + + if pad:l() then + deler=deler*2 + end + + if pad:r() then + deler=deler/2 + end + + if pad:start() then + break + end +end +oldpad=pad + + if orderMove==true then + player.path=CalcPath(CalcMoves(map, math.floor(player.x/xInterval)+1, math.floor(player.y/yInterval)+1, mapx, mapy)) + if player.path==nil then + orderMove=false + end + if player.path~=nil then + player.pathLength=table.getn(player.path) + player.cur=1 + player.xmove=(player.path[player.cur].x*xInterval)-xInterval + player.ymove=(player.path[player.cur].y*yInterval)-yInterval + orderMove=false + player.move=true + end + end + + -- Movement +if player.move==true then + if player.xmove>player.x then + player.x=player.x+player.speed + elseif player.xmoveplayer.y then + player.y=player.y+player.speed + elseif player.ymove=player.pathLength then + player.move=false + end +end + +screen:print(0,264,"A* algorithm for LUA - Ported by Altair 2006",wit) +screen.waitVblankStart() +screen:flip() + +end \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..e69de29