Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2003:
[Freeciv-Dev] (PR#4044) veteran level patch
Home

[Freeciv-Dev] (PR#4044) veteran level patch

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: bursig@xxxxxxxxx, james.blewitt@xxxxxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#4044) veteran level patch
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Mon, 17 Nov 2003 07:08:12 -0800
Reply-to: rt@xxxxxxxxxxx

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

This one is based on Rafal's latest edition of the veteran level patch.

I removed client support in all clients except gtk1&2 (sorry - no idea on
how to fix). Removed a lot of spurious changes that have nothing to do
with veteran levels. Also removed barbarian veteran levels, unlimited
veteran levels, per unit veteran sprites, short names, drawing veteran
level only for own units, and per-unit trireme loss chance. Work raise
chance and raise chance is same for all units. Fixed stack icon vs
veterancy icon bug. Units can now have different number of veterancy
levels, up to a maximum of 10. New unit flag F_NO_VETERAN to disable
veterancy for some unit types. Diplomat escape chance based on
game.diplchance (game.diplchance + 5% each vet level).

I plan on committing this eventually with rulesets set to values that
makes gameplay similiar to current rules. Then we should have
a discussion about what we should use as default rules; better to discuss
this when suggestions can be tested.

You will need one of the new tilesets with veterancy icons, discussed on
the list recently, to test this patch.

  - Per

Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.157
diff -u -r1.157 advmilitary.c
--- ai/advmilitary.c    2003/11/16 22:11:12     1.157
+++ ai/advmilitary.c    2003/11/17 15:02:30
@@ -726,7 +726,7 @@
 **************************************************************************/
 static void process_attacker_want(struct city *pcity,
                                   int value, Unit_Type_id victim_unit_type,
-                                  bool veteran, int x, int y,
+                                  int veteran, int x, int y,
                                   struct ai_choice *best_choice,
                                   struct unit *boat, Unit_Type_id boattype)
 {
@@ -933,7 +933,7 @@
   int boatspeed;
   bool go_by_boat;
   /* Is the defender veteran? */
-  bool def_vet;
+  int def_vet;
   struct ai_choice best_choice;
 
   init_choice(&best_choice);
@@ -1017,7 +1017,7 @@
     } else {
       vuln = 0;
       benefit = 0;
-      def_vet = FALSE;
+      def_vet = 0;
     }
 
     pdef = get_defender(myunit, x, y);
@@ -1318,7 +1318,7 @@
   /* Consider a land attacker */
   unit_type = ai_choose_attacker(pcity, LAND_MOVING);
   if (unit_type >= 0) {
-    virtualunit = create_unit_virtual(pplayer, pcity, unit_type, TRUE);
+    virtualunit = create_unit_virtual(pplayer, pcity, unit_type, 1);
     kill_something_with(pplayer, pcity, virtualunit, choice);
     destroy_unit_virtual(virtualunit);
   }
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.303
diff -u -r1.303 aiunit.c
--- ai/aiunit.c 2003/11/15 12:47:21     1.303
+++ ai/aiunit.c 2003/11/17 15:02:32
@@ -702,7 +702,7 @@
 /**************************************************************************
   Attack rating of this kind of unit.
 **************************************************************************/
-int unittype_att_rating(Unit_Type_id type, bool veteran,
+int unittype_att_rating(Unit_Type_id type, int veteran,
                         int moves_left, int hp)
 {
   return base_get_attack_power(type, veteran, moves_left) * hp
@@ -782,7 +782,7 @@
   x, y, fortified and veteran.
 **************************************************************************/
 int unittype_def_rating_sq(Unit_Type_id att_type, Unit_Type_id def_type,
-                           int x, int y, bool fortified, bool veteran)
+                           int x, int y, bool fortified, int veteran)
 {
   int v = get_virtual_defense_power(att_type, def_type, x, y,
                                     fortified, veteran) *
@@ -883,12 +883,12 @@
       if (!can_unit_attack_all_at_tile(aunit, pdef->x, pdef->y))
        continue;
       d = get_virtual_defense_power(aunit->type, pdef->type, pdef->x,
-                                   pdef->y, FALSE, FALSE);
+                                   pdef->y, FALSE, 0);
       if (d == 0)
        return TRUE;            /* Thanks, Markus -- Syela */
       cur = unit_att_rating_now(aunit) *
          get_virtual_defense_power(punit->type, pdef->type, pdef->x,
-                                   pdef->y, FALSE, FALSE) / d;
+                                   pdef->y, FALSE, 0) / d;
       if (cur > val && ai_fuzzy(unit_owner(punit), TRUE))
        return FALSE;
     }
Index: ai/aiunit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.h,v
retrieving revision 1.49
diff -u -r1.49 aiunit.h
--- ai/aiunit.h 2003/09/27 11:22:40     1.49
+++ ai/aiunit.h 2003/11/17 15:02:32
@@ -64,13 +64,13 @@
                     int *x, int *y);
 
 int build_cost_balanced(Unit_Type_id type);
-int unittype_att_rating(Unit_Type_id type, bool veteran,
+int unittype_att_rating(Unit_Type_id type, int veteran,
                         int moves_left, int hp);
 int unit_att_rating(struct unit *punit);
 int unit_def_rating_basic(struct unit *punit);
 int unit_def_rating_basic_sq(struct unit *punit);
 int unittype_def_rating_sq(Unit_Type_id att_type, Unit_Type_id def_type,
-                           int x, int y, bool fortified, bool veteran);
+                           int x, int y, bool fortified, int veteran);
 int kill_desire(int benefit, int attack, int loss, int vuln, int attack_count);
 
 bool is_on_unit_upgrade_path(Unit_Type_id test, Unit_Type_id base);
Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.121
diff -u -r1.121 climisc.c
--- client/climisc.c    2003/10/21 21:49:55     1.121
+++ client/climisc.c    2003/11/17 15:02:33
@@ -1108,6 +1108,7 @@
   char buffer2[64];
   char buffer3[64];
   char buffer4[64];
+  struct unit_type *ptype = unit_type(punit);
 
   pcity = player_find_city_by_id(game.player_ptr, punit->homecity);
   pcity_near = get_nearest_city(punit, &pcity_near_dist);
@@ -1117,12 +1118,15 @@
   } else {
     buffer3[0] = 0;
   }
-  if (punit->veteran) {
-    my_snprintf(buffer4, sizeof(buffer4),
-               _("%s (veteran)"), unit_type(punit)->name);
-  } else {
-    sz_strlcpy(buffer4, unit_type(punit)->name);
+    
+  my_snprintf(buffer4, sizeof(buffer4), _("%s"), ptype->name);
+    
+  if (ptype->veteran[punit->veteran].name != "") {
+    sz_strlcat(buffer4, " (");
+    sz_strlcat(buffer4, ptype->veteran[punit->veteran].name);
+    sz_strlcat(buffer4, ")");
   }
+  
   my_snprintf(buffer, sizeof(buffer), "%s\n%s\n%s\n%s", 
              buffer4,
              unit_activity_text(punit), 
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.69
diff -u -r1.69 mapview_common.c
--- client/mapview_common.c     2003/11/14 12:26:56     1.69
+++ client/mapview_common.c     2003/11/17 15:02:34
@@ -608,7 +608,8 @@
 {
   struct drawn_sprite drawn_sprites[40];
   bool solid_bg;
-  int count = fill_unit_sprite_array(drawn_sprites, punit, &solid_bg), i;
+  int count = fill_unit_sprite_array(drawn_sprites, punit, &solid_bg, FALSE);
+  int i;
 
   if (!is_isometric && solid_bg) {
     gui_put_rectangle(pcanvas_store, player_color(unit_owner(punit)),
Index: client/options.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/options.c,v
retrieving revision 1.87
diff -u -r1.87 options.c
--- client/options.c    2003/11/13 20:11:31     1.87
+++ client/options.c    2003/11/17 15:02:34
@@ -276,6 +276,7 @@
   GEN_EV(N_("Unit: Built"),                           E_UNIT_BUILD),
   GEN_EV(N_("Unit: Defender Destroyed"),              E_UNIT_LOST),
   GEN_EV(N_("Unit: Defender Survived"),               E_UNIT_WIN),
+  GEN_EV(N_("Unit: Became More Veteran"),             E_UNIT_BECAME_VET),
   GEN_EV(N_("Unit: Production Upgraded"),             E_UNIT_UPGRADED),
   GEN_EV(N_("Unit: Relocated"),                       E_UNIT_RELOCATED),
   GEN_EV(N_("Wonder: Finished"),                      E_WONDER_BUILD),
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.337
diff -u -r1.337 packhand.c
--- client/packhand.c   2003/11/14 12:26:56     1.337
+++ client/packhand.c   2003/11/17 15:02:36
@@ -2052,6 +2052,8 @@
   u->paratroopers_mr_req = p->paratroopers_mr_req;
   u->paratroopers_mr_sub = p->paratroopers_mr_sub;
 
+  memcpy(u->veteran, p->veteran, sizeof(p->veteran));
+
   u->helptext = p->helptext;   /* pointer assignment */
 
   tilespec_setup_unit_type(p->id);
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.133
diff -u -r1.133 tilespec.c
--- client/tilespec.c   2003/10/15 21:15:46     1.133
+++ client/tilespec.c   2003/11/17 15:02:38
@@ -914,6 +914,11 @@
     SET_SPRITE(unit.hp_bar[i], buffer);
   }
 
+  for(i = 0; i < MAX_VET_LEVELS; i++) {
+    my_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
+    SET_SPRITE(unit.vet_lev[i], buffer);
+  }
+
   SET_SPRITE(city.disorder, "city.disorder");
 
   for(i=0; i<NUM_TILES_DIGITS; i++) {
@@ -1403,7 +1408,7 @@
   Fill in the sprite array for the unit
 ***********************************************************************/
 int fill_unit_sprite_array(struct drawn_sprite *sprs, struct unit *punit,
-                          bool *solid_bg)
+                          bool *solid_bg, bool stack)
 {
   struct drawn_sprite *save_sprs = sprs;
   int ihp;
@@ -1496,6 +1501,12 @@
     ADD_SPRITE_SIMPLE(sprites.unit.patrol);
   }
 
+  if (stack) {
+    ADD_SPRITE_SIMPLE(sprites.unit.stack);
+  } else {
+    ADD_SPRITE_SIMPLE(sprites.unit.vet_lev[punit->veteran]);
+  }
+ 
   ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / unit_type(punit)->hp;
   ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
   ADD_SPRITE_SIMPLE(sprites.unit.hp_bar[ihp]);
@@ -2079,12 +2090,13 @@
   if (solid_color_behind_units) {
     punit = get_drawable_unit(abs_x0, abs_y0, citymode);
     if (punit && (draw_units || (draw_focus_unit && pfocus == punit))) {
-      sprs += fill_unit_sprite_array(sprs, punit, solid_bg);
-      *pplayer = unit_owner(punit);
       if (unit_list_size(&ptile->units) > 1
          || unit_list_get(&ptile->units, 0)->occupy) {
-       ADD_SPRITE_SIMPLE(sprites.unit.stack);
+        sprs += fill_unit_sprite_array(sprs, punit, solid_bg, TRUE);
+      } else {
+        sprs += fill_unit_sprite_array(sprs, punit, solid_bg, FALSE);
       }
+      *pplayer = unit_owner(punit);
       return sprs - save_sprs;
     }
 
@@ -2236,12 +2248,13 @@
        bool dummy;
 
        no_backdrop = (pcity != NULL);
-       sprs += fill_unit_sprite_array(sprs, punit, &dummy);
        no_backdrop = FALSE;
        if (unit_list_size(&ptile->units) > 1
            || unit_list_get(&ptile->units, 0)->occupy) {
-         ADD_SPRITE_SIMPLE(sprites.unit.stack);
-       }
+          sprs += fill_unit_sprite_array(sprs, punit, &dummy, TRUE);
+       } else {
+          sprs += fill_unit_sprite_array(sprs, punit, &dummy, FALSE);
+        }
       }
     }
   }
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.48
diff -u -r1.48 tilespec.h
--- client/tilespec.h   2003/10/15 21:15:46     1.48
+++ client/tilespec.h   2003/11/17 15:02:38
@@ -63,7 +63,7 @@
                           bool citymode, bool *solid_bg,
                           struct player **pplayer);
 int fill_unit_sprite_array(struct drawn_sprite *sprs,
-                          struct unit *punit, bool *solid_bg);
+                          struct unit *punit, bool *solid_bg, bool stack);
 int fill_city_sprite_array_iso(struct drawn_sprite *sprs,
                               struct city *pcity);
 
@@ -143,6 +143,7 @@
   struct {
     struct Sprite
       *hp_bar[NUM_TILES_HP_BAR],
+      *vet_lev[MAX_VET_LEVELS],
       *auto_attack,
       *auto_settler,
       *auto_explore,
Index: client/gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.184
diff -u -r1.184 mapview.c
--- client/gui-gtk/mapview.c    2003/11/14 12:26:56     1.184
+++ client/gui-gtk/mapview.c    2003/11/17 15:02:40
@@ -264,13 +264,19 @@
        player_find_city_by_id(game.player_ptr, punit->homecity);
     int infrastructure =
        get_tile_infrastructure_set(map_get_tile(punit->x, punit->y));
+    struct unit_type *ptype = unit_type(punit);
+      
+    my_snprintf(buffer, sizeof(buffer), "%s", ptype->name);
+    
+    if (ptype->veteran[punit->veteran].name != "") {
+      sz_strlcat(buffer, " (");
+      sz_strlcat(buffer, ptype->veteran[punit->veteran].name);
+      sz_strlcat(buffer, ")");
+    }
+    
+    gtk_frame_set_label(GTK_FRAME(unit_info_frame), buffer);
 
-    my_snprintf(buffer, sizeof(buffer), "%s %s", 
-            unit_type(punit)->name,
-            (punit->veteran) ? _("(veteran)") : "" );
-    gtk_frame_set_label( GTK_FRAME(unit_info_frame), buffer);
 
-
     my_snprintf(buffer, sizeof(buffer), "%s\n%s\n%s%s%s",
                (hover_unit == punit->id) ?
                _("Select destination") : unit_activity_text(punit),
@@ -278,7 +284,7 @@
                infrastructure ?
                map_get_infrastructure_text(infrastructure) : "",
                infrastructure ? "\n" : "", pcity ? pcity->name : "");
-    gtk_set_label( unit_info_label, buffer);
+    gtk_set_label(unit_info_label, buffer);
 
     if (hover_unit != punit->id)
       set_hover_state(NULL, HOVER_NONE);
Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.81
diff -u -r1.81 mapview.c
--- client/gui-gtk-2.0/mapview.c        2003/11/14 12:26:57     1.81
+++ client/gui-gtk-2.0/mapview.c        2003/11/17 15:02:41
@@ -304,12 +304,17 @@
        player_find_city_by_id(game.player_ptr, punit->homecity);
     int infrastructure =
        get_tile_infrastructure_set(map_get_tile(punit->x, punit->y));
-
-    my_snprintf(buffer, sizeof(buffer), "%s %s", 
-            unit_type(punit)->name,
-            (punit->veteran) ? _("(veteran)") : "" );
-    gtk_frame_set_label( GTK_FRAME(unit_info_frame), buffer);
-
+    struct unit_type *ptype = unit_type(punit);
+      
+    my_snprintf(buffer, sizeof(buffer), "%s", ptype->name);
+    
+    if (ptype->veteran[punit->veteran].name != "") {
+      sz_strlcat(buffer, " (");
+      sz_strlcat(buffer, ptype->veteran[punit->veteran].name);
+      sz_strlcat(buffer, ")");
+    }
+    
+    gtk_frame_set_label(GTK_FRAME(unit_info_frame), buffer);
 
     my_snprintf(buffer, sizeof(buffer), "%s\n%s\n%s%s%s%s",
                (hover_unit == punit->id) ?
Index: common/combat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/combat.c,v
retrieving revision 1.33
diff -u -r1.33 combat.c
--- common/combat.c     2003/09/17 02:57:21     1.33
+++ common/combat.c     2003/11/17 15:02:43
@@ -383,15 +383,12 @@
  status. Set moves_left to SINGLE_MOVE to disable the reduction of
  power caused by tired units.
 **************************************************************************/
-int base_get_attack_power(Unit_Type_id type, bool veteran, int moves_left)
+int base_get_attack_power(Unit_Type_id type, int veteran, int moves_left)
 {
   int power;
 
   power = get_unit_type(type)->attack_strength * POWER_FACTOR;
-  if (veteran) {
-    /* Veterans get +50% bonus. */
-    power = (power * 3) / 2;
-  }
+  power *= get_unit_type(type)->veteran[veteran].power_fact;
 
   if (!unit_type_flag(type, F_IGTIRED) && moves_left < SINGLE_MOVE) {
     power = (power * moves_left) / SINGLE_MOVE;
@@ -404,11 +401,8 @@
 **************************************************************************/
 int base_get_defense_power(struct unit *punit)
 {
-  int power = unit_type(punit)->defense_strength * POWER_FACTOR;
-  if (punit->veteran) {
-    power = (power * 3) / 2;
-  }
-  return power;
+  return unit_type(punit)->defense_strength * POWER_FACTOR
+       * unit_type(punit)->veteran[punit->veteran].power_fact;
 }
 
 /**************************************************************************
@@ -508,7 +502,7 @@
  depend on the attacker.
 **************************************************************************/
 int get_virtual_defense_power(Unit_Type_id att_type, Unit_Type_id def_type,
-                             int x, int y, bool fortified, bool veteran)
+                             int x, int y, bool fortified, int veteran)
 {
   int defensepower = unit_types[def_type].defense_strength;
   enum tile_terrain_type t = map_get_terrain(x, y);
@@ -524,10 +518,7 @@
     db += (db * terrain_control.river_defense_bonus) / 100;
   }
   defensepower *= db;
-
-  if (veteran) {
-    defensepower = (defensepower * 3) / 2;
-  }
+  defensepower *= get_unit_type(def_type)->veteran[veteran].power_fact;
 
   return defence_multiplication(att_type, def_type, x, y, defensepower,
                                fortified);
Index: common/combat.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/combat.h,v
retrieving revision 1.10
diff -u -r1.10 combat.h
--- common/combat.h     2003/09/17 02:57:21     1.10
+++ common/combat.h     2003/11/17 15:02:43
@@ -47,12 +47,12 @@
 struct city *sdi_defense_close(struct player *owner, int x, int y);
 
 int get_attack_power(struct unit *punit);
-int base_get_attack_power(Unit_Type_id type, bool veteran, int moves_left);
+int base_get_attack_power(Unit_Type_id type, int veteran, int moves_left);
 int base_get_defense_power(struct unit *punit);
 int get_defense_power(struct unit *punit);
 int get_total_defense_power(struct unit *attacker, struct unit *defender);
 int get_virtual_defense_power(Unit_Type_id att_type, Unit_Type_id def_type,
-                             int x, int y, bool fortified, bool veteran);
+                             int x, int y, bool fortified, int veteran);
 int get_total_attack_power(struct unit *attacker, struct unit *defender);
 
 struct unit *get_defender(struct unit *attacker, int x, int y);
Index: common/events.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/events.h,v
retrieving revision 1.23
diff -u -r1.23 events.h
--- common/events.h     2003/08/08 22:11:41     1.23
+++ common/events.h     2003/11/17 15:02:43
@@ -95,6 +95,7 @@
   E_UNIT_BUILD,
   E_UNIT_LOST,
   E_UNIT_WIN,
+  E_UNIT_BECAME_VET,
   E_UNIT_UPGRADED,
   E_UNIT_RELOCATED,
   E_WONDER_BUILD,
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.126
diff -u -r1.126 game.h
--- common/game.h       2003/09/23 22:01:41     1.126
+++ common/game.h       2003/11/17 15:02:43
@@ -164,6 +164,7 @@
 
   char rulesetdir[MAX_LEN_NAME];
   int firepower_factor;                /* See README.rulesets */
+
   struct {
     int cathedral_plus;                /* eg Theology */
     int cathedral_minus;       /* eg Communism */
@@ -222,6 +223,10 @@
     bool load_private_map; /* Only makes sense if the players are loaded. */
     bool load_settings;
   } load_options;
+
+  int trireme_loss_chance[MAX_VET_LEVELS];
+  int work_veteran_chance[MAX_VET_LEVELS];
+  int veteran_chance[MAX_VET_LEVELS];
 };
 
 /* Unused? */
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.150
diff -u -r1.150 map.c
--- common/map.c        2003/11/14 12:26:58     1.150
+++ common/map.c        2003/11/17 15:02:44
@@ -769,7 +769,7 @@
 ***************************************************************/
 int map_build_road_time(int x, int y)
 {
-  return tile_types[map_get_terrain(x, y)].road_time;
+  return tile_types[map_get_terrain(x, y)].road_time * 10;
 }
 
 /***************************************************************
@@ -777,7 +777,7 @@
 ***************************************************************/
 int map_build_irrigation_time(int x, int y)
 {
-  return tile_types[map_get_terrain(x, y)].irrigation_time;
+  return tile_types[map_get_terrain(x, y)].irrigation_time * 10;
 }
 
 /***************************************************************
@@ -785,7 +785,7 @@
 ***************************************************************/
 int map_build_mine_time(int x, int y)
 {
-  return tile_types[map_get_terrain(x, y)].mining_time;
+  return tile_types[map_get_terrain(x, y)].mining_time * 10;
 }
 
 /***************************************************************
@@ -793,7 +793,7 @@
 ***************************************************************/
 int map_transform_time(int x, int y)
 {
-  return tile_types[map_get_terrain(x, y)].transform_time;
+  return tile_types[map_get_terrain(x, y)].transform_time * 10;
 }
 
 /***************************************************************
@@ -801,7 +801,7 @@
 ***************************************************************/
 int map_build_rail_time(int x, int y)
 {
-  return 3;
+  return 30;
 }
 
 /***************************************************************
@@ -809,7 +809,7 @@
 ***************************************************************/
 int map_build_airbase_time(int x, int y)
 {
-  return 3;
+  return 30;
 }
 
 /***************************************************************
@@ -817,7 +817,7 @@
 ***************************************************************/
 int map_build_fortress_time(int x, int y)
 {
-  return 3;
+  return 30;
 }
 
 /***************************************************************
@@ -825,7 +825,7 @@
 ***************************************************************/
 int map_clean_pollution_time(int x, int y)
 {
-  return 3;
+  return 30;
 }
 
 /***************************************************************
@@ -833,7 +833,7 @@
 ***************************************************************/
 int map_clean_fallout_time(int x, int y)
 {
-  return 3;
+  return 30;
 }
 
 /***************************************************************
Index: common/packets.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.c,v
retrieving revision 1.262
diff -u -r1.262 packets.c
--- common/packets.c    2003/10/29 07:32:57     1.262
+++ common/packets.c    2003/11/17 15:02:46
@@ -1283,7 +1283,6 @@
   pack = (COND_SET_BIT(req->done_moving, 1)
          | COND_SET_BIT((req->occupy > 0), 2)
          | COND_SET_BIT(req->carried, 3)
-         | COND_SET_BIT(req->veteran, 4)
          | COND_SET_BIT(req->ai, 5)
          | COND_SET_BIT(req->paradropped, 6)
          | COND_SET_BIT(req->connecting, 7));
@@ -1294,6 +1293,7 @@
   dio_put_uint8(&dout, req->type);
   dio_put_uint8(&dout, req->movesleft);
   dio_put_uint8(&dout, req->hp);
+  dio_put_uint8(&dout, req->veteran);
   dio_put_uint8(&dout, req->upkeep);
   dio_put_uint8(&dout, req->upkeep_food);
   dio_put_uint8(&dout, req->upkeep_gold);
@@ -1565,7 +1565,6 @@
   dio_get_uint8(&din, &pack);
   packet->done_moving = TEST_BIT(pack, 1);
   packet->carried = TEST_BIT(pack, 3);
-  packet->veteran = TEST_BIT(pack, 4);
   packet->ai = TEST_BIT(pack, 5);
   packet->paradropped = TEST_BIT(pack, 6);
   packet->connecting = TEST_BIT(pack, 7);
@@ -1575,6 +1574,7 @@
   dio_get_uint8(&din, &packet->type);
   dio_get_uint8(&din, &packet->movesleft);
   dio_get_uint8(&din, &packet->hp);
+  dio_get_uint8(&din, &packet->veteran);
   dio_get_uint8(&din, &packet->upkeep);
   dio_get_uint8(&din, &packet->upkeep_food);
   dio_get_uint8(&din, &packet->upkeep_gold);
@@ -2089,6 +2089,7 @@
 int send_packet_ruleset_unit(struct connection *pc,
                             const struct packet_ruleset_unit *packet)
 {
+  int i;
   SEND_PACKET_START(PACKET_RULESET_UNIT);
 
   dio_put_uint8(&dout, packet->id);
@@ -2126,6 +2127,11 @@
   }
   dio_put_uint8(&dout, packet->pop_cost);
 
+  for (i = 0; i < MAX_VET_LEVELS; i++) {
+    dio_put_string(&dout, packet->veteran[i].name);
+    dio_put_string(&dout, packet->veteran[i].short_name);
+  }
+  
   /* This must be last, so client can determine length: */
   if(packet->helptext) {
     dio_put_string(&dout, packet->helptext);
@@ -2140,7 +2146,7 @@
 struct packet_ruleset_unit *
 receive_packet_ruleset_unit(struct connection *pc)
 {
-  int len;
+  int len, i;
   RECEIVE_PACKET_START(packet_ruleset_unit, packet);
 
   dio_get_uint8(&din, &packet->id);
@@ -2186,6 +2192,13 @@
   }
   dio_get_uint8(&din, &packet->pop_cost);
 
+  for (i = 0; i < MAX_VET_LEVELS; i++) {
+    dio_get_string(&din, packet->veteran[i].name,
+                   sizeof(packet->veteran[i].name));
+    dio_get_string(&din, packet->veteran[i].short_name,
+                   sizeof(packet->veteran[i].short_name));
+  }
+  
   len = dio_input_remaining(&din);
   if (len > 0) {
     packet->helptext = fc_malloc(len);
@@ -2917,7 +2930,7 @@
   dio_put_uint8(&dout, packet->tech_cost_style);
   dio_put_uint8(&dout, packet->tech_leakage);
   dio_put_tech_list(&dout, packet->global_init_techs);
-
+  
   SEND_PACKET_END;
 }
 
Index: common/packets.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.h,v
retrieving revision 1.159
diff -u -r1.159 packets.h
--- common/packets.h    2003/11/13 19:41:09     1.159
+++ common/packets.h    2003/11/17 15:02:47
@@ -311,11 +311,11 @@
   int id;
   int owner;
   int x, y;
-  bool veteran;
   int homecity;
   int type;
   int movesleft;
   int hp;
+  int veteran;
   int activity;
   int activity_count;
   int unhappiness;
@@ -676,6 +676,8 @@
   int paratroopers_range; /* max range of paratroopers, F_PARATROOPERS */
   int paratroopers_mr_req;
   int paratroopers_mr_sub;
+
+  struct veteran_type veteran[MAX_VET_LEVELS];
 
   /* Following is a pointer to malloced memory; on the server, it
      points to putype->helptext, malloced earlier; on the client,
Index: common/shared.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/shared.h,v
retrieving revision 1.119
diff -u -r1.119 shared.h
--- common/shared.h     2003/10/16 00:04:56     1.119
+++ common/shared.h     2003/11/17 15:02:47
@@ -55,12 +55,15 @@
 #define BUG_EMAIL_ADDRESS "bugs@xxxxxxxxxxxxxxxxxxx"
 #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_ITEMS   200    /* eg, unit_types */
 #define MAX_NUM_TECH_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
 
 /* Use FC_INFINITY to denote that a certain event will never occur or
    another unreachable condition. */
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.187
diff -u -r1.187 unit.c
--- common/unit.c       2003/10/29 08:00:39     1.187
+++ common/unit.c       2003/11/17 15:02:48
@@ -37,22 +37,25 @@
 /***************************************************************
 This function calculates the move rate of the unit taking into 
 account the penalty for reduced hitpoints (affects sea and land 
-units only) and the effects of wonders for sea units. 
+units only) and the effects of wonders for sea units
++ veteran bonus.
 
 FIXME: Use generalised improvements code instead of hardcoded
 wonder effects --RK
 ***************************************************************/
 int unit_move_rate(struct unit *punit)
 {
-  int move_rate = unit_type(punit)->move_rate;
+  int move_rate = 0;
+  int base_move_rate = unit_type(punit)->move_rate 
+                       + unit_type(punit)->veteran[punit->veteran].move_bonus;
 
   switch (unit_type(punit)->move_type) {
   case LAND_MOVING:
-    move_rate = (move_rate * punit->hp) / unit_type(punit)->hp;
+    move_rate = (base_move_rate * punit->hp) / unit_type(punit)->hp;
     break;
  
   case SEA_MOVING:
-    move_rate = (move_rate * punit->hp) / unit_type(punit)->hp;
+    move_rate = (base_move_rate * punit->hp) / unit_type(punit)->hp;
 
     if (player_owns_active_wonder(unit_owner(punit), B_LIGHTHOUSE)) {
       move_rate += SINGLE_MOVE;
@@ -68,20 +71,21 @@
     }
  
     if (move_rate < 2 * SINGLE_MOVE) {
-      move_rate = MIN(2 * SINGLE_MOVE, unit_type(punit)->move_rate);
+      move_rate = MIN(2 * SINGLE_MOVE, base_move_rate);
     }
     break;
 
   case HELI_MOVING:
   case AIR_MOVING:
+    move_rate = base_move_rate;
     break;
 
   default:
     die("In common/unit.c:unit_move_rate: illegal move type %d",
-       unit_type(punit)->move_type);
+                                       unit_type(punit)->move_type);
   }
   
-  if (move_rate < SINGLE_MOVE && unit_type(punit)->move_rate > 0) {
+  if (move_rate < SINGLE_MOVE && base_move_rate > 0) {
     move_rate = SINGLE_MOVE;
   }
   return move_rate;
@@ -1357,7 +1361,8 @@
 /**************************************************************************
   Like base_trireme_loss_pct but take the position into account.
 **************************************************************************/
-int trireme_loss_pct(struct player *pplayer, int x, int y)
+int trireme_loss_pct(struct player *pplayer, int x, int y,
+                    struct unit *punit)
 {
   /*
    * If we are in a city or next to land, we have no chance of losing
@@ -1368,25 +1373,24 @@
   if (map_get_terrain(x, y) != T_OCEAN || is_coastline(x, y)) {
     return 0;
   } else {
-    return base_trireme_loss_pct(pplayer);
+    return base_trireme_loss_pct(pplayer, punit);
   }
 }
 
 /**************************************************************************
- Triremes have a varying loss percentage. based on tech. Seafaring
- reduces this to 25%, Navigation to 12.5%. The Lighthouse wonder
- reduces this to 0.
+  Triremes have a varying loss percentage based on tech and veterancy
+  level.
 **************************************************************************/
-int base_trireme_loss_pct(struct player *pplayer)
+int base_trireme_loss_pct(struct player *pplayer, struct unit *punit)
 {
   if (player_owns_active_wonder(pplayer, B_LIGHTHOUSE)) {
     return 0;
   } else if (player_knows_techs_with_flag(pplayer, TF_REDUCE_TRIREME_LOSS2)) {
-    return 12;
+    return game.trireme_loss_chance[punit->veteran] / 4;
   } else if (player_knows_techs_with_flag(pplayer, TF_REDUCE_TRIREME_LOSS1)) {
-    return 25;
+    return game.trireme_loss_chance[punit->veteran] / 2;
   } else {
-    return 50;
+    return game.trireme_loss_chance[punit->veteran];
   }
 }
 
@@ -1437,7 +1441,7 @@
   to set x, y and homecity yourself.
 **************************************************************************/
 struct unit *create_unit_virtual(struct player *pplayer, struct city *pcity,
-                                 Unit_Type_id type, bool make_veteran)
+                                 Unit_Type_id type, int veteran_level)
 {
   struct unit *punit = fc_calloc(1, sizeof(struct unit));
 
@@ -1454,7 +1458,7 @@
     punit->homecity = 0;
   }
   clear_goto_dest(punit);
-  punit->veteran = make_veteran;
+  punit->veteran = veteran_level;
   punit->upkeep = 0;
   punit->upkeep_food = 0;
   punit->upkeep_gold = 0;
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.103
diff -u -r1.103 unit.h
--- common/unit.h       2003/10/29 08:00:39     1.103
+++ common/unit.h       2003/11/17 15:02:48
@@ -110,10 +110,10 @@
   int id;
   int owner;
   int x, y;                           
-  bool veteran;
   int homecity;
   int moves_left;
   int hp;
+  int veteran;
   int unhappiness;
   int upkeep;
   int upkeep_food;
@@ -271,8 +271,9 @@
 struct unit *is_non_attack_unit_tile(struct tile *ptile,
                                     struct player *pplayer);
 
-int trireme_loss_pct(struct player *pplayer, int x, int y);
-int base_trireme_loss_pct(struct player *pplayer);
+int trireme_loss_pct(struct player *pplayer, int x, int y,
+                    struct unit *punit);
+int base_trireme_loss_pct(struct player *pplayer, struct unit *punit);
 
 bool is_my_zoc(struct player *unit_owner, int x0, int y0);
 bool unit_being_aggressive(struct unit *punit);
@@ -293,7 +294,7 @@
 bool is_build_or_clean_activity(enum unit_activity activity);
 
 struct unit *create_unit_virtual(struct player *pplayer, struct city *pcity,
-                                 Unit_Type_id type, bool make_veteran);
+                                 Unit_Type_id type, int veteran_level);
 void destroy_unit_virtual(struct unit *punit);
 void free_unit_goto_route(struct unit *punit);
 
Index: common/unittype.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v
retrieving revision 1.28
diff -u -r1.28 unittype.c
--- common/unittype.c   2003/08/04 15:42:47     1.28
+++ common/unittype.c   2003/11/17 15:02:49
@@ -46,7 +46,7 @@
   "Trireme", "Nuclear", "Spy", "Transform", "Paratroopers",
   "Airbase", "Cities", "IgTired", "Missile_Carrier", "No_Land_Attack",
   "AddToCity", "Fanatic", "GameLoss", "Unique", "Unbribable", 
-  "Undisbandable", "SuperSpy", "NoHome"
+  "Undisbandable", "SuperSpy", "NoHome", "NoVeteran"
 };
 static const char *role_names[] = {
   "FirstBuild", "Explorer", "Hut", "HutTech", "Partisan",
Index: common/unittype.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.h,v
retrieving revision 1.21
diff -u -r1.21 unittype.h
--- common/unittype.h   2003/08/04 15:42:47     1.21
+++ common/unittype.h   2003/11/17 15:02:49
@@ -115,6 +115,7 @@
   F_UNDISBANDABLE,    /* Cannot be disbanded, won't easily go away */
   F_SUPERSPY,         /* Always wins diplomatic contests */
   F_NOHOME,           /* Has no homecity */
+  F_NO_VETERAN,       /* Cannot increase veteran level */
   F_LAST
 };
 #define F_MAX 64
@@ -156,6 +157,18 @@
 
 BV_DEFINE(bv_flags, F_MAX);
 BV_DEFINE(bv_roles, L_MAX);
+
+struct veteran_type {
+    /* client */
+    char name[MAX_LEN_NAME];                   /* level/rank name */
+    char short_name[MAX_LEN_VET_SHORT_NAME];    /* level/rank name symbol */
+
+    /* server */
+    double power_fact;                         /* combat/work speed/diplomatic
+                                                  power factor */
+    int move_bonus;
+};
+
 struct unit_type {
   char name[MAX_LEN_NAME];
   char name_orig[MAX_LEN_NAME];              /* untranslated */
@@ -193,6 +206,9 @@
   int paratroopers_mr_req;
   int paratroopers_mr_sub;
 
+  /* Additional values for the expanded veteran system */
+  struct veteran_type veteran[MAX_VET_LEVELS];
+  
   char *helptext;
 };
 
Index: common/aicore/pf_tools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/pf_tools.c,v
retrieving revision 1.8
diff -u -r1.8 pf_tools.c
--- common/aicore/pf_tools.c    2003/09/21 09:06:43     1.8
+++ common/aicore/pf_tools.c    2003/11/17 15:02:49
@@ -423,7 +423,7 @@
   }
 
   if (unit_flag(punit, F_TRIREME)
-      && base_trireme_loss_pct(unit_owner(punit)) > 0) {
+      && base_trireme_loss_pct(unit_owner(punit), punit) > 0) {
     parameter->turn_mode = TM_WORST_TIME;
     parameter->is_pos_dangerous = trireme_is_pos_dangerous;
   } else {
@@ -465,7 +465,7 @@
   parameter->get_zoc = NULL;
 
   if (unit_flag(punit, F_TRIREME)
-      && base_trireme_loss_pct(unit_owner(punit)) > 0) {
+      && base_trireme_loss_pct(unit_owner(punit), punit) > 0) {
     parameter->is_pos_dangerous = trireme_is_pos_dangerous;
   } else {
     parameter->is_pos_dangerous = NULL;
Index: data/civ1/units.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/civ1/units.ruleset,v
retrieving revision 1.28
diff -u -r1.28 units.ruleset
--- data/civ1/units.ruleset     2002/11/02 13:33:53     1.28
+++ data/civ1/units.ruleset     2003/11/17 15:02:50
@@ -13,6 +13,32 @@
 description="Civ1-style unit_type data for Freeciv"
 options="1.9"
 
+[veteran_system]
+; How many veteran levels?
+max_veteran_levels = 2
+
+; What are the names of the levels?
+veteran_names = _("green"), _("veteran")
+
+; The percentage chance of increasing level through combat
+veteran_raise_chance = 50, 0
+
+; Power factors are as a percentage.
+; +50% is represented by 150
+veteran_power_fact = 100, 150
+
+; The percentage chance of a settler/engineer increasing level through
+; performing useful work (per turn)
+veteran_work_raise_chance = 0, 0
+
+; The chances of a trireme being lost at sea when not adjacent to a
+; land tile.
+veteran_highseas_loss_pct = 0, 0, 0, 0
+
+; The additional number of movement points granted for different veteran
+; levels.  These are thirds of points, so to increase movement
+: by a whole point 3 must be specified.
+veteran_move_bonus = 0, 0
 
 ; Below: The individual units, one per section.
 ;
@@ -98,6 +124,7 @@
 uk_gold       = 0
 flags         = "Settlers", "NonMil", "AddToCity", "Cities"
 roles         = ""
+veteran_power_fact = 100, 100
 helptext      = _("\
 Settlers are one of the key units in the game.  They can be used to\
  found new cities, irrigate land, build roads, railroads, fortresses\
@@ -142,6 +169,7 @@
 uk_gold       = 0
 flags         = "Settlers", "NonMil", "AddToCity", "Cities"
 roles         = ""
+veteran_power_fact = 100, 100
 
 [unit_militia]
 name          = _("Militia")        ; Civ2 Warriors
@@ -1441,6 +1469,8 @@
 uk_gold       = 0
 flags         = "Diplomat", "IgZOC", "NonMil"
 roles         = "Explorer"
+veteran_power_fact = 100, 100
+veteran_raise_chance = 0, 0
 helptext      = _("\
 - A Diplomat can establish embassies with other civilizations\
  by moving into another player's city.\
@@ -1487,6 +1517,7 @@
 uk_gold       = 0
 flags         = "Diplomat", "IgZOC", "NonMil", "Spy"
 roles         = ""
+veteran_power_fact = 100, 100
 
 [unit_caravan]
 name          = _("Caravan")
Index: data/civ2/units.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/civ2/units.ruleset,v
retrieving revision 1.35
diff -u -r1.35 units.ruleset
--- data/civ2/units.ruleset     2003/02/03 00:49:04     1.35
+++ data/civ2/units.ruleset     2003/11/17 15:02:51
@@ -13,6 +13,33 @@
 description="Civ2 unit_type data for Freeciv (approximate)"
 options="1.9"
 
+[veteran_system]
+; How many veteran levels?
+max_veteran_levels = 2
+
+; What are the names of the levels?
+veteran_names = _("green"), _("veteran")
+
+; The percentage chance of increasing level through combat
+veteran_raise_chance = 50, 0
+
+; Power factors are as a percentage.
+; +50% is represented by 150
+veteran_power_fact = 100, 150
+
+; The percentage chance of a settler/engineer increasing level through
+; performing useful work (per turn)
+veteran_work_raise_chance = 0, 0
+
+; The chances of a trireme being lost at sea when not adjacent to a
+; land tile.
+veteran_highseas_loss_pct = 0, 0, 0, 0
+
+; The additional number of movement points granted for different veteran
+; levels.  These are thirds of points, so to increase movement
+: by a whole point 3 must be specified.
+veteran_move_bonus = 0, 0
+
 ; Below: The individual units, one per section.
 ;
 ; The number can be variable, up to 200.  
@@ -89,6 +116,7 @@
 uk_gold       = 0
 flags         = "Settlers", "NonMil", "Airbase", "AddToCity", "Cities"
 roles         = ""
+veteran_power_fact = 100, 100
 helptext      = _("\
 Settlers are one of the key units in the game.  They can be used to\
  found new cities, irrigate land, build roads, railroads,\
@@ -133,6 +161,7 @@
 uk_gold       = 0
 flags         = "Settlers", "NonMil", "Transform", "Airbase", "AddToCity", 
"Cities"
 roles         = ""
+veteran_power_fact = 100, 100
 helptext      = _("\
 Engineers are similar to Settlers, but they work twice as fast and\
  move twice as fast.  Engineers may also perform major terrain\
@@ -1490,6 +1519,7 @@
 uk_gold       = 0
 flags         = "Diplomat", "IgZOC", "NonMil"
 roles         = ""
+veteran_raise_chance = 0, 0
 helptext      = _("\
 - A Diplomat can establish embassies with other civilizations\
  by moving into another player's city.\
@@ -1536,6 +1566,8 @@
 uk_gold       = 0
 flags         = "Diplomat", "IgZOC", "NonMil", "Spy"
 roles         = ""
+veteran_power_fact = 100, 150
+veteran_raise_chance = 0, 0
 helptext      = _("\
 A Spy is a full time professional and as such is much more\
  skilled in the arts of espionage than her Diplomat predecessor.\
Index: data/default/units.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/units.ruleset,v
retrieving revision 1.51
diff -u -r1.51 units.ruleset
--- data/default/units.ruleset  2003/10/15 20:51:26     1.51
+++ data/default/units.ruleset  2003/11/17 15:02:52
@@ -24,6 +24,35 @@
 description="Default unit_type data for Freeciv"
 options="1.9"
 
+[veteran_system]
+; The values below are defaults applied to all units, and can be
+; overwritten by putting these fields into a unit section.
+
+; What are the names of the veteran levels?
+veteran_names = _("green"), _("veteran"), _("hardened"), _("elite"), 
+                _("elite2"), _("elite3"), _("elite4"), _("elite5"),
+                _("elite6"), _("elite7")
+
+; Power factors are as a percentage.
+; +50% is represented by 150
+veteran_power_fact = 100, 140, 175, 200
+
+; The percentage chance of increasing level through actions
+veteran_raise_chance = 75, 50, 45, 40, 40, 40, 40, 40, 40, 40
+
+; The percentage chance of a settler/engineer increasing level through
+; performing useful work (per turn)
+veteran_work_raise_chance = 7, 6, 5, 0
+
+; The chances of a trireme being lost at sea when not adjacent to a
+; land tile.
+veteran_highseas_loss_pct = 50, 40, 25, 15
+
+; The additional number of movement points granted for different veteran
+; levels.  These are thirds of points, so to increase movement
+; by a whole point 3 must be specified.
+veteran_move_bonus = 0, 0, 0, 3
+
 ; Below: The individual units, one per section.
 ;
 ; The number can be variable, up to 200.  
Index: data/isotrident/units.png
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident/units.png,v
retrieving revision 1.3
diff -u -r1.3 units.png
Binary files /tmp/cvsBBAqCainm and units.png differ
Index: data/isotrident/units.spec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident/units.spec,v
retrieving revision 1.3
diff -u -r1.3 units.spec
--- data/isotrident/units.spec  2003/11/01 10:44:23     1.3
+++ data/isotrident/units.spec  2003/11/17 15:02:54
@@ -75,4 +75,17 @@
   2, 12, "u.fanatics"
   2, 13, "u.awacs"
   2, 14, "u.worker"
+
+; Veteran Levels: up to 9 military honors for experienced units
+                                                                               
 
+  3, 0, "unit.vet_0"
+  3, 1, "unit.vet_1"
+  3, 2, "unit.vet_2"
+  3, 3, "unit.vet_3"
+  3, 4, "unit.vet_4"
+  3, 5, "unit.vet_5"
+  3, 6, "unit.vet_6"
+  3, 7, "unit.vet_7"
+  3, 8, "unit.vet_8"
+  3, 9, "unit.vet_9"
 }
Index: data/trident/tiles.png
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident/tiles.png,v
retrieving revision 1.2
diff -u -r1.2 tiles.png
Binary files /tmp/cvsDBAsCainm and tiles.png differ
Index: data/trident/tiles.spec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident/tiles.spec,v
retrieving revision 1.12
diff -u -r1.12 tiles.spec
--- data/trident/tiles.spec     2003/10/13 21:24:54     1.12
+++ data/trident/tiles.spec     2003/11/17 15:02:56
@@ -454,6 +454,19 @@
  17,  8, "city.t_food_8"
  17,  9, "city.t_food_9"
 
+; Veteran Levels: up to 9 military honors for experienced units
+                                                                               
 
+ 17, 10, "unit.vet_0"
+ 17, 11, "unit.vet_1"
+ 17, 12, "unit.vet_2"
+ 17, 13, "unit.vet_3"
+ 17, 14, "unit.vet_4"
+ 17, 15, "unit.vet_5"
+ 17, 16, "unit.vet_6"
+ 17, 17, "unit.vet_7"
+ 17, 18, "unit.vet_8"
+ 17, 19, "unit.vet_9"
+
  15,  0, "city.t_shields_0"
  15,  1, "city.t_shields_1"
  15,  2, "city.t_shields_2"
Index: server/airgoto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/airgoto.c,v
retrieving revision 1.4
diff -u -r1.4 airgoto.c
--- server/airgoto.c    2003/02/21 13:23:09     1.4
+++ server/airgoto.c    2003/11/17 15:02:56
@@ -371,7 +371,7 @@
 bool find_air_first_destination(struct unit *punit,
                                        int *dest_x, int *dest_y)
 { 
-  unsigned int fullmoves = unit_type(punit)->move_rate / SINGLE_MOVE;
+  unsigned int fullmoves = unit_move_rate(punit) / SINGLE_MOVE;
   unsigned int fullfuel = unit_type(punit)->fuel;
   unsigned int moves_and_fuel_left 
     = punit->moves_left / SINGLE_MOVE + fullmoves * (punit->fuel - 1);
Index: server/autoattack.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/autoattack.c,v
retrieving revision 1.48
diff -u -r1.48 autoattack.c
--- server/autoattack.c 2003/09/17 02:57:21     1.48
+++ server/autoattack.c 2003/11/17 15:02:56
@@ -258,7 +258,7 @@
     if(punit->ai.control
        && is_military_unit(punit)
        && punit->activity == ACTIVITY_GOTO
-       && punit->moves_left == unit_type(punit)->move_rate) {
+       && punit->moves_left == unit_move_rate(punit)) {
       (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
     }
   }
Index: server/barbarian.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/barbarian.c,v
retrieving revision 1.70
diff -u -r1.70 barbarian.c
--- server/barbarian.c  2003/10/08 16:56:07     1.70
+++ server/barbarian.c  2003/11/17 15:02:57
@@ -208,7 +208,7 @@
 
   for (i = 0; i < unit_cnt; i++) {
     unit = find_a_unit_type(L_BARBARIAN, L_BARBARIAN_TECH);
-    (void) create_unit(barbarians, x, y, unit, FALSE, 0, -1);
+    (void) create_unit(barbarians, x, y, unit, 0, 0, -1);
     freelog(LOG_DEBUG, "Created barbarian unit %s", unit_types[unit].name);
   }
 
@@ -247,7 +247,7 @@
            }
            if (is_free_sea(xu, yu, barbarians)) {
               boat = find_a_unit_type(L_BARBARIAN_BOAT, -1);
-             (void) create_unit(barbarians, xu, yu, boat, FALSE, 0, -1);
+             (void) create_unit(barbarians, xu, yu, boat, 0, 0, -1);
              xb = xu; yb = yu;
              break;
            }
@@ -385,26 +385,26 @@
     }
     for (i = 0; i < myrand(3) + uprise * game.barbarianrate; i++) {
       unit = find_a_unit_type(L_BARBARIAN, L_BARBARIAN_TECH);
-      (void) create_unit(barbarians, xu, yu, unit, FALSE, 0, -1);
+      (void) create_unit(barbarians, xu, yu, unit, 0, 0, -1);
       freelog(LOG_DEBUG, "Created barbarian unit %s", unit_types[unit].name);
     }
     (void) create_unit(barbarians, xu, yu,
-                      get_role_unit(L_BARBARIAN_LEADER, 0), FALSE, 0, -1);
+                      get_role_unit(L_BARBARIAN_LEADER, 0), 0, 0, -1);
   } else {                   /* sea raiders - their units will be veteran */
     struct unit *punit, *ptrans;
 
     barbarians = create_barbarian_player(FALSE);
     boat = find_a_unit_type(L_BARBARIAN_BOAT,-1);
-    ptrans = create_unit(barbarians, xu, yu, boat, TRUE, 0, -1);
+    ptrans = create_unit(barbarians, xu, yu, boat, 0, 0, -1);
     cap = get_transporter_capacity(unit_list_get(&map_get_tile(xu, yu)->units, 
0));
     for (i = 0; i < cap-1; i++) {
       unit = find_a_unit_type(L_BARBARIAN_SEA,L_BARBARIAN_SEA_TECH);
-      punit = create_unit(barbarians, xu, yu, unit, TRUE, 0, -1);
+      punit = create_unit(barbarians, xu, yu, unit, 0, 0, -1);
       punit->transported_by = ptrans->id;
       freelog(LOG_DEBUG, "Created barbarian unit %s", unit_types[unit].name);
     }
     punit = create_unit(barbarians, xu, yu,
-                       get_role_unit(L_BARBARIAN_LEADER, 0), FALSE, 0, -1);
+                       get_role_unit(L_BARBARIAN_LEADER, 0), 0, 0, -1);
     punit->transported_by = ptrans->id;
   }
 
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.241
diff -u -r1.241 citytools.c
--- server/citytools.c  2003/11/16 20:57:32     1.241
+++ server/citytools.c  2003/11/17 15:02:58
@@ -508,20 +508,31 @@
 /**************************************************************************
   Will unit of this type be created as veteran?
 **************************************************************************/
-bool do_make_unit_veteran(struct city *pcity, Unit_Type_id id)
+int do_make_unit_veteran(struct city *pcity, Unit_Type_id id)
 {
+  /* we current don't have any wonder or building that have influence on 
+     settler/worker units */
+  if (unit_type_flag(id, F_SETTLERS) || unit_type_flag(id, F_CITIES)) {
+    return 0;
+  }
+  
   if (unit_type_flag(id, F_DIPLOMAT)) {
-    return government_has_flag(get_gov_pcity(pcity), G_BUILD_VETERAN_DIPLOMAT);
+    return (government_has_flag(get_gov_pcity(pcity), 
+                                G_BUILD_VETERAN_DIPLOMAT) ? 1 : 0);
   }
-
+    
   if (is_ground_unittype(id) || improvement_variant(B_BARRACKS) == 1) {
-    return city_got_barracks(pcity);
-  } else if (is_water_unit(id)) {
-    return (city_affected_by_wonder(pcity, B_LIGHTHOUSE)
-            || city_got_building(pcity, B_PORT));
+    return (city_got_barracks(pcity) ? 1 : 0);
   } else {
-    return city_got_building(pcity, B_AIRPORT);
+    if (is_water_unit(id)) {
+      return ((city_affected_by_wonder(pcity, B_LIGHTHOUSE)
+               || city_got_building(pcity, B_PORT)) ? 1 : 0);
+    } else {
+      return (city_got_building(pcity, B_AIRPORT) ? 1 : 0);
+    }
   }
+  
+  return 0;
 }
 
 /**************************************************************************
@@ -706,12 +717,12 @@
   int dist = -1;
   struct city *rcity = NULL;
   city_list_iterate(pplayer->cities, pcity)
-    if ((real_map_distance(x, y, pcity->x, pcity->y) < dist || dist == -1) && 
-       (!sea_required || is_ocean_near_tile(pcity->x, pcity->y)) &&
-       (!pexclcity || (pexclcity != pcity))) {
+    if ((real_map_distance(x, y, pcity->x, pcity->y) < dist || dist == -1) &&
+        (!sea_required || is_ocean_near_tile(pcity->x, pcity->y)) &&
+        (!pexclcity || (pexclcity != pcity))) {
       dist = real_map_distance(x, y, pcity->x, pcity->y);
       rcity = pcity;
-    }      
+    }
   city_list_iterate_end;
 
   return rcity;
Index: server/citytools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.h,v
retrieving revision 1.47
diff -u -r1.47 citytools.h
--- server/citytools.h  2003/07/20 20:41:39     1.47
+++ server/citytools.h  2003/11/17 15:02:58
@@ -39,7 +39,7 @@
 int settler_eats(struct city *pcity);
 bool is_building_other_wonder(struct city *pc);
 bool built_elsewhere(struct city *pc, int wonder);
-bool do_make_unit_veteran(struct city *pcity, Unit_Type_id id);
+int do_make_unit_veteran(struct city *pcity, Unit_Type_id id);
 int city_shield_bonus(struct city *pcity);
 int city_science_bonus(struct city *pcity);
 int city_tax_bonus(struct city *pcity);
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.44
diff -u -r1.44 diplomats.c
--- server/diplomats.c  2003/10/27 14:34:31     1.44
+++ server/diplomats.c  2003/11/17 15:02:59
@@ -39,9 +39,10 @@
 /****************************************************************************/
 
 static void diplomat_charge_movement (struct unit *pdiplomat, int x, int y);
-static bool diplomat_success_vs_defender(struct unit *pdefender);
-static bool diplomat_infiltrate_city (struct player *pplayer, struct player 
*cplayer,
-                                    struct unit *pdiplomat, struct city 
*pcity);
+static bool diplomat_success_vs_defender(struct unit *patt, struct unit *pdef,
+                                               struct tile *pdefender_tile);
+static bool diplomat_infiltrate_tile(struct player *pplayer, struct player 
*cplayer,
+                                    struct unit *pdiplomat, int x, int y);
 static void diplomat_escape (struct player *pplayer, struct unit *pdiplomat,
                             struct city *pcity);
 static void maybe_cause_incident(enum diplomat_actions action, struct player 
*offender,
@@ -78,8 +79,10 @@
     return;
 
   /* Check if the Diplomat/Spy succeeds against defending Diplomats/Spies. */
-  if (!diplomat_infiltrate_city (pplayer, cplayer, pdiplomat, pcity))
+  if (!diplomat_infiltrate_tile(pplayer, cplayer, pdiplomat, 
+                                pcity->x, pcity->y)) {
     return;
+  }
 
   freelog (LOG_DEBUG, "poison: infiltrated");
 
@@ -348,6 +351,12 @@
     return;
   }
 
+  /* Check if the Diplomat/Spy succeeds against defending Diplomats/Spies. */
+  if (!diplomat_infiltrate_tile(pplayer, uplayer, pdiplomat, 
+                                pvictim->x, pvictim->y)) {
+    return;
+  }
+
   freelog (LOG_DEBUG, "sabotage-unit: succeeded");
 
   /* Sabotage the unit by removing half its remaining hit points. */
@@ -391,7 +400,8 @@
 {
   struct player *uplayer;
   int diplomat_id, victim_x, victim_y;
-
+  bool vet = FALSE;
+  
   /* Fetch target unit's player.  Sanity checks. */
   if (!pvictim)
     return;
@@ -444,11 +454,15 @@
                          pdiplomat->homecity, pvictim->moves_left,
                          pvictim->hp);
 
+  /* Check if the unit gained veteran level */
+  vet = maybe_make_veteran(pdiplomat);
+  
   /* Notify everybody involved. */
   notify_player_ex(pplayer, pvictim->x, pvictim->y, E_MY_DIPLOMAT_BRIBE,
-                  _("Game: Your %s succeeded in bribing %s's %s."),
+                  _("Game: Your %s succeeded in bribing %s's %s%s"),
                   unit_name(pdiplomat->type),
-                  unit_owner(pvictim)->name, unit_name(pvictim->type));
+                  unit_owner(pvictim)->name, unit_name(pvictim->type),
+                  vet ? " and became more experienced." : ".");
   notify_player_ex(uplayer, pvictim->x, pvictim->y, E_ENEMY_DIPLOMAT_BRIBE,
                   _("Game: Your %s was bribed by %s."),
                   unit_name(pvictim->type), pplayer->name);
@@ -518,8 +532,10 @@
     technology = game.num_tech_types;
 
   /* Check if the Diplomat/Spy succeeds against defending Diplomats/Spies. */
-  if (!diplomat_infiltrate_city (pplayer, cplayer, pdiplomat, pcity))
+  if (!diplomat_infiltrate_tile(pplayer, cplayer, pdiplomat, 
+                                pcity->x, pcity->y)) {
     return;
+  }
 
   freelog (LOG_DEBUG, "steal-tech: infiltrated");
 
@@ -757,8 +773,10 @@
   }
 
   /* Check if the Diplomat/Spy succeeds against defending Diplomats/Spies. */
-  if (!diplomat_infiltrate_city (pplayer, cplayer, pdiplomat, pcity))
+  if (!diplomat_infiltrate_tile(pplayer, cplayer, pdiplomat, 
+                                pcity->x, pcity->y)) {
     return;
+  }
 
   freelog (LOG_DEBUG, "incite: infiltrated");
 
@@ -862,8 +880,10 @@
     improvement = B_LAST;
 
   /* Check if the Diplomat/Spy succeeds against defending Diplomats/Spies. */
-  if (!diplomat_infiltrate_city (pplayer, cplayer, pdiplomat, pcity))
+  if (!diplomat_infiltrate_tile(pplayer, cplayer, pdiplomat, 
+                                pcity->x, pcity->y)) {
     return;
+  }
 
   freelog (LOG_DEBUG, "sabotage: infiltrated");
 
@@ -1072,54 +1092,72 @@
 
   - Return TRUE if the "attacker" succeeds.
 **************************************************************************/
-static bool diplomat_success_vs_defender (struct unit *pdefender)
+static bool diplomat_success_vs_defender (struct unit *pattacker, 
+       struct unit *pdefender, struct tile *pdefender_tile)
 {
-  int success = game.diplchance;
+  int att = game.diplchance;
+  int def = 100 - game.diplchance;
 
   if (unit_flag(pdefender, F_SUPERSPY)) {
     return TRUE;
   }
-
+  if (unit_flag (pattacker, F_SPY)) {
+    att *= 2;
+  }
   if (unit_flag (pdefender, F_SPY)) {
-    if (success > 66) {
-      success -= (100 - success);
-    } else {
-      success -= (success / 2);
-    }
+    def *= 2;
   }
 
-  if (pdefender->veteran) {
-    if (success >= 50) {
-      success -= ((100 - success) / 2);
-    } else {
-      success -= (success / 2);
+  att += (att/5.0) * pattacker->veteran;
+  def += (def/5.0) * pdefender->veteran;
+
+  if (pdefender_tile->city) {
+    if (city_got_building(pdefender_tile->city, B_PALACE)) {
+      def = (def * 3) / 2;/* +50% */
+    }
+  } else {
+    if (tile_has_special(pdefender_tile, S_FORTRESS)
+       || tile_has_special(pdefender_tile, S_AIRBASE)) {
+       def = (def * 5) / 4;/* +25% */ 
     }
   }
-
-  return (myrand (100) < success);
+  
+  return myrand(att) > myrand(def);
 }
 
 /**************************************************************************
-  This determines if a diplomat/spy succeeds in infiltrating a city.
+  This determines if a diplomat/spy succeeds in infiltrating a tile.
 
   - The infiltrator must go up against each defender.
   - One or the other is eliminated in each contest.
 
   - Return TRUE if the infiltrator succeeds.
 **************************************************************************/
-static bool diplomat_infiltrate_city (struct player *pplayer, struct player 
*cplayer,
-                             struct unit *pdiplomat, struct city *pcity)
+static bool diplomat_infiltrate_tile(struct player *pplayer, struct player 
*cplayer,
+                             struct unit *pdiplomat, int x, int y)
 {
-  unit_list_iterate ((map_get_tile (pcity->x, pcity->y))->units, punit)
+  struct tile *ptile = map_get_tile (x, y);
+  struct city *pcity = ptile->city;
+      
+  unit_list_iterate((map_get_tile(pcity->x, pcity->y))->units, punit) {
     if (unit_flag(punit, F_DIPLOMAT) || unit_flag(punit, F_SUPERSPY)) {
       /* A F_SUPERSPY unit may not acutally be a spy, but a superboss which 
          we cannot allow puny diplomats from getting the better of. Note that 
          diplomat_success_vs_defender(punit) is always TRUE if the attacker
          is F_SUPERSPY. Hence F_SUPERSPY vs F_SUPERSPY in a diplomatic contest
          always kills the attacker. */
-      if (diplomat_success_vs_defender(punit) && !unit_flag(punit, 
F_SUPERSPY)) {
+      if (diplomat_success_vs_defender(pdiplomat, punit, ptile) 
+          && !unit_flag(punit, F_SUPERSPY)) {
        /* Defending Spy/Diplomat dies. */
 
+       notify_player_ex(cplayer, x, y, E_MY_DIPLOMAT_FAILED,
+                        _("Game: Your %s has been eliminated defending %s"
+                          " against a %s."), unit_name(punit->type),
+               (pcity ? pcity->name : ""), unit_name(pdiplomat->type));
+       notify_player_ex(pplayer, x, y, E_ENEMY_DIPLOMAT_FAILED,
+                _("Game: An enemy %s has been eliminated defending %s."),
+               unit_name(punit->type), (pcity ? pcity->name : ""));
+
        notify_player_ex(cplayer, pcity->x, pcity->y, E_MY_DIPLOMAT_FAILED,
                         _("Game: Your %s has been eliminated defending"
                           " against a %s in %s."), unit_name(punit->type),
@@ -1132,24 +1170,28 @@
         pdiplomat->moves_left = MAX(0, pdiplomat->moves_left - SINGLE_MOVE);
         return FALSE;
       } else {
+       /* Check to see if defending unit became more experienced */
+       bool vet = maybe_make_veteran(punit);
+       
        /* Attacking Spy/Diplomat dies. */
 
-       notify_player_ex(pplayer, pcity->x, pcity->y, E_MY_DIPLOMAT_FAILED,
+       notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_FAILED,
                         _("Game: Your %s was eliminated"
-                          " by a defending %s in %s."),
-                        unit_name(pdiplomat->type), unit_name(punit->type),
-                        pcity->name);
-       notify_player_ex(cplayer, pcity->x, pcity->y,
+                          " by a defending %s."),
+                        unit_name(pdiplomat->type), unit_name(punit->type));
+       notify_player_ex(cplayer, x, y,
                         E_ENEMY_DIPLOMAT_FAILED,
-                        _("Game: Eliminated %s %s while infiltrating %s."),
+                        _("Game: Eliminated %s %s while infiltrating %s%s"),
                         get_nation_name(pplayer->nation),
-                        unit_name(pdiplomat->type), pcity->name);
+                        unit_name(pdiplomat->type),
+                        (pcity ? pcity->name : _("our troops")),
+                        vet ? ". The defender became more experienced" : ".");
 
        wipe_unit(pdiplomat);
        return FALSE;
       }
     }
-  unit_list_iterate_end;
+  } unit_list_iterate_end;
 
   return TRUE;
 }
@@ -1158,8 +1200,8 @@
   This determines if a diplomat/spy survives and escapes.
   If "pcity" is NULL, assume action was in the field.
 
-  - A Diplomat always dies.
-  - A Spy has a game.diplchance change of survival:
+  - Spies and Diplomats have a game.diplchance specified chance of 
+    survival (better if veteran):
     - Escapes to home city.
     - Escapee may become a veteran.
 **************************************************************************/
@@ -1167,68 +1209,58 @@
                      struct city *pcity)
 {
   int x, y;
-
-  if (unit_flag (pdiplomat, F_SPY)) {
-    if (pcity) {
-      x = pcity->x;
-      y = pcity->y;
-    } else {
-      x = pdiplomat->x;
-      y = pdiplomat->y;
-    }
-
-    if (myrand (100) < game.diplchance || unit_flag(pdiplomat, F_SUPERSPY)) {
-      /* Attacking Spy/Diplomat survives. */
-
-      struct city *spyhome = find_city_by_id (pdiplomat->homecity);
-
-      /* It may never have had a homecity */
-      if (!spyhome) {
-       spyhome = find_closest_owned_city(pplayer, pdiplomat->x, pdiplomat->y,
-                                         FALSE, NULL);
-      }
-
-      if (!spyhome) {
-       send_unit_info (pplayer, pdiplomat);
-       freelog(LOG_ERROR, "Bug in diplomat_escape: Unhomed Spy.");
-       return;
-      }
+  int escapechance;
+  bool vet;
+  struct city *spyhome;
 
-      notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_ESCAPE,
+  escapechance = game.diplchance + pdiplomat->veteran * 5;
+  
+  if (pcity) {
+    x = pcity->x;
+    y = pcity->y;
+  } else {
+    x = pdiplomat->x;
+    y = pdiplomat->y;
+  }
+  
+  /* find closest city for escape target */
+  spyhome = find_closest_owned_city(unit_owner(pdiplomat), x, y, FALSE, NULL);
+      
+  if (spyhome 
+      && (myrand (100) < escapechance || unit_flag(pdiplomat, F_SUPERSPY))) {
+    /* Attacking Spy/Diplomat survives. */
+
+    /* may become a veteran */
+    vet = maybe_make_veteran(pdiplomat);
+    
+    notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_ESCAPE,
                       _("Game: Your %s has successfully completed"
-                        " her mission and returned unharmed to %s."),
-                      unit_name(pdiplomat->type), spyhome->name);
+                        " her mission and returned unharmed to %s%s"),
+                      unit_name(pdiplomat->type), spyhome->name,
+                      vet ? " and has become more experienced." : ".");
 
-      /* may become a veteran */
-      maybe_make_veteran (pdiplomat);
-
-      /* being teleported costs all movement */
-      if (!teleport_unit_to_city (pdiplomat, spyhome, -1, FALSE)) {
-       send_unit_info (pplayer, pdiplomat);
-       freelog(LOG_ERROR, "Bug in diplomat_escape: Spy can't teleport.");
-       return;
-      }
-
+    /* being teleported costs all movement */
+    if (!teleport_unit_to_city (pdiplomat, spyhome, -1, FALSE)) {
+      send_unit_info (pplayer, pdiplomat);
+      freelog(LOG_ERROR, "Bug in diplomat_escape: Spy can't teleport.");
       return;
-    } else {
-      /* Attacking Spy/Diplomat dies. */
+    }
 
-      if (pcity) {
-       notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_FAILED,
+    return;
+  } else {
+    if (pcity) {
+      notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_FAILED,
                         _("Game: Your %s was captured after completing"
                           " her mission in %s."),
                         unit_name(pdiplomat->type), pcity->name);
-      } else {
-       notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_FAILED,
+    } else {
+      notify_player_ex(pplayer, x, y, E_MY_DIPLOMAT_FAILED,
                         _("Game: Your %s was captured after completing"
                           " her mission."), unit_name(pdiplomat->type));
-      }
-
-      /* fall through */
     }
   }
 
-  wipe_unit (pdiplomat);
+  wipe_unit(pdiplomat);
 }
 
 /**************************************************************************
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.176
diff -u -r1.176 gotohand.c
--- server/gotohand.c   2003/10/21 17:20:47     1.176
+++ server/gotohand.c   2003/11/17 15:03:00
@@ -288,7 +288,7 @@
   /* FIXME: Should this apply only to F_CITIES units? -- jjm */
   if (punit
       && unit_flag(punit, F_SETTLERS)
-      && unit_type(punit)->move_rate==3)
+      && unit_move_rate(punit)==3)
     maxcost /= 2;
   /* (?) was punit->type == U_SETTLERS -- dwp */
 
@@ -312,12 +312,12 @@
            continue;
        } else if (is_ocean(ptile->terrain)) {
          int base_cost = get_tile_type(map_get_terrain(x1, y1))->movement_cost 
* SINGLE_MOVE;
-         move_cost = igter ? MOVE_COST_ROAD : MIN(base_cost, 
unit_type(punit)->move_rate);
+         move_cost = igter ? MOVE_COST_ROAD : MIN(base_cost, 
unit_move_rate(punit));
         } else if (igter)
          /* NOT c = 1 (Syela) [why not? - Thue] */
          move_cost = (ptile->move_cost[dir] != 0 ? SINGLE_MOVE : 0);
         else if (punit)
-         move_cost = MIN(ptile->move_cost[dir], unit_type(punit)->move_rate);
+         move_cost = MIN(ptile->move_cost[dir], unit_move_rate(punit));
        /* else c = ptile->move_cost[k]; 
           This led to a bad bug where a unit in a swamp was considered too far 
away */
         else { /* we have a city */
@@ -648,11 +648,11 @@
            move_cost = 3;
        } else if (is_ocean(psrctile->terrain)) {
          int base_cost = get_tile_type(pdesttile->terrain)->movement_cost * 
SINGLE_MOVE;
-         move_cost = igter ? 1 : MIN(base_cost, unit_type(punit)->move_rate);
+         move_cost = igter ? 1 : MIN(base_cost, unit_move_rate(punit));
        } else if (igter)
          move_cost = (psrctile->move_cost[dir] != 0 ? SINGLE_MOVE : 0);
        else
-         move_cost = MIN(psrctile->move_cost[dir], 
unit_type(punit)->move_rate);
+         move_cost = MIN(psrctile->move_cost[dir], unit_move_rate(punit));
 
        if (!pplayer->ai.control && !map_is_known(x1, y1, pplayer)) {
          /* Don't go into the unknown. 5*SINGLE_MOVE is an arbitrary 
deterrent. */
@@ -712,8 +712,8 @@
            && !same_pos(x1, y1, dest_x, dest_y)) {
          continue;
        }
-       else if (unit_flag(punit, F_TRIREME)
-                && trireme_loss_pct(unit_owner(punit), x1, y1) > 0) {
+       else if (unit_flag(punit, F_TRIREME) &&
+                trireme_loss_pct(unit_owner(punit), x1, y1, punit) > 0) {
          move_cost = 2*SINGLE_MOVE+1;
        } else {
          move_cost = SINGLE_MOVE;
@@ -749,7 +749,7 @@
            && total_cost >= punit->moves_left - 
(get_transporter_capacity(punit) >
                              unit_type(punit)->attack_strength ? 3 : 2)
            && enemies_at(punit, x1, y1)) {
-         total_cost += unit_type(punit)->move_rate;
+         total_cost += unit_move_rate(punit);
          freelog(LOG_DEBUG, "%s#%d@(%d,%d) dissuaded from (%d,%d) -> (%d,%d)",
                  unit_type(punit)->name, punit->id,
                  punit->x, punit->y, x1, y1, dest_x, dest_y);
@@ -874,7 +874,7 @@
                            const int dest_x, const int dest_y)
 {
 #define UNIT_DEFENSE(punit, x, y, defence_multiplier) \
-  ((get_virtual_defense_power(U_LAST, (punit)->type, (x), (y), FALSE, FALSE) *\
+  ((get_virtual_defense_power(U_LAST, (punit)->type, (x), (y), FALSE, 0) *\
     (defence_multiplier)) / 2)
 
 #define UNIT_RATING(punit, x, y, defence_multiplier) \
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.155
diff -u -r1.155 ruleset.c
--- server/ruleset.c    2003/10/02 17:54:58     1.155
+++ server/ruleset.c    2003/11/17 15:03:02
@@ -153,7 +153,7 @@
      section_file_load() may call datafilename() for includes. */
 
   sz_strlcpy(sfilename, dfilename);
-  
+
   if (!section_file_load(file,sfilename)) {
     freelog(LOG_FATAL, _("Could not load ruleset file \"%s\"."), sfilename);
     exit(EXIT_FAILURE);
@@ -674,15 +674,160 @@
 {
   char *datafile_options;
   struct unit_type *u;
-  int i, j, ival, nval;
+  int i, j, ival, nval, vet_levels, vet_levels_default;
   char *sval, **slist, **sec;
   const char *filename = secfile_filename(file);
+  char **vnlist, **def_vnlist;
+  int *vblist, *def_vblist;
 
   datafile_options =
     check_ruleset_capabilities(file, "+1.9", filename);
 
+  /*
+   * Load up expanded veteran system values.
+   */
   sec = secfile_get_secnames_prefix(file, "unit_", &nval);
 
+#define CHECK_VETERAN_LIMIT                                         \
+if (vet_levels_default > MAX_VET_LEVELS || vet_levels > MAX_VET_LEVELS) { \
+  freelog(LOG_FATAL, "Too many veteran levels, %d is the maximum!", \
+          MAX_VET_LEVELS);                                          \
+  exit(EXIT_FAILURE);                                               \
+}                                                                   \
+
+  /* level names */
+  def_vnlist = secfile_lookup_str_vec(file, &vet_levels_default,
+                               "veteran_system.veteran_names");
+
+  unit_type_iterate(i) {
+    u = &unit_types[i];
+
+    vnlist = secfile_lookup_str_vec(file, &vet_levels,
+                                    "%s.veteran_names", sec[i]);
+    CHECK_VETERAN_LIMIT
+    if (vnlist) {
+      /* unit has own veterancy settings */
+      for (j = 0; j < vet_levels; j++) {
+        sz_strlcpy(u->veteran[j].name, vnlist[j]);
+      }
+      free(vnlist);
+    } else {
+      /* apply defaults */  
+      for (j = 0; j < vet_levels_default; j++) {
+        sz_strlcpy(u->veteran[j].name, def_vnlist[j]);
+      }
+    }
+    /* We check for this value to determine how many veteran levels
+     * a unit type has */
+    for (; j < MAX_VET_LEVELS; j++) {
+      u->veteran[j].name[0] = '\0';
+    }
+  } unit_type_iterate_end;
+  free(def_vnlist);
+
+  /* short names */
+  def_vnlist = secfile_lookup_str_vec(file, &vet_levels_default,
+                                      "veteran_system.veteran_short_names");
+  
+  unit_type_iterate(i) {
+    u = &unit_types[i];
+          
+    vnlist = secfile_lookup_str_vec(file, &vet_levels,
+                                    "%s.veteran_short_names", sec[i]);
+    CHECK_VETERAN_LIMIT
+    if (vnlist) {
+      /* unit has own veterancy settings */
+      for (j = 0; j < vet_levels; j++) {
+        sz_strlcpy(u->veteran[j].short_name, vnlist[j]);
+      }
+      free(vnlist);
+    } else {
+      /* apply defaults */  
+      for (j = 0; j < vet_levels_default; j++) {
+        sz_strlcpy(u->veteran[j].short_name, def_vnlist[j]);
+      }
+    }
+  } unit_type_iterate_end;
+  free(def_vnlist);
+
+  /* power factor */
+  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
+                                      "veteran_system.veteran_power_fact");
+  unit_type_iterate(i) {
+    u = &unit_types[i];
+    vblist = secfile_lookup_int_vec(file, &vet_levels,
+                                    "%s.veteran_power_fact", sec[i]);
+    CHECK_VETERAN_LIMIT
+    if (vblist) {
+      for (j = 0; j < vet_levels; j++) {
+        u->veteran[j].power_fact = ((double)vblist[j]) / 100;
+      }
+      free(vblist);
+    } else {
+      for (j = 0; j < vet_levels_default; j++) {
+        u->veteran[j].power_fact = ((double)def_vblist[j]) / 100;
+      }
+    }
+  } unit_type_iterate_end;
+  if (def_vblist) {
+    free(def_vblist);
+  }
+
+  /* raise chance */
+  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
+                                      "veteran_system.veteran_raise_chance");
+  CHECK_VETERAN_LIMIT
+  for (i = 0; i < vet_levels_default; i++) {
+    game.veteran_chance[i] = def_vblist[i];
+  }
+  for (; i < MAX_VET_LEVELS; i++) {
+    game.veteran_chance[i] = 0;
+  }
+
+  /* work raise chance */
+  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
+                                    
"veteran_system.veteran_work_raise_chance");
+  CHECK_VETERAN_LIMIT
+  for (i = 0; i < vet_levels_default; i++) {
+    game.work_veteran_chance[i] = def_vblist[i];
+  }
+  for (; i < MAX_VET_LEVELS; i++) {
+    game.work_veteran_chance[i] = 0;
+  }
+
+  /* highseas loss pct */
+  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
+                       "veteran_system.veteran_highseas_loss_pct");
+  for (i = 0; i < vet_levels_default; i++) {
+    game.trireme_loss_chance[i] = def_vblist[i];
+  }
+  for (; i < MAX_VET_LEVELS; i++) {
+    game.trireme_loss_chance[i] = 50; /* default */
+  }
+  
+  /* move bonus */
+  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
+                                      "veteran_system.veteran_move_bonus");
+  unit_type_iterate(i) {
+    u = &unit_types[i];
+    vblist = secfile_lookup_int_vec(file, &vet_levels,
+                       "%s.veteran_move_bonus", sec[i]);
+    CHECK_VETERAN_LIMIT
+    if (vblist) {
+      for (j = 0; j < vet_levels_default; j++) {
+        u->veteran[j].move_bonus = vblist[j];
+      }
+      free(vblist);
+    } else {
+      for (j = 0; j < vet_levels; j++) {
+        u->veteran[j].move_bonus = def_vblist[j];
+      }
+    }
+  } unit_type_iterate_end;
+  if (def_vblist) {
+    free(def_vblist);
+  }
+  
   /* Tech requirement is used to flag removed unit_types, which
      we might want to know for other fields.  After this we
      can use unit_type_exists()
@@ -692,7 +837,7 @@
     u->tech_requirement = lookup_tech(file, sec[i], "tech_req",
                                      FALSE, filename, u->name);
   } unit_type_iterate_end;
-
+  
   unit_type_iterate(i) {
     u = &unit_types[i];
     if (unit_type_exists(i)) {
@@ -2544,6 +2689,7 @@
     packet.paratroopers_range = u->paratroopers_range;
     packet.paratroopers_mr_req = u->paratroopers_mr_req;
     packet.paratroopers_mr_sub = u->paratroopers_mr_sub;
+    memcpy(packet.veteran, u->veteran, sizeof(packet.veteran));
     packet.helptext = u->helptext;   /* pointer assignment */
 
     lsend_packet_ruleset_unit(dest, &packet);
@@ -2849,7 +2995,7 @@
   misc_p.granary_food_inc = game.rgame.granary_food_inc;
   misc_p.tech_cost_style = game.rgame.tech_cost_style;
   misc_p.tech_leakage = game.rgame.tech_leakage;
-
+    
   assert(sizeof(misc_p.global_init_techs) ==
         sizeof(game.rgame.global_init_techs));
   assert(ARRAY_SIZE(misc_p.global_init_techs) ==
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.140
diff -u -r1.140 savegame.c
--- server/savegame.c   2003/10/27 14:25:24     1.140
+++ server/savegame.c   2003/11/17 15:03:04
@@ -1005,7 +1005,7 @@
 
     punit = create_unit_virtual(plr, NULL, 
                   secfile_lookup_int(file, "player%d.u%d.type", plrno, i),
-                  secfile_lookup_bool(file, "player%d.u%d.veteran", plrno, i));
+                  secfile_lookup_int(file, "player%d.u%d.veteran", plrno, i));
     punit->id=secfile_lookup_int(file, "player%d.u%d.id", plrno, i);
     alloc_id(punit->id);
     idex_register_unit(punit);
@@ -1469,7 +1469,7 @@
     secfile_insert_int(file, punit->id, "player%d.u%d.id", plrno, i);
     secfile_insert_int(file, punit->x, "player%d.u%d.x", plrno, i);
     secfile_insert_int(file, punit->y, "player%d.u%d.y", plrno, i);
-    secfile_insert_bool(file, punit->veteran, "player%d.u%d.veteran", 
+    secfile_insert_int(file, punit->veteran, "player%d.u%d.veteran", 
                                plrno, i);
     secfile_insert_bool(file, punit->foul, "player%d.u%d.foul", 
                                plrno, i);
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.175
diff -u -r1.175 settlers.c
--- server/settlers.c   2003/10/21 17:27:43     1.175
+++ server/settlers.c   2003/11/17 15:03:05
@@ -1496,7 +1496,7 @@
   }
 
   /* Create a localized "virtual" unit to do operations with. */
-  virtualunit = create_unit_virtual(pplayer, pcity, unit_type, FALSE);
+  virtualunit = create_unit_virtual(pplayer, pcity, unit_type, 0);
   virtualunit->x = pcity->x;
   virtualunit->y = pcity->y;
   want = evaluate_city_building(virtualunit, &gx, &gy, &ferryboat);
@@ -1536,7 +1536,7 @@
   }
 
   /* Create a localized "virtual" unit to do operations with. */
-  virtualunit = create_unit_virtual(pplayer, pcity, unit_type, FALSE);
+  virtualunit = create_unit_virtual(pplayer, pcity, unit_type, 0);
   virtualunit->x = pcity->x;
   virtualunit->y = pcity->y;
   want = evaluate_improvements(virtualunit, &best_act, &gx, &gy);
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.278
diff -u -r1.278 unithand.c
--- server/unithand.c   2003/11/13 19:41:10     1.278
+++ server/unithand.c   2003/11/17 15:03:06
@@ -657,6 +657,7 @@
   int def_x = pdefender->x, def_y = pdefender->y;
   struct packet_unit_info unit_att_full_packet, unit_def_full_packet;
   struct packet_short_unit unit_att_short_packet, unit_def_short_packet;
+  int old_unit_vet, old_defender_vet, vet;
 
   freelog(LOG_DEBUG, "Start attack: %s's %s against %s's %s.",
          pplayer->name, unit_type(punit)->name, 
@@ -699,6 +700,8 @@
   moves_used = unit_move_rate(punit) - punit->moves_left;
   def_moves_used = unit_move_rate(pdefender) - pdefender->moves_left;
 
+  old_unit_vet = punit->veteran;
+  old_defender_vet = pdefender->veteran;
   unit_versus_unit(punit, pdefender);
 
   /* Adjust attackers moves_left _after_ unit_versus_unit() so that
@@ -732,12 +735,15 @@
     punit->moves_left = 0;
   pwinner = (punit->hp > 0) ? punit : pdefender;
   plooser = (pdefender->hp > 0) ? punit : pdefender;
-    
+
+  vet = (pwinner->veteran == ((punit->hp > 0) ? old_unit_vet :
+       old_defender_vet)) ? 0 : 1;
+
   combat.attacker_unit_id=punit->id;
   combat.defender_unit_id=pdefender->id;
   combat.attacker_hp=punit->hp;
   combat.defender_hp=pdefender->hp;
-  combat.make_winner_veteran=pwinner->veteran?1:0;
+  combat.make_winner_veteran=vet;
 
   package_unit(punit, &unit_att_full_packet, FALSE);
   package_unit(pdefender, &unit_def_full_packet, FALSE);
@@ -795,11 +801,12 @@
     notify_player_ex(unit_owner(pwinner),
                     pwinner->x, pwinner->y, E_UNIT_WIN,
                     _("Game: Your %s%s survived the pathetic attack"
-                      " from %s's %s."),
+                      " from %s's %s%s"),
                     unit_name(pwinner->type),
                     get_location_str_in(unit_owner(pwinner),
                                         pwinner->x, pwinner->y),
-                    unit_owner(plooser)->name, unit_name(plooser->type));
+                    unit_owner(plooser)->name, unit_name(plooser->type),
+                    vet ? " and became more experienced!" : ".");
     
     notify_player_ex(unit_owner(plooser),
                     def_x, def_y, E_UNIT_LOST_ATT,
@@ -821,10 +828,11 @@
     notify_player_ex(unit_owner(pwinner), punit->x, punit->y,
                     E_UNIT_WIN_ATT,
                     _("Game: Your attacking %s succeeded"
-                      " against %s's %s%s!"), unit_name(pwinner->type),
+                      " against %s's %s%s%s"), unit_name(pwinner->type),
                     unit_owner(plooser)->name, unit_name(plooser->type),
-                    get_location_str_at(unit_owner(pwinner), plooser->x,
-                                        plooser->y));
+                    get_location_str_at(unit_owner(pwinner),
+                    plooser->x, plooser->y),
+                    vet ? " and became more experienced!" : "!");
     kill_unit(pwinner, plooser);
                /* no longer pplayer - want better msgs -- Syela */
   }
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.264
diff -u -r1.264 unittools.c
--- server/unittools.c  2003/11/15 11:32:45     1.264
+++ server/unittools.c  2003/11/17 15:03:08
@@ -104,18 +104,34 @@
 }
 
 /**************************************************************************
-  after a battle this routine is called to decide whether or not the unit
-  should become a veteran, if unit isn't already.
-  there is a 50/50% chance for it to happend, (100% if player got SUNTZU)
-**************************************************************************/
-void maybe_make_veteran(struct unit *punit)
-{
-  if (punit->veteran)
-    return;
-  if (player_owns_active_wonder(unit_owner(punit), B_SUNTZU))
-    punit->veteran = TRUE;
-  else
-    punit->veteran = (myrand(2) == 1);
+  After a battle, after diplomatic aggression and after surviving trireme
+  loss chance, this routine is called to decide whether or not the unit
+  should become more experienced.
+
+  There is a specified chance for it to happen, (+50% if player got SUNTZU)
+  the chances are specified in the units.ruleset file.
+**************************************************************************/
+bool maybe_make_veteran(struct unit *punit)
+{
+  if (punit->veteran + 1 >= MAX_VET_LEVELS
+      || unit_type(punit)->veteran[punit->veteran].name[0] == '\0'
+      || unit_flag(punit, F_NO_VETERAN)) {
+    return FALSE;
+  }
+  if (is_ground_unittype(punit->id)
+      && player_owns_active_wonder(get_player(punit->owner), B_SUNTZU)) {
+    if (myrand(100) < 1.5 * game.veteran_chance[punit->veteran]) {
+      punit->veteran++;
+      return TRUE;
+    }
+  } else {
+    if (myrand(100) < game.veteran_chance[punit->veteran]) {
+      punit->veteran++;
+      return TRUE;
+    }
+  }
+
+  return FALSE;  
 }
 
 /**************************************************************************
@@ -248,7 +264,7 @@
             unit_type(punit)->name,
             get_unit_type(upgrade_type)->name,
             get_location_str_in(pplayer, punit->x, punit->y));
-      punit->veteran = FALSE;
+      punit->veteran = 0;
       upgrade_unit(punit, upgrade_type);
     }
     i++;
@@ -437,18 +453,27 @@
     }
 
     /* 4) Check that triremes are near coastline, otherwise... */
-    if (unit_flag(punit, F_TRIREME)
-       && myrand(100) < trireme_loss_pct(pplayer, punit->x, punit->y)) {
-      notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_LOST, 
-                      _("Game: Your %s has been lost on the high seas."),
-                      unit_name(punit->type));
-      gamelog(GAMELOG_UNITTRI, _("%s Trireme lost at sea"),
-             get_nation_name_plural(pplayer->nation));
-      wipe_unit(punit);
-      continue; /* Continue iterating... */
+    if (unit_flag(punit, F_TRIREME)) {
+      if (myrand(100) < trireme_loss_pct(pplayer, punit->x, punit->y, punit)) {
+        notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_LOST, 
+                         _("Game: Your %s has been lost on the high seas."),
+                         unit_name(punit->type));
+        gamelog(GAMELOG_UNITTRI, _("%s's %s lost at sea"),
+               get_nation_name_plural(pplayer->nation), 
+                unit_name(punit->type));
+        wipe_unit(punit);
+        continue; /* Continue iterating... */
+      } else {
+        if (maybe_make_veteran(punit)) {
+         notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_BECAME_VET,
+                           _("Game: Your %s survived on the high seas "
+                          "and became more experienced."), 
+                           unit_name(punit->type));
+        }
+      }
     }
 
-    /* 5) Resque planes if needed */
+    /* 5) Rescue planes if needed */
     if (is_air_unit(punit)) {
       /* Shall we emergency return home on the last vapors? */
 
@@ -635,6 +660,31 @@
 }
 
 /**************************************************************************
+  Returns the speed of a settler.
+**************************************************************************/
+int get_settler_speed(struct unit *punit) {
+   return (10 * unit_type(punit)->veteran[punit->veteran].power_fact);
+}
+
+/***************************************************************************
+  Maybe settler/worker gains a veteran level?
+****************************************************************************/
+static bool maybe_settler_become_veteran(struct unit *punit)
+{
+  if (punit->veteran + 1 >= MAX_VET_LEVELS
+      || unit_type(punit)->veteran[punit->veteran].name[0] == '\0'
+      || unit_flag(punit, F_NO_VETERAN)) {
+    return FALSE;
+  }
+  if (unit_flag(punit, F_SETTLERS)
+      && myrand(100) <= game.work_veteran_chance[punit->veteran]) {
+    punit->veteran++;
+    return TRUE;
+  }
+  return FALSE;  
+}
+
+/**************************************************************************
   progress settlers in their current tasks, 
   and units that is pillaging.
   also move units that is on a goto.
@@ -644,12 +694,12 @@
 {
   struct player *pplayer = unit_owner(punit);
   int id = punit->id;
-  int mr = unit_type(punit)->move_rate;
+  int mr = unit_move_rate(punit);
   bool unit_activity_done = FALSE;
   enum unit_activity activity = punit->activity;
   enum ocean_land_change solvency = OLC_NONE;
   struct tile *ptile = map_get_tile(punit->x, punit->y);
-
+  
   if (activity != ACTIVITY_IDLE && activity != ACTIVITY_FORTIFIED
       && activity != ACTIVITY_GOTO && activity != ACTIVITY_EXPLORE
       && activity != ACTIVITY_PATROL) {
@@ -659,10 +709,23 @@
        * To allow a settler to begin a task with no moves left without
        * it counting toward the time to finish 
        */
-      punit->activity_count += mr / SINGLE_MOVE;
+
+      /* update settler activity 
+       * note that all activity costs are multiplied
+       * by a factor of 10. */
+      punit->activity_count +=
+             (mr * get_settler_speed(punit)) / SINGLE_MOVE;
     } else if (mr == 0) {
-      punit->activity_count += 1;
+      punit->activity_count += get_settler_speed(punit);
     }
+
+    /* settler may become veteran when doing something useful */
+    if (activity != ACTIVITY_FORTIFYING && activity != ACTIVITY_SENTRY
+       && maybe_settler_become_veteran(punit)) {
+      notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_BECAME_VET,
+       _("Game: Your %s became more experienced."), unit_name(punit->type));
+    }
+    
   }
 
   unit_restore_movepoints(pplayer, punit);
@@ -1148,7 +1211,7 @@
       continue;
     if (unit_list_size(&ptile->units) > 0)
       continue;
-    value = get_virtual_defense_power(U_LAST, u_type, x1, y1, FALSE, FALSE);
+    value = get_virtual_defense_power(U_LAST, u_type, x1, y1, FALSE, 0);
     value *= 10;
 
     if (ptile->continent != map_get_continent(pcity->x, pcity->y)) {
@@ -1177,7 +1240,7 @@
 
   while ((count--) > 0 && find_a_good_partisan_spot(pcity, u_type, &x, &y)) {
     struct unit *punit;
-    punit = create_unit(city_owner(pcity), x, y, u_type, FALSE, 0, -1);
+    punit = create_unit(city_owner(pcity), x, y, u_type, 0, 0, -1);
     if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
       punit->activity = ACTIVITY_FORTIFIED; /* yes; directly fortified */
       send_unit_info(NULL, punit);
@@ -1455,6 +1518,11 @@
   punit->hp = MAX(punit->hp * unit_type(punit)->hp / old_hp, 1);
   punit->moves_left = punit->moves_left * unit_move_rate(punit) / old_mr;
 
+  /* decrease veteran level by 1 */
+  if (punit->veteran > 0) {
+    punit->veteran--;
+  }
+
   conn_list_do_buffer(&pplayer->connections);
 
   /* apply new vision range */
@@ -1475,10 +1543,10 @@
   Wrapper of the below
 *************************************************************************/
 struct unit *create_unit(struct player *pplayer, int x, int y, 
-                         Unit_Type_id type, bool make_veteran, 
+                         Unit_Type_id type, int veteran_level, 
                          int homecity_id, int moves_left)
 {
-  return create_unit_full(pplayer, x, y, type, make_veteran, homecity_id, 
+  return create_unit_full(pplayer, x, y, type, veteran_level, homecity_id, 
                           moves_left, -1);
 }
 
@@ -1487,10 +1555,10 @@
   lists.
 **************************************************************************/
 struct unit *create_unit_full(struct player *pplayer, int x, int y,
-                             Unit_Type_id type, bool veteran, 
+                             Unit_Type_id type, int veteran_level, 
                               int homecity_id, int moves_left, int hp_left)
 {
-  struct unit *punit = create_unit_virtual(pplayer, NULL, type, veteran);
+  struct unit *punit = create_unit_virtual(pplayer, NULL, type, veteran_level);
   struct city *pcity;
 
   /* Register unit */
@@ -2355,7 +2423,7 @@
                     _("Game: Friendly nomads are impressed by you,"
                       " and join you."));
     (void) create_unit(pplayer, punit->x, punit->y, get_role_unit(F_CITIES,0),
-               FALSE, punit->homecity, -1);
+               0, punit->homecity, -1);
   }
 }
 
Index: server/unittools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.h,v
retrieving revision 1.57
diff -u -r1.57 unittools.h
--- server/unittools.h  2003/10/08 16:56:07     1.57
+++ server/unittools.h  2003/11/17 15:03:08
@@ -23,7 +23,7 @@
 
 /* battle related */
 int find_a_unit_type(int role, int role_tech);
-void maybe_make_veteran(struct unit *punit);
+bool maybe_make_veteran(struct unit *punit);
 void unit_versus_unit(struct unit *attacker, struct unit *defender);
 
 /* move check related */
@@ -34,6 +34,7 @@
 /* turn update related */
 void player_restore_units(struct player *pplayer);
 void update_unit_activities(struct player *pplayer);
+int get_settler_speed(struct unit *punit);
 
 /* various */
 char *get_location_str_in(struct player *pplayer, int x, int y);
@@ -53,9 +54,9 @@
 /* creation/deletion/upgrading */
 void upgrade_unit(struct unit *punit, Unit_Type_id to_unit);
 struct unit *create_unit(struct player *pplayer, int x, int y, Unit_Type_id 
type,
-                        bool make_veteran, int homecity_id, int moves_left);
+                        int veteran_level, int homecity_id, int moves_left);
 struct unit *create_unit_full(struct player *pplayer, int x, int y,
-                             Unit_Type_id type, bool make_veteran, int 
homecity_id,
+                             Unit_Type_id type, int veteran_level, int 
homecity_id,
                              int moves_left, int hp_left);
 void wipe_unit(struct unit *punit);
 void wipe_unit_spec_safe(struct unit *punit, bool wipe_cargo);

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#4044) veteran level patch, Per I. Mathisen <=