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

Updated the patch to the latest revision trunk. 

The patch is almost ready but depends on #39450: Make rule names
available in the scripting api; right now there is no way to tell the
user "Your %s was killed by barbarians"

Expanded the patch slightly by porting hut_get_barbarians to Lua, using
a new method Tile:city_exists_within_city_radius and a new action
barbarian_uprising(tile)

Added a copyright header to the script.lua file since it now has a
substantial amount of code; I hope that it is correct.
Index: server/scripting/api_actions.h
===================================================================
--- server/scripting/api_actions.h	(revision 13086)
+++ server/scripting/api_actions.h	(arbetskopia)
@@ -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);
Index: server/scripting/api_methods.h
===================================================================
--- server/scripting/api_methods.h	(revision 13086)
+++ server/scripting/api_methods.h	(arbetskopia)
@@ -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);
Index: server/scripting/api.pkg
===================================================================
--- server/scripting/api.pkg	(revision 13086)
+++ server/scripting/api.pkg	(arbetskopia)
@@ -94,6 +94,7 @@
 
 
 /* Class methods. */
+
 int api_methods_player_num_cities
 	@ methods_player_num_cities (Player *pplayer);
 int api_methods_player_num_units
@@ -103,7 +104,12 @@
 	@ 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);
+bool api_methods_unit_city_can_be_built_here
+	@ methods_unit_city_can_be_built_here (Unit *punit);
 
+bool api_methods_tile_city_exists_within_city_radius
+	@ methods_tile_city_exists_within_city_radius (Tile *ptile, bool center);
+
 bool api_methods_building_type_is_wonder
 	@ methods_building_type_is_wonder (Building_Type *pbuilding);
 bool api_methods_building_type_is_great_wonder
@@ -133,6 +139,15 @@
   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
+
 -- Building_Type methods.
 function Building_Type:build_shield_cost()
   return self.build_cost
@@ -402,4 +417,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);
-
+bool api_unleash_barbarians @ unleash_barbarians (Tile *ptile);
Index: server/scripting/api_actions.c
===================================================================
--- server/scripting/api_actions.c	(revision 13086)
+++ server/scripting/api_actions.c	(arbetskopia)
@@ -15,6 +15,7 @@
 #include <config.h>
 #endif
 
+#include "barbarian.h"
 #include "plrhand.h"
 #include "citytools.h"
 #include "techtools.h"
@@ -26,6 +27,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,
Index: server/scripting/api_methods.c
===================================================================
--- server/scripting/api_methods.c	(revision 13086)
+++ server/scripting/api_methods.c	(arbetskopia)
@@ -21,6 +21,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)
@@ -67,6 +75,16 @@
 }
 
 /**************************************************************************
+  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)
Index: server/barbarian.c
===================================================================
--- server/barbarian.c	(revision 13086)
+++ server/barbarian.c	(arbetskopia)
@@ -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?
 **************************************************************************/
Index: server/barbarian.h
===================================================================
--- server/barbarian.h	(revision 13086)
+++ server/barbarian.h	(arbetskopia)
@@ -32,5 +32,6 @@
 bool unleash_barbarians(struct tile *ptile);
 void summon_barbarians(void);
 bool is_land_barbarian(struct player *pplayer);
+bool hut_get_barbarians(struct unit *punit);
 
 #endif  /* FC__BARBARIAN_H */
Index: server/unittools.c
===================================================================
--- server/unittools.c	(revision 13086)
+++ server/unittools.c	(arbetskopia)
@@ -2242,119 +2242,6 @@
 }
 
 /**************************************************************************
-  Get gold from entering a hut.
-**************************************************************************/
-static void hut_get_gold(struct unit *punit, int cred)
-{
-  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)) {
-    notify_player(pplayer, punit->tile, E_HUT_BARB_CITY_NEAR,
-		     _("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));
-    }
-  }
-  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
 **************************************************************************/
 static bool unit_enter_hut(struct unit *punit)
@@ -2386,34 +2273,6 @@
 
   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;
 }
Index: data/default/script.lua
===================================================================
--- data/default/script.lua	(revision 13086)
+++ data/default/script.lua	(arbetskopia)
@@ -1,8 +1,116 @@
--- 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.
+
+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
+
+function hut_get_tech(unit)
+  local owner = unit.owner
+  local tech = give_technology(owner, nil)
+
+  if tech then
+    notify.event(owner, unit.tile, E.HUT_TECH,
+                 _("You found %s in ancient scrolls of wisdom."),
+                 tech.name)
+    notify.embassies(owner, unit.tile, E.HUT_TECH,
+                     _("The %s have acquired %s from ancient scrolls of\
+                      wisdom."),
+                     owner.nation.name_plural, tech.name)
+    return true
+  else
+    return false
+  end
+end
+ 
+function hut_get_mercenaries(unit)
+  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
+ 
+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
+
+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."))
+  else
+    local alive = unleash_barbarians(tile)
+    if alive then
+      notify.event(owner, tile, E.HUT_BARB,
+                   _("You have unleashed a horde of barbarians!"));
+    else
+      -- FIXME: no type.name available
+      notify.event(owner, tile, E.HUT_BARB_KILLED,
+                   _("Your %s has been killed by barbarians!"),
+                   type.name);
+    end
+  end
+  return alive
+end
+
 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")
-
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to