So, investigating running coroutines in Widelands is not super convenient right now, but it sorta works. I loaded the MoreThenHalf.wgf file and used this Lua script to investigate what is going on:
----
for k, entry in pairs(__coroutine_registry) do
if tonumber(entry) == nil then
print(tostring(entry), ":")
local done = false
for i=1,100 do
if done then break end
for j=1,100 do
if not pcall(debug.getlocal, entry, i, j) then
done = true break
end
l = debug.getlocal(entry, i, j)
if l == nil then break
end
k, v = debug.getlocal(entry, i, j) print(("%s%q = %q"):format((" "):rep(i*3), k, tostring(v)))
if (type(v) == "table") then
for tk, tv in pairs(v) do print(("%s%q = %q"):format((" "):rep((i+1)*3), tk, tostring(tv)))
end
end
end
end
end
end
----
A few remarks to explain what is going on: the debug.* functions are provided by Lua to investigate a running callstack. It is cumbersome, but essentially this script lists all existing coroutines with their local variables (indented by stack depth) and their values. If I run this on the provided savegame I get:
1) there is only one coroutine. This is clearly a bug, but also understandable:
run(function() sleep(5000) check_player_defeated(plrs, lost_game.title, lost_game.body, wc_descname, wc_version)
end)
never loops - so it will only check once for defeated players. So this is a bug in the win condition.
2) remaining_time is 990 seconds and never changes, the _landsizes table is regularly updated though.
3) _calc_current_landsizes is the only function that is listed in the context of this coroutine. Looking through the code I realize that all other functions are globals, i.e. not defined "local function()". Since some of them reference variables from the local frame (like remaining_time), this feels volatile - global funcitons referencing a local frame. I did not test yet if changing those functions to be local () is enough - it might be, because it strongly constraints which variables are available in the functions frame.
4) the logic of the win condition is pretty hard to follow - maybe there is just a plain old bug lurking in it.
So, investigating running coroutines in Widelands is not super convenient right now, but it sorta works. I loaded the MoreThenHalf.wgf file and used this Lua script to investigate what is going on:
---- _coroutine_ registry) do tostring( entry), ":") getlocal, entry, i, j) then
break entry, i, j)
break entry, i, j)
print( ("%s%q = %q"):format((" "):rep(i*3), k, tostring(v)))
print( ("%s%q = %q"):format((" "):rep((i+1)*3), tk, tostring(tv)))
for k, entry in pairs(_
if tonumber(entry) == nil then
print(
local done = false
for i=1,100 do
if done then break end
for j=1,100 do
if not pcall(debug.
done = true
end
l = debug.getlocal(
if l == nil then
end
k, v = debug.getlocal(
if (type(v) == "table") then
for tk, tv in pairs(v) do
end
end
end
end
end
end
----
A few remarks to explain what is going on: the debug.* functions are provided by Lua to investigate a running callstack. It is cumbersome, but essentially this script lists all existing coroutines with their local variables (indented by stack depth) and their values. If I run this on the provided savegame I get:
thread: 0x7ff6d30f0188 : currentcandidat e" = "Player 1" candidateisteam " = "false" remaining_ time" = "990" _calc_current_ landsizes" = "function: 0x7ff6d1237fa0"
"time" = "30000"
"plrs" = "table: 0x7ff6d123dd30"
"1" = "Player(1)"
"2" = "Player(2)"
"fields" = "table: 0x7ff6d1236d70"
... lines omitted
"map" = "table: 0x7ff6d30f1e00"
"0" = "userdata: 0x7ff6d30f1e68"
"
"
"
"teamnumbers" = "table: 0x7ff6d1236ef0"
"_landsizes" = "table: 0x7ff6d1237700"
"1" = "5895"
"2" = "1101"
"
*** Ending Lua interpretation!
1) there is only one coroutine. This is clearly a bug, but also understandable: function( )
sleep( 5000)
check_ player_ defeated( plrs, lost_game.title, lost_game.body, wc_descname, wc_version)
run(
end)
never loops - so it will only check once for defeated players. So this is a bug in the win condition.
2) remaining_time is 990 seconds and never changes, the _landsizes table is regularly updated though. landsizes is the only function that is listed in the context of this coroutine. Looking through the code I realize that all other functions are globals, i.e. not defined "local function()". Since some of them reference variables from the local frame (like remaining_time), this feels volatile - global funcitons referencing a local frame. I did not test yet if changing those functions to be local () is enough - it might be, because it strongly constraints which variables are available in the functions frame.
3) _calc_current_
4) the logic of the win condition is pretty hard to follow - maybe there is just a plain old bug lurking in it.