diff options
author | Walter Bender <walter.bender@gmail.com> | 2011-03-25 14:25:43 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2011-03-25 14:25:43 (GMT) |
commit | f27c2d874f082082c5f39c492f1f3013a5de7429 (patch) | |
tree | 0e3f6efc2e0361b88365e615dc967bf021ecbce3 /game.py | |
parent | 751eef0bb55aa840ba4077cd9115390cf7cc12c9 (diff) |
added give hint to toolbar
Diffstat (limited to 'game.py')
-rw-r--r-- | game.py | 331 |
1 files changed, 176 insertions, 155 deletions
@@ -41,51 +41,51 @@ ROBOT_HAND = 1 class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): - self.activity = parent + self._activity = parent self.colors = colors # Starting from command line if parent is None: - self.running_sugar = False - self.canvas = canvas + self._running_sugar = False + self._canvas = canvas else: - self.running_sugar = True - self.canvas = canvas + self._running_sugar = True + self._canvas = canvas parent.show_all() - self.canvas.set_flags(gtk.CAN_FOCUS) - self.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) - self.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) - self.canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) - self.canvas.connect("expose-event", self._expose_cb) - self.canvas.connect("button-press-event", self._button_press_cb) - self.canvas.connect("button-release-event", self._button_release_cb) - self.canvas.connect("motion-notify-event", self._mouse_move_cb) - self.canvas.connect("key_press_event", self._keypress_cb) - - self.width = gtk.gdk.screen_width() - self.height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) - self.scale = self.height / (8.0 * CARD_HEIGHT) - self.card_width = CARD_WIDTH * self.scale - self.card_height = CARD_HEIGHT * self.scale + self._canvas.set_flags(gtk.CAN_FOCUS) + self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self._canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) + self._canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) + self._canvas.connect("expose-event", self._expose_cb) + self._canvas.connect("button-press-event", self._button_press_cb) + self._canvas.connect("button-release-event", self._button_release_cb) + self._canvas.connect("motion-notify-event", self._mouse_move_cb) + self._canvas.connect("key_press_event", self._keypress_cb) + + self._width = gtk.gdk.screen_width() + self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) + self._scale = self._height / (8.0 * CARD_HEIGHT) + self.card_width = CARD_WIDTH * self._scale + self.card_height = CARD_HEIGHT * self._scale # Generate the sprites we'll need... - self.sprites = Sprites(self.canvas) - self.grid = Grid(self.sprites, self.width, self.height, - self.card_width, self.card_height, self.scale, + self._sprites = Sprites(self._canvas) + self.grid = Grid(self._sprites, self._width, self._height, + self.card_width, self.card_height, self._scale, colors[0]) - self.deck = Deck(self.sprites, self.scale, colors[1]) + self.deck = Deck(self._sprites, self._scale, colors[1]) self.deck.board.move((self.grid.left, self.grid.top)) self.hands = [] self.hands.append(Hand(self.card_width, self.card_height)) - self.errormsg = [] + self._errormsg = [] for i in range(4): - self.errormsg.append(error_card(self.sprites)) - self.highlight = highlight_cards(self.sprites, self.scale) + self._errormsg.append(error_card(self._sprites)) + self._highlight = highlight_cards(self._sprites, self._scale) # and initialize a few variables we'll need. self.buddies = [] - self.my_hand = MY_HAND + self._my_hand = MY_HAND self.playing_with_robot = False self._all_clear() @@ -100,20 +100,20 @@ class Game(): hand.clear() self.show_connected_tiles() - self.press = None - self.release = None - self.dragpos = [0, 0] - self.total_drag = [0, 0] + self._press = None + self._release = None + self._dragpos = [0, 0] + self._total_drag = [0, 0] self.last_spr_moved = None - self.last_tile_played = None - self.last_tile_orientation = 0 - self.last_grid_played = None + self._last_tile_played = None + self._last_tile_orientation = 0 + self._last_grid_played = None self.whos_turn = MY_HAND - self.waiting_for_my_turn = False - self.waiting_for_robot = False + self._waiting_for_my_turn = False + self._waiting_for_robot = False self.placed_a_tile = False - self.there_are_errors = False + self._there_are_errors = False def new_game(self, saved_state=None, deck_index=0): ''' Start a new game. ''' @@ -122,26 +122,26 @@ class Game(): self._all_clear() # If we are not sharing or we are the sharer... - if not self.we_are_sharing() or self.activity.initiating: + if not self.we_are_sharing() or self._activity.initiating: if not self.we_are_sharing(): print 'We are not sharing.' - if not self.activity.initiating: + if not self._activity.initiating: print 'I am initiating.' # Let joiners know we are starting a new game... if self.we_are_sharing(): print 'sending a new_game event' - self.activity.send_event('n| ') + self._activity.send_event('n| ') # The initiator shuffles the deck... self.deck.shuffle() # ...and shares it. if self.we_are_sharing(): print 'sending a new deck event' - self.activity.send_event('d|%s' % (self.deck.serialize())) + self._activity.send_event('d|%s' % (self.deck.serialize())) # Deal a hand to yourself... print 'dealing myself a hand' - self.hands[self.my_hand].deal(self.deck) + self.hands[self._my_hand].deal(self.deck) # ...deal a hand to the robot... if self.playing_with_robot: @@ -153,12 +153,12 @@ class Game(): # ...or deal hands to the joiners. elif len(self.buddies) > 1: for i, buddy in enumerate(self.buddies): - if buddy != self.activity.nick: + if buddy != self._activity.nick: self.hands.append(Hand( self.card_width, self.card_height, remote=True)) self.hands[i].deal(self.deck) print 'dealing %s a hand' % (buddy) - self.activity.send_event('h|%s' % \ + self._activity.send_event('h|%s' % \ (self.hands[i].serialize(buddy=buddy))) # As initiator, you take the first turn. @@ -166,8 +166,8 @@ class Game(): # If we are joining, we need to wait for a hand. else: - self.my_hand = self.buddies.index(self.activity.nick) - print 'my hand is %d' % (self.my_hand) + self._my_hand = self.buddies.index(self._activity.nick) + print 'my hand is %d' % (self._my_hand) print 'Waiting for hand from the sharer and a turn to play.' self.its_their_turn(self.buddies[1]) # Sharer will be buddy 1 @@ -178,8 +178,8 @@ class Game(): def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' - if self.running_sugar: - self.activity.status.set_label(string) + if self._running_sugar: + self._activity.status.set_label(string) elif hasattr(self, 'win'): self.win.set_title('%s: %s' % (_('Paths'), string)) @@ -188,56 +188,56 @@ class Game(): # I need to play a piece... self.placed_a_tile = False # and I am no longer waiting for my turn. - self.waiting_for_my_turn = False + self._waiting_for_my_turn = False # If I don't have any tiles left, time to redeal. - if self.hands[self.my_hand].cards_in_hand() == 0: + if self.hands[self._my_hand].cards_in_hand() == 0: self._redeal() - if self.running_sugar: - self.activity.dialog_button.set_icon('dialog-ok') - self.activity.dialog_button.set_tooltip( + if self._running_sugar: + self._activity.dialog_button.set_icon('dialog-ok') + self._activity.dialog_button.set_tooltip( _('Click after taking your turn.')) - self._set_label(self.activity.nick + ': ' + _('It is your turn.')) + self._set_label(self._activity.nick + ': ' + _('It is your turn.')) def _redeal(self): # Only the sharer deals cards. if not self.we_are_sharing(): - self.hands[self.my_hand].deal(self.deck) + self.hands[self._my_hand].deal(self.deck) if self.playing_with_robot: self.hands[ROBOT_HAND].deal(self.deck) - if self.hands[self.my_hand].cards_in_hand() == 0: - if self.running_sugar: - self.activity.dialog_button.set_icon('dialog-cancel') - self.activity.dialog_button.set_tooltip(_('Game over')) + if self.hands[self._my_hand].cards_in_hand() == 0: + if self._running_sugar: + self._activity.dialog_button.set_icon('dialog-cancel') + self._activity.dialog_button.set_tooltip(_('Game over')) self._set_label(_('Game over')) - elif self.activity.initiating: + elif self._activity.initiating: for i, buddy in enumerate(self.buddies): print 'dealing %s a hand' % (buddy) self.hands[i].deal(self.deck) # Send the joiners their new hands. - if buddy != self.activity.nick: - self.activity.send_event('h|%s' % \ + if buddy != self._activity.nick: + self._activity.send_event('h|%s' % \ (self.hands[i].serialize(buddy=buddy))) def took_my_turn(self): # Did I complete my turn without any errors? - if self.there_are_errors: + if self._there_are_errors: self._set_label(_('There are errors -- it is still your turn.')) return # Are there any completed paths? print 'testing for completed tiles' - # self._test_for_complete_paths(self.grid.spr_to_grid(self.press)) - self._test_for_complete_paths(self.last_grid_played) + # self._test_for_complete_paths(self.grid.spr_to_grid(self._press)) + self._test_for_complete_paths(self._last_grid_played) # If so, let everyone know what piece I moved. if self.we_are_sharing(): - self.activity.send_event('p|%s' % \ - (json_dump([self.last_tile_played, - self.last_tile_orientation, - self.last_grid_played]))) + self._activity.send_event('p|%s' % \ + (json_dump([self._last_tile_played, + self._last_tile_orientation, + self._last_grid_played]))) # I took my turn, so I am waiting again. - self.waiting_for_my_turn = True + self._waiting_for_my_turn = True if self.last_spr_moved is not None: self.last_spr_moved.set_layer(CARDS) self.last_spr_moved = None @@ -247,7 +247,7 @@ class Game(): if self.playing_with_robot: self.its_their_turn(_('robot')) - self.waiting_for_robot = True + self._waiting_for_robot = True gobject.timeout_add(1000, self._robot_turn) elif not self.we_are_sharing(): self.its_my_turn() @@ -260,52 +260,52 @@ class Game(): def its_their_turn(self, nick): # It is someone else's turn. print 'waiting for ', nick - if self.running_sugar: - self.activity.dialog_button.set_icon('dialog-cancel') - self.activity.dialog_button.set_tooltip(_('Wait your turn.')) + if self._running_sugar: + self._activity.dialog_button.set_icon('dialog-cancel') + self._activity.dialog_button.set_tooltip(_('Wait your turn.')) self._set_label(_('Waiting for') + ' ' + nick) - self.waiting_for_my_turn = True # I am still waiting. + self._waiting_for_my_turn = True # I am still waiting. def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) - self.dragpos = [x, y] - self.total_drag = [0, 0] + self._dragpos = [x, y] + self._total_drag = [0, 0] - spr = self.sprites.find_sprite((x, y)) + spr = self._sprites.find_sprite((x, y)) # If it is not my turn, do nothing. - if self.waiting_for_my_turn: + if self._waiting_for_my_turn: print "Waiting for my turn -- ignoring button press." - self.press = None + self._press = None return - self.release = None + self._release = None # Ignore clicks on background except to indicate you took your turn if spr is None or spr in self.grid.blanks or spr == self.deck.board: if self.placed_a_tile and spr is None: print 'placed a tile and clicked on None' self.took_my_turn() - self.press = None + self._press = None return True # Are we clicking on a tile in the hand? - if self.hands[self.my_hand].spr_to_hand(spr) is not None and \ - not self.there_are_errors: + if self.hands[self._my_hand].spr_to_hand(spr) is not None and \ + not self._there_are_errors: self.last_spr_moved = spr clicked_in_hand = True if self.placed_a_tile: print 'placed a tile and clicked in hand' - self.press = None + self._press = None self.took_my_turn() else: clicked_in_hand = False # We cannot switch to an old tile. if spr == self.last_spr_moved: - self.press = spr + self._press = spr spr.set_layer(TOP) self._show_highlight() @@ -313,118 +313,120 @@ class Game(): def _mouse_move_cb(self, win, event): """ Drag a tile with the mouse. """ - spr = self.press + spr = self._press if spr is None: - self.dragpos = [0, 0] + self._dragpos = [0, 0] return True win.grab_focus() x, y = map(int, event.get_coords()) - dx = x - self.dragpos[0] - dy = y - self.dragpos[1] + dx = x - self._dragpos[0] + dy = y - self._dragpos[1] spr.move_relative([dx, dy]) self._move_highlight([dx, dy]) - self.dragpos = [x, y] - self.total_drag[0] += dx - self.total_drag[1] += dy + self._dragpos = [x, y] + self._total_drag[0] += dx + self._total_drag[1] += dy def _button_release_cb(self, win, event): win.grab_focus() - self.dragpos = [0, 0] + self._dragpos = [0, 0] - if self.waiting_for_my_turn: + if self._waiting_for_my_turn: print "waiting for my turn -- ignoring button release" return - if self.press is None: + if self._press is None: return x, y = map(int, event.get_coords()) - spr = self.sprites.find_sprite((x, y)) + spr = self._sprites.find_sprite((x, y)) grid_pos = self.grid.xy_to_grid(x, y) - hand_pos = self.hands[self.my_hand].xy_to_hand(x, y) + hand_pos = self.hands[self._my_hand].xy_to_hand(x, y) if grid_pos is not None: # Placing tile in grid if self.grid.grid[grid_pos] is None: - card = self.deck.spr_to_card(self.press) + card = self.deck.spr_to_card(self._press) card.spr.move(self.grid.grid_to_xy(grid_pos)) - i = self.grid.spr_to_grid(self.press) + i = self.grid.spr_to_grid(self._press) if i is not None: self.grid.grid[i] = None self.grid.grid[grid_pos] = card self.placed_a_tile = True - self.last_tile_played = card.number - self.last_grid_played = grid_pos + self._last_tile_played = card.number + self._last_grid_played = grid_pos - i = self.hands[self.my_hand].spr_to_hand(self.press) + i = self.hands[self._my_hand].spr_to_hand(self._press) if i is not None: - self.hands[self.my_hand].hand[i] = None + self.hands[self._my_hand].hand[i] = None if self.last_spr_moved != card.spr: self.last_spr_moved = card.spr self._show_highlight() elif hand_pos is not None: # Returning tile to hand - i = self.hands[self.my_hand].find_empty_slot() + i = self.hands[self._my_hand].find_empty_slot() print 'found an empty slot?', i if i is not None: - card = self.deck.spr_to_card(self.press) - card.spr.move(self.hands[self.my_hand].hand_to_xy(i)) - if self.hands[self.my_hand].spr_to_hand(self.press) is not None: - self.hands[self.my_hand].hand[ - self.hands[self.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.hands[self.my_hand].hand[i] = card + card = self.deck.spr_to_card(self._press) + card.spr.move(self.hands[self._my_hand].hand_to_xy(i)) + if self.hands[self._my_hand].spr_to_hand( + self._press) is not None: + self.hands[self._my_hand].hand[ + self.hands[self._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.hands[self._my_hand].hand[i] = card if spr == self.last_spr_moved: self.last_spr_moved = None self._hide_errormsgs() self._there_are_errors = False self.show_connected_tiles() else: # Or return tile to the grid - grid_pos = self.grid.spr_to_grid(self.press) + grid_pos = self.grid.spr_to_grid(self._press) if grid_pos is not None: - card = self.deck.spr_to_card(self.press) + card = self.deck.spr_to_card(self._press) card.spr.move(self.grid.grid_to_xy(grid_pos)) self._hide_highlight() - self.press = None - self.release = None + self._press = None + self._release = None self.placed_a_tile = False return True - self.release = spr - if self.press == self.release and not self._it_is_a_drag(): # Rotate + self._release = spr + if self._press == self._release and not self._it_is_a_drag(): # Rotate card = self.deck.spr_to_card(spr) card.rotate_clockwise() - self.last_tile_orientation = card.orientation + self._last_tile_orientation = card.orientation if self.last_spr_moved != card.spr: self.last_spr_moved = card.spr self._show_highlight() if hand_pos is None and x < self.grid.left: # In limbo: return to grid - grid_pos = self.grid.spr_to_grid(self.press) + grid_pos = self.grid.spr_to_grid(self._press) if grid_pos is not None: - card = self.deck.spr_to_card(self.press) + card = self.deck.spr_to_card(self._press) card.spr.move(self.grid.grid_to_xy(grid_pos)) self._hide_highlight() - self._test_for_bad_paths(self.grid.spr_to_grid(self.press)) + self._test_for_bad_paths(self.grid.spr_to_grid(self._press)) self.show_connected_tiles() - self.press = None - self.release = None + self._press = None + self._release = None return True def _it_is_a_drag(self): - if self.total_drag[0] * self.total_drag[0] + \ - self.total_drag[1] * self.total_drag[1] > \ + if self._total_drag[0] * self._total_drag[0] + \ + self._total_drag[1] * self._total_drag[1] > \ self.card_width * self.card_height: return True return False def _game_over(self, msg=_('Game over')): self._set_label(msg) - if self.running_sugar: - self.activity.robot_button.set_icon('robot-off') + if self._running_sugar: + self._activity.robot_button.set_icon('robot-off') def show_connected_tiles(self): ''' Highlight the squares that surround the tiles already on the grid. @@ -452,6 +454,22 @@ class Game(): if tile % ROW > 0 and self.grid.grid[tile + OFFSETS[3]] is not None: return True + def give_a_hint(self): + ''' Try to find an open place on the grid for any tile in my_hand. ''' + order = self.deck.random_order(ROW * COL) + for i in range(ROW * COL): + if self._connected(order[i]): + for tile in self.hands[self._my_hand].hand: + if self._try_placement(tile, order[i]): + # Success, so give hint. + self.grid.grid[order[i]] = None + self._show_highlight( + pos=self.grid.grid_to_xy(order[i])) + print 'hint: %d' % (order[i]) + return + # Nowhere to play. + self._set_label(_('Nowhere to play. Game over')) + def _robot_play(self): ''' The robot tries random cards in random locations. ''' # TODO: strategy try to complete paths @@ -465,19 +483,19 @@ class Game(): self.hands[ROBOT_HAND].hand.index(tile)] = None tile.spr.move(self.grid.grid_to_xy(order[i])) tile.spr.set_layer(CARDS) - self.waiting_for_robot = False + self._waiting_for_robot = False return # If we didn't return above, we were unable to play a tile. - if self.running_sugar: - self.activity.set_robot_status(False, 'robot-off') + if self._running_sugar: + self._activity.set_robot_status(False, 'robot-off') # At the end of the game, show any tiles remaining in the robot's hand. for i in range(COL): 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.waiting_for_robot = False + self._waiting_for_robot = False self._game_over(_('Robot unable to play')) def _try_placement(self, tile, i): @@ -487,7 +505,7 @@ class Game(): self.grid.grid[i] = tile for j in range(4): self._test_for_bad_paths(i) - if not self.there_are_errors: + if not self._there_are_errors: return True tile.rotate_clockwise() self.grid.grid[i] = None @@ -591,7 +609,7 @@ class Game(): def _test_for_bad_paths(self, tile): ''' Is there a path to nowhere? ''' self._hide_errormsgs() - self.there_are_errors = False + self._there_are_errors = False if tile is not None: self._check_card(tile, [int(tile / COL), 0], NORTH, tile + OFFSETS[0]) @@ -622,51 +640,54 @@ class Game(): def _display_errormsg(self, i, direction): ''' Display an error message where and when appropriate. ''' - if self.press is not None: + if self._press is not None: dxdy = [[0.375, -0.125], [0.875, 0.375], [0.375, 0.875], [-0.125, 0.375]] - x, y = self.press.get_xy() - self.errormsg[direction].move( + x, y = self._press.get_xy() + self._errormsg[direction].move( (x + dxdy[direction][0] * self.card_width, y + dxdy[direction][1] * self.card_height)) - self.errormsg[direction].set_layer(OVER_THE_TOP) - self.there_are_errors = True + self._errormsg[direction].set_layer(OVER_THE_TOP) + self._there_are_errors = True def _hide_errormsgs(self): ''' Hide all the error messages. ''' for i in range(4): - self.errormsg[i].move((self.grid.left, self.grid.top)) - self.errormsg[i].set_layer(HIDE) + self._errormsg[i].move((self.grid.left, self.grid.top)) + self._errormsg[i].set_layer(HIDE) def _hide_highlight(self): ''' No tile is selected. ''' for i in range(4): - self.highlight[i].move((self.grid.left, self.grid.top)) - self.highlight[i].set_layer(HIDE) + self._highlight[i].move((self.grid.left, self.grid.top)) + self._highlight[i].set_layer(HIDE) def _move_highlight(self, pos): for i in range(4): - self.highlight[i].move_relative(pos) + self._highlight[i].move_relative(pos) - def _show_highlight(self): + def _show_highlight(self, pos=None): ''' Highlight the tile that is selected. ''' - if self.last_spr_moved is None: + if self.last_spr_moved is None and pos is None: self._hide_highlight() else: - x, y = self.last_spr_moved.get_xy() - self.highlight[0].move((x, y)) - self.highlight[1].move((x + 7 * self.card_width / 8, y)) - self.highlight[2].move((x + 7 * self.card_width / 8, + if pos is None: + x, y = self.last_spr_moved.get_xy() + else: # Giving a hint. + x, y = pos + self._highlight[0].move((x, y)) + self._highlight[1].move((x + 7 * self.card_width / 8, y)) + self._highlight[2].move((x + 7 * self.card_width / 8, y + 7 * self.card_height / 8)) - self.highlight[3].move((x, y + 7 * self.card_height / 8)) + self._highlight[3].move((x, y + 7 * self.card_height / 8)) for i in range(4): - self.highlight[i].set_layer(OVER_THE_TOP) + self._highlight[i].set_layer(OVER_THE_TOP) def _keypress_cb(self, area, event): return True def _expose_cb(self, win, event): - self.sprites.redraw_sprites() + self._sprites.redraw_sprites() return True def _destroy_cb(self, win, event): |