gnome-games r8588 - in trunk/glchess: glade src/lib src/lib/chess src/lib/gtkui src/lib/ui
- From: rancell svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-games r8588 - in trunk/glchess: glade src/lib src/lib/chess src/lib/gtkui src/lib/ui
- Date: Sun, 18 Jan 2009 22:28:28 +0000 (UTC)
Author: rancell
Date: Sun Jan 18 22:28:28 2009
New Revision: 8588
URL: http://svn.gnome.org/viewvc/gnome-games?rev=8588&view=rev
Log:
Added undo support (Bug #388253)
Modified:
trunk/glchess/glade/glchess.glade
trunk/glchess/src/lib/ai.py
trunk/glchess/src/lib/cecp.py
trunk/glchess/src/lib/chess/board.py
trunk/glchess/src/lib/display.py
trunk/glchess/src/lib/game.py
trunk/glchess/src/lib/gtkui/chessview.py
trunk/glchess/src/lib/gtkui/gtkui.py
trunk/glchess/src/lib/main.py
trunk/glchess/src/lib/player.py
trunk/glchess/src/lib/uci.py
trunk/glchess/src/lib/ui/ui.py
Modified: trunk/glchess/glade/glchess.glade
==============================================================================
--- trunk/glchess/glade/glchess.glade (original)
+++ trunk/glchess/glade/glchess.glade Sun Jan 18 22:28:28 2009
@@ -38,7 +38,7 @@
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The Game menu">_Game</property>
+ <property name="label" translatable="yes">_Game</property>
<property name="use_underline">True</property>
<child>
@@ -90,13 +90,13 @@
<child>
<widget class="GtkImageMenuItem" id="menu_play_online_item">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The Game|Network Game menu">Network _Game</property>
+ <property name="label" translatable="yes">Network _Game</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_join_game_button_clicked" last_modification_time="Sun, 30 Jul 2006 14:16:15 GMT"/>
<accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image109">
+ <widget class="GtkImage" id="image121">
<property name="visible">True</property>
<property name="stock">gtk-network</property>
<property name="icon_size">1</property>
@@ -116,14 +116,36 @@
</child>
<child>
+ <widget class="GtkImageMenuItem" id="menu_undo_move">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Undo Move</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="_on_undo_move_clicked" last_modification_time="Fri, 02 Jan 2009 04:57:07 GMT"/>
+ <accelerator key="Z" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image122">
+ <property name="visible">True</property>
+ <property name="stock">gtk-undo</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
<widget class="GtkImageMenuItem" id="menu_resign">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The Game|Resign menu">_Resign</property>
+ <property name="label" translatable="yes">_Resign</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_resign_clicked" last_modification_time="Sun, 20 Jan 2008 19:45:39 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image110">
+ <widget class="GtkImage" id="image123">
<property name="visible">True</property>
<property name="stock">gtk-dialog-warning</property>
<property name="icon_size">1</property>
@@ -139,12 +161,12 @@
<child>
<widget class="GtkImageMenuItem" id="menu_claim_draw">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The Game|Claim Draw menu">Claim _Draw</property>
+ <property name="label" translatable="yes">Claim _Draw</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_claim_draw_clicked" last_modification_time="Sun, 20 Jan 2008 19:45:39 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image111">
+ <widget class="GtkImage" id="image124">
<property name="visible">True</property>
<property name="stock">gtk-delete</property>
<property name="icon_size">1</property>
@@ -179,7 +201,7 @@
<child>
<widget class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The View menu">_View</property>
+ <property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
<child>
@@ -188,13 +210,13 @@
<child>
<widget class="GtkImageMenuItem" id="menu_fullscreen">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The View|Fullscreen menu">_Fullscreen</property>
+ <property name="label" translatable="yes">_Fullscreen</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_view_fullscreen_clicked" last_modification_time="Mon, 30 Oct 2006 21:20:40 GMT"/>
<accelerator key="F11" modifiers="0" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image112">
+ <widget class="GtkImage" id="image125">
<property name="visible">True</property>
<property name="stock">gtk-fullscreen</property>
<property name="icon_size">1</property>
@@ -209,13 +231,13 @@
<child>
<widget class="GtkImageMenuItem" id="menu_leave_fullscreen">
- <property name="label" translatable="yes" comments="The View|Leave Fullscreen menu">Leave _Fullscreen</property>
+ <property name="label" translatable="yes">Leave _Fullscreen</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_view_unfullscreen_clicked" last_modification_time="Mon, 30 Oct 2006 21:43:10 GMT"/>
<accelerator key="F11" modifiers="0" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image113">
+ <widget class="GtkImage" id="image126">
<property name="visible">True</property>
<property name="stock">gtk-leave-fullscreen</property>
<property name="icon_size">1</property>
@@ -231,7 +253,7 @@
<child>
<widget class="GtkCheckMenuItem" id="menu_view_3d">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The View|3D Chess View menu">3_D Chess View</property>
+ <property name="label" translatable="yes">3_D Chess View</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="_on_toggle_3d_clicked" last_modification_time="Thu, 14 Sep 2006 19:40:59 GMT"/>
@@ -241,7 +263,7 @@
<child>
<widget class="GtkCheckMenuItem" id="menu_view_logs">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The View|Show Logs menu">Show _Logs</property>
+ <property name="label" translatable="yes">Show _Logs</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="_on_show_logs_clicked" last_modification_time="Sat, 01 Sep 2007 15:42:25 GMT"/>
@@ -255,7 +277,7 @@
<child>
<widget class="GtkMenuItem" id="settings">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The Settings menu">_Settings</property>
+ <property name="label" translatable="yes">_Settings</property>
<property name="use_underline">True</property>
<child>
@@ -266,10 +288,7 @@
<property name="visible">True</property>
<property name="label">gtk-preferences</property>
<property name="use_stock">True</property>
- <property name="use_underline">True</property>
<signal name="activate" handler="_on_preferences_clicked" last_modification_time="Sun, 20 Jan 2008 17:28:02 GMT"/>
-
-
</widget>
</child>
</widget>
@@ -280,7 +299,7 @@
<child>
<widget class="GtkMenuItem" id="help2">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="The Help menu">_Help</property>
+ <property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
@@ -288,12 +307,12 @@
<child>
<widget class="GtkImageMenuItem" id="menu_help">
- <property name="label" translatable="yes" comments="The Help|Contents menu">_Contents</property>
+ <property name="label" translatable="yes">_Contents</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_help_clicked" last_modification_time="Fri, 11 Aug 2006 12:43:28 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image115">
+ <widget class="GtkImage" id="image127">
<property name="visible">True</property>
<property name="stock">gtk-help</property>
<property name="icon_size">1</property>
@@ -404,6 +423,23 @@
</child>
<child>
+ <widget class="GtkToolButton" id="undo_move_button">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="The tooltip for the Resign toolbar button">Undo Move</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-undo</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="_on_undo_move_clicked" last_modification_time="Fri, 02 Jan 2009 04:58:33 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
<widget class="GtkToolButton" id="resign_button">
<property name="visible">True</property>
<property name="label" translatable="yes" comments="The tooltip for the Resign toolbar button">Resign</property>
Modified: trunk/glchess/src/lib/ai.py
==============================================================================
--- trunk/glchess/src/lib/ai.py (original)
+++ trunk/glchess/src/lib/ai.py Sun Jan 18 22:28:28 2009
@@ -359,6 +359,10 @@
isSelf = player is self and self.moving
self.moving = False
self.connection.reportMove(move.canMove, isSelf)
+
+ def onUndoMove(self):
+ """Called by game.ChessPlayer"""
+ self.connection.undoMove()
def readyToMove(self):
"""Called by game.ChessPlayer"""
Modified: trunk/glchess/src/lib/cecp.py
==============================================================================
--- trunk/glchess/src/lib/cecp.py (original)
+++ trunk/glchess/src/lib/cecp.py Sun Jan 18 22:28:28 2009
@@ -96,6 +96,10 @@
"""Stop the AI from automatically moving"""
self.onOutgoingData('force\n')
+ def sendUndo(self):
+ """Undo the last move"""
+ self.onOutgoingData('undo\n')
+
def sendMovePrompt(self):
"""Get the AI to move for the current player"""
self.onOutgoingData('go\n')
@@ -206,6 +210,11 @@
# Prompt the AI to move
self.sendMovePrompt()
+ def undoMove(self):
+ """Undo the last move made by this AI"""
+ self.sendWait()
+ self.sendUndo()
+
def reportMove(self, move, isSelf):
"""Report the move the current player has made.
Modified: trunk/glchess/src/lib/chess/board.py
==============================================================================
--- trunk/glchess/src/lib/chess/board.py (original)
+++ trunk/glchess/src/lib/chess/board.py Sun Jan 18 22:28:28 2009
@@ -201,6 +201,9 @@
# The move that got us to this state
lastMove = None
+
+ # Pieces moved that got us to this state
+ moves = None
# If the last move was a pawn march the location where it can be taken by en-passant
enPassantSquare = None
@@ -215,10 +218,11 @@
# Flag to show if the previous move has caused a three fold repition
threeFoldRepetition = False
-
+
+ # Bitboards
whiteBitBoard = 0
blackBitBoard = 0
- allBitBoard = 0
+ allBitBoard = 0
def __init__(self, lastState = None):
"""Constuctor for storing the state of a chess board.
@@ -243,6 +247,7 @@
self.moveNumber = 0
self.squares = {}
self.casualties = []
+ self.moves = []
self.whiteState = ChessPlayerState()
self.blackState = ChessPlayerState()
@@ -251,6 +256,7 @@
self.moveNumber = 0
self.squares = {}
self.casualties = []
+ self.moves = []
self.whiteBitBoard = 0
self.blackBitBoard = 0
self.allBitBoard = 0
@@ -275,6 +281,7 @@
self.squares = lastState.squares.copy()
self.casualties = lastState.casualties[:]
self.lastMove = lastState.lastMove
+ self.moves = lastState.moves[:]
self.enPassantSquare = lastState.enPassantSquare
self.whiteState = ChessPlayerState(lastState.whiteState)
self.blackState = ChessPlayerState(lastState.blackState)
@@ -352,8 +359,7 @@
# See if this piece can take
board = ChessBoardState(self)
- move = board.movePiece(enemyPiece.getColour(), enemyCoord, location, testCheck = False, applyMove = False)
- if move is not None:
+ if board.movePiece(enemyPiece.getColour(), enemyCoord, location, testCheck = False, applyMove = False):
return True
return False
@@ -375,8 +381,7 @@
for rank in 'abcdefgh':
for file in '12345678':
board = ChessBoardState(self)
- move = board.movePiece(colour, coord, rank + file, applyMove = False)
- if move is not None:
+ if board.movePiece(colour, coord, rank + file, applyMove = False):
return True
return False
@@ -693,6 +698,8 @@
self.allBitBoard = allBitBoard
else:
+ self.moves = result
+
# Remember the casualties
if victim is not None:
self.casualties.append(victim)
@@ -867,12 +874,11 @@
assert(self.__inCallback is False)
state = ChessBoardState(self.__boardStates[moveNumber])
- moves = state.movePiece(colour, start, end, promotionType = promotionType, allowSuicide = False)
- if moves is None:
+ if not state.movePiece(colour, start, end, promotionType = promotionType, allowSuicide = False):
return None
victim = None
- for (piece, start, end, delete) in moves:
+ for (piece, start, end, delete) in state.moves:
# The victim is the enemy piece that has been deleted
if delete and piece.getColour() != colour:
victim = piece
@@ -899,13 +905,22 @@
if not test:
self.__boardStates.append(state)
move = Move()
- move.moves = moves
+ move.moves = state.moves
move.victim = victim
move.opponentInCheck = state.inCheck(opponentColour)
move.opponentCanMove = state.canMove(opponentColour)
move.threeFoldRepetition = state.threeFoldRepetition
move.fiftyMoveRule = state.fiftyMoveCount >= 50
return move
+
+ def undo(self):
+ """Undo the last move"""
+ undoState = self.__boardStates[-1]
+ self.__boardStates = self.__boardStates[:-1]
+
+ # Undo the moves
+ for (piece, start, end, delete) in undoState.moves:
+ self.__onPieceMoved(piece, end, start, False)
def __str__(self):
"""Returns a representation of the current board state"""
Modified: trunk/glchess/src/lib/display.py
==============================================================================
--- trunk/glchess/src/lib/display.py (original)
+++ trunk/glchess/src/lib/display.py Sun Jan 18 22:28:28 2009
@@ -39,7 +39,7 @@
def onPlayerMoved(self, p, move):
self.view._redrawHighlight()
-
+
def onPlayerStartTurn(self, player):
self.view._redrawHighlight()
@@ -312,6 +312,10 @@
def selectSquare(self, coord):
pass
+
+ def undo(self):
+ """Called by ui.ViewFeedback"""
+ pass
def resign(self):
"""Called by ui.ViewFeedback"""
@@ -553,6 +557,12 @@
if self.game.inHistory:
return None
return self.game.fileName
+
+ def undo(self):
+ """Called by ui.ViewFeedback"""
+ p = self.game.getHumanPlayer()
+ if p is not None:
+ p.undo()
def resign(self):
"""Called by ui.ViewFeedback"""
Modified: trunk/glchess/src/lib/game.py
==============================================================================
--- trunk/glchess/src/lib/game.py (original)
+++ trunk/glchess/src/lib/game.py Sun Jan 18 22:28:28 2009
@@ -105,6 +105,9 @@
"""
pass
+ def onUndoMove(self):
+ pass
+
def onPlayerStartTurn(self, player):
pass
@@ -170,6 +173,10 @@
"""
self.__game.move(self, move)
+ def undo(self):
+ """Undo moves until it is this players turn"""
+ self.__game.undo(self)
+
def endMove(self):
"""Complete this players turn"""
self.__game.endMove(self)
@@ -496,6 +503,39 @@
self._move(player, move)
self.endLock()
+
+ def undo(self, player):
+ if self.__inCallback:
+ self.__queuedCalls.append((self.undo, (player,)))
+ return
+
+ self.startLock()
+
+ self.__whitePlayer._setReadyToMove(False)
+ self.__blackPlayer._setReadyToMove(False)
+
+ # Pretend the current player is the oponent so when endMove() is called
+ # this player will become the active player.
+ # Yes, this IS a big hack...
+ if player is self.__whitePlayer:
+ self.__currentPlayer = self.__blackPlayer
+ else:
+ self.__currentPlayer = self.__whitePlayer
+
+ # If this player hasn't moved then undo oponents move before their one
+ if len(self.__moves) > 0 and self.__moves[-1].player is not player:
+ count = 2
+ else:
+ count = 1
+
+ for i in xrange(count):
+ if len(self.__moves) != 0:
+ self.board.undo()
+ self.__moves = self.__moves[:-1]
+ for p in self.__players:
+ p.onUndoMove()
+
+ self.endLock()
def startLock(self):
assert(self.__inCallback is False)
Modified: trunk/glchess/src/lib/gtkui/chessview.py
==============================================================================
--- trunk/glchess/src/lib/gtkui/chessview.py (original)
+++ trunk/glchess/src/lib/gtkui/chessview.py Sun Jan 18 22:28:28 2009
@@ -570,6 +570,13 @@
self.ui._updateViewButtons()
+ def undoMove(self):
+ """Extends glchess.ui.ViewController"""
+ iter = self.moveModel.iter_nth_child(None, len(self.moveModel) - 1)
+ self.moveModel.remove(iter)
+ self.selectedMove = -1
+ self.ui._updateViewButtons()
+
def endGame(self, game):
# Translators: Message displayed when a player wins. The %s is substituted with the winning player's name
format = _('%s wins')
Modified: trunk/glchess/src/lib/gtkui/gtkui.py
==============================================================================
--- trunk/glchess/src/lib/gtkui/gtkui.py (original)
+++ trunk/glchess/src/lib/gtkui/gtkui.py Sun Jan 18 22:28:28 2009
@@ -821,6 +821,10 @@
except KeyError:
dialog = self.__saveGameDialogs[self.view] = dialogs.GtkSaveGameDialog(self, self.view, self.view.feedback.getFileName())
dialog.window.present()
+
+ def _on_undo_move_clicked(self, widget):
+ """Gtk+ callback"""
+ self.view.feedback.undo()
def _on_resign_clicked(self, widget):
"""Gtk+ callback"""
Modified: trunk/glchess/src/lib/main.py
==============================================================================
--- trunk/glchess/src/lib/main.py (original)
+++ trunk/glchess/src/lib/main.py Sun Jan 18 22:28:28 2009
@@ -648,10 +648,6 @@
return newGame
- def addMove(self, view, move):
- # TEMP
- self.ui.controller.addMove(view, move)
-
def start(self):
"""Run glChess.
Modified: trunk/glchess/src/lib/player.py
==============================================================================
--- trunk/glchess/src/lib/player.py (original)
+++ trunk/glchess/src/lib/player.py Sun Jan 18 22:28:28 2009
@@ -40,6 +40,9 @@
p.endMove()
self.__game.view.controller.addMove(move)
+
+ def onUndoMove(self):
+ self.__game.view.controller.undoMove()
def onGameEnded(self, game):
"""Called by chess.board.ChessPlayer"""
Modified: trunk/glchess/src/lib/uci.py
==============================================================================
--- trunk/glchess/src/lib/uci.py (original)
+++ trunk/glchess/src/lib/uci.py Sun Jan 18 22:28:28 2009
@@ -116,6 +116,16 @@
blackTime = 30000
self.__sendCommand('go wtime %d btime %d' % (whiteTime, blackTime))
+
+ def undoMove(self):
+ """
+ """
+ self.__sendCommand('stop');
+ (self.__positionCommand, _) = self.__positionCommand.rsplit(" ", 1)
+ if self.__positionCommand.endswith(' moves'):
+ self.__haveMoves = False
+ self.__positionCommand = 'position startpos'
+ self.__sendCommand(self.__positionCommand)
def reportMove(self, move, isSelf):
"""
@@ -125,7 +135,7 @@
self.__haveMoves = True
self.__positionCommand += ' ' + move
self.__sendCommand(self.__positionCommand)
-
+
def parseLine(self, line):
"""
"""
Modified: trunk/glchess/src/lib/ui/ui.py
==============================================================================
--- trunk/glchess/src/lib/ui/ui.py (original)
+++ trunk/glchess/src/lib/ui/ui.py Sun Jan 18 22:28:28 2009
@@ -206,6 +206,10 @@
'filename' is the file to save to (string or None to save to last filename).
"""
assert(False)
+
+ def undo(self):
+ """Indicates the human player wants to undo their last move"""
+ assert(False)
def regsign(self):
"""Indicates the human player wants to resign"""
@@ -238,6 +242,10 @@
'move' is the move made (string).
"""
assert(False)
+
+ def undoMove(self):
+ """Remove the last move from this view"""
+ assert(False)
def render(self):
"""Request this view is redrawn"""
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]