Comment 33 for bug 1617576

Revision history for this message
SirVer (sirver) wrote : Re: Noe messages for Territorial Lord?

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:

thread: 0x7ff6d30f0188 :
   "time" = "30000"
      "plrs" = "table: 0x7ff6d123dd30"
         "1" = "Player(1)"
         "2" = "Player(2)"
      "fields" = "table: 0x7ff6d1236d70"
        ... lines omitted
      "map" = "table: 0x7ff6d30f1e00"
         "0" = "userdata: 0x7ff6d30f1e68"
      "currentcandidate" = "Player 1"
      "candidateisteam" = "false"
      "remaining_time" = "990"
      "teamnumbers" = "table: 0x7ff6d1236ef0"
      "_landsizes" = "table: 0x7ff6d1237700"
         "1" = "5895"
         "2" = "1101"
      "_calc_current_landsizes" = "function: 0x7ff6d1237fa0"
*** Ending Lua interpretation!

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.