diff options
Diffstat (limited to 'game.py')
-rw-r--r-- | game.py | 386 |
1 files changed, 386 insertions, 0 deletions
@@ -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) |