Advertisement
SethBling

NeuralEvolve.lua

Mar 13th, 2015
5,500
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.53 KB | None | 0 0
  1. console.clear()
  2.  
  3. boxRadius = 6
  4. buttonNames = {
  5. "A",
  6. "B",
  7. "X",
  8. "Y",
  9. "Up",
  10. "Down",
  11. "Left",
  12. "Right",
  13. }
  14.  
  15. layerSizes = {30, 10, 10, 10, #buttonNames}
  16.  
  17.  
  18. function getTile(dx, dy)
  19. marioX = memory.read_s16_le(0x94)
  20. marioY = memory.read_s16_le(0x96)
  21.  
  22. x = math.floor((marioX+dx)/16)
  23. y = math.floor((marioY+dy)/16)
  24.  
  25. return memory.readbyte(0xC800 + math.floor(x/0x10)*0x1B0 + y*0x10 + x%0x10)
  26. end
  27.  
  28. function getSprites()
  29. sprites = {}
  30. for slot=0,11 do
  31. status = memory.readbyte(0x14C8+slot)
  32. if status ~= 0 then
  33. spritex = memory.readbyte(0xE4+slot) + memory.readbyte(0x14E0+slot)*256
  34. spritey = memory.readbyte(0xD8+slot) + memory.readbyte(0x14D4+slot)*256
  35. sprites[#sprites+1] = {["x"]=spritex, ["y"]=spritey}
  36. end
  37. end
  38.  
  39. return sprites
  40. end
  41.  
  42. function getInputs()
  43. marioX = memory.read_s16_le(0x94)
  44. marioY = memory.read_s16_le(0x96)
  45.  
  46. sprites = getSprites()
  47.  
  48. inputs = {}
  49.  
  50. for dy=-boxRadius*16,boxRadius*16,16 do
  51. for dx=-boxRadius*16,boxRadius*16,16 do
  52. inputs[#inputs+1] = 0
  53.  
  54. tile = getTile(dx, dy)
  55. if tile ~= 0x25 and marioY+dy < 0x1B0 then
  56. inputs[#inputs] = 1
  57. end
  58.  
  59. for i = 1,#sprites do
  60. distx = math.abs(sprites[i]["x"] - (marioX+dx))
  61. disty = math.abs(sprites[i]["y"] - (marioY+dy))
  62. if distx < 8 and disty < 8 then
  63. inputs[#inputs] = -1
  64. end
  65. end
  66. end
  67. end
  68.  
  69. mariovx = memory.read_s8(0x7B)
  70. mariovy = memory.read_s8(0x7D)
  71. inputs[#inputs+1] = mariovx / 70
  72. inputs[#inputs+1] = mariovy / 70
  73.  
  74. return inputs
  75. end
  76.  
  77.  
  78. function evaluate(inputs, chromosome)
  79. layer = {}
  80. prevLayer = inputs
  81. c = 1
  82. for i=1,#layerSizes do
  83. layer = {}
  84. for n=1,layerSizes[i] do
  85. layer[n] = 0
  86. end
  87. for m=1,#layer do
  88. for n=1,#prevLayer do
  89. layer[m] = layer[m] + chromosome[c] * prevLayer[n]
  90. c = c + 1
  91. end
  92. layer[m] = math.atan(layer[m] + chromosome[c])
  93. c = c + 1
  94. end
  95. prevLayer = layer
  96. end
  97.  
  98. return layer
  99. end
  100.  
  101. function randomChromosome()
  102. c = {}
  103.  
  104. inputs = getInputs()
  105. prevSize = #inputs
  106. for i=1,#layerSizes do
  107. for m=1,layerSizes[i] do
  108. for n=1,prevSize do
  109. c[#c+1] = math.random()*2-1
  110. end
  111. c[#c+1] = math.random()*2-1
  112. end
  113. prevSize = layerSizes[i]
  114. end
  115.  
  116. return c
  117. end
  118.  
  119. pool = {}
  120. for i=1,20 do
  121. pool[i] = {["chromosome"] = randomChromosome(), ["fitness"] = 0}
  122. end
  123.  
  124. currentChromosome = 1
  125.  
  126. function initializeRun()
  127. savestate.load("YI2.state");
  128. rightmost = 0
  129. frame = 0
  130. timeout = 120
  131. end
  132.  
  133. function crossover(c1, c2)
  134. c = {["chromosome"] = {}, ["fitness"] = 0}
  135. pick = true
  136. for i=1,#c1["chromosome"] do
  137. if math.random(#c1["chromosome"]/4) == 1 then
  138. pick = not pick
  139. end
  140. if pick then
  141. c["chromosome"][i] = c1["chromosome"][i]
  142. else
  143. c["chromosome"][i] = c2["chromosome"][i]
  144. end
  145. end
  146.  
  147. return c
  148. end
  149.  
  150. function mutate(c)
  151. for i=1,#c["chromosome"] do
  152. if math.random(50) == 1 then
  153. c["chromosome"][i] = math.random()*2-1
  154. end
  155. end
  156. end
  157.  
  158. function createNewGeneration()
  159. index = {}
  160. table.sort(pool, function (a,b)
  161. return (a["fitness"] > b["fitness"])
  162. end)
  163.  
  164.  
  165. for i=((#pool)/2),(#pool) do
  166. c1 = pool[math.random(#pool/2)]
  167. c2 = pool[math.random(#pool/2)]
  168. pool[i] = crossover(c1, c2)
  169. mutate(pool[i])
  170. end
  171.  
  172. generation = generation + 1
  173. end
  174.  
  175. function clearJoypad()
  176. controller = {}
  177. for b = 1,#buttonNames do
  178. controller["P1 " .. buttonNames[b]] = false
  179. end
  180. joypad.set(controller)
  181. end
  182.  
  183. function showTop()
  184. clearJoypad()
  185. currentChromosome = 1
  186. initializeRun()
  187. end
  188.  
  189. form = forms.newform(200, 142, "Fitness")
  190. maxFitnessLabel = forms.label(form, "Top Fitness: ", 5, 8)
  191. goButton = forms.button(form, "Show Top", showTop, 5, 30)
  192. showUI = forms.checkbox(form, "Show Inputs", 5, 52)
  193. inputsLabel = forms.label(form, "Inputs", 5, 74)
  194.  
  195. function onExit()
  196. forms.destroy(form)
  197. end
  198. event.onexit(onExit)
  199.  
  200. generation = 0
  201. maxfitness = 0
  202. initializeRun()
  203.  
  204. while true do
  205. marioX = memory.read_s16_le(0x94)
  206. marioY = memory.read_s16_le(0x96)
  207.  
  208. if timeout <= 0 then
  209. fitness = rightmost - frame / 10
  210. pool[currentChromosome]["fitness"] = fitness
  211.  
  212. if fitness > maxfitness then
  213. forms.settext(maxFitnessLabel, "Top Fitness: " .. math.floor(fitness))
  214. maxfitness = fitness
  215. end
  216.  
  217. console.writeline("Generation " .. generation .. " chromosome " .. currentChromosome .. " fitness: " .. fitness)
  218. if currentChromosome == #pool then
  219. createNewGeneration()
  220. currentChromosome = #pool/2+1
  221. else
  222. currentChromosome = currentChromosome + 1
  223. end
  224. initializeRun()
  225. end
  226.  
  227. inputs = getInputs()
  228. if timeout > 2 and frame % 5 == 0 then
  229. outputs = evaluate(inputs, pool[currentChromosome]["chromosome"])
  230.  
  231. controller = {}
  232. inputsString = ""
  233. for n = 1,#buttonNames do
  234. if outputs[n] > 0 then
  235. controller["P1 " .. buttonNames[n]] = true
  236. inputsString = inputsString .. buttonNames[n]
  237. else
  238. controller["P1 " .. buttonNames[n]] = false
  239. end
  240. end
  241.  
  242. forms.settext(inputsLabel, inputsString)
  243. end
  244. joypad.set(controller)
  245.  
  246. if timeout <= 2 then
  247. clearJoypad()
  248. end
  249.  
  250. if marioX > rightmost then
  251. timeout = 120
  252. rightmost = marioX
  253. end
  254.  
  255. timeout = timeout - 1
  256. frame = frame + 1
  257.  
  258.  
  259. if forms.ischecked(showUI) then
  260. layer1x = memory.read_s16_le(0x1A);
  261. layer1y = memory.read_s16_le(0x1C);
  262.  
  263. for dy = 0,boxRadius*2 do
  264. for dx = 0,boxRadius*2 do
  265. input = inputs[dy*(boxRadius*2+1)+dx+1]
  266. gui.drawText(marioX+(dx-boxRadius)*16-layer1x,marioY+(dy-boxRadius)*16-layer1y,string.format("%i", input),0x80FFFFFF, 11)
  267. end
  268. end
  269. end
  270.  
  271. emu.frameadvance();
  272. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement