| 1 | """The project's referee. check: the route's brain against the season's field, every opening, both colours; the score |
| 2 | is the share of points won (a win 1, a draw 0.5), each field brain a subtask. practice: one opening each, both colours, |
| 3 | a replay of every game in replays/. |
| 4 | python3 -I referee/play.py check|practice <route folder> |
| 5 | """ |
| 6 | import json, os, sys |
| 7 | |
| 8 | ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 9 | sys.path.insert(0, os.path.join(ROOT, 'kit')) |
| 10 | sys.path.insert(0, os.path.join(ROOT, 'referee')) |
| 11 | import league |
| 12 | from gomoku import match |
| 13 | |
| 14 | PY = [sys.executable, '-s'] |
| 15 | |
| 16 | |
| 17 | def brain(folder): |
| 18 | """A folder's brain: an executable named pbrain (any language, as Gomocup brains are), else bot.py.""" |
| 19 | exe = os.path.join(folder, 'pbrain') |
| 20 | if os.path.isfile(exe) and os.access(exe, os.X_OK): |
| 21 | return [exe], folder |
| 22 | if os.path.isfile(os.path.join(folder, 'bot.py')): |
| 23 | return [*PY, 'bot.py'], folder |
| 24 | sys.exit(f'No brain in {folder}: add bot.py (a Gomocup brain in Python) or an executable pbrain') |
| 25 | |
| 26 | |
| 27 | def openings(): |
| 28 | with open(os.path.join(ROOT, 'referee', 'openings.txt')) as f: |
| 29 | return [[tuple(map(int, p.split(','))) for p in l.split()] for l in f if l.strip() and not l.startswith('#')] |
| 30 | |
| 31 | |
| 32 | def main(mode, route): |
| 33 | me = brain(league.bot_dir(route)) |
| 34 | name = league.route_name() |
| 35 | ops = openings() if mode == 'check' else openings()[:1] |
| 36 | reps = league.Replays() if mode == 'practice' else None |
| 37 | subtasks = {} |
| 38 | for opp in league.field(os.path.join(ROOT, 'field')): |
| 39 | them = brain(os.path.join(ROOT, 'field', opp)) |
| 40 | points = 0.0 |
| 41 | for k, op in enumerate(ops): |
| 42 | for black in (0, 1): |
| 43 | seats = [me, them] if black == 0 else [them, me] |
| 44 | r = match(seats, op) |
| 45 | mine = black |
| 46 | points += 1.0 if r['winner'] == mine else 0.5 if r['winner'] is None else 0.0 |
| 47 | if reps: |
| 48 | who = [name, opp] if black == 0 else [opp, name] |
| 49 | r['players'] = who |
| 50 | end = 'a draw' if r['winner'] is None else f'{who[r["winner"]]} wins ({r["reason"]})' |
| 51 | reps.add(f'{opp}-{k}-{"black" if black == 0 else "white"}.json', r, f'{who[0]} (black) vs {who[1]} (white), opening {k + 1}', who, f'{end} in {len(r["moves"]) - r["opening"]} moves') |
| 52 | subtasks[opp] = points / (2 * len(ops)) |
| 53 | league.write_metrics(sum(subtasks.values()) / len(subtasks), subtasks) |
| 54 | |
| 55 | |
| 56 | if __name__ == '__main__': |
| 57 | main(sys.argv[1], sys.argv[2]) |