Viewing file: display.py (17.68 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# -*- coding: utf-8 -*- __author__ = 'Robert Ancell <bob27@users.sourceforge.net>' __license__ = 'GNU General Public License Version 2' __copyright__ = 'Copyright 2005-2006 Robert Ancell'
import config import player import scene import scene.cairo import scene.opengl import scene.human import ui import game import chess.board
class MovePlayer(game.ChessPlayer): """This class provides a pseudo-player to watch for piece movements"""
def __init__(self, view): """Constructor for a move player. 'view' is the view to update """ self.view = view game.ChessPlayer.__init__(self, '@view')
# Extended methods
def onPieceMoved(self, piece, start, end, delete): """Called by chess.board.ChessPlayer""" if self.view.moveNumber != -1: return animate = self.view.game.isStarted() p = self.view.scene.movePiece(piece, end, delete, animate)
# If a player move notify when animation completes if animate and self.view.moveNumber == -1 and start is not None and start != end: self.view.scene.waitingPiece = p
def onPlayerMoved(self, p, move): self.view._redrawHighlight() def onPlayerStartTurn(self, player): self.view._redrawHighlight()
class CairoPiece(scene.ChessPieceFeedback): """ """
def __init__(self, scene, piece): self.scene = scene self.piece = piece self.model = None self.location = ''
def onDeleted(self): """Called by scene.ChessPieceFeedback""" self.scene.pieces.pop(self.piece)
def onMoved(self): """Called by scene.ChessPieceFeedback""" self.scene.view._pieceMoved(self)
class SceneCairo(scene.SceneFeedback, scene.human.SceneHumanInput): """ """
def __init__(self, view): """ """ self.view = view self.controller = scene.cairo.Scene(self) self.game = view.game self.pieces = {} self.waitingPiece = None scene.human.SceneHumanInput.__init__(self) def getPieces(self): return self.pieces.values()
def movePiece(self, piece, location, delete, animate): """ """ # Get the model for this piece creating one if it doesn't exist try: p = self.pieces[piece] except KeyError: # Make the new model pieceName = {chess.board.PAWN: 'pawn', chess.board.ROOK: 'rook', chess.board.KNIGHT: 'knight', chess.board.BISHOP: 'bishop', chess.board.QUEEN: 'queen', chess.board.KING: 'king'}[piece.getType()] chessSet = {chess.board.WHITE: 'white', chess.board.BLACK: 'black'}[piece.getColour()] p = CairoPiece(self, piece) p.model = self.controller.addChessPiece(chessSet, pieceName, location, p) self.pieces[piece] = p
# Move the model p.location = location p.model.move(location, delete, animate) return p
# Extended methods
def onRedraw(self): """Called by scene.cairo.Scene""" if self.game.view is not None and self.game.view.controller is not None: self.game.view.controller.render()
def startAnimation(self): """Called by scene.cairo.Scene""" self.game.application.ui.controller.startAnimation() def getSquare(self, x, y): """Called by scene.human.SceneHumanInput""" return self.controller.getSquare(x, y)
def playerIsHuman(self): """Called by scene.human.SceneHumanInput""" return self.game.currentPlayerIsHuman()
def squareIsFriendly(self, coord): """Called by scene.human.SceneHumanInput""" return self.playerIsHuman() and self.game.squareIsFriendly(coord) def canMove(self, start, end): """Called by scene.human.SceneHumanInput""" return self.playerIsHuman() and self.game.getCurrentPlayer().canMove(start, end) # FIXME: Promotion type
def selectSquare(self, coord): """Called by scene.human.SceneHumanInput""" self.view.setSelectedSquare(coord)
def moveHuman(self, start, end): """Called by scene.human.SceneHumanInput""" self.game.moveHuman(start, end) class OpenGLPiece(scene.ChessPieceFeedback): """ """
def __init__(self, scene, piece): self.scene = scene self.piece = piece self.model = None self.location = ''
def onDeleted(self): """Called by scene.ChessPieceFeedback""" self.scene.pieces.pop(self.piece)
def onMoved(self): """Called by scene.ChessPieceFeedback""" self.scene.view._pieceMoved(self)
class SceneOpenGL(scene.SceneFeedback, scene.human.SceneHumanInput): """ """
def __init__(self, view): """Constructor for a glChess scene.
""" self.view = view self.game = view.game self.pieces = {} self.waitingPiece = None
# Call parent constructors self.controller = scene.opengl.Scene(self) scene.human.SceneHumanInput.__init__(self)
def getPieces(self): return self.pieces.values() def movePiece(self, piece, location, delete, animate): """ """ # Get the model for this piece creating one if it doesn't exist try: p = self.pieces[piece] except KeyError: # Make the new model pieceName = {chess.board.PAWN: 'pawn', chess.board.ROOK: 'rook', chess.board.KNIGHT: 'knight', chess.board.BISHOP: 'bishop', chess.board.QUEEN: 'queen', chess.board.KING: 'king'}[piece.getType()] chessSet = {chess.board.WHITE: 'white', chess.board.BLACK: 'black'}[piece.getColour()] p = OpenGLPiece(self, piece) p.model = self.controller.addChessPiece(chessSet, pieceName, location, p) self.pieces[piece] = p # Move the model p.location = location p.model.move(location, delete)
return p
# Extended methods
def onRedraw(self): """Called by scene.opengl.Scene""" if self.game.view is not None and self.game.view.controller is not None: self.game.view.controller.render()
def startAnimation(self): """Called by scene.opengl.Scene""" self.game.application.ui.controller.startAnimation() def getSquare(self, x, y): """Called by scene.human.SceneHumanInput""" return self.controller.getSquare(x, y)
def playerIsHuman(self): """Called by scene.human.SceneHumanInput""" return self.game.currentPlayerIsHuman()
def squareIsFriendly(self, coord): """Called by scene.human.SceneHumanInput""" return self.playerIsHuman() and self.game.squareIsFriendly(coord) def canMove(self, start, end): """Called by scene.human.SceneHumanInput""" return self.playerIsHuman() and self.game.getCurrentPlayer().canMove(start, end) # FIXME: Promotion type def selectSquare(self, coord): """Called by scene.human.SceneHumanInput""" self.view.setSelectedSquare(coord) def moveHuman(self, start, end): """Called by scene.human.SceneHumanInput""" self.game.moveHuman(start, end)
class Splashscreen(ui.ViewFeedback): """ """
def __init__(self, application): """Constructor. 'application' is ??? """ self.application = application self.cairoScene = scene.cairo.Scene(self) self.scene = scene.opengl.Scene(self)
def updateRotation(self, animate = True): boardView = config.get('board_view') if boardView == 'black': rotation = 180.0 else: rotation = 0.0 self.cairoScene.controller.setBoardRotation(rotation, boardView == 'facetoface', animate) self.scene.controller.setBoardRotation(rotation, boardView == 'facetoface', animate)
def onRedraw(self): """Called by scene.SceneFeedback""" if self.controller is not None: self.controller.render() def showBoardNumbering(self, showNumbering): """Called by ui.ViewFeedback""" self.scene.showBoardNumbering(showNumbering) self.cairoScene.showBoardNumbering(showNumbering)
def showMoveHints(self, showHints): """Called by ui.ViewFeedback""" pass
def renderGL(self): """Called by ui.ViewFeedback""" self.scene.render() def renderCairoStatic(self, context): """Called by ui.ViewFeedback""" return self.cairoScene.renderStatic(context) def renderCairoDynamic(self, context): """Called by ui.ViewFeedback""" self.cairoScene.renderDynamic(context) def reshape(self, width, height): """Called by ui.ViewFeedback""" self.scene.reshape(width, height) self.cairoScene.reshape(width, height)
def select(self, x, y): pass def deselect(self, x, y): pass
def selectSquare(self, coord): pass def undo(self): """Called by ui.ViewFeedback""" pass
def resign(self): """Called by ui.ViewFeedback""" pass def claimDraw(self): """Called by ui.ViewFeedback""" pass def setMoveNumber(self, moveNumber): """Called by ui.ViewFeedback""" pass
class View(ui.ViewFeedback): """ """
def __init__(self, game): """Constructor. 'game' is the game this view is rendering """ self.game = game # The move we are watching self.moveNumber = -1 # The selected square self.selectedCoord = None self.showHints = False self.showNumbering = False self.doSmooth = False self.highlightParams = (None, None, None, None) self.changedHighlight = True self.controller = None # Use a Cairo scene by default - it will be replaced by an OpenGL one if that is the requested view # I wanted to remove this but then scene is None and there are a number of issues... # This should be cleaned up self.scene = SceneCairo(self) config.watch('board_view', self.__onBoardViewChanged)
# Look for game events to update the scene movePlayer = MovePlayer(self) game.addSpectator(movePlayer)
def setSelectedSquare(self, coord): if self.selectedCoord == coord: return self.selectedCoord = coord self._redrawHighlight()
def _redrawHighlight(self): self.changedHighlight = True if self.controller is not None: self.controller.render()
def __onBoardViewChanged(self, key, value): self.updateRotation()
def _updateHighlight(self, coord): if self.moveNumber == -1: player = self.game.getCurrentPlayer() if player is self.game.getWhite(): colour = chess.board.WHITE else: colour = chess.board.BLACK else: if self.moveNumber % 2 == 0: colour = chess.board.WHITE else: colour = chess.board.BLACK
# Don't update if nothing has changed params = (colour, self.moveNumber, self.selectedCoord, self.showHints) if self.highlightParams == params: return self.highlightParams = params
highlights = {} if self.showHints: for file in '12345678': for rank in 'abcdefgh': c = rank + file highlight = None if self.game.board.squareUnderAttack(colour, c, moveNumber = self.moveNumber): highlight = scene.HIGHLIGHT_THREATENED elif coord is not None: move = self.game.board.testMove(colour, coord, c, moveNumber = self.moveNumber) if move is not None: if self.game.board.getPiece(c, self.moveNumber): highlight = scene.HIGHLIGHT_CAN_TAKE else: highlight = scene.HIGHLIGHT_CAN_MOVE
if highlight is not None: highlights[c] = highlight if coord is not None: highlights[coord] = scene.HIGHLIGHT_SELECTED
self.scene.controller.setBoardHighlight(highlights)
def updateRotation(self, animate = True): """ """ # Get the angle to face p = self.game.getCurrentPlayer() if p is self.game.getWhite(): rotation = 0.0 elif p is self.game.getBlack(): rotation = 180.0 # Decide if we should face this angle boardView = config.get('board_view') if boardView == 'white' or boardView == 'facetoface': rotation = 0.0 elif boardView == 'black': rotation = 180.0 elif boardView == 'human': if not isinstance(p, player.HumanPlayer): return
self.scene.controller.setBoardRotation(rotation, boardView == 'facetoface', animate)
def _pieceMoved(self, piece): """ """ self._redrawHighlight() # If waiting for this piece then end players turn if piece is not None and piece is self.scene.waitingPiece: self.scene.waitingPiece = None self.game.getCurrentPlayer().endMove()
def showMoveHints(self, showHints): """Called by ui.ViewFeedback""" self.showHints = showHints self._redrawHighlight()
def showBoardNumbering(self, showNumbering): """Called by ui.ViewFeedback""" self.showNumbering = showNumbering self.scene.controller.showBoardNumbering(showNumbering) def showSmooth(self, doSmooth): """Called by ui.ViewFeedback""" self.doSmooth = doSmooth self.scene.controller.showSmooth(doSmooth)
def updateScene(self, sceneClass): """ """ if self.changedHighlight: self._updateHighlight(self.selectedCoord) self.changedHighlight = False if isinstance(self.scene, sceneClass): return self._pieceMoved(None) self.scene = sceneClass(self) self.reshape(self.width, self.height) self.setMoveNumber(self.moveNumber) self.showBoardNumbering(self.showNumbering) self.showSmooth(self.doSmooth) self.updateRotation(animate = False)
def renderGL(self): """Called by ui.ViewFeedback""" self.updateScene(SceneOpenGL) self.scene.controller.render()
def renderCairoStatic(self, context): """Called by ui.ViewFeedback""" self.updateScene(SceneCairo) return self.scene.controller.renderStatic(context) def renderCairoDynamic(self, context): """Called by ui.ViewFeedback""" self.updateScene(SceneCairo) self.scene.controller.renderDynamic(context)
def reshape(self, width, height): """Called by ui.ViewFeedback""" self.width = width self.height = height self.scene.controller.reshape(width, height) def select(self, x, y): """Called by ui.ViewFeedback""" self.scene.select(x, y) def deselect(self, x, y): """Called by ui.ViewFeedback""" self.scene.deselect(x, y) def setMoveNumber(self, moveNumber): """Called by ui.ViewFeedback""" self.moveNumber = moveNumber # Lock the scene if not tracking the game self.scene.enableHumanInput(moveNumber == -1) # Get the state of this scene piecesByLocation = self.game.getAlivePieces(moveNumber) # Remove any models not present requiredPieces = piecesByLocation.values() for piece in self.scene.getPieces(): try: requiredPieces.index(piece.piece) except ValueError: piece.model.move(piece.location, True) # Move the models in the scene for (location, piece) in piecesByLocation.iteritems(): self.scene.movePiece(piece, location, False, True)
# Can't wait for animation if not looking at the latest move if moveNumber != -1: self._pieceMoved(piece)
self._redrawHighlight()
def save(self, fileName = None): """Called by ui.ViewFeedback""" # If filename supplied take out of the history if fileName is not None: if self.game.inHistory: self.game.inHistory = False if self.game.fileName is not None: self.game.application.history.rename(self.game.fileName, fileName) self.game.fileName = fileName return self.game.save()
def getFileName(self): """Called by ui.ViewFeedback""" # If in the history then prompt for a new name 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""" p = self.game.getHumanPlayer() if p is None: # If no human players then abandon game self.game.abandon() else: p.resign() def claimDraw(self): """Called by ui.ViewFeedback""" # TODO: Have the UI ask if the player wants to make a move first or claim now (or abort) p = self.game.getHumanPlayer() if p is None: return False return p.claimDraw()
|