diff --git a/cardcast_api.py b/cardcast_api.py index 962ed98..b96e6d0 100644 --- a/cardcast_api.py +++ b/cardcast_api.py @@ -8,14 +8,8 @@ default_timeout = 10 class CodeValidationError(Exception): pass def check_code(code): - def accepted_character(char): - # Upper case letters and numbers are allowed - return ord('A') <= ord(char) <= ord('Z') or ord('0') <= ord(char) <= ord('9') - - if len(code) != 5: - raise CodeValidationError('Code %s not 5 characters long' % code) - elif any(not accepted_character(char) for char in code): - raise CodeValidationError('Code %s contains disallowed characters (0-9 and A-Z are allowed' % code) + if not code.isalnum(): + raise CodeValidationError('Code %s contains disallowed characters (0-9 A-Z a-z are allowed)' % code) def request(base_url, additional, timeout): if base_url is None: diff --git a/gameloop.py b/gameloop.py index 058ff8b..3bb8904 100644 --- a/gameloop.py +++ b/gameloop.py @@ -5,6 +5,7 @@ from collections import namedtuple import cardcast_api # TODO: rando +# TODO: https://dl.puckipedia.com/colondeck{,/cards} class events(enum.Enum): quit, nick_change, status, start, ready, unready, kill, join, leave, players, kick, deck_add, deck_add_random, deck_remove, deck_list, limit, card, cards, origins = range(19) @@ -70,22 +71,30 @@ def game(send, notice, voice, devoice, get_event): nonlocal players send(', '.join(sorted(players))) + # TODO: Add bots def add_deck(code): nonlocal decks assert code not in decks + # Colondeck lives elsewhere + if code == 'colondeck': + base_url = 'https://dl.puckipedia.com/' + else: + base_url = None + # First get info for the deck we're adding - info = cardcast_api.info(code) + info = cardcast_api.info(code, base_url = base_url) # Extract the information we want to keep of the deck name = info['name'] author = info['author']['username'] - call_count = int(info['call_count']) - response_count = int(info['response_count']) # Get cards - calls, responses = cardcast_api.cards(code) + calls, responses = cardcast_api.cards(code, base_url = base_url) + + call_count = len(calls) + response_count = len(responses) # Preprocess calls so that ___ becomes only one _ # _ are indicated by splitting the card at that point, e.g. @@ -141,6 +150,8 @@ def game(send, notice, voice, devoice, get_event): if card is not None and card.deck.code == code: player.hand[index] = None + # TODO: Remove from bots + if round_call_card is not None and round_call_card.deck.code == code: round_call_card = None @@ -332,10 +343,11 @@ def game(send, notice, voice, devoice, get_event): deck_add_handler('A5DCM') elif rest[0] == 'offtopia': - send('Adding the default CAH deck (A5DCM), offtopia injoke deck (PXWKC), and three random decks') + send('Adding the default CAH deck (A5DCM), offtopia injoke deck (PXWKC), :Deck (colondeck) and three random decks') deck_add_handler('A5DCM') deck_add_handler('PXWKC') + deck_add_handler('colondeck') deck_add_random_handler() deck_add_random_handler() @@ -493,6 +505,7 @@ def game(send, notice, voice, devoice, get_event): if len(player.hand) < 10: need_responses += 10 - len(player.hand) need_responses += player.hand.count(None) + # TODO: Add bot hooks # If we don't have enough, kick back to setup available_responses = total_responses() @@ -514,6 +527,7 @@ def game(send, notice, voice, devoice, get_event): for index in range(10): if player.hand[index] is None: player.hand[index] = responses.pop() + # TODO: Add bot hooks return top_of_round @@ -578,6 +592,8 @@ def game(send, notice, voice, devoice, get_event): send('Round %i. %s is czar. %s choose your cards' % (round_number, czar.nick, ', '.join(i.nick for i in choosers))) send('[%s]' % '_'.join(sanitize(part) for part in round_call_card.text)) + # TODO: Bot plays + for nick in players: if players[nick] is not czar: send_cards(nick) @@ -693,6 +709,7 @@ def game(send, notice, voice, devoice, get_event): # Yes, restart round send('Lost a card from player\'s hand, restarting round') return setup_round + # TODO: Consider bots else: r = common_handler(event, args) @@ -709,6 +726,7 @@ def game(send, notice, voice, devoice, get_event): choosers = random.sample(card_choices.keys(), k = len(card_choices)) for index, player in enumerate(choosers): send('%i: %s' % (index, combine_cards(round_call_card.text, [player.hand[i].text for i in card_choices[player]]))) + # TODO: Consider bots while True: if len(players) < 2: @@ -750,6 +768,7 @@ def game(send, notice, voice, devoice, get_event): czar = player send('The winner is %s with: %s' % (player.nick, combine_cards(round_call_card.text, [player.hand[i].text for i in card_choices[player]]))) + # TODO: Consider bots break @@ -761,6 +780,7 @@ def game(send, notice, voice, devoice, get_event): # and randomize czar for player in card_choices: player.points += 1 + # TODO: Consider bots # If we set czar to None, setup_round() # will handle ramdomizing it for us @@ -784,6 +804,7 @@ def game(send, notice, voice, devoice, get_event): for index, player in enumerate(choosers): answer_origins = [player.hand[i].deck.code for i in card_choices[player]] answers_origins.append('%i: %s' % (index, ', '.join(answer_origins))) + # TODO: Consider bots notice(nick, 'call: %s; %s' % (round_call_card.deck.code, '; '.join(answers_origins))) @@ -803,6 +824,7 @@ def game(send, notice, voice, devoice, get_event): # Yes, restart round send('Lost a card played this round, restarting round') return setup_round + # TODO: Consider bots else: r = common_handler(event, args) @@ -814,6 +836,7 @@ def game(send, notice, voice, devoice, get_event): points.append('%s: %i (%i)' % (player.nick, player.points, choosers.index(player))) else: points.append('%s: %i' % (player.nick, player.points)) + # TODO: Handle bots send('Points: %s' % ' | '.join(points)) @@ -829,11 +852,13 @@ def game(send, notice, voice, devoice, get_event): elif limit.type == limit_types.points: if max(i.points for i in players.values()) >= limit.number: return end_game + # TODO: Handle bots # Remove the cards that were played this round from hands for player in card_choices: for index in card_choices[player]: player.hand[index] = None + # TODO: Consider bots # Increase the number of the round and clear the call card # These are not done in setup_round() since we might want to @@ -847,6 +872,7 @@ def game(send, notice, voice, devoice, get_event): def end_game(): nonlocal players + # TODO: Handle bots max_score = max(i.points for i in players.values()) winners = [i for i in players.values() if i.points == max_score]