# Task
 An `amazon` (also known as a queen+knight compound) is an imaginary chess piece that can move like a `queen` or a `knight` (or, equivalently, like a `rook`, `bishop`, or `knight`). The diagram below shows all squares which the amazon attacks from e4 (circles represent knight-like moves while crosses correspond to queen-like moves).

 ![](https://codefightsuserpics.s3.amazonaws.com/tasks/amazonCheckmate/img/amazon.png?_tm=1473934566013)

 Recently you've come across a diagram with only three pieces left on the board: a `white amazon`, `white king` and `black king`. 
 
 It's black's move. You don't have time to determine whether the game is over or not, but you'd like to figure it out in your head. 
 
 Unfortunately, the diagram is smudged and you can't see the position of the `black king`, so it looks like you'll have to check them all.

 Given the positions of white pieces on a standard chessboard, determine the number of possible black king's positions such that: 

* It's a checkmate (i.e. black's king is under amazon's 
 attack and it cannot make a valid move);

* It's a check (i.e. black's king is under amazon's attack 
 but it can reach a safe square in one move);

* It's a stalemate (i.e. black's king is on a safe square 
 but it cannot make a valid move);

* Black's king is on a safe square and it can make a valid move.

Note that two kings cannot be placed on two adjacent squares (including two diagonally adjacent ones).

# Example

 For `king = "d3" and amazon = "e4"`, the output should be `[5, 21, 0, 29]`.

 ![](https://codefightsuserpics.s3.amazonaws.com/tasks/amazonCheckmate/img/example1.png?_tm=1473934566299)

 `Red crosses` correspond to the `checkmate` positions, `orange pluses` refer to `checks` and `green circles` denote `safe squares`.

 For `king = "a1" and amazon = "g5"`, the output should be `[0, 29, 1, 29]`.

 ![](https://codefightsuserpics.s3.amazonaws.com/tasks/amazonCheckmate/img/example2.png?_tm=1473934566670)

 `Stalemate` position is marked by a `blue square`.

# Input


 - String `king`

Position of white's king in chess notation.


 - String `amazon`

Position of white's amazon in the same notation.

Constraints: `amazon ≠ king.`

# Output

An array of four integers, each equal to the number of black's king positions corresponding to a specific situation. The integers should be presented in the same order as the situations were described, `i.e. 0 for checkmates, 1 for checks, etc`.

```python

USER_FILENAME = "<user_code>"
import sys, json, builtins
import math, heapq, bisect, itertools, functools, collections, statistics, fractions, decimal, operator, array, random, re, string, os, pathlib
try:
    import resource as _res
except Exception:
    _res = None
from collections import Counter, defaultdict, deque, OrderedDict
from functools import lru_cache, reduce
from itertools import accumulate, permutations, combinations, product
from math import gcd, ceil, floor, sqrt
from decimal import Decimal
try:
    from typing import *
except Exception:
    pass
try:
    sys.setrecursionlimit(1_000_000)
except Exception:
    pass
try:
    import site as _site
    try:
        _sys_sites = _site.getsitepackages() if hasattr(_site, "getsitepackages") else []
        for _p in _sys_sites:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
    try:
        _usp = _site.getusersitepackages()
        if isinstance(_usp, str):
            _usp = [_usp]
        for _p in _usp:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
except Exception:
    pass

def _disabled_input(*args, **kwargs):
    raise RuntimeError("input() is disabled in callable mode")
builtins.input = _disabled_input

ns = {"__name__": "__judge__"}  # prevent if __name__ == "__main__" blocks
for _k, _v in list(globals().items()):
    if not _k.startswith("_"):
        ns[_k] = _v
_CODE = 'from collections import namedtuple\nfrom functools import reduce\nimport enum\nimport sys\n\nclass Outcomes:\n    """Enapsulation of outcomes to which tracks results as named attributes\n    and can return the array expected by the kata.\n    """\n\n    def __init__(self):\n        """Initialize situational count members to 0.\n        """\n\n        self.checkmates = 0\n        self.checks = 0\n        self.stalemates = 0\n        self.alives = 0\n\n    def as_array(self):\n        """Return the array ordered as expected by the kata definition.\n        \n        Returns:\n            array -- integer array of counts of squares by chess condition.\n        """\n\n        return [self.checkmates, self.checks, self.stalemates, self.alives]\n\nclass GameSquareConditions:\n    """Gameplay conditions of a square.\n    """\n\n    def __init__(self, is_threatened=False, is_occupied=False, is_inhibited=False):\n        self.is_threatened = is_threatened\n        self.is_occupied = is_occupied\n        self.is_inhibited = is_inhibited\n\n    @property\n    def is_safe(self):\n        """Property to return the inverse of is_threatened.\n        """\n        return not self.is_threatened\n\nclass GameSquareOutcome(enum.Enum):\n    CHECKMATE = enum.auto()\n    CHECK = enum.auto()\n    STALEMATE = enum.auto()\n    ALIVE = enum.auto()\n    UNKNOWN = enum.auto()\n\n@enum.unique\nclass MovementDirection(enum.Enum):\n    """Enumeration of movement directions.\n    """\n    NORTH = (0, 1)\n    NORTH_EAST = (1, 1)\n    EAST = (1, 0)\n    SOUTH_EAST = (1, -1)\n    SOUTH = (0, -1)\n    SOUTH_WEST = (-1, -1)\n    WEST = (-1, 0)\n    NORTH_WEST = (-1, 1)\n\n    def __init__(self, x_offset, y_offset):\n        self.x_offset = x_offset\n        self.y_offset = y_offset\n\n    @property\n    def cartesian_offset(self):\n        """Return an (x,y) tuple offset for the direction. This method assumes\n        the cartesian grid lower left is 0,0 with positive x to the right and\n        positive y up.\n        """\n        return (self.x_offset, self.y_offset)\n\n    @property\n    def reciprical(self):\n        """Return the opposite direction.\n        """\n        if self == self.NORTH:\n            return self.SOUTH\n        elif self == self.NORTH_EAST:\n            return self.SOUTH_WEST\n        elif self == self.EAST:\n            return self.WEST\n        elif self == self.SOUTH_EAST:\n            return self.NORTH_WEST\n        elif self == self.SOUTH:\n            return self.NORTH\n        elif self == self.SOUTH_WEST:\n            return self.NORTH_EAST\n        elif self == self.WEST:\n            return self.EAST\n        elif self == self.NORTH_WEST:\n            return self.SOUTH_EAST\n\n        raise ValueError("Unknown direction to recipricate!")\n        \n    def move_from(self, x, y):\n        """Apply the movement to the provided X, Y cartesian coordinates.\n        \n        Arguments:\n            x {int} -- Starting X cartesian coordinate to move from.\n            y {int} -- Starting Y cartesian coordinate to move from.\n\n        Returns:\n            Tuple (x,y) cartesian coordinates resulting from the move.\n        """\n        offset = self.cartesian_offset\n        return (x + offset[0], y + offset[1])\n\nclass GameSquare:\n    """Square on the gameboard.\n    """\n\n    def __init__(self):\n        """Initialize the neighbors in all directions to None.\n        """\n        self.neighbors = {}\n        self.condition = GameSquareConditions()\n        self.outcome = GameSquareOutcome.UNKNOWN\n\n    def has_neighbor(self, direction):\n        """Check if there is a neighboring square in the given direction.\n        \n        Arguments:\n            direction {MovementDirection} -- Direction to check.\n        """\n        return self.neighbor(direction) is not None\n\n    def neighbor(self, direction):\n        \n        """Return the neighboring game square in the direction. If no neighbor\n        has been set, None.\n        \n        Arguments:\n            direction {MovementDirection} -- Direction to get neighbor in.\n\n        Return:\n            GameSquare or None.\n        """\n        return self.neighbors.get(direction, None)\n\n    def set_neighbor(self, neighbor, direction):\n        """Store the neighbor to the specified direction.\n\n        Side effects:\n        Neighbor status is also set in the reciprical direction of the\n        provided neighbor. If the neighbor is already set on that\n        direction, it is cleared.\n\n        If the provided neighbor is \'self\' a \n        \n        Arguments:\n            neighbor {GameSquare} -- Neighboring game square to connect.\n            direction {MovementDirection} -- Direction to get neighbor in.\n        """\n        if neighbor is self:\n            raise ValueError("Cannot set yourself as a neighbor!")\n\n        existing_neighbor = self.neighbor(direction)\n        if existing_neighbor is not None and existing_neighbor is not neighbor:\n            raise ValueError("Another neighbor is already in that direction!")\n\n        recip_direction = direction.reciprical\n        existing_recip_neighbor = neighbor.neighbor(recip_direction)\n        if existing_recip_neighbor is not None and existing_recip_neighbor is not self:\n            raise ValueError("Input neighbor already has neighbor in opposite direction!")\n\n        self.neighbors[direction] = neighbor\n        neighbor.neighbors[recip_direction] = self\n\n    def neighbor_conditions(self):\n        """Return a list of all conditions for neighboring squares.\n        """\n        return [n.condition for n in list(self.neighbors.values())]\n\n    def render(self, out_dest):\n        """Simple grid rendering to the output stream.\n\n        Arguments:\n            out_dest -- Output stream to render to.\n        """\n        \n        marker = " "\n        if self.condition.is_threatened:\n            marker = "v"\n        elif self.condition.is_occupied:\n            marker = "*"\n        elif self.condition.is_inhibited:\n            marker = "-"\n        out_dest.write(marker)\n\n    def render_outcome(self, out_dest):\n        """Simple grid rendering of the outcome to the output stream.\n\n        Arguments:\n            out_dest -- Output stream to render to.\n        """\n        \n        marker = "?"\n        if self.outcome == GameSquareOutcome.CHECKMATE:\n            marker = "!"\n        elif self.outcome == GameSquareOutcome.CHECK:\n            marker = ":"\n        elif self.outcome == GameSquareOutcome.STALEMATE:\n            marker = "o"\n        elif self.outcome == GameSquareOutcome.ALIVE:\n            marker = "."\n        out_dest.write(marker)\n\nclass Gameboard:\n    """Gameboard comprised of rows and columns of GameSquares.\n    The origin of the gameboard is the "lower-left".\n    """\n\n    def __init__(self, num_rows, num_cols):\n        """Initialize the gameboard with a num_rows x num_cols grid of \n        GameSquares.\n        \n        Arguments:\n            num_rows {int} -- Number of rows on the gameboard\n            num_cols {int} -- Number of columns on the gameboard\n        """\n        if num_rows < 1:\n            fmt = "Gameboard initialized with number of rows < 1 ({})!"\n            msg = fmt.format(num_rows)\n            raise ValueError()\n\n        if num_cols < 1:\n            fmt = "Gameboard initialized with number of columns < 1 ({})!"\n            msg = fmt.format(num_cols)\n            raise ValueError(msg)\n\n        self.num_rows = num_rows\n        self.num_cols = num_cols\n\n        self.board = {}\n        for row in range(num_rows):\n            for col in range(num_cols):\n                key = (row, col)\n                self.board[key] = GameSquare()\n\n        for row in range(num_rows):\n            for col in range(num_cols):\n                current = self.square_at(row, col)\n                for direction in MovementDirection:\n                    try:\n                        neighbor_x, neighbor_y = direction.move_from(row, col)\n                        neighbor = self.square_at(neighbor_x, neighbor_y)\n                        current.set_neighbor(neighbor, direction)\n                    except KeyError:\n                        pass\n\n    def square_at(self, row, col):\n        """Return the GameSquare at the specified row and column.\n\n        If row or col are out of bounds, an KeyError is raised.\n        \n        Arguments:\n            row {int} -- 0 based index of the row to return the square from.\n            col {int} -- 0 based index of the column to return the square from.\n\n        Return:\n            GameSquare at the specified index.\n        """\n        key = (row, col)\n        return self.board[key]\n\n    def render(self, out_dest):\n        """Simple grid rendering to the output stream. The board is rendered\n        with the "top" row on "top".\n\n        Arguments:\n            out_dest -- Output stream to render to.\n        """\n        out_dest.write("\\n\\nGameboard\\n")\n        for y in range(self.num_cols - 1, -1, -1):\n            for x in range(self.num_rows):\n                out_dest.write("|")\n                self.square_at(x, y).render(out_dest)\n            out_dest.write("|\\n")\n\n    def render_outcome(self, out_dest):\n        """Simple grid rendering to the output stream. The board is rendered\n        with the "top" row on "top".\n\n        Arguments:\n            out_dest -- Output stream to render to.\n        """\n        out_dest.write("\\n\\nOutcomes\\n")\n        for y in range(self.num_cols - 1, -1, -1):\n            for x in range(self.num_rows):\n                out_dest.write("|")\n                self.square_at(x, y).render_outcome(out_dest)\n            out_dest.write("|\\n")\n\nclass DestinationMover:\n    """The DestinationMover attempts to move along a path to reach\n    a GameSquare. Only the final destination is returned.\n    """\n\n    def __init__(self, *args):\n        """Initialize the path to move to.\n\n        Arguments:\n            *args {MovementDirection} -- Path to move along.\n        """\n        self.movement_path = list(args)\n\n    def append_path(self, *args):\n        """Append the provided MovementDirections to the path.\n        """\n\n        self.movement_path = self.movement_path + list(args)\n\n    def execute(self, origin):\n        """Follow the stored movement path from the provided origin.\n        \n        Arguments:\n            origin {GameSquare} -- Position on the gameboard to be move from.\n\n        Return:\n            List of 1 item where the move terminated, or an empty list if the\n            movement path cannot be completed.\n        """\n        current_location = origin\n        for move in self.movement_path:\n            next_location = current_location.neighbor(move)\n            if next_location == None:\n                return []\n            current_location = next_location\n        return [current_location]\n\n    def __str__(self):\n        """Return a nice, printable representation of the DestinationMover.\n        """\n        path = "-".join(p.name for p in self.movement_path)\n        return "DestinationMover: " + path\n\nclass VectorMover:\n    """The VectorMover moves from an origin location in a constant direction\n    and returns each GameSquare along the movement path. The mover stops a \n    GameSquare is occupied or there is no next neighbor in the direction.\n    """\n\n    def __init__(self, direction = None):\n        self.direction = direction\n\n    def execute(self, origin):\n        """Follow the stored direction until there are no neighboring squares or\n        if a square is occupied.\n        \n        Arguments:\n            origin {GameSquare} -- Position on the gameboard to be move from.\n\n        Return:\n            List of squares moved along the path.\n        """\n        if self.direction is None:\n            return []\n        \n        visited = []\n        neighbor = origin.neighbor(self.direction)\n        while neighbor is not None and not neighbor.condition.is_occupied:\n            visited.append(neighbor)\n            neighbor = neighbor.neighbor(self.direction)\n\n        return visited\n\n    def __str__(self):\n        """Return a nice, printable representation of the VectorMover.\n        """\n        return "VectorMover: " + self.direction.name\n\nclass GamePiece:\n\n    def __init__(self, inhibit_as_well_as_threaten = False):\n        self.inhibit_as_well_as_threaten = inhibit_as_well_as_threaten\n        self.location = None\n        self.movers = []\n\n    def place_on_board(self, gamesquare):\n        """Set the piece on the specified gamesquare.\n        \n        Arguments:\n            gamesquare {GameSquare} -- Location on the gameboard to place piece.\n        """\n        self.location = gamesquare\n        self.location.condition.is_occupied = True\n\n    def impart_force(self):\n        """Update the game squares based on the force abilities of the\n        piece.\n\n        Arguments:\n            location {GameSquare} -- Position on the gameboard of the piece.\n\n        Returns a list of the updated game squares.\n        """\n        if self.location is None:\n            return []\n\n        result = []\n        for mover in self.movers:\n            result = result + mover.execute(self.location)\n\n        for square in result:\n            square.condition.is_threatened = True\n            if self.inhibit_as_well_as_threaten:\n                square.condition.is_inhibited = True\n            \n        return result\n\n    def __str__(self):\n        """Return a nice, printable representation of the GamePiece.\n        """\n        mover_content = "\\n  ".join([str(x) for x in self.movers])\n        r = "\\n  ".join([\'GamePiece\', mover_content])\n        return r\n\ndef create_knight_movers():\n    """Create the DestinationMovers for the possible knight moves.\n    \n    Returns:\n        [list(DesintationMover)] -- List of movers to execute knight moves.\n    """\n\n    knight_paths = []\n    knight_paths.append((MovementDirection.NORTH,\n                         MovementDirection.NORTH,\n                         MovementDirection.WEST))\n\n    knight_paths.append((MovementDirection.NORTH,\n                         MovementDirection.NORTH,\n                         MovementDirection.EAST))\n\n    knight_paths.append((MovementDirection.NORTH,\n                         MovementDirection.WEST,\n                         MovementDirection.WEST))\n\n    knight_paths.append((MovementDirection.NORTH,\n                         MovementDirection.EAST,\n                         MovementDirection.EAST))\n\n    knight_paths.append((MovementDirection.SOUTH,\n                         MovementDirection.SOUTH,\n                         MovementDirection.WEST))\n\n    knight_paths.append((MovementDirection.SOUTH,\n                         MovementDirection.SOUTH,\n                         MovementDirection.EAST))\n\n    knight_paths.append((MovementDirection.SOUTH,\n                         MovementDirection.WEST,\n                         MovementDirection.WEST))\n\n    knight_paths.append((MovementDirection.SOUTH,\n                         MovementDirection.EAST,\n                         MovementDirection.EAST))\n\n    return [DestinationMover(*x) for x in knight_paths]\n\ndef create_rook_movers():\n    """Create the VectorMovers for the possible rook moves.\n    \n    Returns:\n        [list(VectorMover)] -- List of movers to execute rook moves.\n    """\n    directions = (MovementDirection.NORTH, \n                  MovementDirection.SOUTH,\n                  MovementDirection.EAST,\n                  MovementDirection.WEST)\n    return [VectorMover(direction) for direction in directions]\n\ndef create_bishop_movers():\n    """Create the VectorMovers for the possible bishop moves.\n    \n    Returns:\n        [list(VectorMover)] -- List of movers to execute bishop moves.\n    """\n    directions = (MovementDirection.NORTH_EAST,\n                  MovementDirection.NORTH_WEST,\n                  MovementDirection.SOUTH_EAST,\n                  MovementDirection.SOUTH_WEST)\n    return [VectorMover(direction) for direction in directions]\n\ndef create_amazon():\n    piece = GamePiece()\n\n    for mover in create_knight_movers():\n        piece.movers.append(mover)\n\n    for mover in create_rook_movers():\n        piece.movers.append(mover)\n\n    for mover in create_bishop_movers():\n        piece.movers.append(mover)\n\n    return piece\n\ndef create_king():\n    piece = GamePiece(inhibit_as_well_as_threaten=True)\n    for direction in MovementDirection:\n        mover = DestinationMover()\n        mover.append_path(direction)\n        piece.movers.append(mover)    \n\n    return piece\n\ndef chess_location_to_game_indicies(pos_string):\n    """Convert chess locations (ex A1) to index for a gameboard.\n\n    Arguments:\n            pos_string {string} -- Chess notation location on the board.\n\n    Return:\n        (x,y) tuple to index the gameboard.\n    """\n    first = ord(pos_string[0].upper()) - ord(\'A\')\n    second = int(pos_string[1]) - 1\n    return (first, second)\n\ndef determine_square_status_and_update_outcome(my_condition, \n                                               neighbor_conditions, \n                                               outcome):\n    """Determine the status of the square from the square\'s condition and\n    the neighboring conditions. Update and return the outcome.\n    \n    Return the outcome type.\n\n    Arguments:\n        my_condition {GameSquareConditions} -- Condition of the square to evaluate\n        neighbor_conditions {list(GameSquareConditions)} -- Conditions of nieghbors\n        outcome {Outcomes} -- Cumulative outcome of the gameboard.\n    """\n    outcome_type = GameSquareOutcome.UNKNOWN\n    if my_condition.is_occupied or my_condition.is_inhibited:\n        return outcome_type\n\n    can_move_to_safety = any([x.is_safe for x in neighbor_conditions])\n    if my_condition.is_threatened:\n        if can_move_to_safety:\n            outcome.checks += 1\n            outcome_type = GameSquareOutcome.CHECK\n        else:\n            outcome.checkmates += 1\n            outcome_type = GameSquareOutcome.CHECKMATE\n\n    else:\n        if can_move_to_safety:\n            outcome.alives += 1\n            outcome_type = GameSquareOutcome.ALIVE\n        else:\n            outcome.stalemates += 1\n            outcome_type = GameSquareOutcome.STALEMATE\n\n    return outcome_type\n\ndef amazon_check_mate(king, amazon):\n    \n    outcomes = Outcomes()\n    king_coords = chess_location_to_game_indicies(king)\n    amazon_coords = chess_location_to_game_indicies(amazon)\n\n    board = Gameboard(8, 8)\n    king_piece = create_king()\n    amazon_piece = create_amazon()\n\n    king_piece.place_on_board(board.square_at(*king_coords))\n    amazon_piece.place_on_board(board.square_at(*amazon_coords))\n\n    king_piece.impart_force()\n    amazon_piece.impart_force()\n \n    for square in list(board.board.values()):\n        determine_square_status_and_update_outcome(square.condition,\n                                                   square.neighbor_conditions(),\n                                                   outcomes)\n\n    return outcomes.as_array()\n'
_co = compile(_CODE, USER_FILENAME, "exec")
exec(_co, ns, ns)

_target = None
_fn_name = 'amazon_check_mate'
if _fn_name:
    if "Solution" in ns:
        try:
            _obj = ns["Solution"]()
            if hasattr(_obj, _fn_name):
                _target = getattr(_obj, _fn_name)
        except Exception:
            _target = None
    if _target is None and _fn_name in ns and callable(ns[_fn_name]):
        _target = ns[_fn_name]
# Fallback: if there's exactly one user-defined function, use it
if _target is None:
    _cands = [v for k, v in ns.items() if callable(v) and getattr(v, "__module__", "") in ("__judge__", "__main__")]
    _user_funcs = [c for c in _cands if getattr(c, "__name__", "").startswith("_") is False]
    if len(_user_funcs) == 1:
        _target = _user_funcs[0]
if _target is None:
    raise RuntimeError(f"Could not resolve callable '{_fn_name}'")

_raw = sys.stdin.read().strip()
if _raw:
    _parsed = json.loads(_raw)
    if isinstance(_parsed, dict):
        _kwargs = _parsed.get("kwargs", {})
        _args = _parsed.get("args", [])
    else:
        _args, _kwargs = _parsed, {}
else:
    _args, _kwargs = [], {}
if not isinstance(_args, (list, tuple)):
    _args = [_args]
_res = _target(*_args, **_kwargs)
try:
    sys.stdout.write(repr(_res) + "\n")
except Exception:
    pass

```

Measured memory_bytes: 69036