Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--activity.py67
-rw-r--r--collaboration.py2
-rw-r--r--gametoolbar.py29
-rw-r--r--gtp.py18
5 files changed, 108 insertions, 9 deletions
diff --git a/MANIFEST b/MANIFEST
index 68f8d82..f08db2a 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -4,6 +4,7 @@ collaboration.py
boardwidget.py
gogame.py
infopanel.py
+gtp.py
activity/activity-go.svg
activity/activity.info
images/b.gif
diff --git a/activity.py b/activity.py
index eaf8339..c0a49a2 100644
--- a/activity.py
+++ b/activity.py
@@ -31,6 +31,7 @@ from gogame import GoGame
import boardwidget
import infopanel
from collaboration import CollaborationWrapper
+from gtp import gnugo
logger = logging.getLogger('PlayGo')
@@ -52,12 +53,15 @@ class PlayGo(Activity):
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.ai_activated = False
self.set_up_ui()
if not handle.object_id:
@@ -115,7 +119,18 @@ class PlayGo(Activity):
self.set_canvas(self.main_view)
self.show_all()
- def insert_cb(self, widget, x, y, announce=True):
+ 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!')
@@ -128,6 +143,8 @@ class PlayGo(Activity):
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()
@@ -136,14 +153,28 @@ class PlayGo(Activity):
if self.get_shared() and announce:
self.collaboration.Play(x, y)
self.change_turn()
- if not self.get_shared(): self.change_player_color()
+ # 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, 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()
- self.change_turn()
- if not self.get_shared(): self.change_player_color()
def pass_cb(self, widget, data=None):
if self.get_shared():
@@ -243,6 +274,8 @@ class PlayGo(Activity):
self.board.status = self.game.status
self.board.do_expose_event()
self.show_score()
+ if self.ai_activated:
+ self.ai.clear()
def board_size_change(self, widget, size):
if size == self.size:
@@ -257,6 +290,32 @@ class PlayGo(Activity):
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):
+ self.restart_game()
+ self.ai_activated = True
+ self.ai = gnugo(boardsize=self.size)
+ self._alert(_('AI'), _('PlayGo AI Activated'))
+
+ def ai_deactivated_cb(self, widget):
+ self.ai_activated = False
+ del self.ai
+ self._alert(_('AI'), _('PlayGo AI Deactivated'))
+
+ def notify_ai(self, x, y, color):
+ if color == self.get_playercolor():
+ 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)
+ #logger.debug('Dumping board: %s', self.ai.dump_board())
def show_score(self):
self.infopanel.show_score(_("Score is: Whites %(W)d - Blacks %(B)d" % self.game.get_score()))
diff --git a/collaboration.py b/collaboration.py
index 38f926e..789eb42 100644
--- a/collaboration.py
+++ b/collaboration.py
@@ -49,6 +49,7 @@ class CollaborationWrapper(ExportedGObject):
def _shared_cb(self, activity):
self.activity.gameToolbar.grey_out_size_change()
self.activity.gameToolbar.grey_out_restart()
+ self.activity.gameToolbar.grey_out_ai()
self._sharing_setup()
self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
SERVICE, {})
@@ -58,6 +59,7 @@ class CollaborationWrapper(ExportedGObject):
def _joined_cb(self, activity):
self.activity.gameToolbar.grey_out_size_change()
self.activity.gameToolbar.grey_out_restart()
+ self.activity.gameToolbar.grey_out_ai()
self._sharing_setup()
self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
reply_handler=self._list_tubes_reply_cb,
diff --git a/gametoolbar.py b/gametoolbar.py
index 834b1e0..d512593 100644
--- a/gametoolbar.py
+++ b/gametoolbar.py
@@ -27,6 +27,8 @@ from sugar.graphics.objectchooser import ObjectChooser
import logging
from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT, TYPE_NONE, TYPE_INT
+from gtp import search_for_gnugo
+
logger = logging.getLogger('PlayGo')
class GameToolbar(gtk.Toolbar):
@@ -34,6 +36,8 @@ class GameToolbar(gtk.Toolbar):
__gsignals__ = {
'game-restart': (SIGNAL_RUN_FIRST, TYPE_NONE, []),
+ 'ai-activated': (SIGNAL_RUN_FIRST, TYPE_NONE, []),
+ 'ai-deactivated': (SIGNAL_RUN_FIRST, TYPE_NONE, []),
'game-board-size': (SIGNAL_RUN_FIRST, TYPE_NONE, [TYPE_INT]),
}
@@ -67,6 +71,22 @@ class GameToolbar(gtk.Toolbar):
self._add_widget(self._size_combo)
self._size_combo.combo.set_active(0)
+ # Separator
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(True)
+ self.insert(separator, -1)
+
+ # Artificial Intelligence Button
+ self._ai_button = gtk.ToggleToolButton()
+ if search_for_gnugo():
+ self._ai_button.connect('toggled', self._ai_toggled_cb)
+ self._ai_button.set_label(_('Play against PlayGo!'))
+ else:
+ self._ai_button.set_label(_('You need to install gnugo to play against PlayGo'))
+ self._ai_button.set_sensitive(False)
+ self.insert(self._ai_button, -1)
+ self._ai_button.show()
+
def _add_widget(self, widget, expand=False):
tool_item = gtk.ToolItem()
tool_item.set_expand(expand)
@@ -95,3 +115,12 @@ class GameToolbar(gtk.Toolbar):
size_index = self._sizes.index(size+' X '+size)
self._size_combo.combo.set_active(int(size_index))
self._size_combo.combo.handler_unblock(self.size_handle_id)
+
+ def _ai_toggled_cb(self, widget):
+ if widget.get_active():
+ self.emit('ai-activated')
+ else:
+ self.emit('ai-deactivated')
+
+ def grey_out_ai(self):
+ self._ai_button.set_sensitive(False)
diff --git a/gtp.py b/gtp.py
index 4f028e1..7484658 100644
--- a/gtp.py
+++ b/gtp.py
@@ -49,13 +49,15 @@ class gnugo:
self.stdout = self.gnugo.stdout
def __del__(self):
+ logger.debug('Closing gnugo')
self.stdin.write('quit \n')
+ self.stdin.flush()
def _xy_to_coords(self, x, y):
- return dict(zip(range(0, 25), 'ABCDEFGHJKLMNOPQRSTUVWXYZ'))[x] + str(self.size - y)
+ return dict(zip(range(25), 'ABCDEFGHJKLMNOPQRSTUVWXYZ'))[x] + str(self.size - y)
def _coords_to_xy(self, coords):
- return int(dict(zip('ABCDEFGHJKLMNOPQRSTUVWXYZ', range(0, 25)))[coords[0]]), self.size - int(coords[1:])
+ return int(dict(zip('ABCDEFGHJKLMNOPQRSTUVWXYZ', range(25)))[coords[0]]), self.size - int(coords[1:])
def short_to_long_colors(self, short_color):
if short_color == 'B':
@@ -88,15 +90,21 @@ class gnugo:
return self._coords_to_xy(output[2:])
def undo(self):
- self.stdin.write('undo \n')
+ self.stdin.write('undo\n')
+ self.stdin.flush()
+ self.stdout.readline()
+ self.stdout.readline()
+
+ def clear(self):
+ self.stdin.write('clear_board\n')
self.stdin.flush()
self.stdout.readline()
self.stdout.readline()
def dump_board(self):
- self.stdin.write('showboard \n')
+ self.stdin.write('showboard\n')
self.stdin.flush()
output = ''
for i in range(0, self.size+4):
output = output + self.stdout.readline()
- logger.debug('%s', output)
+ return output