blackjack

- irc bot to play blackjack
git clone git://git.acid.vegas/blackjack.git
Log | Files | Refs | Archive | README | LICENSE

commit 652245941e457826b064299377fcb03f06b1c967
Author: acidvegas <acid.vegas@acid.vegas>
Date: Mon, 24 Jun 2019 19:00:01 -0400

Initial commit

Diffstat:
ALICENSE | 15+++++++++++++++
AREADME.md | 23+++++++++++++++++++++++
Ablackjack/blackjack.py | 21+++++++++++++++++++++
Ablackjack/core/config.py | 34++++++++++++++++++++++++++++++++++
Ablackjack/core/database.py | 27+++++++++++++++++++++++++++
Ablackjack/core/debug.py | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ablackjack/core/irc.py | 398+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ablackjack/data/cheat.txt | 32++++++++++++++++++++++++++++++++
Ablackjack/data/help.txt | 31+++++++++++++++++++++++++++++++
Ascreens/banner.png | 0
Ascreens/cheat.png | 0
Ascreens/game.png | 0

12 files changed, 645 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas>
+
+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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Binary files differ.
diff --git a/screens/cheat.png b/screens/cheat.png
Binary files differ.
diff --git a/screens/game.png b/screens/game.png
Binary files differ.