Check XYZ Within City Borders

carloscodex

Chieftain
Joined
Sep 14, 2012
Messages
66
Location
Pleasanton (San Francisco), Ca
HasXYZWithinCityBorders -- Explanation, Reasonings, Thoughts, Questions

Determines if certain _things_ are within the city borders. These things are
anything that the game currently does not have a check for. As an example,
worked resources are checked by adding an entry in the XML (Table),
"Building_LocalResourceOrs" and "Building_LocalResourceAnds". These two
create a requirement for "worked" resources.

There are other programmable prerequisites for buildings such as:
- other buildings
- technologies
- general empire resource amounts
- global instances
- per player instances

I did not find a few of the prerequisites checking that I needed, so I am
starting to build it.

This is where I need the community's help. Am I duplicating work? Do these
checks already exist in the game? Is there already a somewhat-standard library
that everyone uses for some of these prerequisite checks? I would love to find
out and I will post at the forums. In the meantime, this is my aim:

For Cities:
- HasFeatureWithinCityBorders(feature)
- HasTerrainWithinCityBorders(terrain)
- HasFeatureInRadius(feature, radius)
- HasTerrainInRadius(terrain, radius)
- HasConnectedResource(resource)
- HasConnectedResourceArea(resource, area)


Ownership

For now, I am taking the liberty of just saying if the _thing_ is within
the city radius (whether it is 3, less, or more -- 5) then it counts as being
"accessible" and therefore returns true.

It is therefore possible for two or more cities to share the benefit of this
unworked and unimproved _thing_.

The point is that these tests can be used to determine if a _thing_ is close
enough to a city to have some small impact (without having to be worked).


Progression

As an example, I could test for FLINT as a requirement for building a
FIREPIT in a city. But, improving FLINT (creating an OUTPOST at the plot), on
the other hand, could provide additional bonsues, such as enhanced arrowheads
for archers and a new PROMOTION.

The idea is to progress the level of effect that terrain, resources,
features, and other _things_ have on a city and/or civilization.

The full FLINT example:

Plot + FLINT = no bonus to Plot
FLINT within City borders = allow building
Outpost created on FLINT = promotion for primitive archers
2nd level improvement (tech req.) = bonus production on plot


Balance

Since I am adding resources to the game, I want to limit their immediate gains.
FLINT gave no default extras. I do this because I use the ResourceGen script
which I think adds new resources in _addition_ to the standard set. If I were
to add luxury-type resources I would probably also lower the happiness gain
down to 3.


Performance

To start, I could organize logic for esacpe tests, such as asking the City if
it has a resource (meaning it is improved). Then, there is no need to proceed
with the plot checks. B

Since I am testing all plots within range of each city, I am bound to double or
triple check the plots. If there are 200 cities in the game, each with 37 plots,
that would be 7400 plot checks. I could keep a lookup table to avoid overlap
but that wouldn't be much of a gain.

For resource checking I may be able to get a gain by using the resource as the
starting plot and checking for cities within their radius -- maybe -- especially
if there are more cities than resources.


Non-Resource Performance

For other checks, such as "HasFeatureWithinCity(__ForestID__)", I would stick
with the city-first strategy.


Finally

Since I am new to all this, I could be rewriting methods and actions that
already exist or that others have already created. I am still dissecting code
and reading APIs (a little sparse -- I hope I can contribute).

Please let me know if something is already there or if you have suggestions
on better ways to do this.


Thanks!



Code:
-- simplified: removed debug and comments
function HasResourceWithinCity( iPlayer, p_resource )

  local player = Players[iPlayer]; -- we're all players in the end
  local playerHuman = player:IsHuman();

  for city in player:Cities() do

    local plot = city:Plot()
    local x = plot:GetX()
    local y = plot:GetY()
    local r = 3
    local t = null

    for dx = -r, r do
      for dy = -r, r do
        plot = Map.PlotXYWithRangeCheck(x, y, dx, dy, r)
        if plot then
          t = plot:GetResourceType()
          if t and t>0 and t==p_resource then
            return plot:IsPlayerCityRadius(player) and plot:IsOwned()
          end
        end
      end
    end
    
  end

  return false

end

-- float error kept giving me 41.99999999999999999
 
Back
Top Bottom