"""Une partie : deux équipes de soldats, chaque équipe pilotée par un bot, tour par tour.""" from __future__ import annotations from dataclasses import dataclass import numpy as np from . import shot as S from .world import World @dataclass class Turn: team: int shooter: int shot: object result: S.ShotResult outcome: str # "kill", "teamkill", "obstacle", "out" class Match: def __init__(self, bot_left, bot_right, rng: np.random.Generator, soldiers: int = 3, max_turns: int = 40): self.bots = [bot_left, bot_right] self.world = World.random(rng, (soldiers, soldiers)) self.team = int(rng.integers(2)) # qui commence self.cursor = [0, 0] self.turns: list[Turn] = [] self.max_turns = max_turns self.stats = [{"tirs": 0, "kills": 0, "teamkills": 0} for _ in range(2)] def next_shooter(self, team): alive = self.world.alive(team) idx = alive[self.cursor[team] % len(alive)] self.cursor[team] += 1 return idx def over(self) -> bool: return self.winner() is not None or len(self.turns) >= self.max_turns def winner(self): a, b = len(self.world.alive(0)), len(self.world.alive(1)) if a and not b: return 0 if b and not a: return 1 if not a and not b: return -1 if len(self.turns) >= self.max_turns: return 0 if a > b else 1 if b > a else -1 # au temps : plus de survivants return None def plan(self): """Le bot de l'équipe dont c'est le tour choisit son tir (sans encore l'appliquer).""" team = self.team shooter = self.next_shooter(team) sh = self.bots[team].act(self.world, shooter) res = S.simulate(self.world, shooter, sh.g, sh.z, sh.target) return team, shooter, sh, res def commit(self, team, shooter, sh, res) -> Turn: st = self.stats[team] st["tirs"] += 1 if res.event == "soldier": victim = self.world.soldiers[res.hit_index] outcome = "teamkill" if victim.team == team else "kill" st["kills" if outcome == "kill" else "teamkills"] += 1 else: outcome = res.event S.apply(self.world, res) t = Turn(team, shooter, sh, res, outcome) self.turns.append(t) self.team = 1 - team if not self.world.alive(self.team): # l'autre équipe n'a plus personne self.team = team return t def step(self) -> Turn: return self.commit(*self.plan()) def play(self): while not self.over(): self.step() return self.winner()