Beispiel #1
1
 def board_size_change(self, widget, size):
     self.lastY = -1
     self.lastX = -1
     if size == self.size:
         return
     self.size = size
     del self.game
     self.game = GoGame(size)
     self.board_aspect.remove(self.board)
     del self.board
     self.board = boardwidget.GoBoardWidget(self.game.get_status(), int(size))
     self.board_aspect.add(self.board)
     self.board.connect('motion-notify-event', self.board_motion_cb)
     self.board.connect('insert-requested', self.insert_cb)
     self.board.show()
     if self.ai_activated:
         del self.ai
         self.ai = gnugo(boardsize=self.size)
Beispiel #2
0
 def board_size_change(self, widget, size):
     self.lastY = -1
     self.lastX = -1
     if size == self.size:
         return
     self.size = size
     del self.game
     self.game = GoGame(size)
     self.board_aspect.remove(self.board)
     del self.board
     self.board = boardwidget.GoBoardWidget(self.game.get_status(),
                                            int(size))
     self.board_aspect.add(self.board)
     self.board.connect('motion-notify-event', self.board_motion_cb)
     self.board.connect('insert-requested', self.insert_cb)
     self.board.show()
     if self.ai_activated:
         del self.ai
         self.ai = gnugo(boardsize=self.size)
Beispiel #3
0
    def __init__(self, handle):
        # Initialize the parent
        Activity.__init__(self, handle)

        logger.debug('Initiating PlayGo')

        self.size = DEFAULT_SIZE
        self.komi = DEFAULT_KOMI

        # Set the activity toolbarbox
        toolbarbox = ToolbarBox()
        self.set_toolbar_box(toolbarbox)

        toolbarbox.toolbar.insert(ActivityToolbarButton(self), -1)
        toolbarbox.toolbar.insert(Gtk.SeparatorToolItem(), -1)

        self.gameToolbar = GameToolbar(self)
        self.gameToolbar.connect('game-restart', self.restart_game)
        self.gameToolbar.connect('game-board-size', self.board_size_change)
        self.gameToolbar.connect('ai-activated', self.ai_activated_cb)
        self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb)
        toolbarbox.toolbar.insert(
            ToolbarButton(page=self.gameToolbar, icon_name='txt'), -1)

        separator = Gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbarbox.toolbar.insert(separator, -1)

        toolbarbox.toolbar.insert(StopButton(self), -1)

        toolbarbox.show_all()
        toolbarbox.toolbar.show_all()
        self.gameToolbar.show_all()

        # Initialize the game
        self.game = GoGame(self.size)
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.ai_activated = False
        self.set_up_ui()

        if not handle.object_id:
            self.infopanel.show(_('Welcome to PlayGo!'))
        else:
            self.show_score()

        self.lastX = -1
        self.lastY = -1

        # Set keypad actions
        self._key_actions = {
            'KP_Up': 'move_up',
            'KP_Right': 'move_right',
            'KP_Down': 'move_down',
            'KP_Left': 'move_left',
            'KP_Home': 'place_stone',
            'KP_Next': 'undo',
            'KP_End': 'pass'
        }

        # Set up collaboration
        self.collaboration = CollaborationWrapper(self, self.buddy_joined,
                                                  self.buddy_left, self.Play,
                                                  self.game.undostack,
                                                  self.bootstrap)

        self.connect('shared', self.collaboration._shared_cb)
        if self.get_shared_activity():
            # We are joining the activity
            self.connect('joined', self.collaboration._joined_cb)
            if self.get_shared():
                # We've already joined
                self.collaboration._joined_cb()
Beispiel #4
0
class PlayGo(Activity):
    def __init__(self, handle):
        # Initialize the parent
        Activity.__init__(self, handle)

        logger.debug('Initiating PlayGo')

        self.size = DEFAULT_SIZE
        self.komi = DEFAULT_KOMI

        # Set the activity toolbarbox
        toolbarbox = ToolbarBox()
        self.set_toolbar_box(toolbarbox)

        toolbarbox.toolbar.insert(ActivityToolbarButton(self), -1)
        toolbarbox.toolbar.insert(Gtk.SeparatorToolItem(), -1)

        self.gameToolbar = GameToolbar(self)
        self.gameToolbar.connect('game-restart', self.restart_game)
        self.gameToolbar.connect('game-board-size', self.board_size_change)
        self.gameToolbar.connect('ai-activated', self.ai_activated_cb)
        self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb)
        toolbarbox.toolbar.insert(
            ToolbarButton(page=self.gameToolbar, icon_name='txt'), -1)

        separator = Gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbarbox.toolbar.insert(separator, -1)

        toolbarbox.toolbar.insert(StopButton(self), -1)

        toolbarbox.show_all()
        toolbarbox.toolbar.show_all()
        self.gameToolbar.show_all()

        # Initialize the game
        self.game = GoGame(self.size)
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.ai_activated = False
        self.set_up_ui()

        if not handle.object_id:
            self.infopanel.show(_('Welcome to PlayGo!'))
        else:
            self.show_score()

        self.lastX = -1
        self.lastY = -1

        # Set keypad actions
        self._key_actions = {
            'KP_Up': 'move_up',
            'KP_Right': 'move_right',
            'KP_Down': 'move_down',
            'KP_Left': 'move_left',
            'KP_Home': 'place_stone',
            'KP_Next': 'undo',
            'KP_End': 'pass'
        }

        # Set up collaboration
        self.collaboration = CollaborationWrapper(self, self.buddy_joined,
                                                  self.buddy_left, self.Play,
                                                  self.game.undostack,
                                                  self.bootstrap)

        self.connect('shared', self.collaboration._shared_cb)
        if self.get_shared_activity():
            # We are joining the activity
            self.connect('joined', self.collaboration._joined_cb)
            if self.get_shared():
                # We've already joined
                self.collaboration._joined_cb()

    def set_up_ui(self):
        self.board = boardwidget.GoBoardWidget(self.game.get_status(),
                                               self.size)
        self.board.connect('motion-notify-event', self.board_motion_cb)
        self.board.connect('insert-requested', self.insert_cb)

        self.main_view = Gtk.VBox()

        self.board_aspect = Gtk.AspectFrame.new(None, .5, .5, 1, False)
        self.board_aspect.add(self.board)
        self.main_view.pack_start(self.board_aspect, True, True, 0)

        self.buttons_box = Gtk.HBox()
        self.buttons_alignment = Gtk.Alignment.new(0.5, 1, 0.5, 1)
        # Pass button
        self.pass_button = Gtk.Button(_('Pass'))
        self.pass_button.connect("clicked", self.pass_cb)
        self.buttons_box.pack_start(self.pass_button, True, True, 10)

        # Undo button
        self.undo_button = Gtk.Button(_('Undo'))
        self.undo_button.connect("clicked", self.undo_cb)
        self.buttons_box.pack_start(self.undo_button, True, True, 10)

        self.buttons_alignment.add(self.buttons_box)
        self.main_view.pack_start(self.buttons_alignment, False, True, 10)

        self.infopanel = infopanel.InfoPanel()
        self.main_view.pack_start(self.infopanel, False, True, 0)

        self.set_canvas(self.main_view)
        self.show_all()

    def insert_cb(self, widget, x, y, announce=True, ai_play=False):
        '''The insert function. It makes the play and manages turn changing
           stone drawing, etc.

        Parameters x and y are the coordinates of the play ((0,0) is top left),
        widget points to the widget that emitted the signal connected to this
        function, announce is True when we need to announce this play to
        other people collaborating, and ai_play is True when this is called
        by the AI, so we know not to ask for an AI play again'''

        # Check if it's our turn only if it's a local play (announce is True)
        # Calls by other players will always be out of turn for us.
        if announce and self.get_currentcolor() != self.get_playercolor():
            logger.debug('Play at %s x %s was out-of-turn!', x, y)
            self.infopanel.show(_('It\'s not your turn!'))
            return False
        # Make the play only if it wasn't a pass move.
        if x != -1:
            self.pass_count = 0
            error = self.game.illegal(x, y, self.get_currentcolor())
            if error:
                self.infopanel.show(error)
                return False
            # Make the play
            captures = self.game.play((x, y), self.get_currentcolor())
            if self.ai_activated and not ai_play:
                self.notify_ai(x, y, self.get_currentcolor())

            self.gameToolbar.grey_out_size_change()

            if captures:
                self.redraw_captures(captures)

            self.show_score()
            self.board.draw_stone(self.board.context, x, y,
                                  self.get_currentcolor(), widget)
            self.board.queue_draw()
        # Player passed
        else:
            self.pass_count += 1
        # Announce the local play
        if self.get_shared() and announce:
            self.collaboration.Play(x, y)
        self.change_turn()
        if x == -1:
            self.infopanel.show(_('Opponent passed'))
        # If this is the second consecutive pass, the game ends
        if self.pass_count == 2:
            self.game_end()
            return
        # If we are playing a local game with AI turned off, change the color
        if not self.get_shared() and not self.ai_activated:
            self.change_player_color()
        # Else, if the AI is on, and this wasn't played by it,
        # request a play by it.
        elif self.ai_activated:
            self.change_player_color()
            if not ai_play:
                self.play_ai()

    def undo_cb(self, widget=None, data=None):
        if self.game.undo():
            self.board.queue_draw()
            # If playing against AI undo twice
            if self.ai_activated:
                self.ai.undo()
                self.game.undo()
                self.ai.undo()
            else:
                self.change_turn()

            if not self.get_shared() and not self.ai_activated:
                self.change_player_color()

            self.show_score()

    def pass_cb(self, widget=None, data=None):
        if self.get_shared():
            if self.get_currentcolor() == self.get_playercolor():
                self.pass_count += 1
                self.collaboration.Play(-1, -1)
            else:
                self.infopanel.show(_('It\'s not your turn!'))
                return
        else:
            self.pass_count += 1
            self.change_player_color()

        self.change_turn()

        if self.pass_count == 2:
            self.game_end()

        if self.ai_activated:
            self.ai.pass_move(self.get_currentcolor())
            self.play_ai()

    def write_file(self, file_path):
        logger.debug('Writing file: %s', file_path)
        # Strip the undostack
        undostack = self.game.undostack[:]
        strippedstack = []
        for pos, color, captures in undostack:
            strippedstack.append(pos)

        f = open(file_path, 'wb')

        try:
            pickle.dump(strippedstack, f, pickle.HIGHEST_PROTOCOL)
        except Exception as e:
            print("Error ", e, " occured")
        finally:
            f.close()

        self.metadata['our-color'] = self.get_playercolor()
        self.metadata['shared'] = str(self.get_shared())
        self.metadata['size'] = str(self.size)
        self.metadata['ai'] = str(self.ai_activated)

    def read_file(self, file_path):
        logger.debug('Reading file: %s', file_path)
        f = open(file_path, 'r')
        try:
            newstack = pickle.load(f)
        finally:
            f.close()

        if self.get_shared():
            logger.debug('The game we are loading is shared!')
            self.PlayerColor = self.metadata.get('our-color', 'B')
        if self.size != self.metadata.get('size', DEFAULT_SIZE):
            self.board_size_change(
                None, int(self.metadata.get('size', DEFAULT_SIZE)))

        self.bootstrap(newstack)

        if self.metadata.get('ai', None) == 'True':
            self.gameToolbar._size_combo.set_sensitive(False)
            # This triggers the 'toggled' signal too
            self.gameToolbar._ai_button.set_active(True)

    def board_motion_cb(self, widget, event):
        x, y = self.board.get_mouse_event_xy(event)
        if x == self.lastX and y == self.lastY:
            return

        if not self.game.is_occupied(x, y)\
                and self.game.legal((x, y), self.get_playercolor()):
            self.board.draw_ghost_stone(x, y, self.get_playercolor())
            self.lastX = x
            self.lastY = y

    def invert_color(self, color):
        if color == 'B':
            return 'W'
        return 'B'

    def get_currentcolor(self):
        return self.CurrentColor

    def change_turn(self):
        # It's the other guy's turn now
        if self.CurrentColor == 'B':
            self.infopanel.show(_('White\'s turn'))
        else:
            self.infopanel.show(_('Black\'s turn'))

        self.CurrentColor = self.invert_color(self.get_currentcolor())

    def get_playercolor(self):
        return self.PlayerColor

    def change_player_color(self):
        self.PlayerColor = self.invert_color(self.get_playercolor())

    def set_player_color(self, color):
        self.PlayerColor = color

    def redraw_captures(self, captures):
        for x in captures:
            self.board.redraw_area(x[0], x[1])

    def bootstrap(self, plays):
        ''' Take our game to the state it would have if
            @plays were manually played'''
        logger.debug('Bootstraping...')
        # HACK: Looks like read_file is called before the board is exposed
        self.board.queue_draw()
        for pos in plays:
            logger.debug('Playing at %s with color %s', pos,
                         self.get_currentcolor())
            captures = self.game.play((pos[0], pos[1]),
                                      self.get_currentcolor())
            if captures:
                self.redraw_captures(captures)

            self.change_turn()
            self.change_player_color()

        logger.debug('Color after bootstraping is %s', self.get_currentcolor())
        self.show_score()
        self.board.queue_draw()

    def restart_game(self, widget=None):
        logger.debug('Received restart signal!')
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.game.clear()
        self.board.territories = None
        self.board.status = self.game.status
        self.board.queue_draw()
        self.show_score()
        self.board.set_sensitive(True)
        self.buttons_box.set_sensitive(True)
        self.lastX = -1
        self.lastY = -1
        if self.ai_activated:
            self.ai.clear()

    def game_end(self):
        self.board.set_sensitive(False)
        self.buttons_box.set_sensitive(False)
        territories = self.game.get_territories()
        self.board.territories = territories

        final_score = {
            'B': (len(territories['B']) - self.game.get_score()['W']),
            'W':
            (len(territories['W']) - self.game.get_score()['B'] + self.komi)
        }

        if final_score['B'] > final_score['W']:
            winner_string = _('Black wins!')

        elif final_score['W'] > final_score['B']:
            winner_string = _('White wins!')

        else:
            winner_string = _('There was a tie!')

        self.infopanel.show(_('Game ended! %s' % winner_string))
        self.infopanel.show_score(
            _('Final score: White %(W)g - Black %(B)g' % final_score))

    def board_size_change(self, widget, size):
        self.lastY = -1
        self.lastX = -1
        if size == self.size:
            return

        self.size = size
        del self.game
        self.game = GoGame(size)
        self.board_aspect.remove(self.board)
        del self.board
        self.board = boardwidget.GoBoardWidget(self.game.get_status(),
                                               int(size))
        self.board_aspect.add(self.board)
        self.board.connect('motion-notify-event', self.board_motion_cb)
        self.board.connect('insert-requested', self.insert_cb)
        self.board.show()
        if self.ai_activated:
            del self.ai
            self.ai = gnugo(boardsize=self.size)

    def ai_activated_cb(self, widget=None):
        try:
            self.ai = gnugo(boardsize=self.size)
        except Exception as e:
            self._alert(_('AI'), _('GnuGo loading failed!: %s' % e))
            self.gameToolbar.set_ai_button_state(False)

        else:
            self.ai_activated = True
            for pos, color, captures in self.game.undostack:
                self.notify_ai(pos[0], pos[1], color)

            self._alert(_('AI'), _('PlayGo AI Activated'))

    def ai_deactivated_cb(self, widget):
        if self.ai:
            self.ai_activated = False
            del self.ai
            self._alert(_('AI'), _('PlayGo AI Deactivated'))

    def notify_ai(self, x, y, color):
        logger.debug('Notifying AI of play by %s at %s x %s', color, x, y)
        self.ai.make_play(color, x, y)

    def play_ai(self):
        if self.get_currentcolor() == self.get_playercolor():
            x, y = self.ai.get_move(self.get_currentcolor())
            logger.debug('Got play %s x %s from AI', x, y)
            self.insert_cb(None, x, y, ai_play=True)

    def show_score(self):
        self.infopanel.show_score(
            _("Score is: White %(W)g - Black %(B)g" % self.game.get_score()))

    def _alert(self, title, text=None):
        alert = NotifyAlert(timeout=5)
        alert.props.title = title
        alert.props.msg = text
        self.add_alert(alert)
        alert.connect('response', self._alert_cancel_cb)
        alert.show()

    def _alert_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)

    # ----------- Keypad events functions ----------- #
    def _key_pressed_cb(self, grabber, keycode, state):
        key = grabber.get_key(keycode, state)
        logging.debug("Key pressed: %s", key)
        action = self._key_actions[key]
        method = getattr(self, 'handle_' + action)
        method()

    def handle_move_up(self):
        self.move_ghost_stone(0, -1)

    def handle_move_right(self):
        self.move_ghost_stone(1, 0)

    def handle_move_down(self):
        self.move_ghost_stone(0, 1)

    def handle_move_left(self):
        self.move_ghost_stone(-1, 0)

    def handle_place_stone(self):
        self.insert_cb(None, self.lastX, self.lastY)

    def handle_undo(self):
        self.undo_cb()

    def handle_pass(self):
        self.pass_cb()

    def move_ghost_stone(self, deltaX=0, deltaY=0):
        if self.lastX < 0:
            self.lastX = int(self.size / 2)
            self.lastY = int(self.size / 2)
        x = self.lastX + deltaX
        y = self.lastY + deltaY
        if x < 0 or x > self.size - 1 or y < 0 or y > self.size - 1:
            return

        self.board.draw_ghost_stone(x, y, self.get_playercolor())
        self.lastX = x
        self.lastY = y

    # ------- Callbacks for Collaboration ------- #
    def buddy_joined(self, buddy):
        self._alert(_('Buddy joined'), _('%s joined' % buddy.props.nick))

    def buddy_left(self, buddy):
        self._alert(_('Buddy left'), _('%s left' % buddy.props.nick))

    def Play(self, x, y, sender=None):
        ''' Called when a stone was placed at x,y by sender'''
        # Discard a pass move received in our turn.
        # Do it here for extra security
        if x == -1 and self.get_currentcolor() == self.get_playercolor():
            return
        self.insert_cb(None, x, y, False)
Beispiel #5
0
    def __init__(self, handle):
        # Initialize the parent
        Activity.__init__(self, handle)
        logger.debug('Initiating PlayGo')
        
        self.size = DEFAULT_SIZE
        self.komi = DEFAULT_KOMI
        
        # Set the activity toolbox
        toolbox = ActivityToolbox(self)
        self.set_toolbox(toolbox)
        self.gameToolbar = GameToolbar(self)
        toolbox.add_toolbar(_('Game'), self.gameToolbar)
        self.gameToolbar.connect('game-restart', self.restart_game)
        self.gameToolbar.connect('game-board-size', self.board_size_change)
        self.gameToolbar.connect('ai-activated', self.ai_activated_cb)
        self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb)
        self.gameToolbar.show()  
        
        # Initialize the game
        self.game = GoGame(self.size)
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.ai_activated = False
        self.set_up_ui()
        
        if not handle.object_id:
            self.infopanel.show(_('Welcome to PlayGo!'))
        else:
            self.show_score()
        self.lastX = -1
        self.lastY = -1

        # Set keypad actions
        self._key_actions = {
            'KP_Up'     : 'move_up',
            'KP_Right'  : 'move_right',
            'KP_Down'   : 'move_down',
            'KP_Left'   : 'move_left',
            'KP_Home'   : 'place_stone',
            'KP_Next'   : 'undo',
            'KP_End'    : 'pass' }

        self._key_grabber = KeyGrabber()
        self._key_grabber.connect('key-pressed',
                                  self._key_pressed_cb)

        # New KeyGrabber API change (ticket #7999)
        try:
            self._key_grabber.grab_keys(self._key_actions.keys())
        except:
            for key in self._key_actions.keys():
                self._key_grabber.grab(key)

        #Set up collaboration
        self.collaboration = CollaborationWrapper(self, 
                                                  self.buddy_joined, 
                                                  self.buddy_left, 
                                                  self.Play, 
                                                  self.game.undostack, 
                                                  self.bootstrap)
        
        self.connect('shared', self.collaboration._shared_cb)
        if self._shared_activity:
            # We are joining the activity
            self.connect('joined', self.collaboration._joined_cb)
            if self.get_shared():
                # We've already joined
                self.collaboration._joined_cb()
Beispiel #6
0
class PlayGo(Activity):
    def __init__(self, handle):
        # Initialize the parent
        Activity.__init__(self, handle)
        logger.debug('Initiating PlayGo')
        
        self.size = DEFAULT_SIZE
        self.komi = DEFAULT_KOMI
        
        # Set the activity toolbox
        toolbox = ActivityToolbox(self)
        self.set_toolbox(toolbox)
        self.gameToolbar = GameToolbar(self)
        toolbox.add_toolbar(_('Game'), self.gameToolbar)
        self.gameToolbar.connect('game-restart', self.restart_game)
        self.gameToolbar.connect('game-board-size', self.board_size_change)
        self.gameToolbar.connect('ai-activated', self.ai_activated_cb)
        self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb)
        self.gameToolbar.show()  
        
        # Initialize the game
        self.game = GoGame(self.size)
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.ai_activated = False
        self.set_up_ui()
        
        if not handle.object_id:
            self.infopanel.show(_('Welcome to PlayGo!'))
        else:
            self.show_score()
        self.lastX = -1
        self.lastY = -1

        # Set keypad actions
        self._key_actions = {
            'KP_Up'     : 'move_up',
            'KP_Right'  : 'move_right',
            'KP_Down'   : 'move_down',
            'KP_Left'   : 'move_left',
            'KP_Home'   : 'place_stone',
            'KP_Next'   : 'undo',
            'KP_End'    : 'pass' }

        self._key_grabber = KeyGrabber()
        self._key_grabber.connect('key-pressed',
                                  self._key_pressed_cb)

        # New KeyGrabber API change (ticket #7999)
        try:
            self._key_grabber.grab_keys(self._key_actions.keys())
        except:
            for key in self._key_actions.keys():
                self._key_grabber.grab(key)

        #Set up collaboration
        self.collaboration = CollaborationWrapper(self, 
                                                  self.buddy_joined, 
                                                  self.buddy_left, 
                                                  self.Play, 
                                                  self.game.undostack, 
                                                  self.bootstrap)
        
        self.connect('shared', self.collaboration._shared_cb)
        if self._shared_activity:
            # We are joining the activity
            self.connect('joined', self.collaboration._joined_cb)
            if self.get_shared():
                # We've already joined
                self.collaboration._joined_cb()

    def set_up_ui(self):        
        self.board = boardwidget.GoBoardWidget(self.game.get_status(), self.size)
        self.board.connect('motion-notify-event', self.board_motion_cb)
        self.board.connect('insert-requested', self.insert_cb)
        
        self.main_view = gtk.VBox()
        
        self.board_aspect = gtk.AspectFrame(None, .5, .5, 1, False)
        self.board_aspect.add(self.board)
        self.main_view.pack_start(self.board_aspect)
        
        self.buttons_box = gtk.HBox()
        self.buttons_alignment = gtk.Alignment(0.5, 1, 0.5, 1)
        #Pass button
        self.pass_button = gtk.Button(_('Pass'))
        self.pass_button.connect("clicked",  self.pass_cb)
        self.buttons_box.pack_start(self.pass_button,  True,  True, 10)
        
        #Undo button
        self.undo_button = gtk.Button(_('Undo'))
        self.undo_button.connect("clicked",  self.undo_cb)
        self.buttons_box.pack_start(self.undo_button, True, True, 10)
        
        self.buttons_alignment.add(self.buttons_box)
        self.main_view.pack_start(self.buttons_alignment, False, padding=10)
        
        self.infopanel = infopanel.InfoPanel()
        self.main_view.pack_start(self.infopanel, False)

        self.set_canvas(self.main_view)
        self.show_all()

    def insert_cb(self, widget, x, y, announce=True, ai_play=False):
        ''' The insert function. It makes the play and manages turn changing
            stone drawing, etc. 
            
        Parameters x and y are the coordinates of the play ((0,0) is top left), 
        widget points to the widget that emitted the signal connected to this
        function, announce is True when we need to announce this play to 
        other people collaborating, and ai_play is True when this is called 
        by the AI, so we know not to ask for an AI play again '''
        
        # Check if it's our turn only if it's a local play (announce is True)
        # Calls by other players will always be out of turn for us. 
        if announce and self.get_currentcolor() != self.get_playercolor():
            logger.debug('Play at %s x %s was out-of-turn!', x, y)
            self.infopanel.show(_('It\'s not your turn!'))
            return False
        # Make the play only if it wasn't a pass move. 
        if x != -1:
            self.pass_count = 0
            error = self.game.illegal(x, y, self.get_currentcolor())
            if error:
                self.infopanel.show(error)
                return False
            # Make the play
            captures = self.game.play((x, y), self.get_currentcolor())
            if self.ai_activated and not ai_play: 
                self.notify_ai(x, y, self.get_currentcolor())
            self.gameToolbar.grey_out_size_change()
            if captures: self.redraw_captures(captures)
            self.show_score()
            self.board.draw_stone(x, y, self.get_currentcolor(), widget)
        # Player passed
        else:
            self.pass_count += 1
        # Announce the local play
        if self.get_shared() and announce:
            self.collaboration.Play(x, y)
        self.change_turn()
        if x == -1:
            self.infopanel.show(_('Opponent passed'))
        # If this is the second consecutive pass, the game ends
        if self.pass_count == 2:
            self.game_end()
            return
        # If we are playing a local game with AI turned off, change the color
        if not self.get_shared() and not self.ai_activated:
            self.change_player_color()
        # Else, if the AI is on, and this wasn't played by it, request a play by it. 
        elif self.ai_activated: 
            self.change_player_color()
            if not ai_play:
                self.play_ai()

    def undo_cb(self, widget=None, data=None):
        if self.game.undo():
            self.board.queue_draw()
            # If playing against AI undo twice
            if self.ai_activated: 
                self.ai.undo()
                self.game.undo()
                self.ai.undo()
            else:
                self.change_turn()
            if not self.get_shared() and not self.ai_activated:
                self.change_player_color()
            self.show_score()
        
    def pass_cb(self, widget=None, data=None):
        if self.get_shared(): 
            if self.get_currentcolor() == self.get_playercolor():
                self.pass_count += 1
                self.collaboration.Play(-1, -1)
            else:
                self.infopanel.show(_('It\'s not your turn!'))
                return
        else:
            self.pass_count += 1
            self.change_player_color()
        self.change_turn()
        if self.pass_count == 2:
            self.game_end()
        if self.ai_activated:
            self.ai.pass_move(self.get_currentcolor())
            self.play_ai()

    def write_file(self, file_path):
        logger.debug('Writing file: %s', file_path)
        # Strip the undostack
        undostack = self.game.undostack[:]
        strippedstack = []
        for pos, color, captures in undostack:
            strippedstack.append(pos)
        f = open(file_path, 'w')
        try:
            cPickle.dump(strippedstack, f, cPickle.HIGHEST_PROTOCOL)
        finally:
            f.close()
        self.metadata['our-color'] = self.get_playercolor()
        self.metadata['shared'] = str(self.get_shared())
        self.metadata['size'] = str(self.size)
        self.metadata['ai'] = str(self.ai_activated)
        
    def read_file(self, file_path):
        logger.debug('Reading file: %s', file_path)
        f = open(file_path, 'r')
        try:
            newstack = cPickle.load(f)
        finally:
            f.close()
        if self.get_shared():
            logger.debug('The game we are loading is shared!')
            self.PlayerColor = self.metadata.get('our-color', 'B')
        if self.size != self.metadata.get('size', DEFAULT_SIZE):
            self.board_size_change(None, int(self.metadata.get('size', DEFAULT_SIZE)))
        self.bootstrap(newstack)
        if self.metadata.get('ai', None) == 'True':
            self.gameToolbar._size_combo.set_sensitive(False)
            self.gameToolbar._ai_button.set_active(True) # This triggers the 'toggled' signal too
        
    def board_motion_cb(self, widget, event):
        x, y = self.board.get_mouse_event_xy(event)
        if x == self.lastX and y == self.lastY:
            return
        if not self.game.is_occupied(x, y) and self.game.legal((x, y), self.get_playercolor()):
            self.board.draw_ghost_stone(x, y, self.get_playercolor())
            self.lastX = x
            self.lastY = y
    
    def invert_color(self, color):
        if color == 'B': return 'W'
        return 'B'
    
    def get_currentcolor(self):
        return self.CurrentColor
    
    def change_turn(self):
        # It's the other guy's turn now
        if self.CurrentColor == 'B':
            self.infopanel.show(_('White\'s turn'))
        else:
            self.infopanel.show(_('Black\'s turn'))
        self.CurrentColor = self.invert_color(self.get_currentcolor())

    def get_playercolor(self):
        return self.PlayerColor

    def change_player_color(self):
        self.PlayerColor = self.invert_color(self.get_playercolor())
        
    def set_player_color(self, color):
        self.PlayerColor = color

    def redraw_captures(self, captures):
        for x in captures:
            self.board.redraw_area(x[0], x[1])
            
    def bootstrap(self, plays):
        ''' Take our game to the state it would have if @plays were manually played'''
        logger.debug('Bootstraping...')
        self.board.do_expose_event() # HACK: Looks like read_file is called before the board is exposed
        for pos in plays:
            logger.debug('Playing at %s with color %s', pos, self.get_currentcolor())
            captures = self.game.play((pos[0], pos[1]), self.get_currentcolor())
            if captures: self.redraw_captures(captures)
            self.change_turn()
            self.change_player_color()
        logger.debug('Color after bootstraping is %s', self.get_currentcolor())
        self.show_score()
        self.board.do_expose_event()
        
    def restart_game(self, widget=None):
        logger.debug('Received restart signal!')
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.game.clear()
        self.board.territories = None
        self.board.status = self.game.status
        self.board.do_expose_event()
        self.show_score()
        self.board.set_sensitive(True)
        self.buttons_box.set_sensitive(True)
        self.lastX = -1
        self.lastY = -1
        if self.ai_activated:
            self.ai.clear()
        
    def game_end(self):
        self.board.set_sensitive(False)
        self.buttons_box.set_sensitive(False)
        territories = self.game.get_territories()
        self.board.territories = territories
        
        final_score = {'B':(len(territories['B']) - self.game.get_score()['W']),
                                'W':(len(territories['W']) - self.game.get_score()['B'] + self.komi)}

        if final_score['B'] > final_score['W']:
            winner_string = _('Black wins!')
        elif final_score['W'] > final_score['B']:
            winner_string = _('White wins!')
        else:
            winner_string = _('There was a tie!')
        self.infopanel.show(_('Game ended! %s' % winner_string))
        self.infopanel.show_score(_('Final score: White %(W)g - Black %(B)g' % final_score))        
        
    def board_size_change(self, widget, size):
        self.lastY = -1
        self.lastX = -1
        if size == self.size:
            return
        self.size = size
        del self.game
        self.game = GoGame(size)
        self.board_aspect.remove(self.board)
        del self.board
        self.board = boardwidget.GoBoardWidget(self.game.get_status(), int(size))
        self.board_aspect.add(self.board)
        self.board.connect('motion-notify-event', self.board_motion_cb)
        self.board.connect('insert-requested', self.insert_cb)
        self.board.show()
        if self.ai_activated:
            del self.ai
            self.ai = gnugo(boardsize=self.size)
        
    def ai_activated_cb(self, widget=None):
        try:
            self.ai = gnugo(boardsize=self.size)
        except Exception, e:
            self._alert(_('AI'), _('GnuGo loading failed!: %s' % e))
            self.gameToolbar.set_ai_button_state(False)
        else:
Beispiel #7
0
    def __init__(self, handle):
        # Initialize the parent
        Activity.__init__(self, handle)
        logger.debug('Initiating PlayGo')

        self.size = DEFAULT_SIZE
        self.komi = DEFAULT_KOMI

        # Set the activity toolbox
        toolbox = ActivityToolbox(self)
        self.set_toolbox(toolbox)
        self.gameToolbar = GameToolbar(self)
        toolbox.add_toolbar(_('Game'), self.gameToolbar)
        self.gameToolbar.connect('game-restart', self.restart_game)
        self.gameToolbar.connect('game-board-size', self.board_size_change)
        self.gameToolbar.connect('ai-activated', self.ai_activated_cb)
        self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb)
        self.gameToolbar.show()

        # Initialize the game
        self.game = GoGame(self.size)
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.ai_activated = False
        self.set_up_ui()

        if not handle.object_id:
            self.infopanel.show(_('Welcome to PlayGo!'))
        else:
            self.show_score()
        self.lastX = -1
        self.lastY = -1

        # Set keypad actions
        self._key_actions = {
            'KP_Up': 'move_up',
            'KP_Right': 'move_right',
            'KP_Down': 'move_down',
            'KP_Left': 'move_left',
            'KP_Home': 'place_stone',
            'KP_Next': 'undo',
            'KP_End': 'pass'
        }

        self._key_grabber = KeyGrabber()
        self._key_grabber.connect('key-pressed', self._key_pressed_cb)

        # New KeyGrabber API change (ticket #7999)
        try:
            self._key_grabber.grab_keys(self._key_actions.keys())
        except:
            for key in self._key_actions.keys():
                self._key_grabber.grab(key)

        #Set up collaboration
        self.collaboration = CollaborationWrapper(self, self.buddy_joined,
                                                  self.buddy_left, self.Play,
                                                  self.game.undostack,
                                                  self.bootstrap)

        self.connect('shared', self.collaboration._shared_cb)
        if self._shared_activity:
            # We are joining the activity
            self.connect('joined', self.collaboration._joined_cb)
            if self.get_shared():
                # We've already joined
                self.collaboration._joined_cb()
Beispiel #8
0
class PlayGo(Activity):
    def __init__(self, handle):
        # Initialize the parent
        Activity.__init__(self, handle)
        logger.debug('Initiating PlayGo')

        self.size = DEFAULT_SIZE
        self.komi = DEFAULT_KOMI

        # Set the activity toolbox
        toolbox = ActivityToolbox(self)
        self.set_toolbox(toolbox)
        self.gameToolbar = GameToolbar(self)
        toolbox.add_toolbar(_('Game'), self.gameToolbar)
        self.gameToolbar.connect('game-restart', self.restart_game)
        self.gameToolbar.connect('game-board-size', self.board_size_change)
        self.gameToolbar.connect('ai-activated', self.ai_activated_cb)
        self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb)
        self.gameToolbar.show()

        # Initialize the game
        self.game = GoGame(self.size)
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.ai_activated = False
        self.set_up_ui()

        if not handle.object_id:
            self.infopanel.show(_('Welcome to PlayGo!'))
        else:
            self.show_score()
        self.lastX = -1
        self.lastY = -1

        # Set keypad actions
        self._key_actions = {
            'KP_Up': 'move_up',
            'KP_Right': 'move_right',
            'KP_Down': 'move_down',
            'KP_Left': 'move_left',
            'KP_Home': 'place_stone',
            'KP_Next': 'undo',
            'KP_End': 'pass'
        }

        self._key_grabber = KeyGrabber()
        self._key_grabber.connect('key-pressed', self._key_pressed_cb)

        # New KeyGrabber API change (ticket #7999)
        try:
            self._key_grabber.grab_keys(self._key_actions.keys())
        except:
            for key in self._key_actions.keys():
                self._key_grabber.grab(key)

        #Set up collaboration
        self.collaboration = CollaborationWrapper(self, self.buddy_joined,
                                                  self.buddy_left, self.Play,
                                                  self.game.undostack,
                                                  self.bootstrap)

        self.connect('shared', self.collaboration._shared_cb)
        if self._shared_activity:
            # We are joining the activity
            self.connect('joined', self.collaboration._joined_cb)
            if self.get_shared():
                # We've already joined
                self.collaboration._joined_cb()

    def set_up_ui(self):
        self.board = boardwidget.GoBoardWidget(self.game.get_status(),
                                               self.size)
        self.board.connect('motion-notify-event', self.board_motion_cb)
        self.board.connect('insert-requested', self.insert_cb)

        self.main_view = gtk.VBox()

        self.board_aspect = gtk.AspectFrame(None, .5, .5, 1, False)
        self.board_aspect.add(self.board)
        self.main_view.pack_start(self.board_aspect)

        self.buttons_box = gtk.HBox()
        self.buttons_alignment = gtk.Alignment(0.5, 1, 0.5, 1)
        #Pass button
        self.pass_button = gtk.Button(_('Pass'))
        self.pass_button.connect("clicked", self.pass_cb)
        self.buttons_box.pack_start(self.pass_button, True, True, 10)

        #Undo button
        self.undo_button = gtk.Button(_('Undo'))
        self.undo_button.connect("clicked", self.undo_cb)
        self.buttons_box.pack_start(self.undo_button, True, True, 10)

        self.buttons_alignment.add(self.buttons_box)
        self.main_view.pack_start(self.buttons_alignment, False, padding=10)

        self.infopanel = infopanel.InfoPanel()
        self.main_view.pack_start(self.infopanel, False)

        self.set_canvas(self.main_view)
        self.show_all()

    def insert_cb(self, widget, x, y, announce=True, ai_play=False):
        ''' The insert function. It makes the play and manages turn changing
            stone drawing, etc. 
            
        Parameters x and y are the coordinates of the play ((0,0) is top left), 
        widget points to the widget that emitted the signal connected to this
        function, announce is True when we need to announce this play to 
        other people collaborating, and ai_play is True when this is called 
        by the AI, so we know not to ask for an AI play again '''

        # Check if it's our turn only if it's a local play (announce is True)
        # Calls by other players will always be out of turn for us.
        if announce and self.get_currentcolor() != self.get_playercolor():
            logger.debug('Play at %s x %s was out-of-turn!', x, y)
            self.infopanel.show(_('It\'s not your turn!'))
            return False
        # Make the play only if it wasn't a pass move.
        if x != -1:
            self.pass_count = 0
            error = self.game.illegal(x, y, self.get_currentcolor())
            if error:
                self.infopanel.show(error)
                return False
            # Make the play
            captures = self.game.play((x, y), self.get_currentcolor())
            if self.ai_activated and not ai_play:
                self.notify_ai(x, y, self.get_currentcolor())
            self.gameToolbar.grey_out_size_change()
            if captures: self.redraw_captures(captures)
            self.show_score()
            self.board.draw_stone(x, y, self.get_currentcolor(), widget)
        # Player passed
        else:
            self.pass_count += 1
        # Announce the local play
        if self.get_shared() and announce:
            self.collaboration.Play(x, y)
        self.change_turn()
        if x == -1:
            self.infopanel.show(_('Opponent passed'))
        # If this is the second consecutive pass, the game ends
        if self.pass_count == 2:
            self.game_end()
            return
        # If we are playing a local game with AI turned off, change the color
        if not self.get_shared() and not self.ai_activated:
            self.change_player_color()
        # Else, if the AI is on, and this wasn't played by it, request a play by it.
        elif self.ai_activated:
            self.change_player_color()
            if not ai_play:
                self.play_ai()

    def undo_cb(self, widget=None, data=None):
        if self.game.undo():
            self.board.queue_draw()
            # If playing against AI undo twice
            if self.ai_activated:
                self.ai.undo()
                self.game.undo()
                self.ai.undo()
            else:
                self.change_turn()
            if not self.get_shared() and not self.ai_activated:
                self.change_player_color()
            self.show_score()

    def pass_cb(self, widget=None, data=None):
        if self.get_shared():
            if self.get_currentcolor() == self.get_playercolor():
                self.pass_count += 1
                self.collaboration.Play(-1, -1)
            else:
                self.infopanel.show(_('It\'s not your turn!'))
                return
        else:
            self.pass_count += 1
            self.change_player_color()
        self.change_turn()
        if self.pass_count == 2:
            self.game_end()
        if self.ai_activated:
            self.ai.pass_move(self.get_currentcolor())
            self.play_ai()

    def write_file(self, file_path):
        logger.debug('Writing file: %s', file_path)
        # Strip the undostack
        undostack = self.game.undostack[:]
        strippedstack = []
        for pos, color, captures in undostack:
            strippedstack.append(pos)
        f = open(file_path, 'w')
        try:
            cPickle.dump(strippedstack, f, cPickle.HIGHEST_PROTOCOL)
        finally:
            f.close()
        self.metadata['our-color'] = self.get_playercolor()
        self.metadata['shared'] = str(self.get_shared())
        self.metadata['size'] = str(self.size)
        self.metadata['ai'] = str(self.ai_activated)

    def read_file(self, file_path):
        logger.debug('Reading file: %s', file_path)
        f = open(file_path, 'r')
        try:
            newstack = cPickle.load(f)
        finally:
            f.close()
        if self.get_shared():
            logger.debug('The game we are loading is shared!')
            self.PlayerColor = self.metadata.get('our-color', 'B')
        if self.size != self.metadata.get('size', DEFAULT_SIZE):
            self.board_size_change(
                None, int(self.metadata.get('size', DEFAULT_SIZE)))
        self.bootstrap(newstack)
        if self.metadata.get('ai', None) == 'True':
            self.gameToolbar._size_combo.set_sensitive(False)
            self.gameToolbar._ai_button.set_active(
                True)  # This triggers the 'toggled' signal too

    def board_motion_cb(self, widget, event):
        x, y = self.board.get_mouse_event_xy(event)
        if x == self.lastX and y == self.lastY:
            return
        if not self.game.is_occupied(x, y) and self.game.legal(
            (x, y), self.get_playercolor()):
            self.board.draw_ghost_stone(x, y, self.get_playercolor())
            self.lastX = x
            self.lastY = y

    def invert_color(self, color):
        if color == 'B': return 'W'
        return 'B'

    def get_currentcolor(self):
        return self.CurrentColor

    def change_turn(self):
        # It's the other guy's turn now
        if self.CurrentColor == 'B':
            self.infopanel.show(_('White\'s turn'))
        else:
            self.infopanel.show(_('Black\'s turn'))
        self.CurrentColor = self.invert_color(self.get_currentcolor())

    def get_playercolor(self):
        return self.PlayerColor

    def change_player_color(self):
        self.PlayerColor = self.invert_color(self.get_playercolor())

    def set_player_color(self, color):
        self.PlayerColor = color

    def redraw_captures(self, captures):
        for x in captures:
            self.board.redraw_area(x[0], x[1])

    def bootstrap(self, plays):
        ''' Take our game to the state it would have if @plays were manually played'''
        logger.debug('Bootstraping...')
        self.board.do_expose_event(
        )  # HACK: Looks like read_file is called before the board is exposed
        for pos in plays:
            logger.debug('Playing at %s with color %s', pos,
                         self.get_currentcolor())
            captures = self.game.play((pos[0], pos[1]),
                                      self.get_currentcolor())
            if captures: self.redraw_captures(captures)
            self.change_turn()
            self.change_player_color()
        logger.debug('Color after bootstraping is %s', self.get_currentcolor())
        self.show_score()
        self.board.do_expose_event()

    def restart_game(self, widget=None):
        logger.debug('Received restart signal!')
        self.CurrentColor = 'B'
        self.PlayerColor = 'B'
        self.pass_count = 0
        self.game.clear()
        self.board.territories = None
        self.board.status = self.game.status
        self.board.do_expose_event()
        self.show_score()
        self.board.set_sensitive(True)
        self.buttons_box.set_sensitive(True)
        self.lastX = -1
        self.lastY = -1
        if self.ai_activated:
            self.ai.clear()

    def game_end(self):
        self.board.set_sensitive(False)
        self.buttons_box.set_sensitive(False)
        territories = self.game.get_territories()
        self.board.territories = territories

        final_score = {
            'B': (len(territories['B']) - self.game.get_score()['W']),
            'W':
            (len(territories['W']) - self.game.get_score()['B'] + self.komi)
        }

        if final_score['B'] > final_score['W']:
            winner_string = _('Black wins!')
        elif final_score['W'] > final_score['B']:
            winner_string = _('White wins!')
        else:
            winner_string = _('There was a tie!')
        self.infopanel.show(_('Game ended! %s' % winner_string))
        self.infopanel.show_score(
            _('Final score: White %(W)g - Black %(B)g' % final_score))

    def board_size_change(self, widget, size):
        self.lastY = -1
        self.lastX = -1
        if size == self.size:
            return
        self.size = size
        del self.game
        self.game = GoGame(size)
        self.board_aspect.remove(self.board)
        del self.board
        self.board = boardwidget.GoBoardWidget(self.game.get_status(),
                                               int(size))
        self.board_aspect.add(self.board)
        self.board.connect('motion-notify-event', self.board_motion_cb)
        self.board.connect('insert-requested', self.insert_cb)
        self.board.show()
        if self.ai_activated:
            del self.ai
            self.ai = gnugo(boardsize=self.size)

    def ai_activated_cb(self, widget=None):
        try:
            self.ai = gnugo(boardsize=self.size)
        except Exception, e:
            self._alert(_('AI'), _('GnuGo loading failed!: %s' % e))
            self.gameToolbar.set_ai_button_state(False)
        else: