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

Here are the three patches for this ticket and its two children:
#39450: Make unit_type etc names available in the scripting api
  api_class_names_v3.diff
#39451: Add signal emit to scripting api
  techsig_v1.diff
#17187: Move hut code into lua script
  hut_v3.diff

Applies to trunk r13103
They are interdependent and should be applied in from top to bottom. I
used git to sort out the interlocking patches, apply to test with
cat ../api_class_names_v3.diff ../techsig_v1.diff ../hut_v3.diff  |
patch -p1
The patches can and should be checked in in succession, none of them
break the build.

Name api changes:
Now we have:
:rule_name()
:name_translation()
and for Nation_Type there is also:
:plural_translation()

Techsig changes:
the api action give_technology now takes a reason string as well; a
script signal with
the given reason is sent; it was decided in #39451 that the signal
events are so fundamental that scripts should not directly emit them.

Hut changes:
Ported hut_get_barbarian as noted in previous emails. unleash_barbarians
is available as an api action, as noted before.

Introduced hut_get_limited for ai players with handicap H_LIMITEDHUTS;
we cannot put this in the script file without passing irrelevant
parameters to the hut_entered signal callback, or opening ai handicaps
etc to the script api.

hut_get_limited is a simplified version of the previous behavior; 25
gold is given as before, but with 1/12 chance the unit is simply wiped
(normally unleash_barbarians) would be called; but as the wipe is the
most common outcome this was simplified.

One hut issue remains: Only Legions are given as mercenaries. This can
be solved by porting a method to find a unittype for role, or simplified
now that different rulesets can customize by script. 

Ready for comments
diff --git a/server/scripting/api.pkg b/server/scripting/api.pkg
index 6f0af93..d8a5986 100644
--- a/server/scripting/api.pkg
+++ b/server/scripting/api.pkg
@@ -94,16 +94,28 @@ struct Terrain {
 
 
 /* Class methods. */
+
+/* Player */
 int api_methods_player_num_cities
 	@ methods_player_num_cities (Player *pplayer);
 int api_methods_player_num_units
 	@ methods_player_num_units (Player *pplayer);
 
-bool api_methods_unit_type_has_flag
-	@ methods_unit_type_has_flag (Unit_Type *punit_type, const char *flag);
-bool api_methods_unit_type_has_role
-	@ methods_unit_type_has_role (Unit_Type *punit_type, const char *role);
-
+/* Government */
+const char *api_methods_government_rule_name
+	@ methods_government_rule_name (Government *pgovernment);
+const char *api_methods_government_name_translation
+	@ methods_government_name_translation (Government *pgovernment);
+
+/* Nation_Type */
+const char *api_methods_nation_type_rule_name
+	@ methods_nation_type_rule_name (Nation_Type *pnation);
+const char *api_methods_nation_type_name_translation
+	@ methods_nation_type_name_translation (Nation_Type *pnation);
+const char *api_methods_nation_type_plural_translation
+	@ methods_nation_type_plural_translation (Nation_Type *pnation);
+
+/* Building_Type */
 bool api_methods_building_type_is_wonder
 	@ methods_building_type_is_wonder (Building_Type *pbuilding);
 bool api_methods_building_type_is_great_wonder
@@ -112,7 +124,32 @@ bool api_methods_building_type_is_small_wonder
 	@ methods_building_type_is_small_wonder (Building_Type *pbuilding);
 bool api_methods_building_type_is_improvement
 	@ methods_building_type_is_improvement (Building_Type *pbuilding);
+const char *api_methods_building_type_rule_name
+	@ methods_building_type_rule_name (Building_Type *pbuilding);
+const char *api_methods_building_type_name_translation
+	@ methods_building_type_name_translation (Building_Type *pbuilding);
 
+/* Unit_Type */
+bool api_methods_unit_type_has_flag
+	@ methods_unit_type_has_flag (Unit_Type *punit_type, const char *flag);
+bool api_methods_unit_type_has_role
+	@ methods_unit_type_has_role (Unit_Type *punit_type, const char *role);
+const char *api_methods_unit_type_rule_name
+	@ methods_unit_type_rule_name (Unit_Type *punit_type);
+const char *api_methods_unit_type_name_translation
+	@ methods_unit_type_name_translation (Unit_Type *punit_type);
+
+/* Tech_Type */
+const char *api_methods_tech_type_rule_name
+	@ methods_tech_type_rule_name (Tech_Type *ptech);
+const char *api_methods_tech_type_name_translation
+	@ methods_tech_type_name_translation (Tech_Type *ptech);
+
+/* Terrain */
+const char *api_methods_terrain_rule_name
+	@ methods_terrain_rule_name (Terrain *pterrain);
+const char *api_methods_terrain_name_translation
+	@ methods_terrain_name_translation (Terrain *pterrain);
 
 $[
 -- Player methods.
@@ -133,6 +170,28 @@ function Unit:homecity()
   return find.city(self.owner, self.homecity_id)
 end
 
+-- Government methods
+function Government:rule_name()
+  return methods_government_rule_name(self)
+end
+
+function Government:name_translation()
+  return methods_government_name_translation(self)
+end
+
+-- Nation_Type methods
+function Nation_Type:rule_name()
+  return methods_nation_type_rule_name(self)
+end
+
+function Nation_Type:name_translation()
+  return methods_nation_type_name_translation(self)
+end
+
+function Nation_Type:plural_translation()
+  return methods_nation_type_plural_translation(self)
+end
+
 -- Building_Type methods.
 function Building_Type:build_shield_cost()
   return self.build_cost
@@ -154,6 +213,14 @@ function Building_Type:is_improvement()
   return methods_building_type_is_improvement(self)
 end
 
+function Building_Type:rule_name()
+  return methods_building_type_rule_name(self)
+end
+
+function Building_Type:name_translation()
+  return methods_building_type_name_translation(self)
+end
+
 -- Unit_Type methods.
 function Unit_Type:build_shield_cost()
   return self.build_cost
@@ -166,6 +233,32 @@ end
 function Unit_Type:has_role(role)
   return methods_unit_type_has_role(self, role)
 end
+
+function Unit_Type:rule_name()
+  return methods_unit_type_rule_name(self)
+end
+
+function Unit_Type:name_translation()
+  return methods_unit_type_name_translation(self)
+end
+
+-- Tech_Type methods
+function Tech_Type:rule_name()
+  return methods_tech_type_rule_name(self)
+end
+
+function Tech_Type:name_translation()
+  return methods_tech_type_name_translation(self)
+end
+
+-- Terrain methods
+function Terrain:rule_name()
+  return methods_terrain_rule_name(self)
+end
+
+function Terrain:name_translation()
+  return methods_terrain_name_translation(self)
+end
 $]
 
 /* Object find module. */
diff --git a/server/scripting/api_methods.c b/server/scripting/api_methods.c
index 896c49b..dc8580b 100644
--- a/server/scripting/api_methods.c
+++ b/server/scripting/api_methods.c
@@ -15,7 +15,13 @@
 #include <config.h>
 #endif
 
+#include "government.h"
+#include "improvement.h"
+#include "nation.h"
+#include "tech.h"
+#include "terrain.h"
 #include "unitlist.h"
+#include "unittype.h"
 
 #include "api_methods.h"
 #include "script.h"
@@ -98,4 +104,107 @@ bool api_methods_building_type_is_improvement(Building_Type *pbuilding)
   return is_improvement(pbuilding->index);
 }
 
+/**************************************************************************
+  Return rule name for Government
+**************************************************************************/
+const char *api_methods_government_rule_name(Government *pgovernment)
+{
+  return government_rule_name(pgovernment);
+}
+
+/**************************************************************************
+  Return translated name for Government
+**************************************************************************/
+const char *api_methods_government_name_translation(Government *pgovernment)
+{
+  return government_name_translation(pgovernment);
+}
+
+/**************************************************************************
+  Return rule name for Nation_Type
+**************************************************************************/
+const char *api_methods_nation_type_rule_name(Nation_Type *pnation)
+{
+  return nation_rule_name(pnation);
+}
+
+/**************************************************************************
+  Return translated name for Nation_Type
+**************************************************************************/
+const char *api_methods_nation_type_name_translation(Nation_Type *pnation)
+{
+  return nation_name_translation(pnation);
+}
+
+/**************************************************************************
+  Return translated plural name for Nation_Type
+**************************************************************************/
+const char *api_methods_nation_type_plural_translation(Nation_Type *pnation)
+{
+  return nation_plural_translation(pnation);
+}
 
+/**************************************************************************
+  Return rule name for Building_Type
+**************************************************************************/
+const char *api_methods_building_type_rule_name(Building_Type *pbuilding)
+{
+  return improvement_rule_name(pbuilding->index);
+}
+
+/**************************************************************************
+  Return translated name for Building_Type
+**************************************************************************/
+const char *api_methods_building_type_name_translation(Building_Type 
+                                                       *pbuilding)
+{
+  return improvement_name_translation(pbuilding->index);
+}
+
+/**************************************************************************
+  Return rule name for Unit_Type
+**************************************************************************/
+const char *api_methods_unit_type_rule_name(Unit_Type *punit_type)
+{
+  return utype_rule_name(punit_type);
+}
+
+/**************************************************************************
+  Return translated name for Unit_Type
+**************************************************************************/
+const char *api_methods_unit_type_name_translation(Unit_Type *punit_type)
+{
+  return utype_name_translation(punit_type);
+}
+
+/**************************************************************************
+  Return rule name for Tech_Type
+**************************************************************************/
+const char *api_methods_tech_type_rule_name(Tech_Type *ptech)
+{
+  return advance_rule_name(ptech->index);
+}
+
+/**************************************************************************
+  Return translated name for Tech_Type
+**************************************************************************/
+const char *api_methods_tech_type_name_translation(Tech_Type *ptech)
+{
+  return advance_name_translation(ptech->index);
+}
+
+/**************************************************************************
+  Return rule name for Terrain
+**************************************************************************/
+const char *api_methods_terrain_rule_name(Terrain *pterrain)
+{
+  return terrain_rule_name(pterrain);
+}
+
+/**************************************************************************
+  Return translated name for Terrain
+**************************************************************************/
+const char *api_methods_terrain_name_translation(Terrain *pterrain)
+{
+  return terrain_name_translation(pterrain);
+}
diff --git a/server/scripting/api_methods.h b/server/scripting/api_methods.h
index 8bb74e0..22d9d8e 100644
--- a/server/scripting/api_methods.h
+++ b/server/scripting/api_methods.h
@@ -27,5 +27,21 @@ bool api_methods_building_type_is_great_wonder(Building_Type *pbuilding);
 bool api_methods_building_type_is_small_wonder(Building_Type *pbuilding);
 bool api_methods_building_type_is_improvement(Building_Type *pbuilding);
 
+/* rule name and translated name methods */
+const char *api_methods_government_rule_name(Government *pgovernment);
+const char *api_methods_government_name_translation(Government *pgovernment);
+const char *api_methods_nation_type_rule_name(Nation_Type *pnation);
+const char *api_methods_nation_type_name_translation(Nation_Type *pnation);
+const char *api_methods_nation_type_plural_translation(Nation_Type
+                                                       *pnation);
+const char *api_methods_building_type_rule_name(Building_Type *pbuilding);
+const char *api_methods_building_type_name_translation(Building_Type 
+                                                       *pbuilding);
+const char *api_methods_unit_type_rule_name(Unit_Type *punit_type);
+const char *api_methods_unit_type_name_translation(Unit_Type *punit_type);
+const char *api_methods_tech_type_rule_name(Tech_Type *ptech);
+const char *api_methods_tech_type_name_translation(Tech_Type *ptech);
+const char *api_methods_terrain_rule_name(Terrain *pterrain);
+const char *api_methods_terrain_name_translation(Terrain *pterrain);
 #endif
 
diff --git a/server/scripting/api.pkg b/server/scripting/api.pkg
index d8a5986..3eee83d 100644
--- a/server/scripting/api.pkg
+++ b/server/scripting/api.pkg
@@ -494,5 +494,6 @@ void api_actions_create_city @ create_city (Player *pplayer, Tile *ptile,
 					    const char *name);
 void api_actions_change_gold @ change_gold (Player *pplayer, int amount);
 Tech_Type *api_actions_give_technology @ give_technology (Player *pplayer,
-						    Tech_Type *ptech);
+						    Tech_Type *ptech,
+						    const char *reason);
 
diff --git a/server/scripting/api_actions.c b/server/scripting/api_actions.c
index 61600bf..ad93f9c 100644
--- a/server/scripting/api_actions.c
+++ b/server/scripting/api_actions.c
@@ -21,6 +21,7 @@
 #include "unittools.h"
 
 #include "api_find.h"
+#include "script_signal.h"
 
 #include "api_actions.h"
 
@@ -59,10 +60,13 @@ void api_actions_change_gold(Player *pplayer, int amount)
   Give pplayer technology ptech.  Quietly returns A_NONE (zero) if 
   player already has this tech; otherwise returns the tech granted.
   Use NULL for ptech to grant a random tech.
+  sends script signal "tech_researched" with the given reason
 **************************************************************************/
-Tech_Type *api_actions_give_technology(Player *pplayer, Tech_Type *ptech)
+Tech_Type *api_actions_give_technology(Player *pplayer, Tech_Type *ptech,
+                                       const char *reason)
 {
   Tech_type_id id;
+  Tech_Type *result;
 
   if (ptech) {
     id = ptech->index;
@@ -76,7 +80,11 @@ Tech_Type *api_actions_give_technology(Player *pplayer, Tech_Type *ptech)
   if (get_invention(pplayer, id) != TECH_KNOWN) {
     do_free_cost(pplayer, id);
     found_new_tech(pplayer, id, FALSE, TRUE);
-    return api_find_tech_type(id);
+    result = api_find_tech_type(id);
+    script_signal_emit("tech_researched", 3,
+                       API_TYPE_TECH_TYPE, result, API_TYPE_PLAYER, pplayer,
+                       API_TYPE_STRING, reason);
+    return result;
   } else {
     return api_find_tech_type(A_NONE);
   }
diff --git a/server/scripting/api_actions.h b/server/scripting/api_actions.h
index 135340c..4273ea1 100644
--- a/server/scripting/api_actions.h
+++ b/server/scripting/api_actions.h
@@ -21,7 +21,8 @@ Unit *api_actions_create_unit(Player *pplayer, Tile *ptile, Unit_Type *ptype,
 			      int moves_left);
 void api_actions_create_city(Player *pplayer, Tile *ptile, const char *name);
 void api_actions_change_gold(Player *pplayer, int amount);
-Tech_Type *api_actions_give_technology(Player *pplayer, Tech_Type *ptech);
+Tech_Type *api_actions_give_technology(Player *pplayer, Tech_Type *ptech,
+                                       const char *reason);
 
 #endif
 
diff --git a/data/default/script.lua b/data/default/script.lua
index 487ec59..53a59f4 100644
--- a/data/default/script.lua
+++ b/data/default/script.lua
@@ -1,8 +1,126 @@
--- Callbacks
+-- Freeciv - Copyright (C) 2007 - The Freeciv Project
+--   This program is free software; you can redistribute it and/or modify
+--   it under the terms of the GNU General Public License as published by
+--   the Free Software Foundation; either version 2, or (at your option)
+--   any later version.
+--
+--   This program is distributed in the hope that it will be useful,
+--   but WITHOUT ANY WARRANTY; without even the implied warranty of
+--   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--   GNU General Public License for more details.
+
+-- Get gold from entering a hut.
+function hut_get_gold(unit, gold)
+  local owner = unit.owner
+ 
+  notify.event(owner, unit.tile, E.HUT_GOLD, _("You found %d gold."), gold)
+  change_gold(owner, gold)
+end
+
+-- Get a tech from entering a hut.
+function hut_get_tech(unit)
+  local owner = unit.owner
+  local tech = give_technology(owner, nil, "hut")
+
+  if tech then
+    notify.event(owner, unit.tile, E.HUT_TECH,
+                 _("You found %s in ancient scrolls of wisdom."),
+                 tech:name_translation())
+    notify.embassies(owner, unit.tile, E.HUT_TECH,
+                     _("The %s have acquired %s from ancient scrolls of\
+                      wisdom."),
+                     owner.nation:plural_translation(),
+                     tech:name_translation())
+    return true
+  else
+    return false
+  end
+end
+
+-- Get a mercenary unit from entering a hut.
+function hut_get_mercenaries(unit)
+  -- FIXME: Should be able to find other types of mercenaries
+  local type = find.unit_type('Legion')
+
+  if type then
+    local owner = unit.owner
+     
+    notify.event(owner, unit.tile, E.HUT_MERC,
+                 _("A band of friendly mercenaries joins your cause."))
+    create_unit(owner, unit.tile, type, 0, unit:homecity(), -1)
+    return true
+  else
+    return false
+  end
+end
+
+-- Get new city from hut, or settlers (nomads) if terrain is poor.
+function hut_get_city(unit)
+  local owner = unit.owner
+  local settlers = find.unit_type('Settlers')
+
+  if unit:is_on_possible_city_tile() then
+    create_city(owner, unit.tile, nil)
+    notify.event(owner, unit.tile, E.HUT_CITY,
+                 _("You found a friendly city."))
+  else
+    create_unit(owner, unit.tile, settlers, 0, unit:homecity(), -1)
+    notify.event(owner, unit.tile, E.HUT_SETTLER,
+                 _("Friendly nomads are impressed by you, and join you."))
+  end
+end
+
+-- Get barbarians from hut, unless close to a city or king enters
+-- Unit may die: returns true if unit is alive
+function hut_get_barbarians(unit)
+  local tile = unit.tile
+  local type = unit.utype
+  local owner = unit.owner
+  
+  if unit.tile:city_exists_within_city_radius(true) 
+    or type:has_flag('Gameloss') then
+    notify.event(owner, unit.tile, E.HUT_BARB_CITY_NEAR,
+                 _("An abandoned village is here."))
+    return true
+  end
+  
+  local alive = unleash_barbarians(tile)
+  if alive then
+    notify.event(owner, tile, E.HUT_BARB,
+                  _("You have unleashed a horde of barbarians!"));
+  else
+    notify.event(owner, tile, E.HUT_BARB_KILLED,
+                  _("Your %s has been killed by barbarians!"),
+                  type:name_translation());
+  end
+  return alive
+end
+
+-- Randomly choose a hut event
 function hut_enter_callback(unit)
-  -- to be implemented
+  local chance = random(0, 11)
+  local alive = true
+
+  if chance == 0 then
+    hut_get_gold(unit, 25)
+  elseif chance == 1 or chance == 2 or chance == 3 then
+    hut_get_gold(unit, 50)
+  elseif chance == 4 then
+    hut_get_gold(unit, 100)
+  elseif chance == 5 or chance == 6 or chance == 7 then
+    hut_get_tech(unit)
+  elseif chance == 8 or chance == 9 then
+    if not hut_get_mercenaries(unit) then
+      hut_get_gold(unit, 25)
+    end
+  elseif chance == 10 then
+    alive = hut_get_barbarians(unit)
+  elseif chance == 11 then
+    hut_get_city(unit)
+  end
+
+  -- continue processing if unit is alive
+  return (not alive)
 end
 
--- Main code
 signal.connect("hut_enter", "hut_enter_callback")
-
diff --git a/server/barbarian.c b/server/barbarian.c
index 2ec1547..4c4e312 100644
--- a/server/barbarian.c
+++ b/server/barbarian.c
@@ -57,14 +57,6 @@
 #define BARBARIAN_INITIAL_VISION_RADIUS 3
 #define BARBARIAN_INITIAL_VISION_RADIUS_SQ 9
 
-/*
- IDEAS:
- 1. Unrest factors configurable via rulesets (distance and gov factor)
- 2. Separate nations for Sea Raiders and Land Barbarians
-
- - are these good ideas ??????
-*/
-
 /**************************************************************************
   Is player a land barbarian?
 **************************************************************************/
diff --git a/server/scripting/api.pkg b/server/scripting/api.pkg
index 3eee83d..ff8ac74 100644
--- a/server/scripting/api.pkg
+++ b/server/scripting/api.pkg
@@ -101,6 +101,14 @@ int api_methods_player_num_cities
 int api_methods_player_num_units
 	@ methods_player_num_units (Player *pplayer);
 
+/* Unit */
+bool api_methods_unit_city_can_be_built_here
+	@ methods_unit_city_can_be_built_here (Unit *punit);
+
+/* Tile */
+bool api_methods_tile_city_exists_within_city_radius
+	@ methods_tile_city_exists_within_city_radius (Tile *ptile, bool center);
+
 /* Government */
 const char *api_methods_government_rule_name
 	@ methods_government_rule_name (Government *pgovernment);
@@ -170,6 +178,15 @@ function Unit:homecity()
   return find.city(self.owner, self.homecity_id)
 end
 
+function Unit:is_on_possible_city_tile()
+  return methods_unit_city_can_be_built_here(self)
+end
+
+-- Tile methods
+function Tile:city_exists_within_city_radius(center)
+  return methods_tile_city_exists_within_city_radius(self, center)
+end
+
 -- Government methods
 function Government:rule_name()
   return methods_government_rule_name(self)
@@ -496,4 +513,4 @@ void api_actions_change_gold @ change_gold (Player *pplayer, int amount);
 Tech_Type *api_actions_give_technology @ give_technology (Player *pplayer,
 						    Tech_Type *ptech,
 						    const char *reason);
-
+bool api_unleash_barbarians @ unleash_barbarians (Tile *ptile);
diff --git a/server/scripting/api_actions.c b/server/scripting/api_actions.c
index ad93f9c..c398d2e 100644
--- a/server/scripting/api_actions.c
+++ b/server/scripting/api_actions.c
@@ -15,6 +15,7 @@
 #include <config.h>
 #endif
 
+#include "barbarian.h"
 #include "plrhand.h"
 #include "citytools.h"
 #include "techtools.h"
@@ -27,6 +28,14 @@
 
 
 /**************************************************************************
+  Unleash barbarians on a tile, for example from a hut
+**************************************************************************/
+bool api_unleash_barbarians(Tile *ptile)
+{
+  return unleash_barbarians(ptile);
+}
+
+/**************************************************************************
   Create a new unit.
 **************************************************************************/
 Unit *api_actions_create_unit(Player *pplayer, Tile *ptile, Unit_Type *ptype,
diff --git a/server/scripting/api_actions.h b/server/scripting/api_actions.h
index 4273ea1..ff0d13a 100644
--- a/server/scripting/api_actions.h
+++ b/server/scripting/api_actions.h
@@ -16,6 +16,7 @@
 
 #include "api_types.h"
 
+bool api_unleash_barbarians(Tile *ptile);
 Unit *api_actions_create_unit(Player *pplayer, Tile *ptile, Unit_Type *ptype,
 		  	      int veteran_level, City *homecity,
 			      int moves_left);
diff --git a/server/scripting/api_methods.c b/server/scripting/api_methods.c
index dc8580b..852b55f 100644
--- a/server/scripting/api_methods.c
+++ b/server/scripting/api_methods.c
@@ -27,6 +27,14 @@
 #include "script.h"
 
 /**************************************************************************
+  Can punit found a city on its tile?
+**************************************************************************/
+bool api_methods_unit_city_can_be_built_here(Unit *punit)
+{
+  return city_can_be_built_here(punit->tile, punit);
+}
+
+/**************************************************************************
   Return the number of cities pplayer has.
 **************************************************************************/
 int api_methods_player_num_cities(Player *pplayer)
@@ -73,6 +81,16 @@ bool api_methods_unit_type_has_role(Unit_Type *punit_type, const char *role)
 }
 
 /**************************************************************************
+  Return TRUE there is a city inside city radius from ptile
+**************************************************************************/
+
+bool api_methods_tile_city_exists_within_city_radius(Tile *ptile, 
+                                              bool may_be_on_center)
+{
+  return city_exists_within_city_radius(ptile, may_be_on_center);
+}
+
+/**************************************************************************
   Return TRUE if pbuilding is a wonder.
 **************************************************************************/
 bool api_methods_building_type_is_wonder(Building_Type *pbuilding)
diff --git a/server/scripting/api_methods.h b/server/scripting/api_methods.h
index 22d9d8e..1d0848d 100644
--- a/server/scripting/api_methods.h
+++ b/server/scripting/api_methods.h
@@ -16,12 +16,17 @@
 
 #include "api_types.h"
 
+bool api_methods_unit_city_can_be_built_here(Unit *punit);
+
 int api_methods_player_num_cities(Player *pplayer);
 int api_methods_player_num_units(Player *pplayer);
 
 bool api_methods_unit_type_has_flag(Unit_Type *punit_type, const char *flag);
 bool api_methods_unit_type_has_role(Unit_Type *punit_type, const char *role);
 
+bool api_methods_tile_city_exists_within_city_radius(Tile *ptile, 
+                                                     bool may_be_on_center);
+
 bool api_methods_building_type_is_wonder(Building_Type *pbuilding);
 bool api_methods_building_type_is_great_wonder(Building_Type *pbuilding);
 bool api_methods_building_type_is_small_wonder(Building_Type *pbuilding);
diff --git a/server/unittools.c b/server/unittools.c
index 52a1fef..48965eb 100644
--- a/server/unittools.c
+++ b/server/unittools.c
@@ -2242,126 +2242,45 @@ bool do_paradrop(struct unit *punit, struct tile *ptile)
 }
 
 /**************************************************************************
-  Get gold from entering a hut.
+  Give 25 Gold or kill the unit. For H_LIMITEDHUTS
+  Return TRUE if unit is alive, and FALSE if it was killed
 **************************************************************************/
-static void hut_get_gold(struct unit *punit, int cred)
+static bool hut_get_limited(struct unit *punit)
 {
-  struct player *pplayer = unit_owner(punit);
-  notify_player(pplayer, punit->tile, E_HUT_GOLD,
-		   _("You found %d gold."), cred);
-  pplayer->economic.gold += cred;
-}
-
-/**************************************************************************
-  Get a tech from entering a hut.
-**************************************************************************/
-static void hut_get_tech(struct unit *punit)
-{
-  struct player *pplayer = unit_owner(punit);
-  Tech_type_id new_tech;
-  const char* tech_name;
-  
-  new_tech = give_random_free_tech(pplayer);
-  
-  tech_name = advance_name_for_player(pplayer, new_tech);
-  notify_player(pplayer, punit->tile, E_HUT_TECH,
-		   _("You found %s in ancient scrolls of wisdom."),
-		   tech_name);
-  script_signal_emit("tech_researched", 3,
-		     API_TYPE_TECH_TYPE, &advances[new_tech],
-		     API_TYPE_PLAYER, pplayer,
-		     API_TYPE_STRING, "hut");
-  notify_embassies(pplayer, NULL, NULL, E_TECH_GAIN,
-		   _("The %s have acquired %s"
-		     " from ancient scrolls of wisdom."),
-		   nation_plural_for_player(pplayer),
-		   tech_name);
-}
-
-/**************************************************************************
-  Get a mercenary unit from entering a hut.
-**************************************************************************/
-static void hut_get_mercenaries(struct unit *punit)
-{
-  struct player *pplayer = unit_owner(punit);
-  
-  notify_player(pplayer, punit->tile, E_HUT_MERC,
-		   _("A band of friendly mercenaries joins your cause."));
-  (void) create_unit(pplayer, punit->tile,
-		     find_a_unit_type(L_HUT, L_HUT_TECH), FALSE,
-		     punit->homecity, -1);
-}
-
-/**************************************************************************
-  Get barbarians from hut, unless close to a city.
-  Unit may die: returns 1 if unit is alive after, or 0 if it was killed.
-**************************************************************************/
-static bool hut_get_barbarians(struct unit *punit)
-{
-  struct player *pplayer = unit_owner(punit);
   bool ok = TRUE;
-
-  if (city_exists_within_city_radius(punit->tile, TRUE)
-      || unit_has_type_flag(punit, F_GAMELOSS)) {
+  int hut_chance = myrand(12);
+  struct player *pplayer = unit_owner(punit);
+  /* 1 in 12 to get barbarians */
+  if (hut_chance != 0) {
+    int cred = 25;
+    notify_player(pplayer, punit->tile, E_HUT_GOLD,
+		              _("You found %d gold."), cred);
+    pplayer->economic.gold += cred;
+  } else if (city_exists_within_city_radius(punit->tile, TRUE)
+             || unit_has_type_flag(punit, F_GAMELOSS)) {
     notify_player(pplayer, punit->tile, E_HUT_BARB_CITY_NEAR,
-		     _("An abandoned village is here."));
+                  _("An abandoned village is here."));
   } else {
-    /* save coords and type in case unit dies */
-    struct tile *unit_tile = punit->tile;
     struct unit_type *type = unit_type(punit);
-
-    ok = unleash_barbarians(unit_tile);
-
-    if (ok) {
-      notify_player(pplayer, unit_tile, E_HUT_BARB,
-		       _("You have unleashed a horde of barbarians!"));
-    } else {
-      notify_player(pplayer, unit_tile, E_HUT_BARB_KILLED,
-		       _("Your %s has been killed by barbarians!"),
-		       utype_name_translation(type));
-    }
+    struct tile *tile = punit->tile;
+    wipe_unit(punit);
+    ok = FALSE;
+    notify_player(pplayer, tile, E_HUT_BARB_KILLED,
+                  _("Your %s has been killed by barbarians!"),
+                  utype_name_translation(type));
   }
   return ok;
 }
 
 /**************************************************************************
-  Get new city from hut, or settlers (nomads) if terrain is poor.
-**************************************************************************/
-static void hut_get_city(struct unit *punit)
-{
-  struct player *pplayer = unit_owner(punit);
-
-  if (city_can_be_built_here(punit->tile, punit)) {
-    notify_player(pplayer, punit->tile, E_HUT_CITY,
-		     _("You found a friendly city."));
-    create_city(pplayer, punit->tile,
-		city_name_suggestion(pplayer, punit->tile));
-
-    if (unit_has_type_flag(punit, F_CITIES) || unit_has_type_flag(punit, F_SETTLERS)) {
-      /* In case city was found during autosettler activities */
-      initialize_infrastructure_cache(pplayer);
-    }
-
-    /* Init ai.choice. Handling ferryboats might use it. */
-    init_choice(&punit->tile->city->ai.choice);
-
-  } else {
-    notify_player(pplayer, punit->tile, E_HUT_SETTLER,
-		     _("Friendly nomads are impressed by you,"
-		       " and join you."));
-    (void) create_unit(pplayer, punit->tile, get_role_unit(F_CITIES,0),
-		0, punit->homecity, -1);
-  }
-}
-
-/**************************************************************************
-  Return 1 if unit is alive, and 0 if it was killed
+  Return FALSE if unit is known killed, TRUE means no information.
+  This is due to the effects in the script signal callback can not
+  be predicted.
 **************************************************************************/
 static bool unit_enter_hut(struct unit *punit)
 {
   struct player *pplayer = unit_owner(punit);
   bool ok = TRUE;
-  int hut_chance = myrand(12);
   enum hut_behavior behavior = unit_class(punit)->hut_behavior;
   
   if (behavior == HUT_NOTHING) {
@@ -2379,41 +2298,12 @@ static bool unit_enter_hut(struct unit *punit)
   }
   
   /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
-  if (pplayer->ai.control && ai_handicap(pplayer, H_LIMITEDHUTS) 
-      && hut_chance != 10) {
-    hut_chance = 0;
+  if (pplayer->ai.control && ai_handicap(pplayer, H_LIMITEDHUTS)) {
+    return hut_get_limited(punit);
   }
 
   script_signal_emit("hut_enter", 1, API_TYPE_UNIT, punit);
 
-  switch (hut_chance) {
-  case 0:
-    hut_get_gold(punit, 25);
-    break;
-  case 1: case 2: case 3:
-    hut_get_gold(punit, 50);
-    break;
-  case 4:
-    hut_get_gold(punit, 100);
-    break;
-  case 5: case 6: case 7:
-    hut_get_tech(punit);
-    break;
-  case 8: case 9:
-    if (num_role_units(L_HUT) != 0) {
-      hut_get_mercenaries(punit);
-    } else {
-      hut_get_gold(punit, 25);
-    }
-    break;
-  case 10:
-    ok = hut_get_barbarians(punit);
-    break;
-  case 11:
-    hut_get_city(punit);
-    break;
-  }
-
   send_player_info(pplayer, pplayer);       /* eg, gold */
   return ok;
 }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to