Project: Freeciv
Revision: 15192
Author: mbook
Date: 03 Sep 2008 16:44:56
Changes:Implemented team alternating movement phases.
- 'Simultaneous phases' server setting renamed
to 'phase mode' and extended to integer values.
- New setting phasemode=2 allows teammates to play
their turn at the same time, but makes teams as
a whole alternate.
Feature requested in #40444 by Michael Mielke .
Files:modified: /trunk/common/packets.def (
try)
modified: /trunk/server/savegame.c (
try)
modified: /trunk/common/game.c (
try)
modified: /trunk/client/text.c (
try)
modified: /trunk/server/srv_main.c (
try)
modified: /trunk/common/game.h (
try)
modified: /trunk/server/settings.c (
try)
modified: /trunk/client/packhand.c (
try)
Diff:
| ... | ...@@ -4106,12 +4106,35 @@ |
| 4106 | 4106 | } else { |
| 4107 | 4107 | game.info.turn = -2; |
| 4108 | 4108 | } |
| 4109 | | game.info.simultaneous_phases |
| 4110 | | = secfile_lookup_bool_default(file, TRUE, |
| 4111 | | "game.simultaneous_phases_now"); |
| 4112 | | game.simultaneous_phases_stored |
| 4113 | | = secfile_lookup_bool_default(file, TRUE, |
| 4114 | | "game.simultaneous_phases_stored"); |
| 4109 | |
| 4110 | if (section_file_lookup(file, "game.simultaneous_phases_now")) { |
| 4111 | bool sp_now; |
| 4112 | |
| 4113 | sp_now = secfile_lookup_bool(file, "game.simultaneous_phases_now"); |
| 4114 | game.info.phase_mode = (sp_now ? PMT_CONCURRENT |
| 4115 | : PMT_PLAYERS_ALTERNATE); |
| 4116 | |
| 4117 | } else { |
| 4118 | game.info.phase_mode = GAME_DEFAULT_PHASE_MODE; |
| 4119 | } |
| 4120 | |
| 4121 | if (section_file_lookup(file, "game.simultaneous_phases_stored")) { |
| 4122 | bool sp_stored; |
| 4123 | |
| 4124 | sp_stored |
| 4125 | = secfile_lookup_bool(file, "game.simultaneous_phases_stored"); |
| 4126 | game.phase_mode_stored = (sp_stored ? PMT_CONCURRENT |
| 4127 | : PMT_PLAYERS_ALTERNATE); |
| 4128 | } else { |
| 4129 | game.phase_mode_stored = game.info.phase_mode; |
| 4130 | } |
| 4131 | |
| 4132 | game.info.phase_mode |
| 4133 | = secfile_lookup_int_default(file, game.info.phase_mode, |
| 4134 | "game.phase_mode"); |
| 4135 | game.phase_mode_stored |
| 4136 | = secfile_lookup_int_default(file, game.phase_mode_stored, |
| 4137 | "game.phase_mode_stored"); |
| 4115 | 4138 | |
| 4116 | 4139 | game.info.min_players = secfile_lookup_int(file, "game.min_players"); |
| 4117 | 4140 | game.info.max_players = secfile_lookup_int(file, "game.max_players"); |
| ... | ...@@ -4819,10 +4842,10 @@ |
| 4819 | 4842 | secfile_insert_int(file, game.info.end_year, "game.end_year"); |
| 4820 | 4843 | secfile_insert_int(file, game.info.year, "game.year"); |
| 4821 | 4844 | secfile_insert_int(file, game.info.turn, "game.turn"); |
| 4822 | | secfile_insert_bool(file, game.info.simultaneous_phases, |
| 4823 | | "game.simultaneous_phases_now"); |
| 4824 | | secfile_insert_bool(file, game.simultaneous_phases_stored, |
| 4825 | | "game.simultaneous_phases_stored"); |
| 4845 | secfile_insert_int(file, game.info.phase_mode, |
| 4846 | "game.phase_mode"); |
| 4847 | secfile_insert_int(file, game.phase_mode_stored, |
| 4848 | "game.phase_mode_stored"); |
| 4826 | 4849 | secfile_insert_int(file, game.info.min_players, "game.min_players"); |
| 4827 | 4850 | secfile_insert_int(file, game.info.max_players, "game.max_players"); |
| 4828 | 4851 | secfile_insert_int(file, game.info.nplayers, "game.nplayers"); |
| ... | ...@@ -319,7 +319,7 @@ |
| 319 | 319 | sz_strlcpy(game.info.start_units, GAME_DEFAULT_START_UNITS); |
| 320 | 320 | |
| 321 | 321 | game.fogofwar_old = game.info.fogofwar; |
| 322 | | game.simultaneous_phases_stored = GAME_DEFAULT_SIMULTANEOUS_PHASES; |
| 322 | game.phase_mode_stored = GAME_DEFAULT_PHASE_MODE; |
| 323 | 323 | game.timeoutint = GAME_DEFAULT_TIMEOUTINT; |
| 324 | 324 | game.timeoutintinc = GAME_DEFAULT_TIMEOUTINTINC; |
| 325 | 325 | game.timeoutinc = GAME_DEFAULT_TIMEOUTINC; |
| ... | ...@@ -615,10 +615,32 @@ |
| 615 | 615 | |
| 616 | 616 | /************************************************************************** |
| 617 | 617 | Return TRUE if it is this player's phase. |
| 618 | NB: The meaning of the 'phase' argument must match its use in the |
| 619 | function begin_turn() in server/srv_main.c. |
| 620 | NB: The phase mode PMT_TEAMS_ALTERNATE assumes that every player is |
| 621 | on a team, i.e. that pplayer->team is never NULL. |
| 618 | 622 | **************************************************************************/ |
| 619 | 623 | bool is_player_phase(const struct player *pplayer, int phase) |
| 620 | 624 | { |
| 621 | | return game.info.simultaneous_phases || player_number(pplayer) == phase; |
| 625 | switch (game.info.phase_mode) { |
| 626 | case PMT_CONCURRENT: |
| 627 | return TRUE; |
| 628 | break; |
| 629 | case PMT_PLAYERS_ALTERNATE: |
| 630 | return player_number(pplayer) == phase; |
| 631 | break; |
| 632 | case PMT_TEAMS_ALTERNATE: |
| 633 | assert(pplayer->team != NULL); |
| 634 | return team_number(pplayer->team) == phase; |
| 635 | break; |
| 636 | default: |
| 637 | break; |
| 638 | } |
| 639 | |
| 640 | freelog(LOG_FATAL, "Unrecognized phase mode %d in is_player_phase().", |
| 641 | phase); |
| 642 | assert(FALSE); |
| 643 | return TRUE; |
| 622 | 644 | } |
| 623 | 645 | |
| 624 | 646 | /**************************************************************************** |
| ... | ...@@ -616,13 +616,20 @@ |
| 616 | 616 | client.conn.playing->economic.luxury, |
| 617 | 617 | client.conn.playing->economic.science); |
| 618 | 618 | } |
| 619 | | if (!game.info.simultaneous_phases) { |
| 619 | if (game.info.phase_mode == PMT_PLAYERS_ALTERNATE) { |
| 620 | 620 | if (game.info.phase < 0 || game.info.phase >= game.info.nplayers) { |
| 621 | 621 | astr_add_line(&str, _("Moving: Nobody")); |
| 622 | 622 | } else { |
| 623 | 623 | astr_add_line(&str, _("Moving: %s"), |
| 624 | 624 | player_name(player_by_number(game.info.phase))); |
| 625 | 625 | } |
| 626 | } else if (game.info.phase_mode == PMT_TEAMS_ALTERNATE) { |
| 627 | if (game.info.phase < 0 || game.info.phase >= team_count()) { |
| 628 | astr_add_line(&str, _("Moving: Nobody")); |
| 629 | } else { |
| 630 | astr_add_line(&str, _("Moving: %s"), |
| 631 | team_name_translation(team_by_number(game.info.phase))); |
| 632 | } |
| 626 | 633 | } |
| 627 | 634 | astr_add_line(&str, _("(Click for more info)")); |
| 628 | 635 | return str.str; |
| ... | ...@@ -602,12 +602,25 @@ |
| 602 | 602 | |
| 603 | 603 | /* Reset this each turn. */ |
| 604 | 604 | if (is_new_turn) { |
| 605 | | game.info.simultaneous_phases = game.simultaneous_phases_stored; |
| 605 | game.info.phase_mode = game.phase_mode_stored; |
| 606 | 606 | } |
| 607 | | if (game.info.simultaneous_phases) { |
| 607 | |
| 608 | /* NB: Phase logic must match is_player_phase(). */ |
| 609 | switch (game.info.phase_mode) { |
| 610 | case PMT_CONCURRENT: |
| 608 | 611 | game.info.num_phases = 1; |
| 609 | | } else { |
| 612 | break; |
| 613 | case PMT_PLAYERS_ALTERNATE: |
| 610 | 614 | game.info.num_phases = game.info.nplayers; |
| 615 | break; |
| 616 | case PMT_TEAMS_ALTERNATE: |
| 617 | game.info.num_phases = team_count(); |
| 618 | break; |
| 619 | default: |
| 620 | freelog(LOG_FATAL, "Unrecognized phase mode %d in begin_turn().", |
| 621 | game.info.phase_mode); |
| 622 | assert(FALSE); |
| 623 | break; |
| 611 | 624 | } |
| 612 | 625 | send_game_info(NULL); |
| 613 | 626 | |
| ... | ...@@ -647,7 +660,7 @@ |
| 647 | 660 | } |
| 648 | 661 | } |
| 649 | 662 | |
| 650 | | if (is_new_turn && game.info.simultaneous_phases) { |
| 663 | if (is_new_turn && game.info.phase_mode == PMT_CONCURRENT) { |
| 651 | 664 | freelog(LOG_DEBUG, "Shuffleplayers"); |
| 652 | 665 | shuffle_players(); |
| 653 | 666 | } |
| ... | ...@@ -32,6 +32,14 @@ |
| 32 | 32 | DEBUG_LAST |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | /* NB: Must match phasemode setting |
| 36 | * help text in server/settings.c */ |
| 37 | enum phase_mode_types { |
| 38 | PMT_CONCURRENT = 0, |
| 39 | PMT_PLAYERS_ALTERNATE = 1, |
| 40 | PMT_TEAMS_ALTERNATE = 2 |
| 41 | }; |
| 42 | |
| 35 | 43 | #define CONTAMINATION_POLLUTION 1 |
| 36 | 44 | #define CONTAMINATION_FALLOUT 2 |
| 37 | 45 | |
| ... | ...@@ -55,10 +63,10 @@ |
| 55 | 63 | time_t last_ping; |
| 56 | 64 | struct timer *phase_timer; /* Time since seconds_to_phase_done was set. */ |
| 57 | 65 | |
| 58 | | /* The .info.simultaneous_phases value indicates the phase mode currently in |
| 66 | /* The .info.phase_mode value indicates the phase mode currently in |
| 59 | 67 | * use. The "stored" value is a value the player can change; it won't |
| 60 | 68 | * take effect until the next turn. */ |
| 61 | | bool simultaneous_phases_stored; |
| 69 | int phase_mode_stored; |
| 62 | 70 | char *startmessage; |
| 63 | 71 | struct player players[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS]; |
| 64 | 72 | struct conn_list *all_connections; /* including not yet established */ |
| ... | ...@@ -275,7 +283,9 @@ |
| 275 | 283 | #define GAME_MIN_TIMEOUT -1 |
| 276 | 284 | #define GAME_MAX_TIMEOUT 8639999 |
| 277 | 285 | |
| 278 | | #define GAME_DEFAULT_SIMULTANEOUS_PHASES TRUE |
| 286 | #define GAME_DEFAULT_PHASE_MODE 0 |
| 287 | #define GAME_MIN_PHASE_MODE 0 |
| 288 | #define GAME_MAX_PHASE_MODE 2 |
| 279 | 289 | |
| 280 | 290 | #define GAME_DEFAULT_TCPTIMEOUT 10 |
| 281 | 291 | #define GAME_MIN_TCPTIMEOUT 0 |
| ... | ...@@ -197,6 +197,25 @@ |
| 197 | 197 | return TRUE; |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | /************************************************************************* |
| 201 | Check that everyone is on a team for team-alternating simultaneous |
| 202 | phases. NB: Assumes that it is not possible to first set team |
| 203 | alternating phase mode then make teamless players. |
| 204 | *************************************************************************/ |
| 205 | static bool phasemode_callback(int value, const char **error_string) |
| 206 | { |
| 207 | if (value == PMT_TEAMS_ALTERNATE) { |
| 208 | players_iterate(pplayer) { |
| 209 | if (!pplayer->team) { |
| 210 | *error_string = _("All players must have a team if this option " |
| 211 | "value is used."); |
| 212 | return FALSE; |
| 213 | } |
| 214 | } players_iterate_end; |
| 215 | } |
| 216 | *error_string = NULL; |
| 217 | return TRUE; |
| 218 | } |
| 200 | 219 | |
| 201 | 220 | /************************************************************************/ |
| 202 | 221 | #if defined(HAVE_LIBBZ2) |
| ... | ...@@ -908,13 +927,18 @@ |
| 908 | 927 | /* This setting points to the "stored" value; changing it won't have |
| 909 | 928 | * an effect until the next synchronization point (i.e., the start of |
| 910 | 929 | * the next turn). */ |
| 911 | | GEN_BOOL("simultaneousphases", game.simultaneous_phases_stored, |
| 912 | | SSET_META, SSET_INTERNAL, SSET_SITUATIONAL, SSET_TO_CLIENT, |
| 913 | | N_("Whether to have simultaneous player phases."), |
| 914 | | N_("If true, all players' movement phases will occur " |
| 915 | | "simultaneously; if false, then players will " |
| 916 | | "alternate movement."), NULL, |
| 917 | | GAME_DEFAULT_SIMULTANEOUS_PHASES) |
| 930 | GEN_INT("phasemode", game.phase_mode_stored, |
| 931 | SSET_META, SSET_INTERNAL, SSET_SITUATIONAL, SSET_TO_CLIENT, |
| 932 | N_("Whether to have simultaneous player/team phases."), |
| 933 | /* NB: The values must match enum phase_mode_types |
| 934 | * defined in common/game.h */ |
| 935 | N_("This setting controls whether players may make " |
| 936 | "moves at the same time during a turn.\n" |
| 937 | " 0 = All players move concurrently.\n" |
| 938 | " 1 = All players alternate movement.\n" |
| 939 | " 2 = Only players on the same team move concurrently."), |
| 940 | phasemode_callback, GAME_MIN_PHASE_MODE, |
| 941 | GAME_MAX_PHASE_MODE, GAME_DEFAULT_PHASE_MODE) |
| 918 | 942 | |
| 919 | 943 | GEN_INT("nettimeout", game.info.tcptimeout, |
| 920 | 944 | SSET_META, SSET_NETWORK, SSET_RARE, SSET_TO_CLIENT, |
| ... | ...@@ -1011,7 +1011,11 @@ |
| 1011 | 1011 | void handle_start_phase(int phase) |
| 1012 | 1012 | { |
| 1013 | 1013 | |
| 1014 | | if (phase < 0 || phase >= player_count()) { |
| 1014 | if (phase < 0 |
| 1015 | || (game.info.phase_mode == PMT_PLAYERS_ALTERNATE |
| 1016 | && phase >= player_count()) |
| 1017 | || (game.info.phase_mode == PMT_TEAMS_ALTERNATE |
| 1018 | && phase >= team_count())) { |
| 1015 | 1019 | freelog(LOG_ERROR, |
| 1016 | 1020 | "handle_start_phase() illegal phase %d.", |
| 1017 | 1021 | phase); |
To list