Add :Deck support
This commit is contained in:
parent
ef0bef0bcc
commit
34e397a9db
2 changed files with 33 additions and 13 deletions
|
@ -8,14 +8,8 @@ default_timeout = 10
|
||||||
class CodeValidationError(Exception): pass
|
class CodeValidationError(Exception): pass
|
||||||
|
|
||||||
def check_code(code):
|
def check_code(code):
|
||||||
def accepted_character(char):
|
if not code.isalnum():
|
||||||
# Upper case letters and numbers are allowed
|
raise CodeValidationError('Code %s contains disallowed characters (0-9 A-Z a-z are allowed)' % code)
|
||||||
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)
|
|
||||||
|
|
||||||
def request(base_url, additional, timeout):
|
def request(base_url, additional, timeout):
|
||||||
if base_url is None:
|
if base_url is None:
|
||||||
|
|
36
gameloop.py
36
gameloop.py
|
@ -5,6 +5,7 @@ from collections import namedtuple
|
||||||
import cardcast_api
|
import cardcast_api
|
||||||
|
|
||||||
# TODO: rando
|
# TODO: rando
|
||||||
|
# TODO: https://dl.puckipedia.com/colondeck{,/cards}
|
||||||
|
|
||||||
class events(enum.Enum):
|
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)
|
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
|
nonlocal players
|
||||||
|
|
||||||
send(', '.join(sorted(players)))
|
send(', '.join(sorted(players)))
|
||||||
|
# TODO: Add bots
|
||||||
|
|
||||||
def add_deck(code):
|
def add_deck(code):
|
||||||
nonlocal decks
|
nonlocal decks
|
||||||
assert code not in 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
|
# 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
|
# Extract the information we want to keep of the deck
|
||||||
name = info['name']
|
name = info['name']
|
||||||
author = info['author']['username']
|
author = info['author']['username']
|
||||||
call_count = int(info['call_count'])
|
|
||||||
response_count = int(info['response_count'])
|
|
||||||
|
|
||||||
# Get cards
|
# 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 _
|
# Preprocess calls so that ___ becomes only one _
|
||||||
# _ are indicated by splitting the card at that point, e.g.
|
# _ 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:
|
if card is not None and card.deck.code == code:
|
||||||
player.hand[index] = None
|
player.hand[index] = None
|
||||||
|
|
||||||
|
# TODO: Remove from bots
|
||||||
|
|
||||||
if round_call_card is not None and round_call_card.deck.code == code:
|
if round_call_card is not None and round_call_card.deck.code == code:
|
||||||
round_call_card = None
|
round_call_card = None
|
||||||
|
|
||||||
|
@ -332,10 +343,11 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
deck_add_handler('A5DCM')
|
deck_add_handler('A5DCM')
|
||||||
|
|
||||||
elif rest[0] == 'offtopia':
|
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('A5DCM')
|
||||||
deck_add_handler('PXWKC')
|
deck_add_handler('PXWKC')
|
||||||
|
deck_add_handler('colondeck')
|
||||||
|
|
||||||
deck_add_random_handler()
|
deck_add_random_handler()
|
||||||
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:
|
if len(player.hand) < 10:
|
||||||
need_responses += 10 - len(player.hand)
|
need_responses += 10 - len(player.hand)
|
||||||
need_responses += player.hand.count(None)
|
need_responses += player.hand.count(None)
|
||||||
|
# TODO: Add bot hooks
|
||||||
|
|
||||||
# If we don't have enough, kick back to setup
|
# If we don't have enough, kick back to setup
|
||||||
available_responses = total_responses()
|
available_responses = total_responses()
|
||||||
|
@ -514,6 +527,7 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
if player.hand[index] is None:
|
if player.hand[index] is None:
|
||||||
player.hand[index] = responses.pop()
|
player.hand[index] = responses.pop()
|
||||||
|
# TODO: Add bot hooks
|
||||||
|
|
||||||
return top_of_round
|
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('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))
|
send('[%s]' % '_'.join(sanitize(part) for part in round_call_card.text))
|
||||||
|
|
||||||
|
# TODO: Bot plays
|
||||||
|
|
||||||
for nick in players:
|
for nick in players:
|
||||||
if players[nick] is not czar:
|
if players[nick] is not czar:
|
||||||
send_cards(nick)
|
send_cards(nick)
|
||||||
|
@ -693,6 +709,7 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
# Yes, restart round
|
# Yes, restart round
|
||||||
send('Lost a card from player\'s hand, restarting round')
|
send('Lost a card from player\'s hand, restarting round')
|
||||||
return setup_round
|
return setup_round
|
||||||
|
# TODO: Consider bots
|
||||||
|
|
||||||
else:
|
else:
|
||||||
r = common_handler(event, args)
|
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))
|
choosers = random.sample(card_choices.keys(), k = len(card_choices))
|
||||||
for index, player in enumerate(choosers):
|
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]])))
|
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:
|
while True:
|
||||||
if len(players) < 2:
|
if len(players) < 2:
|
||||||
|
@ -750,6 +768,7 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
czar = player
|
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]])))
|
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
|
break
|
||||||
|
|
||||||
|
@ -761,6 +780,7 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
# and randomize czar
|
# and randomize czar
|
||||||
for player in card_choices:
|
for player in card_choices:
|
||||||
player.points += 1
|
player.points += 1
|
||||||
|
# TODO: Consider bots
|
||||||
|
|
||||||
# If we set czar to None, setup_round()
|
# If we set czar to None, setup_round()
|
||||||
# will handle ramdomizing it for us
|
# will handle ramdomizing it for us
|
||||||
|
@ -784,6 +804,7 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
for index, player in enumerate(choosers):
|
for index, player in enumerate(choosers):
|
||||||
answer_origins = [player.hand[i].deck.code for i in card_choices[player]]
|
answer_origins = [player.hand[i].deck.code for i in card_choices[player]]
|
||||||
answers_origins.append('%i: %s' % (index, ', '.join(answer_origins)))
|
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)))
|
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
|
# Yes, restart round
|
||||||
send('Lost a card played this round, restarting round')
|
send('Lost a card played this round, restarting round')
|
||||||
return setup_round
|
return setup_round
|
||||||
|
# TODO: Consider bots
|
||||||
|
|
||||||
else:
|
else:
|
||||||
r = common_handler(event, args)
|
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)))
|
points.append('%s: %i (%i)' % (player.nick, player.points, choosers.index(player)))
|
||||||
else:
|
else:
|
||||||
points.append('%s: %i' % (player.nick, player.points))
|
points.append('%s: %i' % (player.nick, player.points))
|
||||||
|
# TODO: Handle bots
|
||||||
|
|
||||||
send('Points: %s' % ' | '.join(points))
|
send('Points: %s' % ' | '.join(points))
|
||||||
|
|
||||||
|
@ -829,11 +852,13 @@ def game(send, notice, voice, devoice, get_event):
|
||||||
elif limit.type == limit_types.points:
|
elif limit.type == limit_types.points:
|
||||||
if max(i.points for i in players.values()) >= limit.number:
|
if max(i.points for i in players.values()) >= limit.number:
|
||||||
return end_game
|
return end_game
|
||||||
|
# TODO: Handle bots
|
||||||
|
|
||||||
# Remove the cards that were played this round from hands
|
# Remove the cards that were played this round from hands
|
||||||
for player in card_choices:
|
for player in card_choices:
|
||||||
for index in card_choices[player]:
|
for index in card_choices[player]:
|
||||||
player.hand[index] = None
|
player.hand[index] = None
|
||||||
|
# TODO: Consider bots
|
||||||
|
|
||||||
# Increase the number of the round and clear the call card
|
# Increase the number of the round and clear the call card
|
||||||
# These are not done in setup_round() since we might want to
|
# 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():
|
def end_game():
|
||||||
nonlocal players
|
nonlocal players
|
||||||
|
|
||||||
|
# TODO: Handle bots
|
||||||
max_score = max(i.points for i in players.values())
|
max_score = max(i.points for i in players.values())
|
||||||
|
|
||||||
winners = [i for i in players.values() if i.points == max_score]
|
winners = [i for i in players.values() if i.points == max_score]
|
||||||
|
|
Loading…
Reference in a new issue