221 lines
7.9 KiB
Python
221 lines
7.9 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Telegram bot to play UNO in group chats
|
|
# Copyright (c) 2016 Jannes Höke <uno@jhoeke.de>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
from telegram.emoji import Emoji
|
|
|
|
# Colors
|
|
RED = 'r'
|
|
BLUE = 'b'
|
|
GREEN = 'g'
|
|
YELLOW = 'y'
|
|
BLACK = 'x'
|
|
|
|
COLORS = (RED, BLUE, GREEN, YELLOW)
|
|
|
|
COLOR_ICONS = {
|
|
RED: Emoji.HEAVY_BLACK_HEART,
|
|
BLUE: Emoji.BLUE_HEART,
|
|
GREEN: Emoji.GREEN_HEART,
|
|
YELLOW: Emoji.YELLOW_HEART,
|
|
BLACK: '⬛️'
|
|
}
|
|
|
|
# Values
|
|
ZERO = '0'
|
|
ONE = '1'
|
|
TWO = '2'
|
|
THREE = '3'
|
|
FOUR = '4'
|
|
FIVE = '5'
|
|
SIX = '6'
|
|
SEVEN = '7'
|
|
EIGHT = '8'
|
|
NINE = '9'
|
|
DRAW_TWO = 'draw'
|
|
REVERSE = 'reverse'
|
|
SKIP = 'skip'
|
|
|
|
VALUES = (ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, DRAW_TWO,
|
|
REVERSE, SKIP)
|
|
|
|
# Special cards
|
|
CHOOSE = 'colorchooser'
|
|
DRAW_FOUR = 'draw_four'
|
|
|
|
SPECIALS = (CHOOSE, DRAW_FOUR)
|
|
|
|
STICKERS = {
|
|
'b_0': 'BQADBAAD2QEAAl9XmQAB--inQsYcLTsC',
|
|
'b_1': 'BQADBAAD2wEAAl9XmQABBzh4U-rFicEC',
|
|
'b_2': 'BQADBAAD3QEAAl9XmQABo3l6TT0MzKwC',
|
|
'b_3': 'BQADBAAD3wEAAl9XmQAB2y-3TSapRtIC',
|
|
'b_4': 'BQADBAAD4QEAAl9XmQABT6nhOuolqKYC',
|
|
'b_5': 'BQADBAAD4wEAAl9XmQABwRfmekGnpn0C',
|
|
'b_6': 'BQADBAAD5QEAAl9XmQABQITgUsEsqxsC',
|
|
'b_7': 'BQADBAAD5wEAAl9XmQABVhPF6EcfWjEC',
|
|
'b_8': 'BQADBAAD6QEAAl9XmQABP6baig0pIvYC',
|
|
'b_9': 'BQADBAAD6wEAAl9XmQAB0CQdsQs_pXIC',
|
|
'b_draw': 'BQADBAAD7QEAAl9XmQAB00Wii7R3gDUC',
|
|
'b_skip': 'BQADBAAD8QEAAl9XmQAB_RJHYKqlc-wC',
|
|
'b_reverse': 'BQADBAAD7wEAAl9XmQABo7D0B9NUPmYC',
|
|
'g_0': 'BQADBAAD9wEAAl9XmQABb8CaxxsQ-Y8C',
|
|
'g_1': 'BQADBAAD-QEAAl9XmQAB9B6ti_j6UB0C',
|
|
'g_2': 'BQADBAAD-wEAAl9XmQABYpLjOzbRz8EC',
|
|
'g_3': 'BQADBAAD_QEAAl9XmQABKvc2ZCiY-D8C',
|
|
'g_4': 'BQADBAAD_wEAAl9XmQABJB52wzPdHssC',
|
|
'g_5': 'BQADBAADAQIAAl9XmQABp_Ep1I4GA2cC',
|
|
'g_6': 'BQADBAADAwIAAl9XmQABaaMxxa4MihwC',
|
|
'g_7': 'BQADBAADBQIAAl9XmQABv5Q264Crz8gC',
|
|
'g_8': 'BQADBAADBwIAAl9XmQABjMH-X9UHh8sC',
|
|
'g_9': 'BQADBAADCQIAAl9XmQAB26fZ2fW7vM0C',
|
|
'g_draw': 'BQADBAADCwIAAl9XmQAB64jIZrgXrQUC',
|
|
'g_skip': 'BQADBAADDwIAAl9XmQAB17yhhnh46VQC',
|
|
'g_reverse': 'BQADBAADDQIAAl9XmQAB_xcaab0DkegC',
|
|
'r_0': 'BQADBAADEQIAAl9XmQABiUfr1hz-zT8C',
|
|
'r_1': 'BQADBAADEwIAAl9XmQAB5bWfwJGs6Q0C',
|
|
'r_2': 'BQADBAADFQIAAl9XmQABHR4mg9Ifjw0C',
|
|
'r_3': 'BQADBAADFwIAAl9XmQABYBx5O_PG2QIC',
|
|
'r_4': 'BQADBAADGQIAAl9XmQABTQpGrlvet3cC',
|
|
'r_5': 'BQADBAADGwIAAl9XmQABbdLt4gdntBQC',
|
|
'r_6': 'BQADBAADHQIAAl9XmQABqEI274p3lSoC',
|
|
'r_7': 'BQADBAADHwIAAl9XmQABCw8u67Q4EK4C',
|
|
'r_8': 'BQADBAADIQIAAl9XmQAB8iDJmLxp8ogC',
|
|
'r_9': 'BQADBAADIwIAAl9XmQAB_HCAww1kNGYC',
|
|
'r_draw': 'BQADBAADJQIAAl9XmQABuz0OZ4l3k6MC',
|
|
'r_skip': 'BQADBAADKQIAAl9XmQAC2AL5Ok_ULwI',
|
|
'r_reverse': 'BQADBAADJwIAAl9XmQABu2tIeQTpDvUC',
|
|
'y_0': 'BQADBAADKwIAAl9XmQAB_nWoNKe8DOQC',
|
|
'y_1': 'BQADBAADLQIAAl9XmQABVprAGUDKgOQC',
|
|
'y_2': 'BQADBAADLwIAAl9XmQABqyT4_YTm54EC',
|
|
'y_3': 'BQADBAADMQIAAl9XmQABGC-Xxg_N6fIC',
|
|
'y_4': 'BQADBAADMwIAAl9XmQABbc-ZGL8kApAC',
|
|
'y_5': 'BQADBAADNQIAAl9XmQAB67QJZIF6XAcC',
|
|
'y_6': 'BQADBAADNwIAAl9XmQABJg_7XXoITsoC',
|
|
'y_7': 'BQADBAADOQIAAl9XmQABVrd7OcS2k34C',
|
|
'y_8': 'BQADBAADOwIAAl9XmQABRpJSahBWk3EC',
|
|
'y_9': 'BQADBAADPQIAAl9XmQAB9MwJWKLJogYC',
|
|
'y_draw': 'BQADBAADPwIAAl9XmQABaPYK8oYg84cC',
|
|
'y_skip': 'BQADBAADQwIAAl9XmQABO_AZKtxY6IMC',
|
|
'y_reverse': 'BQADBAADQQIAAl9XmQABZdQFahGG6UQC',
|
|
'draw_four': 'BQADBAAD9QEAAl9XmQABVlkSNfhn76cC',
|
|
'colorchooser': 'BQADBAAD8wEAAl9XmQABl9rUOPqx4E4C',
|
|
'option_draw': 'BQADBAAD-AIAAl9XmQABxEjEcFM-VHIC',
|
|
'option_pass': 'BQADBAAD-gIAAl9XmQABcEkAAbaZ4SicAg',
|
|
'option_bluff': 'BQADBAADygIAAl9XmQABJoLfB9ntI2UC',
|
|
'option_info': 'BQADBAADxAIAAl9XmQABC5v3Z77VLfEC'
|
|
}
|
|
|
|
STICKERS_GREY = {
|
|
'b_0': 'BQADBAADRQIAAl9XmQAB1IfkQ5xAiK4C',
|
|
'b_1': 'BQADBAADRwIAAl9XmQABbWvhTeKBii4C',
|
|
'b_2': 'BQADBAADSQIAAl9XmQABS1djHgyQokMC',
|
|
'b_3': 'BQADBAADSwIAAl9XmQABwQ6VTbgY-MIC',
|
|
'b_4': 'BQADBAADTQIAAl9XmQABAlKUYha8YccC',
|
|
'b_5': 'BQADBAADTwIAAl9XmQABMvx8xVDnhUEC',
|
|
'b_6': 'BQADBAADUQIAAl9XmQABDEbhP1Zd31kC',
|
|
'b_7': 'BQADBAADUwIAAl9XmQABXb5XQBBaAnIC',
|
|
'b_8': 'BQADBAADVQIAAl9XmQABgL5HRDLvrjgC',
|
|
'b_9': 'BQADBAADVwIAAl9XmQABtO3XDQWZLtYC',
|
|
'b_draw': 'BQADBAADWQIAAl9XmQAB2kk__6_2IhMC',
|
|
'b_skip': 'BQADBAADXQIAAl9XmQABEGJI6CaH3vcC',
|
|
'b_reverse': 'BQADBAADWwIAAl9XmQAB_kZA6UdHXU8C',
|
|
'g_0': 'BQADBAADYwIAAl9XmQABGD5a9oG7Yg4C',
|
|
'g_1': 'BQADBAADZQIAAl9XmQABqwABZHAXZIg0Ag',
|
|
'g_2': 'BQADBAADZwIAAl9XmQABTI3mrEhojRkC',
|
|
'g_3': 'BQADBAADaQIAAl9XmQABVi3rUyzWS3YC',
|
|
'g_4': 'BQADBAADawIAAl9XmQABZIf5ThaXnpUC',
|
|
'g_5': 'BQADBAADbQIAAl9XmQABNndVJSQCenIC',
|
|
'g_6': 'BQADBAADbwIAAl9XmQABpoy1c4ZkrvwC',
|
|
'g_7': 'BQADBAADcQIAAl9XmQABDeaT5fzxwREC',
|
|
'g_8': 'BQADBAADcwIAAl9XmQABLIQ06ZM5NnAC',
|
|
'g_9': 'BQADBAADdQIAAl9XmQABel-mC7eXGsMC',
|
|
'g_draw': 'BQADBAADdwIAAl9XmQABOHEpxSztCf8C',
|
|
'g_skip': 'BQADBAADewIAAl9XmQABDaQdMxjjPsoC',
|
|
'g_reverse': 'BQADBAADeQIAAl9XmQABek1lGz7SJNAC',
|
|
'r_0': 'BQADBAADfQIAAl9XmQABWrxoiXcsg0EC',
|
|
'r_1': 'BQADBAADfwIAAl9XmQABlav-bkgSgRcC',
|
|
'r_2': 'BQADBAADgQIAAl9XmQABDjZkqfJ4AdAC',
|
|
'r_3': 'BQADBAADgwIAAl9XmQABT7lH7VVcy3MC',
|
|
'r_4': 'BQADBAADhQIAAl9XmQAB1arPC5x0LrwC',
|
|
'r_5': 'BQADBAADhwIAAl9XmQABWvs7xkCDldkC',
|
|
'r_6': 'BQADBAADiQIAAl9XmQABjwABH5ZonWn8Ag',
|
|
'r_7': 'BQADBAADiwIAAl9XmQABjekJfm4fBDIC',
|
|
'r_8': 'BQADBAADjQIAAl9XmQABqFjchpsJeEkC',
|
|
'r_9': 'BQADBAADjwIAAl9XmQAB-sKdcgABdNKDAg',
|
|
'r_draw': 'BQADBAADkQIAAl9XmQABtw9RPVDHZOQC',
|
|
'r_skip': 'BQADBAADlQIAAl9XmQABtG2GixCxtX4C',
|
|
'r_reverse': 'BQADBAADkwIAAl9XmQABz2qyEbabnVsC',
|
|
'y_0': 'BQADBAADlwIAAl9XmQABAb3ZwTGS1lMC',
|
|
'y_1': 'BQADBAADmQIAAl9XmQAB9v5qJk9R0x8C',
|
|
'y_2': 'BQADBAADmwIAAl9XmQABCsgpRHC2g-cC',
|
|
'y_3': 'BQADBAADnQIAAl9XmQAB3kLLXCv-qY0C',
|
|
'y_4': 'BQADBAADnwIAAl9XmQAB7R_y-NexNLIC',
|
|
'y_5': 'BQADBAADoQIAAl9XmQABl-7mwsjD-cMC',
|
|
'y_6': 'BQADBAADowIAAl9XmQABwbVsyv2MfPkC',
|
|
'y_7': 'BQADBAADpQIAAl9XmQABoBqC0JsemVwC',
|
|
'y_8': 'BQADBAADpwIAAl9XmQABpkwAAeh9ldlHAg',
|
|
'y_9': 'BQADBAADqQIAAl9XmQABpSBEUfd4IM8C',
|
|
'y_draw': 'BQADBAADqwIAAl9XmQABMt-2zW0VYb4C',
|
|
'y_skip': 'BQADBAADrwIAAl9XmQABIDf-_TuuxtEC',
|
|
'y_reverse': 'BQADBAADrQIAAl9XmQABm9M0Zh-_UwkC',
|
|
'draw_four': 'BQADBAADYQIAAl9XmQAB_HWlvZIscDEC',
|
|
'colorchooser': 'BQADBAADXwIAAl9XmQABY_ksDdMex-wC'
|
|
}
|
|
|
|
|
|
class Card(object):
|
|
"""This class represents an UNO card"""
|
|
|
|
def __init__(self, color, value, special=None):
|
|
self.color = color
|
|
self.value = value
|
|
self.special = special
|
|
|
|
def __str__(self):
|
|
if self.special:
|
|
return self.special
|
|
else:
|
|
return '%s_%s' % (self.color, self.value)
|
|
|
|
def __repr__(self):
|
|
if self.special:
|
|
return '%s%s%s' % (COLOR_ICONS.get(self.color, ''),
|
|
COLOR_ICONS[BLACK],
|
|
' '.join([s.capitalize()
|
|
for s in self.special.split('_')]))
|
|
else:
|
|
return '%s%s' % (COLOR_ICONS[self.color], self.value.capitalize())
|
|
|
|
def __eq__(self, other):
|
|
"""Needed for sorting the cards"""
|
|
return str(self) == str(other)
|
|
|
|
def __lt__(self, other):
|
|
"""Needed for sorting the cards"""
|
|
return str(self) < str(other)
|
|
|
|
|
|
def from_str(string):
|
|
"""Decodes a Card object from a string"""
|
|
if string not in SPECIALS:
|
|
color, value = string.split('_')
|
|
return Card(color, value)
|
|
else:
|
|
return Card(None, None, string)
|