1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
# This script provides an overview of the zero_ad wrapper for 0 AD
# First, we will define some helper functions we will use later.
import math
from os import path
import zero_ad
def dist(p1, p2):
return math.sqrt(sum(math.pow(x2 - x1, 2) for (x1, x2) in zip(p1, p2, strict=False)))
def center(units):
sum_position = map(sum, zip(*(u.position() for u in units), strict=False))
return [x / len(units) for x in sum_position]
def closest(units, position):
dists = (dist(unit.position(), position) for unit in units)
index = 0
min_dist = next(dists)
for i, d in enumerate(dists):
if d < min_dist:
index = i
min_dist = d
return units[index]
# Connect to a 0 AD game server listening at localhost:6000
game = zero_ad.ZeroAD("http://localhost:6000")
# Load the Arcadia map
samples_dir = path.dirname(path.realpath(__file__))
scenario_config_path = path.join(samples_dir, "arcadia.json")
with open(scenario_config_path, encoding="utf-8") as f:
arcadia_config = f.read()
state = game.reset(arcadia_config)
# The game is paused and will only progress upon calling "step"
state = game.step()
# Units can be queried from the game state
citizen_soldiers = state.units(owner=1, entity_type="infantry")
# (including gaia units like trees or other resources)
nearby_tree = closest(state.units(owner=0, entity_type="tree"), center(citizen_soldiers))
# Action commands can be created using zero_ad.actions
collect_wood = zero_ad.actions.gather(citizen_soldiers, nearby_tree)
female_citizens = state.units(owner=1, entity_type="female_citizen")
house_tpl = "structures/spart/house"
x = 680
z = 640
build_house = zero_ad.actions.construct(female_citizens, house_tpl, x, z, autocontinue=True)
# These commands can then be applied to the game in a `step` command
state = game.step([collect_wood, build_house])
# We can also fetch units by id using the `unit` function on the game state
female_id = female_citizens[0].id()
female_citizen = state.unit(female_id)
# A variety of unit information can be queried from the unit:
print("female citizen's max health is", female_citizen.max_health())
# Raw data for units and game states are available via the data attribute
print(female_citizen.data)
# Units can be built using the "train action"
civic_center = state.units(owner=1, entity_type="civil_centre")[0]
spearman_type = "units/spart/infantry_spearman_b"
train_spearmen = zero_ad.actions.train([civic_center], spearman_type)
state = game.step([train_spearmen])
# Let's step the engine until the house has been built
def is_unit_busy(state, unit_id):
return len(state.unit(unit_id).data["unitAIOrderData"]) > 0
while is_unit_busy(state, female_id):
state = game.step()
# The units for the other army can also be controlled
enemy_units = state.units(owner=2)
walk = zero_ad.actions.walk(enemy_units, *civic_center.position())
game.step([walk], player=[2])
# Step the game engine a bit to give them some time to walk
for _ in range(150):
state = game.step()
# Let's attack with our entire military
state = game.step([zero_ad.actions.chat("An attack is coming!")])
while len(state.units(owner=2, entity_type="unit")) > 0:
attack_units = [
unit for unit in state.units(owner=1, entity_type="unit") if "female" not in unit.type()
]
target = closest(state.units(owner=2, entity_type="unit"), center(attack_units))
state = game.step([zero_ad.actions.attack(attack_units, target)])
while state.unit(target.id()):
state = game.step()
game.step([zero_ad.actions.chat("The enemies have been vanquished. Our home is safe again.")])
|