From 6e426b4a243fdc2aa52f3abff8c3302ef7fb33f1 Mon Sep 17 00:00:00 2001 From: Simon Schampijer Date: Thu, 05 Jul 2007 13:20:43 +0000 Subject: - moved the gamestate into the model - added the state of each tile to avoid flipping of already selected tiles - some smaller fixes --- diff --git a/controller.py b/controller.py index dc446aa..ec588fc 100644 --- a/controller.py +++ b/controller.py @@ -9,7 +9,6 @@ from dbus.service import method, signal from dbus.gobject_service import ExportedGObject from model import Model -from gamestate import GameState # XXX: I'm not convinced this is in the right namespace SERVICE = "org.freedesktop.Telepathy.Tube.Memosono" @@ -19,8 +18,9 @@ PATH = "/org/freedesktop/Telepathy/Tube/Memosono" GAME_PATH = os.path.join(os.path.dirname(__file__),'games/drumgit') +MAX_NUM_PLAYERS = 2 -_logger = logging.getLogger('memosono-activity.game') +_logger = logging.getLogger('controller') class Controller(ExportedGObject): @@ -40,56 +40,51 @@ class Controller(ExportedGObject): self.owner = owner self._get_buddy = get_buddy self.activity = activity - - self.model = None - self.playerid = None + self.numplayers = 0 self.turn = 0 - # index 0 is the master - self.players = [] - self.started = 0 - self.count = 0 + if self.is_initiator: - self.gs = GameState() + self.init_game() + for tile in self.pv.tiles: tile.connect('button-press-event', self._button_press_cb, self.pv.tiles.index(tile)) + self.tube.watch_participants(self.participant_change_cb) + def participant_change_cb(self, added, removed): - # Initiator is player 0, other player is player 1. _logger.debug('adding participants: %r', added) _logger.debug('removing participants: %r', removed) for handle, bus_name in added: buddy = self._get_buddy(handle) - _logger.debug('Buddy %r was added', buddy) if buddy is not None: - if len(self.players) < 2: + _logger.debug('buddy %r was added', buddy) + if self.numplayers < MAX_NUM_PLAYERS: self.buddies_panel.add_player(buddy) - self.players.append(self.tube.participants[handle]) - if self.is_initiator: - self.gs.points[self.tube.participants[handle]] = 0 - _logger.debug('MA: points of players: %s', self.gs.points) - _logger.debug('MA: list of players: %s', self.players) + self.numplayers+=1 + if self.is_initiator: + self.model.players[self.tube.participants[handle]] = [buddy.props.nick, 0] + _logger.debug('list of players: %s', self.model.players) else: - self.buddies_panel.add_watcher(buddy) - + self.info_panel.show('we are already two players') + for handle in removed: buddy = self._get_buddy(handle) - _logger.debug('Buddy %r was removed', buddy) if buddy is not None: - self.buddies_panel.remove_watcher(buddy) - try: - self.players.remove(self.tube.participants[handle]) - except ValueError: - # already absent - pass - - if not self.entered: - if self.is_initiator: - _logger.debug('I am the initiator, so making myself the leader of the game.') - self.init_game() + _logger.debug('buddy %r was removed', buddy) + self.buddies_panel.remove_player(buddy) + self.numplayers-=1 + if self.is_initiator: + try: + del self.model.players[self.tube.participants[handle]] + except ValueError: + # already absent + pass + + if not self.entered: self.playerid = self.tube.get_unique_name() self.tube.add_signal_receiver(self.info_cb, 'Info', IFACE, path=PATH, sender_keyword='sender') @@ -99,22 +94,24 @@ class Controller(ExportedGObject): path=PATH, sender_keyword='sender') self.tube.add_signal_receiver(self.points_cb, 'Points', IFACE, path=PATH, sender_keyword='sender') - self.entered = True + self.entered = True + if self.is_initiator: - if len(self.players) == 2 and self.started == 0: - _logger.debug('Start the game.') - self.Info('Start the game') - self.started = 1 - self.Turn(self.players[self.gs.player_active]) + if len(self.model.players) == 2 and self.model.started == 0: + _logger.debug('start the game') + self.Info('start the game') + self.model.started = 1 + self.change_turn() - def init_game(self): + def init_game(self): + _logger.debug('I am the initiator, so making myself the leader of the game.') self.model = Model(GAME_PATH, os.path.dirname(__file__)) self.model.read('drumgit.mson') self.model.def_grid() - self.tube.add_signal_receiver(self.selected_cb, 'Selected', IFACE, path=PATH, sender_keyword='sender') + @signal(dbus_interface=IFACE, signature='n') def Selected(self, tilenum): @@ -123,24 +120,34 @@ class Controller(ExportedGObject): def selected_cb(self, tilenum, sender=None): _logger.debug('MA: %s flipped tile %d', sender, tilenum) obj, color = self.model.gettile(tilenum) - self.Flip(tilenum, obj, color) + if self.model.grid[tilenum][2] == 1: + self.Info('selected already') + else: + self.Flip(tilenum, obj, color) - self.count+=1 - if self.count == 1: - self.gs.selected = tilenum - if self.count == 2: - self.count = 0 - # evaluate - if( self.model.same(tilenum, self.gs.selected) == 1): - _logger.debug('MA: Tile(%d) and (%d) are the same', tilenum, self.gs.selected) - self.gs.points[sender]+=1 - self.Points(sender, self.gs.points[sender]) - self.info_panel.show('Open another one') - else: - gobject.timeout_add(2000, self._turn_back, tilenum, self.gs.selected) - _logger.debug('Tile(%d) and (%d) are NOT the same', tilenum, self.gs.selected) - # next player - self.change_turn() + self.model.count+=1 + if self.model.count == 1: + self.model.selected = tilenum + self.model.grid[tilenum][2] = 1 + return + if self.model.count == 2: + self.model.count = 0 + # evaluate + if( self.model.same(tilenum, self.model.selected) == 1): + _logger.debug('MA: Tile(%d) and (%d) are the same', tilenum, self.model.selected) + self.model.grid[tilenum][2] = 1 + self.model.grid[self.model.selected][2] = 1 + + self.model.players[sender][1]+=1 + self.Points(sender, self.model.players[sender][1]) + self.Info('found pair, one more try') + else: + self.model.grid[tilenum][2] = 0 + self.model.grid[self.model.selected][2] = 0 + self.change_turn() + self.Info('pair does not match, next player') + gobject.timeout_add(2000, self._turn_back, tilenum, self.model.selected) + _logger.debug('Tile(%d) and (%d) are NOT the same', tilenum, self.model.selected) def _turn_back(self, tilenuma, tilenumb): self.Flip(tilenuma, 'images/black.png', 100) @@ -148,12 +155,13 @@ class Controller(ExportedGObject): return False def change_turn(self): - if self.gs.player_active == 0: - self.gs.player_active = 1 + if self.model.player_active < (len(self.model.players)-1): + self.model.player_active+=1 else: - self.gs.player_active = 0 - - self.Turn(self.players[self.gs.player_active]) + self.model.player_active = 0 + + key = self.model.players.keys()[self.model.player_active] + self.Turn(key, self.model.players[key][0]) @signal(dbus_interface=IFACE, signature='nsn') @@ -166,17 +174,16 @@ class Controller(ExportedGObject): self.pv.flip(tilenum, os.path.join(os.path.dirname(__file__), obj), color) - @signal(dbus_interface=IFACE, signature='s') - def Turn(self, playerid): + @signal(dbus_interface=IFACE, signature='ss') + def Turn(self, playerid, name): """Signal that it is the players turn""" - def turn_cb(self, playerid, sender=None): + def turn_cb(self, playerid, name, sender=None): if self.playerid == playerid: self.turn = 1 - self.info_panel.show('It is my turn') else: - self.turn = 0 - + self.turn = 0 + self.info_panel.show('hey %s it is your turn'%name) @signal(dbus_interface=IFACE, signature='sn') def Points(self, player, points): diff --git a/gamestate.py b/gamestate.py deleted file mode 100644 index a3e40c9..0000000 --- a/gamestate.py +++ /dev/null @@ -1,13 +0,0 @@ - - -class GameState(object): - ''' Used by the leader of the game to keep track of the game state - ''' - - def __init__(self): - self.player_active = 0 - self.points = {} - self.turn = 0 - self.selected = 0 - - diff --git a/memosonoactivity.py b/memosonoactivity.py index 3bdc63f..47b60a8 100755 --- a/memosonoactivity.py +++ b/memosonoactivity.py @@ -39,12 +39,13 @@ from infopanel import InfoPanel from controller import Controller +_logger = logging.getLogger('activity') class MemosonoActivity(Activity): def __init__(self, handle): Activity.__init__(self, handle) - logging.debug('Starting Memosono activity...') + _logger.debug('Starting Memosono activity...') self.set_title(_('Memsosono Activity')) @@ -114,19 +115,19 @@ class MemosonoActivity(Activity): def _get_buddy(self, cs_handle): """Get a Buddy from a channel specific handle.""" - logging.debug('Trying to find owner of handle %u...', cs_handle) + _logger.debug('Trying to find owner of handle %u...', cs_handle) group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] my_csh = group.GetSelfHandle() - logging.debug('My handle in that group is %u', my_csh) + _logger.debug('My handle in that group is %u', my_csh) if my_csh == cs_handle: handle = self.conn.GetSelfHandle() - logging.debug('CS handle %u belongs to me, %u', cs_handle, handle) + _logger.debug('CS handle %u belongs to me, %u', cs_handle, handle) elif group.GetGroupFlags() & telepathy.CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES: handle = group.GetHandleOwners([cs_handle])[0] - logging.debug('CS handle %u belongs to %u', cs_handle, handle) + _logger.debug('CS handle %u belongs to %u', cs_handle, handle) else: handle = cs_handle - logging.debug('non-CS handle %u belongs to itself', handle) + _logger.debug('non-CS handle %u belongs to itself', handle) # XXX: deal with failure to get the handle owner assert handle != 0 @@ -137,7 +138,7 @@ class MemosonoActivity(Activity): self.tp_conn_path, handle) def _shared_cb(self, activity): - logging.debug('My Memosono activity was shared') + _logger.debug('My Memosono activity was shared') self.initiating = True self._setup() @@ -147,17 +148,17 @@ class MemosonoActivity(Activity): self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) self._shared_activity.connect('buddy-left', self._buddy_left_cb) - logging.debug('This is my activity: making a tube...') + _logger.debug('This is my activity: making a tube...') id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferTube( telepathy.TUBE_TYPE_DBUS, 'org.fredektop.Telepathy.Tube.Memosono', {}) - logging.debug('Tube address: %s', self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].GetDBusServerAddress(id)) + _logger.debug('Tube address: %s', self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].GetDBusServerAddress(id)) self.info_panel.show('Waiting for another player to join') # FIXME: presence service should be tubes-aware and give us more help # with this def _setup(self): if self._shared_activity is None: - logging.error('Failed to share or join activity') + _logger.error('Failed to share or join activity') return bus_name, conn_path, channel_paths = self._shared_activity.get_channels() @@ -170,27 +171,27 @@ class MemosonoActivity(Activity): channel = telepathy.client.Channel(bus_name, channel_path) htype, handle = channel.GetHandle() if htype == telepathy.HANDLE_TYPE_ROOM: - logging.debug('Found our room: it has handle#%d "%s"', + _logger.debug('Found our room: it has handle#%d "%s"', handle, self.conn.InspectHandles(htype, [handle])[0]) room = handle ctype = channel.GetChannelType() if ctype == telepathy.CHANNEL_TYPE_TUBES: - logging.debug('Found our Tubes channel at %s', channel_path) + _logger.debug('Found our Tubes channel at %s', channel_path) tubes_chan = channel elif ctype == telepathy.CHANNEL_TYPE_TEXT: - logging.debug('Found our Text channel at %s', channel_path) + _logger.debug('Found our Text channel at %s', channel_path) text_chan = channel if room is None: - logging.error("Presence service didn't create a room") + _logger.error("Presence service didn't create a room") return if text_chan is None: - logging.error("Presence service didn't create a text channel") + _logger.error("Presence service didn't create a text channel") return # Make sure we have a Tubes channel - PS doesn't yet provide one if tubes_chan is None: - logging.debug("Didn't find our Tubes channel, requesting one...") + _logger.debug("Didn't find our Tubes channel, requesting one...") tubes_chan = self.conn.request_channel(telepathy.CHANNEL_TYPE_TUBES, telepathy.HANDLE_TYPE_ROOM, room, True) @@ -205,7 +206,7 @@ class MemosonoActivity(Activity): self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): - logging.error('ListTubes() failed: %s', e) + _logger.error('ListTubes() failed: %s', e) def _joined_cb(self, activity): if self.ctrl is not None: @@ -217,18 +218,18 @@ class MemosonoActivity(Activity): for buddy in self._shared_activity.get_joined_buddies(): self.buddies_panel.add_watcher(buddy) - logging.debug('Joined an existing Memosono game') + _logger.debug('Joined an existing Memosono game') self.info_panel.show('Joined a game. Waiting for my turn...') self.initiating = False self._setup() - logging.debug('This is not my activity: waiting for a tube...') + _logger.debug('This is not my 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) def _new_tube_cb(self, id, initiator, type, service, params, state): - logging.debug('New tube: ID=%d initator=%d type=%d service=%s ' + _logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', id, initiator, type, service, params, state) @@ -245,11 +246,11 @@ class MemosonoActivity(Activity): self._get_buddy, self) def _buddy_joined_cb(self, activity, buddy): - logging.debug('buddy joined') + _logger.debug('buddy joined') self.buddies_panel.add_watcher(buddy) def _buddy_left_cb(self, activity, buddy): - logging.debug('buddy left') + _logger.debug('buddy left') self.buddies_panel.remove_watcher(buddy) diff --git a/model.py b/model.py index 581be15..5ba6909 100644 --- a/model.py +++ b/model.py @@ -5,6 +5,8 @@ import random IMAGES_PATH = 'games/drumgit/images' +_logger = logging.getLogger('model') + class Model(object): ''' The model of the activity. Contains methods to read and save the configuration for a game from xml. Stores the pairs and grid @@ -12,19 +14,29 @@ class Model(object): ''' def __init__(self, gamepath, dtdpath, name='noname'): self.name = name - self.pairs = {} - self.grid = [] self.gamepath = gamepath self.dtdpath = dtdpath - try: self.dtd = libxml2.parseDTD(None, os.path.join(self.dtdpath, 'memosono.dtd')) except libxml2.parserError, e: - logging.error('No memosono.dtd found ' +str(e)) + _logger.error('No memosono.dtd found ' +str(e)) self.dtd = None self.ctxt = libxml2.newValidCtxt() + + self.pairs = {} + self.grid = [] + # used by the leader of the game to keep track of the game state + self.players = {} + self.player_active = 0 + self.selected = 0 + self.turn = 0 + self.started = 0 + self.count = 0 + + def read(self, filename): + ''' reades the configuration from an xml file ''' try: doc = libxml2.parseFile(os.path.join(self.gamepath, filename)) if doc.validateDtd(self.ctxt, self.dtd): @@ -55,12 +67,14 @@ class Model(object): self.pairs[idpair] = pair xpa.xpathFreeContext() else: - logging.error('Error in validation of the file') + _logger.error('Error in validation of the file') doc.freeDoc() except libxml2.parserError, e: - logging.error('Error parsing file ' +str(e)) + _logger.error('Error parsing file ' +str(e)) + def save(self, filename): + ''' saves the configuration to an xml file ''' doc = libxml2.newDoc("1.0") root = doc.newChild(None, "memosono", None) root.setProp("name", self.name) @@ -76,47 +90,34 @@ class Model(object): doc.saveFormatFile(filename, 1) doc.freeDoc() + def def_grid(self): - print 'pairs: %s' %self.pairs - ### create grid from pairs information + ''' create the grid for the play from the pairs information + and shuffles the grid so they always appear in a different + place + ''' + _logger.debug(' pairs: %s', self.pairs) for key in self.pairs.iterkeys(): - self.grid.append((key, 0)) - self.grid.append((key, 1)) - print 'self.grid: %s'%self.grid - - ### shuffle the grid tiles + self.grid.append([key, 0, 0]) + self.grid.append([key, 1, 0]) + random.shuffle(self.grid) - print 'self.grid after shufle: %s'%self.grid + _logger.debug(' grid: %s', self.grid) + def gettile(self, tilenum): - pairkey, moch = self.grid[tilenum] + ''' gets the information of an object associated with a tile number ''' + pairkey, moch, state = self.grid[tilenum] obj = os.path.join(IMAGES_PATH, self.pairs[pairkey][moch]) color = self.pairs[pairkey][2] - # logger.debug('obj=%s color=%s'%(obj, color)) return (obj, color) + def same(self, a, b): - pairkeya, moch = self.grid[a] - pairkeyb, moch = self.grid[b] + ''' checks wether two tiles are matching ''' + pairkeya, moch, state = self.grid[a] + pairkeyb, moch, state = self.grid[b] return (pairkeya == pairkeyb) - -if __name__ == '__main__': - - print "[Read game from file] " - model = Model() - model.read('memosono.xml') - print " name=" + model.name - print " pairs=%s" %model.pairs - - elemkey = '0' - if model.pairs.has_key(elemkey): - del model.pairs[elemkey] - - model.pairs['2'] = ['frettchen.jpg', 'frettchen.wav'] - - print "[Write game to file] " - model.save('memosono.xml') - -- cgit v0.9.1