Advertisement
Kirkq

7th Saga Pathing RNG

Dec 6th, 2015
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.41 KB | None | 0 0
  1. --Nitrodon's 7th Saga A* algorithm to walk between towns and avoid encounters, modified by Kirkq to choose varying paths and tend towards the extremes more often and record RNG values to force more or less incrementing.
  2.  
  3. local xdest = 170
  4. local ydest = 52
  5. local savestateinterval
  6.  
  7. --Melenam: 156,252
  8. --Palsu: 120,234
  9. --Gorfun: 170,52
  10. --Guanas: 100,88
  11.  
  12. local xmin = 0
  13. local xmax = 511
  14. local ymin = 0
  15. local ymax = 511
  16. local map1 = 0xce7134
  17. local map2 = 0xce6154
  18. local map3 = 0xce0000
  19. local map4 = 0xce48e0
  20. local sector1
  21. local sector2
  22. local sector3
  23. local sector4
  24. local xcoord
  25. local ycoord
  26. local distance = {[xdest]={[ydest]=0}}
  27. local paths = {[xdest]={[ydest]=1}}
  28. local dx={0,0,-1,1}
  29. local dy={-1,1,0,0}
  30. local dir
  31. local keys
  32. local directions = {"up", "down", "left", "right"}
  33. local optimalpaths = {}
  34. local npaths = {}
  35. local pathdir = {[0]=1}
  36. local stopped = {}
  37. local step
  38. local replay
  39.  
  40. --
  41.  
  42. local randomnum
  43.  
  44. local RNGTable = {}
  45. local RNGStart = 256*memory.readbyte(0x7e006E) + memory.readbyte(0x7e006C)
  46. local RNGValue = RNGStart
  47. local TableLength = 3500 -- Length of RNG Table, make larger for longer distances.
  48. local TableLoopCount = 0
  49.  
  50. local TableBreak
  51. local RNGEnd
  52. local BestRNGAmt = 6000  --Amount of RNGs passed  (set high/low for initial comparison)
  53.  
  54. local tempstate = {}
  55. local value
  56.  
  57. local scriptloop = 0
  58. local scriptlooplimit = 10 -- how many times to run to completion
  59.  
  60. local xtotal
  61. local ytotal
  62. local distotal
  63. local xtendency
  64.  
  65. local CurrAttemptLoads
  66. local MaxAttemptLoads = 160 -- how many times to try a certain attempt
  67.  
  68. moviefile = "MemDump.vbm"
  69. dumpfile = moviefile..".dump"
  70. io.output(dumpfile)
  71.  
  72. value = 5   -- Call optimal state as State5
  73. tempstate[value] = savestate.create()
  74. savestate.save(tempstate[value])
  75. value = 0  --  Call base state as state 0
  76. tempstate[value] = savestate.create()
  77. savestate.save(tempstate[value])
  78.  
  79.  
  80. while TableLoopCount < TableLength do   ---makes a table of RNG values 0 to table length
  81.     RNGTable[TableLoopCount] = RNGValue
  82.     RNGValue = RNGValue*899 - 65536*(math.floor(RNGValue*899/65536))
  83.     TableLoopCount = TableLoopCount + 1
  84. end
  85. --RNG*899 mod 65536
  86.  
  87.  
  88.  
  89. function updatevalue(newx, newy, xcoord, ycoord, distance, paths, changed)
  90.     if newx >= xmin and newx <= xmax and newy >= ymin and newy <= ymax then
  91.         sector1 = math.floor(newx/32) + 16*math.floor(newy/32) -- check for map collision
  92.         sector2 = AND(newx, 0x18)/8 + AND(newy, 0x18)/2
  93.         sector3 = AND(newx, 0x6)/2 + 2*AND(newy, 0x6)
  94.         sector4 = math.fmod(newx, 2) + 2*math.fmod(newy, 2)
  95.         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
  96.             if distance[newx] == nil then
  97.                 distance[newx] = {}
  98.                 paths[newx] = {}
  99.             end
  100.             if distance[newx][newy] == nil or distance[newx][newy] > distance[xcoord][ycoord]+1 then
  101.                 distance[newx][newy] = distance[xcoord][ycoord] + 1
  102.                 paths[newx][newy] = paths[xcoord][ycoord]
  103.                 table.insert(changed,{x=newx, y=newy})
  104.             elseif distance[newx][newy] == distance[xcoord][ycoord]+1 then
  105.                 paths[newx][newy] = paths[newx][newy] + paths[xcoord][ycoord]
  106.             end
  107.         end
  108.     end
  109. end
  110.  
  111.  
  112. --checks to see that distance to destination has lowered.
  113. function isoptimal(newx, newy, xcoord, ycoord, distance)
  114.     if distance[newx] ~= nil and distance[newx][newy] ~= nil and distance[newx][newy] == distance[xcoord][ycoord] - 1 then
  115.         return true
  116.     else
  117.         return false
  118.     end
  119. end
  120.  
  121. --function only runs after cycle is done.
  122. function nextframe()
  123.     gui.text(0,0,"RNG1: " .. memory.readbyte(0x7E006C))
  124.     gui.text(0,10,"RNG2: " .. memory.readbyte(0x7E006E))
  125.     if memory.readbyte(0x7e0722) ~= 2 then
  126.         xcoord = math.floor((memory.readword(0x7e07a8) + memory.readword(0x7e0a91)+16)/32)
  127.         ycoord = math.floor((memory.readword(0x7e07b0) + memory.readword(0x7e0a94)+16)/32)
  128.         region = math.floor(xcoord/8) - 64*math.floor(xcoord/512) + 64*math.floor(ycoord/8) - 4096*math.floor(ycoord/512)
  129.         encmap = memory.readword(0x7e07a3) + 0x10000*memory.readbyte(0x7e07a5)
  130.         gui.text(0,180,"Current location: (" .. xcoord .. ", " .. ycoord .. ")")
  131.         if memory.readbyte(0x7e0723) ~= 2 then
  132.             gui.text(0,190,"Encounter region: " .. memory.readbyte(encmap+region))
  133.             if distance[xcoord] ~= nil and distance[xcoord][ycoord] ~= nil then
  134.                 gui.text(0,200,"Distance: " .. distance[xcoord][ycoord])
  135.                 gui.text(0,210,"Paths: " .. paths[xcoord][ycoord])
  136.             end
  137.         end
  138.     else
  139.         gui.text(0,190,"Enemy HP:")
  140.         if AND(memory.readword(0x7e1e9e),0xa000) == 0 then
  141.             gui.text(96,190,memory.readword(0x7e1e84))
  142.         end
  143.         if AND(memory.readword(0x7e1f1e),0xa000) == 0 then
  144.             gui.text(160,190,memory.readword(0x7e1f04))
  145.         end
  146.         if AND(memory.readword(0x7e1f9e),0xa000) == 0 then
  147.             gui.text(224,190,memory.readword(0x7e1f84))
  148.         end
  149.     end
  150.     snes9x.frameadvance()
  151. end
  152. --
  153.  
  154. ---Begin Cycle
  155. snes9x.speedmode("maximum")
  156.  
  157. local i = 1
  158. local changed = {{x=xdest,y=ydest}}
  159. while i <= # changed do
  160.     xcoord = changed[i].x
  161.     ycoord = changed[i].y
  162.     updatevalue(xcoord-1, ycoord, xcoord, ycoord, distance, paths, changed)
  163.     updatevalue(xcoord+1, ycoord, xcoord, ycoord, distance, paths, changed)
  164.     updatevalue(xcoord, ycoord-1, xcoord, ycoord, distance, paths, changed)
  165.     updatevalue(xcoord, ycoord+1, xcoord, ycoord, distance, paths, changed)
  166.     i = i + 1
  167. end
  168.  
  169.  
  170. while scriptloop < scriptlooplimit do
  171.     CurrAttemptLoads = 0
  172.     savestateinterval = math.random(20)
  173.     if savestateinterval < 6 then
  174.     savestateinterval = savestateinterval + 5
  175.     end
  176.  
  177.     value = 0
  178.     savestate.load(tempstate[value])
  179.  
  180.     nextframe()
  181.  
  182.     value = 0
  183.     savestate.load(tempstate[value])
  184.    
  185.     randomnum = math.random(100)
  186.     xtendency = randomnum
  187.     if xtendency < 5 then   ---prev 5
  188.     xtendency = xtendency + 5  ---prev 5
  189.     elseif xtendency > 95 then  ----prev 95
  190.     xtendency = xtendency - 5    ---prev 5
  191.     end
  192.  
  193.     while memory.readbyte(0x7e0712) ~= 0 do
  194.     nextframe()
  195.     end -- wait until input is accepted
  196.    
  197.    
  198.         xcoord = math.floor((memory.readword(0x7e07a8) + memory.readword(0x7e0a91)+16)/32)
  199.         ycoord = math.floor((memory.readword(0x7e07b0) + memory.readword(0x7e0a94)+16)/32)
  200.     xtotal = xdest - xcoord
  201.     ytotal = ydest - ycoord
  202.    
  203.     if xtotal < 0 then
  204.     xtotal = -1*xtotal
  205.     end
  206.     if ytotal < 0 then
  207.     ytotal = -1*xtotal
  208.     end
  209.     distotal = xtotal + ytotal 
  210.    
  211.     xtotal = xdest - xcoord  --recalc
  212.     ytotal = ydest - ycoord
  213.    
  214.    
  215.    
  216.     local states = {}
  217.     replay = false
  218.     step = 0
  219.     repeat
  220.         step = step + 1
  221.         if math.mod(step, savestateinterval) == 1 and not replay then
  222.             if states[step] == nil then
  223.                 states[step] = savestate.create()
  224.             end
  225.             savestate.save(states[step])
  226.         end
  227.         xcoord = math.floor((memory.readword(0x7e07a8) + memory.readword(0x7e0a91)+16)/32)
  228.         ycoord = math.floor((memory.readword(0x7e07b0) + memory.readword(0x7e0a94)+16)/32)
  229.    
  230.    
  231.         if optimalpaths[step] == nil then
  232.             optimalpaths[step] = {}
  233.         end
  234.    
  235.         if not replay then
  236.             npaths[step] = 0
  237.             for i=1,4 do
  238.                 optimalpaths[step][i] = isoptimal(xcoord+dx[i],ycoord+dy[i],xcoord,ycoord,distance)
  239.                 npaths[step] = npaths[step] + (optimalpaths[step][i] and 1 or 0)
  240.             end
  241.     end
  242.    
  243.     if stopped[step] then
  244.             replay = false
  245.         end
  246.    
  247.     if replay then
  248.     dir = pathdir[step]
  249.    
  250.     else
  251.    
  252.  
  253.        
  254.         randomnum = math.random(100)
  255.         --xtotal positive = walk right
  256.         --ytotal positive = walk up
  257.         -- xtendency = 75%
  258.        
  259.         if randomnum < xtendency then
  260.             if xtotal >= 0 then
  261.             randomnum = 4
  262.             else
  263.             randomnum = 3
  264.             end
  265.         else  -- if ytendency
  266.             if ytotal <=0 then   ---should be less than
  267.             randomnum = 1
  268.             else
  269.             randomnum = 2
  270.             end
  271.         end
  272.        
  273.        
  274.        
  275.        
  276.         --determines directions below
  277.         --1=up 2=down 3=left 4=right--------------------------------------
  278.        
  279.         --Would do well to associate weighted probabilities based on how many
  280.         --steps are being taken in each direction.  I can implement this later.
  281.    
  282.         if randomnum == 1 then
  283.             if optimalpaths[step][1] then
  284.             dir=1
  285.             elseif optimalpaths[step][2] then
  286.             dir=2
  287.             elseif optimalpaths[step][3] then
  288.             dir=3
  289.             elseif optimalpaths[step][4] then
  290.             dir=4
  291.             end
  292.        
  293.         elseif randomnum == 2 then    
  294.             if optimalpaths[step][2] then
  295.             dir=2
  296.             elseif optimalpaths[step][1] then
  297.             dir=1
  298.             elseif optimalpaths[step][4] then
  299.             dir=4
  300.             elseif optimalpaths[step][3] then
  301.             dir=3  
  302.             end
  303.        
  304.         elseif randomnum == 3 then
  305.             if optimalpaths[step][3] then
  306.             dir=3
  307.             elseif optimalpaths[step][4] then
  308.             dir=4
  309.             elseif optimalpaths[step][1] then
  310.             dir=1
  311.             elseif optimalpaths[step][2] then
  312.             dir=2
  313.             end
  314.        
  315.         elseif randomnum == 4 then
  316.             if optimalpaths[step][4] then
  317.             dir=4
  318.             elseif optimalpaths[step][3] then
  319.             dir=3
  320.             elseif optimalpaths[step][2] then
  321.             dir=2
  322.             elseif optimalpaths[step][1] then
  323.             dir=1  
  324.             end
  325.         end
  326.    
  327.    
  328.        
  329.         end
  330.    
  331.    
  332.    
  333.    
  334.    
  335.         pathdir[step] = dir
  336.         keys = {[directions[dir]]=true}
  337.         for i=1,16 do
  338.         gui.text(0,20,"X Tendency" .. xtendency)
  339.         gui.text(0,30,"CurrAttemptLoads" .. CurrAttemptLoads)
  340.         gui.text(0,40,"Trial Number" .. scriptloop)
  341.         gui.text(0,50,"savestateinterval" .. savestateinterval)
  342.             joypad.set(1,keys)
  343.             nextframe()
  344.         end
  345.         if memory.readbyte(0x7e0722) == 2 then
  346.             repeat
  347.                 stopped[step] = true
  348.                 optimalpaths[step][pathdir[step]] = false
  349.                 npaths[step] = npaths[step] - 1
  350.                 step = step - 1
  351.             until step == 0 or npaths[step+1] ~= 0
  352.             step = savestateinterval * math.floor(step/savestateinterval)
  353.             savestate.load(states[step+1])
  354.             replay = true
  355.         CurrAttemptLoads = CurrAttemptLoads + 1
  356.         else
  357.             stopped[step] = false
  358.         end
  359.     until ((xcoord == xdest and ycoord == ydest) or (CurrAttemptLoads>=MaxAttemptLoads))
  360.    
  361.    
  362.     for i =1,3 do
  363.     nextframe()
  364.     end
  365.    
  366.     RNGEnd = 256*memory.readbyte(0x7e006E) + memory.readbyte(0x7e006C)
  367.    
  368.     TableLoopCount = 0   --  Can be edited to later
  369.     TableBreak = 0
  370.     while TableLoopCount < TableLength and TableBreak == 0 do
  371.         TableLoopCount = TableLoopCount+1
  372.         if RNGEnd == RNGTable[TableLoopCount] then
  373.             TableBreak = 1
  374.         end
  375.     end
  376.    
  377.     if CurrAttemptLoads < MaxAttemptLoads then
  378.     if BestRNGAmt > TableLoopCount then  ---change sign depending on whether you want more or less, and change value of TableLoopCount to large or 0.
  379.         BestRNGAmt = TableLoopCount  --Note: if this gives back the initial TableLoopCount, it is off the chart.
  380.         value = 5
  381.         savestate.save(tempstate[value])
  382.        
  383.         ----pathdir[step] contain all steps 0 to n
  384.         while step > 0 do
  385.             io.write(pathdir[step]," ")   --writes in steps backwards**
  386.             step = step-1
  387.         end
  388.         io.write(BestRNGAmt)
  389.         io.write("\n")
  390.        
  391.     end
  392.     end
  393.    
  394.  
  395. scriptloop = scriptloop + 1
  396.    
  397. end  
  398.    
  399.     value = 5
  400.     savestate.load(tempstate[value])
  401.    
  402.     snes9x.speedmode("normal")
  403.     snes9x.pause()
  404.    
  405.     for i =1,3 do
  406.     nextframe()
  407.     end
  408.  
  409. while true do nextframe() end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement