class GamePlayScreen(Screen): numberofsets = NumericProperty(0) restart = ObjectProperty() screenManager = ObjectProperty() aiScore = NumericProperty() aiActivated = BooleanProperty() directory = StringProperty('') hintActivated = BooleanProperty(False) number_of_players = NumericProperty(1) name_of_players = ListProperty(['', '', '', '']) scores_of_players = ListProperty([0, 0, 0, 0]) cards = ListProperty() displayHintTimer = NumericProperty(5) aiPlayed = BooleanProperty(False) active = BooleanProperty(False) def __init__(self, *args, **kwargs): super(GamePlayScreen, self).__init__(*args, **kwargs) self.rotator = Rotator() Clock.schedule_once(self.post_init,0) def post_init(self,*args): self.buttons = self.ids.cards_layout.children for i in range(12): self.buttons[i].bind(on_press=self.checkIfSetOnBoard) # Dealing with multiplayer ### def select_player_popup(self, *args): '''called when three cards are selected''' popup = SelectPlayersPopup(self) popup.open() def on_pre_leave(self): self.endscreen = self.game.get_screen('end') self.endscreen.aiScore = self.aiScore self.active = False def unselectAll(self): ''' Unselect all the toggle buttons ''' for button in self.buttons: button.state = 'normal' def on_enter(self): ''' Sets the game ''' # You can only enter the game from the intro self.deck = Deck() self.cards = self.deck.drawGuarantee(numberofcards=12) for i in range(len(self.scores_of_players)): self.scores_of_players[i] = 0 self.ai = AI(self.directory) self.aiScore = 0 self.game.active = True self.active = True self.newRound() self.t0 = datetime.datetime.now() def goToSettings(self): Clock.unschedule(self.AIplay) Clock.unschedule(self.aiMoves) App.get_running_app().open_settings() def newRound(self): ''' What should be done at the begining of every round ''' self.stopRotation() self.updateGrid() self.setUpHint() self.unselectAll() self.setUpAI() def foundCorrect(self, down, *args): ''' Called once a shugou is found ''' self.aiUpdates() if self.aiPlayed: self.aiScore += 1 self.aiPlayed = False else: if self.number_of_players > 1: self.select_player_popup() else: self.scores_of_players[0] += 1 selectedcards = {self.cards[i] for i in down} try: newcards = self.deck.drawGuarantee( othercards=set(self.cards) ^ selectedcards, numberofcards=3) except ValueError: # no more shugous available self.game.current = 'end' return for index, i in enumerate(down): self.cards[i] = newcards[index] self.newRound() def checkIfSetOnBoard(self, obj): '''Called when a button is pressed, checks if there is a set. If there is one, then refill the display cards''' down = self.selected() if not len(down) == 3: return if Deck.checkSet(self.cards[down[0]], self.cards[down[1]], self.cards[down[2]]): if App.get_running_app().music.soundActivated: # Taken from: http://www.freesound.org/people/lukechalaudio/sounds/151568/ sound = SoundLoader.load("music/" + "151568__lukechalaudio__user-interface-generic" + ".wav") sound.loop = False sound.play() # We send the selection in case the player unselects a card before # self.foundCorrect is found self.stopRotation() Clock.schedule_once(lambda arg: self.foundCorrect(down=down), 2) else: # The cards were not a set self.unselectAll() def updateGrid(self): for i, card in enumerate(self.cards): self.buttons[i].card = card self.buttons[i].state = 'normal' self.setUpHint() self.t0 = datetime.datetime.now() if self.aiActivated: self.setUpAI() def aiUpdates(self): timeDifference = datetime.datetime.now() - self.t0 if self.aiPlayed: self.ai.time += 10 self.ai.updateRatingsAI( self.cards, self.aiCards, timeDifference) else: self.ai.time -= 7 if self.ai.time < 5: self.ai.time = 5 down = self.selected() # Crashes now, no idea why # selected = self.cards[down[0]], \ # self.cards[down[1]],\ # self.cards[down[2]] # self.ai.updateRatingsHuman( # self.cards, selected, timeDifference) def stopRotation(self): self.rotator.end_rotate() def selected(self): '''Returns the indices of all the selected ToggleButton''' down = [] for index, button in enumerate(self.buttons): if button.state == 'down': down.append(index) return down def buttonFromCard(self, card): ''' Returns the instance of the button that contains the given card''' for button in self.buttons: if button.card == card: return button def selectCards(self, cards): ''' selects the given cards if they are in the given cards ''' for index, button in enumerate(self.buttons): if self.cards[index] in cards: button.state = 'down' # Functions related to the AIhint ### def setUpAI(self): Clock.unschedule(self.AIplay) if self.aiActivated and self.active: (time, self.aiCards) = self.ai.suggestion(self.cards) Clock.schedule_once(self.AIplay, time) def AIplay(self, *arg): ''' The AI plays a turn ''' for index, card in enumerate(self.cards): if card in self.aiCards: self.buttons[index].state = 'down' else: self.buttons[index].state = 'normal' # Basic AI animation. Clock.schedule_once(self.aiMoves, 0.1) self.aiPlayed = True def aiMoves(self, *arg): self.checkIfSetOnBoard(None) # Functions related to displaying hint ### def on_displayHintTimer(self, obj, value): self.setUpHint() def setUpHint(self): ''' unschedule any current hint and loads up the next one if appropriate''' # Need to remove any previous call or else it might be activated too # quickly Clock.unschedule(self.displayHint) Clock.unschedule(self.displayHintSecond) # After some time in seconds show a hint if self.hintActivated and self.active: self.hint = Deck.hint(self.cards) Clock.schedule_once(self.displayHint, self.displayHintTimer) def on_hintActivated(self, obj, is_activated): if not is_activated: self.stopRotation() def displayHint(self, *arg): ''' Displays the first card in the hint and sets-up the display of the second card in the hint''' if self.selected() == []: # no cards have been selected # displays on the first card in a hint buttonToRotate = self.buttonFromCard(self.hint[0]) self.rotator.rotate_this(buttonToRotate) Clock.schedule_once(self.displayHintSecond, self.displayHintTimer) else: # if the player has a card selected, try calling it again later self.setUpHint() def displayHintSecond(self, *arg): ''' Displays the second of two cards in a hint''' selectedcards = self.selected() buttonToRotate = self.buttonFromCard(self.hint[1]) self.rotator.rotate_this(buttonToRotate) # Functions to handling the game play screen def selected(self): '''Returns the indices of all the selected ToggleButton''' down = [] for index, button in enumerate(self.buttons): if button.state == 'down': down.append(index) return down def stopClocks(self): Clock.unschedule(self.AIplay) Clock.unschedule(self.displayHint) Clock.unschedule(self.displayHintSecond)