[Freeciv-Dev] (PR#576) Wishlist: alternating unit movement
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=576 >
This updated patch fixes several more bugs:
- Unit MP are drained after the player's phase ends. This keeps the
player from trying to move those units during other players' phases
(good for single-player too).
- Unit focus statuses are restored at the start of the phase, not the
start of the turn (this was a bug, and is probably also helpful for
single-player).
- Changing the movement style mid-turn shouldn't break things anymore.
There is a separate value tracked for the current turn so a change won't
have an effect until the next turn.
- The values are actually saved now. Whee.
There is one major bug remaining, in that an all-AI game will run amok
without any stoppage. This is actually rather obnoxious, since
obviously AI players must have their phase complete without a
stoppage...but if the game is comprised entirely of AI players it shouldn't.
Thanks to Canophone and Gilles for playtesting.
-jason
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.214
diff -u -r1.214 civclient.c
--- client/civclient.c 13 Feb 2005 19:09:05 -0000 1.214
+++ client/civclient.c 20 Feb 2005 05:46:47 -0000
@@ -419,7 +419,7 @@
attribute_flush();
- send_packet_player_turn_done(&aconnection);
+ send_packet_player_phase_done(&aconnection);
update_turn_done_button_state();
}
@@ -669,12 +669,12 @@
}
if (game.player_ptr->is_connected && game.player_ptr->is_alive &&
- !game.player_ptr->turn_done) {
+ !game.player_ptr->phase_done) {
int is_waiting = 0, is_moving = 0;
players_iterate(pplayer) {
if (pplayer->is_alive && pplayer->is_connected) {
- if (pplayer->turn_done) {
+ if (pplayer->phase_done) {
is_waiting++;
} else {
is_moving++;
Index: client/mapctrl_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapctrl_common.c,v
retrieving revision 1.48
diff -u -r1.48 mapctrl_common.c
--- client/mapctrl_common.c 19 Feb 2005 17:15:13 -0000 1.48
+++ client/mapctrl_common.c 20 Feb 2005 05:46:47 -0000
@@ -578,7 +578,7 @@
}
new_state = (can_client_issue_orders()
- && !game.player_ptr->turn_done && !agents_busy()
+ && !game.player_ptr->phase_done && !agents_busy()
&& !turn_done_sent);
if (new_state == turn_done_state) {
return;
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.472
diff -u -r1.472 packhand.c
--- client/packhand.c 19 Feb 2005 17:15:13 -0000 1.472
+++ client/packhand.c 20 Feb 2005 05:46:47 -0000
@@ -345,7 +345,6 @@
if (get_client_state() == CLIENT_GAME_RUNNING_STATE) {
refresh_overview_canvas();
- player_set_unit_focus_status(game.player_ptr);
update_info_label(); /* get initial population right */
update_unit_focus();
@@ -759,7 +758,6 @@
assert(game.turn == turn);
update_info_label();
- player_set_unit_focus_status(game.player_ptr);
update_unit_focus();
auto_center_on_focus_unit();
@@ -788,7 +786,7 @@
/**************************************************************************
...
**************************************************************************/
-void handle_before_new_year(void)
+void handle_end_phase(void)
{
clear_notify_window();
/*
@@ -806,17 +804,25 @@
/**************************************************************************
...
**************************************************************************/
-void handle_start_turn(void)
+void handle_start_phase(int phase)
{
- agents_start_turn();
- non_ai_unit_focus = FALSE;
+ game.phase = phase;
- turn_done_sent = FALSE;
- update_turn_done_button_state();
+ if (is_player_phase(game.player_ptr, phase)) {
+ agents_start_turn();
+ non_ai_unit_focus = FALSE;
- if(game.player_ptr->ai.control && !ai_manual_turn_done) {
- user_ended_turn();
+ turn_done_sent = FALSE;
+ update_turn_done_button_state();
+
+ if(game.player_ptr->ai.control && !ai_manual_turn_done) {
+ user_ended_turn();
+ }
+
+ player_set_unit_focus_status(game.player_ptr);
}
+
+ update_info_label();
}
/**************************************************************************
@@ -1320,6 +1326,9 @@
game.end_year=pinfo->end_year;
game.year=pinfo->year;
game.turn=pinfo->turn;
+ game.phase = pinfo->phase;
+ game.simultaneous_phases_now = pinfo->simultaneous_phases;
+ game.num_phases = pinfo->num_phases;
game.min_players=pinfo->min_players;
game.max_players=pinfo->max_players;
game.nplayers=pinfo->nplayers;
@@ -1365,8 +1374,8 @@
boot_help = (can_client_change_view()
&& game.spacerace != pinfo->spacerace);
game.spacerace=pinfo->spacerace;
- if (game.timeout != 0 && pinfo->seconds_to_turndone != 0) {
- set_seconds_to_turndone(pinfo->seconds_to_turndone);
+ if (game.timeout != 0 && pinfo->seconds_to_phasedone != 0) {
+ set_seconds_to_turndone(pinfo->seconds_to_phasedone);
}
if (boot_help) {
boot_help_texts(); /* reboot, after setting game.spacerace */
@@ -1512,10 +1521,10 @@
city_report_dialog_update();
}
- if (pplayer == game.player_ptr && pplayer->turn_done != pinfo->turn_done) {
+ if (pplayer == game.player_ptr && pplayer->phase_done != pinfo->phase_done) {
update_turn_done_button_state();
}
- pplayer->turn_done=pinfo->turn_done;
+ pplayer->phase_done = pinfo->phase_done;
pplayer->nturns_idle=pinfo->nturns_idle;
pplayer->is_alive=pinfo->is_alive;
Index: client/plrdlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/plrdlg_common.c,v
retrieving revision 1.16
diff -u -r1.16 plrdlg_common.c
--- client/plrdlg_common.c 24 Dec 2004 23:36:33 -0000 1.16
+++ client/plrdlg_common.c 20 Feb 2005 05:46:47 -0000
@@ -179,18 +179,16 @@
*******************************************************************/
static const char *col_state(const struct player *plr)
{
- if (plr->is_alive) {
- if (plr->is_connected) {
- if (plr->turn_done) {
- return _("done");
- } else {
- return _("moving");
- }
- } else {
- return "";
- }
- } else {
+ if (!plr->is_alive) {
return _("R.I.P");
+ } else if (!plr->is_connected) {
+ return "";
+ } else if (!is_player_phase(plr, game.phase)) {
+ return _("waiting");
+ } else if (plr->phase_done) {
+ return _("done");
+ } else {
+ return _("moving");
}
}
Index: client/text.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/text.c,v
retrieving revision 1.27
diff -u -r1.27 text.c
--- client/text.c 16 Feb 2005 17:42:36 -0000 1.27
+++ client/text.c 20 Feb 2005 05:46:47 -0000
@@ -461,6 +461,9 @@
add_line(_("Tax: %d Lux: %d Sci: %d"), game.player_ptr->economic.tax,
game.player_ptr->economic.luxury,
game.player_ptr->economic.science);
+ if (!game.simultaneous_phases_now) {
+ add_line(_("Moving: %s"), get_player(game.phase)->name);
+ }
RETURN;
}
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.196
diff -u -r1.196 game.c
--- common/game.c 16 Feb 2005 18:06:29 -0000 1.196
+++ common/game.c 20 Feb 2005 05:46:48 -0000
@@ -526,6 +526,14 @@
return game.nplayers-game.nbarbarians;
}
+/**************************************************************************
+ Return TRUE if it is this player's phase.
+**************************************************************************/
+bool is_player_phase(const struct player *pplayer, int phase)
+{
+ return game.simultaneous_phases_now != 0 || pplayer->player_no == phase;
+}
+
/***************************************************************
For various data, copy eg .name to .name_orig and put
translated version in .name
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.172
diff -u -r1.172 game.h
--- common/game.h 16 Feb 2005 18:06:29 -0000 1.172
+++ common/game.h 20 Feb 2005 05:46:48 -0000
@@ -75,10 +75,15 @@
time_t last_ping;
int pingtimeout;
int pingtime;
- time_t turn_start;
+ time_t phase_start;
int end_year;
int year;
int turn;
+ /* The simultaneous_phases_now value indicates the phase mode currently in
+ * use. The "stored" value is a value the player can change; it won't
+ * take effect until the next turn. */
+ bool simultaneous_phases_now, simultaneous_phases_stored;
+ int phase, num_phases;
int researchcost; /* Multiplier on cost of new research */
int diplcost, freecost, conquercost;
int diplchance;
@@ -287,6 +292,7 @@
struct player *get_player(int player_id);
bool is_valid_player_id(int player_id);
int get_num_human_and_ai_players(void);
+bool is_player_phase(const struct player *pplayer, int phase);
const char *population_to_text(int thousand_citizen);
@@ -438,6 +444,8 @@
#endif
#define GAME_MAX_TIMEOUT 8639999
+#define GAME_DEFAULT_SIMULTANEOUSPHASES 0
+
#define GAME_DEFAULT_TCPTIMEOUT 10
#define GAME_MIN_TCPTIMEOUT 0
#define GAME_MAX_TCPTIMEOUT 120
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.94
diff -u -r1.94 packets.def
--- common/packets.def 15 Feb 2005 05:37:05 -0000 1.94
+++ common/packets.def 20 Feb 2005 05:46:48 -0000
@@ -208,6 +208,7 @@
type PERCENT = UINT8
type GOLD = UINT32
type TURN = SINT16
+type PHASE = SINT16
/****************************************************
The remaining lines are the definition of the packets. These are
@@ -338,11 +339,15 @@
UINT8 researchcost;
UINT32 skill_level;
- UINT32 seconds_to_turndone;
+ UINT32 seconds_to_phasedone;
UINT32 timeout;
TURN turn;
+ PHASE phase;
YEAR year, end_year;
+ BOOL simultaneous_phases;
+ UINT32 num_phases;
+
PLAYER min_players, max_players, nplayers, player_idx;
UINT32 globalwarming, heating, warminglevel;
@@ -551,7 +556,7 @@
UINT8 city_style;
NATION nation;
TEAM team;
- BOOL turn_done;
+ BOOL phase_done;
TURN nturns_idle;
BOOL is_alive;
@@ -579,7 +584,7 @@
UINT16 small_wonders[B_LAST]; diff
end
-PACKET_PLAYER_TURN_DONE=40;cs
+PACKET_PLAYER_PHASE_DONE=40;cs
end
PACKET_PLAYER_RATES=41;cs,dsend
@@ -876,10 +881,12 @@
/************** New turn packets **********************/
-PACKET_BEFORE_NEW_YEAR=90;sc,lsend
+PACKET_END_PHASE=90;sc,lsend
end
-PACKET_START_TURN=91;sc,lsend
+# sent to everyone, not just the player whose phase it is
+PACKET_START_PHASE=91;sc,lsend,dsend
+ PHASE phase;
end
# send to each client whenever the turn has ended.
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.139
diff -u -r1.139 player.h
--- common/player.h 16 Feb 2005 18:06:29 -0000 1.139
+++ common/player.h 20 Feb 2005 05:46:48 -0000
@@ -189,7 +189,7 @@
int target_government;
Nation_Type_id nation;
Team_Type_id team;
- bool turn_done;
+ bool phase_done;
int nturns_idle;
bool is_alive;
bool is_observer; /* is the player a global observer */
Index: server/barbarian.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/barbarian.c,v
retrieving revision 1.82
diff -u -r1.82 barbarian.c
--- server/barbarian.c 22 Jan 2005 19:45:44 -0000 1.82
+++ server/barbarian.c 20 Feb 2005 05:46:48 -0000
@@ -130,7 +130,7 @@
barbarians->capital = FALSE;
barbarians->economic.gold = 100;
- barbarians->turn_done = TRUE;
+ barbarians->phase_done = TRUE;
/* Do the ai */
barbarians->ai.control = TRUE;
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.297
diff -u -r1.297 cityturn.c
--- server/cityturn.c 15 Feb 2005 11:09:09 -0000 1.297
+++ server/cityturn.c 20 Feb 2005 05:46:49 -0000
@@ -1083,7 +1083,7 @@
(void) create_unit(pplayer, pcity->tile, pcity->currently_building,
do_make_unit_veteran(pcity, pcity->currently_building),
- pcity->id, -1);
+ pcity->id, 0);
/* After we created the unit remove the citizen. This will also
rearrange the worker to take into account the extra resources
@@ -1418,7 +1418,7 @@
(void) create_unit(pplayer, ptile, pcity->currently_building,
do_make_unit_veteran(pcity, pcity->currently_building),
- pcity->id, -1);
+ pcity->id, 0);
/* Shift all the units supported by pcity (including the new unit)
* to rcity. transfer_city_units does not make sure no units are
Index: server/connecthand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/connecthand.c,v
retrieving revision 1.39
diff -u -r1.39 connecthand.c
--- server/connecthand.c 14 Feb 2005 22:52:41 -0000 1.39
+++ server/connecthand.c 20 Feb 2005 05:46:49 -0000
@@ -130,7 +130,7 @@
send_player_info(NULL,NULL);
send_diplomatic_meetings(pconn);
send_packet_thaw_hint(pconn);
- send_packet_start_turn(pconn);
+ dsend_packet_start_phase(pconn, game.phase);
}
gamelog(GAMELOG_PLAYER, pplayer);
@@ -162,7 +162,7 @@
players_iterate(cplayer) {
if (cplayer->is_alive
&& !cplayer->ai.control
- && !cplayer->turn_done
+ && !cplayer->phase_done
&& cplayer != pconn->player) { /* skip current player */
notify_conn(dest, _("Turn-blocking game play: "
"waiting on %s to finish turn..."),
Index: server/gamehand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.c,v
retrieving revision 1.151
diff -u -r1.151 gamehand.c
--- server/gamehand.c 15 Feb 2005 05:37:05 -0000 1.151
+++ server/gamehand.c 20 Feb 2005 05:46:49 -0000
@@ -135,7 +135,7 @@
return;
}
- (void) create_unit(pplayer, ptile, utype, FALSE, 0, -1);
+ (void) create_unit(pplayer, ptile, utype, FALSE, 0, 0);
}
}
@@ -248,14 +248,16 @@
place_starting_unit(ptile, pplayer, game.start_units[i]);
}
} players_iterate_end;
+
+ shuffle_players();
}
/**************************************************************************
...
**************************************************************************/
-void send_start_turn_to_clients(void)
+void send_start_phase_to_clients(void)
{
- lsend_packet_start_turn(game.game_connections);
+ dlsend_packet_start_phase(game.game_connections, game.phase);
}
/**************************************************************************
@@ -269,7 +271,6 @@
for(i=0; i<game.nplayers; i++) {
struct player *pplayer = &game.players[i];
- pplayer->turn_done = FALSE;
pplayer->nturns_idle++;
}
@@ -314,6 +315,9 @@
ginfo.end_year = game.end_year;
ginfo.year = game.year;
ginfo.turn = game.turn;
+ ginfo.phase = game.phase;
+ ginfo.simultaneous_phases = game.simultaneous_phases_now;
+ ginfo.num_phases = game.num_phases;
ginfo.min_players = game.min_players;
ginfo.max_players = game.max_players;
ginfo.nplayers = game.nplayers;
@@ -340,11 +344,11 @@
/* the following values are computed every
time a packet_game_info packet is created */
if (game.timeout != 0) {
- ginfo.seconds_to_turndone =
- game.turn_start + game.timeout - time(NULL);
+ ginfo.seconds_to_phasedone =
+ game.phase_start + game.timeout - time(NULL);
} else {
/* unused but at least initialized */
- ginfo.seconds_to_turndone = -1;
+ ginfo.seconds_to_phasedone = -1;
}
conn_list_iterate(dest, pconn) {
Index: server/gamehand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.h,v
retrieving revision 1.12
diff -u -r1.12 gamehand.h
--- server/gamehand.h 16 Nov 2004 18:09:47 -0000 1.12
+++ server/gamehand.h 20 Feb 2005 05:46:49 -0000
@@ -21,7 +21,7 @@
void send_year_to_clients(int year);
void send_game_info(struct conn_list *dest);
void send_game_state(struct conn_list *dest, int state);
-void send_start_turn_to_clients(void);
+void send_start_phase_to_clients(void);
int update_timeout(void);
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.358
diff -u -r1.358 plrhand.c
--- server/plrhand.c 16 Feb 2005 18:06:29 -0000 1.358
+++ server/plrhand.c 20 Feb 2005 05:46:49 -0000
@@ -1463,7 +1463,7 @@
packet->barbarian_type = plr->ai.barbarian_type;
packet->reputation=plr->reputation;
- packet->turn_done=plr->turn_done;
+ packet->phase_done=plr->phase_done;
packet->nturns_idle=plr->nturns_idle;
for (i = 0; i < B_LAST /*game.num_impr_types */ ; i++) {
@@ -1962,7 +1962,7 @@
tech_type_iterate(i) {
cplayer->research.inventions[i] = pplayer->research.inventions[i];
} tech_type_iterate_end;
- cplayer->turn_done = TRUE; /* Have other things to think about - paralysis*/
+ cplayer->phase_done = TRUE; /* Have other things to think about - paralysis*/
cplayer->embassy = 0; /* all embassies destroyed */
/* Do the ai */
@@ -2189,9 +2189,9 @@
...
(Hmm, how should "turn done" work for multi-connected non-observer players?)
**************************************************************************/
-void handle_player_turn_done(struct player *pplayer)
+void handle_player_phase_done(struct player *pplayer)
{
- pplayer->turn_done = TRUE;
+ pplayer->phase_done = TRUE;
check_for_full_turn_done();
Index: server/plrhand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.h,v
retrieving revision 1.69
diff -u -r1.69 plrhand.h
--- server/plrhand.h 29 Sep 2004 02:24:24 -0000 1.69
+++ server/plrhand.h 20 Feb 2005 05:46:50 -0000
@@ -95,6 +95,14 @@
} \
}
+#define phase_players_iterate(pplayer) \
+ shuffled_players_iterate(pplayer) { \
+ if (is_player_phase(pplayer, game.phase)) {
+
+#define phase_players_iterate_end \
+ } \
+ } shuffled_players_iterate_end
+
bool civil_war_triggered(struct player *pplayer);
void civil_war(struct player *pplayer);
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.220
diff -u -r1.220 savegame.c
--- server/savegame.c 15 Feb 2005 05:37:05 -0000 1.220
+++ server/savegame.c 20 Feb 2005 05:46:50 -0000
@@ -3125,6 +3125,12 @@
} else {
game.turn = -2;
}
+ game.simultaneous_phases_now
+ = secfile_lookup_bool_default(file, TRUE,
+ "game.simultaneous_phases_now");
+ game.simultaneous_phases_stored
+ = secfile_lookup_bool_default(file, TRUE,
+ "game.simultaneous_phases_stored");
game.min_players = secfile_lookup_int(file, "game.min_players");
game.max_players = secfile_lookup_int(file, "game.max_players");
@@ -3659,6 +3665,10 @@
secfile_insert_int(file, game.end_year, "game.end_year");
secfile_insert_int(file, game.year, "game.year");
secfile_insert_int(file, game.turn, "game.turn");
+ secfile_insert_bool(file, game.simultaneous_phases_now,
+ "game.simultaneous_phases_now");
+ secfile_lookup_bool_default(file, game.simultaneous_phases_stored,
+ "game.simultaneous_phases_stored");
secfile_insert_int(file, game.researchcost, "game.researchcost");
secfile_insert_int(file, game.min_players, "game.min_players");
secfile_insert_int(file, game.max_players, "game.max_players");
Index: server/sernet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sernet.c,v
retrieving revision 1.133
diff -u -r1.133 sernet.c
--- server/sernet.c 28 Jan 2005 19:57:09 -0000 1.133
+++ server/sernet.c 20 Feb 2005 05:46:50 -0000
@@ -377,10 +377,6 @@
if(year!=game.year) {
if (server_state == RUN_GAME_STATE) year=game.year;
}
- if (game.timeout == 0) {
- /* Just in case someone sets timeout we keep game.turn_start updated */
- game.turn_start = time(NULL);
- }
while(TRUE) {
con_prompt_on(); /* accepting new input */
@@ -504,7 +500,7 @@
if(select(max_desc+1, &readfs, &writefs, &exceptfs, &tv)==0) { /* timeout
*/
(void) send_server_info_to_metaserver(META_REFRESH);
if(game.timeout != 0
- && (time(NULL)>game.turn_start + game.timeout)
+ && (time(NULL)>game.phase_start + game.timeout)
&& (server_state == RUN_GAME_STATE)){
con_prompt_off();
return 0;
@@ -530,10 +526,6 @@
#endif /* !__VMS */
}
}
- if (game.timeout == 0) {
- /* Just in case someone sets timeout we keep game.turn_start updated */
- game.turn_start = time(NULL);
- }
if(FD_ISSET(sock, &exceptfs)) { /* handle Ctrl-Z suspend/resume */
continue;
@@ -678,7 +670,7 @@
}
con_prompt_off();
- if (game.timeout != 0 && (time(NULL) > game.turn_start + game.timeout)) {
+ if (game.timeout != 0 && (time(NULL) > game.phase_start + game.timeout)) {
return 0;
}
return 1;
Index: server/settings.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settings.c,v
retrieving revision 1.16
diff -u -r1.16 settings.c
--- server/settings.c 24 Dec 2004 16:11:54 -0000 1.16
+++ server/settings.c 20 Feb 2005 05:46:51 -0000
@@ -896,6 +896,14 @@
"\"timeoutincrease\" to have a dynamic timer."), NULL,
GAME_MIN_TIMEOUT, GAME_MAX_TIMEOUT, GAME_DEFAULT_TIMEOUT)
+ GEN_BOOL("simultaneousphases", game.simultaneous_phases_stored,
+ SSET_META, SSET_INTERNAL, SSET_SITUATIONAL, SSET_TO_CLIENT,
+ N_("Whether to have simultaneous player phases."),
+ N_("If true, all players' movement phases will occur "
+ "simultaneously; if false (default) then players will "
+ "alternate movement."), NULL,
+ GAME_DEFAULT_SIMULTANEOUSPHASES)
+
GEN_INT("nettimeout", game.tcptimeout,
SSET_META, SSET_NETWORK, SSET_RARE, SSET_TO_CLIENT,
N_("Seconds to let a client's network connection block"),
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.227
diff -u -r1.227 srv_main.c
--- server/srv_main.c 16 Feb 2005 18:06:29 -0000 1.227
+++ server/srv_main.c 20 Feb 2005 05:46:51 -0000
@@ -106,8 +106,6 @@
#include "srv_main.h"
-static void after_game_advance_year(void);
-static void before_end_year(void);
static void end_turn(void);
static void ai_start_turn(void);
static bool is_game_over(void);
@@ -329,7 +327,7 @@
**************************************************************************/
static void do_reveal_effects(void)
{
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
if (get_player_bonus(pplayer, EFT_REVEAL_CITIES) > 0) {
players_iterate(other_player) {
city_list_iterate(other_player->cities, pcity) {
@@ -343,7 +341,7 @@
* needed. */
map_know_all(pplayer);
}
- } players_iterate_end;
+ } phase_players_iterate_end;
}
/**************************************************************************
@@ -352,7 +350,7 @@
**************************************************************************/
static void do_have_embassies_effect(void)
{
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
if (get_player_bonus(pplayer, EFT_HAVE_EMBASSIES) > 0) {
players_iterate(pother) {
/* Note this gives pplayer contact with pother, but doesn't give
@@ -361,7 +359,7 @@
make_contact(pplayer, pother, NULL);
} players_iterate_end;
}
- } players_iterate_end;
+ } phase_players_iterate_end;
}
/**************************************************************************
@@ -445,26 +443,16 @@
}
/**************************************************************************
- Send packet which tells clients that the server is starting its
- "end year" calculations (and will be sending end-turn updates etc).
- (This is referred to as "before new year" in packet and client code.)
-**************************************************************************/
-static void before_end_year(void)
-{
- lsend_packet_before_new_year(game.est_connections);
-}
-
-/**************************************************************************
...
**************************************************************************/
static void ai_start_turn(void)
{
- shuffled_players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
if (pplayer->ai.control) {
ai_do_first_activities(pplayer);
flush_packets(); /* AIs can be such spammers... */
}
- } shuffled_players_iterate_end;
+ } phase_players_iterate_end;
kill_dying_players();
}
@@ -477,6 +465,17 @@
{
freelog(LOG_DEBUG, "Begin turn");
+ /* Reset this each turn. */
+ if (is_new_turn) {
+ game.simultaneous_phases_now = game.simultaneous_phases_stored;
+ }
+ if (game.simultaneous_phases_now) {
+ game.num_phases = 1;
+ } else {
+ game.num_phases = game.nplayers;
+ }
+ send_game_info(game.game_connections);
+
if (is_new_turn) {
/* We build scores at the beginning and end of every turn. We have to
* build them at the beginning so that the AI can use the data. */
@@ -496,11 +495,15 @@
}
}
- if (is_new_turn) {
+ if (is_new_turn && game.simultaneous_phases_now) {
freelog(LOG_DEBUG, "Shuffleplayers");
shuffle_players();
}
+ if (is_new_turn) {
+ game.phase = 0;
+ }
+
sanity_check();
}
@@ -514,7 +517,22 @@
conn_list_do_buffer(game.game_connections);
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
+ pplayer->phase_done = FALSE;
+ } phase_players_iterate_end;
+
+ send_start_phase_to_clients();
+
+ if (is_new_phase) {
+ /* Unit "end of turn" activities - of course these actually go at
+ * the start of the turn! */
+ phase_players_iterate(pplayer) {
+ update_unit_activities(pplayer); /* major network traffic */
+ flush_packets();
+ } phase_players_iterate_end;
+ }
+
+ phase_players_iterate(pplayer) {
freelog(LOG_DEBUG, "beginning player turn for #%d (%s)",
pplayer->player_no, pplayer->name);
/* human players also need this for building advice */
@@ -522,34 +540,35 @@
if (!pplayer->ai.control) {
ai_manage_buildings(pplayer); /* building advisor */
}
- } players_iterate_end;
+ } phase_players_iterate_end;
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
send_player_cities(pplayer);
- } players_iterate_end;
+ } phase_players_iterate_end;
flush_packets(); /* to curb major city spam */
conn_list_do_unbuffer(game.game_connections);
- shuffled_players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
update_revolution(pplayer);
- } shuffled_players_iterate_end;
+ } phase_players_iterate_end;
if (is_new_phase) {
/* Try to avoid hiding events under a diplomacy dialog */
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
if (pplayer->ai.control && !is_barbarian(pplayer)) {
ai_diplomacy_actions(pplayer);
}
- } players_iterate_end;
+ } phase_players_iterate_end;
freelog(LOG_DEBUG, "Aistartturn");
ai_start_turn();
}
- send_start_turn_to_clients();
-
sanity_check();
+
+ game.phase_start = time(NULL);
+ send_game_info(NULL);
}
/**************************************************************************
@@ -566,20 +585,23 @@
* following parts get wiped out before the user gets a chance to
* see them. --dwp
*/
- before_end_year();
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
+ lsend_packet_end_phase(pplayer->connections);
+ } phase_players_iterate_end;
+
+ phase_players_iterate(pplayer) {
if (pplayer->research.researching == A_UNSET) {
choose_random_tech(pplayer);
update_tech(pplayer, 0);
}
- } players_iterate_end;
+ } phase_players_iterate_end;
/* Freeze sending of cities. */
nocity_send = TRUE;
/* AI end of turn activities */
auto_settlers_init();
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
if (pplayer->ai.control) {
ai_settler_init(pplayer);
}
@@ -587,24 +609,24 @@
if (pplayer->ai.control) {
ai_do_last_activities(pplayer);
}
- } players_iterate_end;
+ } phase_players_iterate_end;
/* Refresh cities */
- shuffled_players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
do_tech_parasite_effect(pplayer);
player_restore_units(pplayer);
update_city_activities(pplayer);
pplayer->research.changed_from=-1;
flush_packets();
- } shuffled_players_iterate_end;
+ } phase_players_iterate_end;
kill_dying_players();
/* Unfreeze sending of cities. */
nocity_send = FALSE;
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
send_player_cities(pplayer);
- } players_iterate_end;
+ } phase_players_iterate_end;
flush_packets(); /* to curb major city spam */
do_reveal_effects();
@@ -646,12 +668,8 @@
stdinhand_turn();
send_player_turn_notifications(NULL);
- freelog(LOG_DEBUG, "Turn ended.");
- game.turn_start = time(NULL);
-
freelog(LOG_DEBUG, "Gamenextyear");
game_advance_year();
- after_game_advance_year();
freelog(LOG_DEBUG, "Updatetimeout");
update_timeout();
@@ -669,19 +687,6 @@
}
/**************************************************************************
- After game advance year stuff.
-**************************************************************************/
-static void after_game_advance_year(void)
-{
- /* Unit end of turn activities */
- shuffled_players_iterate(pplayer) {
- update_unit_activities(pplayer); /* major network traffic */
- flush_packets();
- pplayer->turn_done = FALSE;
- } shuffled_players_iterate_end;
-}
-
-/**************************************************************************
Unconditionally save the game, with specified filename.
Always prints a message: either save ok, or failed.
@@ -1014,16 +1019,16 @@
if (game.fixedlength && game.timeout != 0)
return;
- players_iterate(pplayer) {
+ phase_players_iterate(pplayer) {
if (game.turnblock) {
- if (!pplayer->ai.control && pplayer->is_alive && !pplayer->turn_done)
+ if (!pplayer->ai.control && pplayer->is_alive && !pplayer->phase_done)
return;
} else {
- if(pplayer->is_connected && pplayer->is_alive && !pplayer->turn_done) {
+ if(pplayer->is_connected && pplayer->is_alive && !pplayer->phase_done) {
return;
}
}
- } players_iterate_end;
+ } phase_players_iterate_end;
force_end_of_sniff = TRUE;
}
@@ -1528,55 +1533,63 @@
* loading a game we don't want to do these actions (like AI unit
* movement and AI diplomacy). */
begin_turn(is_new_turn);
- begin_phase(is_new_turn);
- is_new_turn = TRUE;
- force_end_of_sniff = FALSE;
+ for (; game.phase < game.num_phases; game.phase++) {
+ freelog(LOG_DEBUG, "Starting phase %d/%d.", game.phase,
+ game.num_phases);
+ begin_phase(is_new_turn);
+ is_new_turn = TRUE;
- /*
- * This will thaw the reports and agents at the client.
- */
- lsend_packet_thaw_hint(game.game_connections);
-
- /* Before sniff (human player activites), report time to now: */
- freelog(LOG_VERBOSE, "End/start-turn server/ai activities: %g seconds",
- read_timer_seconds(eot_timer));
-
- /* Do auto-saves just before starting sniff_packets(), so that
- * autosave happens effectively "at the same time" as manual
- * saves, from the point of view of restarting and AI players.
- * Post-increment so we don't count the first loop.
- */
- if(save_counter >= game.save_nturns && game.save_nturns>0) {
- save_counter=0;
- save_game_auto();
- }
- save_counter++;
-
- freelog(LOG_DEBUG, "sniffingpackets");
- while (sniff_packets() == 1) {
- /* nothing */
- }
+ force_end_of_sniff = FALSE;
- /* After sniff, re-zero the timer: (read-out above on next loop) */
- clear_timer_start(eot_timer);
-
- conn_list_do_buffer(game.game_connections);
+ /*
+ * This will thaw the reports and agents at the client.
+ */
+ lsend_packet_thaw_hint(game.game_connections);
+
+ /* Before sniff (human player activites), report time to now: */
+ freelog(LOG_VERBOSE, "End/start-turn server/ai activities: %g seconds",
+ read_timer_seconds(eot_timer));
+
+ /* Do auto-saves just before starting sniff_packets(), so that
+ * autosave happens effectively "at the same time" as manual
+ * saves, from the point of view of restarting and AI players.
+ * Post-increment so we don't count the first loop.
+ */
+ if (game.phase == 0) {
+ if (save_counter >= game.save_nturns && game.save_nturns>0) {
+ save_counter=0;
+ save_game_auto();
+ }
+ save_counter++;
+ }
+
+ freelog(LOG_DEBUG, "sniffingpackets");
+ check_for_full_turn_done(); /* HACK: don't wait during AI phases */
+ while (sniff_packets() == 1) {
+ /* nothing */
+ }
- sanity_check();
+ /* After sniff, re-zero the timer: (read-out above on next loop) */
+ clear_timer_start(eot_timer);
- /*
- * This will freeze the reports and agents at the client.
- */
- lsend_packet_freeze_hint(game.game_connections);
+ conn_list_do_buffer(game.game_connections);
- end_phase();
+ sanity_check();
+
+ /*
+ * This will freeze the reports and agents at the client.
+ */
+ lsend_packet_freeze_hint(game.game_connections);
+
+ end_phase();
+
+ conn_list_do_unbuffer(game.game_connections);
+ }
end_turn();
freelog(LOG_DEBUG, "Sendinfotometaserver");
(void) send_server_info_to_metaserver(META_REFRESH);
- conn_list_do_unbuffer(game.game_connections);
-
if (is_game_over()) {
server_state=GAME_OVER_STATE;
}
@@ -1866,10 +1879,6 @@
ai_data_init(pplayer); /* Initialize this at last moment */
} players_iterate_end;
}
-
- /* We want to reset the timer as late as possible but before the info is
- * sent to the clients */
- game.turn_start = time(NULL);
lsend_packet_freeze_hint(game.game_connections);
send_all_info(game.game_connections);
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.385
diff -u -r1.385 stdinhand.c
--- server/stdinhand.c 14 Feb 2005 22:52:41 -0000 1.385
+++ server/stdinhand.c 20 Feb 2005 05:46:52 -0000
@@ -2689,7 +2689,7 @@
pplayer->is_connected = FALSE;
pplayer->is_observer = TRUE;
pplayer->capital = TRUE;
- pplayer->turn_done = TRUE;
+ pplayer->phase_done = TRUE;
pplayer->embassy = 0; /* no embassys */
pplayer->is_alive = FALSE;
pplayer->was_created = FALSE;
@@ -2780,7 +2780,7 @@
send_player_info(NULL, NULL);
send_diplomatic_meetings(pconn);
send_packet_thaw_hint(pconn);
- send_packet_start_turn(pconn);
+ dsend_packet_start_phase(pconn, game.phase);
}
cmd_reply(CMD_OBSERVE, caller, C_OK, _("%s now observes %s"),
@@ -2946,7 +2946,7 @@
send_player_info(NULL, NULL);
send_diplomatic_meetings(pconn);
send_packet_thaw_hint(pconn);
- send_packet_start_turn(pconn);
+ dsend_packet_start_phase(pconn, game.phase);
gamelog(GAMELOG_PLAYER, pplayer);
}
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.322
diff -u -r1.322 unithand.c
--- server/unithand.c 16 Feb 2005 18:28:00 -0000 1.322
+++ server/unithand.c 20 Feb 2005 05:46:52 -0000
@@ -560,7 +560,8 @@
return;
}
- if (!is_tiles_adjacent(punit->tile, ptile)) {
+ if (!is_tiles_adjacent(punit->tile, ptile)
+ || !is_player_phase(unit_owner(punit), game.phase)) {
return;
}
(void) handle_unit_move_request(punit, ptile, FALSE, FALSE);
@@ -1672,7 +1673,8 @@
}
#endif
- if (execute_orders(punit)) {
+ if (!is_player_phase(unit_owner(punit), game.phase)
+ || execute_orders(punit)) {
/* Looks like the unit survived. */
send_unit_info(NULL, punit);
}
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.321
diff -u -r1.321 unittools.c
--- server/unittools.c 15 Feb 2005 17:41:40 -0000 1.321
+++ server/unittools.c 20 Feb 2005 05:46:53 -0000
@@ -426,6 +426,12 @@
wipe_unit(punit);
}
} unit_list_iterate_safe_end;
+
+ /* Send all updates. */
+ unit_list_iterate(pplayer->units, punit) {
+ punit->moves_left = 0;
+ send_unit_info(NULL, punit);
+ } unit_list_iterate_end;
}
/****************************************************************************
|
|