AWDS TAS bot by me and STL. …Probably only works on USA ROM.
Required resources file: http://tasvideos.org/userfiles/info/46695978680246991
require 'resources'
-- Functions to get info for input creation
local function getActivePowerInfo(COAddr)
local value = memory.readbyte(COAddr + 1)
local TAGorSCOPActive = bit.band(value, 8)
local COPActive = bit.band(value, 4)
return TAGorSCOPActive + COPActive
end
local function getNumPowersUsed(COAddr)
local value = memory.readbyte(COAddr + 1) + bit.lshift(memory.readbyte(COAddr + 2), 8)
return bit.rshift(value, 6) % 16
end
local function getPowerCostFactor(Usages)
if Usages >= 10 then
return 2
else
return 1 + Usages * 0.2
end
end
local function getNumUseablePowers()
local COAddr = 0x218936C
local COID = memory.readbyte(COAddr)
if COID > 0 then
local PowersUsed = getNumPowersUsed(COAddr)
local Factor = getPowerCostFactor(PowersUsed)
local COPCost = getCOPCost(COID)
local SCOPCost = getSCOPCost(COID)
local Stars = bit.rshift(memory.readword(COAddr + 2), 4) / 100
local ActivePower = getActivePowerInfo(COAddr)
if ActivePower ~= 0 then
return 0
end
local PowerCount = 0
-- COP charged?
if Stars >= COPCost * Factor then
-- Von Bolt
if COPCost ~= -1 then
PowerCount = PowerCount + 1
end
-- SCOP charged?
if Stars >= SCOPCost * Factor then
PowerCount = PowerCount + 1
-- TAG?
local COAddr2 = 0x2189370
local COID2 = memory.readbyte(COAddr2)
if COID2 > 0 then
local PowersUsed2 = getNumPowersUsed(COAddr2)
local Factor2 = getPowerCostFactor(PowersUsed2)
local SCOPCost2 = getSCOPCost(COID2)
local Stars2 = bit.rshift(memory.readword(COAddr2 + 2), 4) / 100
if Stars2 >= SCOPCost2 * Factor2 then
PowerCount = PowerCount + 1
end
end
end
end
return PowerCount
end
return nil
end
local function getNumCOs()
local COAddr2 = 0x2189370
local COID2 = memory.readbyte(COAddr2)
if COID2 ~= 0 then
return 2
else
return 1
end
end
-- Coordinates and position related stuff
mapCoords = {0,0}
function readMapCoords()
local x = memory.readdword(0x27C3AE0) - 19
local y = memory.readdword(0x27C3AE4) - 14
if x >= 0 and x < 60 and y >= 0 and y < 60 then
if x ~= mapCoords[1] or y ~= mapCoords[2] then
mapCoords = {x,y}
end
end
end
function getMapCoords()
return mapCoords
end
-- Get it in screen space
local function getCursorPos()
local mapX = memory.readbyte(0x2183B30)
local mapY = memory.readbyte(0x2183B32)
local mapCoords = getMapCoords()
local screenX = mapX - mapCoords[1]
local screenY = mapY - mapCoords[1]
return {screenX, screenY}
end
local function mapToScreenPos(mapPos)
local mapCoords = getMapCoords()
local screenX = mapPos[1] - mapCoords[1]
local screenY = mapPos[2] - mapCoords[2]
return {screenX, screenY}
end
local function isPos(Pos1, Pos2)
return (Pos1[1] == Pos2[1]) and (Pos1[2] == Pos2[2])
end
local function isAdjPos(Pos1, Pos2)
return math.abs(Pos1[1] - Pos2[1]) <= 1 and math.abs(Pos1[2] - Pos2[2]) <= 1
end
local function addPos(Pos1, Pos2)
return {Pos1[1] + Pos2[1],Pos1[2] + Pos2[2]}
end
local function subPos(Pos1, Pos2)
return {Pos1[1] - Pos2[1],Pos1[2] - Pos2[2]}
end
-- Screen to pixel space
local function screenToPixelX(x, y)
-- on y = 0 width ~= 13.6
-- on y = 11 width ~= 15.8
local squareWidth = 13.6 + 0.2 * y
return 127 + squareWidth * (x - 7.5)
end
local function screenToPixelY(y)
local Y = {21, 33, 46, 59, 73, 87, 101, 115, 130, 146, 162, 179}
return Y[(y + 1)]
end
local function screenPosToPixelPos(screenPos)
local x = screenToPixelX(screenPos[1], screenPos[2])
local y = screenToPixelY(screenPos[2])
return {x,y}
end
-- Helper functions to create input
function inputBeginMap(Time)
local time1 = Time .. '-15'
local time2 = Time + 3
Input[time1] = { ['buttons'] = { 'start'}}
Input[time2] = { ['stylus'] = {0,0}}
return 9
end
function inputBeginDay(Time, PerfectTouch)
Input[Time] = { ['stylus'] = {0,0}}
if PerfectTouch then
return 33
else
return 34
end
end
function inputSupply(Time, SupplyTime)
return SupplyTime
end
function inputScroll(Time, ScrollPos)
local time1 = Time
local time2 = (time1 + 1) .. '-14'
local time3 = (time1 + 1) .. '-20'
Input[time1] = { ['buttons'] = {'start'}}
Input[time2] = { ['stylus'] = ScrollPos}
Input[time3] = { ['buttons'] = {'start'}}
return 2
end
function inputBuild(Time, BasePos, Unit)
BasePos = mapToScreenPos(BasePos)
local UnitPos
if Unit == 'Infantry' then UnitPos = {64,64}
elseif Unit == 'Mech' then UnitPos = {64,80}
elseif Unit == 'Recon' then UnitPos = {64,96}
elseif Unit == 'Tank' then UnitPos = {64,112}
elseif Unit == 'Md Tank' then UnitPos = {64,128}
elseif Unit == 'Neotank' then UnitPos = {64,144}
elseif Unit == 'Megatank' then UnitPos = {64,160}
elseif Unit == 'APC' then UnitPos = {192,64}
elseif Unit == 'Artillery' then UnitPos = {192,80}
elseif Unit == 'Rockets' then UnitPos = {192,96}
elseif Unit == 'Anti-Air' then UnitPos = {192,112}
elseif Unit == 'Missiles' then UnitPos = {192,128}
elseif Unit == 'Piperunner' then UnitPos = {192,144}
end
local time1 = Time
local time2 = time1 + 1
local time3 = time2 + 1
Input[time1] = { ['cursor'] = BasePos, ['buttons'] = {'A'}}
Input[time2] = { ['stylus'] = UnitPos}
Input[time3] = { ['buttons'] = {'A'}}
return 5
end
function inputMov(Time, UnitPos, Movement, Options)
UnitPos = mapToScreenPos(UnitPos)
local MovPos = addPos(UnitPos, Movement)
local numSquares
if Options and Options['squares'] then
numSquares = Options['squares']
else
numSquares = math.abs(Movement[1]) + math.abs(Movement[2])
end
local time1
-- If the cursor is adjacent we need tap away, 1 frame lost
if Options and Options['cursorAdj'] then
local CursorPos = getCursorPos()
local AwayPos
if UnitPos[1] >= 8 and UnitPos[2] >= 6 then
AwayPos = {2,2}
elseif UnitPos[1] <= 7 and UnitPos[2] >= 6 then
AwayPos = {13,2}
elseif UnitPos[1] >= 8 and UnitPos[2] <= 5 then
AwayPos = {2,9}
else--if UnitPos[1] <= 7 and UnitPos[2] <= 5 then
AwayPos = {13,9}
end
local timeA = Time
Input[timeA] = { ['stylus'] = AwayPos}
time1 = timeA + 1
else
time1 = Time
end
-- Select with removing lag
if Options and Options['removeLag'] then
TempPos = mapToScreenPos(Options['removeLag'])
local timeA = Time
local timeB = timeA + 1
time1 = timeB + 1
Input[timeA] = { ['cursor'] = TempPos}
Input[timeB] = { ['cursor'] = UnitPos}
Input[time1] = { ['buttons'] = {'A'}}
-- Select with Tap+A
elseif (Options and (Options['RNGPath'] or Options['RNGPaths'])) or (Options and Options['cursorAdj']) or isAdjPos(UnitPos, MovPos) then
Input[time1] = { ['cursor'] = UnitPos, ['buttons'] = {'A'}}
-- Select with just Tap
else
Input[time1] = { ['cursor'] = UnitPos}
end
-- Draw a path to advance the RNG if specified
if Options and Options['RNGPath'] then
PathPos = addPos(UnitPos, Options['RNGPath'])
local time1A = time1 + 1
Input[time1A] = { ['cursor'] = PathPos}
elseif Options and Options['RNGPaths'] then
local time1X = time1 + 1
for i, Path in pairs(Options['RNGPaths']) do
PathPos = addPos(UnitPos, Path)
Input[time1X] = { ['cursor'] = PathPos}
time1X = time1X + 1
end
Options['RNGPathDelay'] = table.getn(Options['RNGPaths']) - 1
time1 = time1 + Options['RNGPathDelay']
-- If the cursor was adjacent before or we make an adjacent movement then we need to move the cursor away
elseif (Options and Options['cursorAdj']) or isAdjPos(UnitPos, MovPos) then
local time1A = time1 + 1
-- Loading needs the d-pad
if Options and Options['load'] then
local dirButtons
if isPos(Movement, {0,-1}) then
dirButtons = {'down'}
elseif isPos(Movement, {1,-1}) then
dirButtons = {'left','down'}
elseif isPos(Movement, {1,0}) then
dirButtons = {'left'}
elseif isPos(Movement, {1,1}) then
dirButtons = {'left','up'}
elseif isPos(Movement, {0,1}) then
dirButtons = {'up'}
elseif isPos(Movement, {-1,1}) then
dirButtons = {'right', 'up'}
elseif isPos(Movement, {-1,0}) then
dirButtons = {'right'}
elseif isPos(Movement, {-1,-1}) then
dirButtons = {'right','down'}
else
dirButtons = {'b'}
end
Input[time1A] = { ['buttons'] = dirButtons}
-- Otherwise just tap away
else
local AwayPos
if UnitPos[1] >= 8 and UnitPos[2] >= 6 then
AwayPos = {2,2}
elseif UnitPos[1] <= 7 and UnitPos[2] >= 6 then
AwayPos = {13,2}
elseif UnitPos[1] >= 8 and UnitPos[2] <= 5 then
AwayPos = {2,9}
else--if UnitPos[1] <= 7 and UnitPos[2] <= 5 then
AwayPos = {13,9}
end
Input[time1A] = { ['stylus'] = AwayPos}
end
end
-- Choose the unit menu option, most of the time we just go by default
local MenuPos
if Options and Options['menu'] then
MenuPos = { MovPos[1], MovPos[2] + Options['menu'] - 1}
else
MenuPos = MovPos
end
local time2 = time1 + 2
local time3 = time2 + 3 + 4 * numSquares
Input[time2] = { ['cursor'] = MovPos, ['buttons'] = {'A'}}
Input[time3] = { ['cursor'] = MenuPos}
-- Drop an Inf or Mech
if Options and Options['drop'] then
local DropPos = { MovPos[1] + Options['drop'][1], MovPos[2] + Options['drop'][2]}
local time4 = time3 + 2
Input[time4] = { ['cursor'] = DropPos, ['buttons'] = {'A'}}
end
-- Attack a unit
if Options and Options['attack'] then
local time4 = time3 + 12
if Options and Options['RNGWait'] then
time4 = time4 + Options['RNGWait']
end
-- We might need to select the unit if autotarget doesn't work, 1 frame lost
if Options and Options['targetPos'] then
local TargetPos = mapToScreenPos(Options['targetPos'])
Input[time4] = { ['cursor'] = TargetPos}
else
Input[time4] = { ['buttons'] = {'A'}}
end
end
local ActionLength = 8 + 4 * numSquares
if Options and Options['removeLag'] then
ActionLength = ActionLength + 2
end
if Options and Options['cursorAdj'] then
ActionLength = ActionLength + 1
end
if Options and Options['RNGPathDelay'] then
ActionLength = ActionLength + Options['RNGPathDelay']
end
if Options and Options['load'] then
ActionLength = ActionLength - 1
end
if Options and Options['drop'] then
ActionLength = ActionLength + 6
end
if Options and Options['cap'] then
ActionLength = ActionLength + 112 + Options['cap']
end
if Options and Options['finish'] then
ActionLength = ActionLength + 20
end
if Options and Options['attack'] then
ActionLength = ActionLength + 11
if Options and Options['RNGWait'] then
ActionLength = ActionLength + Options['RNGWait']
end
if Options and Options['targetPos'] then
ActionLength = ActionLength + 1
end
if Options and Options['attDelay'] then
ActionLength = ActionLength + Options['attDelay']
else
ActionLength = ActionLength + 3
end
end
return ActionLength
end
function inputCap(Time, UnitPos, Cap, Options)
UnitPos = mapToScreenPos(UnitPos)
-- Choose the menu option, most of the time we just go by default
local MenuPos
if Options and Options['menu'] then
MenuPos = { UnitPos[1], UnitPos[2] + Options['menu'] - 1}
else
MenuPos = UnitPos
end
local time1 = Time
local time2 = time1 + 3
Input[time1] = { ['cursor'] = UnitPos, ['buttons'] = {'A'}}
Input[time2] = { ['cursor'] = MenuPos}
local ActionLength = 6 + 112 + Cap
if Options and Options['finish'] then
ActionLength = ActionLength + 20
end
return ActionLength
end
function inputAtt(Time, UnitPos, Options)
UnitPos = mapToScreenPos(UnitPos)
local time1
-- If the cursor is adjacent we need to use the d-pad, 1 frame lost
if Options and Options['cursorAdj'] then
local CursorPos = getCursorPos()
local CursorDist = subPos(UnitPos, CursorPos)
local dirButtons
if isPos(CursorDist, {0,-1}) then
dirButtons = {'down'}
elseif isPos(CursorDist, {1,-1}) then
dirButtons = {'left','down'}
elseif isPos(CursorDist, {1,0}) then
dirButtons = {'left'}
elseif isPos(CursorDist, {1,1}) then
dirButtons = {'left','up'}
elseif isPos(CursorDist, {0,1}) then
dirButtons = {'up'}
elseif isPos(CursorDist, {-1,1}) then
dirButtons = {'right', 'up'}
elseif isPos(CursorDist, {-1,0}) then
dirButtons = {'right'}
elseif isPos(CursorDist, {-1,-1}) then
dirButtons = {'right','down'}
else
dirButtons = {'b'}
end
local timeA = Time
Input[timeA] = { ['buttons'] = dirButtons}
time1 = timeA + 1
else
time1 = Time
end
local time2
-- Select with removing lag
if Options and Options['removeLag'] then
local time1A = time1 + 2
Input[time1] = { ['cursor'] = UnitPos}
Input[time1A] = { ['buttons'] = {'A'}}
time2 = time1A + 2
-- Select with Tap+A
else
Input[time1] = { ['cursor'] = UnitPos, ['buttons'] = {'A'}}
time2 = time1 + 3
end
Input[time2] = { ['cursor'] = UnitPos}
local time3 = time2 + 12
if Options and Options['RNGWait'] then
time3 = time3 + Options['RNGWait']
end
-- We might need to select the unit if autotarget doesn't work, 1 frame lost
if Options and Options['targetPos'] then
local TargetPos = mapToScreenPos(Options['targetPos'])
Input[time3] = { ['cursor'] = TargetPos}
else
Input[time3] = { ['buttons'] = {'A'}}
end
local ActionLength = 17
if Options and Options['removeLag'] then
ActionLength = ActionLength + 1
end
if Options and Options['cursorAdj'] then
ActionLength = ActionLength + 1
end
if Options and Options['adj'] then
ActionLength = ActionLength + Options['adj']
end
if Options and Options['RNGWait'] then
ActionLength = ActionLength + Options['RNGWait']
end
if Options and Options['targetPos'] then
ActionLength = ActionLength + 1
end
if Options and Options['attDelay'] then
ActionLength = ActionLength + Options['attDelay']
else
ActionLength = ActionLength + 3
end
return ActionLength
end
function inputExpBB(Time, UnitPos)
UnitPos = mapToScreenPos(UnitPos)
local time1 = (Time + 2) .. '-14'
local time2 = (Time + 2) .. '-29'
Input[time1] = { ['buttons'] = {'start'}}
Input[time2] = { ['buttons'] = {'A'}}
return 108
end
local function inputMenu(Time, MenuItem, Options)
local MenuPos = {128,(MenuItem + 1) * 16}
-- Move the cursor while opening the menu
if Options and Options['cursor'] then
local NewCursorPos = mapToScreenPos(Options['cursor'])
local time1 = Time
local time2 = time1 + 1
local time3 = time2 + 1
Input[time1] = { ['cursor'] = NewCursorPos, ['buttons'] = {'select'}}
Input[time2] = { ['stylus'] = MenuPos}
Input[time3] = { ['buttons'] = {'A'}}
else
local time1 = Time
local time2 = time1 + 1
Input[time1] = { ['buttons'] = {'select'}}
Input[time2] = { ['stylus'] = MenuPos}
end
end
function inputUseCOP(Time, Units, PerfectTouch, Options)
inputMenu(Time, 3, Options)
local time1 = (Time + 6) .. '-14'
Input[time1] = { ['buttons'] = {'start'}}
local ActionLength = 53
if Units > 0 then
ActionLength = ActionLength + 20 + 5 * Units
end
if PerfectTouch and PerfectTouch == true then
ActionLength = ActionLength - 1
end
return ActionLength
end
function inputUseSCOP(Time, Units, PerfectTouch, Options)
inputMenu(Time, 4, Options)
local time1 = (Time + 6) .. '-14'
Input[time1] = { ['buttons'] = {'start'}}
local ActionLength = 132
if Units > 0 then
ActionLength = ActionLength + 26 + 5 * Units
end
if PerfectTouch and PerfectTouch == true then
ActionLength = ActionLength - 1
end
return ActionLength
end
function inputUseTAG(Time, Units, PerfectTouch, Options)
inputMenu(Time, 5, Options)
local time1 = (Time + 6) .. '-14'
Input[time1] = { ['buttons'] = {'start'}}
local ActionLength = 190
if Units > 0 then
ActionLength = ActionLength + 26 + 5 * Units
end
if PerfectTouch and PerfectTouch == true then
ActionLength = ActionLength - 1
end
return ActionLength
end
function inputTAGSwap(Time, Units, PerfectTouch, Options)
inputMenu(Time, 5, Options)
local time1 = (Time + 6) .. '-14'
Input[time1] = { ['buttons'] = {'start'}}
local ActionLength = 84
if Units > 0 then
ActionLength = ActionLength + 26 + 5 * Units
end
if PerfectTouch and PerfectTouch == true then
ActionLength = ActionLength - 1
end
return ActionLength
end
function inputEndDay(Time, Options)
local PowerCount = getNumUseablePowers()
local NumCOs = getNumCOs()
if NumCOs == 1 or (Options and (Options['swap'] or Options['tag'])) then
inputMenu(Time, 5 + PowerCount, Options)
else
inputMenu(Time, 6 + PowerCount, Options)
end
if Options and Options['swap'] then
local time1 = (Time + 6) .. '-14'
Input[time1] = { ['buttons'] = {'start'}}
end
local ActionLength = 13
if Options and Options['swap'] then
ActionLength = ActionLength + 40
end
return ActionLength
end
function inputAIBeginDay(AITime, Options)
if Options and Options['RNGWait'] then
AITime = AITime + Options['RNGWait']
end
AIInput[AITime] = true
end
-- Helper functions
-- RNG
local function Multiply(int1, int2)
local High1 = math.floor(int1 / 32768)
local Low1 = math.floor(int1 % 32768)
local High2 = math.floor(int2 / 32768)
local Low2 = math.floor(int2 % 32768)
local NewHigh = (High1 * Low2 + High2 * Low1) % 32768;
local NewLow = Low1 * Low2
return (NewHigh * 32768 + NewLow) % 1073741824;
end
function RNGStep(i)
local i4 = (i * 4 + 1) % 1073741824
return Multiply(i4, i + 1)
end
local function RNGSteps(iRNG, iTimes)
while iTimes > 0 do
iRNG = RNGStep(iRNG)
iTimes = iTimes - 1
end
return iRNG
end
local function getNumSteps(oldRNG, newRNG)
if oldRNG == newRNG then
return 0
end
for i = 1, 200 do
oldRNG = RNGStep(oldRNG)
if oldRNG == newRNG then
return i
end
end
return -1;
end
local function RNGFrameAdv(iRNG, GameTime)
local x = GameTime + RNGStep(iRNG)
local newRNG = RNGStep(x)
newRNG = newRNG + (math.floor(newRNG / 2) % 2)
return newRNG
end
local function RNGMenuAdv(iRNG)
for i = 1, 80 do
iRNG = RNGStep(iRNG)
iRNG = iRNG + (math.floor(iRNG / 2) % 2)
end
return iRNG
end
-- The core functions of the TASBot
Strategy = {}
nextAction = -1
function resetStrategy()
Input = {}
Strategy = {}
if SurvivalMapCounter == 0 then nextAction = 35
else nextAction = 16
end
end
function addInput(Name, Param1, Param2, Param3, Param4)
table.insert(Strategy, { Name, Param1, Param2, Param3, Param4})
end
function loadStrategyInput()
while next(Strategy) ~= nil and MapTimer >= nextAction do
local Action = Strategy[1]
table.remove(Strategy, 1)
local ActionLength
if Action[1] == 'BeginMap' then
ActionLength = inputBeginMap(nextAction)
elseif Action[1] == 'BeginDay' then
ActionLength = inputBeginDay(nextAction, Action[2])
elseif Action[1] == 'Supply' then
ActionLength = inputSupply(nextAction, Action[2])
elseif Action[1] == 'Scroll' then
ActionLength = inputScroll(nextAction, Action[2])
elseif Action[1] == 'Build' then
ActionLength = inputBuild(nextAction, Action[2], Action[3])
elseif Action[1] == 'Mov' then
ActionLength = inputMov(nextAction, Action[2], Action[3], Action[4])
elseif Action[1] == 'MovLoad' then
local Options = {}
if Action[4] then Options = Action[4] end
Options['load'] = true
ActionLength = inputMov(nextAction, Action[2], Action[3], Options)
elseif Action[1] == 'Cap' then
ActionLength = inputCap(nextAction, Action[2], Action[3], Action[4])
elseif Action[1] == 'MovCap' then
local Options = {}
if Action[5] then Options = Action[5] end
Options['cap'] = Action[4]
ActionLength = inputMov(nextAction, Action[2], Action[3], Options)
elseif Action[1] == 'Att' then
ActionLength = inputAtt(nextAction, Action[2], Action[3])
elseif Action[1] == 'MovAtt' then
local Options = {}
if Action[4] then Options = Action[4] end
Options['attack'] = true
ActionLength = inputMov(nextAction, Action[2], Action[3], Options)
elseif Action[1] == 'MovExpBB' then
ActionLength = inputMov(nextAction, Action[2], Action[3], Action[4])
nextAction = nextAction + ActionLength
ActionLength = inputExpBB(nextAction, addPos(Action[2], Action[3]))
elseif Action[1] == 'UseCOP' then
ActionLength = inputUseCOP(nextAction, Action[2], Action[3], Action[4])
elseif Action[1] == 'UseSCOP' then
ActionLength = inputUseSCOP(nextAction, Action[2], Action[3], Action[4])
elseif Action[1] == 'UseTAG' then
ActionLength = inputUseTAG(nextAction, Action[2], Action[3], Action[4])
elseif Action[1] == 'TAGSwap' then
ActionLength = inputTAGSwap(nextAction, Action[2], Action[3], Action[4])
elseif Action[1] == 'EndDay' then
ActionLength = inputEndDay(nextAction, Action[2])
inputAIBeginDay(AIMapTimer + 6, Action[2])
elseif Action[1] == 'Swap' then
local Options = {}
if Action[2] then Options = Action[2] end
Options['swap'] = true
ActionLength = inputEndDay(nextAction, Options)
inputAIBeginDay(AIMapTimer + 6, Options)
end
nextAction = nextAction + ActionLength
end
end
local lastMap = -1
local lastMapTimer = -1
function loadPlayerInput()
local Map = (SurvivalMapCounter % 11) + 1
-- Reload the strategy if we aren't on the same map with the same or +1 timer or just finished the map and haven't started the next yet
if not ((Map == lastMap or Map == lastMap + 1) and (MapTimer == lastMapTimer or MapTimer == lastMapTimer + 1)) then
resetStrategy()
loadStrategy(Map)
emu.message('Strategy for Map ' .. Map .. ' loaded')
end
lastMap = Map
lastMapTimer = MapTimer
-- If the Map timer frame is not 1 then we already loaded the input
if MapTimerFrame ~= 1 then
return
end
loadStrategyInput()
end
-- Set input that will be executed in the current frame
function setInput(input)
if input['buttons'] then
for k, button in pairs(input['buttons']) do
joypad.set(1, { [button] = 1})
end
end
if input['stylus'] then
local tp = { ['x'] = input['stylus'][1], ['y'] = input['stylus'][2], ['touch'] = 1}
stylus.set(tp)
end
if input['cursor'] then
local scrPos = screenPosToPixelPos(input['cursor'])
local tp = { ['x'] = scrPos[1], ['y'] = scrPos[2], ['touch'] = 1}
stylus.set(tp)
end
end
Input = {}
local function getPlayerInput(Time, TimeFrame)
if Input[Time .. '-' .. TimeFrame] then
return Input[Time .. '-' .. TimeFrame]
elseif Input[Time] then
return Input[Time]
else
return nil
end
end
function executePlayerInput()
local input = getPlayerInput(MapTimer, MapTimerFrame)
if input then
setInput(input)
end
end
AIDayActive = false
function executeAIInput()
if AIDayActive then
setInput({ ['buttons'] = {'A'}})
end
end
AIInput = {}
function executeAIBeginDay()
-- Begin AI day ASAP
if AIInput[AIMapTimer] then
setInput({ ['stylus'] = {0,0}})
end
end
MenuInput = {}
function addMenuInput(GameTime, GameTimeFrame, Input)
MenuInput[GameTime .. '-' .. GameTimeFrame] = Input
end
local function getMenuInput(GameTime, GameTimeFrame)
if MenuInput[GameTime .. '-' .. GameTimeFrame] then
return MenuInput[GameTime .. '-' .. GameTimeFrame]
else
return nil
end
end
function executeMenuInput()
local input = getMenuInput(GameTimer, GameTimerFrame)
if input then
setInput(input)
end
end
local MapTimerAddr = 0x2189394
MapTimer = -1
MapTimerFrame = -1
function readMapTimer()
local newMapTime = memory.readdword(MapTimerAddr)
if MapTimer == newMapTime then
MapTimerFrame = MapTimerFrame + 1
else
MapTimer = newMapTime
MapTimerFrame = 1
-- Player map timer increased? Then AI Day is certainly over
AIDayActive = false
end
end
local AIMapTimerAddr = 0x218942C
AIMapTimer = -1
function readAIMapTimer()
AIMapTimer = memory.readdword(AIMapTimerAddr)
end
local GameTimerAddr = 0x27C0738
GameTimer = -1
GameTimerFrame = -1
function readGameTimer()
local newGameTime = memory.readdword(GameTimerAddr)
if GameTimer == newGameTime then
GameTimerFrame = GameTimerFrame + 1
else
GameTimer = newGameTime
GameTimerFrame = 1
end
end
local RNGAddr = 0x216E2B4
RNG = -1
TotalNumSteps = 0
function readRNG(printChanges)
newRNG = memory.readdword(RNGAddr)
if RNG ~= newRNG then
local printText = ''
if RNG ~= -1 then
local numSteps = getNumSteps(RNG, newRNG)
if numSteps ~= -1 then
TotalNumSteps = TotalNumSteps + numSteps
printText = newRNG .. ' (' .. numSteps .. ')' .. ' Total: ' .. TotalNumSteps .. ' at ' .. GameTimer
else
TotalNumSteps = 0
-- FrameBasedAdvance! AI Day started
if newRNG == RNGFrameAdv(RNG, GameTimer) then
printText = newRNG .. ' (Frame ' .. GameTimer .. ')'
AIDayActive = true
else
local menuRNG = RNG
for i = 1, 10 do
menuRNG = RNGMenuAdv(menuRNG)
if newRNG == menuRNG then
printText = newRNG .. ' (Menu * ' .. i .. ' at ' .. GameTimer .. ')'
AIDayActive = false
end
end
end
end
end
if printChanges then
if printText ~= '' then
print(printText)
else
print(newRNG)
end
end
RNG = newRNG
end
end
function cheatRNG(Value)
memory.writedword(RNGAddr, Value)
end
local SurvivalMapCounterAddr = 0x22A7B86
SurvivalMapCounter = -1
function readSurvivalMapCounter()
SurvivalMapCounter = memory.readbyte(SurvivalMapCounterAddr)
end
function cheatSurvivalMapCounter(Value)
memory.writebyte(SurvivalMapCounterAddr, Value)
end