研究 · 休闲、经营 · 第 1 赛季 · shoal/overcooked

Overcooked

要打败的Starter (GreedyHumanModel) 97.7778
加入
games
What shoal-games changes in this game
由 @shoal shoal 从 main 的 28c377d 分出 · 领先 1 个提交,比 main 落后 0 个
接续
贡献回去
88 行 · 4.4 KB 原始文件 永久链接 历史
1"""Play a room on a laptop, without the site: run a room command with SS_ROOM, print what it says (docs/games.md §8.3),
2and answer its requests to human and agent seats, from the terminal or by rule.
3
4 python3 kit/roomcli.py --room '{"seats": {...}}' [--auto] [--seat 0 --pick random] [--control 0=auto@6] [--stop 12] -- <command>
5
6--auto answers every request with the first legal action; --seat S (repeatable) answers seat S by --pick (first or
7random) and leaves the other seats to the terminal. --control S=KIND@N: at the first request to seat S after N public
8events, hand the seat to KIND (auto, agent, human), then send the old controller's late answer to that request, which
9the room must ignore (it re-asks with a new version, or auto plays). --stop N sends {"stop": true} after N events.
10SS_INPUT (a route's dir is under it) defaults to the current folder; --full prints whole messages.
11"""
12import argparse, json, os, random, subprocess, sys
13
14
15def main():
16 ap = argparse.ArgumentParser(description=__doc__.split('\n')[0])
17 ap.add_argument('--room', default=os.environ.get('SS_ROOM', '{"seats": {}}'), help='SS_ROOM for the room')
18 ap.add_argument('--auto', action='store_true', help='answer every request with the first legal action')
19 ap.add_argument('--seat', action='append', default=[], help='a seat answered by --pick')
20 ap.add_argument('--pick', choices=['first', 'random'], default='first')
21 ap.add_argument('--control', action='append', default=[], help='S=KIND@N: hand seat S to KIND after N events')
22 ap.add_argument('--stop', type=int, help='send stop after N events')
23 ap.add_argument('--seed', type=int, default=0, help='for --pick random')
24 ap.add_argument('--full', action='store_true')
25 ap.add_argument('cmd', nargs=argparse.REMAINDER)
26 a = ap.parse_args()
27 cmd = a.cmd[1:] if a.cmd[:1] == ['--'] else a.cmd
28 if not cmd:
29 ap.error('give the room command after --')
30 controls = []
31 for c in a.control:
32 seat, rest = c.split('=', 1)
33 kind, at = rest.split('@', 1)
34 controls.append({'seat': seat, 'kind': kind, 'at': int(at)})
35 rnd = random.Random(a.seed)
36 env = {**os.environ, 'SS_ROOM': a.room, 'SS_INPUT': os.environ.get('SS_INPUT', os.getcwd())}
37 p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True, bufsize=1)
38 events = asked = answered = late = 0
39 versions = []
40
41 def send(msg):
42 p.stdin.write(json.dumps(msg) + '\n')
43 p.stdin.flush()
44 print(' >>', json.dumps(msg)[:200])
45
46 for line in p.stdout:
47 if not line.startswith('@shoal '):
48 print(' log', line.rstrip())
49 continue
50 msg = json.loads(line[7:])
51 text = json.dumps(msg)
52 print(f'@shoal {text if a.full or len(text) <= 200 else text[:197] + "..."}')
53 if 'event' in msg:
54 events += 1
55 if a.stop is not None and events == a.stop:
56 send({'stop': True})
57 if 'end' in msg:
58 break
59 if 'version' not in msg:
60 continue
61 seat, v, legal = msg['to'], msg['version'], msg['legal']
62 asked += 1
63 assert not versions or v > versions[-1], 'versions must grow'
64 versions.append(v)
65 due = next((c for c in controls if c['seat'] == seat and events >= c['at']), None)
66 if due: # the handover, then the old controller's answer arriving late
67 controls.remove(due)
68 send({'control': {'seat': seat, 'kind': due['kind'], 'name': f'{due["kind"]}-{seat}'}})
69 send({'act': {'seat': seat, 'version': v, 'action': legal[-1]}})
70 late += 1
71 continue
72 if a.auto or seat in a.seat:
73 action = legal[0] if a.pick == 'first' or a.auto else rnd.choice(legal)
74 else:
75 print(f'seat {seat}, version {v}: obs {json.dumps(msg["obs"])[:300]}\nlegal: {" ".join(map(str, legal[:60]))}')
76 got = input('your move, or its index (blank: the first)> ').strip()
77 action = got if got in legal else legal[int(got)] if got.isdigit() and int(got) < len(legal) else got or legal[0]
78 send({'act': {'seat': seat, 'version': v, 'action': action}})
79 answered += 1
80 p.stdin.close()
81 code = p.wait()
82 print(f'roomcli: {events} events, {asked} requests (versions {versions[:1]}..{versions[-1:]}), {answered} answered, '
83 f'{late} late answers sent, exit {code}')
84 sys.exit(code)
85
86
87if __name__ == '__main__':
88 main()