|
15 | 15 | from .network import setup_controller, ZMQPublisher |
16 | 16 | from .base_utils import default_rng |
17 | 17 | from .team import make_team |
18 | | -from .spec import GameState |
| 18 | +from .spec import GameState, Layout, Pos |
19 | 19 | from .viewer import ProgressViewer, AsciiViewer, ReplyToViewer, ReplayWriter, ResultPrinter |
20 | 20 |
|
21 | 21 | _logger = logging.getLogger(__name__) |
@@ -276,7 +276,7 @@ def setup_viewers(viewers, print_result=True): |
276 | 276 | return viewer_state |
277 | 277 |
|
278 | 278 |
|
279 | | -def setup_game(team_specs, *, layout_dict, max_rounds=300, rng=None, |
| 279 | +def setup_game(team_specs, *, layout_dict: Layout, max_rounds=300, rng=None, |
280 | 280 | allow_camping=False, error_limit=5, timeout_length=3, |
281 | 281 | viewers=None, store_output=False, |
282 | 282 | team_names=(None, None), team_infos=(None, None), |
@@ -324,118 +324,118 @@ def setup_game(team_specs, *, layout_dict, max_rounds=300, rng=None, |
324 | 324 |
|
325 | 325 | # Initialize the game state. |
326 | 326 |
|
327 | | - game_state: GameState = dict( |
| 327 | + game_state: GameState = { |
328 | 328 | ### The layout attributes |
329 | 329 | #: Walls. Set of (int, int) |
330 | | - walls=set(layout_dict['walls']), |
| 330 | + 'walls': set(layout_dict['walls']), |
331 | 331 |
|
332 | 332 | #: Shape of the maze. (int, int) |
333 | | - shape=layout_dict['shape'], |
| 333 | + 'shape': layout_dict['shape'], |
334 | 334 |
|
335 | 335 | #: Food per team. List of sets of (int, int) |
336 | | - food=food, |
| 336 | + 'food': food, |
337 | 337 |
|
338 | 338 | #: Food ages per team. Dict of (int, int) to int |
339 | | - food_age=[{}, {}], |
| 339 | + 'food_age': ({}, {}), |
340 | 340 |
|
341 | 341 | ### Round/turn information |
342 | 342 | #: Current bot, int, None |
343 | | - turn=None, |
| 343 | + 'turn': None, |
344 | 344 |
|
345 | 345 | #: Current round, int, None |
346 | | - round=None, |
| 346 | + 'round': None, |
347 | 347 |
|
348 | 348 | #: Is the game finished? bool |
349 | | - gameover=False, |
| 349 | + 'gameover': False, |
350 | 350 |
|
351 | 351 | #: Who won? int, None |
352 | | - whowins=None, |
| 352 | + 'whowins': None, |
353 | 353 |
|
354 | 354 | ### Bot/team status |
355 | 355 | #: Positions of all bots. List of (int, int) |
356 | | - bots=layout_dict['bots'][:], |
| 356 | + 'bots': layout_dict['bots'][:], |
357 | 357 |
|
358 | 358 | #: Score of the teams. List of int |
359 | | - score=[0] * 2, |
| 359 | + 'score': (0, 0), |
360 | 360 |
|
361 | 361 | #: Fatal errors |
362 | | - fatal_errors=[[], []], |
| 362 | + 'fatal_errors': ([], []), |
363 | 363 |
|
364 | 364 | #: Errors |
365 | | - errors=[{}, {}], |
| 365 | + 'errors': ({}, {}), |
366 | 366 |
|
367 | 367 | ### Configuration |
368 | 368 | #: Maximum number of rounds, int |
369 | | - max_rounds=max_rounds, |
| 369 | + 'max_rounds': max_rounds, |
370 | 370 |
|
371 | 371 | #: Time till timeout, int |
372 | | - timeout=3, |
| 372 | + 'timeout': 3, |
373 | 373 |
|
374 | 374 | #: Noise radius, int |
375 | | - noise_radius=NOISE_RADIUS, |
| 375 | + 'noise_radius': NOISE_RADIUS, |
376 | 376 |
|
377 | 377 | #: Sight distance, int |
378 | | - sight_distance=SIGHT_DISTANCE, |
| 378 | + 'sight_distance': SIGHT_DISTANCE, |
379 | 379 |
|
380 | 380 | #: Max food age |
381 | | - max_food_age=max_food_age, |
| 381 | + 'max_food_age': max_food_age, |
382 | 382 |
|
383 | 383 | #: Shadow distance, int |
384 | | - shadow_distance=SHADOW_DISTANCE, |
| 384 | + 'shadow_distance': SHADOW_DISTANCE, |
385 | 385 |
|
386 | 386 | ### Informative |
387 | 387 |
|
388 | 388 | #: Name of the teams. Tuple of str |
389 | | - team_names=team_names, |
| 389 | + 'team_names': team_names, |
390 | 390 |
|
391 | 391 | #: Additional team info. Tuple of str|None |
392 | | - team_infos=team_infos, |
| 392 | + 'team_infos': team_infos, |
393 | 393 |
|
394 | 394 | #: Time each team needed, list of float |
395 | | - team_time=[0, 0], |
| 395 | + 'team_time': (0.0, 0.0), |
396 | 396 |
|
397 | 397 | # List of bot deaths, which counts the number of deaths per bot |
398 | 398 | # In other words, deaths[bot_idx] is the number of times the bot |
399 | 399 | # bot_idx has been killed until now. |
400 | | - deaths = [0]*4, |
| 400 | + 'deaths': [0] * 4, |
401 | 401 |
|
402 | 402 | # List of bot kills, which counts the number of kills per bot |
403 | 403 | # In other words, kills[bot_idx] is the number of times the bot |
404 | 404 | # bot_idx has killed another bot until now. |
405 | | - kills = [0]*4, |
| 405 | + 'kills': [0] * 4, |
406 | 406 |
|
407 | 407 | # List of boolean flags weather bot has been eaten since its last move |
408 | | - bot_was_killed = [False]*4, |
| 408 | + 'bot_was_killed': [False]*4, |
409 | 409 |
|
410 | 410 | # The noisy positions that the bot in `turn` has currently been shown. |
411 | 411 | # None, if not noisy |
412 | | - noisy_positions = [None] * 4, |
| 412 | + 'noisy_positions': [None] * 4, |
413 | 413 |
|
414 | 414 | #: The moves that the bots returned. Keeps only the recent one at the respective bot’s index. |
415 | | - requested_moves=[None] * 4, |
| 415 | + 'requested_moves': [None] * 4, |
416 | 416 |
|
417 | 417 | #: Messages the bots say. Keeps only the recent one at the respective bot’s index. |
418 | | - say=[""] * 4, |
| 418 | + 'say': [""] * 4, |
419 | 419 |
|
420 | 420 | ### Internal |
421 | 421 | #: Internal team representation |
422 | | - teams=[None] * 2, |
| 422 | + 'teams': [None] * 2, |
423 | 423 |
|
424 | 424 | #: Random number generator |
425 | | - rng=rng, |
| 425 | + 'rng': rng, |
426 | 426 |
|
427 | 427 | #: Timeout length, int, None |
428 | | - timeout_length=timeout_length, |
| 428 | + 'timeout_length': timeout_length, |
429 | 429 |
|
430 | 430 | #: Error limit. A team loses when the limit is reached, int |
431 | | - error_limit=error_limit, |
| 431 | + 'error_limit': error_limit, |
432 | 432 |
|
433 | 433 | #: Viewers, list |
434 | | - viewers=viewer_state['viewers'], |
| 434 | + 'viewers': viewer_state['viewers'], |
435 | 435 |
|
436 | 436 | #: Controller |
437 | | - controller=viewer_state['controller'] |
438 | | - ) |
| 437 | + 'controller': viewer_state['controller'] |
| 438 | + } |
439 | 439 |
|
440 | 440 | # Wait until the controller tells us that it is ready |
441 | 441 | # We then can send the initial maze |
@@ -596,20 +596,20 @@ def prepare_bot_state(game_state, idx=None): |
596 | 596 | 'error_count': [len(e) for e in game_state['errors'][:]], |
597 | 597 | 'food': [list(team_food) for team_food in game_state['food']], |
598 | 598 | 'shaded_food': shaded_food, |
599 | | - 'team_names': game_state['team_names'][:], |
600 | 599 | 'team_time': game_state['team_time'][:], |
601 | 600 | 'is_noisy': is_noisy, |
602 | 601 | 'round': game_state['round'], |
603 | 602 | 'turn': turn, |
604 | 603 | 'timeout_length': game_state['timeout_length'], |
605 | | - 'max_rounds': game_state['max_rounds'], |
606 | 604 | } |
607 | 605 |
|
608 | 606 | if bot_initialization: |
609 | 607 | bot_state.update({ |
610 | 608 | 'walls': game_state['walls'], # only in initial round |
611 | 609 | 'shape': game_state['shape'], # only in initial round |
612 | | - 'seed': seed # only used in set_initial phase |
| 610 | + 'seed': seed, # only used in set_initial phase |
| 611 | + 'max_rounds': game_state['max_rounds'], |
| 612 | + 'team_names': game_state['team_names'][:], |
613 | 613 | }) |
614 | 614 |
|
615 | 615 | return bot_state |
@@ -1036,8 +1036,8 @@ def check_exit_remote_teams(game_state): |
1036 | 1036 | pass |
1037 | 1037 |
|
1038 | 1038 |
|
1039 | | -def split_food(width, food): |
1040 | | - team_food = [set(), set()] |
| 1039 | +def split_food(width, food: list[Pos]): |
| 1040 | + team_food: tuple[set[Pos], set[Pos]] = (set(), set()) |
1041 | 1041 | for pos in food: |
1042 | 1042 | idx = pos[0] // (width // 2) |
1043 | 1043 | team_food[idx].add(pos) |
|
0 commit comments