Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/game.py
diff options
context:
space:
mode:
Diffstat (limited to 'game.py')
-rw-r--r--game.py386
1 files changed, 386 insertions, 0 deletions
diff --git a/game.py b/game.py
new file mode 100644
index 0000000..c8df347
--- /dev/null
+++ b/game.py
@@ -0,0 +1,386 @@
+# Copyright (C) 2006, 2007, 2008 One Laptop Per Child
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import logging
+import gobject
+from os.path import join
+
+from gettext import gettext as _
+from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT, GObject, timeout_add
+from gobject import source_remove
+
+from model import Model
+from audio import Audio
+import theme
+
+_logger = logging.getLogger('memorize-activity')
+
+SERVICE = 'org.laptop.Memorize'
+IFACE = SERVICE
+PATH = '/org/laptop/Memorize'
+
+
+class MemorizeGame(GObject):
+
+ __gsignals__ = {
+ 'reset_scoreboard': (SIGNAL_RUN_FIRST, None, []),
+ 'reset_table': (SIGNAL_RUN_FIRST, None, []),
+ 'load_mode': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'load_game': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ 'change_game': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ 'change_game_signal': (SIGNAL_RUN_FIRST, None, 5 * [TYPE_PYOBJECT]),
+ 'set-border': (SIGNAL_RUN_FIRST, None, 3 * [TYPE_PYOBJECT]),
+ 'flip-card': (SIGNAL_RUN_FIRST, None, [int, bool]),
+ 'flip-card-signal': (SIGNAL_RUN_FIRST, None, [int]),
+ 'cement-card': (SIGNAL_RUN_FIRST, None, [int]),
+ 'flop-card': (SIGNAL_RUN_FIRST, None, [int]),
+ 'highlight-card': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ 'add_buddy': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ 'rem_buddy': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'increase-score': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'wait_mode_buddy': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ 'msg_buddy': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ 'change-turn': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ }
+
+ def __init__(self):
+ gobject.GObject.__init__(self)
+ self.myself = None
+ self.players_score = {}
+ self.players = []
+ self.waiting_players = []
+ self.current_player = None
+ self.last_flipped = -1
+ self.last_highlight = 1
+ self._flop_card_timeout = -1
+ self.messenger = None
+ self.sentitive = True
+
+ self.model = Model()
+ self.flip_block = False
+ self._flop_cards = None
+
+ self.audio = Audio()
+
+ def load_game(self, game_name, size, mode):
+ self.set_load_mode('Loading game')
+ if self.model.read(game_name) == 0:
+ self.model.def_grid(size)
+ self.model.data['running'] = 'False'
+ self.model.data['mode'] = mode
+ logging.debug(' Read setup file %r: %r ',
+ game_name, self.model.grid)
+ self.emit('load_game', self.model.data, self.model.grid)
+ else:
+ logging.error(' Reading setup file %s', game_name)
+
+ def load_remote(self, grid, data, mode, signal = False):
+ self.set_load_mode(_('Loading game...'))
+ self.model.grid = grid
+ self.model.data = data
+ self.model.data['mode'] = mode
+ self.emit('reset_scoreboard')
+ if not signal:
+ self.emit('change_game_signal',
+ mode,
+ self.get_grid(),
+ self.model.data,
+ self.waiting_players,
+ self.model.data['game_file'])
+ self.emit('change_game', self.model.data, self.get_grid())
+ for buddy in self.players:
+ self.players_score[buddy] = 0
+ self.current_player = None
+ self.last_flipped = -1
+ self.last_highlight = 1
+ self.change_turn()
+ self.model.data['running'] = 'False'
+
+ for card in self.model.grid:
+ if card['state'] == '1':
+ self.emit('flip-card', self.model.grid.index(card), False)
+ self.last_flipped = self.model.grid.index(card)
+ elif card['state'] != '0':
+ stroke_color, fill_color = card['state'].split(',')
+ self.emit('flip-card', self.model.grid.index(card), False)
+ self.emit('set-border', self.model.grid.index(card),
+ stroke_color, fill_color)
+
+ def add_buddy(self, buddy, score = 0):
+ _logger.debug('Buddy %r was added to game', buddy.props.nick)
+ self.players.append(buddy)
+ self.players_score[buddy] = score
+ self.emit('add_buddy', buddy, score)
+ logging.debug(str(buddy))
+
+ if self.current_player == None:
+ self.current_player = buddy
+ self.change_turn()
+
+ def rem_buddy(self, buddy):
+ _logger.debug('Buddy %r was removed from game', buddy.props.nick)
+ if self.current_player == buddy and len(self.players) >= 2:
+ if self.last_flipped != -1:
+ self.emit('flop-card', self.last_flipped)
+ self.model.grid[self.last_flipped]['state'] = '0'
+ self.last_flipped = -1
+ self.change_turn()
+ index = self.players.index(buddy)
+ del self.players[index]
+ del (self.players_score[buddy])
+ self.emit('rem_buddy', buddy)
+
+ def buddy_message(self, buddy, text):
+ self.emit('msg_buddy', buddy, text)
+
+ def update_turn(self):
+ self.set_sensitive(self.current_player == self.myself)
+ self.emit('change-turn', self.current_player)
+
+ def change_turn(self):
+ if len(self.players) <= 1:
+ self.current_player = self.players[0]
+ if self.current_player == None:
+ self.current_player = self.players[0]
+ elif self.current_player == self.players[-1]:
+ self.current_player = self.players[0]
+ else:
+ next_player = self.players.index(self.current_player) + 1
+ self.current_player = self.players[next_player]
+ self.update_turn()
+
+ def card_overflipped(self, widget, identifier):
+ if self._flop_cards and identifier in self._flop_cards:
+ self.card_flipped(widget, identifier)
+
+ def card_flipped(self, widget, identifier, signal = False):
+ if self._flop_cards:
+ source_remove(self._flop_card_timeout)
+ self.flop_card(self._flop_cards[0], self._flop_cards[1])
+
+ # Check if is my turn
+ if (not self.sentitive and not signal) or \
+ self.last_flipped == identifier:
+ return
+
+ # Handle groups if needed
+ if self.model.data.get('divided') == '1':
+ if self.last_flipped == -1 and identifier \
+ >= (len(self.model.grid)/2):
+ return
+ if self.last_flipped != -1 and identifier \
+ < (len(self.model.grid)/2):
+ return
+
+ # do not process flips when flipping back
+ if self.flip_block:
+ return
+ else:
+ self.flip_block = True
+
+ self.model.data['running'] = 'True'
+
+ def flip_card(full_animation):
+ self.emit('flip-card', identifier, full_animation)
+ if not signal:
+ self.emit('flip-card-signal', identifier)
+
+ snd = self.model.grid[identifier].get('snd', None)
+ if snd != None:
+ sound_file = join(self.model.data.get('pathsnd'), snd)
+ self.audio.play(sound_file)
+
+ # First card case
+ if self.last_flipped == -1:
+ flip_card(full_animation=True)
+
+ self.last_flipped = identifier
+ self.model.grid[identifier]['state'] = '1'
+ self.flip_block = False
+
+ # Second card case
+ else:
+ # Pair matched
+ pair_key_1 = self.model.grid[self.last_flipped]['pairkey']
+ pair_key_2 = self.model.grid[identifier]['pairkey']
+
+ if pair_key_1 == pair_key_2:
+ flip_card(full_animation=False)
+
+ stroke_color, fill_color = \
+ self.current_player.props.color.split(',')
+ self.emit('set-border', identifier, stroke_color, fill_color)
+ self.emit('set-border', self.last_flipped,
+ stroke_color, fill_color)
+
+ self.increase_point(self.current_player)
+ self.model.grid[identifier]['state'] = \
+ self.current_player.props.color
+ self.model.grid[self.last_flipped]['state'] = \
+ self.current_player.props.color
+ self.flip_block = False
+
+ self.emit('cement-card', identifier)
+ self.emit('cement-card', self.last_flipped)
+
+ # Pair didn't match
+ else:
+ flip_card(full_animation=True)
+
+ self.model.grid[identifier]['state'] = '1'
+ self.set_sensitive(False)
+ self._flop_cards = (identifier, self.last_flipped)
+ self._flop_card_timeout = timeout_add(theme.FLOP_BACK_TIMEOUT,
+ self.flop_card, identifier, self.last_flipped)
+ self.last_flipped = -1
+
+ def new_buffer(self, buf):
+ buf = str(buf)
+ self.str_buffer = buf
+ tmp_val = self.max_samples - 1
+ self.integer_buffer = list(unpack(str(int(len(buf))/2)+'h',buf))
+ self.avg = self.integer_buffer[0]
+ if(len(self.main_buffers)>tmp_val):
+ del elf.main_buffers[0:(len(self.main_buffers)-tmp_val)]
+ self.main_buffers += self.integer_buffer
+ logging.debug(self.avg)
+ return True
+
+ def flop_card(self, identifier, identifier2):
+ self._flop_card_timeout = -1
+ self._flop_cards = None
+
+ self.emit('flop-card', identifier)
+ self.model.grid[identifier]['state'] = '0'
+ self.emit('flop-card', identifier2)
+ self.model.grid[identifier2]['state'] = '0'
+
+ #if self.model.data['divided'] == '1':
+ # self.card_highlighted(widget, -1, False)
+ self.set_sensitive(True)
+ self.flip_block = False
+ self.change_turn()
+
+ def card_highlighted(self, widget, identifier, mouse):
+ self.emit('highlight-card', self.last_highlight, False)
+ self.last_highlight = identifier
+
+ if identifier == -1 or not self.sentitive:
+ return
+
+ if self.model.data['divided'] == '1':
+ if self.last_flipped == -1 and identifier \
+ >= (len(self.model.grid)/2):
+ return
+ if self.last_flipped != -1 and identifier \
+ < (len(self.model.grid)/2):
+ return
+
+ if mouse and self.model.grid[identifier]['state'] == '0' or not mouse:
+ self.emit('highlight-card', identifier, True)
+
+
+ def increase_point(self, buddy, inc=1):
+ self.players_score[buddy] += inc
+ for i_ in range(inc):
+ self.emit('increase-score', buddy)
+
+ def get_grid(self):
+ return self.model.grid
+
+ def collect_data(self):
+ for player, score in self.players_score.items():
+ index = self.players.index(player)
+ score = self.players_score[player]
+ self.model.data[str(index)] = str(score)
+ return self.model.data
+
+ def change_game(self, widget, game_name, size, mode,
+ title = None, color= None):
+ if mode in ['file', 'demo']:
+ if self.model.read(game_name) != 0:
+ logging.error(' Reading setup file %s', game_name)
+ return
+ if size == None:
+ size = int(self.model.data['size'])
+ self.model.def_grid(size)
+
+ if title != None:
+ self.model.data['title'] = title
+ if color != None:
+ self.model.data['color'] = color
+ self.load_remote(self.model.grid, self.model.data, mode, False)
+
+ def reset_game(self, size = None):
+ if size == None:
+ size = int(self.model.data['size'])
+ self.model.def_grid(size)
+ self.load_remote(self.model.grid, self.model.data, False)
+
+ def set_load_mode(self, msg):
+ self.emit('load_mode', msg)
+
+ def set_messenger(self, messenger):
+ self.messenger = messenger
+
+ def set_sensitive(self, status):
+ self.sentitive = status
+ if not status:
+ self.emit('highlight-card', self.last_highlight, False)
+
+ def get_sensitive(self):
+ return self.sentitive
+
+ def get_current_player(self):
+ return self.current_player
+
+ def get_players_data(self):
+ data = []
+ for player, score in self.players_score.items():
+ data.append([player.props.key, player.props.nick,
+ player.props.color, score])
+ return data
+
+ def set_wait_list(self, wait_list):
+ self.waiting_players = wait_list
+ for w in wait_list:
+ for p in self.players:
+ if w[0] == p.props.key:
+ list.remove(w)
+ for i_ in range(w[3]):
+ self.increase_point(p)
+
+ def set_myself(self, buddy):
+ self.myself = buddy
+
+ def add_to_waiting_list(self, buddy):
+ self.players.remove(buddy)
+ self.waiting_players.append(buddy)
+ self.emit('wait_mode_buddy', buddy, True)
+
+ def rem_to_waiting_list(self, buddy):
+ self.waiting_players.remove(buddy)
+ self.players.append(buddy)
+ self.emit('wait_mode_buddy', buddy, False)
+
+ def load_waiting_list(self, wait_list):
+ for buddy in wait_list:
+ self.add_to_waiting_list(buddy)
+
+ def empty_waiting_list(self):
+ for buddy in self.waiting_players:
+ self.rem_to_waiting_list(buddy)