Solving the Cretan maze
Tags: python, challenge, tribute, interface
Published: 2018-07-17 09:33:37

---
title: Solving the Cretan maze
description: How to implement simple line-oriented command interpreter for playing a game
published: true
tags: python, challenge, tribute, interface
---

# So let's play the game

Recently [Leonora Der](https://dev.to/leonorader) published great piece of work: [Solve the Cretan maze](https://dev.to/leonorader/solve-the-cretan-maze-2fdg).
That challenge is really interesting because It doesn't require you to write a lot of code, but is still interesting to solve and think about it. Additional thanks for the design: simple and great.
So I've decided to implement basic interface for that game, of course written in Python.
My first intention was to write something like that:
```python
...
class MazeRunner():

    def __init__(self, username, password):
        # For BasicHTTPAuth
        self.username = username
        self.password = password

    def create_maze(self):
        """POST - /api/mazes

        Will let you start the maze
        """

    def start_loop(self):
        ...
...
```
And I even did that. Wrote a dozen methods, mostly non implemented yet but they are just stubs, you know. It covered all API provided. A few days later I've started to dig around `pdb`, then its parent `bdb`, and then back to `pdb`. I've noticed something interesting: here is a piece of source code for the `Pdb` class, file `Lib/pdb.py`
```python
...

line_prefix = '\n-> '   # Probably a better default

class Pdb(bdb.Bdb, cmd.Cmd):

    _previous_sigint_handler = None

...
```

wait, what was that? That second parent class. It is `cmd`. So as usual, Python standard lib has solved a big part of my problems. I started to read docs on this module: [cmd](https://docs.python.org/3/library/cmd.html). It appears that I've been already using this interface for more than half of decade without even noticing that: Python debuggers like `pdb`, `ipdb`, `pudb`.. this common REPL appears everywhere.

```python
>>> import pdb
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) ?

Documented commands (type help <topic>):
========================================
EOF    bt         cont      enable  jump  pp       run      unt   
a      c          continue  exit    l     q        s        until 
alias  cl         d         h       list  quit     step     up    
args   clear      debug     help    n     r        tbreak   w     
b      commands   disable   ignore  next  restart  u        whatis
break  condition  down      j       p     return   unalias  where 

Miscellaneous help topics:
==========================
exec  pdb

Undocumented commands:
======================
retval  rv

(Pdb) 
```

## Let's write something useful

What do we want to solve (what do we need?)
- Implement all API calls
- Document them all
- Make it clear for the user what to do (document it again and provide help)

For implementing `cmd` interface we have to know something:
- the main function is `cmdloop`.
```
From the documentation:

Cmd.cmdloop(intro=None)

Repeatedly issue a prompt, accept input,
parse an initial prefix off the received input,
and dispatch to action methods, passing them the
remainder of the line as argument.
```
- command handlers are methods called `do_<command-name>`
```
An interpreter instance will recognize a command name foo if and only
if it has a method do_foo()
```
- for providing help for this command we have to implement `help_<command-name>` method
- standard `do_help` method calls all `help_*` methods.
- there are pre- and post- handlers for commands: `precmd` and `postcmd` methods.
```

Cmd.precmd(line)

    Hook method executed just before the command line line is interpreted, but
after the input prompt is generated and issued. This method is a stub in Cmd;
it exists to be overridden by subclasses. The return value is used as
the command which will be executed by the onecmd() method; the precmd()
implementation may re-write the command or simply return line unchanged.

Cmd.postcmd(stop, line)

    Hook method executed just after a command dispatch is finished.
This method is a stub in Cmd; it exists to be overridden by subclasses.
line is the command line which was executed, and stop is a flag which
indicates whether execution will be terminated after the call to postcmd();
this will be the return value of the onecmd() method. The return value of
this method will be used as the new value for the internal flag which
corresponds to stop; returning false will cause interpretation to continue.
```

## Ok, so enough talking

Since I prefer using Python over other languages I'm going to change the name of my `cmd` class to MazeCrawler because snakes does not run, yeah? But still, it's little bit boring. I'm gonna go little bit further and rename it to (with regards to It's always sunny in Philadelphia) : [MazeKroller](http://itsalwayssunny.wikia.com/wiki/Night_Crawlers)
```python
import cmd                                                                                                                                                                                                   

class MazeKroller(cmd.Cmd):
    """Interface for walking through the maze
                                                                                                                       
    https://coding-challanges.herokuapp.com/challanges/maze
    """                                                                                                                                                  

    intro = "Welcome to Maze shell. Type `?' or `help' to list commands.\n"
    prompt = '~ '  # Because it's a snake!
```
For now we have only one method -- it is init. And we have to implement rest of the REST.
We need to be able to:
- *create the maze*,
- *navigate through it*
- and *pick up the coins*
to win (actually to get out from the maze). Also a couple of methods should be implemented for usability: *get info* and *give up*.
Here is the stubs for it:
```python
class MazeKroller(cmd.Cmd):
    """Interface for crawling through the maze

    https://coding-challanges.herokuapp.com/challanges/maze
    """
    intro = "Welcome to Maze shell. Type `?' or `help' to list commands.\n"
    prompt = "~ "

    def do_init(self, user, password):
        """Credentials for BasicHTTPAuth."""
        self.user = user
        self.password = password

    def do_create_maze(self, size):
        """Create a new maze.
        Now you have 3600 seconds to escape.

        POST /api/mazes\n"""
    
    def do_info(self, maze_id):
        """Get some general data about your maze

        GET - /api/mazes/{id}\n""" 

    def do_get_cells(self, maze_id):
        """See the cells around you.

        GET - /api/mazes/{id}/steps\n"""

    def do_get_coin(self):
        """Pick up a coin.

        POST - /api/mazes/{id}/coins\n"""

    def do_giveup(self):
        """Gives up the game.

        DELETE /api/mazes/{id}\n"""

```
So here we have a basic class for our MazeKroller.
This class does nothing right now, but could be instantiated with
```
MazeKroller().cmdloop()
```
Play around little bit with it and in the next post I will provide you with implementation of that methods.

Stay tuned!