pacai.eightpuzzle.bin

The main executable for running a game of 8 Puzzle.

  1"""
  2The main executable for running a game of 8 Puzzle.
  3"""
  4
  5import argparse
  6import logging
  7import random
  8import sys
  9
 10import pacai.core.log
 11import pacai.eightpuzzle.board
 12import pacai.eightpuzzle.problem
 13import pacai.search.common
 14import pacai.util.alias
 15import pacai.util.reflection
 16
 17def run(args: argparse.Namespace) -> int:
 18    """ Run a single game of 8 Puzzle. """
 19
 20    rng = random.Random(args.seed)
 21    logging.debug("Using seed %d.", args.seed)
 22
 23    puzzle = pacai.eightpuzzle.board.from_rng(rng)
 24    print(f"Starting Puzzle:\n{puzzle}\n")
 25
 26    solver = pacai.util.reflection.fetch(args.solver)
 27    problem = pacai.eightpuzzle.problem.EightPuzzleSearchProblem(puzzle)
 28
 29    solution = solver(problem, pacai.search.common.null_heuristic, rng)
 30    print(f"Solver ({args.solver}) found a path of {len(solution.actions)} moves: {solution.actions}.\n")
 31
 32    current_puzzle = puzzle
 33    for (i, action) in enumerate(solution.actions):
 34        if (args.interactive):
 35            input('Press return for the next step ...')
 36
 37        current_puzzle = current_puzzle.apply_action(action)
 38        print(f"After {i + 1} moves:\n{current_puzzle}\n")
 39
 40    print('Puzzle Solved!')
 41
 42    return 0
 43
 44def set_cli_args(parser: argparse.ArgumentParser) -> None:
 45    """
 46    Set specific CLI arguments.
 47    This is a sibling to init_from_args(), as the arguments set here can be interpreted there.
 48    """
 49
 50    parser.add_argument('--seed', dest = 'seed',
 51            action = 'store', type = int, default = None,
 52            help = 'The random seed for the game (will be randomly generated if not set.')
 53
 54    parser.add_argument('--interactive', dest = 'interactive',
 55            action = 'store_true', default = False,
 56            help = 'Wait until the user presses enter to show the next state (default: %(default)s).')
 57
 58    parser.add_argument('--solver', dest = 'solver', metavar = 'SOLVER',
 59            action = 'store', type = str, default = pacai.util.alias.SEARCH_SOLVER_RANDOM.short,
 60            help = ('A reflection reference to the solver (pacai.core.search.SearchProblemSolver) to use (default: %(default)s).'
 61                    + ' Not all solvers can solve this problem.'
 62                    + f' Builtin solvers: {pacai.util.alias.SEARCH_SOLVER_SHORT_NAMES}.'))
 63
 64def init_from_args(args: argparse.Namespace) -> argparse.Namespace:
 65    """
 66    Take in args from a parser that was passed to set_cli_args(),
 67    and initialize the proper components.
 68    """
 69
 70    if (args.seed is None):
 71        args.seed = random.randint(0, 2**64)
 72
 73    return args
 74
 75def _parse_args(parser: argparse.ArgumentParser) -> argparse.Namespace:
 76    """ Parse the args from the parser returned by _get_parser(). """
 77
 78    args = parser.parse_args()
 79
 80    # Parse logging arguments.
 81    args = pacai.core.log.init_from_args(parser, args)
 82
 83    # Parse specific options.
 84    args = init_from_args(args)
 85
 86    return args
 87
 88def _get_parser() -> argparse.ArgumentParser:
 89    """ Get a parser with all the options set to handle PacMan. """
 90
 91    parser = argparse.ArgumentParser(description = "Play a game of 8 Puzzle.")
 92
 93    # Add logging arguments.
 94    pacai.core.log.set_cli_args(parser)
 95
 96    # Add specific options.
 97    set_cli_args(parser)
 98
 99    return parser
100
101def main() -> int:
102    """ Invoke a game of 8 Puzzle. """
103
104    args = _parse_args(_get_parser())
105    return run(args)
106
107if (__name__ == '__main__'):
108    sys.exit(main())
def run(args: argparse.Namespace) -> int:
18def run(args: argparse.Namespace) -> int:
19    """ Run a single game of 8 Puzzle. """
20
21    rng = random.Random(args.seed)
22    logging.debug("Using seed %d.", args.seed)
23
24    puzzle = pacai.eightpuzzle.board.from_rng(rng)
25    print(f"Starting Puzzle:\n{puzzle}\n")
26
27    solver = pacai.util.reflection.fetch(args.solver)
28    problem = pacai.eightpuzzle.problem.EightPuzzleSearchProblem(puzzle)
29
30    solution = solver(problem, pacai.search.common.null_heuristic, rng)
31    print(f"Solver ({args.solver}) found a path of {len(solution.actions)} moves: {solution.actions}.\n")
32
33    current_puzzle = puzzle
34    for (i, action) in enumerate(solution.actions):
35        if (args.interactive):
36            input('Press return for the next step ...')
37
38        current_puzzle = current_puzzle.apply_action(action)
39        print(f"After {i + 1} moves:\n{current_puzzle}\n")
40
41    print('Puzzle Solved!')
42
43    return 0

Run a single game of 8 Puzzle.

def set_cli_args(parser: argparse.ArgumentParser) -> None:
45def set_cli_args(parser: argparse.ArgumentParser) -> None:
46    """
47    Set specific CLI arguments.
48    This is a sibling to init_from_args(), as the arguments set here can be interpreted there.
49    """
50
51    parser.add_argument('--seed', dest = 'seed',
52            action = 'store', type = int, default = None,
53            help = 'The random seed for the game (will be randomly generated if not set.')
54
55    parser.add_argument('--interactive', dest = 'interactive',
56            action = 'store_true', default = False,
57            help = 'Wait until the user presses enter to show the next state (default: %(default)s).')
58
59    parser.add_argument('--solver', dest = 'solver', metavar = 'SOLVER',
60            action = 'store', type = str, default = pacai.util.alias.SEARCH_SOLVER_RANDOM.short,
61            help = ('A reflection reference to the solver (pacai.core.search.SearchProblemSolver) to use (default: %(default)s).'
62                    + ' Not all solvers can solve this problem.'
63                    + f' Builtin solvers: {pacai.util.alias.SEARCH_SOLVER_SHORT_NAMES}.'))

Set specific CLI arguments. This is a sibling to init_from_args(), as the arguments set here can be interpreted there.

def init_from_args(args: argparse.Namespace) -> argparse.Namespace:
65def init_from_args(args: argparse.Namespace) -> argparse.Namespace:
66    """
67    Take in args from a parser that was passed to set_cli_args(),
68    and initialize the proper components.
69    """
70
71    if (args.seed is None):
72        args.seed = random.randint(0, 2**64)
73
74    return args

Take in args from a parser that was passed to set_cli_args(), and initialize the proper components.

def main() -> int:
102def main() -> int:
103    """ Invoke a game of 8 Puzzle. """
104
105    args = _parse_args(_get_parser())
106    return run(args)

Invoke a game of 8 Puzzle.