diff --git a/aoe/housing.py b/aoe/housing.py index e1172ab..4dc5ffb 100644 --- a/aoe/housing.py +++ b/aoe/housing.py @@ -12,3 +12,5 @@ class Housing(): Buildings.HOUSE: 5, Buildings.TOWNCENTER: 5, }) + + self.required = defaultdict(int, {u: 1 for u in Units}) diff --git a/aoe/production.py b/aoe/production.py index 38d7f36..e4334d5 100644 --- a/aoe/production.py +++ b/aoe/production.py @@ -1,3 +1,5 @@ +from collections import defaultdict + from aoe.types import * @@ -7,7 +9,7 @@ class Production(): # assumes for now each unit can be built in only one type of building def __init__(self): - self.building = { + self.building = defaultdict(None, { Units.VILLAGER: Buildings.TOWNCENTER, Units.TRADECART: Buildings.MARKET, Units.SPEARMAN: Buildings.BARRACKS, @@ -93,4 +95,4 @@ class Production(): Research.LOOM: Buildings.TOWNCENTER, Research.SAPPERS: Buildings.CASTLE, Research.BOMBARDTOWER: Buildings.UNIVERSITY, - } + }) diff --git a/aoe/world.py b/aoe/world.py index d030494..37a0f1f 100644 --- a/aoe/world.py +++ b/aoe/world.py @@ -54,6 +54,7 @@ class World(): # possibly other things # TODO gathering boars and hunting # spend villager time in exchange for adding gatherable resource + # TODO food spoilage # TODO use market for buy/sell @@ -68,19 +69,22 @@ class World(): self.resources[i] -= self.costs.costs[purchase][i] - def _check_research_dependencies(self, research): - self._check_dependencies(self.research_deps.dependencies[research]) + def _check_dependencies(self, thing): + thing_type = type(thing) + + if thing_type == Ages: + self._check_age_dependencies(thing) + else: + if thing_type == Buildings: + dependencies = self.building_deps.dependencies[thing] + elif thing_type == Units: + dependencies = self.unit_deps.dependencies[thing] + elif thing_type == Research: + dependencies = self.research_deps.dependencies[thing] + self._check_non_age_dependencies(dependencies) - def _check_building_dependencies(self, building): - self._check_dependencies(self.building_deps.dependencies[building]) - - - def _check_unit_dependencies(self, unit): - self._check_dependencies(self.unit_deps.dependencies[unit]) - - - def _check_dependencies(self, dependencies): + def _check_non_age_dependencies(self, dependencies): for dep in dependencies: if dep not in self.buildings and \ dep not in self.research and \ @@ -103,13 +107,6 @@ class World(): raise MissingDependencyException - def queue_research(self, research): - self._check_research_dependencies(research) - self._pay_cost(research) - - self._start_research(research) - - def _schedule_next_gather_rate_decrease(self, task): if task in [Tasks.IDLE, Tasks.BUILD]: return @@ -254,7 +251,8 @@ class World(): villagers_from_count = Counter(villagers_from) self._check_villager_move(villagers_from_count) - self._check_building_dependencies(building) + + self._check_dependencies(building) self._pay_cost(building) self._move_villagers_to_build(villagers_from_count) @@ -342,60 +340,40 @@ class World(): def _free_housing(self): pop_space = self._get_population_space() - original_queue_len = len(self.production_queue) - # Assumes each unit costs 1 pop - new_builds = [] i = 0 while (self._get_effective_population() < pop_space and - i < original_queue_len): + i < len(self.production_queue)): - unit = self.production_queue[i] - if self._check_production(unit): - if unit in Units: - self._build_unit(unit) - elif unit in Research: - self._start_research(unit) - new_builds.append(i) - - i += 1 - - self.production_queue = [self.production_queue[i] - for i in range(original_queue_len) - if i not in new_builds] + thing = self.production_queue[i] + if self._check_housing(thing) and self._check_production(thing): + self._start_producing(thing) + del self.production_queue[i] + else: + i += 1 - def _free_production_building_of_unit(self, unit): - building = self.production.building[unit] + def _free_production_building_of_thing(self, thing): + building = self.production.building[thing] self._free_production_building(building) def _free_production_building(self, building): self.production_available[building] += 1 - # Start the next queued unit if one exists + # Start the next queued thing if one exists ready_index = None - ready_unit = None + ready_thing = None for i in range(len(self.production_queue)): - unit = self.production_queue[i] - if self.production.building[unit] == building: + thing = self.production_queue[i] + if self.production.building[thing] == building: ready_index = i - ready_unit = unit + ready_thing = thing break if ready_index: self.production_queue.remove(i) - if unit in Units: - self._build_unit(unit) - elif unit in Research: - self._start_research(unit) - - - def _check_housing(self, unit): - # assumes for now that all units cost 1 pop - pop_space = sum([self.housing.space[building] for building in self.buildings]) - if self._get_effective_population() >= pop_space: - raise YallGotHousedException + self._start_producing(thing) def _check_gather(self, task, count=1): @@ -415,51 +393,37 @@ class World(): raise GatherBuildingNotAvailableException + def _check_housing(self, thing): + required = self.housing.required[thing] + + if required > 0: + pop_space = self._get_population_space() + if self._get_effective_population() > pop_space + required: + raise YallGotHousedException + + def _check_production(self, unit): building = self.production.building[unit] if self.production_available[building] < 1: raise ProductionBuildingNotAvailableException - def _use_production_for_research(self, research): - self._check_production(research) + def _use_housing_and_production(self, thing): + self._check_housing(thing) + self._check_production(thing) - building = self.production.building[research] - self.production_available[building] -= 1 + building = self.production.building[thing] + if building is not None: + self.production_available[building] -= 1 - - def _add_research(self, research): - self.research.append(research) - ResearchEffects.complete_research(self, research) - self._free_production_building_of_unit(research) - - - def _start_research(self, research): - try: - self._use_production_for_research(research) - except ProductionBuildingNotAvailableException: - self.production_queue.append(research) - else: - update_time = self.current_time + self.build_times.build_times[research] - self.events[update_time].append((self._add_research, (research,))) - - - def _use_housing_and_production(self, unit): - self._check_housing(unit) - self._check_production(unit) - - building = self.production.building[unit] - - self.production_available[building] -= 1 - self.units_being_built += 1 + self.units_being_built += self.housing.required[thing] def _kill_unit(self, unit, task=None): if unit == Units.VILLAGER and not task: raise IllegalVillagerMoveException - # assumes population of 1 for every unit - self.population -= 1 + self.population -= self.housing.required(unit) if unit == Units.VILLAGER: self.assign_villager(task, None) @@ -467,39 +431,49 @@ class World(): self._free_housing() - def _add_unit(self, unit, initial_task): - # assumes population of 1 for every unit - self.units_being_built -= 1 - self.population += 1 - self._free_production_building_of_unit(unit) + def _add_thing(self, thing, initial_task): + self.units_being_built -= self.housing.required[thing] + self.population += self.housing.required[thing] - if unit == Units.VILLAGER: + if thing in Research: + self.research.append(thing) + ResearchEffects.complete_research(self, thing) + + self._free_production_building_of_thing(thing) + + if thing == Units.VILLAGER: self.villagers += 1 self.villager_tasks[Tasks.IDLE] += 1 self.assign_villager(Tasks.IDLE, initial_task) - def _build_unit(self, unit, initial_task): + def _start_producing(self, thing, initial_task): try: - self._use_housing_and_production(unit) + self._use_housing_and_production(thing) except ProductionBuildingNotAvailableException: - self.production_queue.append(unit) - except YallGotHousedException: - pass + self.production_queue.append(thing) else: - update_time = self.current_time + self.build_times.build_times[unit] - self.events[update_time].append((self._add_unit, (unit, initial_task,))) + update_time = self.current_time + self.build_times.build_times[thing] + self.events[update_time].append((self._add_thing, (thing, initial_task,))) - def queue_unit(self, unit, initial_task=None): - self._check_unit_dependencies(unit) - self._pay_cost(unit) + def _queue_thing(self, thing, initial_task=None): + self._check_dependencies(thing) + self._pay_cost(thing) - self._build_unit(unit, initial_task) + self._start_producing(thing, initial_task) + + + def queue_research(self, research): + self._queue_thing(research) + + + def queue_unit(self, unit): + self._queue_thing(unit) def queue_villager(self, initial_task): - self.queue_unit(Units.VILLAGER, initial_task) + self._queue_thing(Units.VILLAGER, initial_task) def _gather_resources_for_duration(self, duration):