diff options
author | Walter Bender <walter.bender@gmail.com> | 2011-03-25 00:22:09 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2011-03-25 00:22:09 (GMT) |
commit | 751eef0bb55aa840ba4077cd9115390cf7cc12c9 (patch) | |
tree | 597d3aa2f0f117d15fbd43a83fdc4734b6fe9e1b | |
parent | a6a6d15fcfa73acbf7a1ea9027898c713184aa73 (diff) |
more sharing code
-rw-r--r-- | PathsActivity.py | 149 | ||||
-rw-r--r-- | card.py | 10 | ||||
-rw-r--r-- | game.py | 69 | ||||
-rwxr-xr-x | genpieces.py | 29 | ||||
-rw-r--r-- | utils.py | 10 |
5 files changed, 158 insertions, 109 deletions
diff --git a/PathsActivity.py b/PathsActivity.py index 5b2af2b..eb7926f 100644 --- a/PathsActivity.py +++ b/PathsActivity.py @@ -45,7 +45,8 @@ import os.path from game import Game, CARDS from hand import Hand -from utils import json_load, json_dump +from genpieces import generate_xo +from utils import json_load, json_dump, svg_str_to_pixbuf from constants import ROW, COL MAX_HANDS = 4 @@ -96,6 +97,20 @@ def _separator_factory(toolbar, visible=True, expand=False): separator.show() +def _image_factory(image, toolbar, from_file=False): + """ Add an image to the toolbar """ + print "in image factory", image, toolbar + img = gtk.Image() + if from_file: + img.set_from_file(image) + else: + img.set_from_pixbuf(image) + img_tool = gtk.ToolItem() + img_tool.add(img) + toolbar.insert(img_tool, -1) + img_tool.show() + + class PathsActivity(activity.Activity): """ Path puzzle game """ @@ -123,22 +138,22 @@ class PathsActivity(activity.Activity): # Restore game state from Journal or start new game if 'deck' in self.metadata: - print 'restoring' + print 'Restoring.' self._restore() elif not hasattr(self, 'initiating'): - print 'no initiating' + print 'No initiating attribute.' self._game.new_game() elif not self.initiating: - print 'I am not initiating' + print 'I am not initiating.' self._game.new_game() elif len(self._game.buddies) == 1: - print 'no buddies' + print 'No buddies.' self._game.new_game() else: print 'I am confused' def _setup_toolbars(self, have_toolbox): - """ Setup the toolbars.. """ + """ Setup the toolbars. """ self.max_participants = 4 @@ -153,7 +168,7 @@ class PathsActivity(activity.Activity): self.set_toolbar_box(toolbox) toolbox.show() - toolbar = toolbox.toolbar + self.toolbar = toolbox.toolbar else: # Use pre-0.86 toolbar design @@ -163,21 +178,21 @@ class PathsActivity(activity.Activity): toolbox.add_toolbar(_('Game'), games_toolbar) toolbox.show() toolbox.set_current_toolbar(1) - toolbar = games_toolbar + self.toolbar = games_toolbar self._new_game_button = _button_factory('new-game', _('Start a new game.'), - self._new_game_cb, toolbar) + self._new_game_cb, self.toolbar) self.robot_button = _button_factory('robot-off', _('Play with the computer.'), - self._robot_cb, toolbar) + self._robot_cb, self.toolbar) self.dialog_button = _button_factory('dialog-ok', _('Turn complete'), - self._dialog_cb, toolbar) + self._dialog_cb, self.toolbar) - self.status = _label_factory(_('It is your turn.'), toolbar) + self.status = _label_factory('', self.toolbar) if _have_toolbox: _separator_factory(toolbox.toolbar, False, True) @@ -208,10 +223,10 @@ class PathsActivity(activity.Activity): def _dialog_cb(self, button=None): ''' Send end of turn ''' if self._game.placed_a_tile: - print 'placed a tile and click on toolbar button' + print 'Placed a tile and clicked on toolbar button.' self._game.took_my_turn() else: - print 'need to place a piece' + print 'Clicked on the toolbar button but need to place a piece.' def write_file(self, file_path): """ Write the grid status to the Journal """ @@ -219,15 +234,20 @@ class PathsActivity(activity.Activity): return self.metadata['deck'] = self._game.deck.serialize() self.metadata['grid'] = self._game.grid.serialize() - if self._game._we_are_sharing(): + if self._game.we_are_sharing(): for i, hand in enumerate(self._game.hands): self.metadata['hand-' + str(i)] = hand.serialize() else: self.metadata['hand-0'] = self._game.hands[0].serialize() if self._game.playing_with_robot: self.metadata['hand-1'] = self._game.hands[1].serialize() - elif 'hand-1' in self.metadata: - del self.metadata['hand-1'] + self.metadata['robot'] = 'True' + else: + if 'hand-1' in self.metadata: + del self.metadata['hand-1'] + if 'robot' in self.metadata: + del self.metadata['robot'] + if self._game.last_spr_moved is not None and \ self._game.grid.spr_to_grid(self._game.last_spr_moved) is not None: self.metadata['last'] = str(self._game.grid.grid[ @@ -235,6 +255,8 @@ class PathsActivity(activity.Activity): def _restore(self): """ Restore the game state from metadata """ + if 'robot' in self.metadata: + self.set_robot_status(True, 'robot-on') if 'deck' in self.metadata: self._game.deck.restore(self.metadata['deck']) if 'grid' in self.metadata: @@ -278,62 +300,54 @@ class PathsActivity(activity.Activity): def _shared_cb(self, activity): """ Either set up initial share...""" - if self._shared_activity is None: - print("Error: Failed to share or join activity ... \ - _shared_activity is null in _shared_cb()") - return - - self.initiating = True - self.waiting_for_hand = False - print('I am sharing...') - - 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) - - print('This is my activity: making a tube...') - id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( - SERVICE, {}) - - self._new_game_button.set_tooltip( - _('Start a new game once everyone has joined.')) - - self.robot_button.set_icon('no-robot') - self.robot_button.set_tooltip(_('The robot is disabled when sharing.')) + self._new_tube_common(True) def _joined_cb(self, activity): """ ...or join an exisiting share. """ + self._new_tube_common(False) + + def _new_tube_common(self, sharer): + """ Joining and sharing are mostly the same... """ if self._shared_activity is None: print("Error: Failed to share or join activity ... \ _shared_activity is null in _shared_cb()") return - self.initiating = False - print('I joined a shared activity.') + self.initiating = sharer + self.waiting_for_hand = not sharer 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) + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal\ + ('NewTube', self._new_tube_cb) + + if sharer: + print('This is my activity: making a tube...') + id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( + SERVICE, {}) - print('I am joining an 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) + self._new_game_button.set_tooltip( + _('Start a new game once everyone has joined.')) + else: + print('I am joining an 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) - self._new_game_button.set_icon('no-new-game') - self._new_game_button.set_tooltip( - _('Only the sharer can start a new game.')) + self._new_game_button.set_icon('no-new-game') + self._new_game_button.set_tooltip( + _('Only the sharer can start a new game.')) self.robot_button.set_icon('no-robot') self.robot_button.set_tooltip(_('The robot is disabled when sharing.')) - self.waiting_for_hand = True + # display your XO on the toolbar + print "calling image_factory", self.colors + _image_factory(svg_str_to_pixbuf(generate_xo(colors=self.colors)), + self.toolbar) + self.toolbar.show() def _list_tubes_reply_cb(self, tubes): """ Reply to a list request. """ @@ -396,6 +410,10 @@ state=%d' % (id, initiator, type, service, params, state)) self.status.set_label(nick + ' ' + _('has joined.')) if not nick in self._game.buddies: self._game.buddies.append(nick) + # TODO: get joiner's colors + _image_factory(svg_str_to_pixbuf(generate_xo()), + toolbar) + if self.initiating: payload = json_dump(self._game.buddies) print payload @@ -432,7 +450,7 @@ state=%d' % (id, initiator, type, service, params, state)) print 'I saw a hand for %s' % (nick) def _play_a_piece(self, payload): - # TO DO: something with buttons and label + # When a piece is played, everyone should move it into position. tile_number, orientation, grid_position = json_load(payload) print 'moving tile', tile_number, orientation, grid_position for i in range(ROW * COL): # find the tile with this number @@ -442,24 +460,31 @@ state=%d' % (id, initiator, type, service, params, state)) self._game.grid.add_card_to_grid(tile_to_move, orientation, grid_position, self._game.deck) self._game.show_connected_tiles() + + # Then the sharer should let the next player know it is their turn. if self.initiating: self._game.whos_turn += 1 if self._game.whos_turn == len(self._game.buddies): self._game.whos_turn = 0 + if self._game.whos_turn == 0: # Sharer's turn + self.status.set_label(self.nick + ': ' + _('take a turn.')) + self._take_a_turn(self._game.buddies[self._game.whos_turn]) print "it is %s's turn" % (self._game.buddies[self._game.whos_turn]) print 'sending turn event' - self.send_event('t|%s' % (self._game.buddies[self._game.whos_turn])) - self._take_a_turn(self._game.buddies[self._game.whos_turn]) + self.send_event('t|%s' % (self._game.buddies[ + self._game.whos_turn])) def _take_a_turn(self, payload): + # If it is your turn, take it, otherwise, wait. print 'take a turn event' nick = payload print "It's %s's turn." % (nick) - self.status.set_label(nick + ': ' + _('take a turn.')) - if nick == self.nick: - self._game.its_my_turn() - else: - self._game.its_their_turn(nick) + if not self.initiating: + self.status.set_label(nick + ': ' + _('take a turn.')) + if nick == self.nick: + self._game.its_my_turn() + else: + self._game.its_their_turn(nick) def send_event(self, entry): """ Send event through the tube. """ @@ -13,7 +13,7 @@ import gtk from constants import NORTH, EAST, SOUTH, WEST, HIDE, CARDS from sprites import Sprite - +from utils import svg_str_to_pixbuf class Card: @@ -75,14 +75,6 @@ class Card: self.spr.move((-self.spr.images[0].get_width(),0)) -def svg_str_to_pixbuf(svg_string): - ''' Load pixbuf from SVG string ''' - pl = gtk.gdk.PixbufLoader('svg') - pl.write(svg_string) - pl.close() - pixbuf = pl.get_pixbuf() - return pixbuf - # # Utilities used to create graphics used for interactions # @@ -12,6 +12,7 @@ # Boston, MA 02111-1307, USA. import gtk +import gobject from gettext import gettext as _ import logging @@ -121,20 +122,20 @@ class Game(): self._all_clear() # If we are not sharing or we are the sharer... - if not self._we_are_sharing() or self.activity.initiating: - if not self._we_are_sharing(): + if not self.we_are_sharing() or self.activity.initiating: + if not self.we_are_sharing(): print 'We are not sharing.' if not self.activity.initiating: print 'I am initiating.' # Let joiners know we are starting a new game... - if self._we_are_sharing(): + if self.we_are_sharing(): print 'sending a new_game event' self.activity.send_event('n| ') # The initiator shuffles the deck... self.deck.shuffle() # ...and shares it. - if self._we_are_sharing(): + if self.we_are_sharing(): print 'sending a new deck event' self.activity.send_event('d|%s' % (self.deck.serialize())) @@ -166,10 +167,11 @@ class Game(): # If we are joining, we need to wait for a hand. else: self.my_hand = self.buddies.index(self.activity.nick) + print 'my hand is %d' % (self.my_hand) print 'Waiting for hand from the sharer and a turn to play.' - self.its_their_turn(_('my turn')) + self.its_their_turn(self.buddies[1]) # Sharer will be buddy 1 - def _we_are_sharing(self): + def we_are_sharing(self): ''' If we are sharing, there is more than one buddy. ''' if len(self.buddies) > 1: return True @@ -194,11 +196,11 @@ class Game(): self.activity.dialog_button.set_icon('dialog-ok') self.activity.dialog_button.set_tooltip( _('Click after taking your turn.')) - self._set_label(self.activity.nick + ': ' + _('It is my turn.')) + self._set_label(self.activity.nick + ': ' + _('It is your turn.')) def _redeal(self): # Only the sharer deals cards. - if not self._we_are_sharing(): + if not self.we_are_sharing(): self.hands[self.my_hand].deal(self.deck) if self.playing_with_robot: self.hands[ROBOT_HAND].deal(self.deck) @@ -220,7 +222,7 @@ class Game(): def took_my_turn(self): # Did I complete my turn without any errors? if self.there_are_errors: - self._set_label(_('There are errors -- still my turn.')) + self._set_label(_('There are errors -- it is still your turn.')) return # Are there any completed paths? @@ -229,34 +231,40 @@ class Game(): self._test_for_complete_paths(self.last_grid_played) # If so, let everyone know what piece I moved. - if self._we_are_sharing(): + if self.we_are_sharing(): self.activity.send_event('p|%s' % \ (json_dump([self.last_tile_played, self.last_tile_orientation, self.last_grid_played]))) # I took my turn, so I am waiting again. self.waiting_for_my_turn = True - self.last_spr_moved.set_layer(CARDS) + if self.last_spr_moved is not None: + self.last_spr_moved.set_layer(CARDS) + self.last_spr_moved = None self._hide_highlight() print 'took my turn' - self._set_label(_('I took my turn.')) + self._set_label(_('You took your turn.')) + if self.playing_with_robot: self.its_their_turn(_('robot')) self.waiting_for_robot = True - self._robot_play() - self.show_connected_tiles() - - # If the robot played or playing solitaire, go again. - if self.playing_with_robot or not self._we_are_sharing(): + gobject.timeout_add(1000, self._robot_turn) + elif not self.we_are_sharing(): self.its_my_turn() + def _robot_turn(self): + self._robot_play() + self.show_connected_tiles() + self.its_my_turn() + def its_their_turn(self, nick): # It is someone else's turn. print 'waiting for ', nick if self.running_sugar: self.activity.dialog_button.set_icon('dialog-cancel') self.activity.dialog_button.set_tooltip(_('Wait your turn.')) - self._set_label(_('Waiting for') + nick) + self._set_label(_('Waiting for') + ' ' + nick) + self.waiting_for_my_turn = True # I am still waiting. def _button_press_cb(self, win, event): win.grab_focus() @@ -276,9 +284,7 @@ class Game(): self.release = None # Ignore clicks on background except to indicate you took your turn - if spr is None or \ - spr in self.grid.blanks or \ - spr == self.deck.board: + if spr is None or spr in self.grid.blanks or spr == self.deck.board: if self.placed_a_tile and spr is None: print 'placed a tile and clicked on None' self.took_my_turn() @@ -335,15 +341,12 @@ class Game(): x, y = map(int, event.get_coords()) spr = self.sprites.find_sprite((x, y)) - - # when we are dragging, this sprite will be the same as self.press grid_pos = self.grid.xy_to_grid(x, y) hand_pos = self.hands[self.my_hand].xy_to_hand(x, y) - print grid_pos, hand_pos + if grid_pos is not None: # Placing tile in grid if self.grid.grid[grid_pos] is None: card = self.deck.spr_to_card(self.press) - print 'moving card to grid ', self.grid.grid_to_xy(grid_pos) card.spr.move(self.grid.grid_to_xy(grid_pos)) i = self.grid.spr_to_grid(self.press) if i is not None: @@ -361,14 +364,11 @@ class Game(): if self.last_spr_moved != card.spr: self.last_spr_moved = card.spr self._show_highlight() - # Returning tile to hand - elif hand_pos is not None: # or x < self.grid.left: + elif hand_pos is not None: # Returning tile to hand i = self.hands[self.my_hand].find_empty_slot() print 'found an empty slot?', i if i is not None: - print 'returning card to hand' card = self.deck.spr_to_card(self.press) - print 'moving card to ', self.hands[self.my_hand].hand_to_xy(i) card.spr.move(self.hands[self.my_hand].hand_to_xy(i)) if self.hands[self.my_hand].spr_to_hand(self.press) is not None: self.hands[self.my_hand].hand[ @@ -385,9 +385,7 @@ class Game(): grid_pos = self.grid.spr_to_grid(self.press) if grid_pos is not None: card = self.deck.spr_to_card(self.press) - print 'returning card to grid' card.spr.move(self.grid.grid_to_xy(grid_pos)) - self._hide_highlight() self.press = None self.release = None @@ -395,7 +393,7 @@ class Game(): return True self.release = spr - if self.press == self.release and not self._it_is_a_drag(): + if self.press == self.release and not self._it_is_a_drag(): # Rotate card = self.deck.spr_to_card(spr) card.rotate_clockwise() self.last_tile_orientation = card.orientation @@ -403,6 +401,13 @@ class Game(): self.last_spr_moved = card.spr self._show_highlight() + if hand_pos is None and x < self.grid.left: # In limbo: return to grid + grid_pos = self.grid.spr_to_grid(self.press) + if grid_pos is not None: + card = self.deck.spr_to_card(self.press) + card.spr.move(self.grid.grid_to_xy(grid_pos)) + self._hide_highlight() + self._test_for_bad_paths(self.grid.spr_to_grid(self.press)) self.show_connected_tiles() self.press = None diff --git a/genpieces.py b/genpieces.py index 90934d5..9cba133 100755 --- a/genpieces.py +++ b/genpieces.py @@ -26,11 +26,19 @@ class SVG: self._stroke = '#000000' def _svg_style(self, extras=""): - return "%s%s%s%s%s%f%s%s%s" % ("style=\"fill:", self._fill, ";stroke:", + return "%s%s%s%s%s%f%s%s%s" % (" style=\"fill:", self._fill, ";stroke:", self._stroke, ";stroke-width:", self._stroke_width, ";", extras, "\" />\n") + def _svg_xo(self): + self.set_stroke_width(3.5) + svg_string = "<path d=\"M33.233,35.1l10.102,10.1c0.752,0.75,1.217,1.783,1.217,2.932 c0,2.287-1.855,4.143-4.146,4.143c-1.145,0-2.178-0.463-2.932-1.211L27.372,40.961l-10.1,10.1c-0.75,0.75-1.787,1.211-2.934,1.211 c-2.284,0-4.143-1.854-4.143-4.141c0-1.146,0.465-2.184,1.212-2.934l10.104-10.102L11.409,24.995 c-0.747-0.748-1.212-1.785-1.212-2.93c0-2.289,1.854-4.146,4.146-4.146c1.143,0,2.18,0.465,2.93,1.214l10.099,10.102l10.102-10.103 c0.754-0.749,1.787-1.214,2.934-1.214c2.289,0,4.146,1.856,4.146,4.145c0,1.146-0.467,2.18-1.217,2.932L33.233,35.1z\"" + svg_string += self._svg_style() + svg_string += "\n<circle cx=\"27.371\" cy=\"10.849\" r=\"8.122\"" + svg_string += self._svg_style() + return svg_string + def _svg_line(self, x1, y1, x2, y2): svg_string = "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\"\n" % \ (x1, y1, x2, y2) @@ -127,6 +135,15 @@ class SVG: # # Card generators # +def generate_xo(scale=1, colors=["#FFFFFF", "#000000"]): + svg = SVG() + svg.set_scale(scale) + svg.set_colors(colors) + svg_string = svg.header(background=False) + svg_string += svg._svg_xo() + svg_string += svg.footer() + return svg_string + def generate_x(scale=1): svg = SVG() svg.set_scale(scale) @@ -192,6 +209,7 @@ def close_file(f): f.close() def generator(datapath): + """ i = 0 filename = "tile-%d.svg" % (i) f = open_file(datapath, filename) @@ -226,23 +244,22 @@ def generator(datapath): filename = "tile-%d.svg" % (i) f = open_file(datapath, filename) f.write(generate_tile_2_lines(-1, 0, 0, 0, 0, -1, 1, 0)) - i += 1 close_file(f) f = open_file(datapath, 'x.svg') f.write(generate_x()) - i += 1 close_file(f) f = open_file(datapath, 'blank.svg') f.write(generate_blank()) - i += 1 close_file(f) f = open_file(datapath, 'corners.svg') f.write(generate_corners()) - i += 1 close_file(f) f = open_file(datapath, 'board.svg') f.write(generate_board()) - i += 1 + close_file(f) + """ + f = open_file(datapath, 'xo.svg') + f.write(generate_xo()) close_file(f) def main(): @@ -10,6 +10,7 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. +import gtk from StringIO import StringIO try: OLD_SUGAR_SYSTEM = False @@ -51,3 +52,12 @@ def json_dump(data): _io = StringIO() jdump(data, _io) return _io.getvalue() + + +def svg_str_to_pixbuf(svg_string): + ''' Load pixbuf from SVG string ''' + pl = gtk.gdk.PixbufLoader('svg') + pl.write(svg_string) + pl.close() + pixbuf = pl.get_pixbuf() + return pixbuf |