Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2004:
[Freeciv-Dev] Re: (PR#8749) Scenario fixes
Home

[Freeciv-Dev] Re: (PR#8749) Scenario fixes

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: per@xxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#8749) Scenario fixes
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 15 May 2004 21:15:38 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8749 >

Jason Short wrote:
> <URL: http://rt.freeciv.org/Ticket/Display.html?id=8749 >
> 
> Here's a new patch.
> 
> Changes:
> 
> - Save the nations in savegames.
> - Rename the nation savegame tag (to match what Per has).

Here's a new patch.

Changes:

- Fixed a hideous bug that caused everything to break.

It now works as expected.

In a scenario, if you raise maxplayers and set aifill to be too high, 
the extra players will be cut.  I don't know what would happen to them 
if they were human.

jason

Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.182
diff -u -r1.182 map.h
--- common/map.h        5 May 2004 21:58:11 -0000       1.182
+++ common/map.h        16 May 2004 04:13:44 -0000
@@ -140,7 +140,10 @@
   struct tile *tiles;
 
   /* Only used by server. */
-  struct map_position *start_positions;        /* allocated at runtime */
+  struct start_position {
+    int x, y;
+    Nation_Type_id nation; /* May be NO_NATION_SELECTED. */
+  } *start_positions;  /* allocated at runtime */
 };
 
 enum topo_flag {
Index: common/nation.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/nation.c,v
retrieving revision 1.37
diff -u -r1.37 nation.c
--- common/nation.c     15 Sep 2003 16:51:07 -0000      1.37
+++ common/nation.c     16 May 2004 04:13:44 -0000
@@ -68,7 +68,7 @@
      if(mystrcasecmp(name, get_nation_name (i)) == 0)
        return i;
 
-  return -1;
+  return NO_NATION_SELECTED;
 }
 
 /***************************************************************
Index: server/gamehand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.c,v
retrieving revision 1.132
diff -u -r1.132 gamehand.c
--- server/gamehand.c   14 May 2004 11:04:22 -0000      1.132
+++ server/gamehand.c   16 May 2004 04:13:45 -0000
@@ -91,107 +91,64 @@
 }
 
 /****************************************************************************
-  Swap two map positions.
-****************************************************************************/
-static void swap_map_positions(struct map_position *a,
-                              struct map_position *b)
-{
-  struct map_position tmp;
-
-  tmp = *a;
-  *a = *b;
-  *b = tmp;
-}
-
-/****************************************************************************
-  Get the start position for the given player.
-****************************************************************************/
-static struct map_position get_start_position(struct player *pplayer,
-                                             int *start_pos)
-{
-  if (map.fixed_start_positions) {
-    return map.start_positions[start_pos[pplayer->player_no]];
-  } else {
-    return map.start_positions[pplayer->player_no];
-  }
-}
-
-/****************************************************************************
   Initialize a new game: place the players' units onto the map, etc.
 ****************************************************************************/
 void init_new_game(void)
 {
-  Nation_Type_id start_pos[MAX_NUM_PLAYERS];
+#define NO_START_POS -1
+  int start_pos[game.nplayers];
+  bool pos_used[map.num_start_positions];
+  int i, num_used = 0;
+
   init_game_id();
 
   /* Shuffle starting positions around so that they match up with the
    * desired players. */
-  if (!map.fixed_start_positions) {
-    /* With non-fixed starting positions, just randomize the order.  This
-     * avoids giving an advantage to lower-numbered players. */
-    assert(game.nplayers == map.num_start_positions);
-    players_iterate(pplayer) {
-      swap_map_positions(&map.start_positions[pplayer->player_no],
-                        &map.start_positions[myrand(game.nplayers)]);
-    } players_iterate_end;
-  } else {
-    /* In a scenario, choose starting positions by nation.  If there are too
-     * few starts for number of nations, assign to nations with specific
-     * starts first, then assign the rest to random from remainder.  (It
-     * would be better to label start positions by nation etc, but this will
-     * do for now.)
-     *
-     * NOTE: map.num_start_positions may be very high.
-     *
-     * FIXME: this method is broken since it assumes nations have a constant
-     * id, which is generally not true. */
-    const int npos = map.num_start_positions;
-    int nrem = npos, player_no;
-    bool *pos_used = fc_calloc(map.num_start_positions, sizeof(*pos_used));
-
-    /* Match nation 0 to starting position 0, and so on.  This needs an
-     * explicit for loop to guarantee the proper ordering. */
-    assert(game.nplayers <= map.num_start_positions);
-    for (player_no = 0; player_no < game.nplayers; player_no++) {
-      Nation_Type_id nation = game.players[player_no].nation;
-
-      if (nation < npos) {
-       start_pos[player_no] = nation;
-       pos_used[nation] = TRUE;
-       nrem--;
-      } else {
-       start_pos[player_no] = NO_NATION_SELECTED;
+
+  /* First set up some data fields. */
+  for (i = 0; i < map.num_start_positions; i++) {
+    pos_used[i] = FALSE;
+  }
+  players_iterate(pplayer) {
+    start_pos[pplayer->player_no] = NO_START_POS;
+  } players_iterate_end;
+
+  /* Second, assign a nation to a start position for that nation. */
+  players_iterate(pplayer) {
+    for (i = 0; i < map.num_start_positions; i++) {
+      assert(pplayer->nation != NO_NATION_SELECTED);
+      if (pplayer->nation == map.start_positions[i].nation) {
+       start_pos[pplayer->player_no] = i;
+       pos_used[i] = TRUE;
+       num_used++;
       }
     }
+  } players_iterate_end;
 
-    /* Now randomize the unchosen nations. */
-    players_iterate(pplayer) {
-      if (start_pos[pplayer->player_no] == NO_NATION_SELECTED) {
-       int j, k;
-
-       assert(nrem > 0);
-       k = myrand(nrem);
-       for (j = 0; j < npos; j++) {
-         if (!pos_used[j] && (0 == k--)) {
-           start_pos[pplayer->player_no] = j;
-           pos_used[j] = TRUE;
-           nrem--;
+  /* Third, assign players randomly to the remaining start positions. */
+  players_iterate(pplayer) {
+    if (start_pos[pplayer->player_no] == NO_START_POS) {
+      int which = myrand(map.num_start_positions - num_used);
+
+      for (i = 0; i < map.num_start_positions; i++) {
+       if (!pos_used[i]) {
+         if (which == 0) {
+           start_pos[pplayer->player_no] = i;
+           pos_used[i] = TRUE;
+           num_used++;
            break;
          }
+         which--;
        }
-       assert(start_pos[pplayer->player_no] != NO_NATION_SELECTED);
       }
-    } players_iterate_end;
-
-    /* The starting positions are now stored in the start_pos array, and
-     * may be accessed via the get_start_position function. */
-
-    free(pos_used);
-  }
+    }
+    assert(start_pos[pplayer->player_no] != NO_START_POS);
+  } players_iterate_end;
 
   /* Loop over all players, creating their initial units... */
   players_iterate(pplayer) {
-    struct map_position pos = get_start_position(pplayer, start_pos);
+    struct start_position pos
+      = map.start_positions[start_pos[pplayer->player_no]];
 
     /* Place the first unit. */
     assert(game.settlers > 0);
@@ -201,7 +158,8 @@
   /* Place all other units. */
   players_iterate(pplayer) {
     int i, x, y;
-    struct map_position p = get_start_position(pplayer, start_pos);
+    struct start_position p
+      = map.start_positions[start_pos[pplayer->player_no]];
 
     for (i = 1; i < (game.settlers + game.explorer); i++) {
       do {
Index: server/mapgen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/mapgen.c,v
retrieving revision 1.132
diff -u -r1.132 mapgen.c
--- server/mapgen.c     20 Apr 2004 20:10:38 -0000      1.132
+++ server/mapgen.c     16 May 2004 04:13:45 -0000
@@ -1252,6 +1252,7 @@
       islands[(int)map_get_continent(x, y)].starters--;
       map.start_positions[data.count].x = x;
       map.start_positions[data.count].y = y;
+      map.start_positions[data.count].nation = NO_NATION_SELECTED;
       freelog(LOG_DEBUG, "Adding %d,%d as starting position %d.",
              x, y, data.count);
       data.count++;
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.150
diff -u -r1.150 savegame.c
--- server/savegame.c   15 May 2004 22:41:37 -0000      1.150
+++ server/savegame.c   16 May 2004 04:13:46 -0000
@@ -302,8 +302,23 @@
   while (i < game.max_players
         && (pos = secfile_lookup_int_default(file, -1,
                                              "map.r%dsx", i)) != -1) {
+    char *nation = secfile_lookup_str_default(file, NULL, "map.r%dsnation",
+                                             i);
+
     map.start_positions[i].x = pos;
     map.start_positions[i].y = secfile_lookup_int(file, "map.r%dsy", i);
+
+    if (nation) {
+      /* This will fall back to NO_NATION_SELECTED if the string doesn't
+       * match any nation. */
+      map.start_positions[i].nation = find_nation_by_name(nation);
+    } else {
+      /* Old-style nation ordering is useless to us because the nations
+       * have been reordered.  Just ignore it and order the nations
+       * randomly. */
+      map.start_positions[i].nation = NO_NATION_SELECTED;
+    }
+
     i++;
   }
 
@@ -466,6 +481,12 @@
     for (i=0; i<map.num_start_positions; i++) {
       secfile_insert_int(file, map.start_positions[i].x, "map.r%dsx", i);
       secfile_insert_int(file, map.start_positions[i].y, "map.r%dsy", i);
+
+      if (map.start_positions[i].nation != NO_NATION_SELECTED) {
+       const char *nation = get_nation_name(map.start_positions[i].nation);
+
+       secfile_insert_str(file, nation, "map.r%dsnation", i);
+      }
     }
   }
     

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