Правила были такие: стратегия, на квадратной карте быстрее всех построить базу и разбомбить трёх таких же как ты врагов, ну или хотя бы успеть набрать больше всех очков.
Конечно это больше не программа, а поток сознания. В этом году учавствовать было особо некогда. К первому раунду подготовиться успеть толком не удалось, во второй как в прошлом году тоже впрыгнуть не лолучилось. Но всё равно было здорово и захватывающе. Закончил в песочнице на 431 месте с 35% побед. Результаты для потраченного времени считаю удовлетворительными.
Маленько про реализованные в стратегии идеи:
- Бойцы делятся на 3 направления: левое, правое и по центру. Но это не значит, что больше они никуда не пойдут. Расчитывается вес расстояния до врагов, но для своего направления координата важнее (в последней версии в 1.7 раза):
def nearest_left_weight(x, y):
result = int(x * 1.7 + y)
Это обеспечивает, что если бойцы в своём направлении всех победили, то будут двигаться дальше по карте, пока не победят остальных. Для просты деление на отряды происходило остатком от деления их id на 3 или 5 (7 тоже пробовал). - Реализован план застройки территории my_plan_to_build со списком необходимых зданий и их точными координатами. Из работяг выбирался один или два ответственных, которые при достаточном количестве денег и наличии свободного места шли строить в нужное место здания в соответствии с планом.
- Для удобства и понимания происходящего насоздавал много массивов-групп со своими (g_…) и вражескими (e_…) объектами. Это потом позволило писать простую логику. Ну и вообще был сделан массив-карта, по которой можно было выцеплять объекты по координатам, например my_map.get_entity(e_nearest_left_x, e_nearest_left_y) — вытащить ближайшего врага слева.
- Настроил бегство работяг, если враги наступают.
- Здания ремонтировали не все подряд, а формировалась бригада ремонтников. Но пока ремонтировать нечего — они тоже валили лес.
- Если базы рейнджеров ещё не было, а ресурсов уже было достаточно, то её готов был строить любой работяга в любом подходящем по размеру месте, не зависимо от плана застройки. Это позволяло быстрее побеждать врагов, пока им нечем защищаться.
- При подходящих условиях дома строить работягам тоже можно было где угодно при первой возможности. Это позволяло быстро нарастить население.
- Начал писать код, чтоб лучники на чужой территории в атаку шли так, чтоб стреллять по врагу одновременно, чтобы раньше его победить. Это давало небольшое преимущество.
- Пушками не увлекался, на долго их не хватает. Для атаки строил только лучников.
Остальное можно почитать в моём коде ниже 🙂
# 19
'''
если лучнику до вражеского лучника или пехоты 6 клеток не у себя на базе, то не двигаться, тогда можно выжить
если на базе, то всяко разно надо отбиваться
если лучник при смерти, и сзади свободно, то вообще отступить
'''
from model import *
import random
def distance(x1, y1, x2, y2):
result = ( (x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
return result
def nearest_left_weight(x, y):
result = int(x * 1.7 + y)
#print("nearest_left_weight(%s, %s) = %s" % (x, y, result) )
return result
def nearest_right_weight(x, y):
result = int(x + y * 1.7)
#print("nearest_right_weight(%s, %s) = %s" % (x, y, result) )
return result
def nearest_center_weight(x, y):
result = x + y
#print("nearest_center_weight(%s, %s) = %s" % (x, y, result) )
return result
def get_distance_weight(x1, y1, x2, y2):
result = (x2 - x1) ** 2 + (y2 - y1) ** 2
return result
class MyMap:
def __init__(self, player_view):
self.size = player_view.map_size
self.properties = player_view.entity_properties
self.entities = [] # доступ к элементам по остатку от деления координат
for i in range(0, self.size ** 2):
self.entities.append(None)
def get_entity(self, x, y):
result = self.entities[(x * self.size) + y]
return result
#def set_entity(self, x, y):
# pass
def add(self, entity):
for i in range(0, self.properties[entity.entity_type].size):
for j in range(0, self.properties[entity.entity_type].size):
self.entities[ ( (entity.position.x + i) * self.size ) + ( entity.position.y + j) ] = entity
def to_string(self):
i = 0
result = ""
for entity in self.entities:
if entity == None:
result += ' '
elif entity.entity_type == EntityType.RESOURCE:
result += 'W'
else:
result += 'x'
i += 1
if i >= self.size:
result += '\n'
i = 0
return result
def is_area_clear(self, x, y, size):
result = True
for i in range(size):
for j in range(size):
if self.get_entity(x + i, y + j) != None:
result = False
return result
def select_to_build(my_map, get_next, has_ranged_base):
# entity_type x y importance size
skipped = False
my_plan_to_build = [
#(EntityType.HOUSE, 5, 11, 100, 3),
#(EntityType.HOUSE, 11, 5, 100, 3),
(EntityType.HOUSE, 5, 6, 100, 3),
(EntityType.HOUSE, 5, 2, 100, 3),
#(EntityType.RANGED_BASE, 15, 5, 100, 5),
#(EntityType.RANGED_BASE, 11, 9, 100, 5),
#(EntityType.RANGED_BASE, 9, 11, 100, 5),
(EntityType.RANGED_BASE, 10, 4, 100, 5),
(EntityType.RANGED_BASE, 4, 10, 100, 5),
#(EntityType.HOUSE, 11, 11, 100, 3),
(EntityType.HOUSE, 2, 2, 100, 3),
(EntityType.HOUSE, 2, 5, 100, 3),
(EntityType.HOUSE, 1, 9, 100, 3),
#(EntityType.TURRET, 6, 22, 100, 2),
#(EntityType.TURRET, 22, 22, 100, 2),
#(EntityType.TURRET, 22, 6, 100, 2),
(EntityType.BUILDER_BASE, 6, 6, 100, 5),
(EntityType.HOUSE, 1, 11, 100, 3),
(EntityType.HOUSE, 1, 13, 100, 3),
(EntityType.HOUSE, 1, 17, 100, 3),
(EntityType.HOUSE, 1, 21, 100, 3),
(EntityType.HOUSE, 5, 2, 100, 3),
(EntityType.HOUSE, 9, 1, 100, 3),
(EntityType.HOUSE, 13, 1, 100, 3),
(EntityType.HOUSE, 17, 1, 100, 3),
(EntityType.HOUSE, 21, 1, 100, 3),
(EntityType.HOUSE, 21, 4, 100, 3),
(EntityType.HOUSE, 21, 8, 100, 3),
(EntityType.HOUSE, 21, 12, 100, 3),
(EntityType.HOUSE, 17, 12, 100, 3),
#(EntityType.HOUSE, 15, 12, 100, 3),
#(EntityType.HOUSE, 12, 15, 100, 3),
(EntityType.HOUSE, 12, 19, 100, 3),
(EntityType.HOUSE, 12, 23, 100, 3),
(EntityType.HOUSE, 8, 23, 100, 3),
(EntityType.HOUSE, 4, 23, 100, 3),
#(EntityType.TURRET, 21, 21, 100, 2),
(EntityType.TURRET, 4, 26, 100, 2),
(EntityType.TURRET, 10, 26, 100, 2),
(EntityType.TURRET, 30, 26, 100, 2),
(EntityType.TURRET, 26, 4, 100, 2),
(EntityType.TURRET, 26, 10, 100, 2),
(EntityType.TURRET, 26, 30, 100, 2),
(EntityType.RANGED_BASE, 5, 15, 100, 5),
#(EntityType.BUILDER_BASE, 11, 17, 100, 5),
]
for b in my_plan_to_build:
etype, x, y, importance, size = b
#print(my_map.to_string())
#print('my_map.get_entity(%s, %s) = %s' % (x, y, my_map.get_entity(x, y)))
#if my_map.get_entity(x, y) == None:
if my_map.is_area_clear(x, y, size):
if get_next and not skipped:
skipped = True
else:
print("to build: ", b)
if etype == EntityType.RANGED_BASE and has_ranged_base:
pass
else:
return b
class MyStrategy:
def get_action(self, player_view, debug_interface):
result = Action({})
my_id = player_view.my_id
my_player = None
for p in player_view.players:
if p.id == my_id:
my_player = p
if my_player == None:
print("Error: my_player == None")
# для поиска по id
entities_by_id = {}
# мои группы юнитов - по id
g_units = []
g_builder_units = []
g_melee_units = []
g_ranged_units = []
# строители
g_builders = [] # список
g_builders_count = 1 # сколько надо
g_builders_target = Vec2Int(20, 20) # куда идти собираются
# ремонтники
g_repairs = []
# хавестеры
#g_harvesters = []
# левое крыло
g_left_1 = []
#g_left_4 = []
#g_left_6 = []
# правое крыло
g_right_2 = []
#g_right_5 = []
#g_right_7 = []
# центр
g_center_3 = []
# охрана
#g_guard = []
# здания
g_houses = []
g_melee_bases = []
g_ranged_bases = []
g_builder_bases = []
# вражеские здания
e_buildings_left = []
e_buildings_center = []
e_buildings_right = []
# враги на нашей базе
e_units_on_base = []
e_units_on_base_left = []
e_units_on_base_right = []
e_nearest_left_x = player_view.map_size - 5
e_nearest_left_y = 5
e_nearest_left_weight = 10000
e_nearest_right_x = 5
e_nearest_right_y = player_view.map_size - 5
e_nearest_right_weight = 10000
e_nearest_center_x = player_view.map_size - 5
e_nearest_center_y = player_view.map_size - 5
e_nearest_center_weight = 10000
# очередь для ремонта
g_damaged_buildings = []
g_damaged_houses = []
g_damaged_ranged_bases = []
# карта
my_map = MyMap(player_view)
# вообще разобраться что творится
for entity in player_view.entities:
# индексируем, вдруг пригодится
entities_by_id[entity.id] = entity
# подтягиваем общие свойства объекта
properties = player_view.entity_properties[entity.entity_type]
# составляем карту
my_map.add(entity)
# если враг
if entity.player_id != my_id:
# считаем здания врагов
if entity.entity_type in (EntityType.HOUSE,
EntityType.MELEE_BASE,
EntityType.RANGED_BASE,
EntityType.BUILDER_BASE):
if entity.position.x < (player_view.map_size / 2):
e_buildings_left.append(entity.id)
elif entity.position.y < (player_view.map_size / 2):
e_buildings_right.append(entity.id)
else:
e_buildings_center.append(entity.id)
# ищем ближайших врагов по направлениям
if entity.entity_type != EntityType.RESOURCE:
if e_nearest_left_weight > nearest_left_weight(entity.position.x, entity.position.y):
e_nearest_left_weight = nearest_left_weight(entity.position.x, entity.position.y)
e_nearest_left_x = entity.position.x
e_nearest_left_y = entity.position.y
if e_nearest_right_weight > nearest_right_weight(entity.position.x, entity.position.y):
e_nearest_right_weight = nearest_right_weight(entity.position.x, entity.position.y)
e_nearest_right_x = entity.position.x
e_nearest_right_y = entity.position.y
if e_nearest_center_weight > nearest_center_weight(entity.position.x, entity.position.y):
e_nearest_center_weight = nearest_center_weight(entity.position.x, entity.position.y)
e_nearest_center_x = entity.position.x
e_nearest_center_y = entity.position.y
#print("found e_nearest_center_weight: ", e_nearest_center_weight)
# если наши
else:
# считаем, кто такой
if entity.entity_type == EntityType.MELEE_UNIT:
g_units.append(entity.id)
g_melee_units.append(entity.id)
if entity.entity_type == EntityType.RANGED_UNIT:
g_units.append(entity.id)
g_ranged_units.append(entity.id)
if entity.entity_type == EntityType.BUILDER_UNIT:
g_units.append(entity.id)
g_builder_units.append(entity.id)
# выбираем строителей
if len(g_builders) < g_builders_count and \
my_player.resource > 30: # чтоб не стоял на месте если денег нет
g_builders.append(entity.id)
# выбираем ремонтников
elif len(g_repairs) < len(g_builder_units) / 3:
g_repairs.append(entity.id)
if entity.entity_type == EntityType.BUILDER_BASE:
g_builder_bases.append(entity.id)
if entity.entity_type == EntityType.MELEE_BASE:
g_melee_bases.append(entity.id)
if entity.entity_type == EntityType.RANGED_BASE:
g_ranged_bases.append(entity.id)
if entity.entity_type == EntityType.HOUSE:
g_houses.append(entity.id)
# делим бойцов на отряды - по остатку от деления
tmpdiv = entity.id % 5
if tmpdiv in (1, 3):
g_left_1.append(entity.id)
elif tmpdiv in (2, 4):
g_right_2.append(entity.id)
else:
g_center_3.append(entity.id)
# выбираем хавестеров
# смотрим какие дома ремонтировать
if entity.health < properties.max_health:
if entity.entity_type in (EntityType.HOUSE,
EntityType.BUILDER_BASE,
EntityType.MELEE_BASE,
EntityType.RANGED_BASE,
EntityType.TURRET):
g_damaged_buildings.append(entity.id)
if entity.entity_type == EntityType.HOUSE:
g_damaged_houses.append(entity.id)
if entity.entity_type == EntityType.RANGED_BASE:
g_damaged_ranged_bases.append(entity.id)
# стратегические решения
# кэш чтоб 2 раза не считать
len_g_units = len(g_units)
len_g_builder_units = len(g_builder_units)
len_g_melee_units = len(g_melee_units)
len_g_ranged_units = len(g_ranged_units)
len_g_houses = len(g_houses)
len_g_damaged_buildings = len(g_damaged_buildings)
len_g_damaged_houses = len(g_damaged_houses)
len_g_damaged_ranged_bases = len(g_damaged_ranged_bases)
len_e_buildings_center = len(e_buildings_center)
len_e_buildings_left = len(e_buildings_left)
len_e_buildings_right = len(e_buildings_right)
# где что строить
build_entity_type = EntityType.HOUSE
build_x = 5
build_y = 11
build_importance = 1
build_size = 3
has_ranged_base = False if len(g_ranged_bases) == 0 else True
try:
if entity.id == g_builders[0]:
build_entity_type, build_x, build_y, build_importance, build_size = select_to_build(my_map, False, has_ranged_base)
else:
build_entity_type, build_x, build_y, build_importance, build_size = select_to_build(my_map, True, has_ranged_base)
except:
print("Нечего строить!!!")
# где что ремонтировать
repair_needed = False
repair_x = 5
repair_y = 11
repair_target = 1
# словарь заданий для ремонтников
repair_tasks = {}
# достраиваем базу лучников
if len_g_damaged_ranged_bases > 0:
print("ремонт базы лучников")
for r in g_repairs:
repair_tasks[r] = [0, 100000] # id здания и вес
for h in g_damaged_ranged_bases:
h_weight = get_distance_weight(
entities_by_id[r].position.x,
entities_by_id[r].position.y,
entities_by_id[h].position.x,
entities_by_id[h].position.y,
)
if h_weight < repair_tasks[r][1]:
repair_tasks[r][0] = h
repair_tasks[r][1] = h_weight
# ремонт только если хватает юнитов или усраться ресурсов
elif len_g_units > (len_g_houses - 1) * 4 or \
my_player.resource > 200:
# назначаем ремонтникам ближайшие недостроенные дома
if len_g_damaged_houses > 0:
print("ремонт дома")
for r in g_repairs:
repair_tasks[r] = [0, 100000] # id здания и вес
for h in g_damaged_houses:
h_weight = get_distance_weight(
entities_by_id[r].position.x,
entities_by_id[r].position.y,
entities_by_id[h].position.x,
entities_by_id[h].position.y,
)
if h_weight < repair_tasks[r][1]:
repair_tasks[r][0] = h
repair_tasks[r][1] = h_weight
# потом распределяем незанятым остальные повреждённые здания
elif len_g_damaged_buildings > 0:
print("ремонт здания")
for r in g_repairs:
repair_tasks[r] = [0, 100000] # id здания и вес
for h in g_damaged_buildings:
h_weight = get_distance_weight(
entities_by_id[r].position.x,
entities_by_id[r].position.y,
entities_by_id[h].position.x,
entities_by_id[h].position.y,
)
if h_weight < repair_tasks[r][1]:
repair_tasks[r][0] = h
repair_tasks[r][1] = h_weight
else:
print("мало народа")
'''
if len_g_damaged_houses > 0:
repair_target = g_damaged_houses[0]
repair_needed = True
repair_x = entities_by_id[repair_target].position.x
repair_y = entities_by_id[repair_target].position.y
elif len_g_damaged_buildings > 0:
repair_target = g_damaged_buildings[0]
repair_needed = True
repair_x = entities_by_id[repair_target].position.x
repair_y = entities_by_id[repair_target].position.y
'''
# отладка
print('Ремонтники: ', len(g_repairs))
print('Задания: ', repair_tasks)
#if len(g_damaged_buildings) > 0:
# tmpe = entities_by_id[g_damaged_buildings[0]]
# print("что надо ремонтировать: ", tmpe.position.x, ", ", tmpe.position.y)
#print("e_nearest_left_weight: ", e_nearest_left_weight)
#print("e_nearest_right_weight: ", e_nearest_right_weight)
#print("e_nearest_center_weight: ", e_nearest_center_weight)
# теперь решаем кому что делать
for entity in player_view.entities:
#print(entity) #debug
if entity.player_id != my_id:
continue
properties = player_view.entity_properties[entity.entity_type]
move_action = None
build_action = None
repair_action = None
attack_action = AttackAction(None, AutoAttack(properties.sight_range, [
EntityType.RESOURCE] if entity.entity_type == EntityType.BUILDER_UNIT else []))
if properties.can_move:
if entity.entity_type in (EntityType.MELEE_UNIT, EntityType.RANGED_UNIT):
enemies_buildings_sum = len_e_buildings_center + \
len_e_buildings_left + \
len_e_buildings_right
AttackAction(None, AutoAttack(properties.sight_range, []))
if entity.id in g_left_1:
# если не у себя, и враги подходят, то лучнику замереть
if entity.entity_type == EntityType.RANGED_UNIT and \
e_nearest_left_y > 35 and \
my_map.get_entity(e_nearest_left_x, e_nearest_left_y) != None and \
my_map.get_entity(e_nearest_left_x, e_nearest_left_y).entity_type in \
(EntityType.MELEE_UNIT, EntityType.RANGED_UNIT) and \
abs(e_nearest_left_y - entity.position.y) + \
abs(e_nearest_left_x - entity.position.x) == 6:
move_action = None
attack_action = None
elif player_view.current_tick < 500 or \
len_e_buildings_left > 0 or \
enemies_buildings_sum == 0:
move_action = MoveAction(
Vec2Int(e_nearest_left_x, e_nearest_left_y), True, True)
elif len(e_buildings_center) > 0:
move_action = MoveAction(
Vec2Int(int(player_view.map_size * 0.95),
int(player_view.map_size * 0.95) ),
True,
True)
else:
move_action = MoveAction(
Vec2Int(int(player_view.map_size * 0.95),
int(player_view.map_size * 0.05) ),
True,
True)
elif entity.id in g_right_2:
if entity.entity_type == EntityType.RANGED_UNIT and \
e_nearest_right_x > 35 and \
my_map.get_entity(e_nearest_right_x, e_nearest_right_y) != None and \
my_map.get_entity(e_nearest_right_x, e_nearest_right_y).entity_type in \
(EntityType.MELEE_UNIT, EntityType.RANGED_UNIT) and \
abs(e_nearest_right_y - entity.position.y) + \
abs(e_nearest_right_x - entity.position.x) == 6:
move_action = None
attack_action = None
elif player_view.current_tick < 500 or \
len_e_buildings_right > 0 or \
enemies_buildings_sum == 0:
move_action = MoveAction(
Vec2Int(e_nearest_right_x, e_nearest_right_y), True, True)
elif len(e_buildings_center) > 0:
move_action = MoveAction(
Vec2Int(int(player_view.map_size * 0.95),
int(player_view.map_size * 0.95) ),
True,
True)
else:
move_action = MoveAction(
Vec2Int(int(player_view.map_size * 0.05),
int(player_view.map_size * 0.95) ),
True,
True)
elif entity.id in g_center_3:
if entity.entity_type == EntityType.RANGED_UNIT and \
e_nearest_center_x + e_nearest_center_y > 40 and \
my_map.get_entity(e_nearest_center_x, e_nearest_center_y) != None and \
my_map.get_entity(e_nearest_center_x, e_nearest_center_y).entity_type in \
(EntityType.MELEE_UNIT, EntityType.RANGED_UNIT) and \
abs(e_nearest_center_y - entity.position.y) + \
abs(e_nearest_center_x - entity.position.x) == 6:
move_action = None
attack_action = None
elif player_view.current_tick < 500 or \
len_e_buildings_center > 0 or \
enemies_buildings_sum == 0:
move_action = MoveAction(
Vec2Int(e_nearest_center_x, e_nearest_center_y), True, True)
elif len(e_buildings_left) > 0:
move_action = MoveAction(
Vec2Int(int(player_view.map_size * 0.05),
int(player_view.map_size * 0.95) ),
True,
True)
else:
move_action = MoveAction(
Vec2Int(int(player_view.map_size * 0.95),
int(player_view.map_size * 0.05) ),
True,
True)
elif entity.entity_type == EntityType.BUILDER_UNIT:
# если враги рядом, то валим
if distance(entity.position.x,
entity.position.y,
e_nearest_left_x,
e_nearest_left_y) < 10:
move_action = MoveAction(Vec2Int(40, 5), True, True)
attack_action = None
elif distance(entity.position.x,
entity.position.y,
e_nearest_right_x,
e_nearest_right_y) < 10:
move_action = MoveAction(Vec2Int(5, 40), True, True)
attack_action = None
# дальше без паники разбираемся
elif entity.id in g_builders:
print("Я здесь: x=%s, y=%s" % (entity.position.x, entity.position.y))
#print('builder`s properties.build: ', properties.build)
if len(g_damaged_buildings) > 0:
move_action = None
attack_action = None
# идти строить
elif len(g_damaged_buildings) == 0 \
and build_importance > 0 \
and my_player.resource > player_view.entity_properties[build_entity_type].initial_cost:
# чтоб один строил сбоку, а второй сверху
if entity.id == g_builders[0]:
move_action = MoveAction(Vec2Int(build_x - 1, build_y), True, True)
else:
move_action = MoveAction(Vec2Int(build_x, build_y - 1), True, True)
attack_action = None
else: # валить лес
repair_action = None
attack_action = AttackAction(None, AutoAttack(properties.sight_range, [EntityType.RESOURCE]))
# если есть работа для ремонтников
elif entity.id in g_repairs:
'''
if repair_needed:
attack_action = None
move_action = MoveAction(Vec2Int(repair_x + 2,
repair_y + 2),
True, True)
repair_action = RepairAction(g_damaged_buildings[0])
'''
if entity.id in repair_tasks.keys():
if repair_tasks[entity.id][0] > 0:
attack_action = None
move_action = MoveAction(
Vec2Int(entities_by_id[repair_tasks[entity.id][0]].position.x+2,
entities_by_id[repair_tasks[entity.id][0]].position.y+2),
True, True)
repair_action = RepairAction(repair_tasks[entity.id][0])
else: # пусть валит лес
repair_action = None
attack_action = AttackAction(None, AutoAttack(properties.sight_range, [EntityType.RESOURCE]))
else:
# попробовать дом построить
if len_g_houses >= 2 and not has_ranged_base:
build_action = BuildAction(
EntityType.RANGED_BASE,
Vec2Int(entity.position.x, entity.position.y + 1) )
elif my_player.resource > 60 and \
len_g_damaged_houses < 3 and \
has_ranged_base and \
entity.position.x + entity.position.y < 50:
build_action = BuildAction(
EntityType.HOUSE,
Vec2Int(entity.position.x, entity.position.y + 1) )
# где-нибудь ресурсы искать
elif entity.id % 2 == 0:
move_action = MoveAction(Vec2Int(int(player_view.map_size * 0.5) - 10, 25),
True, True)
else:
move_action = MoveAction(Vec2Int(25, int(player_view.map_size * 0.5) - 10),
True, True)
# Строительство
if properties.build is not None:
# Если строитель
if entity.entity_type == EntityType.BUILDER_UNIT:
if entity.id in g_builders and \
my_player.resource > player_view.entity_properties[build_entity_type].initial_cost:
if len(g_damaged_buildings) == 0:
#print("Строю!")
build_action = BuildAction(
build_entity_type,
Vec2Int(build_x, build_y))
else: # надо что-то ремонтировать
pass
#print("Ремонтирую!")
#repair_action = RepairAction(g_damaged_buildings[0])
elif entity.id not in g_builders and \
entity.id not in g_repairs:
# обычные работяги могут строить дома в подходящих местах
if has_ranged_base and \
len_g_damaged_houses < 2 and \
entity.position.x + entity.position.y < 40 and \
entity.position.x % 5 == 4 and \
entity.position.y >= 4 and \
entity.position.y % 5 == 1 and \
(entity.position.x > entities_by_id[g_ranged_bases[0]].position.x + 2 or \
entity.position.x < entities_by_id[g_ranged_bases[0]].position.x + 2 \
) and \
(entity.position.x > entities_by_id[g_builder_bases[0]].position.x + 9 or \
entity.position.x < entities_by_id[g_builder_bases[0]].position.x + 2):
build_action = BuildAction(
EntityType.HOUSE,
#Vec2Int(entity.position.x, entity.position.y - 3)
Vec2Int(entity.position.x, entity.position.y - 4)
)
# Строим юнитов
entity_type = properties.build.options[0]
if entity.entity_type == EntityType.BUILDER_BASE and \
(len_g_ranged_units > len_g_builder_units - 8 or not has_ranged_base):
spawn_x = entity.position.x + properties.size
spawn_y = entity.position.y + properties.size
if my_map.get_entity(spawn_x, spawn_y) == None:
build_action = BuildAction(
entity_type,
Vec2Int(spawn_x, spawn_y - 1)
)
else:
build_action = BuildAction(
entity_type,
Vec2Int(spawn_x - 1, spawn_y)
)
elif entity.entity_type == EntityType.MELEE_BASE:
pass
'''
spawn_x = entity.position.x + properties.size
spawn_y = entity.position.y + properties.size
if my_map.get_entity(spawn_x, spawn_y) == None:
build_action = BuildAction(
entity_type,
Vec2Int(spawn_x, spawn_y - 1)
)
else:
build_action = BuildAction(
entity_type,
Vec2Int(spawn_x - 1, spawn_y)
)'''
elif entity.entity_type == EntityType.RANGED_BASE and \
my_player.resource > 80:
spawn_x = entity.position.x + properties.size
spawn_y = entity.position.y + properties.size
if my_map.get_entity(spawn_x, spawn_y) == None:
build_action = BuildAction(
EntityType.RANGED_UNIT,
Vec2Int(spawn_x, spawn_y - 1)
)
else:
build_action = BuildAction(
entity_type,
Vec2Int(spawn_x - 1, spawn_y)
)
#print("build_action: ", build_action)
result.entity_actions[entity.id] = EntityAction(
move_action,
build_action,
attack_action,
repair_action
)
return result
def debug_update(self, player_view, debug_interface):
debug_interface.send(DebugCommand.Clear())
debug_interface.get_state()