Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2005:
[Freeciv-Dev] (PR#576) Wishlist: alternating unit movement
Home

[Freeciv-Dev] (PR#576) Wishlist: alternating unit movement

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: tomg@xxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#576) Wishlist: alternating unit movement
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 19 Feb 2005 21:50:29 -0800
Reply-to: bugs@xxxxxxxxxxx

<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;
 }
 
 /****************************************************************************

[Prev in Thread] Current Thread [Next in Thread]