Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2006:
[Freeciv-Dev] Re: (PR#19132) [Bug] Startunits in non-native terrains
Home

[Freeciv-Dev] Re: (PR#19132) [Bug] Startunits in non-native terrains

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#19132) [Bug] Startunits in non-native terrains
From: "Marko Lindqvist" <cazfi74@xxxxxxxxx>
Date: Wed, 16 Aug 2006 13:05:58 -0700
Reply-to: bugs@xxxxxxxxxxx

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

Marko Lindqvist wrote:
> 
>   Basically any land tile can be starting place. Startunits are placed 
> to that tile even if it's non-native to them. Placing units to 
> non-native terrain causes sanitycheck assert.

  Patch


  - ML


diff -Nurd -X.diff_ignore freeciv/server/gamehand.c freeciv/server/gamehand.c
--- freeciv/server/gamehand.c   2006-08-16 22:09:19.390500000 +0300
+++ freeciv/server/gamehand.c   2006-08-16 22:49:56.984250000 +0300
@@ -59,29 +59,16 @@
 }
 
 /****************************************************************************
-  Place a starting unit for the player.
+  Place a starting unit for the player. Returns tile where unit was really
+  placed.
 ****************************************************************************/
-static void place_starting_unit(struct tile *ptile, struct player *pplayer,
-                               char crole)
+static struct tile *place_starting_unit(struct tile *starttile,
+                                        struct player *pplayer,
+                                        char crole)
 {
-  struct unit_type *utype;
+  struct unit_type *utype = NULL;
   enum unit_flag_id role;
-
-  assert(!is_non_allied_unit_tile(ptile, pplayer));
-
-  /* For scenarios or dispersion, huts may coincide with player starts (in 
-   * other cases, huts are avoided as start positions).  Remove any such hut,
-   * and make sure to tell the client, since we may have already sent this
-   * tile (with the hut) earlier: */
-  if (tile_has_special(ptile, S_HUT)) {
-    tile_clear_special(ptile, S_HUT);
-    update_tile_knowledge(ptile);
-    freelog(LOG_VERBOSE, "Removed hut on start position for %s",
-           pplayer->name);
-  }
-
-  /* Expose visible area. */
-  map_show_circle(pplayer, ptile, game.info.init_vis_radius_sq);
+  struct tile *ptile = NULL;
 
   switch(crole) {
   case 'c':
@@ -116,7 +103,7 @@
     break;
   default: 
     assert(FALSE);
-    return;
+    return NULL;
   }
 
   /* Create the unit of an appropriate type, if it exists */
@@ -125,7 +112,40 @@
     if (utype == NULL) {
       utype = get_role_unit(role, 0);
     }
+  }
+
+  if (utype != NULL) {
+    iterate_outward(starttile, map.xsize + map.ysize, itertile) {
+      if (!is_non_allied_unit_tile(itertile, pplayer)
+          && is_native_tile(utype, itertile)) {
+        ptile = itertile;
+        break;
+      }
+    } iterate_outward_end;
+  }
+
+  if (ptile == NULL) {
+    /* No place where unit may exist. */
+    return NULL;
+  }
+
+  assert(!is_non_allied_unit_tile(ptile, pplayer));
+
+  /* For scenarios or dispersion, huts may coincide with player starts (in 
+   * other cases, huts are avoided as start positions).  Remove any such hut,
+   * and make sure to tell the client, since we may have already sent this
+   * tile (with the hut) earlier: */
+  if (tile_has_special(ptile, S_HUT)) {
+    tile_clear_special(ptile, S_HUT);
+    update_tile_knowledge(ptile);
+    freelog(LOG_VERBOSE, "Removed hut on start position for %s",
+           pplayer->name);
+  }
+
+  /* Expose visible area. */
+  map_show_circle(pplayer, ptile, game.info.init_vis_radius_sq);
 
+  if (utype != NULL) {
     /* We cannot currently handle sea units as start units.
      * TODO: remove this code block when we can. */
     if (get_unit_move_type(utype) == SEA_MOVING) {
@@ -134,11 +154,14 @@
       notify_player(pplayer, NULL, E_BAD_COMMAND,
                    _("Sea moving start units are not yet supported. "
                      "Nobody gets %s."), utype->name);
-      return;
+      return NULL;
     }
 
     (void) create_unit(pplayer, ptile, utype, FALSE, 0, 0);
+    return ptile;
   }
+
+  return NULL;
 }
 
 /****************************************************************************
@@ -170,6 +193,7 @@
 {
   const int NO_START_POS = -1;
   int start_pos[game.info.nplayers];
+  int placed_units[game.info.nplayers];
   bool pos_used[map.num_start_positions];
   int i, num_used = 0;
 
@@ -239,7 +263,12 @@
       = map.start_positions[start_pos[pplayer->player_no]];
 
     /* Place the first unit. */
-    place_starting_unit(pos.tile, pplayer, game.info.start_units[0]);
+    if (place_starting_unit(pos.tile, pplayer,
+                            game.info.start_units[0]) != NULL) {
+      placed_units[pplayer->player_no] = 1;
+    } else {
+      placed_units[pplayer->player_no] = 0;
+    }
   } players_iterate_end;
 
   /* Place all other units. */
@@ -255,7 +284,10 @@
       ptile = find_dispersed_position(pplayer, &p);
 
       /* Create the unit of an appropriate type. */
-      place_starting_unit(ptile, pplayer, game.info.start_units[i]);
+      if (place_starting_unit(ptile, pplayer,
+                              game.info.start_units[i]) != NULL) {
+        placed_units[pplayer->player_no]++;
+      }
     }
 
     /* Place nation specific start units (not role based!) */
@@ -263,10 +295,18 @@
     while (nation->init_units[i] != NULL && i < MAX_NUM_UNIT_LIST) {
       ptile = find_dispersed_position(pplayer, &p);
       create_unit(pplayer, ptile, nation->init_units[i], FALSE, 0, 0);
+      placed_units[pplayer->player_no]++;
       i++;
     }
   } players_iterate_end;
 
+  players_iterate(pplayer) {
+    if (placed_units[pplayer->player_no] == 0) {
+      /* No units at all for some player! */
+      die(_("No units placed for %s!"), pplayer->name);
+    }
+  } players_iterate_end;
+
   shuffle_players();
 }
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Re: (PR#19132) [Bug] Startunits in non-native terrains, Marko Lindqvist <=