[Freeciv-Dev] (PR#8754) effects patch v3
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: |
undisclosed-recipients: ; |
Subject: |
[Freeciv-Dev] (PR#8754) effects patch v3 |
From: |
"Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx> |
Date: |
Fri, 21 May 2004 15:36:23 -0700 |
Reply-to: |
rt@xxxxxxxxxxx |
<URL: http://rt.freeciv.org/Ticket/Display.html?id=8754 >
Here is the latest version of the effects patch, plus the changes
necessary to implement several building effects for reference, all in one.
diff -Nurd -X diff_ignore freecvs/client/packhand.c freeciv/client/packhand.c
--- freecvs/client/packhand.c 2004-05-21 20:28:19.960223568 +0100
+++ freeciv/client/packhand.c 2004-05-21 23:34:43.750029088 +0100
@@ -25,6 +25,7 @@
#include "capability.h"
#include "capstr.h"
+#include "eff.h"
#include "events.h"
#include "fcintl.h"
#include "game.h"
@@ -2098,6 +2099,8 @@
tilespec_free_city_tiles(game.styles_count);
ruleset_data_free();
+ eff_hash_init();
+
game.aqueduct_size = packet->aqueduct_size;
game.sewer_size = packet->sewer_size;
game.add_to_size_limit = packet->add_to_size_limit;
@@ -2934,3 +2937,31 @@
{
freelog(LOG_VERBOSE, "server shutdown");
}
+
+/**************************************************************************
+...
+**************************************************************************/
+void handle_eff_hash_group(char *name, enum effect_type eff,
+ int num_buildings, Impr_Type_id *buildings)
+{
+ struct eff_group *pgroup;
+ int i;
+
+ pgroup = eff_group_new(name, eff);
+
+ for (i = 0; i < num_buildings; i++) {
+ struct impr_type *bldg = get_improvement_type(buildings[i]);
+
+ eff_group_add(pgroup, bldg->name);
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void handle_eff_hash_effect(struct packet_eff_hash_effect *packet)
+{
+ eff_hash_add(packet->id, packet->eff, packet->op, packet->value,
+ packet->req, packet->arg, packet->group);
+}
+
diff -Nurd -X diff_ignore freecvs/common/city.c freeciv/common/city.c
--- freecvs/common/city.c 2004-05-21 20:28:20.452148784 +0100
+++ freeciv/common/city.c 2004-05-21 23:34:44.370934696 +0100
@@ -18,6 +18,7 @@
#include <assert.h>
#include <string.h>
+#include "eff.h"
#include "fcintl.h"
#include "game.h"
#include "government.h"
@@ -49,7 +50,7 @@
/* end helper functions for generic_city_refresh */
static int improvement_upkeep_asmiths(struct city *pcity, Impr_Type_id i,
- bool asmiths);
+ int asmiths);
/* Iterate a city map, from the center (the city) outwards */
@@ -491,8 +492,8 @@
return 0;
if (is_wonder(i))
return 0;
- if (improvement_types[i].upkeep == 1 &&
- city_affected_by_wonder(pcity, B_ASMITHS))
+ if (improvement_types[i].upkeep <=
+ get_city_bonus(pcity, EFT_UPKEEP_FREE))
return 0;
if (government_has_flag(get_gov_pcity(pcity), G_CONVERT_TITHES_TO_MONEY)
&& (i == B_TEMPLE || i == B_COLOSSEUM || i == B_CATHEDRAL)) {
@@ -506,13 +507,13 @@
Caller to pass asmiths = city_affected_by_wonder(pcity, B_ASMITHS)
**************************************************************************/
static int improvement_upkeep_asmiths(struct city *pcity, Impr_Type_id i,
- bool asmiths)
+ int asmiths)
{
if (!improvement_exists(i))
return 0;
if (is_wonder(i))
return 0;
- if (asmiths && improvement_types[i].upkeep == 1)
+ if (improvement_types[i].upkeep <= asmiths)
return 0;
if (government_has_flag(get_gov_pcity(pcity), G_CONVERT_TITHES_TO_MONEY)
&& (i == B_TEMPLE || i == B_COLOSSEUM || i == B_CATHEDRAL)) {
@@ -531,6 +532,7 @@
{
enum tile_special_type spec_t = map_get_special(map_x, map_y);
enum tile_terrain_type tile_t = map_get_terrain(map_x, map_y);
+ struct tile *ptile = map_get_tile(map_x, map_y);
int s;
if (contains_special(spec_t, S_SPECIAL_1)) {
@@ -554,12 +556,7 @@
int before_penalty = (is_celebrating ? g->celeb_shields_before_penalty
: g->shields_before_penalty);
- if (city_affected_by_wonder(pcity, B_RICHARDS)) {
- s++;
- }
- if (is_ocean(tile_t) && city_got_building(pcity, B_OFFSHORE)) {
- s++;
- }
+ s += get_city_tile_bonus(pcity, ptile, EFT_PROD_ADD_TILE);
/* government shield bonus & penalty */
if (s > 0) {
@@ -635,6 +632,7 @@
{
enum tile_special_type spec_t = map_get_special(map_x, map_y);
enum tile_terrain_type tile_t = map_get_terrain(map_x, map_y);
+ struct tile *ptile = map_get_tile(map_x, map_y);
int t;
if (contains_special(spec_t, S_SPECIAL_1)) {
@@ -667,14 +665,8 @@
t += (is_celebrating ? g->celeb_trade_bonus : g->trade_bonus);
}
- if (city_affected_by_wonder(pcity, B_COLLOSSUS)) {
- t++;
- }
-
- if (contains_special(spec_t, S_ROAD)
- && city_got_building(pcity, B_SUPERHIGHWAYS)) {
- t += (t * terrain_control.road_superhighway_trade_bonus) / 100;
- }
+ t += get_city_bonus(pcity, EFT_TRADE_INC_TILE);
+ t += (t * get_city_tile_bonus(pcity, ptile, EFT_TRADE_PER_TILE)) / 100;
/* government trade penalty -- SKi */
if (before_penalty > 0 && t > before_penalty) {
@@ -749,6 +741,7 @@
const enum tile_special_type spec_t = map_get_special(map_x, map_y);
const enum tile_terrain_type tile_t = map_get_terrain(map_x, map_y);
struct tile_type *type = get_tile_type(tile_t);
+ struct tile *ptile = map_get_tile(map_x, map_y);
int f;
const bool auto_water = (pcity && is_city_center(city_x, city_y)
&& tile_t == type->irrigation_result
@@ -787,9 +780,7 @@
int before_penalty = (is_celebrating ? g->celeb_food_before_penalty
: g->food_before_penalty);
- if (is_ocean(tile_t) && city_got_building(pcity, B_HARBOUR)) {
- f++;
- }
+ f += get_city_tile_bonus(pcity, ptile, EFT_FOOD_ADD_TILE);
if (f > 0) {
f += (is_celebrating ? g->celeb_food_bonus : g->food_bonus);
@@ -1044,11 +1035,11 @@
*************************************************************************/
int city_gold_surplus(struct city *pcity)
{
- bool asmiths = city_affected_by_wonder(pcity, B_ASMITHS);
int cost = 0;
built_impr_iterate(pcity, i) {
- cost += improvement_upkeep_asmiths(pcity, i, asmiths);
+ cost += improvement_upkeep_asmiths(pcity, i,
+ get_city_bonus(pcity, EFT_UPKEEP_FREE));
} built_impr_iterate_end;
unit_list_iterate(pcity->units_supported, punit) {
@@ -1104,47 +1095,18 @@
* Otherwise the player who owns the city needs to have it to
* get the effect.
*/
- if (id==B_MANHATTEN)
- return (game.global_wonders[id] != 0);
-
tmp = player_find_city_by_id(city_owner(pcity), game.global_wonders[id]);
if (!tmp)
return FALSE;
- switch (id) {
- case B_ASMITHS:
- case B_APOLLO:
- case B_CURE:
- case B_GREAT:
- case B_WALL:
- case B_HANGING:
- case B_ORACLE:
- case B_UNITED:
- case B_WOMENS:
- case B_DARWIN:
- case B_LIGHTHOUSE:
- case B_MAGELLAN:
- case B_MICHELANGELO:
- case B_SETI:
- case B_PYRAMIDS:
- case B_LIBERTY:
- case B_SUNTZU:
- return TRUE;
- case B_ISAAC:
- case B_COPERNICUS:
- case B_SHAKESPEARE:
- case B_COLLOSSUS:
- case B_RICHARDS:
- return FALSE;
- case B_HOOVER:
- case B_BACH:
- if (improvement_variant(id)==1) {
+
+ switch (get_improvement_type(id)->equiv_range) {
+ case IR_PLAYER:
+ return TRUE;
+ case IR_ISLAND:
return (map_get_continent(tmp->x, tmp->y) ==
map_get_continent(pcity->x, pcity->y));
- } else {
- return TRUE;
- }
- default:
- return FALSE;
+ default:
+ return FALSE;
}
}
@@ -1619,23 +1581,7 @@
**************************************************************************/
int get_city_shield_bonus(struct city *pcity)
{
- int shield_bonus = 100;
-
- if (city_got_building(pcity, B_FACTORY)) {
- shield_bonus += 50;
- if (city_got_building(pcity, B_MFG)) {
- shield_bonus += 50;
- }
-
- if (city_affected_by_wonder(pcity, B_HOOVER) ||
- city_got_building(pcity, B_POWER) ||
- city_got_building(pcity, B_HYDRO) ||
- city_got_building(pcity, B_NUCLEAR)) {
- shield_bonus = 100 + (3 * (shield_bonus - 100)) / 2;
- }
- }
-
- return shield_bonus;
+ return (100 + get_city_bonus(pcity, EFT_PROD_BONUS));
}
/**************************************************************************
@@ -1644,19 +1590,7 @@
**************************************************************************/
int get_city_tax_bonus(struct city *pcity)
{
- int tax_bonus = 100;
-
- if (city_got_building(pcity, B_MARKETPLACE)) {
- tax_bonus += 50;
- if (city_got_building(pcity, B_BANK)) {
- tax_bonus += 50;
- if (city_got_building(pcity, B_STOCK)) {
- tax_bonus += 50;
- }
- }
- }
-
- return tax_bonus;
+ return (100 + get_city_bonus(pcity, EFT_TAX_BONUS));
}
/**************************************************************************
@@ -1690,23 +1624,10 @@
**************************************************************************/
int get_city_science_bonus(struct city *pcity)
{
- int science_bonus = 100;
+ int science_bonus;
+
+ science_bonus = 100 + get_city_bonus(pcity, EFT_SCIENCE_BONUS);
- if (city_got_building(pcity, B_LIBRARY)) {
- science_bonus += 50;
- if (city_got_building(pcity, B_UNIVERSITY)) {
- science_bonus += 50;
- }
- if (city_got_effect(pcity, B_RESEARCH)) {
- science_bonus += 50;
- }
- }
- if (city_affected_by_wonder(pcity, B_COPERNICUS)) {
- science_bonus += 50;
- }
- if (city_affected_by_wonder(pcity, B_ISAAC)) {
- science_bonus += 100;
- }
if (government_has_flag(get_gov_pcity(pcity), G_REDUCED_RESEARCH)) {
science_bonus /= 2;
}
@@ -1957,21 +1878,11 @@
**************************************************************************/
static void citizen_happy_buildings(struct city *pcity)
{
- struct government *g = get_gov_pcity(pcity);
int faces = 0;
happy_copy(pcity, 1);
- if (city_got_building(pcity, B_TEMPLE)) {
- faces += get_temple_power(pcity);
- }
- if (city_got_building(pcity, B_COURTHOUSE) && g->corruption_level == 0) {
- faces++;
- }
+ faces += get_city_bonus(pcity, EFT_MAKE_CONTENT);
- if (city_got_building(pcity, B_COLOSSEUM))
- faces += get_colosseum_power(pcity);
- if (city_got_effect(pcity, B_CATHEDRAL))
- faces += get_cathedral_power(pcity);
/* make people content (but not happy):
get rid of angry first, then make unhappy content. */
while (faces > 0 && pcity->ppl_angry[2] > 0) {
@@ -2001,14 +1912,13 @@
**************************************************************************/
static void citizen_happy_wonders(struct city *pcity)
{
- int bonus = 0;
+ int bonus = 0, mod;
happy_copy(pcity, 3);
- if (city_affected_by_wonder(pcity, B_HANGING)) {
- bonus += 1;
- if (city_got_building(pcity, B_HANGING))
- bonus += 2;
+ if ((mod = get_city_bonus(pcity, EFT_MAKE_HAPPY)) > 0) {
+ bonus += mod;
+
while (bonus > 0 && pcity->ppl_content[4] > 0) {
pcity->ppl_content[4]--;
pcity->ppl_happy[4]++;
@@ -2017,10 +1927,9 @@
will let it make unhappy content */
}
}
- if (city_affected_by_wonder(pcity, B_BACH))
- bonus += 2;
- if (city_affected_by_wonder(pcity, B_CURE))
- bonus += 1;
+
+ bonus += get_city_bonus(pcity, EFT_FORCE_CONTENT);
+
/* get rid of angry first, then make unhappy content */
while (bonus > 0 && pcity->ppl_angry[4] > 0) {
pcity->ppl_angry[4]--;
diff -Nurd -X diff_ignore freecvs/common/eff.c freeciv/common/eff.c
--- freecvs/common/eff.c 1970-01-01 01:00:00.000000000 +0100
+++ freeciv/common/eff.c 2004-05-21 23:33:09.496357824 +0100
@@ -0,0 +1,977 @@
+/**********************************************************************
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+ 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.
+***********************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+
+#include "eff.h"
+
+#include "log.h"
+
+#include "map.h"
+#include "shared.h"
+#include "support.h"
+#include "improvement.h"
+#include "city.h"
+#include "player.h"
+#include "government.h"
+
+#include "packets.h"
+
+
+/**************************************************************************
+ The code creates an effects hash on ruleset load. This constant effects
+ hash is used to speed up all effects queries. There is no further memory
+ allocation or de-allocation by any of the code after hash creation.
+
+ Since the hash is constant, the server only needs to send effects data to
+ the client upon connect. It also means that an AI can do fast searches in
+ the effects space by trying the possible combinations of addition or
+ removal of buildings with the effects it cares about, like is done in the
+ existing code.
+
+
+ To know how much a target is being affected, simply use the convenience
+ functions:
+
+ * get_player_everlasting_bonus
+ * get_player_bonus
+ * get_city_bonus
+ * get_city_building_bonus
+ * get_city_tile_bonus
+
+ These functions require as arguments the target and the effect type to be
+ queried.
+
+ Improvements and wonders are unique and in a well known place in the
+ data structures. This allows lots of optimizations in the code.
+
+
+ === Future extensions:
+ The uniqueness aspect of a building is not as important as it being in a
+ well known place. Since a wonder is in a well known place, i.e.
+ game.global_wonders[], it is easy to find out if something is affected by
+ it or not.
+
+ This could easily be extended by turning game.global_wonders[] into a list
+ of lists of pointers to places of buildings, i.e. game.buildings[].
+
+ To add small wonder and satellite support, you can simply add a similar
+ player.buildings[] list.
+
+ These extensions would allow buildings with global and player range
+ without hard limitations in uniqueness, or type whatsoever.
+
+ The actual range of a building is separate.
+
+ Since this means one always knows where to look for a building, we
+ can have very fast queries on effects that will scale well with complex
+ effects.
+**************************************************************************/
+struct effect {
+ enum op_type op;
+ int value;
+
+ enum req_type type;
+ union {
+ Tech_Type_id tech;
+ struct government *gov;
+ Impr_Type_id building;
+ Impr_Type_id wonder;
+ enum tile_special_type special;
+ enum tile_terrain_type terrain;
+ } req;
+};
+
+#define SPECLIST_TAG eff
+#define SPECLIST_TYPE struct effect
+#include "speclist.h"
+
+#define eff_list_iterate(list, elt) \
+TYPED_LIST_ITERATE(struct effect, list, elt)
+#define eff_list_iterate_end LIST_ITERATE_END
+
+/**************************************************************************
+...
+**************************************************************************/
+#define SPECVEC_TAG building
+#define SPECVEC_TYPE Impr_Type_id
+#include "specvec.h"
+
+#define building_vector_iterate(vector, elt) \
+TYPED_VECTOR_ITERATE(Impr_Type_id, vector, elt)
+#define building_vector_iterate_end VECTOR_ITERATE_END
+
+/**************************************************************************
+...
+**************************************************************************/
+struct eff_group {
+ char *name;
+ enum effect_type eff;
+ int id;
+ struct building_vector buildings;
+};
+
+#define SPECLIST_TAG eff_group
+#define SPECLIST_TYPE struct eff_group
+#include "speclist.h"
+
+#define eff_group_list_iterate(list, elt) \
+TYPED_LIST_ITERATE(struct eff_group, list, elt)
+#define eff_group_list_iterate_end LIST_ITERATE_END
+
+
+/**************************************************************************
+ Effects hash. The hash is created during ruleset loading and the data
+ is organized to enable fast queries.
+**************************************************************************/
+static struct {
+ struct building_vector buildings;
+ struct eff_list buckets[B_LAST];
+
+ struct eff_group *groups[B_LAST];
+} eff_hash[EFT_LAST];
+
+struct eff_group_list groups;
+int groups_id;
+
+/**************************************************************************
+ Wrappers for access to effects hash data.
+**************************************************************************/
+static inline
+struct building_vector *get_effect_buildings(enum effect_type eff)
+{
+ return &eff_hash[eff].buildings;
+}
+
+static inline
+struct eff_list *get_building_effects(Impr_Type_id id, enum effect_type eff)
+{
+ return &eff_hash[eff].buckets[id];
+}
+
+static inline
+struct eff_group **get_building_eff_group(Impr_Type_id id,
+ enum effect_type eff)
+{
+ return &eff_hash[eff].groups[id];
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+static const char *req_type_names[] = {
+ "Unknown",
+
+ "None",
+ "Tech",
+ "Gov",
+ "Building",
+ "Wonder",
+ "Special",
+ "Terrain"
+};
+
+/**************************************************************************
+...
+**************************************************************************/
+enum req_type req_type_from_str(const char *str)
+{
+ enum req_type id;
+
+ for (id = 1; id < ARRAY_SIZE(req_type_names); id++) {
+ if (0 == mystrcasecmp(req_type_names[id], str)) {
+ return id;
+ }
+ }
+
+ return REQ_UNKNOWN;
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+struct eff_group *eff_group_new(const char *name, enum effect_type eff)
+{
+ struct eff_group *group;
+
+ group = fc_malloc(sizeof(*group));
+ group->name = mystrdup(name);
+ group->eff = eff;
+ group->id = groups_id++;
+ building_vector_init(&group->buildings);
+
+ eff_group_list_insert_back(&groups, group);
+ return group;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void eff_group_add(struct eff_group *group, const char *building)
+{
+ Impr_Type_id id;
+
+ if ((id = find_improvement_by_name(building)) != B_LAST) {
+ building_vector_append(&group->buildings, &id);
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int find_eff_group(const char *name, enum effect_type eff)
+{
+ int i = 0;
+
+ eff_group_list_iterate(groups, pgroup) {
+ if (0 == strcasecmp(pgroup->name, name) && pgroup->eff == eff) {
+ return i;
+ }
+ i++;
+ } eff_group_list_iterate_end;
+
+ return -1;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void eff_hash_init(void)
+{
+ int i, j;
+
+ assert(ARRAY_SIZE(req_type_names) == REQ_LAST);
+
+ eff_group_list_init(&groups);
+ groups_id = 0;
+
+ for (i = 0; i < ARRAY_SIZE(eff_hash); i++) {
+ building_vector_init(get_effect_buildings(i));
+
+ for (j = 0; j < ARRAY_SIZE(eff_hash[i].groups); j++) {
+ eff_hash[i].groups[j] = NULL;
+ }
+ for (j = 0; j < ARRAY_SIZE(eff_hash[i].buckets); j++) {
+ eff_list_init(get_building_effects(j, i));
+ }
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+enum op_type parse_value(const char *str, int *value)
+{
+ const char *pch = str;
+ int num;
+ enum op_type op;
+
+ while (isspace(*pch)) {
+ pch++;
+ }
+
+ /* binary operators. the operation executed will be accum = accum OP b. */
+ switch (*pch) {
+ case '+':
+ op = OP_PLUS;
+ pch++;
+ break;
+ case '-':
+ op = OP_MINUS;
+ pch++;
+ break;
+ case '*':
+ op = OP_TIMES;
+ pch++;
+ break;
+ case '/':
+ op = OP_DIVIDE;
+ pch++;
+ break;
+ default:
+ op = OP_PLUS;
+ break;
+ }
+
+ num = 0;
+ for (; *pch != '\0'; pch++) {
+ if (isdigit(*pch)) {
+ num *= 10;
+ num += *pch - '0';
+ } else {
+ return OP_NONE;
+ }
+ }
+ *value = num;
+ return op;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int parse_req(Impr_Type_id id, enum req_type type, const char *arg)
+{
+ bool problem;
+ int data;
+ struct government *pgov;
+
+ switch (type) {
+ case REQ_NONE:
+ problem = FALSE;
+ data = 0;
+ break;
+ case REQ_TECH:
+ problem =
+ (A_LAST == (data = find_tech_by_name(arg)));
+ break;
+ case REQ_GOV:
+ if (!(pgov = find_government_by_name(arg))) {
+ problem = TRUE;
+ } else {
+ problem = FALSE;
+ data = pgov->index;
+ }
+ break;
+ case REQ_BUILDING:
+ problem =
+ (B_LAST == (data = find_improvement_by_name(arg)));
+ break;
+ case REQ_WONDER:
+ problem =
+ (B_LAST == (data = find_improvement_by_name(arg)));
+ break;
+ case REQ_SPECIAL:
+ problem =
+ (S_NO_SPECIAL == (data = get_special_by_name(arg)));
+ break;
+ case REQ_TERRAIN:
+ problem =
+ (T_LAST == (data = get_terrain_by_name(arg)));
+ break;
+ default:
+ freelog(LOG_ERROR, "for %s: unimplemented requirement type '%d'",
+ get_improvement_name(id), type);
+ return -1;
+ }
+
+ if (problem) {
+ freelog(LOG_ERROR, "for %s: bad requirement data '%s'",
+ get_improvement_name(id), arg);
+ return -1;
+ } else {
+ return data;
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void eff_hash_add(Impr_Type_id id, enum effect_type eff,
+ enum op_type op, int value,
+ enum req_type req, int arg,
+ int group)
+{
+ struct effect *peff;
+
+ peff = fc_malloc(sizeof(*peff));
+
+ peff->op = op;
+ peff->value = value;
+
+ peff->type = req;
+
+ switch (req) {
+ case REQ_NONE:
+ break;
+ case REQ_TECH:
+ peff->req.tech = arg;
+ break;
+ case REQ_GOV:
+ peff->req.gov = get_government(arg);
+ break;
+ case REQ_BUILDING:
+ peff->req.building = arg;
+ break;
+ case REQ_WONDER:
+ peff->req.wonder = arg;
+ break;
+ case REQ_SPECIAL:
+ peff->req.special = arg;
+ break;
+ case REQ_TERRAIN:
+ peff->req.terrain = arg;
+ break;
+ default:
+ freelog(LOG_ERROR, "for %s: unimplemented requirement type '%d'",
+ get_improvement_name(id), req);
+ free(peff);
+ return;
+ }
+
+ eff_list_insert_back(get_building_effects(id, eff), peff);
+
+ if (group >= 0 && group < eff_group_list_size(&groups)) {
+ *get_building_eff_group(id, eff) = eff_group_list_get(&groups, group);
+ }
+
+ {
+ struct building_vector *vec;
+ Impr_Type_id *pid;
+
+ vec = get_effect_buildings(eff);
+
+ if (!(pid = building_vector_get(vec, -1)) || *pid != id) {
+ building_vector_append(vec, &id);
+ }
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void send_eff_hash_groups(struct conn_list *dest)
+{
+ struct packet_eff_hash_group packet;
+ int i;
+
+ eff_group_list_iterate(groups, pgroup) {
+ sz_strlcpy(packet.name, pgroup->name);
+ packet.eff = pgroup->eff;
+
+ packet.num_buildings = building_vector_size(&pgroup->buildings);
+ for (i = 0; i < packet.num_buildings; i++) {
+ Impr_Type_id *pid = building_vector_get(&pgroup->buildings, i);
+
+ packet.buildings[i] = *pid;
+ }
+
+ lsend_packet_eff_hash_group(dest, &packet);
+ } eff_group_list_iterate_end;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void send_eff_hash_effects(struct conn_list *dest)
+{
+ struct packet_eff_hash_effect packet;
+ enum effect_type eff;
+
+ for (eff = 0; eff < EFT_LAST; eff++) {
+ packet.eff = eff;
+
+ building_vector_iterate(get_effect_buildings(eff), id) {
+ struct eff_group *pgroup;
+
+ packet.id = *id;
+
+ if ((pgroup = *get_building_eff_group(*id, eff))) {
+ packet.group = find_eff_group(pgroup->name, eff);
+ } else {
+ packet.group = -1;
+ }
+
+ eff_list_iterate(*get_building_effects(*id, eff), elt) {
+ packet.op = elt->op;
+ packet.value = elt->value;
+ packet.req = elt->type;
+
+ switch (packet.req) {
+ case REQ_NONE:
+ packet.arg = 0;
+ break;
+ case REQ_TECH:
+ packet.arg = elt->req.tech;
+ break;
+ case REQ_GOV:
+ packet.arg = (elt->req.gov ? elt->req.gov->index : -1);
+ break;
+ case REQ_BUILDING:
+ packet.arg = elt->req.building;
+ break;
+ case REQ_WONDER:
+ packet.arg = elt->req.wonder;
+ break;
+ case REQ_SPECIAL:
+ packet.arg = elt->req.special;
+ break;
+ case REQ_TERRAIN:
+ packet.arg = elt->req.terrain;
+ break;
+ default:
+ freelog(LOG_ERROR, "send_eff_hash_effects: %d", packet.req);
+ break;
+ }
+
+ lsend_packet_eff_hash_effect(dest, &packet);
+ } eff_list_iterate_end;
+ } building_vector_iterate_end;
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void send_eff_hash(struct conn_list *dest)
+{
+ send_eff_hash_groups(dest);
+ send_eff_hash_effects(dest);
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline bool player_knows_tech(struct player *plr, Tech_Type_id tech) {
+ return (get_invention(plr, tech) == TECH_KNOWN);
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline void operate(enum op_type op, int *accum, int value)
+{
+ switch (op) {
+ case OP_PLUS:
+ *accum += value;
+ break;
+ case OP_MINUS:
+ *accum -= value;
+ break;
+ case OP_TIMES:
+ *accum *= value;
+ break;
+ case OP_DIVIDE:
+ *accum /= value;
+ break;
+ default:
+ freelog(LOG_ERROR, "operate: %d", op);
+ break;
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline void player_power_func(struct player *plr, struct effect *eff,
+ int *power)
+{
+ bool active = FALSE;
+
+ switch (eff->type) {
+ case REQ_NONE:
+ active = TRUE;
+ break;
+ case REQ_TECH:
+ active = player_knows_tech(plr, eff->req.tech);
+ break;
+ case REQ_GOV:
+ active = (get_gov_pplayer(plr) == eff->req.gov);
+ break;
+ default:
+ freelog(LOG_ERROR, "player_power_func: %d", eff->type);
+ break;
+ }
+
+ if (active) {
+ operate(eff->op, power, eff->value);
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline void city_power_func(struct city *pcity, struct effect *eff,
+ int *power)
+{
+ bool active = FALSE;
+
+ switch (eff->type) {
+ case REQ_NONE:
+ active = TRUE;
+ break;
+ case REQ_TECH:
+ active = player_knows_tech(city_owner(pcity), eff->req.tech);
+ break;
+ case REQ_GOV:
+ active = (get_gov_pcity(pcity) == eff->req.gov);
+ break;
+ case REQ_BUILDING:
+ active = city_got_building(pcity, eff->req.building);
+ break;
+ case REQ_WONDER:
+ active = city_affected_by_wonder(pcity, eff->req.wonder);
+ break;
+ default:
+ freelog(LOG_ERROR, "city_power_func: %d", eff->type);
+ break;
+ }
+
+ if (active) {
+ operate(eff->op, power, eff->value);
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline void city_building_power_func(struct city *pcity,
+ Impr_Type_id id,
+ struct effect *eff, int *power)
+{
+ bool active = FALSE;
+
+ switch (eff->type) {
+ case REQ_NONE:
+ active = TRUE;
+ break;
+ case REQ_TECH:
+ active = player_knows_tech(city_owner(pcity), eff->req.tech);
+ break;
+ case REQ_GOV:
+ active = (get_gov_pcity(pcity) == eff->req.gov);
+ break;
+ case REQ_BUILDING:
+ active = city_got_building(pcity, eff->req.building);
+ break;
+ case REQ_WONDER:
+ active = city_affected_by_wonder(pcity, eff->req.wonder);
+ break;
+ default:
+ freelog(LOG_ERROR, "city_building_power_func: %d", eff->type);
+ break;
+ }
+
+ if (active) {
+ operate(eff->op, power, eff->value);
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline void city_tile_power_func(struct city *pcity,
+ struct tile *ptile,
+ struct effect *eff, int *power)
+{
+ bool active = FALSE;
+
+ switch (eff->type) {
+ case REQ_NONE:
+ active = TRUE;
+ break;
+ case REQ_TECH:
+ active = player_knows_tech(city_owner(pcity), eff->req.tech);
+ break;
+ case REQ_GOV:
+ active = (get_gov_pcity(pcity) == eff->req.gov);
+ break;
+ case REQ_BUILDING:
+ active = city_got_building(pcity, eff->req.building);
+ break;
+ case REQ_WONDER:
+ active = city_affected_by_wonder(pcity, eff->req.wonder);
+ break;
+ case REQ_SPECIAL:
+ active = tile_has_special(ptile, eff->req.special);
+ break;
+ case REQ_TERRAIN:
+ active = (ptile->terrain == eff->req.terrain);
+ break;
+ default:
+ freelog(LOG_ERROR, "city_tile_power_func: %d", eff->type);
+ break;
+ }
+
+ if (active) {
+ operate(eff->op, power, eff->value);
+ }
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+static int get_player_power(struct player *plr, Impr_Type_id bldg,
+ enum effect_type eff)
+{
+ int power = 0;
+
+ eff_list_iterate(*get_building_effects(bldg, eff), elt) {
+ player_power_func(plr, elt, &power);
+ } eff_list_iterate_end;
+
+ return power;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static int get_city_power(struct city *pcity, Impr_Type_id bldg,
+ enum effect_type eff)
+{
+ int power = 0;
+
+ eff_list_iterate(*get_building_effects(bldg, eff), elt) {
+ city_power_func(pcity, elt, &power);
+ } eff_list_iterate_end;
+
+ return power;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static int get_city_building_power(struct city *pcity, Impr_Type_id bldg,
+ enum effect_type eff)
+{
+ int power = 0;
+
+ eff_list_iterate(*get_building_effects(bldg, eff), elt) {
+ city_building_power_func(pcity, bldg, elt, &power);
+ } eff_list_iterate_end;
+
+ return power;
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+static int get_city_tile_power(struct city *pcity, struct tile *ptile,
+ Impr_Type_id bldg, enum effect_type eff)
+{
+ int power = 0;
+
+ eff_list_iterate(*get_building_effects(bldg, eff), elt) {
+ city_tile_power_func(pcity, ptile, elt, &power);
+ } eff_list_iterate_end;
+
+ return power;
+}
+
+
+/**************************************************************************
+...
+**************************************************************************/
+static inline bool wonder_active(Impr_Type_id id)
+{
+ return (improvement_exists(id)
+ && is_wonder(id)
+ && (!wonder_obsolete(id))
+ && game.global_wonders[id] != 0);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static int inline active_player_everlasting_building(struct player *plr,
+ Impr_Type_id id,
enum effect_type eff)
+{
+ struct eff_group *group;
+
+ if (!(group = *get_building_eff_group(id, eff))) {
+ /* unique. */
+ if (wonder_active(id)) {
+ return id;
+ }
+
+ return -1;
+ } else {
+ /* got more than one building in the same equiv group?
+ * first in the group that exists wins. */
+ building_vector_iterate(&group->buildings, elt) {
+ if (wonder_active(*elt)) {
+ return *elt;
+ }
+ } building_vector_iterate_end;
+
+ return -1;
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int get_player_everlasting_bonus(struct player *plr, enum effect_type eff)
+{
+ int bonus = 0;
+
+ building_vector_iterate(get_effect_buildings(eff), elt) {
+ int active;
+
+ active = active_player_everlasting_building(plr, *elt, eff);
+
+ if (active == *elt) {
+ bonus += get_player_power(plr, active, eff);
+ }
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static int inline active_player_building(struct player *plr, Impr_Type_id id,
enum effect_type eff)
+{
+ struct eff_group *group;
+
+ if (!(group = *get_building_eff_group(id, eff))) {
+ /* unique. */
+ if (player_owns_active_wonder(plr, id)) {
+ return id;
+ }
+
+ return -1;
+ } else {
+ /* got more than one building in the same equiv group?
+ * first in the group that exists wins. */
+ building_vector_iterate(&group->buildings, elt) {
+ if (player_owns_active_wonder(plr, *elt)) {
+ return *elt;
+ }
+ } building_vector_iterate_end;
+
+ return -1;
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int get_player_bonus(struct player *plr, enum effect_type eff)
+{
+ int bonus = 0;
+
+ building_vector_iterate(get_effect_buildings(eff), elt) {
+ int active;
+
+ active = active_player_building(plr, *elt, eff);
+
+ if (active == *elt) {
+ bonus += get_player_power(plr, active, eff);
+ }
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static int inline active_city_building(struct city *pcity, Impr_Type_id id,
+ enum effect_type eff)
+{
+ struct eff_group *group;
+
+ if (!(group = *get_building_eff_group(id, eff))) {
+ /* unique. */
+ if (is_wonder(id)) {
+ if (city_affected_by_wonder(pcity, id)) {
+ return id;
+ }
+ } else {
+ if (city_got_building(pcity, id)) {
+ return id;
+ }
+ }
+
+ return -1;
+ } else {
+ /* got more than one building in the same equiv group?
+ * first in the group that exists wins. */
+ building_vector_iterate(&group->buildings, elt) {
+ if (is_wonder(*elt)) {
+ if (city_affected_by_wonder(pcity, *elt)) {
+ return *elt;
+ }
+ } else {
+ if (city_got_building(pcity, *elt)) {
+ return *elt;
+ }
+ }
+ } building_vector_iterate_end;
+
+ return -1;
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int get_city_bonus(struct city *pcity, enum effect_type eff)
+{
+ int bonus = 0;
+
+ /* get bonus effect from improvements and wonders. */
+ building_vector_iterate(get_effect_buildings(eff), elt) {
+ int active;
+
+ active = active_city_building(pcity, *elt, eff);
+
+ if (active == *elt) {
+ bonus += get_city_power(pcity, active, eff);
+ }
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int get_city_building_bonus(struct city *pcity, Impr_Type_id id,
+ enum effect_type eff)
+{
+ int bonus = 0;
+
+ if (pcity) {
+ building_vector_iterate(get_effect_buildings(eff), elt) {
+ if (city_got_building(pcity, id)) {
+ bonus += get_city_building_power(pcity, id, eff);
+ }
+ } building_vector_iterate_end;
+ }
+
+ return bonus;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+int get_city_tile_bonus(struct city *pcity, struct tile *ptile,
+ enum effect_type eff)
+{
+ int bonus = 0;
+
+ if (pcity) {
+ building_vector_iterate(get_effect_buildings(eff), elt) {
+ int active;
+
+ active = active_city_building(pcity, *elt, eff);
+
+ if (active == *elt) {
+ bonus += get_city_tile_power(pcity, ptile, active, eff);
+ }
+ } building_vector_iterate_end;
+ }
+
+ return bonus;
+}
diff -Nurd -X diff_ignore freecvs/common/eff.h freeciv/common/eff.h
--- freecvs/common/eff.h 1970-01-01 01:00:00.000000000 +0100
+++ freeciv/common/eff.h 2004-05-21 19:05:27.637131576 +0100
@@ -0,0 +1,60 @@
+#ifndef FC__EFF_H
+#define FC__EFF_H
+
+#include "improvement.h"
+#include "effects.h"
+
+#include "map.h"
+
+/* Effect operator type. */
+enum op_type {
+ OP_NONE, OP_PLUS, OP_MINUS, OP_TIMES, OP_DIVIDE
+};
+
+/* Effect requirement type. */
+enum req_type {
+ REQ_UNKNOWN,
+
+ REQ_NONE,
+ REQ_TECH,
+ REQ_GOV,
+ REQ_BUILDING,
+ REQ_WONDER,
+ REQ_SPECIAL,
+ REQ_TERRAIN,
+ REQ_LAST
+};
+
+struct eff_group;
+struct conn_list;
+
+/* Effects Hash creation and communication functions. */
+void eff_hash_init(void);
+
+void eff_hash_add(Impr_Type_id id, enum effect_type eff,
+ enum op_type op, int value,
+ enum req_type req, int arg, int equiv);
+
+void send_eff_hash(struct conn_list *dest);
+
+/* Equivalent effect group. */
+struct eff_group *eff_group_new(const char *name, enum effect_type eff);
+void eff_group_add(struct eff_group *group, const char *building);
+int find_eff_group(const char *name, enum effect_type eff);
+
+/* Name string to value functions. */
+enum op_type parse_value(const char *str, int *value);
+enum req_type req_type_from_str(const char *str);
+int parse_req(Impr_Type_id id, enum req_type req, const char *arg);
+
+/* Functions to know the bonuses a certain effect is granting. */
+int get_player_everlasting_bonus(struct player *plr, enum effect_type eff);
+int get_player_bonus(struct player *plr, enum effect_type eff);
+
+int get_city_bonus(struct city *pcity, enum effect_type eff);
+int get_city_building_bonus(struct city *pcity, Impr_Type_id id,
+ enum effect_type eff);
+int get_city_tile_bonus(struct city *city, struct tile *ptile,
+ enum effect_type eff);
+#endif
+
diff -Nurd -X diff_ignore freecvs/common/Makefile.am freeciv/common/Makefile.am
--- freecvs/common/Makefile.am 2004-05-02 13:13:51.000000000 +0100
+++ freeciv/common/Makefile.am 2004-05-10 13:31:36.000000000 +0100
@@ -23,6 +23,8 @@
diptreaty.h \
effects.c \
effects.h \
+ eff.c \
+ eff.h \
events.h \
game.c \
game.h \
diff -Nurd -X diff_ignore freecvs/common/packets.def freeciv/common/packets.def
--- freecvs/common/packets.def 2004-05-21 20:28:20.507140424 +0100
+++ freeciv/common/packets.def 2004-05-21 23:34:44.599899888 +0100
@@ -174,6 +174,11 @@
type ORDERS = uint8(enum unit_orders)
type SSET_TYPE = uint8(enum sset_type)
+# typedefs for effects
+type EFF = uint8(enum effect_type)
+type OP = uint8(enum op_type)
+type REQ = uint8(enum req_type)
+
# typedefs for IDs
type PLAYER = UINT8
type CITY = UINT16
@@ -1284,3 +1289,24 @@
UINT8 category; /* which category this is in */
end
+
+/************** Effects hash packets **********************/
+
+PACKET_EFF_HASH_GROUP=120;sc,lsend
+ STRING name[MAX_LEN_NAME];
+ EFF eff;
+
+ UINT8 num_buildings;
+ IMPROVEMENT buildings[255:num_buildings];
+end
+
+PACKET_EFF_HASH_EFFECT=121;sc,lsend
+ IMPROVEMENT id;
+ EFF eff;
+ OP op;
+ SINT32 value;
+ REQ req;
+ SINT32 arg;
+ SINT32 group;
+end
+
diff -Nurd -X diff_ignore freecvs/common/packets.h freeciv/common/packets.h
--- freecvs/common/packets.h 2004-01-14 11:58:12.000000000 +0000
+++ freeciv/common/packets.h 2004-05-16 01:21:39.000000000 +0100
@@ -26,6 +26,7 @@
#include "spaceship.h"
#include "unittype.h"
#include "worklist.h"
+#include "eff.h"
#define MAX_LEN_USERNAME 10 /* see below */
diff -Nurd -X diff_ignore freecvs/common/unit.c freeciv/common/unit.c
--- freecvs/common/unit.c 2004-05-19 21:14:58.000000000 +0100
+++ freeciv/common/unit.c 2004-05-19 21:07:06.000000000 +0100
@@ -18,6 +18,7 @@
#include <assert.h>
#include "fcintl.h"
+#include "eff.h"
#include "game.h"
#include "log.h"
#include "map.h"
@@ -53,15 +54,8 @@
case SEA_MOVING:
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;
- }
-
- if (player_owns_active_wonder(unit_owner(punit), B_MAGELLAN)) {
- move_rate += (improvement_variant(B_MAGELLAN) == 1)
- ? SINGLE_MOVE : 2 * SINGLE_MOVE;
- }
-
+ move_rate += get_player_bonus(unit_owner(punit), EFT_UNIT_MOVE) *
SINGLE_MOVE;
+
if (player_knows_techs_with_flag(unit_owner(punit), TF_BOAT_FAST)) {
move_rate += SINGLE_MOVE;
}
diff -Nurd -X diff_ignore freecvs/data/default/buildings.ruleset
freeciv/data/default/buildings.ruleset
--- freecvs/data/default/buildings.ruleset 2004-05-13 19:17:37.000000000
+0100
+++ freeciv/data/default/buildings.ruleset 2004-05-20 01:20:09.000000000
+0100
@@ -69,8 +69,42 @@
; helptext = optional help text string; should escape all raw
; newlines so that xgettext parsing works
;
+; affect { = list of effects; parameters are:
+; eff = effect name; e.g. "Tax_Bonus"
+; value = modifier value of effect; by ommission "+1".
+; it is possible to use several operators: +, -, *, /.
+; type = requirement type; one of:
+; "None", "Tech", "Gov", "Building", "Wonder", "Special",
+; "Terrain".
+; req = requirement data; varies with requirement type.
+;
+; } the effects in the list are cumulative.
+;
; */ <-- avoid gettext warnings
+;
+; Effect groups are a convenience mechanism to handle
+; equivalent effects which may be done by one of several buildings.
+; The first building in the 'buildings' list of the group which
+; exists wins.
+;
+
+[group_cathedrals]
+name = "Cathedrals"
+eff = "Make_Content"
+buildings = "Michelangelo's Chapel", "Cathedral"
+
+[group_labs]
+name = "Labs"
+eff = "Science_Bonus"
+buildings = "SETI Program", "Research Lab"
+
+[group_generators]
+name = "Generators"
+eff = "Prod_Bonus"
+buildings = "Hoover Dam", "Nuclear Plant", "Hydro Plant",
+ "Power Plant"
+
[building_airport]
name = _("Airport")
tech_req = "Radio"
@@ -152,6 +186,11 @@
build_cost = 80
upkeep = 2
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Tax_Bonus", "50", "Building", "Marketplace"
+ "Luxury_Bonus", "50", "Building", "Marketplace"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Tax_Bonus", "City", 50, "Marketplace"
@@ -274,6 +313,12 @@
build_cost = 80
upkeep = 3
sabotage = 100
++affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Make_Content", "3", "Cathedrals"
+ "Make_Content", "1", "Cathedrals", "Tech", "Theology"
+ "Make_Content", "-1", "Cathedrals", "Tech", "Communism"
+ }
effect =
{ "type", "range", "amount", "cond_adv"
"Make_Content", "City", 3
@@ -367,6 +412,11 @@
build_cost = 70
upkeep = 4
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Make_Content", "3"
+ "Make_Content", "1", "Tech", "Electricity"
+ }
effect =
{ "type", "range", "amount", "cond_adv"
"Make_Content", "City", 3
@@ -397,6 +447,12 @@
build_cost = 60
upkeep = 1
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Corrupt_Pct", "50"
+ "Make_Content", "1", "Gov", "Democracy"
+ "Revolt_Dist_Pct", "50"
+ }
effect =
{ "type", "range", "amount", "cond_gov"
"Corrupt_Pct", "City", 50
@@ -428,6 +484,10 @@
build_cost = 140
upkeep = 4
sabotage = 100
+affect =
+ { "eff", "value"
+ "Prod_Bonus", "50"
+ }
effect =
{ "type", "range", "amount"
"Prod_Bonus", "City", 50
@@ -486,6 +546,10 @@
build_cost = 40
upkeep = 1
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Food_Add_Tile", "1", "Terrain", "Ocean"
+ }
effect =
{ "type", "range", "amount", "aff_terr", "aff_spec"
"Food_Add_Tile", "City", 1, "Ocean", "None"
@@ -556,6 +620,10 @@
build_cost = 60
upkeep = 1
sabotage = 100
+affect =
+ { "eff", "value"
+ "Science_Bonus", "50"
+ }
effect =
{ "type", "range", "amount"
"Science_Bonus", "City", 50
@@ -583,6 +651,11 @@
build_cost = 60
upkeep = 0
sabotage = 100
+affect =
+ { "eff", "value"
+ "Tax_Bonus", "50"
+ "Luxury_Bonus", "50"
+ }
effect =
{ "type", "range", "amount"
"Tax_Bonus", "City", 50
@@ -611,6 +684,10 @@
build_cost = 120
upkeep = 4
sabotage = 100
+affect =
+ { "eff", "value"
+ "Pollu_Pop_Pct", "100"
+ }
effect =
{ "type", "range", "amount"
"Pollu_Pop_Pct", "City", 0
@@ -639,6 +716,10 @@
build_cost = 220
upkeep = 6
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Prod_Bonus", "50", "Building", "Factory"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Prod_Bonus", "City", 50, "Factory"
@@ -667,6 +748,11 @@
build_cost = 120
upkeep = 2
sabotage = 100
+affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Prod_Bonus", "25", "Generators", "Building", "Factory"
+ "Prod_Bonus", "25", "Generators", "Building", "Mfg. Plant"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Prod_Bonus", "City", 25, "Factory"
@@ -711,6 +797,10 @@
build_cost = 120
upkeep = 3
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Prod_Add_Tile", "1", "Terrain", "Ocean"
+ }
effect =
{ "type", "range", "amount", "aff_terr", "aff_spec"
"Prod_Add_Tile", "City", 1, "Ocean", "None"
@@ -836,6 +926,11 @@
build_cost = 130
upkeep = 4
sabotage = 100
+affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Prod_Bonus", "25", "Generators", "Building", "Factory"
+ "Prod_Bonus", "25", "Generators", "Building", "Mfg. Plant"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Prod_Bonus", "City", 25, "Factory"
@@ -902,6 +997,10 @@
build_cost = 120
upkeep = 3
sabotage = 100
+affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Science_Bonus", "50", "Labs", "Building", "Library"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Science_Bonus", "City", 50, "Library"
@@ -1165,6 +1264,11 @@
build_cost = 120
upkeep = 3
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Tax_Bonus", "50", "Building", "Bank"
+ "Luxury_Bonus", "50", "Building", "Bank"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Tax_Bonus", "City", 50, "Bank"
@@ -1194,6 +1298,10 @@
build_cost = 120
upkeep = 3
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Trade_Per_Tile", "50", "Special", "Road"
+ }
effect =
{ "type", "range", "amount", "aff_terr", "aff_spec"
"Trade_Per_Tile", "City", 50, "None", "Road"
@@ -1224,6 +1332,10 @@
build_cost = 80
upkeep = 3
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Food_Per_Tile", "50", "Special", "Farmland"
+ }
effect =
{ "type", "range", "amount", "aff_terr", "aff_spec"
"Food_Per_Tile", "City", 50, "None", "Farmland"
@@ -1253,6 +1365,12 @@
build_cost = 30
upkeep = 1
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Make_Content", "1"
+ "Make_Content", "1", "Tech", "Mysticism"
+ "Make_Content", "*2", "Wonder", "Oracle"
+ }
effect =
{ "type", "range", "amount", "cond_adv"
"Make_Content", "City", 1
@@ -1282,6 +1400,10 @@
build_cost = 120
upkeep = 3
sabotage = 100
+affect =
+ { "eff", "value", "type", "req"
+ "Science_Bonus", "50", "Building", "Library"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Science_Bonus", "City", 50, "Library"
@@ -1339,6 +1461,10 @@
build_cost = 400
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Upkeep_Free", "1"
+ }
effect =
{ "type", "range", "amount"
"Upkeep_Free", "Player", 1
@@ -1366,6 +1492,10 @@
build_cost = 100
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Trade_Inc_Tile", "1"
+ }
effect =
{ "type", "range", "amount"
"Trade_Inc_Tile", "City", 1
@@ -1393,6 +1523,10 @@
build_cost = 200
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Science_Bonus", "50"
+ }
effect =
{ "type", "range", "amount"
"Science_Bonus", "City", 50
@@ -1420,6 +1554,10 @@
build_cost = 600
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Force_Content", "1"
+ }
effect =
{ "type", "range", "amount"
"Make_Content", "Player", 1
@@ -1507,6 +1645,10 @@
build_cost = 300
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Adv_Parasite", "2"
+ }
effect =
{ "type", "range", "amount"
"Adv_Parasite", "Player", 2
@@ -1564,6 +1706,11 @@
build_cost = 200
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value", "type", "req"
+ "Make_Happy", "1"
+ "Make_Happy", "2", "Building", "Hanging Gardens"
+ }
effect =
{ "type", "range", "amount"
"Make_Happy", "Player", 1
@@ -1595,6 +1742,11 @@
build_cost = 600
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Prod_Bonus", "25", "Generators", "Building", "Factory"
+ "Prod_Bonus", "25", "Generators", "Building", "Mfg. Plant"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Prod_Bonus", "Player", 25, "Factory"
@@ -1625,6 +1777,10 @@
build_cost = 300
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Science_Bonus", "100"
+ }
effect =
{ "type", "range", "amount"
"Science_Bonus", "City", 100
@@ -1652,6 +1808,10 @@
build_cost = 400
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Force_Content", "2"
+ }
effect =
{ "type", "range", "amount"
"Make_Content", "Player", 2
@@ -1678,6 +1838,10 @@
build_cost = 150
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Prod_Add_Tile", "1"
+ }
effect =
{ "type", "range", "amount"
"Prod_Add_Tile", "City", 1
@@ -1697,7 +1861,7 @@
graphic_alt = "-"
;terr_gate =
;spec_gate =
-equiv_range = "Player"
+equiv_range = "None"
;equiv_dupl =
;equiv_repl =
obsolete_by = "Automobile"
@@ -1731,6 +1895,10 @@
build_cost = 200
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Unit_Move", "1"
+ }
effect =
{ "type", "range", "amount", "aff_unit"
"Unit_Move", "Player", 1, "Sea"
@@ -1753,7 +1921,7 @@
graphic_alt = "-"
;terr_gate =
;spec_gate =
-equiv_range = "Player"
+equiv_range = "None"
;equiv_dupl =
;equiv_repl =
obsolete_by = "None"
@@ -1761,6 +1929,10 @@
build_cost = 400
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value"
+ "Unit_Move", "2"
+ }
effect =
{ "type", "range", "amount", "aff_unit"
"Unit_Move", "Player", 2, "Sea"
@@ -1838,6 +2010,12 @@
build_cost = 400
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Make_Content", "3", "Cathedrals"
+ "Make_Content", "1", "Cathedrals", "Tech", "Theology"
+ "Make_Content", "-1", "Cathedrals", "Tech", "Communism"
+ }
effect =
{ "type", "range", "amount", "cond_adv"
"Make_Content", "Player", 3
@@ -1924,6 +2102,10 @@
build_cost = 600
upkeep = 0
sabotage = 0
+affect =
+ { "eff", "value", "equiv", "type", "req"
+ "Science_Bonus", "50", "Labs", "Building", "Library"
+ }
effect =
{ "type", "range", "amount", "cond_bldg"
"Science_Bonus", "Player", 50, "Library"
diff -Nurd -X diff_ignore freecvs/server/plrhand.c freeciv/server/plrhand.c
--- freecvs/server/plrhand.c 2004-05-11 18:59:34.000000000 +0100
+++ freeciv/server/plrhand.c 2004-05-16 18:15:52.000000000 +0100
@@ -19,6 +19,7 @@
#include <stdarg.h>
#include "diptreaty.h"
+#include "eff.h"
#include "events.h"
#include "fcintl.h"
#include "government.h"
@@ -128,31 +129,29 @@
**************************************************************************/
void great_library(struct player *pplayer)
{
- if (wonder_obsolete(B_GREAT))
- return;
- if (find_city_wonder(B_GREAT)) {
- if (pplayer->player_no==find_city_wonder(B_GREAT)->owner) {
- tech_type_iterate(i) {
- if (get_invention(pplayer, i) != TECH_KNOWN
- && tech_is_available(pplayer, i)
- && game.global_advances[i]>=2) {
- notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
- _("Game: %s acquired from The Great Library!"),
- advances[i].name);
- gamelog(GAMELOG_TECH, _("%s discover %s (Library)"),
- get_nation_name_plural(pplayer->nation), advances[i].name);
- notify_embassies(pplayer, NULL,
- _("Game: The %s have acquired %s"
- " from the Great Library."),
- get_nation_name_plural(pplayer->nation),
- advances[i].name);
+ int mod;
- do_free_cost(pplayer);
- found_new_tech(pplayer, i, FALSE, FALSE, A_NONE);
- break;
- }
- } tech_type_iterate_end;
- }
+ if ((mod = get_player_bonus(pplayer, EFT_ADV_PARASITE)) > 0) {
+ tech_type_iterate(i) {
+ if (get_invention(pplayer, i) != TECH_KNOWN
+ && tech_is_available(pplayer, i)
+ && game.global_advances[i] >= mod) {
+ notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
+ _("Game: %s acquired from The Great Library!"),
+ advances[i].name);
+ gamelog(GAMELOG_TECH, _("%s discover %s (Library)"),
+ get_nation_name_plural(pplayer->nation), advances[i].name);
+ notify_embassies(pplayer, NULL,
+ _("Game: The %s have acquired %s"
+ " from the Great Library."),
+ get_nation_name_plural(pplayer->nation),
+ advances[i].name);
+
+ do_free_cost(pplayer);
+ found_new_tech(pplayer, i, FALSE, FALSE, A_NONE);
+ break;
+ }
+ } tech_type_iterate_end;
}
}
diff -Nurd -X diff_ignore freecvs/server/ruleset.c freeciv/server/ruleset.c
--- freecvs/server/ruleset.c 2004-05-21 20:28:22.423849040 +0100
+++ freeciv/server/ruleset.c 2004-05-21 23:34:47.866403304 +0100
@@ -42,6 +42,8 @@
#include "ruleset.h"
+#include "eff.h"
+
static const char name_too_long[] = "Name \"%s\" too long; truncating.";
#define check_name(name) (check_strlen(name, MAX_LEN_NAME, name_too_long))
#define name_strlcpy(dst, src) ((void) sz_loud_strlcpy(dst, src,
name_too_long))
@@ -1109,6 +1111,8 @@
improvement_types[i].name_orig[0] = 0;
} impr_type_iterate_end;
+ eff_hash_init();
+
free(sec);
}
@@ -1126,6 +1130,32 @@
(void) check_ruleset_capabilities(file, "+1.10.1", filename);
+ /* Parse effect equivalence building groups. */
+ sec = secfile_get_secnames_prefix(file, "group_", &nval);
+ for (i = 0; i < nval; i++) {
+ struct eff_group *group;
+ enum effect_type eff;
+ char name[MAX_LEN_NAME];
+
+ item = secfile_lookup_str(file, "%s.name", sec[i]);
+ sz_strlcpy(name, item);
+
+ item = secfile_lookup_str(file, "%s.eff", sec[i]);
+ if ((eff = effect_type_from_str(item)) == IR_LAST) {
+ freelog(LOG_ERROR, "for group %s unknown effect type: \"%s\" (%s)",
+ name, item, filename);
+ continue;
+ }
+ group = eff_group_new(name, eff);
+
+ list = secfile_lookup_str_vec(file, &count, "%s.buildings", sec[i]);
+ for (j = 0; j < count; j++) {
+ eff_group_add(group, list[j]);
+ }
+ free(list);
+ }
+ free(sec);
+
sec = secfile_get_secnames_prefix(file, "building_", &nval);
for (i = 0; i < nval; i++) {
@@ -1387,6 +1417,77 @@
}
b->effect[k].type = EFT_LAST;
+ /* Parse building effects and add them to the effects hash. */
+ {
+ for (j = 0;
+ (item = secfile_lookup_str_default(file, NULL, "%s.affect%d.eff",
+ sec[i], j));
+ j++) {
+ enum op_type op;
+ int value;
+ enum effect_type eff;
+ enum req_type type;
+ int req, equiv;
+
+ if ((eff = effect_type_from_str(item)) == IR_LAST) {
+ freelog(LOG_ERROR, "for %s unknown effect type: \"%s\" (%s)",
+ b->name, item, filename);
+ continue;
+ }
+
+ item = secfile_lookup_str_default(file, NULL, "%s.affect%d.value",
+ sec[i], j);
+ if (item) {
+ if ((op = parse_value(item, &value)) == OP_NONE) {
+ freelog(LOG_ERROR, "for %s bad value: \"%s\" (%s)",
+ b->name, item, filename);
+ continue;
+ }
+ } else {
+ op = OP_PLUS;
+ value = 1;
+ }
+
+ item = secfile_lookup_str_default(file, NULL, "%s.affect%d.equiv",
+ sec[i], j);
+ if (item) {
+ if ((equiv = find_eff_group(item, eff)) == -1) {
+ freelog(LOG_ERROR, "for %s bad group: \"%s\" (%s)",
+ b->name, item, filename);
+ continue;
+ }
+ } else {
+ equiv = -1;
+ }
+
+ item = secfile_lookup_str_default(file, NULL, "%s.affect%d.type",
+ sec[i], j);
+ if (item) {
+ if ((type = req_type_from_str(item)) == REQ_UNKNOWN) {
+ freelog(LOG_ERROR, "for %s unknown requirement type: \"%s\" (%s)",
+ b->name, item, filename);
+ continue;
+ }
+
+ item = secfile_lookup_str_default(file, NULL, "%s.affect%d.req",
+ sec[i], j);
+
+ if (!item) {
+ freelog(LOG_ERROR, "for %s missing requirement data (%s)",
+ b->name, filename);
+ continue;
+ } else {
+ req = parse_req(i, type, item);
+ }
+ } else {
+ type = REQ_NONE;
+ req = 0;
+ }
+
+ eff_hash_add(i, eff, op, value, type, req, equiv);
+ }
+ }
+
/* FIXME: remove when gen-impr obsoletes */
b->variant = secfile_lookup_int_default(file, 0, "%s.variant", sec[i]);
@@ -3193,6 +3294,9 @@
send_ruleset_nations(dest);
send_ruleset_cities(dest);
+ send_eff_hash(dest);
+
lsend_packet_thaw_hint(dest);
conn_list_do_unbuffer(dest);
}
+
- [Freeciv-Dev] Re: (PR#8754) effects patch (2), (continued)
- [Freeciv-Dev] Re: (PR#8754) effects patch (2), Per Inge Mathisen, 2004/05/17
- [Freeciv-Dev] Re: (PR#8754) effects patch, Jason Short, 2004/05/17
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/19
- [Freeciv-Dev] (PR#8754) effects patch v2, Vasco Alexandre da Silva Costa, 2004/05/19
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/19
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/19
- [Freeciv-Dev] (PR#8754) fix civ1 ruleset equiv_range for Hoover and Bach, Vasco Alexandre da Silva Costa, 2004/05/19
- [Freeciv-Dev] (PR#8754) effects patch: everlasting wonders, Vasco Alexandre da Silva Costa, 2004/05/19
- [Freeciv-Dev] Re: (PR#8754) effects patch: everlasting wonders, Per Inge Mathisen, 2004/05/20
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/20
- [Freeciv-Dev] (PR#8754) effects patch v3,
Vasco Alexandre da Silva Costa <=
- [Freeciv-Dev] (PR#8754) effects patch, Jason Short, 2004/05/26
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/28
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/28
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/29
- [Freeciv-Dev] (PR#8754) effects patch, Marcelo Burda, 2004/05/31
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/31
- [Freeciv-Dev] Re: (PR#8754) effects patch, Mike Kaufman, 2004/05/31
- [Freeciv-Dev] (PR#8754) effects patch v3, Vasco Alexandre da Silva Costa, 2004/05/31
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/05/31
|
|