←︎ blackjack :: 6522459


1
commit 652245941e457826b064299377fcb03f06b1c967 (HEAD -> master)
2
Author: acidvegas <acid.vegas@acid.vegas>
3
Date:   Mon Jun 24 19:00:01 2019 -0400
4
5
    Initial commit
6
---
7
 LICENSE                    |  15 ++
8
 README.md                  |  22 +++
9
 blackjack/blackjack.py     |  20 +++
10
 blackjack/core/config.py   |  34 ++++
11
 blackjack/core/database.py |  27 +++
12
 blackjack/core/debug.py    |  63 +++++++
13
 blackjack/core/irc.py      | 398 +++++++++++++++++++++++++++++++++++++++++++++
14
 blackjack/data/cheat.txt   |  32 ++++
15
 blackjack/data/help.txt    |  31 ++++
16
 screens/banner.png         | Bin 0 -> 9111 bytes
17
 screens/cheat.png          | Bin 0 -> 30389 bytes
18
 screens/game.png           | Bin 0 -> 19796 bytes
19
 12 files changed, 642 insertions(+)
20
21
diff --git a/LICENSE b/LICENSE
22
new file mode 100644
23
index 0000000..69997e8
24
--- /dev/null
25
+++ b/LICENSE
26
@@ -0,0 +1,15 @@
27
+ISC License
28
+
29
+Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas>
30
+
31
+Permission to use, copy, modify, and/or distribute this software for any
32
+purpose with or without fee is hereby granted, provided that the above
33
+copyright notice and this permission notice appear in all copies.
34
+
35
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
36
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
37
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
38
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
39
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
40
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
41
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42
diff --git a/README.md b/README.md
43
new file mode 100644
44
index 0000000..69f62fe
45
--- /dev/null
46
+++ b/README.md
47
@@ -0,0 +1,22 @@
48
+![](screens/banner.png)
49
+
50
+###### Commands
51
+| Command | Description |
52
+| --- | --- |
53
+| @help | Information about the commands. |
54
+| @cheat | Betting cheat sheet. |
55
+| .hit | Draw a card. |
56
+| .mini | Toggle the mini deck. |
57
+| .play | Start a game. |
58
+| .stand | Stop drawing cards. |
59
+| .stop | End the curent game. |
60
+
61
+##### Todo
62
+- Add player database / chip system.
63
+- Reward chips based on number of lines of chat in a channel. (Cap it to prevent flood.)
64
+- Add a player versus player and a player versus computer system.
65
+- Incorperate splits and double downs, etc.
66
+
67
+##### Screens
68
+![](screens/game.png)
69
+![](screens/cheat.png)
70
diff --git a/blackjack/blackjack.py b/blackjack/blackjack.py
71
new file mode 100644
72
index 0000000..f164d38
73
--- /dev/null
74
+++ b/blackjack/blackjack.py
75
@@ -0,0 +1,20 @@
76
+#!/usr/bin/env python
77
+# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack)
78
+# blackjack.py
79
+
80
+import os
81
+import sys
82
+
83
+sys.dont_write_bytecode = True
84
+os.chdir(sys.path[0] or '.')
85
+sys.path += ('core',)
86
+
87
+import debug
88
+
89
+debug.info()
90
+if not debug.check_version(3):
91
+	debug.error_exit('BlackJack requires Python 3!')
92
+elif debug.check_privileges():
93
+	debug.error_exit('Do not run BlackJack as admin/root!')
94
+import irc
95
+irc.BlackJack.connect()
96
diff --git a/blackjack/core/config.py b/blackjack/core/config.py
97
new file mode 100644
98
index 0000000..135af5a
99
--- /dev/null
100
+++ b/blackjack/core/config.py
101
@@ -0,0 +1,34 @@
102
+#!/usr/bin/env python
103
+# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack)
104
+# config.py
105
+
106
+class connection:
107
+	server     = 'irc.server.com'
108
+	port       = 6667
109
+	proxy      = None
110
+	ipv6       = False
111
+	ssl	       = False
112
+	ssl_verify = False
113
+	vhost      = None
114
+	channel	   = '#blackjack'
115
+	key	       = None
116
+
117
+class cert:
118
+	file     = None
119
+	key      = None
120
+	password = None
121
+
122
+class ident:
123
+	nickname = 'BlackJack'
124
+	username = 'blackjack'
125
+	realname = 'https://acid.vegas/blackjack'
126
+
127
+class login:
128
+	network  = None
129
+	nickserv = None
130
+	operator = None
131
+
132
+class settings:
133
+	cmd_char = '!'
134
+	log      = False
135
+	modes    = None
136
diff --git a/blackjack/core/database.py b/blackjack/core/database.py
137
new file mode 100644
138
index 0000000..72653f1
139
--- /dev/null
140
+++ b/blackjack/core/database.py
141
@@ -0,0 +1,27 @@
142
+#!/usr/bin/env python
143
+# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack)
144
+# functions.py
145
+
146
+import datetime
147
+import os
148
+import sqlite3
149
+
150
+# Globals
151
+db  = sqlite3.connect(os.path.join('data', 'bot.db'), check_same_thread=False)
152
+sql = db.cursor()
153
+
154
+def check():
155
+	tables = sql.execute('SELECT name FROM sqlite_master WHERE type=\'table\'').fetchall()
156
+	if not len(tables):
157
+		sql.execute('CREATE TABLE IGNORE (IDENT TEXT NOT NULL);')
158
+		db.commit()
159
+
160
+class Player:
161
+    def register(nick, ident):
162
+        now = str(datetime.datetime.now())
163
+        sql.execute('INSERT INTO PLAYERS (NICK,IDENT,MONEY,LAST) VALUES (\'{0}\', \'{1}\', \'{2}\', \'{3}\')'.format(nick, ident, '0', now))
164
+        db.commit()
165
+
166
+    def get_money(ident):
167
+        return sql.execute('SELECT MONEY FROM PLAYERS WHERE IDENT=\'{0}\''.format(ident)).fetchall()[0][0]
168
+
169
diff --git a/blackjack/core/debug.py b/blackjack/core/debug.py
170
new file mode 100644
171
index 0000000..6594fb7
172
--- /dev/null
173
+++ b/blackjack/core/debug.py
174
@@ -0,0 +1,63 @@
175
+#!/usr/bin/env python
176
+# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack)
177
+# debug.py
178
+
179
+import ctypes
180
+import os
181
+import sys
182
+import time
183
+
184
+def check_privileges():
185
+    if check_windows():
186
+        if ctypes.windll.shell32.IsUserAnAdmin() != 0:
187
+            return True
188
+        else:
189
+            return False
190
+    else:
191
+        if os.getuid() == 0 or os.geteuid() == 0:
192
+            return True
193
+        else:
194
+            return False
195
+
196
+def check_version(major):
197
+    if sys.version_info.major == major:
198
+        return True
199
+    else:
200
+        return False
201
+
202
+def check_windows():
203
+    if os.name == 'nt':
204
+        return True
205
+    else:
206
+        return False
207
+
208
+def clear():
209
+    if check_windows():
210
+        os.system('cls')
211
+    else:
212
+        os.system('clear')
213
+
214
+def error(msg, reason=None):
215
+    if reason:
216
+        print(f'{get_time()} | [!] - {msg} ({reason})')
217
+    else:
218
+        print(f'{get_time()} | [!] - {msg}')
219
+
220
+def error_exit(msg):
221
+    raise SystemExit(f'{get_time()} | [!] - {msg}')
222
+
223
+def get_time():
224
+    return time.strftime('%I:%M:%S')
225
+
226
+def info():
227
+    clear()
228
+    print(''.rjust(56, '#'))
229
+    print('#{0}#'.format(''.center(54)))
230
+    print('#{0}#'.format('BlackJack IRC Bot'.center(54)))
231
+    print('#{0}#'.format('Developed by acidvegas in Python'.center(54)))
232
+    print('#{0}#'.format('https://acid.vegas/blackjack'.center(54)))
233
+    print('#{0}#'.format(''.center(54)))
234
+    print(''.rjust(56, '#'))
235
+
236
+def irc(msg):
237
+    print(f'{get_time()} | [~] - {msg}')
238
diff --git a/blackjack/core/irc.py b/blackjack/core/irc.py
239
new file mode 100644
240
index 0000000..819f91c
241
--- /dev/null
242
+++ b/blackjack/core/irc.py
243
@@ -0,0 +1,398 @@
244
+#!/usr/bin/env python
245
+# BlackJack IRC Bot - Developed by acidvegas in Python (https://acid.vegas/blackjack)
246
+# irc.py
247
+
248
+import inspect
249
+import os
250
+import random
251
+import socket
252
+import ssl
253
+import threading
254
+import time
255
+
256
+import config
257
+import debug
258
+
259
+# Data Directories & Files (DO NOT EDIT)
260
+data_dir   = os.path.join(os.path.dirname(os.path.realpath(inspect.stack()[-1][1])), 'data')
261
+cheat_file = os.path.join(data_dir, 'cheat.txt')
262
+help_file  = os.path.join(data_dir, 'help.txt')
263
+
264
+# Card Types
265
+club	= ('♣','clubs')
266
+diamond = ('♦','diamonds')
267
+heart   = ('♥','hearts')
268
+spade   = ('♠','spades')
269
+
270
+# Deck Table (Name, ASCII, Value, Remaining Suits)
271
+deck = {
272
+	'ace'   : [None, 11, [club,diamond,heart,spade]],
273
+	'two'   : [None, 2,  [club,diamond,heart,spade]],
274
+	'three' : [None, 3,  [club,diamond,heart,spade]],
275
+	'four'  : [None, 4,  [club,diamond,heart,spade]],
276
+	'five'  : [None, 5,  [club,diamond,heart,spade]],
277
+	'six'   : [None, 6,  [club,diamond,heart,spade]],
278
+	'seven' : [None, 7,  [club,diamond,heart,spade]],
279
+	'eight' : [None, 8,  [club,diamond,heart,spade]],
280
+	'nine'  : [None, 9,  [club,diamond,heart,spade]],
281
+	'ten'   : [None, 10, [club,diamond,heart,spade]],
282
+	'jack'  : [None, 10, [club,diamond,heart,spade]],
283
+	'queen' : [None, 10, [club,diamond,heart,spade]],
284
+	'king'  : [None, 10, [club,diamond,heart,spade]]
285
+}
286
+
287
+# Formatting Control Characters / Color Codes
288
+bold        = '\x02'
289
+italic      = '\x1D'
290
+underline   = '\x1F'
291
+reverse     = '\x16'
292
+reset       = '\x0f'
293
+white       = '00'
294
+black       = '01'
295
+blue        = '02'
296
+green       = '03'
297
+red         = '04'
298
+brown       = '05'
299
+purple      = '06'
300
+orange      = '07'
301
+yellow      = '08'
302
+light_green = '09'
303
+cyan        = '10'
304
+light_cyan  = '11'
305
+light_blue  = '12'
306
+pink        = '13'
307
+grey        = '14'
308
+light_grey  = '15'
309
+
310
+def color(msg, foreground, background=None):
311
+	if background:
312
+		return '\x03{0},{1}{2}{3}'.format(foreground, background, msg, reset)
313
+	else:
314
+		return '\x03{0}{1}{2}'.format(foreground, msg, reset)
315
+
316
+class IRC(object):
317
+	def __init__(self):
318
+		self.ace_minus = False
319
+		self.hand      = None
320
+		self.last_move = 0
321
+		self.last_time = 0
322
+		self.player    = None
323
+		self.total     = 0
324
+		self.mini_deck = False
325
+		self.sock       = None
326
+
327
+	def action(self, chan, msg):
328
+		self.sendmsg(chan, '\x01ACTION {0}\x01'.format(msg))
329
+
330
+	def connect(self):
331
+		try:
332
+			self.create_socket()
333
+			self.sock.connect((config.connection.server, config.connection.port))
334
+			if config.login.network:
335
+				self.raw('PASS ' + config.login.network)
336
+			self.raw('USER {0} 0 * :{1}'.format(config.ident.username, config.ident.realname))
337
+			self.raw('NICK ' + config.ident.nickname)
338
+		except socket.error as ex:
339
+			debug.error('Failed to connect to IRC server.', ex)
340
+			self.event_disconnect()
341
+		else:
342
+			self.listen()
343
+
344
+	def create_socket(self):
345
+		family	= socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET
346
+		self.sock = socket.socket(family, socket.SOCK_STREAM)
347
+		if config.connection.vhost:
348
+			self.sock.bind((config.connection.vhost, 0))
349
+		if config.connection.ssl:
350
+			self.sock = ssl.wrap_socket(self.sock)
351
+
352
+	def draw(self):
353
+		card_type = random.choice(list(deck.keys()))
354
+		remaining = deck[card_type][2]
355
+		while not remaining:
356
+			card_type = random.choice(list(deck.keys()))
357
+			remaining = deck[card_type][2]
358
+		card_suit = random.choice(remaining)
359
+		if card_suit in (heart,diamond):
360
+			card_color = red
361
+		else:
362
+			card_color = black
363
+		card_value = deck[card_type][1]
364
+		if self.mini_deck:
365
+			card = deck[card_type][0].replace('X', card_suit[0])
366
+			card = color(card, card_color, white)
367
+			self.hand.append(card)
368
+		else:
369
+			for i in range(5):
370
+				card = deck[card_type][0][i].replace('X', card_suit[0])
371
+				card = color(card, card_color, white)
372
+				self.hand[i].append(card)
373
+		deck[card_type][2].remove(card_suit)
374
+		self.total += card_value
375
+		if card_type == 'ace' and deck['ace'][1] != 1:
376
+			deck['ace'][1] = 1
377
+		return (card_type, card_suit)
378
+
379
+	def error(self, chan, msg, reason=None):
380
+		if reason:
381
+			self.sendmsg(chan, '[{0}] {1} {2}'.format(color('ERROR', red), msg, color('({0})'.format(str(reason)), grey)))
382
+		else:
383
+			self.sendmsg(chan, '[{0}] {1}'.format(color('ERROR', red), msg))
384
+
385
+	def event_connect(self):
386
+		self.setup_deck('normal')
387
+		if config.login.nickserv:
388
+			self.identify(self.username, config.login.nickserv)
389
+		if config.login.operator:
390
+			self.oper(config.ident.username, config.login.operator)
391
+		self.join(config.connection.channel, config.connection.key)
392
+
393
+	def event_disconnect(self):
394
+		self.sock.close()
395
+		self.reset()
396
+		time.sleep(10)
397
+		self.connect()
398
+
399
+	def event_kick(self, nick, chan, kicked):
400
+		if kicked == config.ident.nickname and chan == config.connection.channel:
401
+			time.sleep(3)
402
+			self.join(config.connection.channel, config.connection.key)
403
+
404
+	def event_message(self, nick, chan, msg):
405
+		if chan == config.connection.channel:
406
+			if not msg.startswith('.'):
407
+				if msg == '@help':
408
+					self.action(chan, 'Sending help in a private message...')
409
+					help = [line.strip() for line in open(help_file).readlines() if line]
410
+					for line in help:
411
+						self.sendmsg(chan, line)
412
+				elif msg == '@cheat':
413
+					self.action(chan, 'Sending cheat sheet in a private message...')
414
+					cheat_sheet = [line.strip() for line in open(cheat_file).readlines() if line]
415
+					for line in cheat_sheet:
416
+						self.sendmsg(chan, line)
417
+			else:
418
+				cmd  = msg.split()[0][1:]
419
+				args = msg[len(cmd)+2:]
420
+				if time.time() - self.last_time < 2:
421
+					self.sendmsg(chan, color('Slow down nerd!', red))
422
+				elif cmd == 'hit':
423
+					if self.player:
424
+						if self.player == nick:
425
+							card_type, card_suit = self.draw()
426
+							if self.mini_deck:
427
+								msg_str = ''
428
+								for i in self.hand:
429
+									msg_str += ' ' + i
430
+								self.sendmsg(chan, msg_str)
431
+							else:
432
+								for i in range(5):
433
+									msg_str = ''
434
+									for i in self.hand[i]:
435
+										msg_str += ' ' + i
436
+									self.sendmsg(chan, msg_str)
437
+							if self.total > 21:
438
+								if deck['ace'][1] == 1 and not self.ace_minus:
439
+									self.total	 = self.total - 10
440
+									self.ace_minus = True
441
+									if self.total > 21:
442
+										self.sendmsg(chan, '{0} {1}'.format(color('BUST!', red), color('You went over 21 and lost!', grey)))
443
+										self.reset()
444
+									else:
445
+										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)))
446
+										self.last_move = time.time()
447
+								else:
448
+									self.sendmsg(chan, '{0} {1}'.format(color('BUST!', red), color('You went over 21 and lost!', grey)))
449
+									self.reset()
450
+							else:
451
+								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)))
452
+								self.last_move = time.time()
453
+						else:
454
+							self.error(chan, 'You are not currently playing!', '{0} is playing still'.format(self.player))
455
+					else:
456
+						self.error(chan, 'You are not currently playing!')
457
+				elif cmd == 'mini':
458
+					if not self.player:
459
+						if self.mini_deck:
460
+							self.setup_deck('normal')
461
+							self.sendmsg(chan, '{0} {1}'.format(color('Mini deck has been', yellow), color('DISABLED', red)))
462
+						else:
463
+							self.setup_deck('mini')
464
+							self.sendmsg(chan, '{0} {1}'.format(color('Mini deck has been', yellow), color('ENABLED', green)))
465
+					else:
466
+						self.error(chan, 'You can not change the deck in game!')
467
+				elif cmd == 'play':
468
+					if not self.player:
469
+						self.player = nick
470
+						self.action(chan, 'Starting a game of blackjack with {0}!'.format(nick))
471
+						for i in range(2):
472
+							self.draw()
473
+						if self.mini_deck:
474
+							msg_str = ''
475
+							for i in self.hand:
476
+								msg_str += ' ' + i
477
+							self.sendmsg(chan, msg_str)
478
+						else:
479
+							for i in range(5):
480
+								msg_str = ''
481
+								for i in self.hand[i]:
482
+									msg_str += ' ' + i
483
+								self.sendmsg(chan, msg_str)
484
+						self.sendmsg(chan, '{0} {1}'.format(color('Your total is now:', yellow), color(str(self.total), light_blue)))
485
+						self.last_move = time.time()
486
+						threading.Thread(target=self.timer).start()
487
+					elif self.player == nick:
488
+						self.error(chan, 'You have already started a game, please finish or stop the game!'.format(self.player))
489
+					else:
490
+						self.error(chan, '{0} is currently playing a game, please wait!'.format(self.player))
491
+				elif cmd == 'stand':
492
+					if self.player:
493
+						if self.player == nick:
494
+							self.sendmsg(chan, 'You have chosen to stand with {0} as your total.'.format(self.total))
495
+						else:
496
+							self.error(chan, 'You are not currently playing!', '{0} is playing still'.format(self.player))
497
+					else:
498
+						self.error(chan, 'You are not currently playing!')
499
+				elif cmd == 'stop':
500
+					if self.player:
501
+						if self.player == nick:
502
+							self.action(chan, 'Ending current game with {0}!'.format(nick))
503
+							self.reset()
504
+						else:
505
+							self.error(chan, 'You are not currently playing!', '{0} is playing still'.format(self.player))
506
+					else:
507
+						self.error(chan, 'You are not currently playing!')
508
+			self.last_time = time.time()
509
+
510
+	def event_nick_in_use(self):
511
+		debug.error_exit('BlackJack is already running.')
512
+
513
+	def event_part(self, nick, chan):
514
+		if self.player == nick:
515
+			self.sendmsg(chan, 'The game with {0} has ended.'.format(color(self.nick, light_blue)))
516
+			self.reset()
517
+
518
+	def event_quit(self, nick):
519
+		if self.player == nick:
520
+			self.sendmsg(chan, 'The game with {0} has ended.'.format(color(self.nick, light_blue)))
521
+			self.reset()
522
+
523
+	def handle_events(self, data):
524
+		args = data.split()
525
+		if args[0] == 'PING':
526
+			self.raw('PONG ' + args[1][1:])
527
+		elif args[1] == '001': # Use 002 or 003 if you run into issues.
528
+			self.event_connect()
529
+		elif args[1] == '433':
530
+			self.event_nick_in_use()
531
+		elif args[1] in ('KICK','PART','PRIVMSG','QUIT'):
532
+			nick  = args[0].split('!')[0][1:]
533
+			if nick != config.ident.nickname:
534
+				if args[1] == 'KICK':
535
+					chan   = args[2]
536
+					kicked = args[3]
537
+					self.event_kick(nick, chan, kicked)
538
+				elif args[1] == 'PART':
539
+					chan = args[2]
540
+					self.event_part(nick, chan)
541
+				elif args[1] == 'PRIVMSG':
542
+					chan = args[2]
543
+					msg  = data.split('{0} PRIVMSG {1} :'.format(args[0], chan))[1]
544
+					if chan != config.ident.nickname:
545
+						self.event_message(nick, chan, msg)
546
+				elif args[1] == 'QUIT':
547
+					self.event_quit(nick)
548
+
549
+	def identify(self, username, password):
550
+		self.sendmsg('nickserv', f'identify {username} {password}')
551
+
552
+	def join(self, chan, key=None):
553
+		self.raw(f'JOIN {chan} {key}') if key else self.raw('JOIN ' + chan)
554
+
555
+	def listen(self):
556
+		while True:
557
+			try:
558
+				data = self.sock.recv(1024).decode('utf-8')
559
+				if data:
560
+					for line in (line for line in data.split('\r\n') if line):
561
+						debug.irc(line)
562
+						if line.startswith('ERROR :Closing Link:') and config.ident.nickname in data:
563
+							raise Exception('Connection has closed.')
564
+						elif len(line.split()) >= 2:
565
+							self.handle_events(line)
566
+				else:
567
+					debug.error('No data recieved from server.')
568
+					break
569
+			except (UnicodeDecodeError,UnicodeEncodeError):
570
+				debug.error('Unicode error has occured.')
571
+			except Exception as ex:
572
+				debug.error('Unexpected error occured.', ex)
573
+				break
574
+		self.event_disconnect()
575
+
576
+	def mode(self, target, mode):
577
+		self.raw(f'MODE {target} {mode}')
578
+
579
+	def raw(self, msg):
580
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
581
+
582
+	def reset(self):
583
+		self.ace       = [False,False]
584
+		self.last_move = 0
585
+		self.player    = None
586
+		self.total     = 0
587
+		if self.mini_deck:
588
+			self.hand = []
589
+		else:
590
+			self.hand = {0:[],1:[],2:[],3:[],4:[]}
591
+		deck['ace'][1] = 11
592
+		for card in deck:
593
+			deck[card][2] = [club,diamond,heart,spade]
594
+
595
+	def sendmsg(self, target, msg):
596
+		self.raw(f'PRIVMSG {target} :{msg}')
597
+
598
+	def setup_deck(self, deck_type):
599
+		if deck_type == 'mini':
600
+			self.hand        = []
601
+			self.mini_deck   = True
602
+			deck['ace'][0]   = 'A X'
603
+			deck['two'][0]   = '2 X'
604
+			deck['three'][0] = '3 X'
605
+			deck['four'][0]  = '4 X'
606
+			deck['five'][0]  = '5 X'
607
+			deck['six'][0]   = '6 X'
608
+			deck['seven'][0] = '7 X'
609
+			deck['eight'][0] = '8 X'
610
+			deck['nine'][0]  = '9 X'
611
+			deck['ten'][0]   = '10X'
612
+			deck['jack'][0]  = 'J X'
613
+			deck['queen'][0] = 'Q X'
614
+			deck['king'][0]  = 'K X'
615
+		elif deck_type == 'normal':
616
+			self.hand        = {0:[],1:[],2:[],3:[],4:[]}
617
+			self.mini_deck   = False
618
+			deck['ace'][0]   = ('A      ','       ','   X   ','       ','      A')
619
+			deck['two'][0]   = ('2      ','   X   ','       ','   X   ','      2')
620
+			deck['three'][0] = ('3      ','   X   ','   X   ','   X   ','      3')
621
+			deck['four'][0]  = ('4      ','  X X  ','       ','  X X  ','      4')
622
+			deck['five'][0]  = ('5      ','  X X  ','   X   ','  X X  ','      5')
623
+			deck['six'][0]   = ('6      ','  X X  ','  X X  ','  X X  ','      6')
624
+			deck['seven'][0] = ('7      ','  X X  ','  XXX  ','  X X  ','      7')
625
+			deck['eight'][0] = ('8      ','  XXX  ','  X X  ','  XXX  ','      8')
626
+			deck['nine'][0]  = ('9      ','  XXX  ','  XXX  ','  XXX  ','      9')
627
+			deck['ten'][0]   = ('10     ','  XXX  ',' XX XX ','  XXX  ','     10')
628
+			deck['jack'][0]  = ('J      ','       ','   X   ','       ','      J')
629
+			deck['queen'][0] = ('Q      ','       ','   X   ','       ','      Q')
630
+			deck['king'][0]  = ('K      ','       ','   X   ','       ','      K')
631
+
632
+	def timer(self):
633
+		while self.player:
634
+			if time.time() - self.last_move > self.game_timeout:
635
+				self.sendmsg(config.connection.channel, '{0}, you took too long! The game has ended.'.format(self.player))
636
+				self.reset()
637
+				break
638
+			else:
639
+				time.sleep(1)
640
+
641
+BlackJack = IRC()
642
diff --git a/blackjack/data/cheat.txt b/blackjack/data/cheat.txt
643
new file mode 100644
644
index 0000000..bf2500d
645
--- /dev/null
646
+++ b/blackjack/data/cheat.txt
647
@@ -0,0 +1,32 @@
648
+0,10  1      BLACKJACK CHEAT SHEET     0   
649
+0,10 1,9 H 0,10HIT 0,4 S 0,10STAND 1,8 D 0,10DOUBLE 0,12 P 0,10SPLIT 1 
650
+0,1 1 0              DEALERS HAND    1     
651
+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 
652
+0,1 1,5 1,15 A A 0,12 P  P  P  P  P  P  P  P  P  P14 
653
+0,1 1,5 1,1410 100,4 S  S  S  S  S  S  S  S  S  S 
654
+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 
655
+0,1 0,5P1,14 8 8 0,12 P  P  P  P  P  P  P  P  P  P 
656
+0,1 0,5A1,15 7 7 1,9 H  H  H  H 0,12 P  P  P  P  P  P 
657
+0,1 0,5I1,14 6 6 1,9 H  H  H  H  H  H  H  H  H  H 
658
+0,1 0,5R1,15 5 5 1,9 H  H 1,8 D  D  D  D  D  D  D  D 
659
+0,1P1,5 1,14 4 4 0,9 1H  H  H  H  H0 0,12 P  P 0,9 1H  H  H 
660
+0,1L1,5 1,15 3 3 0,9 1H0  1H  H  H0 0,12 P  P  P  P  P  P 
661
+0,1A1,5 1,14 2 2 0,9 1H  H  H  H0 0,12 P  P  P  P  P  P 
662
+0,1Y1,7 1,15 17+ 0,4 S  S  S  S  S  S  S  S  S  S 
663
+0,1E1,7 1,14 16  0,9 1H  H  H  H0  1H0 0,4 S  S  S  S  S 
664
+0,1R1,7 1,15 15  0,9 1H  H  H  H0  1H0 0,4 S  S  S  S  S 
665
+0,1S1,7H1,14 14  0,9 1H  H  H  H0  1H0 0,4 S  S  S  S  S 
666
+0,1 1,7A1,15 13  0,9 1H  H  H  H0  1H0 0,4 S  S  S  S  S 
667
+0,1H1,7R1,14 12  0,9 1H  H  H  H  H 0,4 S  S  S 0,9 1H  H 
668
+0,1A1,7D1,15 11 0 0,9 1H0 1,8 D  D  D  D  D  D  D  D  D 
669
+0,1N1,7 1,14 10  0,9 1H0  1H0 1,8 D  D  D  D  D  D  D  D 
670
+0,1D1,7 1,15  9  0,9 1H0  1H  H  H  H0 1,8 D  D  D  D 0,9 1H0 
671
+0,1 1,7 1,14 8-  0,9 1H  H  H  H  H  H  H  H  H  H0 
672
+0,1 0,5 1,15 A-9 0,4 S  S  S  S  S 1,8 D  D  D  D  D 
673
+0,1 0,5 1,14 A-8 0,4 S  S  S  S  S 1,8 D  D  D  D  D 
674
+0,1 0,5S1,15 A-7 1,9 H  H  H0 0,4 S  S 1,8 D  D  D  D  D 
675
+0,1 0,5O1,14 A-6 1,9 H  H 0 1H  H  H0 1,8 D  D  D  D 1,9 H 
676
+0,1 0,5F1,15 A-5 1,9 H  H  H  H  H0 1,8 D  D  D 0,9 1H  H 
677
+0,1 0,5T1,14 A-4 1,9 H  H  H  H0  1H0 1,8 D  D  D 0,9 1H0 1 H 
678
+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 
679
+0,1 0,5 1,14 A-2 0,9 1H  H  H  H  H0 1,8 D  D 1,9 H  H  H0 
680
diff --git a/blackjack/data/help.txt b/blackjack/data/help.txt
681
new file mode 100644
682
index 0000000..ac3a3f7
683
--- /dev/null
684
+++ b/blackjack/data/help.txt
685
@@ -0,0 +1,31 @@
686
+                        1,0       1,1 1,0      1,1   1,0     1,1 
687
+                        1,1  1,0   1,1   1,0  1,1   1,0  1,1 1,0  1,1   1,0  
688
+                        1,1  1,0   1,1   1,0      1,1  1,0  1,1     
689
+                        1,1  1,0   1,1   1,0  1,1   1,0  1,1 1,0  1,1   1,0  
690
+                        1,0       1,1 1,0  1,1 0  1,0  1,1  1,0     1,1 
691
+ 
692
+12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓
693
+12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓
694
+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▓▓▓
695
+12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓
696
+12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓ 04,00▓▓▓▓▓▓▓ 12,00▓▓▓▓▓▓▓
697
+ 
698
+00┌─────────────────────────────────────────────────────────────────────┐
699
+00│                          08.: HOW TO PLAY :. 00                         │
700
+00├─────────────────────────────────────────────────────────────────────┤
701
+00│                                                                     │
702
+00│ Type in the chat @help to see this message displayed.00               │
703
+00│                                                                     │
704
+00│ Start a game of BlackJack with the .play command. 00                  │
705
+00│                                                                     │
706
+00│ You can end the game at any time with the .stop command. 00           │
707
+00│                                                                     │
708
+00│ The limit is 1 player at a time, and games will end if the player 00  │
709
+00│ has not executed a command after 20 seconds since the last command.00 │
710
+00│                                                                     │
711
+00│                                                                     │
712
+00│ Once in a game, you can use the .hit command to draw another card. 00 │
713
+00│                                                                     │
714
+00│ You can stop drawing cards with the .stand command.  00               │
715
+00│                                                                     │
716
+00└─────────────────────────────────────────────────────────────────────┘
717
diff --git a/screens/banner.png b/screens/banner.png
718
new file mode 100644
719
index 0000000..34a925c
720
Binary files /dev/null and b/screens/banner.png differ
721
diff --git a/screens/cheat.png b/screens/cheat.png
722
new file mode 100644
723
index 0000000..1474313
724
Binary files /dev/null and b/screens/cheat.png differ
725
diff --git a/screens/game.png b/screens/game.png
726
new file mode 100644
727
index 0000000..e4d50fb
728
Binary files /dev/null and b/screens/game.png differ