Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2000:
[Freeciv-Dev] TODO: proposal for format more flexible rulesets
Home

[Freeciv-Dev] TODO: proposal for format more flexible rulesets

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] TODO: proposal for format more flexible rulesets
From: Marc Strous <m.strous@xxxxxxxxxxx>
Date: Mon, 18 Sep 2000 16:24:44 +0200

this is a proposal for a format of a new version of the rulesets (v2?) as
proposed on Thue's TODO list, to increase the power of rulesets:

it is not yet completely worked out and what follows is probably not very
well explained. still i hope you will understand the general direction.

i agree, it is ambitious

* make a new ruleset called 'pools.ruleset' or 'treasury.ruleset' or a
reformatted 'government.ruleset' that instructs the server how to allocate
tile resources and how this can be influenced by the player. this ruleset
defines variables (VAR) and pools (POOL, such as the amount of food you
have in stock, the treasure, the amount of science you have etc). It
defines what type of specialists (taxman, scientist, elvis and whatever
else you like) are possible and what they do (on which pool they operate).
It also defines what sliders (SLIDER) should be displayed in city or
government windows, and their possible values).
definitions could look like this:

VAR "GranaryAfterGrowth" {"City", 0} /*means that this var is set for each
city and that the default is 0. 
VAR "GeneralSpecialistEfficiency" {"Player", 100} /* means that the
efficiency of specialists is 100 and that the scope of this variable is
nationwide
VAR "ChanceToLearnFreeTechKnownByOthers" {"Player", 0} /* can be modified
by great library

POOL "Shields" {"city"} /* means that each city has a pool named shields

SLIDER "Science" {"player", 0, 100, 10} /*means that each player has a
nationwide slider 'science' with minimum value 0, maximum value 100, and a
stepsize of 10

SPEC "Merchants" {"Marketplace"} /* means that merchants are a form of
specialists that are allowed after the building 'marketplace' has been built.

all these things can be defined by the designer of new game styles. 

* make a new ruleset named 'actions.ruleset'. This ruleset defines all unit
actions as well and, also important,  what to do at the end (or beginning)
of each turn. For example, part of the new turn action might look like this:

the format is: Pool_X = (calculation of the input (order of operators is
strictly as written), the pool where the input comes from, what happens if
there's not enough)

ACTION "newturn" {
  ...
;food
  Pool_Harvest = (Tiles_Food * Building_Bonuses,,)
  Pool_Unit_Food_Upkeep = (Var_UnitFood * Unit_Food_Upkeep, Pool_Harvest,
Unit_Disband)
  Pool_Granary = (Pool_Granary + Pool_Harvest, Pool_Harvest,)
  Pool_Rations = (Slider_Rations * Citizens / 10, Pool_Granary, Starve)
  Pool_City_Growth = (Var_FoodBoxFull - Pool_Granary,,CityGrow)
  Pool_Granary = (0 - Pool_CityGrowth max 0 / Pool_City_Growth *
Granary_After_Growth,,)
  ...
  }
This snippet would mean that each turn the server should add all the "food"
on the worked tiles (so the tiles.ruleset should state what can be found on
each tile (food, production, shields, whatever you desire as long as it
corresponds to the names used in calculations in this ruleset), and
multiply it with building bonuses (see below, buildings.ruleset). Part of
the contents of 'harvest' is then transfered to the pool
'unit_food_upkeep', but if there's not enough, units get disbanded. Next,
the granary is filled. Then citizens are given food ('pool_rations' and the
amount is calculated by multiplying the setting of Slider_Rations with the
number of citizens and dividing by 10. If there's not enough food in the
granary, citizens starve. Finally, city growth is dealt with by defining a
city growth pool that is calculated by subtracting the granary from the
variable foodboxfull. If granary is larger, citygrow is called. The final
calculation adjusts the value of the granary after growth (note that
pool_city_growth can never be 0).
For the calculations, variables, pools, specialists, slidersettings, all
defined in the pools.ruleset, are valid, and plain values. The operators
required are: "+", "-", "/", "*", "max". Things like Unit_Food_upkeep
(iterate through the units and add their food_upkeep) and Unit_Disband,
should all be hard-coded. With a surprisingly limited amount of such
hard-coded functions, i was able to include all features of freeciv, civ2
and CTP. And much more would be possible.

The most difficult part is probably to code the interpreter of this
ruleset. this function should translate the "calculations" supplied in the
ruleset to a series of operations on the actual values that can be called
in the server each turn. Probably the most elegant way is to let the
interpreter code brief bits of machine code that can then be called by the
server. it shouldn't be too difficult because the operations are simple and
should be executed simply in the order they are provided in the ruleset.
Alternatively, the ruleset could be translated to a char with instructions
to the newturn function that would work its way along these instructions
each time executing a switch statement with the operators, and finally
return the updated pool values.

The buildings.ruleset becomes a lot simpler, a couple of examples:

the format is:
"type" =
   "Plus" (added directly),
   "Bonus" (to multiply with tile_resources, corresponds with calculation
shown above, all bonuses will be added before the multiplication, but a
bonus that multiplies other bonuses could also be included),
   "PerCit" (to multiply with the number of citizens),
   "Resistant" (acquire a pct resistance against specified actions),
   "VarChange", to change a variable in the game. this could be anything,
vars defined in pools.ruleset, or variables in unit definitions etc.

"range" same as before,
"pool" on which pool this building operates,
"amount", self evident.

(from CTP aquaduct)
effect          =
    { "type", "range", "pool", "amount"
        "Plus", "City", "Overcrowding", -2
        "Bonus", "City", "Harvest", 20
    }
helptext        = _("\
Decreases overcrowding unhappiness with 2;\
 increases food by 20%.\
 ")

(from cathedral)
effect          =
    { "type", "range", "pool", "amount", "cond_gov"
        "Plus", "City", "Building Happiness", 3
        "Plus", "City", "Building Happiness", 2, "Theocracy"
        "Plus", "City", "Building Happiness", -2, "Communism"
    }
helptext        = _("\
Increases happiness by 3 (5 under Theocracy,\
 1 under Communism)\
")

(from CTP city wall)
effect          =
    { "type", "range", "pool", "action", "amount"
        "Plus", "City", "Defense", "", 4
        "Resistant", "City", "", "Enslave", 100
        "Resistant", "City", "", "Convert", 50
    }
helptext        = _("\
Gives +4 on defense and prevents attacks by slavers;\
 gives 50% protection against conversion attempts by\
 priests.\
")

from freeciv oracle
effect          =
    { "type", "range", "var", "amount"
        "varChange", "Player", "Building_Temple_Amount", 4
    }
helptext        = _("\
Temples produce double happiness.\
")

I think all buildings in different civ varieties can be accomodated this way

* In the units ruleset, units should get a new property called "actions",
partly replacing the unit flags.
Actions are all the actions a unit can do, simple and complex ones, such as
"pillage", "combat", "settle city", "spy", "make embassy", "bribe unit",
"enslave" etc. Cities can become resistant to specific actions by building
certain buildings (see above example). Unit and Buildings rulesets should
use the same action names.
Perhaps actions should be stored in action structures, and have member
values gold_cost, pollution_cost, food_costs, number of turns it takes to
complete, target), and a reference to a hard-coded function call to do the
action.

These structures could then be initialized using the actions.rulesets,
allowing for a considerable degree of freedom.

marc




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