← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~2td0-andreas-y5md/widelands/territorial_time into lp:widelands

 

Andreas Eriksson has proposed merging lp:~2td0-andreas-y5md/widelands/territorial_time into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~2td0-andreas-y5md/widelands/territorial_time/+merge/94688

Added a new game mode/win condition "Territorial Time".
The new game mode is essentially "Territorial Lord" with a time limit of 4
hours. Similar to the "Wood Gnome" or "Collectors" mode the player with the
most land wins after 4 hours. Or a player wins if the player manages to hold
more than 50% of the land for 20 minutes before the 4 hours are up (as in
regular "Territorial Lord").
-- 
https://code.launchpad.net/~2td0-andreas-y5md/widelands/territorial_time/+merge/94688
Your team Widelands Developers is requested to review the proposed merge of lp:~2td0-andreas-y5md/widelands/territorial_time into lp:widelands.
=== modified file 'scripting/win_condition_texts.lua'
--- scripting/win_condition_texts.lua	2012-01-28 19:47:46 +0000
+++ scripting/win_condition_texts.lua	2012-02-26 19:42:20 +0000
@@ -47,4 +47,9 @@
   other2 = _ "You still got %i minutes to prevent a victory.",
   player1 = _ "You own more than half of the maps area.",
   player2 = _ "Keep it for %i more minutes to win the game."
-}
\ No newline at end of file
+}
+
+game_status_territoral_lord_time = {
+  end_in = _ "game will end in %i minutes.",
+  land = _ "%s %s %i%% of the land (%i of %i)."
+}

=== added file 'scripting/win_conditions/03_territorial_time.lua'
--- scripting/win_conditions/03_territorial_time.lua	1970-01-01 00:00:00 +0000
+++ scripting/win_conditions/03_territorial_time.lua	2012-02-26 19:42:20 +0000
@@ -0,0 +1,272 @@
+-- =======================================================================
+--                   Territorial Time Win condition
+-- =======================================================================
+
+use("aux", "coroutine") -- for sleep
+use("aux", "table")
+use("aux", "win_condition_functions")
+
+set_textdomain("win_conditions")
+
+use("aux", "win_condition_texts")
+
+local wc_name = _ "Territorial Time"
+local wc_version = 1
+local wc_desc = _ (
+	"Each player or team tries to obtain more than half of the maps' " ..
+	"area. The winner will be the player or the team that is able to keep " ..
+	"that area for at least 20 minutes or the one with the most territory " ..
+	"after 4 hours, whichever comes first."
+)
+return {
+	name = wc_name,
+	description = wc_desc,
+	func = function()
+
+		-- Get all valueable fields of the map
+		local fields = {}
+      local map = wl.Game().map
+		for x=0,map.width-1 do
+			for y=0,map.height-1 do
+				local f = map:get_field(x,y)
+				if f then
+					-- add this field to the list as long as it has not movecaps swim
+					if not f:has_caps("swimmable") then
+						if f:has_caps("walkable") then
+							fields[#fields+1] = f
+						else
+							-- editor disallows placement of immovables on dead and acid fields
+							if f.immovable then
+								fields[#fields+1] = f
+							end
+						end
+					end
+				end
+			end
+		end
+
+		-- variables to track the maximum 4 hours of gametime
+		local remaining_max_time = 4 * 60 * 60 -- 4 hours
+
+		-- these variables will be used once a player or team owns more than half
+		-- of the map's area
+		local currentcandidate = "" -- Name of Team or Player
+		local candidateisteam = false
+		local remaining_time = 10 -- (dummy) -- time in secs, if == 0 -> victory
+
+		-- Find all valid players
+      local plrs = wl.Game().players
+
+		-- send a message with the game type to all players
+		broadcast(plrs, wc_name, wc_desc)
+
+		-- Find all valid teams
+		local teamnumbers = {} -- array with team numbers
+		for idx,p in ipairs(plrs) do
+			local team = p.team
+			if team > 0 then
+				local found = false
+				for idy,t in ipairs(teamnumbers) do
+					if t == team then
+						found = true
+						break
+					end
+				end
+				if not found then
+					teamnumbers[#teamnumbers+1] = team
+				end
+			end
+		end
+
+		local _landsizes = {}
+		local function _calc_current_landsizes()
+			-- init the landsizes for each player
+			for idx,plr in ipairs(plrs) do
+				_landsizes[plr.number] = 0
+			end
+
+			for idx,f in ipairs(fields) do
+				-- check if field is owned by a player
+				local o = f.owner
+				if o then
+					local n = o.number
+					_landsizes[n] = _landsizes[n] + 1
+				end
+			end
+		end
+
+		function _calc_points()
+			local teampoints = {}     -- points of teams
+			local points = {} -- tracking points of teams and players without teams
+			local maxplayerpoints = 0 -- the highest points of a player without team
+			local maxpointsplayer = 0 -- the player
+			local foundcandidate = false
+
+			_calc_current_landsizes()
+
+			for idx, p in ipairs(plrs) do
+				local team = p.team
+				if team == 0 then
+					if maxplayerpoints < _landsizes[p.number] then
+						maxplayerpoints = _landsizes[p.number]
+						maxpointsplayer = p
+					end
+					points[#points + 1] = { p.name, _landsizes[p.number] }
+				else
+					if not teampoints[team] then -- init the value
+						teampoints[team] = 0
+					end
+					teampoints[team] = teampoints[team] + _landsizes[p.number]
+				end
+			end
+
+			if maxplayerpoints > ( #fields / 2 ) then
+				-- player owns more than half of the map's area
+				foundcandidate = true
+				if candidateisteam == false and currentcandidate == maxpointsplayer.name then
+					remaining_time = remaining_time - 30
+				else
+					currentcandidate = maxpointsplayer.name
+					candidateisteam = false
+					remaining_time = 20 * 60 -- 20 minutes
+				end
+			end
+			for idx, t in ipairs(teamnumbers) do
+				if teampoints[t] > ( #fields / 2 ) then
+					-- this team owns more than half of the map's area
+					foundcandidate = true
+					if candidateisteam == true and currentcandidate == game_status_territoral_lord.team:format(t) then
+						remaining_time = remaining_time - 30
+					else
+						currentcandidate = game_status_territoral_lord.team:format(t)
+						candidateisteam = true
+						remaining_time = 20 * 60 -- 20 minutes
+					end
+				end
+				points[#points + 1] = { game_status_territoral_lord.team:format(t), teampoints[t] }
+			end
+			if not foundcandidate then
+				remaining_time = 10
+			end
+			return points
+		end
+
+		function _percent(part, whole)
+			return (part * 100) / whole
+		end
+
+		-- Helper function to get the points that the leader has
+		function _maxpoints(points)
+			local max = 0
+			for i=1,#points do
+				if points[i][2] > max then max = points[i][2] end
+			end
+			return max
+		end
+
+		-- Helper function that returns a string containing the current
+		-- land percentages of players/teams.
+		function _status(points, has_had)
+			local msg = ""
+			for i=1,#points do
+				msg = msg .. "\n"
+				msg = msg ..
+								game_status_territoral_lord_time.land:format(
+										points[i][1],
+										has_had,
+										_percent(points[i][2], #fields),
+										points[i][2],
+										#fields)
+			end
+			return msg
+		end
+
+		function _send_state(points)
+			local msg1 = game_status_territoral_lord.other1:format(currentcandidate)
+			msg1 = msg1 .. "\n"
+			msg1 = msg1 .. game_status_territoral_lord.other2:format(remaining_time / 60)
+
+			local msg2 = game_status_territoral_lord.player1
+			msg2 = msg2 .. "\n"
+			msg2 = msg2 .. game_status_territoral_lord.player2:format(remaining_time / 60)
+
+
+			for idx, p in ipairs(plrs) do
+				local msg = ""
+				if remaining_time < remaining_max_time and _maxpoints(points) > ( #fields / 2 ) then
+					if candidateisteam and currentcandidate == game_status_territoral_lord.team:format(p.team)
+						or not candidateisteam and currentcandidate == p.name then
+						msg = msg .. msg2 .. "\n\n"
+					else
+						msg = msg .. msg1 .. "\n\n"
+					end
+					msg = msg .. "Otherwise the "
+				else
+					msg = msg .. "The "
+				end
+				msg = msg .. game_status_territoral_lord_time.end_in:format(remaining_max_time/60)
+				msg = msg .. "\n\n"
+				msg = msg .. game_status.body
+				msg = msg .. _status(points, "has")
+				p:send_message(game_status.title, msg, {popup = true})
+			end
+		end
+
+		-- Start a new coroutine that checks for defeated players
+		run(function()
+			sleep(5000)
+			check_player_defeated(plrs, lost_game.title,
+				lost_game.body, wc_name, wc_version)
+		end)
+
+		-- here is the main loop!!!
+		while true do
+			-- Sleep 30 seconds == STATISTICS_SAMPLE_TIME
+			sleep(30000)
+
+			remaining_max_time = remaining_max_time - 30
+
+			-- Check if a player or team is a candidate and update variables
+			-- Returns the names and points for the teams and players without a team
+			local points = _calc_points()
+
+
+			-- Game is over, do stuff after loop
+			if remaining_time <= 0 or remaining_max_time <= 0 then break end
+
+			-- at the beginning send remaining max time message only each 30 minutes
+			-- if only 30 minutes or less are left, send each 5 minutes
+			-- also check if there is a candidate and we need to send an update
+			if ((remaining_max_time < (30 * 60) and remaining_max_time % (5 * 60) == 0)
+					or remaining_max_time % (30 * 60) == 0)
+					or remaining_time % 300 == 0 then
+				_send_state(points)
+			end
+		end
+
+		local points = _calc_points()
+		table.sort(points, function(a,b) return a[2] > b[2] end)
+
+		-- Game has ended
+		for idx, p in ipairs(plrs) do
+			p.see_all = 1
+
+			maxpoints = points[1][2]
+			local wonmsg = won_game_over.body
+			wonmsg = wonmsg .. "\n\n" .. game_status.body
+			local lostmsg = lost_game_over.body
+			lostmsg = lostmsg .. "\n\n" .. game_status.body
+			for i=1,#points do
+				if points[i][1] == game_status_territoral_lord.team:format(p.team) or points[i][1] == p.name then
+					if points[i][2] >= maxpoints then
+						p:send_message(won_game_over.title, wonmsg .. _status(points, "had"), {popup = true})
+						wl.game.report_result(p, true, _landsizes[p.number], make_extra_data(p, wc_name, wc_version))
+					else
+						p:send_message(lost_game_over.title, lostmsg .. _status(points, "had"), {popup = true})
+						wl.game.report_result(p, false, _landsizes[p.number], make_extra_data(p, wc_name, wc_version))
+					end
+				end
+			end
+		end
+	end
+}


Follow ups