|
|
@@ -345,9 +345,9 @@ class Grid(BaseClass):
|
|
|
|
|
|
k_convert_number = -10
|
|
|
k_convert_distance = 10
|
|
|
- k_convert_danger = 30
|
|
|
- k_shoot_opponent_cultist = 10
|
|
|
- k_shoot_opponent_cult_leader = 5
|
|
|
+ k_convert_danger = 20
|
|
|
+ k_shoot_opponent_cultist = 15
|
|
|
+ k_shoot_opponent_cult_leader = 10
|
|
|
k0_protect_cult_leader = 30
|
|
|
k_protect_threat_level = -5
|
|
|
k_cover_threat = 10
|
|
|
@@ -372,12 +372,11 @@ class Grid(BaseClass):
|
|
|
key=(lambda pos: pos in self.index and self.index[pos].neutral),
|
|
|
limit=min(4, len(self.neutrals()))
|
|
|
)
|
|
|
- # log(conversion_path)
|
|
|
+ log(conversion_path)
|
|
|
|
|
|
# Conversion des neutres
|
|
|
if cult_leader and conversion_path:
|
|
|
path = conversion_path.next_candidate()
|
|
|
- log(path)
|
|
|
if path:
|
|
|
targets = [self.index[c] for c in path[-1].candidates]
|
|
|
|
|
|
@@ -392,17 +391,18 @@ class Grid(BaseClass):
|
|
|
action = ActionMove(cult_leader, path[1].pos, f'go convert {",".join([str(t.id) for t in targets])}')
|
|
|
actions.put(priority, action)
|
|
|
|
|
|
- # Attaque d'unités ennemies
|
|
|
+ # Tire sur une unités ennemies
|
|
|
targets = self.opponent_cultists()
|
|
|
if opponent_cult_leader:
|
|
|
targets.append(opponent_cult_leader)
|
|
|
|
|
|
- advantage = sum([t.hp for t in targets]) < sum([u.hp for u in self.owned_units()])
|
|
|
+ has_advantage = sum([t.hp for t in targets]) < sum([u.hp for u in self.owned_units()])
|
|
|
|
|
|
for a in self.allied_cultists():
|
|
|
for u in targets:
|
|
|
shooting_distance = self.shooting_distance(a.pos, u.pos)
|
|
|
- log(f"{a.id} - {u.id} - {self.line(a.pos, u.pos)[1:]}")
|
|
|
+ if a.id == 4 and u.id == 1:
|
|
|
+ log(self.line_of_sight(a.pos, u.pos))
|
|
|
if shooting_distance and shooting_distance < u.SHOOTING_RANGE:
|
|
|
action = ActionShoot(a, u)
|
|
|
|
|
|
@@ -440,9 +440,9 @@ class Grid(BaseClass):
|
|
|
covers = [n for n in self.neighbors(*cult_leader.pos) if self.can_move_on(cult_leader, n)]
|
|
|
|
|
|
for pos in covers:
|
|
|
- action = ActionMove(cult_leader, pos, 'take cover')
|
|
|
+ action = ActionMove(cult_leader, pos, f'take cover (t: {current_threat})')
|
|
|
|
|
|
- interest = conversion_path and conversion_path.steps and conversion_path.steps[0].pos == pos
|
|
|
+ interest = conversion_path and conversion_path.steps and pos in [s.pos for s in conversion_path.steps]
|
|
|
|
|
|
priority = k0_protect_cult_leader
|
|
|
priority += k_protect_threat_level * current_threat
|
|
|
@@ -492,44 +492,41 @@ class Grid(BaseClass):
|
|
|
return zone
|
|
|
|
|
|
@classmethod
|
|
|
- def line(cls, from_, to_):
|
|
|
- """ Implementation of bresenham's algorithm """
|
|
|
- xa, ya = from_
|
|
|
- xb, yb = to_
|
|
|
+ def line(cls, start, target):
|
|
|
+ """
|
|
|
+ adapted from https://github.com/fragkakis/bresenham/blob/master/src/main/java/org/fragkakis/Bresenham.java
|
|
|
+ if strict is true, None is return if an obstacle interrupted the line; else a partial line is returned (from start to obstacle)
|
|
|
+ """
|
|
|
+ line = []
|
|
|
|
|
|
- if (xa, ya) == (xb, yb):
|
|
|
- return [(xa, ya)]
|
|
|
+ x0, y0 = start
|
|
|
+ x1, y1 = target
|
|
|
|
|
|
- # diagonal symmetry
|
|
|
- vertically_oriented = (abs(yb - ya) > abs(xb - xa))
|
|
|
- if vertically_oriented:
|
|
|
- ya, xa, yb, xb = xa, ya, xb, yb
|
|
|
+ dx = abs(x1 - x0)
|
|
|
+ dy = abs(y1 - y0)
|
|
|
|
|
|
- # horizontal symmetry
|
|
|
- reversed_sym = (xa > xb)
|
|
|
- if reversed_sym:
|
|
|
- xb, yb, xa, ya = xa, ya, xb, yb
|
|
|
+ sx = 1 if x0 < x1 else -1
|
|
|
+ sy = 1 if y0 < y1 else -1
|
|
|
|
|
|
- # angle
|
|
|
- dx, dy = xb - xa, yb - ya
|
|
|
- alpha = (abs(dy) / dx)
|
|
|
+ err = dx - dy
|
|
|
+ x, y = x0, y0
|
|
|
|
|
|
- offset = 0.0
|
|
|
- step = 1 if dy > 0 else -1
|
|
|
+ while 1:
|
|
|
+ line.append((x, y))
|
|
|
+
|
|
|
+ if x == x1 and y == y1:
|
|
|
+ break
|
|
|
|
|
|
- result = []
|
|
|
- y_ = ya
|
|
|
- for x_ in range(xa, xb + 1):
|
|
|
- result.append((y_, x_) if vertically_oriented else (x_, y_))
|
|
|
+ e2 = 2 * err
|
|
|
+ if e2 > (-1 * dy):
|
|
|
+ err -= dy
|
|
|
+ x += sx
|
|
|
|
|
|
- offset += alpha
|
|
|
- if offset > 0.51:
|
|
|
- y_ += step
|
|
|
- offset -= 1.0
|
|
|
+ if e2 < dx:
|
|
|
+ err += dx
|
|
|
+ y += sy
|
|
|
|
|
|
- if reversed_sym:
|
|
|
- result.reverse()
|
|
|
- return result
|
|
|
+ return line
|
|
|
|
|
|
def line_of_sight(self, from_, to_):
|
|
|
line = self.line(from_, to_)[1:]
|
|
|
@@ -687,6 +684,7 @@ class Grid(BaseClass):
|
|
|
return ConversionPath.make_from_discovery_node(best_node)
|
|
|
|
|
|
def _repr_cell(self, pos):
|
|
|
+ return f"{self.threat[pos]}"
|
|
|
# return f"{self.control[pos]}/{self.threat[pos]}"
|
|
|
# return self.heat_map[pos]
|
|
|
|
|
|
@@ -724,7 +722,6 @@ while 1:
|
|
|
# TODO: ajouter une action "s'interposer" où une unité s'interpose entre le leader et un ennemi ; à mettre en balance avec le 'take cover'
|
|
|
# TODO: remplacer le discover par un algo qui cherche le plus court chemin pour relier tous les neutres les uns après les autres
|
|
|
|
|
|
-
|
|
|
GRID.reinit_round()
|
|
|
for _ in range(int(input())):
|
|
|
GRID.update_unit(*[int(j) for j in input().split()])
|
|
|
@@ -734,11 +731,11 @@ while 1:
|
|
|
|
|
|
actions = GRID.list_actions()
|
|
|
|
|
|
+ print("\n" + GRID.graph(), file=sys.stderr)
|
|
|
+
|
|
|
for action in actions.items:
|
|
|
log(f"* {action}")
|
|
|
|
|
|
- # print("\n" + GRID.graph(), file=sys.stderr)
|
|
|
-
|
|
|
try:
|
|
|
action = actions.get()
|
|
|
except IndexError:
|