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, 12 Feb 2005 22:38:27 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=576 >

Here is a new alternating-moves patch.  It actually works, and is not
too complicated.  It's lacking a bit in the GUI interface department
however.  The panel needs to show whose turn it is, at a minimum.

It also needs lots of testing.  I just played a few turns with two
clients to try it out.  Since alternating movement applies to AI players
too playing single-player will help find some bugs, but not all.  I
haven't tested it with saving and reloading or with a timeout.

-jason

Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.213
diff -u -r1.213 civclient.c
--- client/civclient.c  12 Feb 2005 18:47:18 -0000      1.213
+++ client/civclient.c  13 Feb 2005 06:29:51 -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.45
diff -u -r1.45 mapctrl_common.c
--- client/mapctrl_common.c     5 Feb 2005 07:41:53 -0000       1.45
+++ client/mapctrl_common.c     13 Feb 2005 06:29:51 -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.469
diff -u -r1.469 packhand.c
--- client/packhand.c   12 Feb 2005 18:47:18 -0000      1.469
+++ client/packhand.c   13 Feb 2005 06:29:52 -0000
@@ -788,7 +788,7 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void handle_before_new_year(void)
+void handle_end_phase(void)
 {
   clear_notify_window();
   /*
@@ -806,16 +806,20 @@
 /**************************************************************************
 ...
 **************************************************************************/
-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 (game.simultaneous_phases || game.phase == game.player_idx) {
+    agents_start_turn();
+    non_ai_unit_focus = FALSE;
+
+    turn_done_sent = FALSE;
+    update_turn_done_button_state();
 
-  if(game.player_ptr->ai.control && !ai_manual_turn_done) {
-    user_ended_turn();
+    if(game.player_ptr->ai.control && !ai_manual_turn_done) {
+      user_ended_turn();
+    }
   }
 }
 
@@ -1362,8 +1366,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 */
@@ -1509,10 +1513,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      13 Feb 2005 06:29:52 -0000
@@ -181,7 +181,7 @@
 {
   if (plr->is_alive) {
     if (plr->is_connected) {
-      if (plr->turn_done) {
+      if (plr->phase_done) {
        return _("done");
       } else {
        return _("moving");
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.171
diff -u -r1.171 game.h
--- common/game.h       29 Jan 2005 17:58:18 -0000      1.171
+++ common/game.h       13 Feb 2005 06:29:52 -0000
@@ -75,10 +75,12 @@
   time_t last_ping;
   int pingtimeout;
   int pingtime;
-  time_t turn_start;
+  time_t phase_start;
   int end_year;
   int year;
   int turn;
+  bool simultaneous_phases;
+  int phase, num_phases;
   int researchcost; /* Multiplier on cost of new research */
   int diplcost, freecost, conquercost;
   int diplchance;
@@ -437,6 +439,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.93
diff -u -r1.93 packets.def
--- common/packets.def  5 Feb 2005 07:15:37 -0000       1.93
+++ common/packets.def  13 Feb 2005 06:29:52 -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,9 +339,10 @@
   UINT8 researchcost;
   UINT32 skill_level;
 
-  UINT32 seconds_to_turndone;
+  UINT32 seconds_to_phasedone;
   UINT32 timeout;
   TURN turn;
+  PHASE phase;
   YEAR year, end_year;
 
   PLAYER min_players, max_players, nplayers, player_idx;
@@ -550,7 +552,7 @@
   UINT8 city_style;
   NATION nation;
   TEAM team;
-  BOOL turn_done;
+  BOOL phase_done;
   TURN nturns_idle;
   BOOL is_alive;
 
@@ -578,7 +580,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
@@ -875,10 +877,11 @@
 
 /************** New turn packets **********************/
 
-PACKET_BEFORE_NEW_YEAR=90;sc,lsend
+PACKET_END_PHASE=90;sc,lsend
 end
 
-PACKET_START_TURN=91;sc,lsend
+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.138
diff -u -r1.138 player.h
--- common/player.h     22 Jan 2005 19:45:43 -0000      1.138
+++ common/player.h     13 Feb 2005 06:29:52 -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  13 Feb 2005 06:29:53 -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.295
diff -u -r1.295 cityturn.c
--- server/cityturn.c   9 Feb 2005 04:01:40 -0000       1.295
+++ server/cityturn.c   13 Feb 2005 06:29:53 -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.38
diff -u -r1.38 connecthand.c
--- server/connecthand.c        22 Jan 2005 19:45:44 -0000      1.38
+++ server/connecthand.c        13 Feb 2005 06:29:53 -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.150
diff -u -r1.150 gamehand.c
--- server/gamehand.c   5 Feb 2005 07:15:38 -0000       1.150
+++ server/gamehand.c   13 Feb 2005 06:29:54 -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++;
   }
 
@@ -338,11 +339,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   13 Feb 2005 06:29:54 -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.356
diff -u -r1.356 plrhand.c
--- server/plrhand.c    2 Feb 2005 02:44:32 -0000       1.356
+++ server/plrhand.c    13 Feb 2005 06:29:54 -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 */
@@ -2185,12 +2185,20 @@
 }
 
 /**************************************************************************
+  Return TRUE if it is this player's phase.
+**************************************************************************/
+bool is_player_phase(const struct player *pplayer)
+{
+  return game.simultaneous_phases || pplayer->player_no == game.phase;
+}
+
+/**************************************************************************
 ...
 (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    13 Feb 2005 06:29:54 -0000
@@ -78,6 +78,7 @@
 void do_free_cost(struct player *pplayer);
 void do_conquer_cost(struct player *pplayer);
 
+bool is_player_phase(const struct player *pplayer);
 void shuffle_players(void);
 void set_shuffled_players(int *shuffled_players);
 struct player *shuffled_player(int i);
@@ -95,6 +96,14 @@
   }                                                                         \
 }
 
+#define phase_players_iterate(pplayer) \
+  shuffled_players_iterate(pplayer) { \
+    if (game.simultaneous_phases || game.phase == pplayer->player_no) {
+
+#define phase_players_iterate_end              \
+    }                                          \
+  } shuffled_players_iterate_end
+
 bool civil_war_triggered(struct player *pplayer);
 void civil_war(struct player *pplayer);
 
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     13 Feb 2005 06:29:54 -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   13 Feb 2005 06:29:54 -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,
+          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.222
diff -u -r1.222 srv_main.c
--- server/srv_main.c   13 Feb 2005 03:01:50 -0000      1.222
+++ server/srv_main.c   13 Feb 2005 06:29:55 -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();
 }
 
@@ -496,11 +484,15 @@
     }
   }
 
-  if (is_new_turn) {
+  if (is_new_turn && game.simultaneous_phases) {
     freelog(LOG_DEBUG, "Shuffleplayers");
     shuffle_players();
   }
 
+  if (is_new_turn) {
+    game.phase = 0;
+  }
+
   sanity_check();
 }
 
@@ -514,17 +506,30 @@
 
   conn_list_do_buffer(game.game_connections);
 
-  players_iterate(pplayer) {
+  phase_players_iterate(pplayer) {
+    pplayer->phase_done = FALSE;
+  } phase_players_iterate_end;
+
+  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 */
     ai_data_phase_init(pplayer, is_new_phase);
     ai_manage_buildings(pplayer);
-  } 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);
@@ -535,19 +540,22 @@
 
   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();
+  send_start_phase_to_clients();
 
   sanity_check();
+
+  game.phase_start = time(NULL);
+  send_game_info(NULL);
 }
 
 /**************************************************************************
@@ -564,20 +572,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);
     }
@@ -585,24 +596,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();
@@ -644,12 +655,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();
@@ -667,19 +674,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.
 
@@ -1012,16 +1006,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;
 }
@@ -1527,55 +1521,70 @@
      * 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;
 
-    /* 
-     * 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 */
+    /* Reset this each turn (FIXME: what if the game is saved in the middle
+     * of the turn after it's been changed?) */
+    if (game.simultaneous_phases) {
+      game.num_phases = 1;
+    } else {
+      game.num_phases = game.nplayers;
     }
 
-    /* After sniff, re-zero the timer: (read-out above on next loop) */
-    clear_timer_start(eot_timer);
-    
-    conn_list_do_buffer(game.game_connections);
+    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;
 
-    sanity_check();
+      force_end_of_sniff = FALSE;
 
-    /* 
-     * This will freeze the reports and agents at the client.
-     */
-    lsend_packet_freeze_hint(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");
+      while (sniff_packets() == 1) {
+       /* nothing */
+      }
+
+      /* After sniff, re-zero the timer: (read-out above on next loop) */
+      clear_timer_start(eot_timer);
+
+      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;
     }
@@ -1865,10 +1874,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.384
diff -u -r1.384 stdinhand.c
--- server/stdinhand.c  9 Feb 2005 09:10:55 -0000       1.384
+++ server/stdinhand.c  13 Feb 2005 06:29:56 -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.319
diff -u -r1.319 unithand.c
--- server/unithand.c   5 Feb 2005 07:41:54 -0000       1.319
+++ server/unithand.c   13 Feb 2005 06:29:56 -0000
@@ -561,7 +561,8 @@
     return;
   }
 
-  if (!is_tiles_adjacent(punit->tile, ptile)) {
+  if (!is_tiles_adjacent(punit->tile, ptile)
+      || !is_player_phase(unit_owner(punit))) {
     return;
   }
   (void) handle_unit_move_request(punit, ptile, FALSE, FALSE);
@@ -1687,7 +1688,7 @@
   }
 #endif
 
-  if (execute_orders(punit)) {
+  if (!is_player_phase(unit_owner(punit)) || execute_orders(punit)) {
     /* Looks like the unit survived. */
     send_unit_info(NULL, punit);
   }

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