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

On 1/22/07, Marko Lindqvist <[EMAIL PROTECTED]> wrote:
>  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.

 Removed overzealous assert.


 - 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-25 21:49:07.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-25 21:49:07.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-25 17:59:51.000000000 +0200
+++ freeciv/common/unittype.c	2007-01-25 21:52:13.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,32 @@
     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. So following gives wrong answer in the client.
+       * This is called at the client when received create_city
+       * packet for a barbarian city. City initialization tries
+       * to find L_FIRSTBUILD unit. */
+
+      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 +526,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 +544,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