Initial commit, with rules 0.5 and basic bots
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""Bot decisions on the fixture board (positions as in test_engine.py)."""
|
||||
|
||||
import random
|
||||
|
||||
import pytest
|
||||
from scripted import make_game, put
|
||||
|
||||
from dojo.board import Board, Pos
|
||||
from dojo.bots import (
|
||||
AGGRESSIVE,
|
||||
BALANCED,
|
||||
FARMER,
|
||||
PROFILES,
|
||||
HeuristicAgent,
|
||||
Profile,
|
||||
RandomAgent,
|
||||
win_probability,
|
||||
)
|
||||
from dojo.engine import Agent, FightView, Game, RandomSource
|
||||
from dojo.rules import VARIANT_A, VARIANT_B, Card, RulesConfig
|
||||
|
||||
ALLENAMENTO = Pos(0, 5)
|
||||
FATICA = Pos(3, 6)
|
||||
TATAMI = Pos(4, 4)
|
||||
DOJO_ENTRANCE = Pos(5, 7)
|
||||
DOJO = Pos(6, 7)
|
||||
|
||||
|
||||
def test_win_probability_counts_senshu_and_bonuses() -> None:
|
||||
assert win_probability(0, 0) == pytest.approx(21 / 36)
|
||||
assert win_probability(2, 0) == pytest.approx(30 / 36)
|
||||
assert win_probability(0, 2) == pytest.approx(10 / 36)
|
||||
|
||||
|
||||
def test_heuristic_prefers_allenamento_to_fatica() -> None:
|
||||
game, _, _ = make_game()
|
||||
|
||||
choice = HeuristicAgent().choose_path(game.view(0), [(FATICA,), (ALLENAMENTO,)])
|
||||
|
||||
assert choice == (ALLENAMENTO,)
|
||||
|
||||
|
||||
def test_brown_heuristic_takes_the_exam_when_it_can() -> None:
|
||||
game, _, _ = make_game()
|
||||
put(game, 0, DOJO_ENTRANCE, track=15)
|
||||
|
||||
choice = HeuristicAgent().choose_path(game.view(0), [(ALLENAMENTO,), (DOJO,)])
|
||||
|
||||
assert choice == (DOJO,)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("profile", "fights"), [(FARMER, False), (AGGRESSIVE, True)])
|
||||
def test_profiles_differ_on_an_even_fight(profile: Profile, fights: bool) -> None:
|
||||
game, _, _ = make_game()
|
||||
put(game, 0, Pos(4, 3), track=3)
|
||||
put(game, 1, TATAMI, track=3)
|
||||
choice = HeuristicAgent(profile).choose_path(game.view(0), [(Pos(5, 3),), (TATAMI,)])
|
||||
|
||||
assert (choice == (TATAMI,)) is fights
|
||||
|
||||
|
||||
def fight(attacker_total: int, defender_total: int) -> FightView:
|
||||
return FightView(0, 1, False, attacker_total, defender_total, played=())
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("me", "card", "totals", "plays"),
|
||||
[
|
||||
(0, Card.KIAI, (3, 5), True), # 5 ties 5: Senshu gives it to the attacker.
|
||||
(0, Card.KIAI, (2, 5), False), # Kiai cannot turn it: keep it.
|
||||
(0, Card.KIAI, (5, 5), False), # Already winning.
|
||||
(1, Card.KIAI, (5, 4), True), # The defender needs to beat, not tie.
|
||||
(1, Card.KIAI, (6, 4), False),
|
||||
(0, Card.KAESHI, (1, 6), True), # Losing: a reroll can only help.
|
||||
(1, Card.UKE, (4, 4), True),
|
||||
],
|
||||
)
|
||||
def test_heuristic_plays_a_tecnica_only_when_losing(
|
||||
me: int, card: Card, totals: tuple[int, int], plays: bool
|
||||
) -> None:
|
||||
game, _, _ = make_game()
|
||||
game.players[me].tecnica = card
|
||||
|
||||
assert HeuristicAgent().play_tecnica(game.view(me), fight(*totals)) is plays
|
||||
|
||||
|
||||
def test_heuristic_keeps_the_tecnica_its_profile_ranks_first() -> None:
|
||||
game, _, _ = make_game()
|
||||
|
||||
assert HeuristicAgent(BALANCED).keep_tecnica(game.view(0), Card.UKE, Card.KIAI) is Card.KIAI
|
||||
assert HeuristicAgent(FARMER).keep_tecnica(game.view(0), Card.UKE, Card.KIAI) is Card.UKE
|
||||
|
||||
|
||||
def play(board: Board, config: RulesConfig, seed: int) -> Game:
|
||||
rng = random.Random(seed)
|
||||
agents: list[Agent] = [HeuristicAgent(p) for p in PROFILES.values()]
|
||||
agents.append(RandomAgent(rng))
|
||||
game = Game(board, config, agents, RandomSource(seed))
|
||||
game.run()
|
||||
return game
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config", [VARIANT_A, VARIANT_B])
|
||||
def test_bots_play_full_games_reproducibly(board: Board, config: RulesConfig) -> None:
|
||||
first, again = play(board, config, seed=7), play(board, config, seed=7)
|
||||
|
||||
assert first.winner is not None
|
||||
assert first.events == again.events
|
||||
Reference in New Issue
Block a user