Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2005:
[Freeciv-Dev] (PR#12873) OR Requirements for Buildings
Home

[Freeciv-Dev] (PR#12873) OR Requirements for Buildings

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12873) OR Requirements for Buildings
From: "Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx>
Date: Fri, 22 Apr 2005 18:13:45 -0700
Reply-to: bugs@xxxxxxxxxxx

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

---------- Forwarded message ----------
Date: Sat, 23 Apr 2005 01:47:20 +0100 (WET DST)
From: Vasco Alexandre Da Silva Costa <vasc@xxxxxxxxxxxxxx>
To: Benedict Adamson <badamson@xxxxxxxxxxx>
Cc: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] Re: OR Requirements for Buildings

On Fri, 22 Apr 2005, Benedict Adamson wrote:

> Using the new requirements style for buildings, how do I express that
> any one of several requirements is needed for a building, rather than
> requiring all the requirements in a list are necessary? Or is that not
> now possible?
>
> The Ancients rule-set has a Fish Market improvement, which could be
> built in a city adjacent to an Ocean tile or adjacent to a river tile.
> This was done by having a spec_gate = "River" and a terr_gate = "Ocean"

That does not happen just for the Ancients ruleset. Hydro Plant in the
default ruleset is also like that. This is what is there now:

reqs    =
    { "type", "name", "range"
      "Tech", "Electronics", "Player"
      "Building", "Factory", "City"
      "Terrain", "Mountains", "Adjacent"
      "Special", "River", "Adjacent"
    }

The pseudo-code for the check should be like this:

if (hasTech(ELECTRONICS)
    && hasBuilding(FACTORY)
    && (hasAdjacentTerrain(MOUNTAINS) || hasAdjacentSpecial(RIVER)))

That is not what the reqs definition above means. It has no way of using
the OR operator.

This worked in the old code, because of this:

  for (;*spec_gate!=S_NO_SPECIAL;spec_gate++) {
    if (map_has_special(pcity->tile, *spec_gate) ||
        is_special_near_tile(pcity->tile, *spec_gate)) {
      return TRUE;
    }
  }

  for (; *terr_gate != T_NONE; terr_gate++) {
    if (pcity->tile->terrain == *terr_gate
        || is_terrain_near_tile(pcity->tile, *terr_gate)) {
      return TRUE;
    }
  }

i.e. you only needed to meet either the terrain, or the special.

We got several possible options to fix this. Kludge by hardcoding (like
the old code did) or supporting more generic expressions for enablers.

The .ini format is too rigid to allow expressions like this easily,
unless we use a trick. If we use infix notation, or prefix notation, we
need to have some way to support changing operator priority, like ()s.
Which is near to impossible to parse using .ini format.

So an answer is: Reverse Polish Notation aka postfix notation. Like this:

sreqs    =
    { "type", "name", "range"
      "Tech", "Electronics", "Player"
      "Building", "Factory", "City"
      "Operator", "AND"
      "Terrain", "Mountains", "Adjacent"
      "Special", "River", "Adjacent"
      "Operator", "OR"
      "Operator", "AND"
    }

Super reqs. You can still store the expression as a list, and with a
stack you can calculate the expression pretty easily.

Sick no? The old effects expressions were hardcoded like this:

enable = (a && b && c && d...) && !(a || b || c || d...)

With the sreqs extension, we could do it like this for effects:

enable = reqs && nreqs

OR

enable = sreqs && !nsreqs

and like this for the things which do not require disablers:

enable = reqs

OR

enable = sreqs

---
Vasco Alexandre da Silva Costa @ Instituto Superior Tecnico, Lisboa








[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#12873) OR Requirements for Buildings, Vasco Alexandre da Silva Costa <=