diff options
author | Walter Bender <walter.bender@gmail.com> | 2011-03-13 13:28:12 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2011-03-13 13:28:12 (GMT) |
commit | 0279518276390439777a351a770c9e98b23d6ab3 (patch) | |
tree | 6ff4e6612f2575f1661750e8b7ae8275e9f7c0f1 | |
parent | cb523a3e3f4687e49f1c900898f3659e8b92fd97 (diff) |
refactoring in anticipation of sharing
-rw-r--r-- | PathsActivity.py | 83 | ||||
-rw-r--r-- | deck.py | 27 | ||||
-rw-r--r-- | game.py | 62 | ||||
-rw-r--r-- | grid.py | 118 | ||||
-rw-r--r-- | hand.py | 106 | ||||
-rw-r--r-- | utils.py | 56 |
6 files changed, 266 insertions, 186 deletions
diff --git a/PathsActivity.py b/PathsActivity.py index 38f4c66..9f2f1da 100644 --- a/PathsActivity.py +++ b/PathsActivity.py @@ -38,6 +38,7 @@ import locale import os.path from game import Game, CARDS +from hand import Hand SERVICE = 'org.sugarlabs.PathsActivity' IFACE = SERVICE @@ -184,30 +185,16 @@ class PathsActivity(activity.Activity): def set_robot_status(self, status, icon): ''' Reset robot icon and status ''' self._game.playing_with_robot = status - self._game.grid.set_robot_status(status) self.robot_button.set_icon(icon) def write_file(self, file_path): """ Write the grid status to the Journal """ if not hasattr(self, '_game'): return - for i in range(64): - self.metadata['deck' + str(i)] = \ - str(self._game.deck.cards[i].number) - for i in range(64): - if self._game.grid.grid[i] is not None: - self.metadata['grid' + str(i)] = \ - str(self._game.grid.grid[i].number) - self.metadata['rotate' + str(i)] = \ - str(self._game.grid.grid[i].orientation) - else: - self.metadata['grid' + str(i)] = 'None' - for i in range(8): - if self._game.grid.hand[i] is not None: - self.metadata['hand' + str(i)] = \ - str(self._game.grid.hand[i].number) - else: - self.metadata['hand' + str(i)] = 'None' + self.metadata['deck'] = self._game.deck.serialize() + self.metadata['grid'] = self._game.grid.serialize() + for i, hand in enumerate(self._game.hands): + self.metadata['hand-' + str(i)] = hand.serialize() 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[ @@ -215,52 +202,24 @@ class PathsActivity(activity.Activity): def _restore(self): """ Restore the game state from metadata """ - deck = [] - for i in range(64): - if 'deck' + str(i) in self.metadata: - deck.append(self._game.deck.cards[ - int(self.metadata['deck' + str(i)])]) - if len(deck) == 64: # We've retrieved an entire deck - self._game.deck.cards = deck[:] - - for i in range(64): - if 'grid' + str(i) in self.metadata: - if self.metadata['grid' + str(i)] == 'None': - self._game.grid.grid[i] = None - else: - j = int(self.metadata['grid' + str(i)]) - for k in range(64): - if self._game.deck.cards[k].number == j: - self._game.grid.grid[i] = self._game.deck.cards[k] - self._game.grid.grid[i].spr.move( - self._game.grid.grid_to_xy(i)) - self._game.grid.grid[i].spr.set_layer(CARDS) - if 'rotate' + str(i) in self.metadata: - o = int(self.metadata['rotate' + str(i)]) - while o > 0: - self._game.grid.grid[i].rotate_clockwise() - o -= 90 - else: - self._game.grid.grid[i] = None + if 'deck' in self.metadata: + self._game.deck.restore(self.metadata['deck']) + if 'grid' in self.metadata: + self._game.grid.restore(self.metadata['grid'], self._game.deck) self._game.show_connected_tiles() - for i in range(8): - if 'hand' + str(i) in self.metadata: - if self.metadata['hand' + str(i)] == 'None': - self._game.grid.hand[i] = None - else: - j = int(self.metadata['hand' + str(i)]) - for k in range(64): - if self._game.deck.cards[k].number == j: - self._game.grid.hand[i] = self._game.deck.cards[k] - self._game.grid.hand[i].spr.move( - self._game.grid.hand_to_xy(i)) - self._game.grid.hand[i].spr.set_layer(CARDS) - else: - self._game.grid.hand[i] = None - - self._game.deck.index = 64 - self._game.grid.grid.count(None) + \ - 8 - self._game.grid.hand.count(None) + for i in range(2): + if 'hand-' + str(i) in self.metadata: + if len(self._game.hands) < i + 1: # Add robot hand? + self._game.hands.append( + Hand(self._game.card_width, self._game.card_height, + robot=True)) + self._game.hands[i].restore(self.metadata['hand-' + str(i)], + self._game.deck) + + self._game.deck.index = 64 - self._game.grid.cards_in_grid() + for h in self._game.hands: + self._game.deck.index += (8 - h.cards_in_hand()) self._game.last_spr_moved = None if 'last' in self.metadata: @@ -15,7 +15,7 @@ from random import randrange from card import Card, board_card from genpieces import generate_tile_1_line, generate_tile_2_lines - +from utils import json_dump, json_load HIDE = 0 BOARD = 1 @@ -117,19 +117,20 @@ class Deck: order[size - 1 - i] = a return order - def restore(self, saved_deck_indices): - ''' Restore the deck upon resume. ''' - decksize = len(saved_deck_indices) - # If we have a short deck, then we need to abort. - if self.count() < decksize: - return False - _deck = [] - for i in saved_deck_indices: - _deck.append(self.index_to_card(i)) - for i in range(decksize): - self.cards[i] = _deck[i] - return True + def serialize(self): + ''' Serialize the deck for passing to share and saving ''' + order = [] + for i in range(64): + order.append(self.cards[i].number) + return json_dump(order) + def restore(self, deck_as_text): + ''' Restore the deck upon resume. ''' + deck = [] + order = json_load(deck_as_text) + for i in order: + deck.append(self.cards[order[i]]) + self.cards = deck[:] def clear(self): ''' Remove any highlight from the cards. ''' @@ -23,6 +23,7 @@ except ImportError: GRID_CELL_SIZE = 0 from grid import Grid +from hand import Hand from deck import Deck from card import error_card, highlight_cards from sprites import Sprites @@ -41,6 +42,8 @@ BOARD = 1 GRID = 2 CARDS = 3 OVERLAY = 4 +MY_HAND = 0 +ROBOT_HAND = 1 class Game(): @@ -82,6 +85,8 @@ class Game(): self.deck.board.move((self.grid.left, self.grid.top)) self.deck.hide() + self.hands = [] + self.hands.append(Hand(self.card_width, self.card_height)) for i in range(4): self.errormsg.append(error_card(self.sprites)) self._hide_errormsgs() @@ -104,15 +109,24 @@ class Game(): self.deck.hide() # Shuffle the deck and deal a hand of tiles. + ''' if self.playing_with_robot: self.grid.set_robot_status(True) else: self.grid.set_robot_status(False) + ''' self.grid.clear() self.deck.clear() self.show_connected_tiles() self.deck.shuffle() - self.grid.deal(self.deck) + for hand in self.hands: + hand.clear() + self.hands[MY_HAND].deal(self.deck) + if self.playing_with_robot: + if len(self.hands) < ROBOT_HAND + 1: + self.hands.append(Hand(self.card_width, self.card_height, + robot=True)) + self.hands[ROBOT_HAND].deal(self.deck) self.press = None self.release = None self.placed_a_tile = None @@ -137,15 +151,17 @@ class Game(): if self.playing_with_robot: self._robot_play() self.show_connected_tiles() - if self.grid.cards_in_hand() == 0: - self.grid.redeal(self.deck) + if self.hands[MY_HAND].cards_in_hand() == 0: + for hand in self.hands: + hand.deal(self.deck) if self.playing_with_robot and self.sugar: self.activity.status.set_label(_('It is your turn.')) self.placed_a_tile = False return True # Are we clicking on a tile in the hand? - if self.grid.spr_to_hand(spr) is not None and \ + # if self.grid.spr_to_hand(spr) is not None and \ + if self.hands[MY_HAND].spr_to_hand(spr) is not None and \ not self.there_are_errors: self.last_spr_moved = spr if self.sugar: @@ -153,8 +169,9 @@ class Game(): if self.placed_a_tile: if self.playing_with_robot: self._robot_play() - if self.grid.cards_in_hand() == 0: - self.grid.redeal(self.deck) + if self.hands[MY_HAND].cards_in_hand() == 0: + for hand in self.hands: + hand.deal(self.deck) self.placed_a_tile = False else: clicked_in_hand = False @@ -176,15 +193,17 @@ class Game(): spr = self.sprites.find_sprite((x, y)) if spr is None: # Returning tile to hand - i = self.grid.find_empty_slot() + i = self.hands[MY_HAND].find_empty_slot() if i is not None: card = self.deck.spr_to_card(self.press) - card.spr.move(self.grid.hand_to_xy(i)) - if self.grid.spr_to_hand(self.press) is not None: - self.grid.hand[self.grid.spr_to_hand(self.press)] = None + + card.spr.move(self.hands[MY_HAND].hand_to_xy(i)) + if self.hands[MY_HAND].spr_to_hand(self.press) is not None: + self.hands[MY_HAND].hand[ + self.hands[MY_HAND].spr_to_hand(self.press)] = None elif self.grid.spr_to_grid(self.press) is not None: self.grid.grid[self.grid.spr_to_grid(self.press)] = None - self.grid.hand[i] = card + self.hands[MY_HAND].hand[i] = card if spr == self.last_spr_moved: self.last_spr_moved = None self._hide_highlight() @@ -213,9 +232,9 @@ class Game(): self.grid.grid[self.grid.xy_to_grid(x, y)] = card self.placed_a_tile = True - i = self.grid.spr_to_hand(self.press) + i = self.hands[MY_HAND].spr_to_hand(self.press) if i is not None: - self.grid.hand[i] = None + self.hands[MY_HAND].hand[i] = None if self.last_spr_moved != card.spr: self.last_spr_moved = card.spr @@ -227,8 +246,13 @@ class Game(): self.release = None self.show_connected_tiles() + ''' if self.grid.cards_in_hand() == 0 and not self.playing_with_robot: self.grid.redeal(self.deck) + ''' + if self.hands[MY_HAND].cards_in_hand() == 0 and \ + not self.playing_with_robot: + self.hands[MY_HAND].deal(self.deck) return True def _game_over(self, msg=_('Game over')): @@ -268,11 +292,11 @@ class Game(): order = self.deck.random_order(ROW * COL) for i in range(ROW * COL): if self._connected(order[i]): - for tile in self.grid.robot_hand: + for tile in self.hands[ROBOT_HAND].hand: if self._try_placement(tile, order[i]): # Success, so remove tile from hand - self.grid.robot_hand[ - self.grid.robot_hand.index(tile)] = None + self.hands[ROBOT_HAND].hand[ + self.hands[ROBOT_HAND].hand.index(tile)] = None tile.spr.move(self.grid.grid_to_xy(order[i])) tile.spr.set_layer(CARDS) return @@ -280,9 +304,9 @@ class Game(): self.activity.set_robot_status(False, 'robot-off') # Show any tiles remaining in the robot's hand for i in range(COL): - if self.grid.robot_hand[i] is not None: - x, y = self.grid.robot_hand_to_xy(i) - self.grid.robot_hand[i].spr.move( + if self.hands[ROBOT_HAND].hand[i] is not None: + x, y = self.hands[ROBOT_HAND].hand_to_xy(i) + self.hands[ROBOT_HAND].hand[i].spr.move( (self.grid.left_hand + self.grid.xinc, y)) self._game_over(_('Robot unable to play')) @@ -14,6 +14,7 @@ import gtk from deck import Deck from card import blank_card +from utils import json_dump, json_load ROW = 8 COL = 8 @@ -30,18 +31,9 @@ class Grid: self.grid = [] self.blanks = [] - # the tiles in your hand - self.hand = [] - self.robot_hand = [] - self.robot_status = False - for i in range(ROW * COL): self.grid.append(None) - for i in range(COL): - self.hand.append(None) - self.robot_hand.append(None) - # card spacing self.left_hand = int(card_width / 2) self.left = int((width - (card_width * COL)) / 2 + card_width) @@ -54,73 +46,42 @@ class Grid: self.blanks[i].move(self.grid_to_xy(i)) self.blanks[i].set_layer(GRID) - def set_robot_status(self, status=False): - self.robot_status = status - def clear(self): for i in range(ROW * COL): self.grid[i] = None - for i in range(COL): - self.hand[i] = None - self.robot_hand[i] = None - - def deal(self, deck): - ''' Deal an initial set of cards to the hand ''' - for i in range(COL): - self.hand[i] = deck.deal_next_card() - self.place_a_card(self.hand[i], self.hand_to_xy(i)[0], - self.hand_to_xy(i)[1]) - if self.robot_status: - self.robot_hand[i] = deck.deal_next_card() - self.place_a_card(self.robot_hand[i], self.robot_hand_to_xy(i)[0], - self.robot_hand_to_xy(i)[1]) - - # ...and empty the grid. - for i in range(ROW * COL): - self.grid[i] = None - - def redeal(self, deck): - ''' Deal another set of cards to the hand ''' - for i in range(COL): - self.hand[i] = deck.deal_next_card() - self.place_a_card(self.hand[i], self.hand_to_xy(i)[0], - self.hand_to_xy(i)[1]) - if self.robot_status: - self.robot_hand[i] = deck.deal_next_card() - self.place_a_card(self.robot_hand[i], - self.robot_hand_to_xy(i)[0], - self.robot_hand_to_xy(i)[1]) - - def find_empty_slot(self): - ''' Is there an empty slot in the hand? ''' - for i in range(COL): - if self.hand[i] == None: - return i - return None - - def cards_in_hand(self): - ''' How many cards are in the hand? ''' - return COL - self.hand.count(None) - - def cards_in_robot_hand(self): - ''' How many cards are in the robot hand? ''' - return COL - self.robot_hand.count(None) def cards_in_grid(self): ''' How many cards are on the grid? ''' return ROW * COL - self.grid.count(None) - def restore(self, deck, saved_card_index): + def serialize(self): + ''' Serialize the grid for passing to share and saving ''' + grid = [] + for i in range(ROW * COL): + if self.grid[i] is not None: + grid.append([self.grid[i].number, self.grid[i].orientation]) + else: + grid.append([None, None]) + return json_dump(grid) + + def restore(self, grid_as_text, deck): ''' Restore cards to grid upon resume or share. ''' - # TODO: restore hand too self.hide() - j = 0 - for i in saved_card_index: - if i is None: - self.grid[j] = None + grid = json_load(grid_as_text) + for i in range(ROW * COL): + if grid[i][0] is None: + self.grid[i] = None else: - self.grid[j] = deck.index_to_card(i) - j += 1 + for k in range(ROW * COL): + if deck.cards[k].number == grid[i][0]: + self.grid[i] = deck.cards[k] + self.grid[i].spr.move(self.grid_to_xy(i)) + self.grid[i].spr.set_layer(CARDS) + o = grid[i][1] + while o > 0: + self.grid[i].rotate_clockwise() + o -= 90 + break self.show() def place_a_card(self, c, x, y): @@ -134,35 +95,15 @@ class Grid: return COL * int((y - self.top) / self.yinc) + \ int((x - self.left) / self.xinc) - def xy_to_hand(self, x, y): - ''' Convert from sprite x,y to hand index. ''' - return int((y - self.top) / self.yinc) - def grid_to_xy(self, i): ''' Convert from grid index to sprite x,y. ''' return (int((self.left + i % COL * self.xinc)), int((self.top + (i / COL) * self.yinc))) - def hand_to_xy(self, i): - ''' Convert from hand index to sprite x,y. ''' - return ((self.left_hand, (self.top + i * self.yinc))) - - def robot_hand_to_xy(self, i): - ''' Convert from hand index to sprite x,y. ''' - return ((-self.xinc, (self.top + i * self.yinc))) - def grid_to_spr(self, i): ''' Return the sprite in grid-position i. ''' return self.grid[i].spr - def hand_to_spr(self, i): - ''' Return the sprite in hand-position i. ''' - return self.hand[i].spr - - def robot_hand_to_spr(self, i): - ''' Return the sprite in robot-hand-position i. ''' - return self.robot_hand[i].spr - def spr_to_grid(self, spr): ''' Return the index of a sprite in grid. ''' for i in range(ROW * COL): @@ -170,13 +111,6 @@ class Grid: return(i) return None - def spr_to_hand(self, spr): - ''' Return the index of a sprite in hand. ''' - for i in range(COL): - if self.hand[i] is not None and self.hand[i].spr == spr: - return(i) - return None - def hide(self): ''' Hide all of the cards on the grid. ''' for i in range(ROW * COL): @@ -0,0 +1,106 @@ +#Copyright (c) 2011 Walter Bender + +# 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 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gtk + +from utils import json_dump, json_load + +ROW = 8 +COL = 8 +CARDS = 3 + + +class Hand: + ''' Class for managing COL matrix of cards ''' + + def __init__(self, card_width, card_height, robot=False): + # the tiles in your hand + self.hand = [] + self.robot = robot # Does this hand belong to the robot? + + for i in range(COL): + self.hand.append(None) + + # card spacing + self.xinc = int(card_width) + if self.robot: + self.left = -self.xinc + else: + self.left = int(card_width / 2) + self.top = 0 + self.yinc = int(card_height) + print 'hand: left = %d, top = %d' % (self.left, self.top) + + def clear(self): + for i in range(COL): + self.hand[i] = None + + def deal(self, deck): + ''' Deal an initial set of cards to the hand ''' + for i in range(COL): + self.hand[i] = deck.deal_next_card() + self.hand[i].spr.move(self.hand_to_xy(i)) + self.hand[i].spr.set_layer(CARDS) + + def find_empty_slot(self): + ''' Is there an empty slot in the hand? ''' + for i in range(COL): + if self.hand[i] == None: + return i + return None + + def cards_in_hand(self): + ''' How many cards are in the hand? ''' + return COL - self.hand.count(None) + + def serialize(self): + ''' Serialize the hand for passing to share and saving ''' + hand = [] + for i in range( COL): + if self.hand[i] is not None: + hand.append(self.hand[i].number) + else: + hand.append(None) + return json_dump(hand) + + def restore(self, hand_as_text, deck): + ''' Restore cards to hand upon resume or share. ''' + hand = json_load(hand_as_text) + for i in range(COL): + if hand[i] is None: + self.hand[i] = None + else: + for k in range(ROW * COL): + if deck.cards[k].number == hand[i]: + self.hand[i] = deck.cards[k] + self.hand[i].spr.move(self.hand_to_xy(i)) + self.hand[i].spr.set_layer(CARDS) + break + + def xy_to_hand(self, x, y): + ''' Convert from sprite x,y to hand index. ''' + return int((y - self.top) / self.yinc) + + def hand_to_xy(self, i): + ''' Convert from hand index to sprite x,y. ''' + return ((self.left, (self.top + i * self.yinc))) + + def hand_to_spr(self, i): + ''' Return the sprite in hand-position i. ''' + return self.hand[i].spr + + def spr_to_hand(self, spr): + ''' Return the index of a sprite in hand. ''' + for i in range(COL): + if self.hand[i] is not None and self.hand[i].spr == spr: + return(i) + return None diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..39298e3 --- /dev/null +++ b/utils.py @@ -0,0 +1,56 @@ +#Copyright (c) 2011 Walter Bender + +# 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 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +from StringIO import StringIO +try: + OLD_SUGAR_SYSTEM = False + import json + json.dumps + from json import load as jload + from json import dump as jdump +except (ImportError, AttributeError): + try: + import simplejson as json + from simplejson import load as jload + from simplejson import dump as jdump + except: + OLD_SUGAR_SYSTEM = True + + +def json_load(text): + """ Load JSON data using what ever resources are available. """ + if OLD_SUGAR_SYSTEM is True: + listdata = json.read(text) + else: + # strip out leading and trailing whitespace, nulls, and newlines + clean_text = text.lstrip() + clean_text = clean_text.replace('\12', '') + clean_text = clean_text.replace('\00', '') + io = StringIO(clean_text.rstrip()) + try: + listdata = jload(io) + except ValueError: + # assume that text is ascii list + listdata = text.split() + for i, value in enumerate(listdata): + listdata[i] = int(value) + return listdata + +def json_dump(data): + """ Save data using available JSON tools. """ + if OLD_SUGAR_SYSTEM is True: + return json.write(data) + else: + _io = StringIO() + jdump(data, _io) + return _io.getvalue() + |