Pass sprites around

This commit is contained in:
Empathic Qubit 2021-05-08 23:44:18 -04:00
parent 22b41082a7
commit 8233847f46
4 changed files with 119 additions and 53 deletions

View file

@ -25,9 +25,10 @@ _M.State = {
-- W1.2 Mainbrace Mayhem -- W1.2 Mainbrace Mayhem
"MainbraceMayhem.lsmv", -- [4] "MainbraceMayhem.lsmv", -- [4]
"MainbraceMayhemBonus.lsmv", -- [5] "MainbraceMayhemBonus.lsmv", -- [5]
"MainbraceMayhemTopOfRope.lsmv", -- [6]
} }
_M.Filename = _M.PoolDir .. _M.State[4] _M.Filename = _M.PoolDir .. _M.State[1]
--[[ --[[
Start game with specific powerup. Start game with specific powerup.
@ -61,7 +62,7 @@ BiasMutationChance = 0.40,
StepSize = 0.1, StepSize = 0.1,
DisableMutationChance = 0.4, DisableMutationChance = 0.4,
EnableMutationChance = 0.2, EnableMutationChance = 0.2,
TimeoutConstant = 20, TimeoutConstant = 30,
MaxNodes = 1000000, MaxNodes = 1000000,
} }

View file

@ -1,5 +1,5 @@
--Notes here --Notes here
local memory, bit, memory2, input, callback, movie = memory, bit, memory2, input, callback, movie local memory, bit, memory2, input, callback, movie, utime = memory, bit, memory2, input, callback, movie, utime
local base = string.gsub(@@LUA_SCRIPT_FILENAME@@, "(.*[/\\])(.*)", "%1") local base = string.gsub(@@LUA_SCRIPT_FILENAME@@, "(.*[/\\])(.*)", "%1")
@ -265,11 +265,10 @@ function _M.getWaypoints(startX, startY)
return collisions return collisions
end end
function _M.getGoalHit() function _M.getGoalHit(sprites)
local sprites = _M.getSprites()
for i=1,#sprites,1 do for i=1,#sprites,1 do
local sprite = sprites[i] local sprite = sprites[i]
if sprite.control ~= 0x0164 then if sprite.control ~= spritelist.GoodSprites.goalBarrel then
goto continue goto continue
end end
-- Check if the goal barrel is moving up -- Check if the goal barrel is moving up
@ -517,9 +516,8 @@ end
-- Currently only for single bananas since they don't -- Currently only for single bananas since they don't
-- count as regular computed sprites -- count as regular computed sprites
function _M.getExtendedSprites() function _M.getExtendedSprites(sprites)
local oam = memory2.OAM:readregion(0x00, 0x220) local oam = memory2.OAM:readregion(0x00, 0x220)
local sprites = _M.getSprites()
local extended = {} local extended = {}
for idx=0,0x200/4-1,1 do for idx=0,0x200/4-1,1 do
@ -562,21 +560,21 @@ function _M.getExtendedSprites()
end end
function _M.getInputs() function _M.getInputs()
_M.getPositions() _M.getPositions()
local sprites = _M.getSprites() local sprites = _M.getSprites()
local extended = _M.getExtendedSprites() local extended = _M.getExtendedSprites(sprites)
local inputs = {} local inputs = {}
local inputDeltaDistance = {} local inputDeltaDistance = {}
for dy = -config.BoxRadius, config.BoxRadius, 1 do for dy = -config.BoxRadius, config.BoxRadius, 1 do
for dx = -config.BoxRadius, config.BoxRadius, 1 do for dx = -config.BoxRadius, config.BoxRadius, 1 do
inputs[#inputs+1] = 0 inputs[#inputs+1] = 0
inputDeltaDistance[#inputDeltaDistance+1] = 1 inputDeltaDistance[#inputDeltaDistance+1] = 1
local tile = _M.getTile(dx, dy) local tile = _M.getTile(dx, dy)
if tile == 1 then if tile == 1 then
if inputs[#inputs-config.BoxRadius*2-1] == -1 then if inputs[#inputs-config.BoxRadius*2-1] == -1 then
inputs[#inputs] = -1 inputs[#inputs] = -1
else else
@ -601,42 +599,43 @@ function _M.getInputs()
inputs[#inputs] = -1 inputs[#inputs] = -1
end end
end end
end end
for i = 1,#sprites do for i = 1,#sprites do
local sprite = sprites[i] local sprite = sprites[i]
local distx = math.abs(sprite.x - (_M.partyX+dx*mem.size.tile)) if sprite.good == 0 then
local disty = math.abs(sprite.y - (_M.partyY+dy*mem.size.tile)) goto continue
end
local distx = math.abs(sprite.x - (_M.partyX+dx*mem.size.tile))
local disty = math.abs(sprite.y - (_M.partyY+dy*mem.size.tile))
local dist = math.sqrt((distx * distx) + (disty * disty)) local dist = math.sqrt((distx * distx) + (disty * disty))
if dist <= mem.size.tile * 1.25 then if dist <= mem.size.tile * 1.25 then
if sprite.good == 0 then inputs[#inputs] = sprite.good
goto continue
if dist > mem.size.tile then
inputDeltaDistance[#inputDeltaDistance] = mathFunctions.squashDistance(dist)
end end
inputs[#inputs] = sprite.good end
if dist > mem.size.tile then
inputDeltaDistance[#inputDeltaDistance] = mathFunctions.squashDistance(dist)
end
end
::continue:: ::continue::
end end
for i = 1,#extended do for i = 1,#extended do
local distx = math.abs(extended[i]["x"]+_M.cameraX - (_M.partyX+dx*mem.size.tile)) local distx = math.abs(extended[i]["x"]+_M.cameraX - (_M.partyX+dx*mem.size.tile))
local disty = math.abs(extended[i]["y"]+_M.cameraY - (_M.partyY+dy*mem.size.tile)) local disty = math.abs(extended[i]["y"]+_M.cameraY - (_M.partyY+dy*mem.size.tile))
if distx < mem.size.tile / 2 and disty < mem.size.tile / 2 then if distx < mem.size.tile / 2 and disty < mem.size.tile / 2 then
inputs[#inputs] = extended[i]["good"] inputs[#inputs] = extended[i]["good"]
local dist = math.sqrt((distx * distx) + (disty * disty)) local dist = math.sqrt((distx * distx) + (disty * disty))
if dist > mem.size.tile / 2 then if dist > mem.size.tile / 2 then
inputDeltaDistance[#inputDeltaDistance] = mathFunctions.squashDistance(dist) inputDeltaDistance[#inputDeltaDistance] = mathFunctions.squashDistance(dist)
end end
end end
end end
end end
end end
return inputs, inputDeltaDistance return inputs, inputDeltaDistance
end end
function _M.getClimbing() function _M.getClimbing()

View file

@ -579,7 +579,8 @@ local function mainLoop(_M, genome)
end end
if _M.currentFrame % 5 == 0 then if _M.currentFrame % 5 == 0 then
local inputs, inputDeltas = game.getInputs() local sprites = game.getSprites()
local inputs, inputDeltas = game.getInputs(sprites)
if game.bonusScreenDisplayed(inputs) and _M.timeout > -1000 and _M.timeout < timeoutConst then if game.bonusScreenDisplayed(inputs) and _M.timeout > -1000 and _M.timeout < timeoutConst then
_M.timeout = timeoutConst _M.timeout = timeoutConst
end end
@ -677,10 +678,13 @@ local function mainLoop(_M, genome)
message(_M, "Extra live bonus added " .. extraLiveBonus) message(_M, "Extra live bonus added " .. extraLiveBonus)
end end
if game.getGoalHit() then local sprites = game.getSprites()
-- FIXME We should test this before we time out
if game.getGoalHit(sprites) then
fitness = fitness + 1000 fitness = fitness + 1000
message(_M, string.format("LEVEL WON! Fitness: %d", fitness), 0x0000ff00) message(_M, string.format("LEVEL WON! Fitness: %d", fitness), 0x0000ff00)
end end
if fitness == 0 then if fitness == 0 then
fitness = -1 fitness = -1
end end

View file

@ -18,6 +18,44 @@ function _M.promiseWrap(next, value)
return promise:next(next) return promise:next(next)
end end
local times = {}
--- Track how long a function takes
---@param toCall function Function that executes synchronously
---@param name string What to print in the finish text
---@return any any The original value
function _M.time(toCall, name)
if name == nil then
name = 'function'
end
local sec, usec = utime()
local startTime = sec * 1000000 + usec
local finishTime = 0
local ret = toCall()
sec, usec = utime()
finishTime = sec * 1000000 + usec
local t = times[name]
if t == nil then
t = {}
times[name] = t
end
if #t > 50 then
table.remove(t, 1)
end
t[#t+1] = finishTime - startTime
local sum = 0
for i=1,#t,1 do
sum = sum + t[i]
end
print(name..' is averaging '..math.floor(sum / #t))
return ret
end
--- Wait for a specified amount of time. Note that this is dependent on the --- Wait for a specified amount of time. Note that this is dependent on the
--- timer timeout getting set elsewhere in the code, probably in the Promise --- timer timeout getting set elsewhere in the code, probably in the Promise
--- handler setup --- handler setup
@ -41,6 +79,30 @@ function _M.delay(delayUsec)
end) end)
end end
function _M.saveState(filename)
return Promise.new(function(res, rej)
local unSave = nil
local unErrSave = nil
local function errSave(f)
if f == filename then
callback.unregister('post_save', unSave)
callback.unregister('err_save', unErrSave)
rej()
end
end
local function postSave(f)
if f == filename then
callback.unregister('post_save', unSave)
callback.unregister('err_save', unErrSave)
res()
end
end
unSave = callback.register('post_save', postSave)
unErrSave = callback.register('err_save', errSave)
exec('save-state '..filename)
end)
end
function _M.loadAndStart(romFile) function _M.loadAndStart(romFile)
return Promise.new(function(res, rej) return Promise.new(function(res, rej)
local unPaint = nil local unPaint = nil