← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1751440-smugglers-desync into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1751440-smugglers-desync into lp:widelands.

Commit message:
To address desync problems in Smugglers, going round robin rather than smuggling a random ware. Also, allow smuggling if players are playing different tribes - only wares that both tribes have will be smuggled.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1751440 in widelands: "Desync in Smugglers scenario"
  https://bugs.launchpad.net/widelands/+bug/1751440

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1751440-smugglers-desync/+merge/340735

I'm not 100% sure if this branch actually fixes the problem, by I was able to play a full game with 2 players having 2 smuggling routes and the 2 other players idle.

Also, we can now expand the scenario in the future to allow players to choose their tribes, but we need to finish the game loading screen UI first before we can start working on that.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1751440-smugglers-desync into lp:widelands.
=== modified file 'data/maps/MP_Scenarios/Smugglers.wmf/scripting/smuggling.lua'
--- data/maps/MP_Scenarios/Smugglers.wmf/scripting/smuggling.lua	2016-03-26 09:09:43 +0000
+++ data/maps/MP_Scenarios/Smugglers.wmf/scripting/smuggling.lua	2018-03-05 10:38:57 +0000
@@ -35,8 +35,27 @@
    game_over_done = true
 end
 
-function do_smuggling(route_descr, recv_plr, send_plr, recv_whf, send_whf)
-   while 1 do
+function do_smuggling(route_descr, recv_plr, send_plr, recv_wh_field, send_wh_field)
+   -- Collect ware types that both sending and receiving player can use
+   local wares = {}
+   for idx,ware in pairs(send_plr.tribe.wares) do
+      if recv_plr.tribe:has_ware(ware.name) then
+         table.insert(wares, ware.name)
+      end
+   end
+
+   -- If the tribes don't have any wares in common, nothing can be smuggled
+   -- This should not happen, but let's have a safeguard anyway.
+   if #wares < 1 then
+      do_game_over()
+      return
+   end
+
+   -- We start counting at 0 so that we can use the modulo (%) operator
+   -- for going round robin
+   local last_ware_index = 0;
+
+   while true do
       sleep(10000) -- Sleep 10s
 
       if points[1] >= points_to_win or
@@ -46,36 +65,45 @@
          break
       end
 
-      if not send_whf.immovable or
-         send_whf.immovable.descr.type_name ~= "warehouse" or
-         send_whf.immovable.owner ~= send_plr or
-         not recv_whf.immovable or
-         recv_whf.immovable.descr.type_name ~= "warehouse" or
-         recv_whf.immovable.owner ~= recv_plr
+      if not send_wh_field.immovable or
+         send_wh_field.immovable.descr.type_name ~= "warehouse" or
+         send_wh_field.immovable.owner ~= send_plr or
+         not recv_wh_field.immovable or
+         recv_wh_field.immovable.descr.type_name ~= "warehouse" or
+         recv_wh_field.immovable.owner ~= recv_plr
       then
          send_to_all(smuggling_route_broken:bformat(
             (ngettext("%i point", "%i points", route_descr.value)):format(route_descr.value), recv_plr.name, send_plr.name)
          )
          run(wait_for_established_route, route_descr)
-         break
+         return
       end
 
-      -- Warp one ware
-      local wares = send_whf.immovable:get_wares("all")
-      local wn = {}
-      for name,count in pairs(wares) do
-         if count > 0 then
-            wn[#wn + 1] = name
+      -- Warp the next available ware, going round robin
+      local empty_warehouse_guard = #wares
+      local warp_index = last_ware_index
+      local ware_to_warp = nil
+      while empty_warehouse_guard > 0 do
+         -- Index shift, because Lua tables start counting at 1
+         local candidate = wares[warp_index + 1]
+         if send_wh_field.immovable:get_wares(candidate) > 0 then
+            ware_to_warp = candidate
+            break
          end
+
+         warp_index = (warp_index + 1) % #wares;
+         empty_warehouse_guard = empty_warehouse_guard - 1
       end
-      if #wn > 0 then
-         local ware_to_warp = wn[math.random(#wn)]
-         send_whf.immovable:set_wares(ware_to_warp, wares[ware_to_warp] - 1)
-         recv_whf.immovable:set_wares(
-            ware_to_warp, recv_whf.immovable:get_wares(ware_to_warp) + 1
+
+      if ware_to_warp ~= nil then
+         send_wh_field.immovable:set_wares(ware_to_warp, send_wh_field.immovable:get_wares(ware_to_warp) - 1)
+         recv_wh_field.immovable:set_wares(
+            ware_to_warp, recv_wh_field.immovable:get_wares(ware_to_warp) + 1
          )
          points[recv_plr.team] = points[recv_plr.team] + route_descr.value
       end
+      -- Next round robin index
+      last_ware_index = (last_ware_index + 1) % #wares;
    end
 end
 


Follow ups