RandomPlayer, HeuristicPlayer (MC tipper nad rozdaniami neznamych kariet + tipom riadena hracia heuristika) a McPlayer (MC ohodnotenie kazdeho kandidatskeho tahu nad rozdaniami konzistentnymi s dedukovanymi voidmi). Evaluacia s rotaciou sedadiel: py -m rl.evaluate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
"""Evaluacny harness: odohra N kol medzi 4 hracmi a spocita metriky.
|
|
|
|
Metriky per hrac (viz rl/DESIGN.md, sekcia 5): priemerne body na kolo
|
|
a presnost tipu (% kol s presne trafenym tipom). Sedadla sa medzi kolami
|
|
rotuju, aby ziadny hrac nebol systematicky zvyhodneny poradim tipovania.
|
|
|
|
Spustenie ako skript porovna baseline botov:
|
|
py -m rl.evaluate --rounds 500 --seed 7
|
|
"""
|
|
|
|
import argparse
|
|
from random import Random
|
|
|
|
from bridzik import ROUNDS_PER_SERIES
|
|
from rl.env import PHASE_GUESS, RoundEnv
|
|
|
|
|
|
def play_round(players: list, env: RoundEnv, round_number: int = None,
|
|
first_player: int = None) -> list:
|
|
"""Odohra jedno kolo; `players[seat]` rozhoduje za sedadlo `seat`.
|
|
|
|
Vrati body 4 sedadiel (`Round.get_points_summary()`).
|
|
"""
|
|
decision = env.reset(round_number, first_player)
|
|
while True:
|
|
seat = decision.player
|
|
if decision.phase == PHASE_GUESS:
|
|
action = players[seat].guess(env.round, seat)
|
|
else:
|
|
action = players[seat].play(env.round, seat)
|
|
decision, rewards, done = env.step(action)
|
|
if done:
|
|
return rewards
|
|
|
|
|
|
def evaluate(players: list, n_rounds: int, rng: Random = None,
|
|
round_numbers: list = None) -> list:
|
|
"""Odohra `n_rounds` kol s rotaciou sedadiel; vrati stats per hrac.
|
|
|
|
Vystup: zoznam dictov v poradi `players` --
|
|
{'avg_points': float, 'hit_rate': float, 'rounds': int}.
|
|
"""
|
|
rng = rng if rng is not None else Random()
|
|
env = RoundEnv(rng)
|
|
points = [0] * 4
|
|
hits = [0] * 4
|
|
for i in range(n_rounds):
|
|
round_number = rng.choice(round_numbers) if round_numbers \
|
|
else rng.randrange(ROUNDS_PER_SERIES)
|
|
# rotacia: sedadlo s obsadzuje players[(s + i) % 4]
|
|
seating = [players[(s + i) % 4] for s in range(4)]
|
|
rewards = play_round(seating, env, round_number)
|
|
for seat in range(4):
|
|
player_index = (seat + i) % 4
|
|
points[player_index] += rewards[seat]
|
|
hits[player_index] += rewards[seat] > 0
|
|
return [{'avg_points': points[p] / n_rounds,
|
|
'hit_rate': hits[p] / n_rounds,
|
|
'rounds': n_rounds} for p in range(len(players))]
|
|
|
|
|
|
def main():
|
|
from rl.players import HeuristicPlayer, RandomPlayer
|
|
|
|
parser = argparse.ArgumentParser(description='Evaluacia baseline botov')
|
|
parser.add_argument('--rounds', type=int, default=500)
|
|
parser.add_argument('--seed', type=int, default=7)
|
|
parser.add_argument('--mc-samples', type=int, default=100)
|
|
args = parser.parse_args()
|
|
|
|
rng = Random(args.seed)
|
|
lineups = [
|
|
('4x random', [RandomPlayer(rng) for _ in range(4)]),
|
|
('1x heuristika + 3x random',
|
|
[HeuristicPlayer(rng, n_samples=args.mc_samples)]
|
|
+ [RandomPlayer(rng) for _ in range(3)]),
|
|
('4x heuristika',
|
|
[HeuristicPlayer(rng, n_samples=args.mc_samples) for _ in range(4)]),
|
|
]
|
|
for label, players in lineups:
|
|
stats = evaluate(players, args.rounds, rng)
|
|
print(f'\n{label} ({args.rounds} kol):')
|
|
for i, s in enumerate(stats):
|
|
print(f' hrac {i}: {s["avg_points"]:6.2f} bodov/kolo, '
|
|
f'tip trafeny {100 * s["hit_rate"]:5.1f} %')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|