Deal with farms and varying gather rates
This commit is contained in:
244
aoe/gather.py
244
aoe/gather.py
@@ -1,3 +1,5 @@
|
||||
import copy
|
||||
|
||||
from aoe.types import *
|
||||
|
||||
|
||||
@@ -5,23 +7,174 @@ from aoe.types import *
|
||||
class Gather():
|
||||
|
||||
|
||||
# Gathering occurs when a villager is assigned to some relevant Task.
|
||||
#
|
||||
# Each Task consumes a map resource (e.g., a boar) at some rate.
|
||||
# That rate is recorded in gather_rates.
|
||||
#
|
||||
# Map resources such as boars should not be confused with a player's
|
||||
# resource stockpile. For example, Wood as a map resource is consumed by
|
||||
# gathering, whereas the player's Wood resource amount is increased. As
|
||||
# another example, a boar is a map resource that is consumed and leads to
|
||||
# an increase in Food in the player's stockpile.
|
||||
#
|
||||
# When a Task is performed and a map resource is consumed, one or more
|
||||
# resources are added to the player's stockpile. The typical case is to
|
||||
# add one resource. E.g., when chopping wood, wood is added to the
|
||||
# player's stockpile. However, for some civs or technologies, more than one
|
||||
# resource may be gathered by a single Task. For example, there is a
|
||||
# technology that allows woodcutters to generate food as they gather wood.
|
||||
#
|
||||
# The resources gathered by a Task are recorded in gathered_resources.
|
||||
# Each Task is associated with 0 or more Resource->Int key-value pairs.
|
||||
# A Task gathers all resources associated with itself. The integer values
|
||||
# in the aforementioned pairs are multipliers. A value of 1 indicates
|
||||
# that the corresponding resource will be added to the player's stockpile
|
||||
# at the same rate that the world's resource is consumed. A higher value
|
||||
# indicates that the resource is added at a more favorable ratio to the
|
||||
# player, whereas a lower value indicates a less favorable ratio.
|
||||
#
|
||||
# To reiterate, a value in gather_rates indicates how quickly a world
|
||||
# resource is removed. It may have been better named "consumption_rates"
|
||||
# or something similar. On the other hand, to determine how quickly a
|
||||
# resource is actually added to the player's stockpile, you must consider
|
||||
# the gather rate from gather_rates *and* the corresponding multiplier from
|
||||
# gathered_resources.
|
||||
#
|
||||
# Buildings #
|
||||
#
|
||||
# Most gathering cannot be performed without one or more buildings. In
|
||||
# many cases, there are a few options for a building or set of buildings
|
||||
# that will allow the resource to be gathered. The dictionary
|
||||
# required_gather_buildings records which buildings are necessary and
|
||||
# sufficient to perform each gathering Task. For a given Task, there is a
|
||||
# corresponding list of sets. If the world contains *all* of the buildings
|
||||
# in *any* of those sets, then the Task can be performed. Otherwise, it
|
||||
# cannot.
|
||||
#
|
||||
# Varying Rates and Resource Exhaustion #
|
||||
#
|
||||
# The rate of consumption in gather_rates is not fixed over time. In
|
||||
# general, as a task is performed, the rate will either slow down or stop
|
||||
# entirely. For example, a lumber camp gets "stale" and the rate will drop
|
||||
# unless a new camp is built, and a gold mine will be exhausted and the
|
||||
# rate will effectively drop to zero until a new mine is built.
|
||||
#
|
||||
# Several data structures are involved in the implementation of this idea.
|
||||
# We assume the world at any given time has some amount of consumables
|
||||
# accessible to a player, which is stored in gatherable_amounts. This is
|
||||
# *not* the total amount of, e.g., wood available on the map. It is
|
||||
# instead the amount of, e.g., wood that can be consumed *at the current
|
||||
# rate* given the available buildings. This amount goes down as resources
|
||||
# are gathered and can go up as new buildings, such as lumber camps, are
|
||||
# built. Resources are subtracted from gatherable_amounts at a rate
|
||||
# determined by gather_rates and the number of villagers performing a Task.
|
||||
#
|
||||
# When the amount drops below 0, either the gather rate decreases (as in
|
||||
# the case of cutting wood) or that Task stops entirely (as in the case of
|
||||
# mining gold). If the rate merely decreases, the process repeats itself.
|
||||
# That is, the value in gatherable_amounts is increased, the value in
|
||||
# gather_rates is decreased, and another decrease will occur when the new
|
||||
# amount in gatherable_amounts is exhausted. The dictionary
|
||||
# gather_decrease_rates contains the multipliers by which the gather rate
|
||||
# is decreased when resource exhaustion occurs. A value of 0 indicates
|
||||
# that Task is stopped entirely.
|
||||
#
|
||||
# When a new building relevant for gathering, such as a lumber camp, is
|
||||
# created, the amount of the corresponding consumable in gatherable_amounts
|
||||
# is increased. If the gather rate was already at its original value, then
|
||||
# some fixed amount is simply added to the available consumable, which will
|
||||
# delay the next rate decrease. If the corresponding gather rate had
|
||||
# previously been decreased, that rate is reset to its ideal value. In
|
||||
# that case, the amount of available consumable is set to a value rather
|
||||
# than added to the current value because the current value was available
|
||||
# at a lower gather rate.
|
||||
#
|
||||
# A given building can provide access to various resources and may provide
|
||||
# access to more than one. For example, a mining camp could provide access
|
||||
# to gold, stone, both, or neither. The dictionary
|
||||
# buildings_gather_increase stores information about which Task or group of
|
||||
# Tasks can have their consumable amount increased when a particular
|
||||
# building is built. A user can specify which Tasks, if any, benefit from
|
||||
# a particular instance of a building, but the selected Tasks must be
|
||||
# available for that building according to buildings_gather_increase for
|
||||
# the choice to be considered valid. This is especially valuable for Town
|
||||
# Centers, which can be built near any number of resources. That same data
|
||||
# structure also stores the amount by which the relevant consumables are
|
||||
# increased (which is also the reset value for that entry of
|
||||
# gatherable_amounts in the case where a rate decrease has already
|
||||
# occurred).
|
||||
#
|
||||
# Note that gathered_resources, which contains the multipliers for
|
||||
# gather_rates and determines how much of a resource the player actually
|
||||
# receives, is not relevant for determining how quickly a resource is
|
||||
# exhausted. That calculation involves solely gatherable_amounts,
|
||||
# gather_rates, the number of villagers performing the Task, and the amount
|
||||
# of simulated time that passes.
|
||||
#
|
||||
# Known Limitations #
|
||||
#
|
||||
# There is currently no penalty for having too many villagers gathering at
|
||||
# a particular building (e.g., 100 lumberjacks at a single wood camp).
|
||||
# However, if there are not enough lumber camps, the scheduled decrease
|
||||
# will happen quickly in that case, which will help penalize it somewhat.
|
||||
#
|
||||
# We also do not put a ceiling on the amount of a world resource that can
|
||||
# be accessed. For example, we do not have a fixed amount of berries. If
|
||||
# a user continues building mills and assigning more villagers to berries,
|
||||
# they can do so indefinitely. We are trusting the user to know how many
|
||||
# resources are available on their map.
|
||||
#
|
||||
# Farming #
|
||||
#
|
||||
# Farming is a little different, and I don't feel like explaining it right
|
||||
# now.
|
||||
#
|
||||
|
||||
|
||||
|
||||
BIG_NUMBER = 1e6
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.gather_rates = {
|
||||
Tasks.BERRIES: {Resources.FOOD: 18.6/60},
|
||||
Tasks.SHEEP: {Resources.FOOD: 19.8/60},
|
||||
Tasks.BOAR: {Resources.FOOD: 24.6/60},
|
||||
Tasks.HUNT: {Resources.FOOD: 24.6/60},
|
||||
Tasks.FARM: {Resources.FOOD: 20/60},
|
||||
Tasks.FISH_VILLAGER: {Resources.FOOD: 25.8/60},
|
||||
Tasks.FISH_SHIP_SHORE: {Resources.FOOD: 16.8/60},
|
||||
Tasks.FISH_SHIP_DEEP: {Resources.FOOD: 29.4/60},
|
||||
Tasks.FISHTRAP: {Resources.FOOD: 21/60},
|
||||
Tasks.WOOD: {Resources.WOOD: 23.4/60},
|
||||
Tasks.GOLD: {Resources.GOLD: 22.8/60},
|
||||
Tasks.TRADECART: {Resources.GOLD: 25.9/60},
|
||||
Tasks.TRADECOG: {Resources.GOLD: 25.9/60},
|
||||
Tasks.RELIC: {Resources.GOLD: 30/60},
|
||||
Tasks.STONE: {Resources.STONE: 21.6/60},
|
||||
Tasks.BERRIES: 18.6/60,
|
||||
Tasks.SHEEP: 19.8/60,
|
||||
Tasks.BOAR: 24.6/60,
|
||||
Tasks.HUNT: 24.6/60,
|
||||
Tasks.FARM: 20/60,
|
||||
Tasks.FISH_VILLAGER: 25.8/60,
|
||||
Tasks.FISH_SHIP_SHORE: 16.8/60,
|
||||
Tasks.FISH_SHIP_DEEP: 29.4/60,
|
||||
Tasks.FISHTRAP: 21/60,
|
||||
Tasks.WOOD: 23.4/60,
|
||||
Tasks.GOLD: 22.8/60,
|
||||
Tasks.TRADECART: 25.9/60,
|
||||
Tasks.TRADECOG: 25.9/60,
|
||||
Tasks.RELIC: 30/60,
|
||||
Tasks.STONE: 21.6/60,
|
||||
Tasks.BUILD: 0,
|
||||
Tasks.IDLE: 0,
|
||||
}
|
||||
|
||||
self.original_gather_rates = copy.deepcopy(self.gather_rates)
|
||||
|
||||
self.gathered_resources = {
|
||||
Tasks.BERRIES: {Resources.FOOD: 1},
|
||||
Tasks.SHEEP: {Resources.FOOD: 1},
|
||||
Tasks.BOAR: {Resources.FOOD: 1},
|
||||
Tasks.HUNT: {Resources.FOOD: 1},
|
||||
Tasks.FARM: {Resources.FOOD: 1},
|
||||
Tasks.FISH_VILLAGER: {Resources.FOOD: 1},
|
||||
Tasks.FISH_SHIP_SHORE: {Resources.FOOD: 1},
|
||||
Tasks.FISH_SHIP_DEEP: {Resources.FOOD: 1},
|
||||
Tasks.FISHTRAP: {Resources.FOOD: 1},
|
||||
Tasks.WOOD: {Resources.WOOD: 1},
|
||||
Tasks.GOLD: {Resources.GOLD: 1},
|
||||
Tasks.TRADECART: {Resources.GOLD: 1},
|
||||
Tasks.TRADECOG: {Resources.GOLD: 1},
|
||||
Tasks.RELIC: {Resources.GOLD: 1},
|
||||
Tasks.STONE: {Resources.STONE: 1},
|
||||
Tasks.BUILD: {},
|
||||
Tasks.IDLE: {},
|
||||
}
|
||||
@@ -56,4 +209,63 @@ class Gather():
|
||||
Tasks.IDLE: [],
|
||||
}
|
||||
|
||||
self.improved_gather_buildings = {}
|
||||
self.gatherable_amounts = {
|
||||
# These will vary based on the map.
|
||||
# I am assuming Arabia with:
|
||||
# 6 forage bushes
|
||||
# 8 sheep
|
||||
# 2 boars
|
||||
# 4 deer
|
||||
Tasks.BERRIES: 6*125,
|
||||
Tasks.SHEEP: 8*100,
|
||||
Tasks.BOAR: 2*340,
|
||||
Tasks.HUNT: 4*140,
|
||||
Tasks.FARM: 0,
|
||||
# TODO next two should be shared
|
||||
Tasks.FISH_VILLAGER: 0,
|
||||
Tasks.FISH_SHIP_SHORE: 0,
|
||||
Tasks.FISH_SHIP_DEEP: 0,
|
||||
Tasks.FISHTRAP: 0,
|
||||
Tasks.WOOD: 0,
|
||||
Tasks.GOLD: 0,
|
||||
Tasks.TRADECART: Gather.BIG_NUMBER,
|
||||
Tasks.TRADECOG: Gather.BIG_NUMBER,
|
||||
Tasks.RELIC: Gather.BIG_NUMBER,
|
||||
Tasks.STONE: 0,
|
||||
}
|
||||
|
||||
self.buildings_gather_increase = {
|
||||
# Made-up numbers for now
|
||||
Buildings.LUMBERCAMP: {Tasks.WOOD: 1000},
|
||||
Buildings.MILL: {Tasks.HUNT: 4*140,
|
||||
Tasks.BERRIES: 6*125},
|
||||
Buildings.MININGCAMP: {Tasks.GOLD: 4*800,
|
||||
Tasks.STONE: 4*350},
|
||||
Buildings.FARM: {Tasks.FARM: 175},
|
||||
#Buildings.DOCK: {Tasks.WOOD: 100},
|
||||
Buildings.TOWNCENTER: {Tasks.WOOD: 2000,
|
||||
Tasks.GOLD: 4*800,
|
||||
Tasks.STONE: 4*350,
|
||||
Tasks.BERRIES: 6*125,
|
||||
Tasks.HUNT: 4*140}
|
||||
#Buildings.FISHTRAP: {Tasks.WOOD: 100},
|
||||
}
|
||||
|
||||
self.gather_decrease_rates = {
|
||||
# Made-up numbers for now
|
||||
Tasks.BERRIES: 0,
|
||||
Tasks.SHEEP: 0,
|
||||
Tasks.BOAR: 0,
|
||||
Tasks.HUNT: 0,
|
||||
Tasks.FARM: 0,
|
||||
Tasks.FISH_VILLAGER: 0.5,
|
||||
Tasks.FISH_SHIP_SHORE: 0.5,
|
||||
Tasks.FISH_SHIP_DEEP: 0,
|
||||
Tasks.FISHTRAP: 0,
|
||||
Tasks.WOOD: 0.85,
|
||||
Tasks.GOLD: 0,
|
||||
Tasks.TRADECART: 1,
|
||||
Tasks.TRADECOG: 1,
|
||||
Tasks.RELIC: 1,
|
||||
Tasks.STONE: 0,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user