~ubuntu-branches/ubuntu/precise/gnome-games/precise-proposed

« back to all changes in this revision

Viewing changes to glchess/src/lib/cecp.py

  • Committer: Package Import Robot
  • Author(s): Rodrigo Moya
  • Date: 2011-05-30 13:32:04 UTC
  • mfrom: (1.3.4)
  • mto: (163.1.3 precise)
  • mto: This revision was merged to the branch mainline in revision 143.
  • Revision ID: package-import@ubuntu.com-20110530133204-celaq1v1dsxc48q1
Tags: upstream-3.0.2
ImportĀ upstreamĀ versionĀ 3.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
__author__ = 'Robert Ancell <bob27@users.sourceforge.net>'
3
 
__license__ = 'GNU General Public License Version 2'
4
 
__copyright__ = 'Copyright 2005-2006  Robert Ancell'
5
 
 
6
 
class CECPProtocol:
7
 
    """CECP protocol en/decoder."""
8
 
    
9
 
    NEWLINE             = '\n'
10
 
    MOVE_PREFIXS        = ['My move is: ', 'my move is ', 'move ']
11
 
    INVALID_MOVE_PREFIX = 'Illegal move: '
12
 
    RESIGN_PREFIX       = 'resign'
13
 
    RESIGN_ICS_PREFIX   = 'tellics resign'    
14
 
    DRAW_PREFIX         = 'offer draw'
15
 
 
16
 
    def __init__(self):
17
 
        """
18
 
        """
19
 
        self.__buffer = '' # Data being accumulated to be parsed
20
 
        # Go to simple interface mode
21
 
        self.onOutgoingData('xboard\n')
22
 
        
23
 
    # Methods to extend
24
 
    
25
 
    def onOutgoingData(self, data):
26
 
        """Called when there is data to send to the CECP engine.
27
 
        
28
 
        'data' is the data to give to the AI (string).
29
 
        """
30
 
        print 'OUT: ' + repr(data)
31
 
    
32
 
    def onUnknownLine(self, line):
33
 
        """Called when an unknown line is received from the CECP AI.
34
 
        
35
 
        'line' is the line that has not been decoded (string). There is
36
 
               no newline on the end of the string.
37
 
        """
38
 
        print 'Unknown CECP line: ' + line
39
 
    
40
 
    def onMove(self, move):
41
 
        """Called when the AI makes a move.
42
 
        
43
 
        'move' is the move the AI has decided to make (string).
44
 
        """
45
 
        print 'CECP move: ' + move
46
 
    
47
 
    def onIllegalMove(self, move):
48
 
        """Called when the AI rejects a move.
49
 
        
50
 
        'move' is the move the AI rejected (string).
51
 
        """
52
 
        print 'CECP illegal move: ' + move
53
 
        
54
 
    def onResign(self):
55
 
        """Called when the AI resigns"""
56
 
        print 'CECP AI resigns'
57
 
        
58
 
    def onDraw(self):
59
 
        """Called when the AI requests a draw"""
60
 
        print 'CECP AI calls a draw'
61
 
        
62
 
    def logText(self, text, style):
63
 
        print 'LOG: %s' % text
64
 
        
65
 
    # Public methods
66
 
    
67
 
    def sendSetSearchDepth(self, searchDepth):
68
 
        """Set the search depth for the AI.
69
 
        
70
 
        'searchDepth' is the number of moves to look ahead (integer).
71
 
        """
72
 
        # This is the CECP specified method
73
 
        self.onOutgoingData('sd %i\n' % int(searchDepth))
74
 
        
75
 
        # GNUchess uses this instead
76
 
        self.onOutgoingData('depth %i\n' % int(searchDepth))
77
 
        
78
 
    def sendSetPondering(self, aiPonders):
79
 
        """Enable/disable AI pondering.
80
 
        
81
 
        'aiPonders' is a flag to show if the AI thinks during opponent moves (True) or not (False).
82
 
        """
83
 
        if aiPonders:
84
 
            self.onOutgoingData('hard\n')
85
 
        else:
86
 
            self.onOutgoingData('easy\n')
87
 
    
88
 
    def sendMove(self, move):
89
 
        """Move for the current player.
90
 
        
91
 
        'move' is the move the current player has made (string).
92
 
        """
93
 
        self.onOutgoingData(move + '\n')
94
 
        
95
 
    def sendWait(self):
96
 
        """Stop the AI from automatically moving"""
97
 
        self.onOutgoingData('force\n')
98
 
        
99
 
    def sendUndo(self):
100
 
        """Undo the last move"""
101
 
        self.onOutgoingData('undo\n')
102
 
        
103
 
    def sendMovePrompt(self):
104
 
        """Get the AI to move for the current player"""
105
 
        self.onOutgoingData('go\n')
106
 
        
107
 
    def sendConventionalClock(self, moveCount, base, increment):
108
 
        """
109
 
        
110
 
        'moveCount' ???
111
 
        'base' ??? (seconds)
112
 
        'increment' ??? (seconds)
113
 
        """
114
 
        self.onOutgoingData('level %d %d:%02d %d:%02d\n' % (moveCount, base / 60, base % 60, increment / 60, increment % 60))
115
 
 
116
 
    def sendQuit(self):
117
 
        """Quit the engine"""
118
 
        # Send 'quit' starting with a newline in case there are some characters already sent
119
 
        self.onOutgoingData('\nquit\n')
120
 
    
121
 
    def registerIncomingData(self, data):
122
 
        """
123
 
        """
124
 
        self.__buffer += data
125
 
        self.__parseData()
126
 
        
127
 
    # Private methods
128
 
        
129
 
    def __parseData(self):
130
 
        while True:
131
 
            index = self.__buffer.find(self.NEWLINE)
132
 
            if index < 0:
133
 
                return
134
 
            
135
 
            line = self.__buffer[:index]
136
 
            self.__buffer = self.__buffer[index+1:]
137
 
 
138
 
            self.__parseLine(line)
139
 
    
140
 
    def __parseLine(self, line):
141
 
        for prefix in self.MOVE_PREFIXS:
142
 
            if line.startswith(prefix):
143
 
                move = line[len(prefix):]
144
 
                self.logText(line + '\n', 'move')
145
 
                self.onMove(move.strip())
146
 
                return
147
 
 
148
 
        if line.startswith(self.INVALID_MOVE_PREFIX):
149
 
            self.onIllegalMove(line[len(self.INVALID_MOVE_PREFIX):])
150
 
    
151
 
        elif line.startswith(self.RESIGN_PREFIX) or line.startswith(self.RESIGN_ICS_PREFIX):
152
 
            self.logText(line + '\n', 'move')
153
 
            self.onResign()
154
 
            return
155
 
 
156
 
        elif line.startswith(self.DRAW_PREFIX):
157
 
            self.logText(line + '\n', 'move')
158
 
            self.onDraw()
159
 
            return
160
 
 
161
 
        else:
162
 
            self.onUnknownLine(line)
163
 
            
164
 
        self.logText(line + '\n', 'input')
165
 
 
166
 
class Connection(CECPProtocol):
167
 
    """
168
 
    """
169
 
    
170
 
    def __init__(self):
171
 
        """
172
 
        """
173
 
        # Start protocol
174
 
        CECPProtocol.__init__(self)
175
 
        
176
 
    # Methods to extend
177
 
    
178
 
    def logText(self, text, style):
179
 
        """FIXME: define style
180
 
        """
181
 
        pass
182
 
    
183
 
    def onMove(self, move):
184
 
        """Called when the AI makes a move.
185
 
        
186
 
        'move' is the move the AI made (string).
187
 
        """
188
 
        print 'AI moves: ' + move
189
 
 
190
 
    # Public methods
191
 
    
192
 
    def start(self):
193
 
        """
194
 
        """
195
 
        pass
196
 
    
197
 
    def startGame(self):
198
 
        """
199
 
        """
200
 
        pass
201
 
    
202
 
    def configure(self, options = []):
203
 
        """
204
 
        """
205
 
        for option in options:
206
 
            self.onOutgoingData(option.value + '\n')
207
 
 
208
 
    def requestMove(self, whiteTime, blackTime, ownTime):
209
 
        """Request the AI moves for the current player"""
210
 
        # Set the clock
211
 
        if ownTime > 0:
212
 
            self.sendConventionalClock(0, ownTime / 1000, 0)
213
 
        
214
 
        # Prompt the AI to move
215
 
        self.sendMovePrompt()
216
 
        
217
 
    def undoMove(self):
218
 
        """Undo the last move made by this AI"""
219
 
        self.sendWait()
220
 
        self.sendUndo()
221
 
 
222
 
    def reportMove(self, move, isSelf):
223
 
        """Report the move the current player has made.
224
 
        
225
 
        'move' is the move to report (string).
226
 
        'isSelf' is a flag to say if the move is the move this AI made (True).
227
 
        """
228
 
        # Don't report the move we made
229
 
        if isSelf:
230
 
            return
231
 
        
232
 
        # Stop the AI from automatically moving
233
 
        self.sendWait()
234
 
 
235
 
        # Report the move
236
 
        self.sendMove(move)
237
 
 
238
 
    # Private methods
239
 
 
240
 
    def onUnknownLine(self, line):
241
 
        """Called by CECPProtocol"""
242
 
        pass#print 'Unknown CECP line: ' + line
243
 
 
244
 
    def onIllegalMove(self, move):
245
 
        """Called by CECPProtocol"""
246
 
        print 'CECP illegal move: ' + move