diff options
author | Gerard J. Cerchio <gjpc@circlesoft.com> | 2007-11-28 00:54:37 (GMT) |
---|---|---|
committer | Gerard J. Cerchio <gjpc@circlesoft.com> | 2007-11-28 00:54:37 (GMT) |
commit | 958f0fcb437be76c2b420e84b138c944ae47847a (patch) | |
tree | 16fc6c92f2c139974bb0c83b59ae3044e0087d46 |
Initial import
-rw-r--r-- | MANIFEST | 25 | ||||
-rw-r--r-- | NEWS | 77 | ||||
-rw-r--r-- | PlayGo-1.xo | bin | 0 -> 218530 bytes | |||
-rwxr-xr-x | activity.py | 199 | ||||
-rw-r--r-- | activity.pyc | bin | 0 -> 7415 bytes | |||
-rw-r--r-- | activity/activity-go.svg | 118 | ||||
-rw-r--r-- | activity/activity-helloworld.svg | 8 | ||||
-rw-r--r-- | activity/activity.info | 7 | ||||
-rwxr-xr-x | boardwidget.py | 231 | ||||
-rw-r--r-- | boardwidget.pyc | bin | 0 -> 7399 bytes | |||
-rwxr-xr-x | buddiespanel.py | 132 | ||||
-rw-r--r-- | buddiespanel.pyc | bin | 0 -> 4529 bytes | |||
-rwxr-xr-x | game.py | 305 | ||||
-rw-r--r-- | game.pyc | bin | 0 -> 10728 bytes | |||
-rw-r--r-- | images/BsTurn.gif | bin | 0 -> 691 bytes | |||
-rw-r--r-- | images/README | 7 | ||||
-rw-r--r-- | images/WsTurn.gif | bin | 0 -> 728 bytes | |||
-rw-r--r-- | images/b.gif | bin | 0 -> 107 bytes | |||
-rw-r--r-- | images/black.gif | bin | 0 -> 1343 bytes | |||
-rw-r--r-- | images/board.gif | bin | 0 -> 197707 bytes | |||
-rw-r--r-- | images/bw.gif | bin | 0 -> 141 bytes | |||
-rw-r--r-- | images/w.gif | bin | 0 -> 105 bytes | |||
-rw-r--r-- | images/white.gif | bin | 0 -> 1250 bytes | |||
-rwxr-xr-x | infopanel.py | 20 | ||||
-rw-r--r-- | infopanel.pyc | bin | 0 -> 1270 bytes | |||
-rw-r--r-- | locale/ar/LC_MESSAGES/org.laptop.Connect.mo | bin | 0 -> 1084 bytes | |||
-rw-r--r-- | locale/ar/LC_MESSAGES/org.laptop.Playg.mo | bin | 0 -> 1084 bytes | |||
-rw-r--r-- | locale/ar/activity.linfo | 2 | ||||
-rw-r--r-- | locale/de/LC_MESSAGES/org.laptop.Connect.mo | bin | 0 -> 845 bytes | |||
-rw-r--r-- | locale/de/LC_MESSAGES/org.laptop.Playg.mo | bin | 0 -> 845 bytes | |||
-rw-r--r-- | locale/de/activity.linfo | 2 | ||||
-rw-r--r-- | locale/el/LC_MESSAGES/org.laptop.Connect.mo | bin | 0 -> 967 bytes | |||
-rw-r--r-- | locale/el/LC_MESSAGES/org.laptop.Playg.mo | bin | 0 -> 967 bytes | |||
-rw-r--r-- | locale/el/activity.linfo | 2 | ||||
-rw-r--r-- | locale/es/LC_MESSAGES/org.laptop.Connect.mo | bin | 0 -> 967 bytes | |||
-rw-r--r-- | locale/es/LC_MESSAGES/org.laptop.Playg.mo | bin | 0 -> 967 bytes | |||
-rw-r--r-- | locale/es/activity.linfo | 2 | ||||
-rw-r--r-- | po/Connect.pot | 49 | ||||
-rw-r--r-- | po/ar.po | 63 | ||||
-rw-r--r-- | po/de.po | 58 | ||||
-rw-r--r-- | po/el.po | 58 | ||||
-rw-r--r-- | po/es.po | 58 | ||||
-rwxr-xr-x | setup.py | 22 | ||||
-rwxr-xr-x | widgettest.py | 62 |
44 files changed, 1507 insertions, 0 deletions
diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..8df329a --- /dev/null +++ b/MANIFEST @@ -0,0 +1,25 @@ +activity.py +boardwidget.py +buddiespanel.py +game.py +gridwidget.py +infopanel.py +activity/activity-go.svg +activity/activity.info +images/b.gif +images/black.gif +images/board.gif +images/BsTurn.gif +images/bw.gif +images/w.gif +images/white.gif +images/WsTurn.gif +locale/ar +locale/de +locale/el +locale/es +po/ar.po +po/Connect.pot +po/de.po +po/el.po +po/es.po @@ -0,0 +1,77 @@ +20 +* morph Connect into Go most of the boardwidget is complete, +* you can click play on a single machine (sortof) + +19 + +* #4663: fix and use _get_buddy again to convert handles into buddies + (morgs) + +18 + +* Fixes in usage of sugar.presence API (morgs) + +17 + +* Remove Tubes boilerplate and rely on #4503 having been fixed in + sugar.presence (smcv) + -- this depends on sugar snapshot 8c89bfaed7 + +16 + +* Remove self.set_title() (morgs) +* #3492: Don't quit on escape (cassidy) + +15 + +* #3557: Updated spanish translation (morgs) + +14 + +* Updated spanish translation (morgs) +* Add spanish translation (xavi) + +13 + +* #2349 Suggests sharing or inviting someone to play (morgs) +* #3194 Detect win with more than 4 in a row (morgs) + +12 + +* New activity icon, Fix for #2829 (erikos) + +11 + +* Port to new tubes API (cassidy) + +10 + +* Fix sugar.graphics change to CanvasIcon (morgs) +* Add greek translation. (simosx) +* Add arabic translation. (khaled) + +9 + +* Fix buddy icon (morgs) +* Use tubeconn from sugar.presence (morgs) +* Use sugar.graphics.style instead of sugar.graphics.color (danw) +* #2579 German translation (morgs) + +8 + +* Add gettext for i18n (morgs) +* #1625, #2420: Fix activity icon (danw, cassidy) + +7 + +* 1960, #1624: Show the activity toolbox and sidebar when PS not connected + (morgs) + +6 + +* Adapt to sugar API change (marco) + +5 + +* Fix buddy handles for Salut (Link Local) channels (smcv) +* UI improvement to show whose turn it is, below grid (morgs) diff --git a/PlayGo-1.xo b/PlayGo-1.xo Binary files differnew file mode 100644 index 0000000..d973f99 --- /dev/null +++ b/PlayGo-1.xo diff --git a/activity.py b/activity.py new file mode 100755 index 0000000..756a712 --- /dev/null +++ b/activity.py @@ -0,0 +1,199 @@ +import logging +from gettext import gettext as _ + +import dbus +import gtk +import hippo +import telepathy +import telepathy.client + +from sugar.activity.activity import Activity, ActivityToolbox +from sugar.presence import presenceservice +import sugar.logger + +import boardwidget +import game + +from sugar.presence.tubeconn import TubeConnection +from buddiespanel import BuddiesPanel +from infopanel import InfoPanel + + +logger = logging.getLogger('connect-activity') + + +class PlayGo(Activity): + def __init__(self, handle): + Activity.__init__(self, handle) + + logger.debug('Starting Connect activity...') + + board = game.GoBoard( 19 ) + self.grid = boardwidget.BoardWidget( board ) + + self.buddies_panel = BuddiesPanel() + + self.info_panel = InfoPanel() + + vbox = hippo.CanvasBox(spacing=4, + orientation=hippo.ORIENTATION_VERTICAL) + + hbox = hippo.CanvasBox(spacing=4, + orientation=hippo.ORIENTATION_HORIZONTAL) + + hbox.append(self.buddies_panel) + hbox.append(hippo.CanvasWidget(widget=self.grid), hippo.PACK_EXPAND) + + vbox.append(hbox, hippo.PACK_EXPAND) + vbox.append(self.info_panel, hippo.PACK_END) + + canvas = hippo.Canvas() + canvas.set_root(vbox) + self.set_canvas(canvas) + self.show_all() + + toolbox = ActivityToolbox(self) + self.set_toolbox(toolbox) + toolbox.show() + + self.pservice = presenceservice.get_instance() + owner = self.pservice.get_owner() + self.owner = owner + + # This displays the buddies_panel even if we fail to connect: + self.buddies_panel.add_watcher(owner) + self.info_panel.show(_('To play, share or invite someone.')) + + self.initiating = None + + self.game = None + + self.connect('shared', self._shared_cb) + + if self._shared_activity: + # we are joining the activity + self.buddies_panel.add_watcher(owner) + self.connect('joined', self._joined_cb) + self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) + self._shared_activity.connect('buddy-left', self._buddy_left_cb) + if self.get_shared(): + # oh, OK, we've already joined + self._joined_cb() + else: + # we are creating the activity + self.buddies_panel.remove_watcher(owner) + self.buddies_panel.add_player(owner) + #self.buddies_panel.set_is_playing(owner) + #self.buddies_panel.set_count(owner, 69) + + self.connect('key-press-event', self.key_press_cb) + + def _get_buddy(self, cs_handle): + """Get a Buddy from a channel specific handle.""" + # FIXME: After Update.1, design a better API for sugar.presence + # to track handles of buddies, and use that instead + logger.debug('Trying to find owner of handle %u...', cs_handle) + group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] + my_csh = group.GetSelfHandle() + logger.debug('My handle in that group is %u', my_csh) + if my_csh == cs_handle: + handle = self.conn.GetSelfHandle() + logger.debug('CS handle %u belongs to me, %u', cs_handle, handle) + elif group.GetGroupFlags() & telepathy.CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES: + handle = group.GetHandleOwners([cs_handle])[0] + logger.debug('CS handle %u belongs to %u', cs_handle, handle) + else: + handle = cs_handle + logger.debug('non-CS handle %u belongs to itself', handle) + + # XXX: deal with failure to get the handle owner + assert handle != 0 + + return self.pservice.get_buddy_by_telepathy_handle( + self.conn.service_name, self.conn.object_path, handle) + + def key_press_cb(self, widget, event): + logger.debug('Keypress: %r, %r', widget, event) + + if self.game is not None: + self.game.key_press_event(widget, event) + + def _shared_cb(self, activity): + logger.debug('My Connect activity was shared') + self.initiating = True + self._setup() + + for buddy in self._shared_activity.get_joined_buddies(): + self.buddies_panel.add_watcher(buddy) + + self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) + self._shared_activity.connect('buddy-left', self._buddy_left_cb) + + logger.debug('This is my activity: making a tube...') + id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( + SERVICE, {}) + self.info_panel.show(_('Waiting for another player to join.')) + + def _setup(self): + if self._shared_activity is None: + logger.error('Failed to share or join activity') + return + + self.conn = self._shared_activity.telepathy_conn + self.tubes_chan = self._shared_activity.telepathy_tubes_chan + self.text_chan = self._shared_activity.telepathy_text_chan + + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( + 'NewTube', self._new_tube_cb) + + def _list_tubes_reply_cb(self, tubes): + for tube_info in tubes: + self._new_tube_cb(*tube_info) + + def _list_tubes_error_cb(self, e): + logger.error('ListTubes() failed: %s', e) + + def _joined_cb(self, activity): + if self.game is not None: + return + + if not self._shared_activity: + return + + for buddy in self._shared_activity.get_joined_buddies(): + self.buddies_panel.add_watcher(buddy) + + logger.debug('Joined an existing Connect game') + self.info_panel.show(_('Joined a game. Waiting for my turn...')) + self.initiating = False + self._setup() + + logger.debug('This is not my activity: waiting for a tube...') + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( + reply_handler=self._list_tubes_reply_cb, + error_handler=self._list_tubes_error_cb) + + def _new_tube_cb(self, id, initiator, type, service, params, state): + logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' + 'params=%r state=%d', id, initiator, type, service, + params, state) + + if (self.game is None and type == telepathy.TUBE_TYPE_DBUS and + service == SERVICE): + if state == telepathy.TUBE_STATE_LOCAL_PENDING: + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) + + tube_conn = TubeConnection(self.conn, + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], + id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) + self.game = GoGame(tube_conn, self.grid, self.initiating, + self.buddies_panel, self.info_panel, self.owner, + self._get_buddy, self) + + def _buddy_joined_cb (self, activity, buddy): + logger.debug("buddy joined") + self.buddies_panel.add_watcher(buddy) + + def _buddy_left_cb (self, activity, buddy): + logger.debug("buddy left") + self.buddies_panel.remove_watcher(buddy) diff --git a/activity.pyc b/activity.pyc Binary files differnew file mode 100644 index 0000000..6020793 --- /dev/null +++ b/activity.pyc diff --git a/activity/activity-go.svg b/activity/activity-go.svg new file mode 100644 index 0000000..c40cafa --- /dev/null +++ b/activity/activity-go.svg @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> + + <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_svg "http://www.w3.org/2000/svg"> + <!ENTITY ns_xlink " http://www.w3.org/1999/xlink"> + <!ENTITY stroke_color "#000000"> + <!ENTITY fill_color "#AAAAAA"> + ]> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + enable-background="new 0 0 55 55" + height="55px" + version="1.1" + viewBox="0 0 55 55" + width="55px" + x="0px" + xml:space="preserve" + y="0px" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docname="activity-go.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:docbase="/home/gjpc/PlayGo/PlayGo/src/activity"><metadata + id="metadata26"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs24" /><sodipodi:namedview + inkscape:window-height="619" + inkscape:window-width="872" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + inkscape:zoom="7.3818182" + inkscape:cx="27.5" + inkscape:cy="27.5" + inkscape:window-x="26" + inkscape:window-y="59" + inkscape:current-layer="svg2" /><g + display="block" + id="activity-connect" + transform="translate(-0.5418719,-1.2192118)" + style="display:block"> + <g + display="inline" + id="g5" + style="display:inline"> + <path + d="M 14.118,9.535 C 14.119,11.967 12.148,13.94 9.716,13.941 C 7.283,13.942 5.311,11.971 5.31,9.539 C 5.31,9.538 5.31,9.536 5.31,9.535 C 5.308,7.103 7.279,5.13 9.711,5.128 C 12.143,5.127 14.116,7.098 14.117,9.53 C 14.118,9.532 14.118,9.534 14.118,9.535 z " + id="path2160" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 51.188,9.535 C 51.19,11.967 49.219,13.94 46.786,13.941 C 44.354,13.942 42.382,11.971 42.38,9.539 C 42.38,9.538 42.38,9.536 42.38,9.535 C 42.38,7.102 44.351,5.13 46.782,5.128 C 49.216,5.127 51.188,7.098 51.188,9.53 C 51.188,9.532 51.188,9.534 51.188,9.535 z " + id="path2162" + style="fill:#010101;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 26.475,9.535 C 26.475,11.967 24.504,13.94 22.072,13.941 C 19.639,13.942 17.667,11.971 17.665,9.539 C 17.665,9.538 17.665,9.536 17.665,9.535 C 17.664,7.102 19.635,5.13 22.067,5.128 C 24.5,5.127 26.472,7.098 26.474,9.53 C 26.475,9.532 26.475,9.534 26.475,9.535 z " + id="path3134" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 38.832,9.535 C 38.832,11.967 36.861,13.94 34.43,13.941 C 31.996,13.942 30.024,11.971 30.022,9.539 C 30.022,9.538 30.022,9.536 30.022,9.535 C 30.022,7.102 31.993,5.13 34.424,5.128 C 36.858,5.127 38.83,7.098 38.832,9.53 C 38.832,9.532 38.832,9.534 38.832,9.535 z " + id="path3136" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 26.475,21.892 C 26.475,24.325 24.504,26.297 22.072,26.298 C 19.639,26.299 17.667,24.328 17.665,21.896 C 17.665,21.895 17.665,21.893 17.665,21.892 C 17.664,19.459 19.635,17.487 22.067,17.485 C 24.5,17.484 26.472,19.455 26.474,21.887 C 26.475,21.889 26.475,21.891 26.475,21.892 z " + id="path3138" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 38.832,21.892 C 38.832,24.325 36.861,26.297 34.43,26.298 C 31.996,26.299 30.024,24.328 30.022,21.896 C 30.022,21.895 30.022,21.893 30.022,21.892 C 30.022,19.459 31.993,17.487 34.424,17.485 C 36.858,17.484 38.83,19.455 38.832,21.887 C 38.832,21.889 38.832,21.891 38.832,21.892 z " + id="path3140" + style="fill:#010101;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 14.118,21.892 C 14.119,24.325 12.148,26.297 9.716,26.298 C 7.284,26.299 5.311,24.328 5.31,21.896 C 5.31,21.895 5.31,21.893 5.31,21.892 C 5.309,19.459 7.28,17.487 9.712,17.485 C 12.144,17.484 14.117,19.455 14.118,21.887 C 14.118,21.889 14.118,21.891 14.118,21.892 z " + id="path3142" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 51.188,21.892 C 51.19,24.325 49.219,26.297 46.786,26.298 C 44.354,26.299 42.382,24.328 42.38,21.896 C 42.38,21.895 42.38,21.893 42.38,21.892 C 42.38,19.459 44.351,17.487 46.782,17.485 C 49.216,17.484 51.188,19.455 51.188,21.887 C 51.188,21.889 51.188,21.891 51.188,21.892 z " + id="path3144" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 14.118,34.248 C 14.119,36.68 12.148,38.652 9.716,38.654 C 7.283,38.655 5.311,36.684 5.31,34.252 C 5.31,34.25 5.31,34.249 5.31,34.248 C 5.309,31.815 7.28,29.843 9.712,29.842 C 12.144,29.84 14.117,31.811 14.118,34.244 C 14.118,34.245 14.118,34.246 14.118,34.248 z " + id="path3146" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + + <path + d="M 38.832,34.248 C 38.832,36.68 36.861,38.652 34.43,38.654 C 31.996,38.655 30.024,36.684 30.022,34.252 C 30.022,34.25 30.022,34.249 30.022,34.248 C 30.022,31.815 31.993,29.843 34.424,29.842 C 36.858,29.84 38.83,31.811 38.832,34.244 C 38.832,34.245 38.832,34.246 38.832,34.248 z " + id="path3152" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 38.832,46.604 C 38.832,49.038 36.861,51.01 34.43,51.011 C 31.996,51.012 30.024,49.041 30.022,46.609 C 30.022,46.608 30.022,46.606 30.022,46.604 C 30.022,44.172 31.993,42.2 34.424,42.198 C 36.858,42.198 38.83,44.169 38.832,46.6 C 38.832,46.602 38.832,46.603 38.832,46.604 z " + id="path3154" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 14.118,46.604 C 14.119,49.038 12.148,51.01 9.716,51.011 C 7.284,51.012 5.311,49.041 5.31,46.609 C 5.31,46.608 5.31,46.606 5.31,46.604 C 5.309,44.172 7.28,42.2 9.712,42.198 C 12.144,42.198 14.117,44.169 14.118,46.6 C 14.118,46.602 14.118,46.603 14.118,46.604 z " + id="path3156" + style="fill:#010101;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 26.475,46.604 C 26.475,49.038 24.504,51.01 22.072,51.011 C 19.639,51.012 17.667,49.041 17.665,46.609 C 17.665,46.608 17.665,46.606 17.665,46.604 C 17.664,44.172 19.635,42.2 22.067,42.198 C 24.5,42.198 26.472,44.169 26.474,46.6 C 26.475,46.602 26.475,46.603 26.475,46.604 z " + id="path3158" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + <path + d="M 51.188,46.604 C 51.19,49.038 49.219,51.01 46.786,51.011 C 44.354,51.012 42.382,49.041 42.38,46.609 C 42.38,46.608 42.38,46.606 42.38,46.604 C 42.38,44.172 44.351,42.2 46.782,42.198 C 49.216,42.198 51.188,44.169 51.188,46.6 C 51.188,46.602 51.188,46.603 51.188,46.604 z " + id="path3160" + style="fill:&fill_color;stroke:&stroke_color;stroke-width:2.25;stroke-linejoin:bevel" /> + </g> +</g></svg>
\ No newline at end of file diff --git a/activity/activity-helloworld.svg b/activity/activity-helloworld.svg new file mode 100644 index 0000000..b9278b0 --- /dev/null +++ b/activity/activity-helloworld.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY fill_color "#FFFFFF"> + <!ENTITY stroke_color "#000000"> +]> +<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50"> +<rect x="1" y="1" width="48" height="48" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2"/> +</svg> diff --git a/activity/activity.info b/activity/activity.info new file mode 100644 index 0000000..f5ed3b4 --- /dev/null +++ b/activity/activity.info @@ -0,0 +1,7 @@ +[Activity] +name = PlayGo +service_name = org.laptop.Playg +class = activity.PlayGo +icon = activity-go +activity_version = 1 +show_launcher = yes diff --git a/boardwidget.py b/boardwidget.py new file mode 100755 index 0000000..373a898 --- /dev/null +++ b/boardwidget.py @@ -0,0 +1,231 @@ +import logging +import cairo +import gobject +import gtk + +import game + + +logger = logging.getLogger('PlayGo-activity.gridwidget') + + +class BoardWidget(gtk.EventBox): + "Gtk widget for drawing the graphical board.""" + + __gsignals__ = { + 'insert-requested': (gobject.SIGNAL_RUN_FIRST, None, [int]), + } + + def __init__( self, aBoard ): + + gtk.EventBox.__init__( self ) + + self.output = gtk.DrawingArea() + self.set_property('child', self.output) + + self.output.connect('expose-event', self.expose_cb) + self.add_events(gtk.gdk.POINTER_MOTION_MASK) + + self.connect('button-release-event', self.__class__.button_release_cb) + self.connect('motion-notify-event', self.__class__.motion_cb) + + self.drawCoords = 1 + self.columns = aBoard.size + self.rows = aBoard.size + self.lastUnit = 0 + self.myBoard = aBoard + + self.lastColor = 1 + + # get the bitmap for genuine simulated wooden board + input = open("./images/board.gif") + imagebuf = input.read() + pixbufloader = gtk.gdk.PixbufLoader() + pixbufloader.write(imagebuf) + pixbufloader.close() + self.pixBoard = pixbufloader.get_pixbuf() + + # get the bitmap for genuine simulated white stone + input = open("./images/white.gif") + imagebuf = input.read() + pixbufloader = gtk.gdk.PixbufLoader() + pixbufloader.write(imagebuf) + pixbufloader.close() + self.pixWhite = pixbufloader.get_pixbuf() + + # get the bitmap for genuine simulated black stone + input = open("./images/black.gif") + imagebuf = input.read() + pixbufloader = gtk.gdk.PixbufLoader() + pixbufloader.write(imagebuf) + pixbufloader.close() + self.pixBlack = pixbufloader.get_pixbuf() + + def check_coord (self, i, j): + return i >= 0 and i < self.rows and j >= 0 and j < self.columns + + def insert(self, column, value): + """Return: + None : no winner + 0, 1: player 0/1 wins the game + """ + discs = [row[column] for row in self.grid] + + if -1 not in discs: + raise ValueError('Column is full') + + row = self.rows - list(reversed(discs)).index(-1) - 1 + self.grid[row][column] = value + + return self.check_winner(row, column, value) + + + def draw_background(self, rect, unit, ctx): + + ct = gtk.gdk.CairoContext(ctx) + ct.set_source_pixbuf(self.pixBoard,0,0) + ctx.paint() + ctx.stroke() + + + def draw_lines(self, rect, unit, ctx): + + # single width balck lines + ctx.set_line_width(1) + ctx.set_source_rgba(0, 0, 0, 1) + + for i in xrange(self.rows + 1): + ctx.move_to( unit, i * unit) + ctx.line_to(self.columns * unit, i * unit ) + + for i in xrange(self.columns + 1): + ctx.move_to(i * unit, unit ) + ctx.line_to(i * unit, self.rows * unit) + + ctx.stroke() + + # star point coords per board size + if self.columns == 19 : + seq = [ 4, 10, 16 ] + elif self.columns == 13 : + seq = [ 4, 7, 10 ] + elif self.columns == 9 : + seq = [ 3, 7 ] + # set the middle singleton + ctx.arc( unit * 5, unit * 5, 3, 0, -1e-10) + ctx.fill_preserve() + ctx.stroke() + + # stroke in the star points + #TODO: adjust size for teeny boards + for x in seq : + for y in seq : + ctx.arc( unit * x, unit * y, 3, 0, -1e-10) + ctx.fill_preserve() + ctx.stroke() + + + + def draw_stone(self, x, y, color, unit, ctx): + + x = x + 1 + y = y + 1 + ct = gtk.gdk.CairoContext(ctx) + if color == 0 : + ct.set_source_pixbuf(self.pixBlackSized, unit*x - unit/2, unit*y - unit/2, ) + else : + ct.set_source_pixbuf(self.pixWhiteSized, unit*x - unit/2, unit*y - unit/2, ) + + ctx.paint() + + def draw_stones( self, ctx ): + + for x in xrange(self.rows): + for y in xrange(self.columns): + + point = self.myBoard.getPoint( x, y ) + + if ( point == 1 ) : + self.draw_stone( x, y, 1, self.lastUnit, ctx ) + elif ( point == 2 ) : + self.draw_stone( x, y, 0, self.lastUnit, ctx ) + + ctx.stroke() + + def get_mouse_event_col(self, event): + + unit, x0, y0 = self.get_coordinates(self.get_allocation()) + col = ( event.x - x0 ) / unit + row = ( event.y - y0 ) / unit + return int(row), int(col) + + def motion_cb(self, event): + + col = self.get_mouse_event_col(event) + + def button_release_cb(self, event): + + self.motion_cb(event) + row, col = self.get_mouse_event_col(event) + + self.myBoard.setPointi( col, row, self.lastColor ) + if self.lastColor == 1: + self.lastColor = 2 + else : + self.lastColor = 1 + + self.window.invalidate_rect(self.get_allocation(), True) + #self.emit('insert-requested', col) + + def queue_draw(self): + self.output.queue_draw() + + def get_coordinates(self, rect): + """Returns tuple (unit size, origin x, origin y) suitable for drawing + a grid within @rect.""" + + if rect.height / float(self.rows) < rect.width / float(self.columns): + # wide + unit = rect.height / float(self.rows) + x0 = rect.x + (rect.width - self.columns * unit) / 2.0 + y0 = rect.y + else: + # narrow + unit = rect.width / float(self.columns) + x0 = rect.x + y0 = rect.y + (rect.height - self.rows * unit) / 2.0 + + # now shrink the size for a 1 unit boarder + unit = unit - unit / self.rows + + return unit, x0, y0 + + def draw(self, rect, ctx): + """Draw a grid using the cairo context @ctx within the rectangle + @rect.""" + + ctx.save() + ctx.set_line_cap(cairo.LINE_CAP_ROUND) + unit, x0, y0 = self.get_coordinates(rect) + + # I could not find the resize event so... + if self.lastUnit != unit : + self.pixBlackSized = self.pixBlack.scale_simple( int(unit), int(unit), gtk.gdk.INTERP_BILINEAR ) + self.pixWhiteSized = self.pixWhite.scale_simple( int(unit), int(unit), gtk.gdk.INTERP_BILINEAR ) + self.lastUnit = unit +# bx, by = self.pixBoard.get_size() +# if rect.height > by : +# self.pixBoard = self.pixBoard.scaleSimple( bx, by, gtk.gdk.INTERP_BILINEAR ) + + ctx.translate( x0, y0 ) + self.draw_background( rect, unit, ctx ) + self.draw_lines( rect, unit, ctx ) + self.draw_stones( ctx ) + ctx.restore() + + + def expose_cb(self, widget, event): + + ctx = widget.window.cairo_create() + rect = self.get_allocation() + self.draw(rect, ctx) diff --git a/boardwidget.pyc b/boardwidget.pyc Binary files differnew file mode 100644 index 0000000..d6bc0ca --- /dev/null +++ b/boardwidget.pyc diff --git a/buddiespanel.py b/buddiespanel.py new file mode 100755 index 0000000..5787f5c --- /dev/null +++ b/buddiespanel.py @@ -0,0 +1,132 @@ +import gtk +import hippo +import logging +from sugar.graphics.icon import CanvasIcon +from sugar.graphics.xocolor import XoColor +from sugar.graphics import style + +logger = logging.getLogger('PlayGo.buddiespanel') + +class BuddiesPanel(hippo.CanvasBox): + def __init__(self): + hippo.CanvasBox.__init__(self, spacing=4, padding=5, + orientation=hippo.ORIENTATION_VERTICAL) + + self.players_box = hippo.CanvasBox(spacing=4, padding=5, + orientation=hippo.ORIENTATION_VERTICAL) + + self.watchers_box = hippo.CanvasBox(spacing=4, padding=5, + orientation=hippo.ORIENTATION_VERTICAL) + + self.append(self.players_box) + self.append(hippo.CanvasWidget(widget=gtk.HSeparator())) + self.append(self.watchers_box, hippo.PACK_EXPAND) + + self.players = {} + self.watchers = {} + + def _create_buddy_vbox (self, buddy): + buddy_color = buddy.props.color + if not buddy_color: + buddy_color = "#000000,#ffffff" + + icon = CanvasIcon( + icon_name='computer-xo', + xo_color=XoColor(buddy_color)) + + nick = buddy.props.nick + if not nick: + nick = "" + name = hippo.CanvasText(text=nick, color=style.COLOR_WHITE.get_int()) + + vbox = hippo.CanvasBox(padding=5) + vbox.append(icon) + vbox.append(name) + + return vbox + + def add_watcher(self, buddy): + op = buddy.object_path() + if self.watchers.get(op) is not None: + return + # if the watcher is also a player, don't add them + if self.players.get(op) is not None: + return + + vbox = self._create_buddy_vbox (buddy) + + logger.debug("add watcher %s" % op) + self.watchers_box.append(vbox) + + self.watchers[op] = vbox + + def add_player(self, buddy): + op = buddy.object_path() + if self.players.get(op) is not None: + return + # if the player is also a watcher, drop them from the watchers + widget = self.watchers.pop(op, None) + if widget is not None: + self.watchers_box.remove(widget) + + logger.debug("add player %s" % op) + + assert len(self.players) < 2 + + hbox = hippo.CanvasBox(spacing=4, padding=5, + orientation=hippo.ORIENTATION_HORIZONTAL) + + vbox = self._create_buddy_vbox(buddy) + hbox.append(vbox) + + count_font = style.FONT_BOLD.get_pango_desc() + count_font.set_size(30000) + count = hippo.CanvasText(text="0", color=style.COLOR_WHITE.get_int(), + font_desc=count_font) + hbox.append(count) + + self.players_box.append(hbox) + + self.players[op] = hbox + + def set_is_playing(self, buddy): + op = buddy.object_path() + for player, hbox in self.players.items(): + vbox = hbox.get_children()[0] + icon, name = vbox.get_children() + if player == op: + name.props.font_desc = style.FONT_BOLD.get_pango_desc() + else: + name.props.font_desc = style.FONT_NORMAL.get_pango_desc() + + def set_count(self, buddy, val): + hbox = self.players.get(buddy.object_path()) + if hbox is None: + return + + count = hbox.get_children()[1] + count.props.text = str(val) + + def remove_watcher(self, buddy): + op = buddy.object_path() + widget = self.watchers[op] + if widget is None: + return + + self.watchers_box.remove(widget) + del self.watchers[op] + + # removing someone from the game entirely should also remove them + # from the players + self.remove_player(buddy) + + def remove_player(self, buddy): + op = buddy.object_path() + widget = self.players.get(op) + if widget is None: + return + + self.players_box.remove(widget) + del self.players[op] + + self.add_watcher(buddy) diff --git a/buddiespanel.pyc b/buddiespanel.pyc Binary files differnew file mode 100644 index 0000000..28f6d8f --- /dev/null +++ b/buddiespanel.pyc @@ -0,0 +1,305 @@ +import logging + +from Numeric import * +from gettext import gettext as _ +import gtk + +from dbus import Interface +from dbus.service import method, signal +from dbus.gobject_service import ExportedGObject + + +# XXX: I'm not convinced this is in the right namespace +SERVICE = "org.freedesktop.Telepathy.Tube.Connect" +IFACE = SERVICE +PATH = "/org/freedesktop/Telepathy/Tube/Connect" + + +_logger = logging.getLogger('PlayGo.game') + + +def redraw(grid): + """Utility function to force a redraw of a Gtk widget.""" + grid.queue_draw() + + +def dump_grid(seq): + grid = '' + for row in seq: + row_str = '' + for col in row: + if col == -1: + row_str += ' |' + else: + row_str += '%d|' % col + grid = '%s%s\n' % (grid, row_str) + _logger.debug('Grid state is now:\n%s', grid) + +class GoBoard( object ) : + + def __init__( self, size ): + + self.size = size + self.board = zeros( [ size, size ], Int ) + self.playNumber = 0; + + + def getPoint( self, x, y ): + + assert( x < self.size ) + assert( y < self.size ) + return self.board[x][y] + + def setPoint( self, x, y, value ): + + if value is 'Empty' : + n = 0; + elif value is 'White' : + n = 1; + elif value is 'Black' : + n = 2; + elif value is 'WhiteKo' : + n = 3; + elif value is 'BlackKo' : + n = 4; + + self.board[x][y] = n + + def setPointi( self, x, y, value ): + self.board[x][y] = value + + def clear(self): + for x in range( self.size ): + for y in range( self.size ): + self.board[x][y] = 0 + + def CopyBoard( self ) : + copy = GoBoard( self.size ) + copy.board = self.board + copy.playNumber = self.playNumber + return copy + + + +class GoGame(ExportedGObject): + + def __init__(self, tube, grid, is_initiator, buddies_panel, info_panel, + owner, get_buddy, activity): + super(GoGame, self).__init__(tube, PATH) + self.tube = tube + self.grid = grid + self.is_initiator = is_initiator + self.entered = False + self.player_id = None + self.buddies_panel = buddies_panel + self.info_panel = info_panel + self.owner = owner + self._get_buddy = get_buddy + self.activity = activity + + # list indexed by player ID + # 0, 1 are players 0, 1 + # 2+ are the spectator queue, 2 is to play next + self.ordered_bus_names = [] + + self.tube.watch_participants(self.participant_change_cb) + self.grid.connect('insert-requested', self.insert_requested_cb) + + def participant_change_cb(self, added, removed): + # Initiator is player 0, other player is player 1. + + _logger.debug('adding participants: %r', added) + _logger.debug('removing participants: %r', removed) + + for handle, bus_name in added: + buddy = self._get_buddy(handle) + _logger.debug('Buddy %r was added', buddy) + if buddy is not None: + self.buddies_panel.add_watcher(buddy) + + for handle in removed: + buddy = self._get_buddy(handle) + _logger.debug('Buddy %r was removed', buddy) + if buddy is not None: + self.buddies_panel.remove_watcher(buddy) + try: + self.ordered_bus_names.remove(self.tube.participants[handle]) + except ValueError: + # already absent + pass + + if not self.entered: + self.tube.add_signal_receiver(self.insert_cb, 'Insert', IFACE, + path=PATH, sender_keyword='sender') + if self.is_initiator: + _logger.debug('I am the initiator, so making myself player 0') + self.add_hello_handler() + self.ordered_bus_names = [self.tube.get_unique_name()] + self.player_id = 0 + self.buddies_panel.add_player(self.owner) + else: + _logger.debug('Hello, everyone! What did I miss?') + self.Hello() + self.entered = True + + @signal(dbus_interface=IFACE, signature='') + def Hello(self): + """Request that this player's Welcome method is called to bring it + up to date with the game state. + """ + + @method(dbus_interface=IFACE, in_signature='aanas', out_signature='') + def Welcome(self, grid, bus_names): + """To be called on the incoming player by the other players to + inform them of the game state. + + FIXME: nominate a "referee" (initially the initiator) responsible + for saying Welcome, elect a new referee when the current referee + leaves? This could also be used to make the protocol robust against + cheating/bugs + """ + if self.player_id is None: + _logger.debug('Welcomed to the game. Player bus names are %r', + bus_names) + self.grid.grid = grid + dump_grid(grid) + self.ordered_bus_names = bus_names + self.player_id = bus_names.index(self.tube.get_unique_name()) + # OK, now I'm synched with the game, I can welcome others + self.add_hello_handler() + + buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_names[0]]) + self.buddies_panel.add_player(buddy) + buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_names[1]]) + self.buddies_panel.add_player(buddy) + + if self.get_active_player() == self.player_id: + _logger.debug("It's my turn already!") + self.change_turn() + + redraw(self.grid) + else: + _logger.debug("I've already been welcomed, doing nothing") + + def add_hello_handler(self): + self.tube.add_signal_receiver(self.hello_cb, 'Hello', IFACE, + path=PATH, sender_keyword='sender') + + @signal(dbus_interface=IFACE, signature='n') + def Insert(self, column): + """Signal that the local player has placed a disc.""" + assert column >= 0 + assert column < 7 + + def hello_cb(self, sender=None): + """Tell the newcomer what's going on.""" + _logger.debug('Newcomer %s has joined', sender) + self.ordered_bus_names.append(sender) + if len(self.ordered_bus_names) == 2: + buddy = self._get_buddy(self.tube.bus_name_to_handle[sender]) + self.buddies_panel.add_player(buddy) + _logger.debug('Bus names are now: %r', self.ordered_bus_names) + _logger.debug('Welcoming newcomer and sending them the game state') + self.tube.get_object(sender, PATH).Welcome(self.grid.grid, + self.ordered_bus_names, + dbus_interface=IFACE) + if (self.player_id == 0 and len(self.ordered_bus_names) == 2): + _logger.debug("This is my game and an opponent has joined. " + "I go first") + self.change_turn() + + def insert_cb(self, column, sender=None): + # Someone placed a disc + handle = self.tube.bus_name_to_handle[sender] + _logger.debug('Insert(%d) from %s', column, sender) + + if self.tube.self_handle == handle: + _logger.debug('Ignoring Insert signal from myself: %d', column) + return + + try: + winner = self.grid.insert(column, self.get_active_player()) + except ValueError: + return + + dump_grid(self.grid.grid) + + if winner is not None: + _logger.debug('Player with handle %d wins', handle) + self.info_panel.show(_('The other player wins!')) + redraw(self.grid) + return + + self.change_turn() + + def change_turn(self): + try: + bus_name = self.ordered_bus_names[self.get_active_player()] + buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_name]) + self.buddies_panel.set_is_playing(buddy) + except: + _logger.error('argh!', exc_info=1) + raise + + if self.get_active_player() == self.player_id: + _logger.debug('It\'s my turn now') + self.info_panel.show(_('Your turn')) + self.grid.selected_column = 3 + self.activity.grab_focus() + else: + _logger.debug('It\'s not my turn') + self.grid.selected_column = None + + redraw(self.grid) + + def get_active_player(self): + count = {} + + for row in self.grid.grid: + for player in row: + if player > -1: + count[player] = count.get(player, 0) + 1 + + if count.get(0, 0) > count.get(1, 0): + return 1 + else: + return 0 + + def key_press_event(self, widget, event): + if self.grid.selected_column is None: + _logger.debug('Ignoring keypress - not my turn') + return + + _logger.debug('Keypress: keyval %s', event.keyval) + + if event.keyval in (gtk.keysyms.Left,): + _logger.debug('<--') + if self.grid.selected_column > 0: + self.grid.selected_column -= 1 + redraw(self.grid) + elif event.keyval in (gtk.keysyms.Right,): + _logger.debug('-->') + if self.grid.selected_column < 6: + self.grid.selected_column += 1 + redraw(self.grid) + elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.space): + _logger.debug('v') + self.insert_requested_cb(self.grid, self.grid.selected_column) + + def insert_requested_cb(self, grid, col): + winner = grid.insert(col, self.player_id) + if winner == -1: + return + + _logger.debug('Inserting at %d', col) + dump_grid(grid.grid) + redraw(grid) + self.Insert(col) + + self.change_turn() + + if winner is not None: + _logger.debug("I win") + self.info_panel.show(_('You win!')) + else: + self.info_panel.show(_('Other player\'s turn')) diff --git a/game.pyc b/game.pyc Binary files differnew file mode 100644 index 0000000..a098753 --- /dev/null +++ b/game.pyc diff --git a/images/BsTurn.gif b/images/BsTurn.gif Binary files differnew file mode 100644 index 0000000..52edae7 --- /dev/null +++ b/images/BsTurn.gif diff --git a/images/README b/images/README new file mode 100644 index 0000000..cca19e0 --- /dev/null +++ b/images/README @@ -0,0 +1,7 @@ +OLPC PlayGo Activity image library + +These images are from Ulrich Goertz's (u@g0ertz.de) uliGo 0.3 + +They are published under the GNU GENERAL PUBLIC LICENSE Version 2, June 1991. + +(C) Ulrich Goertz (u@g0ertz.de), 2001-2003.
\ No newline at end of file diff --git a/images/WsTurn.gif b/images/WsTurn.gif Binary files differnew file mode 100644 index 0000000..ab00f50 --- /dev/null +++ b/images/WsTurn.gif diff --git a/images/b.gif b/images/b.gif Binary files differnew file mode 100644 index 0000000..e56bc98 --- /dev/null +++ b/images/b.gif diff --git a/images/black.gif b/images/black.gif Binary files differnew file mode 100644 index 0000000..1719614 --- /dev/null +++ b/images/black.gif diff --git a/images/board.gif b/images/board.gif Binary files differnew file mode 100644 index 0000000..c253991 --- /dev/null +++ b/images/board.gif diff --git a/images/bw.gif b/images/bw.gif Binary files differnew file mode 100644 index 0000000..eb069a0 --- /dev/null +++ b/images/bw.gif diff --git a/images/w.gif b/images/w.gif Binary files differnew file mode 100644 index 0000000..1374cba --- /dev/null +++ b/images/w.gif diff --git a/images/white.gif b/images/white.gif Binary files differnew file mode 100644 index 0000000..03e3bf7 --- /dev/null +++ b/images/white.gif diff --git a/infopanel.py b/infopanel.py new file mode 100755 index 0000000..e608889 --- /dev/null +++ b/infopanel.py @@ -0,0 +1,20 @@ +import hippo +import pango +from sugar.graphics import style + +class InfoPanel(hippo.CanvasBox): + def __init__(self): + hippo.CanvasBox.__init__(self, spacing=4, padding=5, + orientation=hippo.ORIENTATION_VERTICAL) + self.status_box = hippo.CanvasBox(spacing=4, padding=5, + orientation=hippo.ORIENTATION_VERTICAL) + self.append(self.status_box) + + def show(self, text): + textwidget = hippo.CanvasText(text=text, + font_desc=pango.FontDescription('Sans 16'), + color=style.COLOR_WHITE.get_int(), + xalign=hippo.ALIGNMENT_CENTER) + self.status_box.remove_all() + self.status_box.append(textwidget) + diff --git a/infopanel.pyc b/infopanel.pyc Binary files differnew file mode 100644 index 0000000..003f43e --- /dev/null +++ b/infopanel.pyc diff --git a/locale/ar/LC_MESSAGES/org.laptop.Connect.mo b/locale/ar/LC_MESSAGES/org.laptop.Connect.mo Binary files differnew file mode 100644 index 0000000..24d15c3 --- /dev/null +++ b/locale/ar/LC_MESSAGES/org.laptop.Connect.mo diff --git a/locale/ar/LC_MESSAGES/org.laptop.Playg.mo b/locale/ar/LC_MESSAGES/org.laptop.Playg.mo Binary files differnew file mode 100644 index 0000000..24d15c3 --- /dev/null +++ b/locale/ar/LC_MESSAGES/org.laptop.Playg.mo diff --git a/locale/ar/activity.linfo b/locale/ar/activity.linfo new file mode 100644 index 0000000..97bb718 --- /dev/null +++ b/locale/ar/activity.linfo @@ -0,0 +1,2 @@ +[Activity] +name = PlayGo diff --git a/locale/de/LC_MESSAGES/org.laptop.Connect.mo b/locale/de/LC_MESSAGES/org.laptop.Connect.mo Binary files differnew file mode 100644 index 0000000..79cbe9f --- /dev/null +++ b/locale/de/LC_MESSAGES/org.laptop.Connect.mo diff --git a/locale/de/LC_MESSAGES/org.laptop.Playg.mo b/locale/de/LC_MESSAGES/org.laptop.Playg.mo Binary files differnew file mode 100644 index 0000000..79cbe9f --- /dev/null +++ b/locale/de/LC_MESSAGES/org.laptop.Playg.mo diff --git a/locale/de/activity.linfo b/locale/de/activity.linfo new file mode 100644 index 0000000..97bb718 --- /dev/null +++ b/locale/de/activity.linfo @@ -0,0 +1,2 @@ +[Activity] +name = PlayGo diff --git a/locale/el/LC_MESSAGES/org.laptop.Connect.mo b/locale/el/LC_MESSAGES/org.laptop.Connect.mo Binary files differnew file mode 100644 index 0000000..6493eb9 --- /dev/null +++ b/locale/el/LC_MESSAGES/org.laptop.Connect.mo diff --git a/locale/el/LC_MESSAGES/org.laptop.Playg.mo b/locale/el/LC_MESSAGES/org.laptop.Playg.mo Binary files differnew file mode 100644 index 0000000..6493eb9 --- /dev/null +++ b/locale/el/LC_MESSAGES/org.laptop.Playg.mo diff --git a/locale/el/activity.linfo b/locale/el/activity.linfo new file mode 100644 index 0000000..97bb718 --- /dev/null +++ b/locale/el/activity.linfo @@ -0,0 +1,2 @@ +[Activity] +name = PlayGo diff --git a/locale/es/LC_MESSAGES/org.laptop.Connect.mo b/locale/es/LC_MESSAGES/org.laptop.Connect.mo Binary files differnew file mode 100644 index 0000000..a0fae11 --- /dev/null +++ b/locale/es/LC_MESSAGES/org.laptop.Connect.mo diff --git a/locale/es/LC_MESSAGES/org.laptop.Playg.mo b/locale/es/LC_MESSAGES/org.laptop.Playg.mo Binary files differnew file mode 100644 index 0000000..a0fae11 --- /dev/null +++ b/locale/es/LC_MESSAGES/org.laptop.Playg.mo diff --git a/locale/es/activity.linfo b/locale/es/activity.linfo new file mode 100644 index 0000000..97bb718 --- /dev/null +++ b/locale/es/activity.linfo @@ -0,0 +1,2 @@ +[Activity] +name = PlayGo diff --git a/po/Connect.pot b/po/Connect.pot new file mode 100644 index 0000000..562cb13 --- /dev/null +++ b/po/Connect.pot @@ -0,0 +1,49 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-10-31 13:04+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: activity/activity.info:2 +msgid "Go" +msgstr "" + +#: activity.py:63 +msgid "To play the game of Go, share or invite someone." +msgstr "" + +#: activity.py:133 +msgid "Waiting for another player to join." +msgstr "" + +#: activity.py:164 +msgid "Joined a game. Waiting for my turn..." +msgstr "" + +#: game.py:183 +msgid "The other player wins!" +msgstr "" + +#: game.py:200 +msgid "Your turn" +msgstr "" + +#: game.py:257 +msgid "You win!" +msgstr "" + +#: game.py:259 +msgid "Other player's turn" +msgstr "" diff --git a/po/ar.po b/po/ar.po new file mode 100644 index 0000000..ace3d98 --- /dev/null +++ b/po/ar.po @@ -0,0 +1,63 @@ +# translation of Connect.master.po to Arabic +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Khaled Hosny <khaledhosny@eglug.org>, 2007. +msgid "" +msgstr "" +"Project-Id-Version: Connect.master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-10-31 13:04+0200\n" +"PO-Revision-Date: 2007-08-16 01:03+0300\n" +"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n" +"Language-Team: Arabic <doc@arabeyes.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? " +"3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#: activity/activity.info:2 +#, fuzzy +msgid "Connect" +msgstr "نشاط التوصيل" + +#: activity.py:63 +msgid "To play, share or invite someone." +msgstr "" + +#: activity.py:133 +msgid "Waiting for another player to join." +msgstr "بانتظار انضمام لاعب آخر." + +#: activity.py:164 +msgid "Joined a game. Waiting for my turn..." +msgstr "انضممت للعبة. أنتظر دوري..." + +#: game.py:183 +msgid "The other player wins!" +msgstr "فاز اللاعب الآخر!" + +#: game.py:200 +msgid "Your turn" +msgstr "دورك" + +#: game.py:257 +msgid "You win!" +msgstr "فزت!" + +#: game.py:259 +msgid "Other player's turn" +msgstr "دور اللاعب الآخر" + +#~ msgid "Connect Activity" +#~ msgstr "نشاط التوصيل" + +#~ msgid "Offline" +#~ msgstr "بدون اتصال" + +#~ msgid "To play, share!" +#~ msgstr "لتلعب، شارِك!" diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..09988ac --- /dev/null +++ b/po/de.po @@ -0,0 +1,58 @@ +# This file is distributed under the same license as the PACKAGE package. +# Fabian Affolter <fab@fedoraproject.org>, 2007. +# +# +msgid "" +msgstr "" +"Project-Id-Version: connect\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-10-31 13:04+0200\n" +"PO-Revision-Date: 2007-07-30 10:44+0100\n" +"Last-Translator: Fabian Affolter <fab@fedoraproject.org>\n" +"Language-Team: German <fedora-trans-de@redhat.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: German\n" + +#: activity/activity.info:2 +#, fuzzy +msgid "Connect" +msgstr "Verbindungs-Aktivität" + +#: activity.py:63 +msgid "To play, share or invite someone." +msgstr "" + +#: activity.py:133 +msgid "Waiting for another player to join." +msgstr "Warte auf andere Spieleum beizutreten." + +#: activity.py:164 +msgid "Joined a game. Waiting for my turn..." +msgstr "Einem Spiel begetreten. Warte auf meinen Zug..." + +#: game.py:183 +msgid "The other player wins!" +msgstr "Der andere Spieler gewinnt!" + +#: game.py:200 +msgid "Your turn" +msgstr "Dein Zug" + +#: game.py:257 +msgid "You win!" +msgstr "Du gewinnst!" + +#: game.py:259 +msgid "Other player's turn" +msgstr "Der andere Spieler ist am Zug" + +#~ msgid "Connect Activity" +#~ msgstr "Verbindungs-Aktivität" + +#~ msgid "Offline" +#~ msgstr "Offline" + +#~ msgid "To play, share!" +#~ msgstr "Zum Spielen, teile!" diff --git a/po/el.po b/po/el.po new file mode 100644 index 0000000..a15c023 --- /dev/null +++ b/po/el.po @@ -0,0 +1,58 @@ +# Greek translation of Connect activity. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Simos Xenitellis <simos.lists@googlemail.com>, 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: Connect activity\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-10-31 13:04+0200\n" +"PO-Revision-Date: 2007-08-20 17:08+0100\n" +"Last-Translator: Simos Xenitellis <simos.lists@googlemail.com>\n" +"Language-Team: Greek <olpc-l10n-el@googlegroups.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: activity/activity.info:2 +#, fuzzy +msgid "Connect" +msgstr "Δραστηριότητα Συνδεθείτε" + +#: activity.py:63 +msgid "To play, share or invite someone." +msgstr "" + +#: activity.py:133 +msgid "Waiting for another player to join." +msgstr "Σε αναμονή για τη σύνδεση άλλου παίκτη." + +#: activity.py:164 +msgid "Joined a game. Waiting for my turn..." +msgstr "Σε σύνδεση σε παιχνίδι. Αναμένουμε για τη σειρά μας..." + +#: game.py:183 +msgid "The other player wins!" +msgstr "Η άλλη πλευρά κερδίζει!" + +#: game.py:200 +msgid "Your turn" +msgstr "Η σειρά σου" + +#: game.py:257 +msgid "You win!" +msgstr "Κέρδισες!" + +#: game.py:259 +msgid "Other player's turn" +msgstr "Η σειρά της άλλης πλευράς" + +#~ msgid "Connect Activity" +#~ msgstr "Δραστηριότητα Συνδεθείτε" + +#~ msgid "Offline" +#~ msgstr "Εκτός σύνδεσης" + +#~ msgid "To play, share!" +#~ msgstr "Για να παίξετε, να μοιραστείτε!" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..eb6fcea --- /dev/null +++ b/po/es.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Actividad Conectar\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-10-31 13:04+0200\n" +"PO-Revision-Date: 2007-09-18 09:24-0300\n" +"Last-Translator: Domingo Becker <domingobecker@gmail.com>\n" +"Language-Team: Fedora Spanish <fedora-trans-es@redhat.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Spanish\n" + +#: activity/activity.info:2 +msgid "Connect" +msgstr "Conectar" + +#: activity.py:63 +msgid "To play, share or invite someone." +msgstr "Para jugar, compartir o invitar a alguien." + +#: activity.py:133 +msgid "Waiting for another player to join." +msgstr "Esperando que otro jugador se conecte." + +#: activity.py:164 +msgid "Joined a game. Waiting for my turn..." +msgstr "Jugando. Esperando mi turno..." + +#: game.py:183 +msgid "The other player wins!" +msgstr "El otro jugador ganó!" + +#: game.py:200 +msgid "Your turn" +msgstr "Tu turno" + +#: game.py:257 +msgid "You win!" +msgstr "Ganaste!" + +#: game.py:259 +msgid "Other player's turn" +msgstr "Turno del otro jugador" + +#~ msgid "Connect Activity" +#~ msgstr "Actividad Conectar" + +#~ msgid "Offline" +#~ msgstr "Fuera de línea" + +#~ msgid "To play, share!" +#~ msgstr "Para jugar, comparte!" diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..d07fb3d --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (C) 2006, Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +from sugar.activity import bundlebuilder + +if __name__ == "__main__": + bundlebuilder.start('PlayGo') diff --git a/widgettest.py b/widgettest.py new file mode 100755 index 0000000..7803dab --- /dev/null +++ b/widgettest.py @@ -0,0 +1,62 @@ + +import gtk +import random + +import game +import boardwidget + +board = game.GoBoard( 19 ) + +def redraw(grid): + """Utility function to force a redraw of a Gtk widget.""" + grid.window.invalidate_rect(grid.get_allocation(), True) + +def key_press_cb(window, event, grid, player): + + key = gtk.gdk.keyval_name(event.keyval) + + if key in ('Left',): + for x in range( 19 ): + board.setPoint(x, 3, 'Black' ) + redraw(grid) + + elif key in ('Right',): + for x in range( 19 ): + board.setPoint(x, 3, 'Empty' ) + redraw(grid) + + elif key in ( 'r', ): + for x in range( 19 ): + for y in range( 19 ): + board.setPointi(x, y, random.randint( 0, 3 ) ) + + redraw(grid) + + elif key in ( 'c', ): + board.clear() + redraw(grid) + + elif gtk.gdk.keyval_name(event.keyval) in ('Escape', 'q'): + gtk.main_quit() + +def main(): + + for x in range( 19 ): + board.setPoint(x, 0, 'White' ) + + grid = boardwidget.BoardWidget( board ) + + window = gtk.Window() + window.connect('destroy', gtk.main_quit) + window.connect('key-press-event', key_press_cb, grid, [1]) + window.add(grid) + window.show_all() + + try: + gtk.main() + except KeyboardInterrupt: + pass + +if __name__ == '__main__': + main() + |