Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function Split(s, delimiter)
- result = {};
- for match in (s..delimiter):gmatch("(.-)"..delimiter) do
- table.insert(result, match);
- end
- return result;
- end
- function waitFrames(n)
- for i=1,n,1 do
- emu.frameadvance()
- end
- end
- function waitForEvent(addr, eventType, val)
- val = val or nil
- flag = false
- if (eventType == "r") then
- f = event.onmemoryread
- elseif (eventType == "w") then
- f = event.onmemorywrite
- elseif (eventType == "x") then
- f = event.onmemoryexecute
- else
- print("waitForEvent ERROR: invalid eventType")
- end
- f(function()
- if (eventType == "x" or val == nil or mainmemory.readbyte(addr) == val) then
- flag = true
- end
- end)
- while (~flag) do
- emu.frameadvance()
- end
- if (~event.unregisterbyid(guid)) then
- print("waitForEvent ERROR: could not unregister event")
- end
- end
- function waitForRead(addr, val)
- val = val or nil
- waitForEvent(addr, "r", val)
- end
- function waitForWrite(addr, val)
- val = val or nil
- waitForEvent(addr, "w", val)
- end
- function waitForExecute(addr)
- waitForEvent(addr, "x", nil)
- end
- function node(n)
- return { name = n, state = nil, parent = nil, children = nil, cn = 0, value = 0, visits = 0 }
- end
- function selection(node)
- topChild = nil
- topScore = -999
- c = math.sqrt(2)
- k = 0.5
- for i, kid in pairs(node.children) do
- if (kid.visits > 0) then
- score = (kid.value / (kid.visits) ) + c * math.sqrt( ( 2 * math.log(node.visits) ) / (kid.visits) )
- else
- score = k + c * math.sqrt( ( 2 * math.log(node.visits) ) / (node.cn + 1) )
- end
- if score > topScore then
- topChild = kid
- topScore = score
- end
- end
- --If unvisited child is chosen, increase the "expanded children" counter
- if topChild.visits == 0 then node.cn = node.cn + 1 end
- return topChild
- end
- function MonteCarloTreeSearch(game, n, root)
- for i=1,n,1 do
- curNode = root
- curNode.visits = curNode.visits + 1
- while (curNode.state ~= nil) do
- if (curNode.children == nil) then
- game.expand(curNode)
- end
- curNode = selection(curNode)
- curNode.visits = curNode.visits + 1
- end
- memorysavestate.loadcorestate(curNode.parent.state)
- game.perform(curNode.name)
- curNode.state = memorysavestate.savecorestate()
- game.rollout()
- result = game.score()
- if game.loseFlag then
- result = 0
- game.loseFlag = false
- end
- while (curNode ~= nil) do
- curNode.value = curNode.value + result;
- curNode = curNode.parent
- end
- end
- topKid = nil
- topScore = -999
- for i, kid in pairs(root.children) do
- if (kid.value / kid.visits > topScore) then
- topKid = kid
- topScore = kid.value / kid.visits
- end
- end
- return topKid
- end
- function simulate(game, N, n)
- for i, trigger in ipairs(game.winTriggers) do
- event.onmemoryexecute(game.setWinFlag, trigger)
- end
- for i, trigger in ipairs(game.loseTriggers) do
- event.onmemoryexecute(game.setLoseFlag, trigger)
- end
- root = node(nil)
- root.state = memorysavestate.savecorestate()
- for i=1,N,1 do
- root = MonteCarloTreeSearch(game, n, root)
- memorysavestate.loadcorestate(root.state)
- root.parent = nil
- end
- end
- OnimushaTactics = {
- name = "Onimusha Tactics",
- winFlag = false,
- winTriggers =
- {
- },
- setWinFlag = function()
- winFlag = true
- end,
- loseFlag = false,
- loseTriggers =
- {
- },
- setLoseFlag = function()
- loseFlag = true
- end,
- getActs = function()
- acts = {}
- -- If game mode is "unit select"
- -- List of actions =
- -- * Selecting each unit
- -- * Ending turn
- -- If game mode is "unit menu"
- -- List of actions =
- -- * Each Move //
- -- * Each Attack // For these two, run the appropriate function(s) to generate legal tiles then restore savestate
- -- * Done
- return acts
- end,
- expand = function(p)
- acts = getActs()
- kids = {}
- for k,v in pairs(acts) do
- kids[k] = node(k)
- kids[k].parent = p
- end
- p.children = kids
- end,
- perform = function(act)
- -- If action is "finish turn"
- -- Menu
- -- Select "finish turn"
- -- Press A
- -- Set wait for "start of player turn" game mode
- -- If action is "select unit"
- -- Parse unit # from action string name
- -- Find x/y pos of that unit
- -- Move cursor to that position
- -- Press A
- -- Set wait for "unit menu" game mode
- -- else if action is "move"
- -- Move cursor to "Move"
- -- Press A
- -- Set wait for "move" game mode
- -- Parse x/y position from action string name
- -- Move cursor to that position
- -- Press A
- -- Set wait for "unit menu" game mode
- -- else if action is "attack"
- -- Move cursor to "Attack"
- -- Press A
- -- Set wait for "attack" game mode
- -- Parse x/y position from action string name
- -- Move cursor to that position
- -- Press A
- -- Set wait for "unit menu" game mode
- -- else if action is "done"
- -- Select done
- -- Press A
- -- If all units are done, set wait for "start of player turn" function
- -- Else set wait for "unit select" game mode
- end,
- rollout = function()
- --Rollout logic:
- ---Random action until end
- while (~winFlag and ~loseFlag) do
- acts = getActs()
- a = chooseRandom(acts) -- implement this
- perform(a)
- end
- end,
- score = function()
- UNIT_ADDR = 0x28DC
- UNIT_SIZE = 0xEC
- total = 0
- for i=0,15,1 do
- curUnit = UNIT_ADDR + UNIT_SIZE*i
- unitID = mainmemory.readbyte(curUnit)
- if unitID ~= 0 and unitID <= 15 then
- unitLVL = mainmemory.readbyte(curUnit+40)
- unitEXP = mainmemory.readbyte(curUnit+180)
- total = total + 100*unitLVL + unitEXP
- end
- end
- return total
- end
- }
- simulate(OnimushaTactics, 10, 10)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement