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

 Barbarian building code just starts building units without checking
if building that unit is at all possible in that city. So barbarian
can for example end building ship in landlocked city, if someone gives
ship a BARBARIAN_BUILD role.

 Attached is untested patch to fix this.
can_player_build_unit_direct() is modified so it works correctly for
barbarian players too. ai_barbarian_choose_build() now uses
can_build_unit() (which eventually calls
can_player_build_unit_direct()) to check if unit can be built.


 - ML

diff -Nurd -X.diff_ignore freeciv/ai/aicity.c freeciv/ai/aicity.c
--- freeciv/ai/aicity.c	2006-07-17 23:56:47.000000000 +0300
+++ freeciv/ai/aicity.c	2007-01-22 19:34:00.000000000 +0200
@@ -1237,6 +1237,7 @@
   so can be a bigger bother to cache it.
 **************************************************************************/
 static void ai_barbarian_choose_build(struct player *pplayer, 
+                                      struct city *pcity,
 				      struct ai_choice *choice)
 {
   struct unit_type *bestunit = NULL;
@@ -1246,7 +1247,8 @@
   for(i = 0; i < num_role_units(L_BARBARIAN_BUILD); i++) {
     struct unit_type *iunit = get_role_unit(L_BARBARIAN_BUILD, i);
 
-    if (iunit->attack_strength > bestattack) {
+    if (iunit->attack_strength > bestattack
+        && can_build_unit(pcity, iunit)) {
       bestunit = iunit;
       bestattack = iunit->attack_strength;
     }
@@ -1256,8 +1258,8 @@
   for(i = 0; i < num_role_units(L_BARBARIAN_BUILD_TECH); i++) {
     struct unit_type *iunit = get_role_unit(L_BARBARIAN_BUILD_TECH, i);
 
-    if (game.info.global_advances[iunit->tech_requirement]
-	&& iunit->attack_strength > bestattack) {
+    if (iunit->attack_strength > bestattack
+        && can_build_unit(pcity, iunit)) {
       bestunit = iunit;
       bestattack = iunit->attack_strength;
     }
@@ -1297,7 +1299,7 @@
   }
 
   if( is_barbarian(pplayer) ) {
-    ai_barbarian_choose_build(pplayer, &(pcity->ai.choice));
+    ai_barbarian_choose_build(pplayer, pcity, &(pcity->ai.choice));
   } else {
     /* FIXME: 101 is the "overriding military emergency" indicator */
     if ((pcity->ai.choice.want <= 100 || pcity->ai.urgency == 0)
diff -Nurd -X.diff_ignore freeciv/common/city.c freeciv/common/city.c
--- freeciv/common/city.c	2007-01-19 16:20:07.000000000 +0200
+++ freeciv/common/city.c	2007-01-22 19:31:42.000000000 +0200
@@ -483,7 +483,7 @@
 }
 
 /**************************************************************************
-  Return whether given city can build given unit; returns 0 if unit is 
+  Return whether given city can build given unit; returns FALSE if unit is 
   obsolete.
 **************************************************************************/
 bool can_build_unit(const struct city *pcity,
@@ -502,7 +502,7 @@
 
 /**************************************************************************
   Return whether player can eventually build given unit in the city;
-  returns 0 if unit can never possibly be built in this city.
+  returns FALSE if unit can never possibly be built in this city.
 **************************************************************************/
 bool can_eventually_build_unit(const struct city *pcity,
 			       const struct unit_type *punittype)
diff -Nurd -X.diff_ignore freeciv/common/unittype.c freeciv/common/unittype.c
--- freeciv/common/unittype.c	2007-01-20 18:07:16.000000000 +0200
+++ freeciv/common/unittype.c	2007-01-22 19:39:22.000000000 +0200
@@ -454,6 +454,14 @@
   Impr_type_id impr_req;
 
   CHECK_UNIT_TYPE(punittype);
+
+  if (is_barbarian(p)
+      && !unit_has_role(punittype, L_BARBARIAN_BUILD)
+      && !unit_has_role(punittype, L_BARBARIAN_BUILD_TECH)) {
+    /* Barbarians can build only role units */
+    return FALSE;
+  }
+
   if (unit_type_flag(punittype, F_NUCLEAR)
       && !get_player_bonus(p, EFT_ENABLE_NUKE) > 0) {
     return FALSE;
@@ -466,7 +474,31 @@
     return FALSE;
   }
   if (get_invention(p,punittype->tech_requirement) != TECH_KNOWN) {
-    return FALSE;
+    if (!is_barbarian(p)) {
+      /* Normal players can never build units without knowing tech
+       * requirements. */
+      return FALSE;
+    }
+    if (!unit_has_role(punittype, L_BARBARIAN_BUILD)) {
+      /* Even barbarian cannot build this unit without tech */
+
+      /* Unit has to have L_BARBARIAN_BUILD_TECH role
+       * In the beginning of this function we checked that
+       * barbarian player tries to build only role
+       * L_BARBARIAN_BUILD or L_BARBARIAN_BUILD_TECH units. */
+      assert(unit_has_role(punittype, L_BARBARIAN_BUILD_TECH));
+
+      /* Client does not know all the advances other players have
+       * got. Client should never call this function for
+       * barbarian player. */
+      assert(is_server);
+
+      if (!game.info.global_advances[punittype->tech_requirement]) {
+        /* Nobody knows required tech */
+        return FALSE;
+      }
+    }
+    
   }
   if (unit_type_flag(punittype, F_UNIQUE)) {
     /* FIXME: This could be slow if we have lots of units. We could
@@ -493,7 +525,7 @@
 
 /**************************************************************************
 Whether player can build given unit somewhere;
-returns 0 if unit is obsolete.
+returns FALSE if unit is obsolete.
 **************************************************************************/
 bool can_player_build_unit(const struct player *p,
 			   const struct unit_type *punittype)
@@ -511,8 +543,8 @@
 
 /**************************************************************************
 Whether player can _eventually_ build given unit somewhere -- ie,
-returns 1 if unit is available with current tech OR will be available
-with future tech.  returns 0 if unit is obsolete.
+returns TRUE if unit is available with current tech OR will be available
+with future tech. Returns FALSE if unit is obsolete.
 **************************************************************************/
 bool can_player_eventually_build_unit(const struct player *p,
 				      const struct unit_type *punittype)
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to