diff --git a/unobot.py b/unobot.py index 7ac4895..994aa63 100644 --- a/unobot.py +++ b/unobot.py @@ -63,6 +63,9 @@ 'DONT_HAVE': "You don't have that card!", 'DOESNT_PLAY': "That card can't be played now.", 'UNO': "UNO! %s has ONE card left!", + 'CHALLENGE_FALSE': "Challenging failure to call UNO does not make sense at this time.", + 'CHALLENGE_TRUE': "%s caught %s forgetting to call UNO! Two penalty cards dealt.", + 'CHALLENGE_NONE': "%s holds more than one card. Challenge is void.", 'WIN': "We have a winner: %s!!! This game took %s", 'DRAWN_ALREADY': "You've already drawn, either play or pass.", 'DRAWN_CARD': "You drew: %s", @@ -128,6 +131,7 @@ def __init__(self, trigger): self.way = 1 self.drawn = NO self.smallestHand = DECK_SIZE + self.unoCalled = NO self.deck = [] self.startTime = None @@ -249,12 +253,42 @@ def play(self, bot, trigger): self.inc_player() self.card_played(bot, playcard) - if len(self.players[self.playerOrder[pl]]) == 1: - bot.say(STRINGS['UNO'] % self.playerOrder[pl]) - elif len(self.players[self.playerOrder[pl]]) == 0: + if len(self.players[self.playerOrder[pl]]) == 0: return WIN self.show_on_turn(bot) + def call_uno(self, bot, trigger): + if not self.dealt: + return + + caller = trigger.nick + if caller not in (self.playerOrder[self.currentPlayer], self.playerOrder[self.previousPlayer]): + # only the current or previous player can call UNO + bot.say(STRINGS['ON_TURN'] % self.playerOrder[self.currentPlayer]) + return + if self.unoCalled == caller: + # UNO was already called this turn + return + self.unoCalled = caller + bot.say(STRINGS['UNO'] % caller) + + def challenge_uno(self, bot, trigger): + if not self.dealt: + return + + prev = self.playerOrder[self.previousPlayer] + if len(self.players[prev]) == 1: + if self.unoCalled == prev: + bot.say(STRINGS['CHALLENGE_FALSE']) + return + else: + bot.say(STRINGS['CHALLENGE_TRUE'] % (trigger.nick, prev)) + z = [self.get_card(), self.get_card()] + self.players[prev].extend(z) + bot.notice(STRINGS['DRAWN_CARD'] % self.render_cards(bot, z, prev), prev) + else: + bot.say(STRINGS['CHALLENGE_NONE'] % prev) + def draw(self, bot, trigger): if not self.deck: return @@ -479,6 +513,9 @@ def inc_player(self): self.currentPlayer = 0 if self.currentPlayer < 0: self.currentPlayer = len(self.players) - 1 + if self.unoCalled != self.previousPlayer: + # Reset once it's too late to challenge a missed UNO call + self.unoCalled = NO def remove_player(self, bot, player): if len(self.players) == 1: @@ -606,6 +643,16 @@ def play(self, bot, trigger): bot.say(STRINGS['WIN'] % (winner, game_duration)) self.game_ended(bot, trigger, winner) + def call_uno(self, bot, trigger): + if trigger.sender not in self.games: + return + self.games[trigger.sender].call_uno(bot, trigger) + + def challenge_uno(self, bot, trigger): + if trigger.sender not in self.games: + return + self.games[trigger.sender].challenge_uno(bot, trigger) + def draw(self, bot, trigger): if trigger.sender not in self.games: return @@ -881,6 +928,20 @@ def unoplay(bot, trigger): unobot.play(bot, trigger) +@module.rule('^uno!?$') +@module.priority('high') +@module.require_chanmsg +def unocall(bot, trigger): + unobot.call_uno(bot, trigger) + + +@module.commands('unofail') +@module.priority('medium') +@module.require_chanmsg +def unofail(bot, trigger): + unobot.challenge_uno(bot, trigger) + + @module.commands('draw') @module.priority('medium') @module.require_chanmsg