Add :Deck support

This commit is contained in:
Juhani Krekelä 2019-05-10 18:01:05 +03:00
parent ef0bef0bcc
commit 34e397a9db
2 changed files with 33 additions and 13 deletions

View File

@ -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:

View File

@ -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]