better makefile
[imago.git] / src / output.py
1 """Imago output module."""
2
3 import copy
4 import sys
5
6 COORDS = 'abcdefghijklmnopqrs'
7
8 # TODO refactor method names
9
10 class Board:
11     """Represents the state of the board."""
12     def __init__(self, size, stones):
13         self.stones = stones        
14         self.size = size
15
16     def __str__(self):
17         """Retrun string representation of the board."""
18         lines = []
19         k = 0
20         for i in range(self.size):
21             line = []
22             for j in range(self.size):
23                 line.append(self.stones[k])
24                 k += 1
25             lines.append(" ".join(line))
26         lines.append("")
27         return ("\n".join(lines))
28
29     def asSGFsetPos(self):
30         """Returns SGF (set position) representation of the position."""
31
32         #TODO version numbering
33         sgf = "(;FF[4]GM[1]SZ[" + str(self.size) + "]AP[Imago:0.1.0]\n"
34         sgf += self.SGFpos()
35         sgf += ")"
36         return sgf
37
38     def SGFpos(self):
39         black = []
40         white = []
41
42         for i in range(self.size):
43             for j in range(self.size):
44                 stone = self.stones[i * self.size + j]
45                 if stone == 'B':
46                     black.append(Move('B', i, j))
47                 elif stone == 'W':
48                     white.append(Move('W', i, j))
49         sgf = ""
50         if len(black) > 0:
51             sgf += "AB" + ''.join('[' + m.sgf_coords() + ']'
52                               for m in black) + "\n"
53         if len(white) > 0:
54             sgf += "AW" + ''.join('[' + m.sgf_coords() + ']' 
55                               for m in white) + "\n"
56         return sgf
57
58     def addMove(self, m):
59         """Add move to the board."""
60         self.stones[(m.y * self.size) + m.x] = m.color
61
62     def getMoveCandidates(self, board):
63         """Take the next board in game and return a list of moves that are
64         new."""
65         candidates = []
66         for i in range(self.size):
67             for j in range(self.size):
68                 if (self.stones[self.size * i + j] == "."):
69                     if (board.stones[self.size * i + j] == "W"):
70                         candidates.append(Move("W", i, j))
71                     elif (board.stones[self.size * i + j] == "B"):
72                         candidates.append(Move("B", i, j))
73         return candidates
74
75 class Move:
76     """Repsresents a move."""
77     def __init__(self, color, y, x, comment=None):
78         self.color = color
79         self.x = x
80         self.y = y
81         self.comment = comment
82
83     def sgf_coords(self):
84         """Return coordinates of the move in SGF."""
85         return COORDS[self.x] + COORDS[self.y]
86
87 class Game:
88     """Represents a game."""
89     def __init__(self, size, board=None, debug=True):
90         self.init_board = board or Board(size, (size * size) * ".")
91         self.board = copy.deepcopy(self.init_board)
92         self.moves = []
93         self.size = size
94         self.debug = debug
95         self.debug_comment = ""
96
97     def addMove(self, board):
98         """Add next move to the game."""
99         candidates = self.board.getMoveCandidates(board)
100         if self.debug:
101             comment = str(board)
102             comment += "Candidates: " + str(len(candidates))
103             
104         if not candidates:
105             self.debug_comment += "No candidates."
106             return
107
108         move = candidates[0]
109         move.comment = comment
110         self.moves.append(move)
111         self.board.addMove(move)
112
113     def asSGF(self):
114         """Return the game representation as SGF string."""
115         sgf = "(;FF[4]GM[1]SZ[" + str(self.size) + "]AP[Imago:0.1.0]\n"
116         sgf += self.init_board.SGFpos()
117         for m in self.moves:
118             if m:
119                 sgf += ";" + m.color + "[" + m.sgf_coords() + "]"
120                 if m.comment:
121                     sgf += "C[" + m.comment + "]"
122                 sgf += "\n"
123         sgf += ")"
124         return sgf
125
126