diff --git a/config.lua b/config.lua index a41f3bf..a115928 100644 --- a/config.lua +++ b/config.lua @@ -41,7 +41,7 @@ _M.StartPowerup = 0 _M.NeatConfig = { DisableSound = true, -Threads = 7, +Threads = 1, --Filename = "DP1.state", SaveFile = _M.Filename .. ".pool", diff --git a/pool.lua b/pool.lua index 8a34e43..fb4ae75 100644 --- a/pool.lua +++ b/pool.lua @@ -9,9 +9,7 @@ local util = dofile(base.."/util.lua")(Promise) local serpent = dofile(base.."/serpent.lua") local libDeflate = dofile(base.."/LibDeflate.lua") -local hasThreads = - --not util.isWin and - config.NeatConfig.Threads > 1 +local hasThreads = config.NeatConfig.Threads > 1 -- Only the parent should manage ticks! callback.register('timer', function() @@ -20,18 +18,14 @@ callback.register('timer', function() end) set_timer_timeout(1) +local warn = '========== The ROM file to use comes from config.lua.' +io.stderr:write(warn) +print(warn) + local Runner = nil if hasThreads then - local warn = '========== When using threads, the ROM file to use comes from config.lua. Also, you do not need to start any ROM in the parent process.' - io.stderr:write(warn) - print(warn) - Runner = dofile(base.."/runner-wrapper.lua") else - local warn = '========== The ROM must already be running when you only have one thread.' - io.stderr:write(warn) - print(warn) - Runner = dofile(base.."/runner.lua") end @@ -821,8 +815,12 @@ function _M.run(reset) return promise:next(function() return writeFile(config.PoolDir.."temp.pool") end):next(function () + if not hasThreads then + return util.loadAndStart(config.ROM) + end + end):next(function() return mainLoop() end) end -return _M +return _M \ No newline at end of file diff --git a/runner.lua b/runner.lua index 1027c1b..6387ade 100644 --- a/runner.lua +++ b/runner.lua @@ -1,7 +1,6 @@ local gui, input, movie, settings, exec, callback, set_timer_timeout = gui, input, movie, settings, exec, callback, set_timer_timeout local base = string.gsub(@@LUA_SCRIPT_FILENAME@@, "(.*[/\\])(.*)", "%1") - local Promise = nil local config = dofile(base.."/config.lua") @@ -451,9 +450,9 @@ local function generateNetwork(genome) genome.network = network end -local rew = movie.to_rewind(config.NeatConfig.Filename) +local beginRewindState = nil local function rewind() - return game.rewind(rew):next(function() + return game.rewind(beginRewindState):next(function() frame = 0 lastFrame = 0 end) @@ -846,6 +845,9 @@ local function saveLoadInput(_M) end local function run(_M, species, generationIdx, genomeCallback) + if beginRewindState == nil then + beginRewindState = movie.to_rewind(config.NeatConfig.Filename) + end game.registerHandlers() _M.currentGenerationIndex = generationIdx @@ -952,4 +954,4 @@ return function(promise) end return _M -end +end \ No newline at end of file diff --git a/state-test.lua b/state-test.lua index c8f8ebb..57d17bc 100644 --- a/state-test.lua +++ b/state-test.lua @@ -1,4 +1,4 @@ -local memory, movie, utime, callback, set_timer_timeout, input = memory, movie, utime, callback, set_timer_timeout, input +local memory, movie, utime, callback, set_timer_timeout, input, gui, exec, settings = memory, movie, utime, callback, set_timer_timeout, input, gui, exec, settings local base = string.gsub(@@LUA_SCRIPT_FILENAME@@, "(.*[/\\])(.*)", "%1") local Promise = dofile(base.."/promise.lua") @@ -9,9 +9,4 @@ end) set_timer_timeout(1) local game = dofile(base.."/game.lua")(Promise) local util = dofile(base.."/util.lua")(Promise) -local serpent = dofile(base.."/serpent.lua") - -local test = io.popen("cat > Z:\\UserProfiles\\EmpathicQubit\\testy.txt", 'w') -test:write("hello world\n") -test:flush() -test:close() \ No newline at end of file +local serpent = dofile(base.."/serpent.lua") \ No newline at end of file diff --git a/util.lua b/util.lua index 19767b2..92ecc9c 100644 --- a/util.lua +++ b/util.lua @@ -1,4 +1,4 @@ -local utime, bit = utime, bit +local utime, bit, callback, exec = utime, bit, callback, exec local base = string.gsub(@@LUA_SCRIPT_FILENAME@@, "(.*[/\\])(.*)", "%1") @@ -8,12 +8,61 @@ local _M = {} _M.isWin = package.config:sub(1, 1) == '\\' +--- Converts a function into a promise. +--- Useful for decoupling code from the original event it was fired in. +---@param next function The function to resolve on the next tick +---@return Promise Promise A promise that returns the value of the next function function _M.promiseWrap(next) local promise = Promise.new() promise:resolve() return promise:next(next) end +--- 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 +--- handler setup +---@param delayUsec number Number of microseconds to wait +---@return Promise Promise A promise that resolves when the time has elapsed +function _M.delay(delayUsec) + return Promise.new(function(res, rej) + local sec, usec = utime() + local start = sec * 1000000 + usec + local finish = start + local unTimer = nil + local function onTimer() + sec, usec = utime() + finish = sec * 1000000 + usec + if finish - start >= delayUsec then + callback.unregister('timer', unTimer) + res() + end + end + unTimer = callback.register('timer', onTimer) + end) +end + +function _M.loadAndStart(romFile) + return Promise.new(function(res, rej) + local unPaint = nil + local paint = 0 + local function onPaint() + paint = paint + 1 + + _M.promiseWrap(function() + if paint == 1 then + exec('pause-emulator') + elseif paint > 1 then + callback.unregister('paint', unPaint) + res() + end + end) + end + unPaint = callback.register('paint', onPaint) + + exec('load-rom '..romFile) + end) +end + function _M.getTempDir() local temps = { os.getenv("TMPDIR"),