aboutsummaryrefslogtreecommitdiff
path: root/imago/engine/parseHelpers.py
blob: 64342d3f02cf517ea1c4eb10dd14ad82e0d69bb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"""Handles translation of input text to internal data and vice versa."""

import re
from enum import Enum, auto as enumAuto

from imago.data.enums import Player

VALID_WHITE_STRINGS = {
    "W",
    "WHITE"
}

VALID_BLACK_STRINGS = {
    "B",
    "BLACK"
}

def parseMove(args, boardsize):
    """Converts the textual representation of a move to a move instance."""
    if len(args) != 2:
        raise RuntimeError(
                "Unable to transform string [%s] to move: Wrong format."
                % args)
    color = parseColor(args[0])
    vertex = parseVertex(args[1], boardsize)
    return GtpMove(color, vertex)

def parseColor(text):
    """Returns color of a move given its input string."""
    textUpper = text.upper()
    if textUpper in VALID_WHITE_STRINGS:
        return Player.WHITE
    if textUpper in VALID_BLACK_STRINGS:
        return Player.BLACK
    raise RuntimeError("Unknown color [%s]." % text)

def parseVertex(text, boardSize):
    """Returns row and column of a vertex given its input string. A vertex can also be the
    string "pass".

    GTP uses A1 style notation: columns are letters left to right, rows are number bottom
    to top.
    """
    text = text.upper()

    if not re.match("^[A-HJ-Z][1-9][0-9]*$", text):
        if text == "PASS":
            return "pass"
        raise RuntimeError(
                "Unable to transform string [%s] to vertex. Wrong format."
                % text)

    vertexCol = ord(text[0])
    # Column 'I' does not exist
    if vertexCol > ord('I'):
        vertexCol -= 1
    vertexCol -= ord('A')

    vertexRow = boardSize - int(text[1:])

    if (vertexCol < 0 or vertexRow < 0
        or vertexCol >= boardSize or vertexRow >= boardSize):
        raise RuntimeError(
                "Unable to transform string [%s] to vertex. Maps to [%d, %d], which is out of board bounds (size [%d])"
                % (text, vertexCol, vertexRow, boardSize))

    return (vertexRow, vertexCol)

def vertexToString(vertex, boardSize):
    """Returns a string representing the vertex.

    GTP uses A1 style notation: columns are letters left to right, rows are number bottom
    to top.
    """
    if vertex == "pass":
        return "pass"
    if len(vertex) != 2:
        raise RuntimeError(
                "Unable to transform vertex [%s] to string. Too many elements."
                % str(vertex))
    if vertex[0] >= boardSize or vertex[1] >= boardSize or vertex[0] < 0 or vertex[1] < 0:
        raise RuntimeError(
                "Unable to transform vertex [%s] to string. Vertex out of board bounds (size [%d])"
                % (str(vertex), boardSize))

    vertexRow = boardSize - vertex[0]
    vertexCol = ord('A') + vertex[1]

    # Column 'I' does not exist
    if vertexCol >= ord('I'):
        vertexCol += 1

    return "%s%d" % (chr(vertexCol), vertexRow)

class GtpMove:
    """Stores the info of a move according to GTP specification: color and vertex."""
    def __init__(self, color, vertex):
        self.color = color
        self.vertex = vertex