Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#12667) A few modpack fixes
Home

[Freeciv-Dev] (PR#12667) A few modpack fixes

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12667) A few modpack fixes
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Sat, 26 Mar 2005 13:21:48 -0800
Reply-to: bugs@xxxxxxxxxxx

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

CHANGES:
 - Correctly handle rulesets with no F_HELP_WONDER units
 - Generate actually helpful error messages from gen req code
 - Do no try to unleash barbarians if there are no barbarian units in the
   ruleset
 - Allow rulesets with no barbarians or hut units
 - Moved some freeciv-specific defines from shared.h to fc_types.h
 - Add init_units="" list to nation rulesets where you add specific units
   this nation should start the game with

I would also like to say that writing rulesets became quite a bit more
daunting with effects.ruleset, although the game mechanics it allows are
quite neat.

  - Per

Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.206
diff -u -r1.206 aicity.c
--- ai/aicity.c 24 Mar 2005 16:41:40 -0000      1.206
+++ ai/aicity.c 26 Mar 2005 21:19:14 -0000
@@ -628,12 +628,13 @@
     pcity->ai.downtown = 0;
   } city_list_iterate_end;
 
+  if (num_role_units(F_HELP_WONDER) == 0) {
+    return; /* ruleset has no help wonder unit */
+  }
+
   unittype = best_role_unit_for_player(pplayer, F_HELP_WONDER);
   if (unittype == U_LAST) {
     unittype = get_role_unit(F_HELP_WONDER, 0); /* simulate future unit */
-    if (unittype == U_LAST) {
-      return; /* ruleset has no help wonder unit */
-    }
   }
   ghost = create_unit_virtual(pplayer, NULL, unittype, 0);
   range = unit_move_rate(ghost) * 4;
@@ -752,7 +753,7 @@
     int best_candidate_value = 0;
     struct city *best_candidate = NULL;
     /* Whether ruleset has a help wonder unit type */
-    bool has_help = (get_role_unit(F_HELP_WONDER, 0) != U_LAST);
+    bool has_help = (num_role_units(F_HELP_WONDER) > 0);
 
     calculate_city_clusters(pplayer);
 
Index: common/fc_types.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/fc_types.h,v
retrieving revision 1.15
diff -u -r1.15 fc_types.h
--- common/fc_types.h   14 Mar 2005 20:26:25 -0000      1.15
+++ common/fc_types.h   26 Mar 2005 21:19:16 -0000
@@ -21,6 +21,20 @@
  * Nothing in this file should require anything else from the common/
  * directory! */
 
+#define BUG_EMAIL_ADDRESS "bugs@xxxxxxxxxxx"
+#define WEBSITE_URL "http://www.freeciv.org/";
+
+/* MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS <= 32 !!!! */
+#define MAX_NUM_PLAYERS  30
+#define MAX_NUM_BARBARIANS   2
+#define MAX_NUM_CONNECTIONS (2 * (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS))
+#define MAX_NUM_ITEMS   200     /* eg, unit_types */
+#define MAX_NUM_TECH_LIST 10
+#define MAX_NUM_UNIT_LIST 10
+#define MAX_NUM_BUILDING_LIST 10
+#define MAX_LEN_VET_SHORT_NAME 8
+#define MAX_VET_LEVELS 10
+
 enum output_type {
   O_FOOD, O_SHIELD, O_TRADE, O_GOLD, O_LUXURY, O_SCIENCE, O_LAST
 };
Index: common/nation.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/nation.h,v
retrieving revision 1.35
diff -u -r1.35 nation.h
--- common/nation.h     22 Jan 2005 21:12:10 -0000      1.35
+++ common/nation.h     26 Mar 2005 21:19:16 -0000
@@ -17,6 +17,7 @@
 
 #include "fc_types.h"
 #include "terrain.h"           /* T_COUNT */
+#include "unittype.h"           /* Unit_Type_id */
 
 #define MAX_NUM_TECH_GOALS 10
 
@@ -92,6 +93,7 @@
   /* Items given to this nation at game start.  Server only. */
   int init_techs[MAX_NUM_TECH_LIST];
   int init_buildings[MAX_NUM_BUILDING_LIST];
+  Unit_Type_id init_units[MAX_NUM_UNIT_LIST];
 };
 
 struct team {
Index: common/requirements.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.c,v
retrieving revision 1.6
diff -u -r1.6 requirements.c
--- common/requirements.c       23 Mar 2005 02:07:44 -0000      1.6
+++ common/requirements.c       26 Mar 2005 21:19:21 -0000
@@ -212,7 +212,8 @@
 /****************************************************************************
   Parse a requirement type and value string into a requrement structure.
   Returns REQ_LAST on error.  Passing in a NULL type is considered REQ_NONE
-  (not an error).
+  (not an error).  Pass in a helpful location for this parsing in case
+  we encounter an error.
 
   Pass this some values like "Building", "Factory".
 ****************************************************************************/
@@ -268,7 +269,7 @@
   if (invalid) {
     freelog(LOG_ERROR, "Invalid requirement %s | %s | %s | %s",
            type, range, survives ? "survives" : "", value);
-    exit(EXIT_FAILURE);
+    req.source.type = REQ_LAST;
   }
 
   return req;
Index: server/barbarian.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/barbarian.c,v
retrieving revision 1.84
diff -u -r1.84 barbarian.c
--- server/barbarian.c  14 Mar 2005 20:26:25 -0000      1.84
+++ server/barbarian.c  26 Mar 2005 21:19:25 -0000
@@ -201,7 +201,9 @@
   struct tile *utile = NULL;
   bool alive = TRUE;     /* explorer survived */
 
-  if (game.barbarianrate == 0 || (game.year < game.onsetbarbarian)) {
+  if (game.barbarianrate == 0
+      || game.year < game.onsetbarbarian
+      || num_role_units(L_BARBARIAN) != 0) {
     unit_list_iterate_safe((ptile)->units, punit) {
       wipe_unit(punit);
     } unit_list_iterate_safe_end;
Index: server/gamehand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.c,v
retrieving revision 1.157
diff -u -r1.157 gamehand.c
--- server/gamehand.c   14 Mar 2005 20:26:25 -0000      1.157
+++ server/gamehand.c   26 Mar 2005 21:19:26 -0000
@@ -141,6 +141,26 @@
 }
 
 /****************************************************************************
+  Find a valid position not far from our starting position.
+****************************************************************************/
+static struct tile *find_dispersed_position(struct player *pplayer,
+                                            struct start_position *p)
+{
+  struct tile *ptile;
+  int x, y;
+
+  do {
+    x = p->tile->x + myrand(2 * game.dispersion + 1) - game.dispersion;
+    y = p->tile->y + myrand(2 * game.dispersion + 1) - game.dispersion;
+  } while (!((ptile = map_pos_to_tile(x, y))
+             && map_get_continent(p->tile) == map_get_continent(ptile)
+             && !is_ocean(map_get_terrain(ptile))
+             && !is_non_allied_unit_tile(ptile, pplayer)));
+
+  return ptile;
+}
+
+/****************************************************************************
   Initialize a new game: place the players' units onto the map, etc.
 ****************************************************************************/
 void init_new_game(void)
@@ -225,8 +245,9 @@
 
   /* Place all other units. */
   players_iterate(pplayer) {
-    int i, x, y;
+    int i;
     struct tile *ptile;
+    struct nation_type *nation = get_nation_by_plr(pplayer);
     struct start_position p
       = map.start_positions[start_pos[pplayer->player_no]];
 
@@ -235,19 +256,21 @@
       continue;
     }
 
+    /* Place global start units */
     for (i = 1; i < strlen(game.start_units); i++) {
-      do {
-       x = p.tile->x + myrand(2 * game.dispersion + 1) - game.dispersion;
-       y = p.tile->y + myrand(2 * game.dispersion + 1) - game.dispersion;
-      } while (!((ptile = map_pos_to_tile(x, y))
-                && map_get_continent(p.tile) == map_get_continent(ptile)
-                && !is_ocean(map_get_terrain(ptile))
-                && !is_non_allied_unit_tile(ptile, pplayer)));
-
+      ptile = find_dispersed_position(pplayer, &p);
 
       /* Create the unit of an appropriate type. */
       place_starting_unit(ptile, pplayer, game.start_units[i]);
     }
+
+    /* Place nation specific start units (not role based!) */
+    i = 0;
+    while (nation->init_units[i] != U_LAST && i < MAX_NUM_UNIT_LIST) {
+      ptile = find_dispersed_position(pplayer, &p);
+      create_unit(pplayer, ptile, nation->init_units[i], FALSE, 0, 0);
+      i++;
+    }
   } players_iterate_end;
 
   shuffle_players();
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.235
diff -u -r1.235 ruleset.c
--- server/ruleset.c    24 Mar 2005 16:41:42 -0000      1.235
+++ server/ruleset.c    26 Mar 2005 21:19:27 -0000
@@ -232,6 +232,58 @@
 
 /**************************************************************************
  Lookup a prefix.entry string vector in the file and fill in the
+ array, which should hold MAX_NUM_UNIT_LIST items. The output array is
+ either U_LAST terminated or full (contains MAX_NUM_UNIT_LIST
+ items). If the vector is not found and the required parameter is set,
+ we report it as an error, otherwise we just punt.
+**************************************************************************/
+static void lookup_unit_list(struct section_file *file, const char *prefix,
+                            const char *entry, int *output, 
+                             const char *filename, bool required)
+{
+  char **slist;
+  int i, nval;
+
+  /* pre-fill with U_LAST: */
+  for(i = 0; i < MAX_NUM_UNIT_LIST; i++) {
+    output[i] = A_LAST;
+  }
+  slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
+  if (nval == 0) {
+    if (required) {
+      freelog(LOG_FATAL, "Missing string vector %s.%s (%s)",
+             prefix, entry, filename);
+      exit(EXIT_FAILURE);
+    }
+    return;
+  }
+  if (nval > MAX_NUM_UNIT_LIST) {
+    freelog(LOG_FATAL, "String vector %s.%s too long (%d, max %d) (%s)",
+           prefix, entry, nval, MAX_NUM_UNIT_LIST, filename);
+    exit(EXIT_FAILURE);
+  }
+  if (nval == 1 && strcmp(slist[0], "") == 0) {
+    free(slist);
+    return;
+  }
+  for (i = 0; i < nval; i++) {
+    char *sval = slist[i];
+    Unit_Type_id uid = find_unit_type_by_name(sval);
+
+    if (uid == U_LAST) {
+      freelog(LOG_FATAL, "For %s %s (%d) couldn't match unit \"%s\" (%s)",
+             prefix, entry, i, sval, filename);
+      exit(EXIT_FAILURE);
+    }
+    output[i] = uid;
+    freelog(LOG_DEBUG, "%s.%s,%d %s %d", prefix, entry, i, sval, uid);
+  }
+  free(slist);
+  return;
+}
+
+/**************************************************************************
+ Lookup a prefix.entry string vector in the file and fill in the
  array, which should hold MAX_NUM_TECH_LIST items. The output array is
  either A_LAST terminated or full (contains MAX_NUM_TECH_LIST
  items). All valid entries of the output array are guaranteed to
@@ -1057,40 +1109,37 @@
     freelog(LOG_FATAL, "No role=ferryboat units? (%s)", filename);
     exit(EXIT_FAILURE);
   }
-  if(num_role_units(L_HUT)==0) {
-    freelog(LOG_FATAL, "No role=hut units? (%s)", filename);
-    exit(EXIT_FAILURE);
-  }
   if(num_role_units(L_FIRSTBUILD)==0) {
     freelog(LOG_FATAL, "No role=firstbuild units? (%s)", filename);
     exit(EXIT_FAILURE);
   }
-  if(num_role_units(L_BARBARIAN)==0) {
+  if (num_role_units(L_BARBARIAN) == 0 && game.barbarianrate > 0) {
     freelog(LOG_FATAL, "No role=barbarian units? (%s)", filename);
     exit(EXIT_FAILURE);
   }
-  if(num_role_units(L_BARBARIAN_LEADER)==0) {
+  if (num_role_units(L_BARBARIAN_LEADER) == 0 && game.barbarianrate > 0) {
     freelog(LOG_FATAL, "No role=barbarian leader units? (%s)", filename);
     exit(EXIT_FAILURE);
   }
-  if(num_role_units(L_BARBARIAN_BUILD)==0) {
+  if (num_role_units(L_BARBARIAN_BUILD) == 0 && game.barbarianrate > 0) {
     freelog(LOG_FATAL, "No role=barbarian build units? (%s)", filename);
     exit(EXIT_FAILURE);
   }
-  if(num_role_units(L_BARBARIAN_BOAT)==0) {
+  if (num_role_units(L_BARBARIAN_BOAT) == 0 && game.barbarianrate > 0) {
     freelog(LOG_FATAL, "No role=barbarian ship units? (%s)", filename);
     exit(EXIT_FAILURE);
+  } else if (num_role_units(L_BARBARIAN_BOAT) > 0) {
+    u = &unit_types[get_role_unit(L_BARBARIAN_BOAT,0)];
+    if(u->move_type != SEA_MOVING) {
+      freelog(LOG_FATAL, "Barbarian boat (%s) needs to be a sea unit (%s)",
+              u->name, filename);
+      exit(EXIT_FAILURE);
+    }
   }
-  if(num_role_units(L_BARBARIAN_SEA)==0) {
+  if (num_role_units(L_BARBARIAN_SEA) == 0 && game.barbarianrate > 0) {
     freelog(LOG_FATAL, "No role=sea raider barbarian units? (%s)", filename);
     exit(EXIT_FAILURE);
   }
-  u = &unit_types[get_role_unit(L_BARBARIAN_BOAT,0)];
-  if(u->move_type != SEA_MOVING) {
-    freelog(LOG_FATAL, "Barbarian boat (%s) needs to be a sea unit (%s)",
-            u->name, filename);
-    exit(EXIT_FAILURE);
-  }
 
   /* pre-calculate game.rtech.u_partisan
      (tech for first partisan unit, or A_LAST */
@@ -2146,6 +2195,8 @@
     lookup_tech_list(file, sec[i], "init_techs", pl->init_techs, filename);
     lookup_building_list(file, sec[i], "init_buildings", pl->init_buildings,
                         filename);
+    lookup_unit_list(file, sec[i], "init_units", pl->init_units, filename,
+                     FALSE);
 
     /* read "normal" city names */
 
@@ -2269,7 +2320,7 @@
       const char *value
        = secfile_lookup_str_default(file, "", "specialist.%s_req%d.value",
                                     name, j);
-      struct requirement req = req_from_str(type, range, survives, value);
+      struct requirement req = req_from_str(type, range, survives, value); 
 
       if (req.source.type == REQ_LAST) {
        freelog(LOG_ERROR,
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.330
diff -u -r1.330 unittools.c
--- server/unittools.c  24 Mar 2005 17:48:49 -0000      1.330
+++ server/unittools.c  26 Mar 2005 21:19:29 -0000
@@ -2382,7 +2382,11 @@
     hut_get_tech(punit);
     break;
   case 8: case 9:
-    hut_get_mercenaries(punit);
+    if (num_role_units(L_HUT) != 0) {
+      hut_get_mercenaries(punit);
+    } else {
+      hut_get_gold(punit, 25);
+    }
     break;
   case 10:
     ok = hut_get_barbarians(punit);
Index: utility/shared.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/shared.h,v
retrieving revision 1.141
diff -u -r1.141 shared.h
--- utility/shared.h    26 Feb 2005 18:27:19 -0000      1.141
+++ utility/shared.h    26 Mar 2005 21:19:29 -0000
@@ -55,24 +55,8 @@
 #define fc__attribute(x)
 #endif
 
-
-/* Note: the capability string is now in capstr.c --dwp */
-/* Version stuff is now in version.h --dwp */
-
-#define BUG_EMAIL_ADDRESS "bugs@xxxxxxxxxxx"
-#define WEBSITE_URL "http://www.freeciv.org/";
-
-/* MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS <= 32 !!!! */
-#define MAX_NUM_PLAYERS  30
-#define MAX_NUM_BARBARIANS   2
-#define MAX_NUM_CONNECTIONS (2 * (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS))
-#define MAX_NUM_ITEMS   200    /* eg, unit_types */
-#define MAX_NUM_TECH_LIST 10
-#define MAX_NUM_BUILDING_LIST 10
 #define MAX_LEN_NAME     32
 #define MAX_LEN_ADDR     256   /* see also MAXHOSTNAMELEN and RFC 1123 2.1 */
-#define MAX_LEN_VET_SHORT_NAME 8
-#define MAX_VET_LEVELS 10
 #define MAX_LEN_PATH 4095
 
 /* Use FC_INFINITY to denote that a certain event will never occur or

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#12667) A few modpack fixes, Per I. Mathisen <=