Complete.Org: Mailing Lists: Archives: freeciv-dev: December 2002:
[Freeciv-Dev] (PR#2521) general effects framework
Home

[Freeciv-Dev] (PR#2521) general effects framework

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] (PR#2521) general effects framework
From: "Mike Kaufman via RT" <rt@xxxxxxxxxxxxxx>
Date: Sun, 8 Dec 2002 16:44:48 -0800
Reply-to: rt@xxxxxxxxxxxxxx

Here is the first draft of the first step toward general-improvements.
This is the initial framework.

Current situation (for the uninitiated): 

improvements have certain "effects" defined in data/default/buildings.ruleset 
that define what they can do when built. Read the ruleset for for specific 
info. Except for the spaceship parts effect, these "effects" currently do 
nothing. Everything is hardcoded by building all throughout the codebase.

There is an access method to theses effects currently, but it is not complete, 
and after examining it, I have found it lacking and fairly unintelligable.

What the patch does (tutorial): 

This patch gives (what I think) is an improved and complete access method to 
these effects. In a nutshell, each improvement has an "effect definition" that 
it gets from the ruleset. on startup, these can be found in:

struct impr_type {
 ...
 struct effect_defn_list effect_defs;
 ...
}

When an improvement is built, an effect [struct effect] is created (which 
has a pointer to the definition) for each effect definition in the list.
Each effect is then added to an effect list based on the range of its
definition. 
The ranges are: "None", "Local", "City", "Island", "Player", and "World". 
Each range defines where the effect is felt. For example, if the effect 
has World range, it will be felt by everything (all cities, improvements, 
units, etc) by all players. If it has City range, it will be felt by 
everything in the city (or perhaps on the city tiles) where the improvement 
is built that is creating the effect. Thus effects created by improvements 
have a "home" (if an effect survives an improvement's destruction, it
becomes "homeless").

Once the effect is added, you can check for the effect by iterating though
the lists of effects. For example, say, you had a spy attempting to
sabotage a city's city walls. Now two effects that a given city wall have
are:

effect          = 
    { "type",          "range",  "amount", "cond_bldg"
      "Spy_Resistant", "Local",  50
      "Spy_Resistant", "Local",  -50,      "Palace"
    }

Local in this context means that this effect _only_ matters for this
improvement. Let's read the definition:

"Spy_Resistant" - if a spy specifies a target for sabotage,
                  then she  has an AMOUNT percent chance to fail
                  (all Spy_Resistant's are summed before being applied)

Note that the second effect depends on there being a "Palace" in the same
city as the walls improvement (that's because it [the palace] confers 
Spy_Resistance of 50% on the entire city that it's in, and we don't want 
the wall to double the effect...).
Now to check to see if the Spy fails to sabotage the walls... For
motivation, let's say she begins with a 25% chance of failure. To apply
effects, we need to iterate through all the applicable effects, now we need 
to check for the Spy_Resistant effect in ALL the lists that affect the
walls. In this case, we need to look at 2. the Local list (that the
improvement has (actually stored as pcity->impr_effects[B_CITY]), the City
list where the walls are located (pcity->effects), the Island list (on
which that city is located
(pplayer->island_effects[map_get_continent(pcity->x, pcity->y)]), the
Player list for the player who owns the city and its improvement
(pplayer->effects), and finally the World list (game->effects). Each of
these lists could possibly have an effect which confers Spy_Resistant.

Instead of going though each one by hand, fortunately we have an iterator
function which helps us:

void effect_iterator_init(struct effect_iter *iter, unsigned int ranges,
                          struct player *pplayer, struct city *pcity,
                          int id, enum effect_type type);

which describes the kind of search to do and:

struct effect *effect_iterator_get_next_active(struct effect_iter *iter);

which returns an (active) matching effect.

  struct effect_iter iter;
  struct effect *eff;
  int failure_chance = 25;
  
  effect_iterator_init(&iter, EFR_LAST, pplayer, pcity, 
                       walls_impr_id, EFT_SPY_RESISTANT);
  while( (eff = effect_iterator_get_next_active(&iter)) ) {
    failure_chance += eff->defn->amount;
  }
 
my, wasn't that nice? A word on the init function the range EFR_LAST is a
synonym for iterate through all applicable ranges (as defined by pplayer,
pcity, and walls_impr_id). If you needed just the World and Island ranges
for some reason, you would do:

  effect_iterator_init(&iter, EFR_WORLD|EFR_ISLAND, pplayer, pcity,
                       walls_impr_id, EFT_SPY_RESISTANT);

so ranges can be ORed together. If you needed to look for all active
effects, use EFT_LAST instead of EFT_SPY_RESISTANT.

What else the patch does (the bonus):

Improvements aren't the only things that can have effects. Nations,
governments and techs can also have effects (any effects from these must
be World or Player ranged). Note: non-improvements effects are known to be
buggy in this version. Beware. Also easily extensible from this framework
are unit effects (which will be restricted to Local ranged effects).

What the patch doesn't do (the downside):

With the exception of the spaceship parts, this patch really does nothing
yet. Adding zany effects to buildings will do nothing to gameplay. This is
the framework patch. But as you can see from the above example, it ain't
hard to actually to the next step.

Oh, and island effects are not implemented yet. So don't specify anything
as Island ranged. This is the result of a bit of disagreement as to how to
proceed with regard to who defines an island.

There is a lot of debugging information (to be removed when it's committed)
that will help you see that effects are actually getting added and removed.

do ser -d 4:effects.c to see it.

Enjoy.

-mike

Attachment: effects1.diff.bz2
Description: effects1.diff.bz2

Attachment: buildings.ruleset.bz2
Description: buildings.ruleset.bz2


[Prev in Thread] Current Thread [Next in Thread]