Advertisement
Kirkq

7th Saga Pathing

Dec 6th, 2015
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.43 KB | None | 0 0
  1. --Nitrodon's 7th Saga A* algorithm to walk between towns and avoid encounters.
  2.  
  3. local xdest = 482
  4. local ydest = 130
  5. local savestateinterval = 20
  6.  
  7. local xmin = 0
  8. local xmax = 511
  9. local ymin = 0
  10. local ymax = 511
  11. local map1 = 0xce7134
  12. local map2 = 0xce6154
  13. local map3 = 0xce0000
  14. local map4 = 0xce48e0
  15. local sector1
  16. local sector2
  17. local sector3
  18. local sector4
  19. local xcoord
  20. local ycoord
  21. local distance = {[xdest]={[ydest]=0}}
  22. local paths = {[xdest]={[ydest]=1}}
  23. local dx={0,0,-1,1}
  24. local dy={-1,1,0,0}
  25. local dir
  26. local keys
  27. local directions = {"up", "down", "left", "right"}
  28. local optimalpaths = {}
  29. local npaths = {}
  30. local pathdir = {[0]=1}
  31. local stopped = {}
  32. local step
  33. local replay
  34.  
  35. function updatevalue(newx, newy, xcoord, ycoord, distance, paths, changed)
  36.     if newx >= xmin and newx <= xmax and newy >= ymin and newy <= ymax then
  37.         sector1 = math.floor(newx/32) + 16*math.floor(newy/32) -- check for map collision
  38.         sector2 = AND(newx, 0x18)/8 + AND(newy, 0x18)/2
  39.         sector3 = AND(newx, 0x6)/2 + 2*AND(newy, 0x6)
  40.         sector4 = math.fmod(newx, 2) + 2*math.fmod(newy, 2)
  41.         if AND(memory.readbyte(memory.readbyte(memory.readword(memory.readbyte(map1+sector1)*32+map2+2*sector2)*16+map3+sector3)*32+map4+1),2^(5-sector4)) == 0 then
  42.             if distance[newx] == nil then
  43.                 distance[newx] = {}
  44.                 paths[newx] = {}
  45.             end
  46.             if distance[newx][newy] == nil or distance[newx][newy] > distance[xcoord][ycoord]+1 then
  47.                 distance[newx][newy] = distance[xcoord][ycoord] + 1
  48.                 paths[newx][newy] = paths[xcoord][ycoord]
  49.                 table.insert(changed,{x=newx, y=newy})
  50.             elseif distance[newx][newy] == distance[xcoord][ycoord]+1 then
  51.                 paths[newx][newy] = paths[newx][newy] + paths[xcoord][ycoord]
  52.             end
  53.         end
  54.     end
  55. end
  56.  
  57.  
  58. --checks to see that distance to destination has lowered.
  59. function isoptimal(newx, newy, xcoord, ycoord, distance)
  60.     if distance[newx] ~= nil and distance[newx][newy] ~= nil and distance[newx][newy] == distance[xcoord][ycoord] - 1 then
  61.         return true
  62.     else
  63.         return false
  64.     end
  65. end
  66.  
  67. --function only runs after cycle is done.
  68. function nextframe()
  69.     if memory.readbyte(0x7e0722) ~= 2 then
  70.         xcoord = math.floor((memory.readword(0x7e07a8) + memory.readword(0x7e0a91)+16)/32)
  71.         ycoord = math.floor((memory.readword(0x7e07b0) + memory.readword(0x7e0a94)+16)/32)
  72.         region = math.floor(xcoord/8) - 64*math.floor(xcoord/512) + 64*math.floor(ycoord/8) - 4096*math.floor(ycoord/512)
  73.         encmap = memory.readword(0x7e07a3) + 0x10000*memory.readbyte(0x7e07a5)
  74.         gui.text(0,180,"Current location: (" .. xcoord .. ", " .. ycoord .. ")")
  75.         if memory.readbyte(0x7e0723) ~= 2 then
  76.             gui.text(0,190,"Encounter region: " .. memory.readbyte(encmap+region))
  77.             if distance[xcoord] ~= nil and distance[xcoord][ycoord] ~= nil then
  78.                 gui.text(0,200,"Distance: " .. distance[xcoord][ycoord])
  79.                 gui.text(0,210,"Paths: " .. paths[xcoord][ycoord])
  80.             end
  81.         end
  82.     else
  83.         gui.text(0,190,"Enemy HP:")
  84.         if AND(memory.readword(0x7e1e9e),0xa000) == 0 then
  85.             gui.text(96,190,memory.readword(0x7e1e84))
  86.         end
  87.         if AND(memory.readword(0x7e1f1e),0xa000) == 0 then
  88.             gui.text(160,190,memory.readword(0x7e1f04))
  89.         end
  90.         if AND(memory.readword(0x7e1f9e),0xa000) == 0 then
  91.             gui.text(224,190,memory.readword(0x7e1f84))
  92.         end
  93.     end
  94.     snes9x.frameadvance()
  95. end
  96. --
  97.  
  98. ---Begin Cycle
  99. snes9x.speedmode("maximum")
  100.  
  101. local i = 1
  102. local changed = {{x=xdest,y=ydest}}
  103. while i <= # changed do
  104.     xcoord = changed[i].x
  105.     ycoord = changed[i].y
  106.     updatevalue(xcoord-1, ycoord, xcoord, ycoord, distance, paths, changed)
  107.     updatevalue(xcoord+1, ycoord, xcoord, ycoord, distance, paths, changed)
  108.     updatevalue(xcoord, ycoord-1, xcoord, ycoord, distance, paths, changed)
  109.     updatevalue(xcoord, ycoord+1, xcoord, ycoord, distance, paths, changed)
  110.     i = i + 1
  111. end
  112.  
  113. while memory.readbyte(0x7e0712) ~= 0 do nextframe() end -- wait until input is accepted
  114.  
  115. if distance[xcoord] ~= nil and distance[xcoord][ycoord] ~= nil then
  116.     local states = {}
  117.     replay = false
  118.     step = 0
  119.     repeat
  120.         step = step + 1
  121.         if math.mod(step, savestateinterval) == 1 and not replay then
  122.             if states[step] == nil then
  123.                 states[step] = savestate.create()
  124.             end
  125.             savestate.save(states[step])
  126.         end
  127.         xcoord = math.floor((memory.readword(0x7e07a8) + memory.readword(0x7e0a91)+16)/32)
  128.         ycoord = math.floor((memory.readword(0x7e07b0) + memory.readword(0x7e0a94)+16)/32)
  129.         if optimalpaths[step] == nil then
  130.             optimalpaths[step] = {}
  131.         end
  132.         if not replay then
  133.             npaths[step] = 0
  134.             for i=1,4 do
  135.                 optimalpaths[step][i] = isoptimal(xcoord+dx[i],ycoord+dy[i],xcoord,ycoord,distance)
  136.                 npaths[step] = npaths[step] + (optimalpaths[step][i] and 1 or 0)
  137.             end
  138.         end
  139.         if stopped[step] then
  140.             replay = false
  141.         end
  142.         if optimalpaths[step][pathdir[step-1]] then
  143.             dir=pathdir[step-1]
  144.         elseif optimalpaths[step][1+XOR(pathdir[step-1]-1,2)] then
  145.             dir=1+XOR(pathdir[step-1]-1,2)
  146.         elseif optimalpaths[step][1+XOR(pathdir[step-1]-1,3)] then
  147.             dir=1+XOR(pathdir[step-1]-1,3)
  148.         elseif optimalpaths[step][1+XOR(pathdir[step-1]-1,1)] then
  149.             dir=1+XOR(pathdir[step-1]-1,1)
  150.         else
  151.             break
  152.         end
  153.         pathdir[step] = dir
  154.         keys = {[directions[dir]]=true}
  155.         for i=1,16 do
  156.             joypad.set(1,keys)
  157.             nextframe()
  158.         end
  159.         if memory.readbyte(0x7e0722) == 2 then
  160.             repeat
  161.                 stopped[step] = true
  162.                 optimalpaths[step][pathdir[step]] = false
  163.                 npaths[step] = npaths[step] - 1
  164.                 step = step - 1
  165.             until step == 0 or npaths[step+1] ~= 0
  166.             step = savestateinterval * math.floor(step/savestateinterval)
  167.             savestate.load(states[step+1])
  168.             replay = true
  169.         else
  170.             stopped[step] = false
  171.         end
  172.     until xcoord == xdest and ycoord == ydest
  173.     snes9x.speedmode("normal")
  174.     snes9x.pause()
  175. end
  176.  
  177. while true do nextframe() end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement