Added "Score Mode"
This commit is contained in:
parent
37a6c40ebe
commit
10b91f2c98
7 changed files with 177 additions and 7 deletions
75
actions.py
75
actions.py
|
@ -7,12 +7,12 @@ from datetime import datetime
|
|||
|
||||
from telegram import Message, Chat
|
||||
|
||||
from config import TIME_REMOVAL_AFTER_SKIP, MIN_FAST_TURN_TIME
|
||||
from config import TIME_REMOVAL_AFTER_SKIP, MIN_FAST_TURN_TIME, SCORE_WIN
|
||||
from errors import DeckEmptyError, NotEnoughPlayersError
|
||||
from internationalization import __, _
|
||||
from shared_vars import gm
|
||||
from user_setting import UserSetting
|
||||
from utils import send_async, display_name, game_is_running
|
||||
from utils import send_async, display_name, game_is_running, TIMEOUT
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -108,6 +108,77 @@ def do_play_card(bot, player, result_id):
|
|||
text=__("{name} won!", multi=game.translate)
|
||||
.format(name=user.first_name))
|
||||
|
||||
if game.mode == "score":
|
||||
game.add_score(player)
|
||||
score = sum([n[0] for n in game.last_round_score])
|
||||
bot.sendMessage(chat.id,
|
||||
text=__("Added {pt} point",
|
||||
"Added {pt} points",
|
||||
score)
|
||||
.format(pt=score))
|
||||
bot.sendMessage(
|
||||
chat.id,
|
||||
text=", ".join(
|
||||
["{cl} {vl} (+{pt})"
|
||||
.format(cl=c.COLOR_ICONS[n[1].color],
|
||||
vl=n[1].value or n[1].special,
|
||||
pt=n[0])
|
||||
for n in sorted(game.last_round_score,
|
||||
key=lambda x: x[0])]))
|
||||
bot.sendMessage(
|
||||
chat.id,
|
||||
text=__("Current standings:\n\n") +
|
||||
"\n".join([
|
||||
"{no}. {name}: {pt}".format(
|
||||
no=i + 1,
|
||||
name=x[0].user.first_name,
|
||||
pt=x[1])
|
||||
for i, x in enumerate(
|
||||
sorted(game.get_scores(),
|
||||
key=lambda x: x[1],
|
||||
reverse=True))]))
|
||||
bot.sendMessage(
|
||||
chat.id,
|
||||
text=__("Points to win: {score}").format(score=game.win_score))
|
||||
|
||||
players_cache = game.players
|
||||
highest = sorted(zip(players_cache, map(
|
||||
game.get_score, players_cache
|
||||
)), key=lambda x: x[1])[-1]
|
||||
if highest[1] >= game.win_score:
|
||||
send_async(bot, chat.id,
|
||||
text=__("Game ended! {name} wins the game!",
|
||||
multi=game.translate)
|
||||
.format(highest[0].user.first_name))
|
||||
if us.stats:
|
||||
us.first_places += 1
|
||||
for player in players_cache:
|
||||
us_ = UserSetting.get(id=player.user.id)
|
||||
if not us:
|
||||
us_ = UserSetting(id=player.user.id)
|
||||
us_.games_played += 1
|
||||
else:
|
||||
game.reset_cards()
|
||||
game.new_round()
|
||||
next_round_message = (
|
||||
__("Next round!", multi=game.translate))
|
||||
next_player_message = (
|
||||
__("First player: {name}\n",
|
||||
multi=game.translate)
|
||||
.format(name=display_name(game.current_player.user)))
|
||||
|
||||
bot.sendMessage(chat.id,
|
||||
text=next_round_message,
|
||||
timeout=TIMEOUT)
|
||||
bot.sendSticker(chat.id,
|
||||
sticker=c.STICKERS[str(game.last_card)],
|
||||
timeout=TIMEOUT)
|
||||
bot.sendMessage(chat.id,
|
||||
text=next_player_message,
|
||||
timeout=TIMEOUT)
|
||||
return
|
||||
# If game mode is "score", 'do_play_card' should stop here
|
||||
|
||||
if us.stats:
|
||||
us.games_played += 1
|
||||
|
||||
|
|
13
bot.py
13
bot.py
|
@ -30,13 +30,15 @@ import card as c
|
|||
import settings
|
||||
import simple_commands
|
||||
from actions import do_skip, do_play_card, do_draw, do_call_bluff, start_player_countdown
|
||||
from config import WAITING_TIME, DEFAULT_GAMEMODE, MIN_PLAYERS
|
||||
from config import (WAITING_TIME, DEFAULT_GAMEMODE, MIN_PLAYERS, SCORE_WIN,
|
||||
SCORE_DUEL, ADDITIONAL_POINT, PLAYER_THRESHOLD)
|
||||
from errors import (NoGameInChatError, LobbyClosedError, AlreadyJoinedError,
|
||||
NotEnoughPlayersError, DeckEmptyError)
|
||||
from internationalization import _, __, user_locale, game_locales
|
||||
from results import (add_call_bluff, add_choose_color, add_draw, add_gameinfo,
|
||||
add_no_game, add_not_started, add_other_cards, add_pass,
|
||||
add_card, add_mode_classic, add_mode_fast, add_mode_wild)
|
||||
add_card, add_mode_classic, add_mode_fast, add_mode_wild,
|
||||
add_mode_score)
|
||||
from shared_vars import gm, updater, dispatcher
|
||||
from simple_commands import help_handler
|
||||
from start_bot import start_bot
|
||||
|
@ -370,6 +372,12 @@ def start_game(bot, update, args, job_queue):
|
|||
"before you can start it").format(minplayers=MIN_PLAYERS))
|
||||
|
||||
else:
|
||||
# Set winning score
|
||||
player_num = len(game.players)
|
||||
if player_num == 2:
|
||||
game.win_score = SCORE_DUEL
|
||||
else:
|
||||
game.win_score = ADDITIONAL_POINT * player_num
|
||||
# Starting a game
|
||||
game.start()
|
||||
|
||||
|
@ -594,6 +602,7 @@ def reply_to_query(bot, update):
|
|||
add_mode_classic(results)
|
||||
add_mode_fast(results)
|
||||
add_mode_wild(results)
|
||||
add_mode_score(results)
|
||||
else:
|
||||
add_not_started(results)
|
||||
|
||||
|
|
5
card.py
5
card.py
|
@ -60,6 +60,11 @@ DRAW_FOUR = 'draw_four'
|
|||
|
||||
SPECIALS = (CHOOSE, DRAW_FOUR)
|
||||
|
||||
# Card score
|
||||
CARD_SCORES = {v: int(v) for v in VALUES[0:10]}
|
||||
CARD_SCORES.update({v: 15 for v in VALUES[10:13]})
|
||||
CARD_SCORES.update({SPECIALS[0]: 20, SPECIALS[1]: 25})
|
||||
|
||||
STICKERS = {
|
||||
'b_0': 'BQADBAAD2QEAAl9XmQAB--inQsYcLTsC',
|
||||
'b_1': 'BQADBAAD2wEAAl9XmQABBzh4U-rFicEC',
|
||||
|
|
|
@ -33,3 +33,7 @@ WAITING_TIME = config.get("waiting_time", 120)
|
|||
TIME_REMOVAL_AFTER_SKIP = config.get("time_removal_after_skip", 20)
|
||||
MIN_FAST_TURN_TIME = config.get("min_fast_turn_time", 15)
|
||||
MIN_PLAYERS = config.get("min_players", 2)
|
||||
SCORE_WIN = config.get("score_mode_win_score", 500)
|
||||
SCORE_DUEL = config.get("score_mode_win_duel", 100)
|
||||
ADDITIONAL_POINT = config.get("score_mode_win_per_player_additional", 100)
|
||||
PLAYER_THRESHOLD = config.get("score_mode_normal_score_threshold_player_count", 5)
|
54
game.py
54
game.py
|
@ -19,7 +19,8 @@
|
|||
|
||||
|
||||
import logging
|
||||
from config import ADMIN_LIST, OPEN_LOBBY, DEFAULT_GAMEMODE, ENABLE_TRANSLATIONS
|
||||
from config import (ADMIN_LIST, OPEN_LOBBY, DEFAULT_GAMEMODE,
|
||||
ENABLE_TRANSLATIONS, SCORE_WIN)
|
||||
from datetime import datetime
|
||||
|
||||
from deck import Deck
|
||||
|
@ -39,6 +40,9 @@ class Game(object):
|
|||
owner = ADMIN_LIST
|
||||
open = OPEN_LOBBY
|
||||
translate = ENABLE_TRANSLATIONS
|
||||
scores = dict()
|
||||
last_round_score = list()
|
||||
win_score = SCORE_WIN
|
||||
|
||||
def __init__(self, chat):
|
||||
self.chat = chat
|
||||
|
@ -137,3 +141,51 @@ class Game(object):
|
|||
"""Carries out the color choosing and turns the game"""
|
||||
self.last_card.color = color
|
||||
self.turn()
|
||||
|
||||
def add_score(self, player):
|
||||
"""Add total value of all card in every players hand
|
||||
to the winner's score."""
|
||||
scores = 0
|
||||
self.last_round_score.clear()
|
||||
for player in self.players:
|
||||
for card in player.cards:
|
||||
sc = c.CARD_SCORES[card.value or card.special]
|
||||
self.last_round_score.append((sc, card))
|
||||
scores += sc
|
||||
try:
|
||||
self.scores[player.user.id] += scores
|
||||
except KeyError:
|
||||
self.scores[player.user.id] = scores
|
||||
|
||||
def reset_cards(self):
|
||||
"""Reset game deck and player's hand"""
|
||||
players_cache = self.players
|
||||
# clear player's card, might as well use player.cards.clear()
|
||||
for player in players_cache:
|
||||
for card in player.cards:
|
||||
self.deck.dismiss(card)
|
||||
player.cards = list()
|
||||
# fill deck with normal cards set
|
||||
self.deck._fill_classic_()
|
||||
# draw player's hand
|
||||
for player in players_cache:
|
||||
player.draw_first_hand()
|
||||
|
||||
def new_round(self):
|
||||
lc = self.last_card
|
||||
while self.last_card == lc or not self.last_card or self.last_card.special:
|
||||
self.last_card = self.deck.draw()
|
||||
# If the card drawn was special, return it to the deck and loop again
|
||||
if self.last_card.special:
|
||||
self.deck.dismiss(self.last_card)
|
||||
self.play_card(self.last_card)
|
||||
|
||||
def get_score(self, player):
|
||||
try:
|
||||
return self.scores[player.user.id]
|
||||
except KeyError:
|
||||
self.scores[player.user.id] = 0
|
||||
return 0
|
||||
|
||||
def get_scores(self):
|
||||
return [(player, self.get_score(player))for player in self.players]
|
||||
|
|
30
results.py
30
results.py
|
@ -130,6 +130,18 @@ def add_mode_wild(results):
|
|||
)
|
||||
|
||||
|
||||
def add_mode_score(results):
|
||||
"""Change mode to classic"""
|
||||
results.append(
|
||||
InlineQueryResultArticle(
|
||||
"mode_score",
|
||||
title=_("💯 Score mode"),
|
||||
input_message_content=
|
||||
InputTextMessageContent(_('Kaching~ 💯'))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def add_draw(player, results):
|
||||
"""Add option to draw"""
|
||||
n = player.game.draw_counter or 1
|
||||
|
@ -198,7 +210,10 @@ def add_card(game, card, results, can_play):
|
|||
|
||||
|
||||
def game_info(game):
|
||||
players = player_list(game)
|
||||
if game.mode == 'score':
|
||||
players = score_list(game)
|
||||
else:
|
||||
players = player_list(game)
|
||||
players_numbered = [
|
||||
'{}. {}'.format(i + 1, p)
|
||||
for i, p in enumerate(players)
|
||||
|
@ -214,3 +229,16 @@ def game_info(game):
|
|||
len(players))
|
||||
.format(player_list="\n".join(players_numbered))
|
||||
)
|
||||
|
||||
|
||||
def score_list(game):
|
||||
scores = [game.get_score(player) for player in game.players]
|
||||
plist = [_("{name} ({number} card)",
|
||||
"{name} ({number} cards)",
|
||||
len(player.cards))
|
||||
.format(name=player.user.first_name, number=len(player.cards))
|
||||
for player in game.players]
|
||||
return [s + " " +
|
||||
_("[{point} point]", "[{point} points]", scores[i])
|
||||
.format(point=scores[i])
|
||||
for i, s in enumerate(plist)]
|
||||
|
|
|
@ -75,7 +75,8 @@ attributions = ("Attributions:\n"
|
|||
modes_explanation = ("This UNO bot has three game modes: Classic, Sanic and Wild.\n\n"
|
||||
" 🎻 The Classic mode uses the conventional UNO deck and there is no auto skip.\n"
|
||||
" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically skips a player if he/she takes too long to play its turn\n"
|
||||
" 🐉 The Wild mode uses a deck with more special cards, less number variety and no auto skip.\n\n"
|
||||
" 🐉 The Wild mode uses a deck with more special cards, less number variety and no auto skip.\n"
|
||||
" 💯 The Score mode is how Uno meant to be played, scored when one player run out of card.\n\n"
|
||||
"To change the game mode, the GAME CREATOR has to type the bot nickname and a space, just like when playing a card, and all gamemode options should appear.")
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue