widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #00680
[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