neat-donk/runner-wrapper.lua

214 lines
6.1 KiB
Lua
Raw Normal View History

local random = random
2021-04-09 15:06:55 -04:00
local base = string.gsub(@@LUA_SCRIPT_FILENAME@@, "(.*[/\\])(.*)", "%1")
local util = dofile(base.."/util.lua")
2021-04-23 19:04:59 -04:00
local config = dofile(base.."/config.lua")
2021-04-23 15:39:11 -04:00
local serpent = dofile(base.."/serpent.lua")
local temps = {
os.getenv("TMPDIR"),
os.getenv("TEMP"),
os.getenv("TEMPDIR"),
os.getenv("TMP"),
}
local tempDir = "/tmp"
for i=1,#temps,1 do
local temp = temps[i]
if temp ~= nil and temp ~= "" then
tempDir = temps[i]
break
end
end
2021-04-28 18:54:39 -04:00
local tmpFileName = tempDir.."/donk_runner_"..
string.hex(math.floor(random.integer(0, 0xffffffff)))..
string.hex(math.floor(random.integer(0, 0xffffffff)))
2021-04-09 15:06:55 -04:00
local function message(_M, msg, color)
if color == nil then
color = 0x00009900
end
for i=#_M.onMessageHandler,1,-1 do
_M.onMessageHandler[i](msg, color)
end
end
2021-04-09 17:47:08 -04:00
local function save(_M, filename)
2021-04-09 15:06:55 -04:00
for i=#_M.onSaveHandler,1,-1 do
2021-04-09 17:47:08 -04:00
_M.onSaveHandler[i](filename)
2021-04-09 15:06:55 -04:00
end
end
local function onSave(_M, handler)
table.insert(_M.onSaveHandler, handler)
end
2021-04-09 17:47:08 -04:00
local function load(_M, filename)
2021-04-09 15:06:55 -04:00
for i=#_M.onLoadHandler,1,-1 do
2021-04-09 17:47:08 -04:00
_M.onLoadHandler[i](filename)
2021-04-09 15:06:55 -04:00
end
end
local function onLoad(_M, handler)
table.insert(_M.onLoadHandler, handler)
end
2021-04-09 17:47:08 -04:00
local function onMessage(_M, handler)
table.insert(_M.onMessageHandler, handler)
end
2021-04-09 15:06:55 -04:00
return function()
2021-04-30 00:54:35 -04:00
if util.isWin then
util.downloadFile('https://github.com/watchexec/watchexec/releases/download/1.13.1/watchexec-1.13.1-x86_64-pc-windows-gnu.zip', base..'/watchexec.zip')
util.unzip(base..'/watchexec.zip', base)
os.rename(base..'watchexec-1.13.1-x86_64-pc-windows-gnu', base..'/watchexec')
end
2021-04-09 15:06:55 -04:00
local _M = {
onMessageHandler = {},
2021-04-09 17:47:08 -04:00
onSaveHandler = {},
onLoadHandler = {},
2021-04-28 18:54:39 -04:00
poppets = {},
2021-04-29 08:51:03 -04:00
hostProcess = "lsnes",
2021-04-09 15:06:55 -04:00
}
2021-04-29 08:51:03 -04:00
if util.isWin then
_M.hostProcess = util.scrapeCmd('*l', 'powershell "(Get-WmiObject Win32_Process -Filter ProcessId=$((Get-WmiObject Win32_Process -Filter ProcessId=$((Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId)).ParentProcessId)").ExecutablePath')
if _M.hostProcess == nil or _M.hostProcess == "" then
_M.hostProcess = "lsnes-bsnes.exe"
end
else
-- FIXME Linux
end
2021-04-09 15:06:55 -04:00
_M.onRenderForm = function(handler)
end
_M.onMessage = function(handler)
onMessage(_M, handler)
end
2021-04-09 17:47:08 -04:00
_M.message = function(msg, color)
message(_M, msg, color)
end
_M.onSave = function(handler)
onSave(_M, handler)
end
_M.onLoad = function(handler)
onLoad(_M, handler)
end
_M.run = function(species, generationIdx, genomeCallback, finishCallback)
local inputPrefix = tmpFileName..'_input_'
local outputPrefix = tmpFileName..'_output_'
-- Create the input files and output files
for i=1,#species,1 do
local inputFileName = inputPrefix..i
local inputFile = io.open(inputFileName, 'a')
inputFile:close()
local outputFileName = outputPrefix..i
local outputFile = io.open(outputFileName, 'a')
outputFile:close()
end
2021-04-28 18:54:39 -04:00
while #_M.poppets < #species do
local i = #_M.poppets+1
local outputFileName = outputPrefix..i
local inputFileName = inputPrefix..i
2021-04-28 18:54:39 -04:00
2021-04-29 08:51:03 -04:00
message(_M, _M.hostProcess)
2021-04-28 18:54:39 -04:00
2021-04-29 04:56:55 -04:00
local settingsDir = nil
if isWin then
settingsDir = tempDir.."/donk_runner_settings_"..i
util.mkdir(settingsDir)
end
local envs = {
2021-04-28 18:54:39 -04:00
RUNNER_INPUT_FILE = inputFileName,
RUNNER_OUTPUT_FILE = outputFileName,
2021-04-29 04:56:55 -04:00
APPDATA = settingsDir,
}
local waiter = util.startWaiting(outputFileName)
2021-04-28 18:54:39 -04:00
2021-04-29 08:51:03 -04:00
local cmd = '"'.._M.hostProcess..'" "--rom='..config.ROM..'" --unpause "--lua='..base..'/runner-process.lua"'
2021-04-28 18:54:39 -04:00
local poppet = util.popenCmd(cmd, nil, envs)
table.insert(_M.poppets, poppet)
util.finishWaiting(waiter)
2021-04-09 15:06:55 -04:00
end
local waiters = {}
for i=1,#species,1 do
table.insert(waiters, outputPrefix..i)
end
local waiter = util.startWaiting(waiters, nil, tmpFileName.."_output_*")
2021-04-28 18:54:39 -04:00
message(_M, 'Setting up child processes')
for i=1,#species,1 do
2021-04-28 18:54:39 -04:00
local inputFileName = tmpFileName.."_input_"..i
local inputFile = io.open(inputFileName, 'w')
inputFile:write(serpent.dump({species[i], generationIdx}))
inputFile:close()
2021-04-09 15:06:55 -04:00
end
2021-04-28 18:54:39 -04:00
message(_M, 'Waiting for child processes to finish')
util.finishWaiting(waiter, #waiters)
2021-04-28 18:54:39 -04:00
message(_M, 'Child processes finished')
2021-04-23 18:09:35 -04:00
for i=1,#species,1 do
2021-04-28 18:54:39 -04:00
message(_M, "Processing output "..i)
2021-04-23 18:09:35 -04:00
local outputFileName = tmpFileName..'_output_'..i
local outputFile = io.open(outputFileName, "r")
local line = ""
repeat
local ok, obj = serpent.load(line)
if not ok then
2021-04-23 18:09:35 -04:00
goto continue
end
if obj == nil then
goto continue
end
if obj.type == 'onMessage' then
message(_M, obj.msg, obj.color)
elseif obj.type == 'onLoad' then
load(_M, obj.filename)
elseif obj.type == 'onSave' then
save(_M, obj.filename)
elseif obj.type == 'onGenome' then
for i=1,#species,1 do
local s = species[i]
if s.id == obj.speciesId then
s.genomes[obj.genomeIndex] = obj.genome
break
end
end
2021-04-23 18:09:35 -04:00
genomeCallback(obj.genome, obj.index)
elseif obj.type == 'onFinish' then
finishCallback()
end
::continue::
line = outputFile:read()
until(line == "" or line == nil)
outputFile:close()
2021-04-09 15:06:55 -04:00
end
end
return _M
end