commit 652245941e457826b064299377fcb03f06b1c967 Author: acidvegas Date: Mon Jun 24 19:00:01 2019 -0400 Initial commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..69997e8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2019, acidvegas + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..69f62fe --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +![](screens/banner.png) + +###### Commands +| Command | Description | +| --- | --- | +| @help | Information about the commands. | +| @cheat | Betting cheat sheet. | +| .hit | Draw a card. | +| .mini | Toggle the mini deck. | +| .play | Start a game. | +| .stand | Stop drawing cards. | +| .stop | End the curent game. | + +##### Todo +- Add player database / chip system. +- Reward chips based on number of lines of chat in a channel. (Cap it to prevent flood.) +- Add a player versus player and a player versus computer system. +- Incorperate splits and double downs, etc. + +##### Screens +![](screens/game.png) +![](screens/cheat.png) \ No newline at end of file diff --git a/blackjack/blackjack.py b/blackjack/blackjack.py new file mode 100644 index 0000000..f164d38 --- /dev/null +++ b/blackjack/blackjack.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack) +# blackjack.py + +import os +import sys + +sys.dont_write_bytecode = True +os.chdir(sys.path[0] or '.') +sys.path += ('core',) + +import debug + +debug.info() +if not debug.check_version(3): + debug.error_exit('BlackJack requires Python 3!') +elif debug.check_privileges(): + debug.error_exit('Do not run BlackJack as admin/root!') +import irc +irc.BlackJack.connect() \ No newline at end of file diff --git a/blackjack/core/config.py b/blackjack/core/config.py new file mode 100644 index 0000000..135af5a --- /dev/null +++ b/blackjack/core/config.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack) +# config.py + +class connection: + server = 'irc.server.com' + port = 6667 + proxy = None + ipv6 = False + ssl = False + ssl_verify = False + vhost = None + channel = '#blackjack' + key = None + +class cert: + file = None + key = None + password = None + +class ident: + nickname = 'BlackJack' + username = 'blackjack' + realname = 'https://acid.vegas/blackjack' + +class login: + network = None + nickserv = None + operator = None + +class settings: + cmd_char = '!' + log = False + modes = None diff --git a/blackjack/core/database.py b/blackjack/core/database.py new file mode 100644 index 0000000..72653f1 --- /dev/null +++ b/blackjack/core/database.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack) +# functions.py + +import datetime +import os +import sqlite3 + +# Globals +db = sqlite3.connect(os.path.join('data', 'bot.db'), check_same_thread=False) +sql = db.cursor() + +def check(): + tables = sql.execute('SELECT name FROM sqlite_master WHERE type=\'table\'').fetchall() + if not len(tables): + sql.execute('CREATE TABLE IGNORE (IDENT TEXT NOT NULL);') + db.commit() + +class Player: + def register(nick, ident): + now = str(datetime.datetime.now()) + sql.execute('INSERT INTO PLAYERS (NICK,IDENT,MONEY,LAST) VALUES (\'{0}\', \'{1}\', \'{2}\', \'{3}\')'.format(nick, ident, '0', now)) + db.commit() + + def get_money(ident): + return sql.execute('SELECT MONEY FROM PLAYERS WHERE IDENT=\'{0}\''.format(ident)).fetchall()[0][0] + diff --git a/blackjack/core/debug.py b/blackjack/core/debug.py new file mode 100644 index 0000000..6594fb7 --- /dev/null +++ b/blackjack/core/debug.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack) +# debug.py + +import ctypes +import os +import sys +import time + +def check_privileges(): + if check_windows(): + if ctypes.windll.shell32.IsUserAnAdmin() != 0: + return True + else: + return False + else: + if os.getuid() == 0 or os.geteuid() == 0: + return True + else: + return False + +def check_version(major): + if sys.version_info.major == major: + return True + else: + return False + +def check_windows(): + if os.name == 'nt': + return True + else: + return False + +def clear(): + if check_windows(): + os.system('cls') + else: + os.system('clear') + +def error(msg, reason=None): + if reason: + print(f'{get_time()} | [!] - {msg} ({reason})') + else: + print(f'{get_time()} | [!] - {msg}') + +def error_exit(msg): + raise SystemExit(f'{get_time()} | [!] - {msg}') + +def get_time(): + return time.strftime('%I:%M:%S') + +def info(): + clear() + print(''.rjust(56, '#')) + print('#{0}#'.format(''.center(54))) + print('#{0}#'.format('BlackJack IRC Bot'.center(54))) + print('#{0}#'.format('Developed by acidvegas in Python'.center(54))) + print('#{0}#'.format('https://acid.vegas/blackjack'.center(54))) + print('#{0}#'.format(''.center(54))) + print(''.rjust(56, '#')) + +def irc(msg): + print(f'{get_time()} | [~] - {msg}') \ No newline at end of file diff --git a/blackjack/core/irc.py b/blackjack/core/irc.py new file mode 100644 index 0000000..819f91c --- /dev/null +++ b/blackjack/core/irc.py @@ -0,0 +1,398 @@ +#!/usr/bin/env python +# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack) +# irc.py + +import inspect +import os +import random +import socket +import ssl +import threading +import time + +import config +import debug + +# Data Directories & Files (DO NOT EDIT) +data_dir = os.path.join(os.path.dirname(os.path.realpath(inspect.stack()[-1][1])), 'data') +cheat_file = os.path.join(data_dir, 'cheat.txt') +help_file = os.path.join(data_dir, 'help.txt') + +# Card Types +club = ('♣','clubs') +diamond = ('♦','diamonds') +heart = ('♥','hearts') +spade = ('♠','spades') + +# Deck Table (Name, ASCII, Value, Remaining Suits) +deck = { + 'ace' : [None, 11, [club,diamond,heart,spade]], + 'two' : [None, 2, [club,diamond,heart,spade]], + 'three' : [None, 3, [club,diamond,heart,spade]], + 'four' : [None, 4, [club,diamond,heart,spade]], + 'five' : [None, 5, [club,diamond,heart,spade]], + 'six' : [None, 6, [club,diamond,heart,spade]], + 'seven' : [None, 7, [club,diamond,heart,spade]], + 'eight' : [None, 8, [club,diamond,heart,spade]], + 'nine' : [None, 9, [club,diamond,heart,spade]], + 'ten' : [None, 10, [club,diamond,heart,spade]], + 'jack' : [None, 10, [club,diamond,heart,spade]], + 'queen' : [None, 10, [club,diamond,heart,spade]], + 'king' : [None, 10, [club,diamond,heart,spade]] +} + +# Formatting Control Characters / Color Codes +bold = '\x02' +italic = '\x1D' +underline = '\x1F' +reverse = '\x16' +reset = '\x0f' +white = '00' +black = '01' +blue = '02' +green = '03' +red = '04' +brown = '05' +purple = '06' +orange = '07' +yellow = '08' +light_green = '09' +cyan = '10' +light_cyan = '11' +light_blue = '12' +pink = '13' +grey = '14' +light_grey = '15' + +def color(msg, foreground, background=None): + if background: + return '\x03{0},{1}{2}{3}'.format(foreground, background, msg, reset) + else: + return '\x03{0}{1}{2}'.format(foreground, msg, reset) + +class IRC(object): + def __init__(self): + self.ace_minus = False + self.hand = None + self.last_move = 0 + self.last_time = 0 + self.player = None + self.total = 0 + self.mini_deck = False + self.sock = None + + def action(self, chan, msg): + self.sendmsg(chan, '\x01ACTION {0}\x01'.format(msg)) + + def connect(self): + try: + self.create_socket() + self.sock.connect((config.connection.server, config.connection.port)) + if config.login.network: + self.raw('PASS ' + config.login.network) + self.raw('USER {0} 0 * :{1}'.format(config.ident.username, config.ident.realname)) + self.raw('NICK ' + config.ident.nickname) + except socket.error as ex: + debug.error('Failed to connect to IRC server.', ex) + self.event_disconnect() + else: + self.listen() + + def create_socket(self): + family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET + self.sock = socket.socket(family, socket.SOCK_STREAM) + if config.connection.vhost: + self.sock.bind((config.connection.vhost, 0)) + if config.connection.ssl: + self.sock = ssl.wrap_socket(self.sock) + + def draw(self): + card_type = random.choice(list(deck.keys())) + remaining = deck[card_type][2] + while not remaining: + card_type = random.choice(list(deck.keys())) + remaining = deck[card_type][2] + card_suit = random.choice(remaining) + if card_suit in (heart,diamond): + card_color = red + else: + card_color = black + card_value = deck[card_type][1] + if self.mini_deck: + card = deck[card_type][0].replace('X', card_suit[0]) + card = color(card, card_color, white) + self.hand.append(card) + else: + for i in range(5): + card = deck[card_type][0][i].replace('X', card_suit[0]) + card = color(card, card_color, white) + self.hand[i].append(card) + deck[card_type][2].remove(card_suit) + self.total += card_value + if card_type == 'ace' and deck['ace'][1] != 1: + deck['ace'][1] = 1 + return (card_type, card_suit) + + def error(self, chan, msg, reason=None): + if reason: + self.sendmsg(chan, '[{0}] {1} {2}'.format(color('ERROR', red), msg, color('({0})'.format(str(reason)), grey))) + else: + self.sendmsg(chan, '[{0}] {1}'.format(color('ERROR', red), msg)) + + def event_connect(self): + self.setup_deck('normal') + if config.login.nickserv: + self.identify(self.username, config.login.nickserv) + if config.login.operator: + self.oper(config.ident.username, config.login.operator) + self.join(config.connection.channel, config.connection.key) + + def event_disconnect(self): + self.sock.close() + self.reset() + time.sleep(10) + self.connect() + + def event_kick(self, nick, chan, kicked): + if kicked == config.ident.nickname and chan == config.connection.channel: + time.sleep(3) + self.join(config.connection.channel, config.connection.key) + + def event_message(self, nick, chan, msg): + if chan == config.connection.channel: + if not msg.startswith('.'): + if msg == '@help': + self.action(chan, 'Sending help in a private message...') + help = [line.strip() for line in open(help_file).readlines() if line] + for line in help: + self.sendmsg(chan, line) + elif msg == '@cheat': + self.action(chan, 'Sending cheat sheet in a private message...') + cheat_sheet = [line.strip() for line in open(cheat_file).readlines() if line] + for line in cheat_sheet: + self.sendmsg(chan, line) + else: + cmd = msg.split()[0][1:] + args = msg[len(cmd)+2:] + if time.time() - self.last_time < 2: + self.sendmsg(chan, color('Slow down nerd!', red)) + elif cmd == 'hit': + if self.player: + if self.player == nick: + card_type, card_suit = self.draw() + if self.mini_deck: + msg_str = '' + for i in self.hand: + msg_str += ' ' + i + self.sendmsg(chan, msg_str) + else: + for i in range(5): + msg_str = '' + for i in self.hand[i]: + msg_str += ' ' + i + self.sendmsg(chan, msg_str) + if self.total > 21: + if deck['ace'][1] == 1 and not self.ace_minus: + self.total = self.total - 10 + self.ace_minus = True + if self.total > 21: + self.sendmsg(chan, '{0} {1}'.format(color('BUST!', red), color('You went over 21 and lost!', grey))) + self.reset() + else: + self.sendmsg(chan, '{0} {1}'.format(color('You drew a {0} of {1}! Your total is now:'.format(card_type, card_suit[1]), yellow), color(str(self.total), light_blue))) + self.last_move = time.time() + else: + self.sendmsg(chan, '{0} {1}'.format(color('BUST!', red), color('You went over 21 and lost!', grey))) + self.reset() + else: + self.sendmsg(chan, '{0} {1}'.format(color('You drew a {0} of {1}! Your total is now:'.format(card_type, card_suit[1]), yellow), color(str(self.total), light_blue))) + self.last_move = time.time() + else: + self.error(chan, 'You are not currently playing!', '{0} is playing still'.format(self.player)) + else: + self.error(chan, 'You are not currently playing!') + elif cmd == 'mini': + if not self.player: + if self.mini_deck: + self.setup_deck('normal') + self.sendmsg(chan, '{0} {1}'.format(color('Mini deck has been', yellow), color('DISABLED', red))) + else: + self.setup_deck('mini') + self.sendmsg(chan, '{0} {1}'.format(color('Mini deck has been', yellow), color('ENABLED', green))) + else: + self.error(chan, 'You can not change the deck in game!') + elif cmd == 'play': + if not self.player: + self.player = nick + self.action(chan, 'Starting a game of blackjack with {0}!'.format(nick)) + for i in range(2): + self.draw() + if self.mini_deck: + msg_str = '' + for i in self.hand: + msg_str += ' ' + i + self.sendmsg(chan, msg_str) + else: + for i in range(5): + msg_str = '' + for i in self.hand[i]: + msg_str += ' ' + i + self.sendmsg(chan, msg_str) + self.sendmsg(chan, '{0} {1}'.format(color('Your total is now:', yellow), color(str(self.total), light_blue))) + self.last_move = time.time() + threading.Thread(target=self.timer).start() + elif self.player == nick: + self.error(chan, 'You have already started a game, please finish or stop the game!'.format(self.player)) + else: + self.error(chan, '{0} is currently playing a game, please wait!'.format(self.player)) + elif cmd == 'stand': + if self.player: + if self.player == nick: + self.sendmsg(chan, 'You have chosen to stand with {0} as your total.'.format(self.total)) + else: + self.error(chan, 'You are not currently playing!', '{0} is playing still'.format(self.player)) + else: + self.error(chan, 'You are not currently playing!') + elif cmd == 'stop': + if self.player: + if self.player == nick: + self.action(chan, 'Ending current game with {0}!'.format(nick)) + self.reset() + else: + self.error(chan, 'You are not currently playing!', '{0} is playing still'.format(self.player)) + else: + self.error(chan, 'You are not currently playing!') + self.last_time = time.time() + + def event_nick_in_use(self): + debug.error_exit('BlackJack is already running.') + + def event_part(self, nick, chan): + if self.player == nick: + self.sendmsg(chan, 'The game with {0} has ended.'.format(color(self.nick, light_blue))) + self.reset() + + def event_quit(self, nick): + if self.player == nick: + self.sendmsg(chan, 'The game with {0} has ended.'.format(color(self.nick, light_blue))) + self.reset() + + def handle_events(self, data): + args = data.split() + if args[0] == 'PING': + self.raw('PONG ' + args[1][1:]) + elif args[1] == '001': # Use 002 or 003 if you run into issues. + self.event_connect() + elif args[1] == '433': + self.event_nick_in_use() + elif args[1] in ('KICK','PART','PRIVMSG','QUIT'): + nick = args[0].split('!')[0][1:] + if nick != config.ident.nickname: + if args[1] == 'KICK': + chan = args[2] + kicked = args[3] + self.event_kick(nick, chan, kicked) + elif args[1] == 'PART': + chan = args[2] + self.event_part(nick, chan) + elif args[1] == 'PRIVMSG': + chan = args[2] + msg = data.split('{0} PRIVMSG {1} :'.format(args[0], chan))[1] + if chan != config.ident.nickname: + self.event_message(nick, chan, msg) + elif args[1] == 'QUIT': + self.event_quit(nick) + + def identify(self, username, password): + self.sendmsg('nickserv', f'identify {username} {password}') + + def join(self, chan, key=None): + self.raw(f'JOIN {chan} {key}') if key else self.raw('JOIN ' + chan) + + def listen(self): + while True: + try: + data = self.sock.recv(1024).decode('utf-8') + if data: + for line in (line for line in data.split('\r\n') if line): + debug.irc(line) + if line.startswith('ERROR :Closing Link:') and config.ident.nickname in data: + raise Exception('Connection has closed.') + elif len(line.split()) >= 2: + self.handle_events(line) + else: + debug.error('No data recieved from server.') + break + except (UnicodeDecodeError,UnicodeEncodeError): + debug.error('Unicode error has occured.') + except Exception as ex: + debug.error('Unexpected error occured.', ex) + break + self.event_disconnect() + + def mode(self, target, mode): + self.raw(f'MODE {target} {mode}') + + def raw(self, msg): + self.sock.send(bytes(msg + '\r\n', 'utf-8')) + + def reset(self): + self.ace = [False,False] + self.last_move = 0 + self.player = None + self.total = 0 + if self.mini_deck: + self.hand = [] + else: + self.hand = {0:[],1:[],2:[],3:[],4:[]} + deck['ace'][1] = 11 + for card in deck: + deck[card][2] = [club,diamond,heart,spade] + + def sendmsg(self, target, msg): + self.raw(f'PRIVMSG {target} :{msg}') + + def setup_deck(self, deck_type): + if deck_type == 'mini': + self.hand = [] + self.mini_deck = True + deck['ace'][0] = 'A X' + deck['two'][0] = '2 X' + deck['three'][0] = '3 X' + deck['four'][0] = '4 X' + deck['five'][0] = '5 X' + deck['six'][0] = '6 X' + deck['seven'][0] = '7 X' + deck['eight'][0] = '8 X' + deck['nine'][0] = '9 X' + deck['ten'][0] = '10X' + deck['jack'][0] = 'J X' + deck['queen'][0] = 'Q X' + deck['king'][0] = 'K X' + elif deck_type == 'normal': + self.hand = {0:[],1:[],2:[],3:[],4:[]} + self.mini_deck = False + deck['ace'][0] = ('A ',' ',' X ',' ',' A') + deck['two'][0] = ('2 ',' X ',' ',' X ',' 2') + deck['three'][0] = ('3 ',' X ',' X ',' X ',' 3') + deck['four'][0] = ('4 ',' X X ',' ',' X X ',' 4') + deck['five'][0] = ('5 ',' X X ',' X ',' X X ',' 5') + deck['six'][0] = ('6 ',' X X ',' X X ',' X X ',' 6') + deck['seven'][0] = ('7 ',' X X ',' XXX ',' X X ',' 7') + deck['eight'][0] = ('8 ',' XXX ',' X X ',' XXX ',' 8') + deck['nine'][0] = ('9 ',' XXX ',' XXX ',' XXX ',' 9') + deck['ten'][0] = ('10 ',' XXX ',' XX XX ',' XXX ',' 10') + deck['jack'][0] = ('J ',' ',' X ',' ',' J') + deck['queen'][0] = ('Q ',' ',' X ',' ',' Q') + deck['king'][0] = ('K ',' ',' X ',' ',' K') + + def timer(self): + while self.player: + if time.time() - self.last_move > self.game_timeout: + self.sendmsg(config.connection.channel, '{0}, you took too long! The game has ended.'.format(self.player)) + self.reset() + break + else: + time.sleep(1) + +BlackJack = IRC() diff --git a/blackjack/data/cheat.txt b/blackjack/data/cheat.txt new file mode 100644 index 0000000..bf2500d --- /dev/null +++ b/blackjack/data/cheat.txt @@ -0,0 +1,32 @@ +0,10 1 BLACKJACK CHEAT SHEET 0 +0,10 1,9 H 0,10HIT 0,4 S 0,10STAND 1,8 D 0,10DOUBLE 0,12 P 0,10SPLIT 1 +0,1 1 0 DEALERS HAND 1 +0,1 1,0 1,15 A 1,14 101,15 9 1,14 8 1,15 7 1,14 6 1,15 5 1,14 4 1,15 3 1,14 2 +0,1 1,5 1,15 A A 0,12 P P P P P P P P P P14 +0,1 1,5 1,1410 100,4 S S S S S S S S S S +0,1 0,5 1,15 9 9 0,4 S S 0,12 P P 0,4 S 0,12 P P P P P +0,1 0,5P1,14 8 8 0,12 P P P P P P P P P P +0,1 0,5A1,15 7 7 1,9 H H H H 0,12 P P P P P P +0,1 0,5I1,14 6 6 1,9 H H H H H H H H H H +0,1 0,5R1,15 5 5 1,9 H H 1,8 D D D D D D D D +0,1P1,5 1,14 4 4 0,9 1H H H H H0 0,12 P P 0,9 1H H H +0,1L1,5 1,15 3 3 0,9 1H0 1H H H0 0,12 P P P P P P +0,1A1,5 1,14 2 2 0,9 1H H H H0 0,12 P P P P P P +0,1Y1,7 1,15 17+ 0,4 S S S S S S S S S S +0,1E1,7 1,14 16 0,9 1H H H H0 1H0 0,4 S S S S S +0,1R1,7 1,15 15 0,9 1H H H H0 1H0 0,4 S S S S S +0,1S1,7H1,14 14 0,9 1H H H H0 1H0 0,4 S S S S S +0,1 1,7A1,15 13 0,9 1H H H H0 1H0 0,4 S S S S S +0,1H1,7R1,14 12 0,9 1H H H H H 0,4 S S S 0,9 1H H +0,1A1,7D1,15 11 0 0,9 1H0 1,8 D D D D D D D D D +0,1N1,7 1,14 10 0,9 1H0 1H0 1,8 D D D D D D D D +0,1D1,7 1,15 9 0,9 1H0 1H H H H0 1,8 D D D D 0,9 1H0 +0,1 1,7 1,14 8- 0,9 1H H H H H H H H H H0 +0,1 0,5 1,15 A-9 0,4 S S S S S 1,8 D D D D D +0,1 0,5 1,14 A-8 0,4 S S S S S 1,8 D D D D D +0,1 0,5S1,15 A-7 1,9 H H H0 0,4 S S 1,8 D D D D D +0,1 0,5O1,14 A-6 1,9 H H 0 1H H H0 1,8 D D D D 1,9 H +0,1 0,5F1,15 A-5 1,9 H H H H H0 1,8 D D D 0,9 1H H +0,1 0,5T1,14 A-4 1,9 H H H H0 1H0 1,8 D D D 0,9 1H0 1 H +0,1 0,5 1,15 A-3 0,9 1H 0 1H0 1 H0 1H0 1H0 1,8 D D 1,9 H H H +0,1 0,5 1,14 A-2 0,9 1H H H H H0 1,8 D D 1,9 H H H0 diff --git a/blackjack/data/help.txt b/blackjack/data/help.txt new file mode 100644 index 0000000..ac3a3f7 --- /dev/null +++ b/blackjack/data/help.txt @@ -0,0 +1,31 @@ + 1,0 1,1 1,0 1,1 1,0 1,1 + 1,1 1,0 1,1 1,0 1,1 1,0 1,1 1,0 1,1 1,0 + 1,1 1,0 1,1 1,0 1,1 1,0 1,1 + 1,1 1,0 1,1 1,0 1,1 1,0 1,1 1,0 1,1 1,0 + 1,0 1,1 1,0 1,1 0 1,0 1,1 1,0 1,1 + +12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ +12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ +12,00▓▓▓00,12B12,00▓▓▓ 04,00▓▓▓00,04L04,00▓▓▓ 12,00▓▓▓00,12A12,00▓▓▓ 04,00▓▓▓00,04C04,00▓▓▓ 12,00▓▓▓00,12K12,00▓▓▓ 04,00▓▓▓00,04J04,00▓▓▓ 12,00▓▓▓00,12A12,00▓▓▓ 04,00▓▓▓00,04C04,00▓▓▓ 12,00▓▓▓00,12K12,00▓▓▓ +12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ +12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ + +00┌─────────────────────────────────────────────────────────────────────┐ +00│ 08.: HOW TO PLAY :. 00 │ +00├─────────────────────────────────────────────────────────────────────┤ +00│ │ +00│ Type in the chat @help to see this message displayed.00 │ +00│ │ +00│ Start a game of BlackJack with the .play command. 00 │ +00│ │ +00│ You can end the game at any time with the .stop command. 00 │ +00│ │ +00│ The limit is 1 player at a time, and games will end if the player 00 │ +00│ has not executed a command after 20 seconds since the last command.00 │ +00│ │ +00│ │ +00│ Once in a game, you can use the .hit command to draw another card. 00 │ +00│ │ +00│ You can stop drawing cards with the .stand command. 00 │ +00│ │ +00└─────────────────────────────────────────────────────────────────────┘ diff --git a/screens/banner.png b/screens/banner.png new file mode 100644 index 0000000..34a925c Binary files /dev/null and b/screens/banner.png differ diff --git a/screens/cheat.png b/screens/cheat.png new file mode 100644 index 0000000..1474313 Binary files /dev/null and b/screens/cheat.png differ diff --git a/screens/game.png b/screens/game.png new file mode 100644 index 0000000..e4d50fb Binary files /dev/null and b/screens/game.png differ