ChatCraft / backend /game /tech_tree.py
gabraken's picture
feat: add new units/buildings/map assets, admin routes, and frontend build
dd96d2f
from __future__ import annotations
from typing import TYPE_CHECKING
from .buildings import BuildingType, BuildingStatus
from .units import UnitType
if TYPE_CHECKING:
from .state import PlayerState
# unit_type -> required active buildings
UNIT_REQUIREMENTS: dict[UnitType, list[BuildingType]] = {
UnitType.SCV: [BuildingType.COMMAND_CENTER],
UnitType.MARINE: [BuildingType.BARRACKS],
UnitType.MEDIC: [BuildingType.BARRACKS, BuildingType.ENGINEERING_BAY],
UnitType.GOLIATH: [BuildingType.FACTORY],
UnitType.TANK: [BuildingType.FACTORY, BuildingType.ARMORY],
UnitType.WRAITH: [BuildingType.STARPORT],
}
# building_type -> required active buildings (to be able to construct it)
BUILDING_REQUIREMENTS: dict[BuildingType, list[BuildingType]] = {
BuildingType.COMMAND_CENTER: [],
BuildingType.SUPPLY_DEPOT: [],
BuildingType.REFINERY: [],
BuildingType.BARRACKS: [BuildingType.SUPPLY_DEPOT],
BuildingType.ENGINEERING_BAY: [BuildingType.BARRACKS],
BuildingType.FACTORY: [BuildingType.BARRACKS],
BuildingType.ARMORY: [BuildingType.FACTORY],
BuildingType.STARPORT: [BuildingType.FACTORY],
}
# unit_type -> building that produces it
PRODUCTION_SOURCES: dict[UnitType, BuildingType] = {
UnitType.SCV: BuildingType.COMMAND_CENTER,
UnitType.MARINE: BuildingType.BARRACKS,
UnitType.MEDIC: BuildingType.BARRACKS,
UnitType.GOLIATH: BuildingType.FACTORY,
UnitType.TANK: BuildingType.FACTORY,
UnitType.WRAITH: BuildingType.STARPORT,
}
def _active(player: "PlayerState", bt: BuildingType) -> bool:
return any(
b.building_type == bt
and b.status not in (BuildingStatus.CONSTRUCTING, BuildingStatus.DESTROYED)
for b in player.buildings.values()
)
def can_build(bt: BuildingType, player: "PlayerState") -> bool:
return all(_active(player, req) for req in BUILDING_REQUIREMENTS[bt])
def can_train(ut: UnitType, player: "PlayerState") -> bool:
return all(_active(player, req) for req in UNIT_REQUIREMENTS[ut])
def missing_for_build(bt: BuildingType, player: "PlayerState") -> list[BuildingType]:
return [req for req in BUILDING_REQUIREMENTS[bt] if not _active(player, req)]
def missing_for_train(ut: UnitType, player: "PlayerState") -> list[BuildingType]:
return [req for req in UNIT_REQUIREMENTS[ut] if not _active(player, req)]
def get_producer(ut: UnitType) -> BuildingType:
return PRODUCTION_SOURCES[ut]