Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter 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)
commit0279518276390439777a351a770c9e98b23d6ab3 (patch)
tree6ff4e6612f2575f1661750e8b7ae8275e9f7c0f1
parentcb523a3e3f4687e49f1c900898f3659e8b92fd97 (diff)
refactoring in anticipation of sharing
-rw-r--r--PathsActivity.py83
-rw-r--r--deck.py27
-rw-r--r--game.py62
-rw-r--r--grid.py118
-rw-r--r--hand.py106
-rw-r--r--utils.py56
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:
diff --git a/deck.py b/deck.py
index b6428a8..c16d37c 100644
--- a/deck.py
+++ b/deck.py
@@ -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. '''
diff --git a/game.py b/game.py
index 735bd78..a3c3ec4 100644
--- a/game.py
+++ b/game.py
@@ -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'))
diff --git a/grid.py b/grid.py
index 1f6ed84..78a2d4d 100644
--- a/grid.py
+++ b/grid.py
@@ -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):
diff --git a/hand.py b/hand.py
new file mode 100644
index 0000000..7b99b26
--- /dev/null
+++ b/hand.py
@@ -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()
+