2015-01-12 21:52:05 +00:00
#!/bin/python
#
# Cryptonote tipbot - blackjack commands
# Copyright 2015 moneromooo
#
# The Cryptonote tipbot is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
import sys
import os
import redis
import hashlib
import time
import string
import random
import tipbot . config as config
from tipbot . log import log_error , log_warn , log_info , log_log
import tipbot . coinspecs as coinspecs
from tipbot . utils import *
from tipbot . command_manager import *
from tipbot . redisdb import *
from tipbot . betutils import *
players = dict ( )
utf8users = set ( )
deck_cards = " 234567890JQKA "
deck_scores = [ 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 10 , 10 , 10 , 1 ]
deck_suits = [ " spades " , " hearts " , " diamonds " , " clubs " ]
deck_unicode_suits_ordering = [ 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 13 , 14 , 1 ]
deck_names = [ ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' 10 ' , ' J ' , ' Q ' , ' K ' , ' A ' ]
def MakeNewDeck ( decks , seed ) :
deck = [ ]
for n in range ( decks ) :
for s in range ( 4 ) :
for c in range ( 13 ) :
deck . append ( deck_cards [ c ] + " : " + deck_suits [ s ] )
r = random . Random ( )
r . seed ( seed )
r . shuffle ( deck )
return deck
def DrawCard ( deck ) :
card = deck [ 0 ]
del deck [ 0 ]
return card
def DrawForPlayer ( link ) :
identity = link . identity ( )
card = DrawCard ( players [ identity ] [ ' deck ' ] )
players [ identity ] [ ' player_hands ' ] [ players [ identity ] [ ' player_current_hand ' ] ] [ ' hand ' ] . append ( card )
return card
def DrawForDealer ( link ) :
identity = link . identity ( )
card = DrawCard ( players [ identity ] [ ' deck ' ] )
players [ identity ] [ ' dealer_hand ' ] . append ( card )
return card
def GetCardScore ( card ) :
idx = deck_cards . find ( card . split ( ' : ' ) [ 0 ] )
return deck_scores [ idx ]
def GetCardName ( card , utf8 = False ) :
parts = card . split ( ' : ' )
idx = deck_cards . find ( parts [ 0 ] )
if utf8 :
suitidx = deck_suits . index ( parts [ 1 ] )
name = chr ( 0b11110000 ) + chr ( 0b10011111 )
name = name + chr ( 0b10000010 + suitidx / 2 )
name = name + chr ( 0b10000000 + ( ( suitidx + 2 ) % 4 ) * 0b10000 + deck_unicode_suits_ordering [ idx ] )
return name
else :
return deck_names [ idx ]
def GetHandScores ( hand ) :
score = [ 0 ]
for card in hand :
card_score = GetCardScore ( card )
for n in range ( len ( score ) ) :
score [ n ] = score [ n ] + card_score
if card . split ( ' : ' ) [ 0 ] == ' A ' :
idx = len ( score )
score . extend ( score )
while idx < len ( score ) :
score [ idx ] = score [ idx ] + 10
idx = idx + 1
return score
def GetHandScore ( hand ) :
scores = GetHandScores ( hand )
score = scores [ 0 ]
for s in scores :
if s > score and s < = 21 :
score = s
return score
def IsSoftHand ( hand ) :
ace_found = False
score = 0
for card in hand :
if card . split ( ' : ' ) [ 0 ] == ' A ' :
if ace_found :
score = score + 1
else :
score = score + 11
ace_found = True
else :
score = score + GetCardScore ( card )
return ace_found and score < = 21
def GetPlayerCurrentHand ( link ) :
identity = link . identity ( )
idx = players [ identity ] [ ' player_current_hand ' ]
hand = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' hand ' ]
return hand
def GetPlayerCurrentHandScore ( link ) :
return GetHandScore ( GetPlayerCurrentHand ( link ) )
def HandToString ( hand , utf8 = False , hide_last = False , with_score = False ) :
s = " "
if hide_last :
hand = hand [ 0 : - 1 ]
hand . append ( ' ? ' )
for card in hand :
if s != " " :
if utf8 :
s = s + " "
else :
s = s + " , "
if card == ' ? ' :
if utf8 :
s = s + chr ( 0b11110000 ) + chr ( 0b10011111 ) + chr ( 0b10000010 ) + chr ( 0b10100000 )
else :
s = s + card
else :
s = s + GetCardName ( card , utf8 )
if not utf8 :
s = ' [ ' + s + ' ] '
if with_score and not hide_last :
s = s + " (score " + str ( GetHandScore ( hand ) ) + " ) "
return s
def PlayerHandsToString ( link , utf8 = False , with_score = False ) :
identity = link . identity ( )
S = " "
selected = players [ identity ] [ ' player_current_hand ' ]
for hand in players [ identity ] [ ' player_hands ' ] :
s = HandToString ( hand [ ' hand ' ] , identity in utf8users , False , with_score )
if selected == 0 :
s = " >>> " + s + " <<< "
selected = selected - 1
if S != " " :
S = S + " , "
S = S + s
return S
def UpdateBlackjackRecord ( link , win , lose , units ) :
try :
RecordGameResult ( link , " blackjack " , win , lose , units )
except Exception , e :
link . send ( " An error has occured " )
def UpdateSidebetRecord ( link , sidebet , win , lose , units ) :
try :
RecordGameResult ( link , " blackjack: %s " % sidebet , win , lose , units )
except :
link . send ( " An error has occured " )
def SwitchToNextHand ( link ) :
identity = link . identity ( )
log_log ( ' switching to next hand, from current %d ' % players [ identity ] [ ' player_current_hand ' ] )
players [ identity ] [ ' player_current_hand ' ] = players [ identity ] [ ' player_current_hand ' ] + 1
if players [ identity ] [ ' player_current_hand ' ] < len ( players [ identity ] [ ' player_hands ' ] ) :
if not players [ identity ] [ ' finished ' ] :
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
link . send ( " %s : Your hand is %s . Dealer ' s hand is %s " % ( link . user . nick , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users , True , False ) ) )
elif not players [ identity ] [ ' finished ' ] :
DealerMove ( link )
def IsBlackjack ( hand ) :
return len ( hand ) == 2 and GetHandScore ( hand ) == 21
def Win ( link , blackjack ) :
identity = link . identity ( )
idx = players [ identity ] [ ' player_current_hand ' ]
player_hand = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' hand ' ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
win_units = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' amount ' ]
if blackjack :
win_units = win_units * 3 / 2
link . send ( " %s wins %s on hand %d - BLACKJACK! - %s , dealer %s " % ( link . user . nick , AmountToString ( win_units ) , idx + 1 , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users ) ) )
else :
link . send ( " %s wins %s on hand %d - %s , dealer %s " % ( link . user . nick , AmountToString ( win_units ) , idx + 1 , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users ) ) )
players [ identity ] [ ' player_hands ' ] [ idx ] [ ' finished ' ] = True
UpdateBlackjackRecord ( link , True , False , win_units )
SwitchToNextHand ( link )
def Lose ( link , blackjack ) :
identity = link . identity ( )
idx = players [ identity ] [ ' player_current_hand ' ]
player_hand = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' hand ' ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
lose_units = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' amount ' ]
if blackjack :
link . send ( " %s loses %s on hand %d - %s , dealer BLACKJACK! %s " % ( link . user . nick , AmountToString ( lose_units ) , idx + 1 , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users ) ) )
else :
link . send ( " %s loses %s on hand %d - %s , dealer %s " % ( link . user . nick , AmountToString ( lose_units ) , idx + 1 , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users ) ) )
players [ identity ] [ ' player_hands ' ] [ idx ] [ ' finished ' ] = True
UpdateBlackjackRecord ( link , False , True , lose_units )
SwitchToNextHand ( link )
def Draw ( link , blackjack ) :
identity = link . identity ( )
idx = players [ identity ] [ ' player_current_hand ' ]
player_hand = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' hand ' ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
if blackjack :
link . send ( " %s pushes on hand %d - BLACKJACK vs BLACKJACK! - %s , dealer %s " % ( link . user . nick , idx + 1 , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users ) ) )
else :
link . send ( " %s pushes on hand %d - %s , dealer %s " % ( link . user . nick , idx + 1 , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users ) ) )
players [ identity ] [ ' player_hands ' ] [ idx ] [ ' finished ' ] = True
UpdateBlackjackRecord ( link , False , False , 0 )
SwitchToNextHand ( link )
def CheckEndGame ( link , force_end ) :
identity = link . identity ( )
player_score = GetPlayerCurrentHandScore ( link )
dealer_score = GetHandScore ( players [ identity ] [ ' dealer_hand ' ] )
dealer_blackjack = IsBlackjack ( players [ identity ] [ ' dealer_hand ' ] )
if dealer_score > 21 :
return Win ( link , False )
if player_score == 21 and dealer_score == 21 :
if dealer_blackjack :
return Lose ( link , True )
else :
return Draw ( link , False )
elif player_score == 21 :
return Win ( link , False )
elif dealer_score == 21 :
return Lose ( link , dealer_blackjack )
if force_end :
if player_score > dealer_score :
return Win ( link , False )
elif player_score < dealer_score :
return Lose ( link , False )
else :
return Draw ( link , False )
def AreAllHandsFinished ( link ) :
identity = link . identity ( )
for hand in players [ identity ] [ ' player_hands ' ] :
if not hand [ ' finished ' ] :
return False
return True
def ShouldDealerHit ( link ) :
identity = link . identity ( )
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
score = GetHandScore ( dealer_hand )
if score < 17 :
return True
if score == 17 and IsSoftHand ( dealer_hand ) :
return True
return False
def DealerMove ( link ) :
identity = link . identity ( )
log_log ( ' dealer move - finished: %d ' % players [ identity ] [ ' finished ' ] )
if AreAllHandsFinished ( link ) :
log_log ( ' all hands finished, marking game as finished ' )
players [ identity ] [ ' finished ' ] = True
if not players [ identity ] [ ' finished ' ] :
if not IsBlackjack ( players [ identity ] [ ' dealer_hand ' ] ) :
while ShouldDealerHit ( link ) :
card = DrawForDealer ( link )
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
bustmsg = " "
if GetHandScore ( dealer_hand ) > 21 :
bustmsg = " - Dealer busts! "
link . send ( " %s : Dealer draws %s : %s %s " % ( link . user . nick , GetCardName ( card , identity in utf8users ) , HandToString ( dealer_hand , identity in utf8users , False , True ) , bustmsg ) )
players [ identity ] [ ' finished ' ] = True
players [ identity ] [ ' player_current_hand ' ] = 0
log_log ( ' sweeping through open games ' )
while players [ identity ] [ ' player_current_hand ' ] < len ( players [ identity ] [ ' player_hands ' ] ) :
log_log ( ' sweeping through hand %d ' % players [ identity ] [ ' player_current_hand ' ] )
if players [ identity ] [ ' player_hands ' ] [ players [ identity ] [ ' player_current_hand ' ] ] [ ' finished ' ] :
log_log ( ' %d is already finished, skipping ' % players [ identity ] [ ' player_current_hand ' ] )
players [ identity ] [ ' player_current_hand ' ] = players [ identity ] [ ' player_current_hand ' ] + 1
continue
CheckEndGame ( link , True )
log_log ( ' done sweeping through open games ' )
sidebets = players [ identity ] [ ' sidebets ' ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
if sidebets [ ' splits ' ] :
bet_units = sidebets [ ' splits ' ]
nsplits = len ( players [ identity ] [ ' player_hands ' ] )
if nsplits == 1 :
link . send ( ' %s did not split - you lose %s ' % ( link . user . nick , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " splits " , False , True , bet_units )
if sidebets [ ' buster ' ] :
bet_units = sidebets [ ' buster ' ]
if GetHandScore ( dealer_hand ) > 21 :
cards = len ( dealer_hand )
if cards == 3 :
win_units = bet_units * 3 / 2
elif cards == 4 :
win_units = bet_units * 3
elif cards == 5 :
win_units = bet_units * 5
elif cards == 6 :
win_units = bet_units * 11
elif cards > = 7 :
win_units = bet_units * 21
link . send ( ' The dealer busted with %s cards - you win %s ' % ( cards , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " buster " , True , False , win_units )
else :
link . send ( ' The dealer did not bust - you lose %s ' % ( AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " buster " , False , True , bet_units )
del players [ identity ]
def GetNewShuffleSeed ( link ) :
identity = link . identity ( )
try :
if redis_hexists ( ' blackjack:rolls ' , identity ) :
rolls = redis_hget ( ' blackjack:rolls ' , identity )
rolls = long ( rolls ) + 1
else :
rolls = 1
except Exception , e :
log_error ( ' Failed to prepare roll for %s : %s ' % ( identity , str ( e ) ) )
raise
try :
s = GetServerSeed ( link , ' blackjack ' ) + " : " + GetPlayerSeed ( link , ' blackjack ' ) + " : " + str ( rolls )
seed = hashlib . sha256 ( s ) . hexdigest ( )
redis_hset ( " blackjack:rolls " , identity , rolls )
return rolls , seed
except Exception , e :
log_error ( ' Failed to roll for %s : %s ' % ( identity , str ( e ) ) )
raise
def ParseSideBets ( names , units ) :
sidebets = {
" total_amount_wagered " : 0 ,
" potential_loss " : 0 ,
" over13 " : None ,
" under13 " : None ,
" pair " : None ,
" climber " : None ,
" buster " : None ,
" splits " : None ,
" match " : None ,
" addup " : None ,
}
if len ( config . blackjack_sidebets ) == 0 :
return sidebets , None
wagered_amount = 0
total_amount_wagered = 0
potential_loss = 0
payout = 0
for name in names :
name = name . strip ( )
if name == " " :
continue
if not name in config . blackjack_sidebets :
return None , " Unavailable side bet: %s " % name
if name == " over13 " :
wagered_amount = units / 2
payout = wagered_amount
elif name == " under13 " :
wagered_amount = units / 2
payout = wagered_amount
elif name == " pair " :
wagered_amount = units / 2
payout = wagered_amount * 10
elif name == " climber " :
wagered_amount = units / 2
payout = wagered_amount * 21
elif name == " buster " :
wagered_amount = units / 2
payout = wagered_amount * 11
elif name == " splits " :
wagered_amount = units / 2
payout = wagered_amount * 21
elif name == " match " :
wagered_amount = units / 2
payout = wagered_amount * 21
elif name == " addup " :
wagered_amount = units / 2
payout = wagered_amount * 27
else :
return None , " Invalid side bet: %s " % name
total_amount_wagered = total_amount_wagered + wagered_amount
potential_loss = potential_loss + payout
sidebets [ name ] = wagered_amount
sidebets [ " total_amount_wagered " ] = total_amount_wagered
sidebets [ " potential_loss " ] = potential_loss
return sidebets , None
def GetBasicStrategyMove ( link ) :
identity = link . identity ( )
player_hand = GetPlayerCurrentHand ( link )
player_has_soft_hand = IsSoftHand ( player_hand )
player_can_double = len ( player_hand ) == 2
player_has_split = len ( players [ identity ] [ ' player_hands ' ] ) > 1
player_can_split = len ( players [ identity ] [ ' player_hands ' ] ) < config . blackjack_split_to
player_score = GetHandScore ( player_hand )
player_first_card = player_hand [ 0 ] . split ( ' : ' ) [ 0 ]
player_second_card = player_hand [ 1 ] . split ( ' : ' ) [ 0 ]
player_has_pair = player_first_card == player_second_card
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
dealer_upcard = dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ]
2015-01-22 10:02:10 +00:00
if player_score == 21 :
return " stand "
2015-01-12 21:52:05 +00:00
if player_has_split :
if player_first_card == ' A ' :
return " stand "
if player_has_pair :
if player_first_card in [ ' 8 ' , ' A ' ] :
if player_can_split :
return " split "
if player_first_card in [ ' 0 ' , ' J ' , ' Q ' , ' K ' ] :
return " stand "
if player_first_card == ' 9 ' :
if dealer_upcard in [ ' 7 ' , ' 0 ' , ' J ' , ' Q ' , ' K ' , ' A ' ] :
return " stand "
if player_can_split :
return " split "
if player_first_card in [ ' 2 ' , ' 3 ' , ' 7 ' ] :
if dealer_upcard in [ ' 8 ' , ' 9 ' , ' 0 ' , ' J ' , ' Q ' , ' K ' , ' A ' ] :
return " hit "
if player_can_split :
return " split "
if player_first_card == ' 6 ' :
if dealer_upcard in [ ' 7 ' , ' 8 ' , ' 9 ' , ' 0 ' , ' J ' , ' Q ' , ' K ' , ' A ' ] :
return " hit "
if player_can_split :
return " split "
if player_first_card == ' 5 ' :
if dealer_upcard in [ ' 0 ' , ' J ' , ' Q ' , ' K ' , ' A ' ] :
return " hit "
if player_can_double :
return " double "
else :
return " hit "
if player_first_card == ' 4 ' :
if dealer_upcard in [ ' 5 ' , ' 6 ' ] :
if player_can_split :
return " split "
else :
return " hit "
if player_has_soft_hand :
if player_first_card == ' A ' :
other_card = player_second_card
else :
other_card = player_first_card
if other_card in [ ' 8 ' , ' 9 ' ] :
return " stand "
if other_card == ' 7 ' :
if dealer_upcard in [ ' 2 ' , ' 7 ' , ' 8 ' ] :
return " stand "
if dealer_upcard in [ ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' ] :
if player_can_double :
return " double "
else :
return " stand "
return " hit "
if other_card == ' 6 ' :
if dealer_upcard in [ ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' ] :
if player_can_double :
return " double "
else :
return " hit "
return " hit "
if other_card in [ ' 4 ' , ' 5 ' ] :
if dealer_upcard in [ ' 4 ' , ' 5 ' , ' 6 ' ] :
if player_can_double :
return " double "
else :
return " hit "
return " hit "
if other_card in [ ' 2 ' , ' 3 ' ] :
if dealer_upcard in [ ' 5 ' , ' 6 ' ] :
if player_can_double :
return " double "
else :
return " hit "
return " hit "
else :
if player_score > = 17 :
return " stand "
if player_score > = 13 :
if dealer_upcard in [ ' 7 ' , ' 8 ' , ' 9 ' , ' 0 ' , ' J ' , ' Q ' , ' K ' , ' A ' ] :
return " hit "
else :
return " stand "
if player_score == 12 :
return " stand " if dealer_upcard in [ ' 4 ' , ' 5 ' , ' 6 ' ] else " hit "
if player_score == 11 :
if dealer_upcard == ' A ' :
return " hit "
else :
return " double " if player_can_double else " hit "
if player_score == 10 :
if dealer_upcard in [ ' 0 ' , ' J ' , ' Q ' , ' K ' , ' A ' ] :
return " hit "
else :
return " double " if player_can_double else " hit "
if player_score == 9 :
if dealer_upcard in [ ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' ] :
return " double " if player_can_double else " hit "
else :
return " hit "
if player_score > = 5 :
return " hit "
2015-01-22 10:02:46 +00:00
log_error ( ' GetBasicStrategyMove: missed a case: player %s , dealer %s ' % ( HandToString ( player_hand ) , HandToString ( dealer_hand ) ) )
2015-01-12 21:52:05 +00:00
return None
def RecordMove ( link , actual ) :
identity = link . identity ( )
basic = GetBasicStrategyMove ( link )
log_info ( ' %s %s s, basic strategy would %s ' % ( identity , actual , basic ) )
try :
p = redis_pipeline ( )
tname = " blackjack:strategy: " + identity
alltname = " blackjack:strategy: "
p . hincrby ( tname , " moves " , 1 )
if actual == basic :
p . hincrby ( tname , " matching " , 1 )
p . execute ( )
except Exception , e :
log_error ( ' Failed to record move for %s : %s ' % ( identity , str ( e ) ) )
def Blackjack ( link , cmd ) :
identity = link . identity ( )
if identity in players :
link . send ( " %s : you already are in a game of blackjack " % link . user . nick )
return
try :
amount = float ( cmd [ 1 ] )
units = long ( amount * coinspecs . atomic_units )
except Exception , e :
link . send ( " %s : usage: !blackjack amount " % link . user . nick )
return
sidebets , reason = ParseSideBets ( cmd [ 2 : ] , units )
if not sidebets :
link . send ( " %s : invalid side bet list: %s " % ( link . user . nick , reason ) )
return
total_amount_wagered = amount + sidebets [ " total_amount_wagered " ] / coinspecs . atomic_units
total_units_wagered = units + sidebets [ " total_amount_wagered " ]
potential_loss = amount * 1.5 + sidebets [ " potential_loss " ] / coinspecs . atomic_units
potential_units_loss = long ( potential_loss * coinspecs . atomic_units )
2015-01-21 22:00:22 +00:00
log_info ( ' %s bets a total of %s ( %.16g ), potential loss %s , side bets %s ' % ( identity , AmountToString ( total_units_wagered ) , total_amount_wagered , AmountToString ( potential_units_loss ) , str ( sidebets ) ) )
2015-01-21 18:15:49 +00:00
valid , reason = IsBetValid ( link , total_amount_wagered , config . blackjack_min_bet , config . blackjack_max_bet , potential_loss , config . blackjack_max_loss , config . blackjack_max_loss_ratio )
2015-01-12 21:52:05 +00:00
if not valid :
log_info ( " Dice: %s ' s bet refused: %s " % ( identity , reason ) )
link . send ( " %s : %s " % ( link . user . nick , reason ) )
return
try :
rolls , seed = GetNewShuffleSeed ( link )
except Exception , e :
link . send ( " %s : An error occured " % link . user . nick )
return
players [ identity ] = {
' deck ' : MakeNewDeck ( config . blackjack_decks , seed ) ,
' amount ' : total_units_wagered ,
2015-01-23 10:52:32 +00:00
' base_amount ' : units ,
2015-01-12 21:52:05 +00:00
' player_hands ' : [ dict ( {
' amount ' : units ,
' hand ' : [ ] ,
' finished ' : False ,
} ) ] ,
' player_current_hand ' : 0 ,
' dealer_hand ' : [ ] ,
' finished ' : False ,
' insurance ' : False ,
' sidebets ' : sidebets ,
}
DrawForPlayer ( link )
DrawForDealer ( link )
DrawForPlayer ( link )
DrawForDealer ( link )
if False : # TEST FOR SPLIT
if False :
players [ identity ] [ ' player_hands ' ] [ 0 ] [ ' hand ' ] [ 0 ] . split ( ' : ' ) [ 0 ] = ' A '
players [ identity ] [ ' player_hands ' ] [ 0 ] [ ' hand ' ] [ 1 ] = players [ identity ] [ ' player_hands ' ] [ 0 ] [ ' hand ' ] [ 0 ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
link . send ( " %s : Game %d starts. You draw %s . Dealer draws %s " % ( link . user . nick , rolls , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users , True , False ) ) )
player_hand = players [ identity ] [ ' player_hands ' ] [ 0 ] [ ' hand ' ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
plain_score = GetCardScore ( player_hand [ 0 ] ) + GetCardScore ( player_hand [ 1 ] )
if sidebets [ ' over13 ' ] :
bet_units = sidebets [ ' over13 ' ]
if plain_score > 13 :
win_units = bet_units
link . send ( ' %s : your first two cards total %d , over 13 - you win %s ' % ( link . user . nick , plain_score , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " over13 " , True , False , win_units )
else :
link . send ( ' %s : your first two cards total %d , not over 13 - you lose %s ' % ( link . user . nick , plain_score , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " over13 " , False , True , bet_units )
if sidebets [ ' under13 ' ] :
bet_units = sidebets [ ' under13 ' ]
if plain_score < 13 :
win_units = bet_units
link . send ( ' %s : your first two cards total %d , under 13 - you win %s ' % ( link . user . nick , plain_score , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " under13 " , True , False , win_units )
else :
link . send ( ' %s : your first two cards total %d , not under 13 - you lose %s ' % ( link . user . nick , plain_score , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " under13 " , False , True , bet_units )
if sidebets [ ' pair ' ] :
bet_units = sidebets [ ' pair ' ]
if player_hand [ 0 ] . split ( ' : ' ) [ 0 ] == player_hand [ 1 ] . split ( ' : ' ) [ 0 ] :
win_units = bet_units * 10
link . send ( ' %s : your first two cards are a pair - you win %s ' % ( link . user . nick , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " pair " , True , False , win_units )
else :
link . send ( ' %s : your first two cards are not a pair - you lose %s ' % ( link . user . nick , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " pair " , False , True , bet_units )
if sidebets [ ' climber ' ] :
bet_units = sidebets [ ' climber ' ]
if GetHandScore ( player_hand ) == 20 :
if dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] == ' A ' :
win_units = bet_units * 21
else :
win_units = bet_units * GetCardScore ( dealer_hand [ 0 ] )
link . send ( ' %s : your first two cards score 20, dealer \' s first card is %s - you win %s ' % ( link . user . nick , GetCardName ( dealer_hand [ 0 ] , identity in utf8users ) , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " climber " , True , False , win_units )
else :
link . send ( ' %s : your first two cards do not score 20 - you lose %s ' % ( link . user . nick , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " climber " , False , True , bet_units )
if sidebets [ ' match ' ] :
bet_units = sidebets [ ' match ' ]
if player_hand [ 0 ] . split ( ' : ' ) [ 0 ] == dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] and player_hand [ 1 ] . split ( ' : ' ) [ 0 ] == dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] :
win_units = bet_units * 21
link . send ( ' %s : your first two cards match the dealer \' s - you win %s ' % ( link . user . nick , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " match " , True , False , win_units )
elif player_hand [ 0 ] . split ( ' : ' ) [ 0 ] == dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] or player_hand [ 1 ] . split ( ' : ' ) [ 0 ] == dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] :
win_units = bet_units * 5
link . send ( ' %s : one of your first two cards match the dealer \' s - you win %s ' % ( link . user . nick , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " match " , True , False , win_units )
else :
link . send ( ' %s : none of your first two cards match the dealer \' s - you lose %s ' % ( link . user . nick , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " match " , False , True , bet_units )
if sidebets [ ' addup ' ] :
bet_units = sidebets [ ' addup ' ]
scores = GetHandScores ( player_hand )
if GetCardScore ( dealer_hand [ 0 ] ) in scores :
win_units = bet_units * 25
link . send ( ' %s : your first two cards \' scores add up to the dealer \' s - you win %s ' % ( link . user . nick , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " addup " , True , False , win_units )
else :
link . send ( ' %s : your first two cards \' scores do not add up to the dealer \' s - you lose %s ' % ( link . user . nick , AmountToString ( bet_units ) ) )
UpdateSidebetRecord ( link , " addup " , False , True , bet_units )
if IsBlackjack ( GetPlayerCurrentHand ( link ) ) :
if IsBlackjack ( dealer_hand ) :
Draw ( link , True )
else :
Win ( link , True )
return
if config . blackjack_insurance :
if dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] == ' A ' :
link . send ( " %s : dealer ' s first card is an ace, you can claim !insurance as your first move " % link . user . nick )
return
if IsBlackjack ( dealer_hand ) :
Lose ( link , True )
def Insurance ( link , cmd ) :
identity = link . identity ( )
if not config . blackjack_insurance :
return
if not identity in players :
link . send ( " %s : you are not in a game of blackjack - you can start one with !blackjack <amount> " % link . user . nick )
return
units = players [ identity ] [ ' amount ' ]
enough , reason = IsPlayerBalanceAtLeast ( link , units )
if not enough :
link . send ( " %s : %s - please refund your account to continue playing " % ( link . user . nick , reason ) )
return
nhands = len ( players [ identity ] [ ' player_hands ' ] )
if nhands > 1 or len ( GetPlayerCurrentHand ( link ) ) > 2 :
link . send ( " %s : you can only claim insurance as first move " % link . user . nick )
return
if players [ identity ] [ ' insurance ' ] :
link . send ( " %s : you can only claim insurance once " % link . user . nick )
return
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
if dealer_hand [ 0 ] . split ( ' : ' ) [ 0 ] != ' A ' :
link . send ( " %s : you can only claim insurance when the dealer ' s first card is an ace " % link . user . nick )
return
units = players [ identity ] [ ' player_hands ' ] [ 0 ] [ ' amount ' ]
insurance_units = units / 2
enough , reason = IsPlayerBalanceAtLeast ( link , units + insurance_units )
if not enough :
link . send ( " %s : you do not have enough %s in your account to insure with %s " % ( link . user . nick , coinspecs . name , idx + 1 , AmountToString ( insurance_units ) ) )
return
if IsBlackjack ( dealer_hand ) :
Lose ( link , True )
2015-01-22 10:50:53 +00:00
# From here on, players[identity] is deleted
2015-01-12 21:52:05 +00:00
win_insurance_units = insurance_units * 2
link . send ( ' %s wins %s insurance - dealer had a blackjack - %s ' % ( link . user . nick , AmountToString ( win_insurance_units ) , HandToString ( dealer_hand , identity in utf8users , False , False ) ) )
UpdateSidebetRecord ( link , " insurance " , True , False , win_insurance_units )
else :
link . send ( ' %s loses %s insurance - dealer had no blackjack ' % ( link . user . nick , AmountToString ( insurance_units ) ) )
UpdateSidebetRecord ( link , " insurance " , False , True , insurance_units )
link . send ( " %s : Your hand is %s . Dealer ' s hand is %s " % ( link . user . nick , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users , True , False ) ) )
2015-01-22 10:50:53 +00:00
if identity in players :
players [ identity ] [ ' insurance ' ] = True
2015-01-12 21:52:05 +00:00
def IsCurrentPlayerHandASplitAce ( link ) :
identity = link . identity ( )
if len ( players [ identity ] [ ' player_hands ' ] ) == 1 :
return False
idx = players [ identity ] [ ' player_current_hand ' ]
if players [ identity ] [ ' player_hands ' ] [ idx ] [ ' hand ' ] [ 0 ] . split ( ' : ' ) [ 0 ] == ' A ' :
return True
return False
def Hit ( link , cmd ) :
identity = link . identity ( )
if not identity in players :
link . send ( " %s : you are not in a game of blackjack - you can start one with !blackjack <amount> " % link . user . nick )
return
units = players [ identity ] [ ' amount ' ]
enough , reason = IsPlayerBalanceAtLeast ( link , units )
if not enough :
link . send ( " %s : %s - please refund your account to continue playing " % ( link . user . nick , reason ) )
return
if IsCurrentPlayerHandASplitAce ( link ) :
link . send ( " %s : You cannot hit a split ace " % ( link . user . nick ) )
return
RecordMove ( link , " hit " )
card = DrawForPlayer ( link )
link . send ( " %s : you draw %s . Your hand is %s . Dealer ' s hand is %s " % ( link . user . nick , GetCardName ( card , identity in utf8users ) , PlayerHandsToString ( link , True ) , HandToString ( players [ identity ] [ ' dealer_hand ' ] , identity in utf8users , True , True ) ) )
score = GetPlayerCurrentHandScore ( link )
if score > 21 :
Lose ( link , False )
elif score == 21 :
SwitchToNextHand ( link )
def Double ( link , cmd ) :
identity = link . identity ( )
if not identity in players :
link . send ( " %s : you are not in a game of blackjack - you can start one with !blackjack <amount> " % link . user . nick )
return
if len ( GetPlayerCurrentHand ( link ) ) > 2 :
link . send ( " %s : you can not double down with more than 2 cards " % link . user . nick )
return
units = players [ identity ] [ ' amount ' ]
enough , reason = IsPlayerBalanceAtLeast ( link , units )
if not enough :
link . send ( " %s : %s - please refund your account to continue playing " % ( link . user . nick , reason ) )
return
idx = players [ identity ] [ ' player_current_hand ' ]
units = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' amount ' ]
enough , reason = IsPlayerBalanceAtLeast ( link , units * 2 )
if not enough :
link . send ( " %s : you do not have enough %s in your account to double your bet on hand %d " % ( link . user . nick , coinspecs . name , idx + 1 ) )
return
if IsCurrentPlayerHandASplitAce ( link ) :
link . send ( " %s : You cannot double down on a split ace " % ( link . user . nick ) )
return
RecordMove ( link , " double " )
players [ identity ] [ ' player_hands ' ] [ idx ] [ ' amount ' ] = players [ identity ] [ ' player_hands ' ] [ idx ] [ ' amount ' ] + units
players [ identity ] [ ' amount ' ] = players [ identity ] [ ' amount ' ] + units
card = DrawForPlayer ( link )
link . send ( " %s : you draw %s . Your hand is %s . Dealer ' s hand is %s " % ( link . user . nick , GetCardName ( card , identity in utf8users ) , PlayerHandsToString ( link , True ) , HandToString ( players [ identity ] [ ' dealer_hand ' ] , identity in utf8users , True , True ) ) )
score = GetPlayerCurrentHandScore ( link )
if score > 21 :
Lose ( link , False )
else :
SwitchToNextHand ( link )
def Stand ( link , cmd ) :
identity = link . identity ( )
if not identity in players :
link . send ( " %s : you are not in a game of blackjack - you can start one with !blackjack <amount> " % link . user . nick )
return
units = players [ identity ] [ ' amount ' ]
enough , reason = IsPlayerBalanceAtLeast ( link , units )
if not enough :
link . send ( " %s : %s - please refund your account to continue playing " % ( link . user . nick , reason ) )
return
RecordMove ( link , " stand " )
link . send ( " %s stands " % link . user . nick )
SwitchToNextHand ( link )
def Split ( link , cmd ) :
identity = link . identity ( )
if not identity in players :
link . send ( " %s : you are not in a game of blackjack - you can start one with !blackjack <amount> " % link . user . nick )
return
units = players [ identity ] [ ' amount ' ]
enough , reason = IsPlayerBalanceAtLeast ( link , units )
if not enough :
link . send ( " %s : %s - please refund your account to continue playing " % ( link . user . nick , reason ) )
return
2015-01-23 10:52:32 +00:00
idx = players [ identity ] [ ' player_current_hand ' ]
2015-01-12 21:52:05 +00:00
hand = GetPlayerCurrentHand ( link )
if len ( hand ) != 2 or GetCardScore ( hand [ 0 ] ) != GetCardScore ( hand [ 1 ] ) :
link . send ( " %s : only pairs with the same value can be split " % ( link . user . nick ) )
return
if len ( players [ identity ] [ ' player_hands ' ] ) > = config . blackjack_split_to :
link . send ( " %s : you can only split to %d " % ( link . user . nick , config . blackjack_split_to ) )
return
2015-01-23 10:52:32 +00:00
enough , reason = IsPlayerBalanceAtLeast ( link , units + players [ identity ] [ ' base_amount ' ] )
2015-01-12 21:52:05 +00:00
if not enough :
link . send ( " %s : you do not have enough %s in your account to split hand %d " % ( link . user . nick , coinspecs . name , idx + 1 ) )
return
2015-01-23 10:52:32 +00:00
players [ identity ] [ ' amount ' ] = players [ identity ] [ ' amount ' ] + players [ identity ] [ ' base_amount ' ]
2015-01-12 21:52:05 +00:00
RecordMove ( link , " split " )
log_log ( ' splitting hand %d ' % idx )
2015-01-24 21:51:33 +00:00
split_card_0 = hand [ 0 ]
split_card_1 = hand [ 1 ]
2015-01-12 21:52:05 +00:00
players [ identity ] [ ' player_hands ' ] . insert ( idx + 1 , players [ identity ] [ ' player_hands ' ] [ idx ] . copy ( ) )
2015-01-24 21:51:33 +00:00
players [ identity ] [ ' player_hands ' ] [ idx ] [ ' hand ' ] = [ split_card_0 , DrawCard ( players [ identity ] [ ' deck ' ] ) ]
players [ identity ] [ ' player_hands ' ] [ idx + 1 ] [ ' hand ' ] = [ split_card_1 , DrawCard ( players [ identity ] [ ' deck ' ] ) ]
2015-01-12 21:52:05 +00:00
sidebets = players [ identity ] [ ' sidebets ' ]
if sidebets [ ' splits ' ] :
bet_units = sidebets [ ' splits ' ]
nsplits = len ( players [ identity ] [ ' player_hands ' ] )
if nsplits == 2 :
win_units = bet_units * 5
elif nsplits == 3 :
win_units = bet_units * ( 11 - 5 )
elif nsplits == 4 :
win_units = bet_units * ( 21 - 11 )
if nsplits == 2 :
link . send ( ' %s splits to %d - you win %s ' % ( link . user . nick , nsplits , AmountToString ( win_units ) ) )
else :
link . send ( ' %s resplits to %d - you win another %s ' % ( link . user . nick , nsplits , AmountToString ( win_units ) ) )
UpdateSidebetRecord ( link , " splits " , True , False , win_units )
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
link . send ( " %s : your hand is now %s . Dealer ' s hand is %s " % ( link . user . nick , PlayerHandsToString ( link ) , HandToString ( dealer_hand , identity in utf8users , True , False ) ) )
def Hand ( link , cmd ) :
identity = link . identity ( )
if not identity in players :
link . send ( " %s : you are not in a game of blackjack - you can start one with !blackjack <amount> " % link . user . nick )
return
units = players [ identity ] [ ' amount ' ]
dealer_hand = players [ identity ] [ ' dealer_hand ' ]
link . send ( " %s : your total bet is %s . Your hand is %s . Dealer ' s hand is %s " % ( link . user . nick , AmountToString ( units ) , PlayerHandsToString ( link , True ) , HandToString ( dealer_hand , identity in utf8users , True , False ) ) )
enough , reason = IsPlayerBalanceAtLeast ( link , units )
if not enough :
link . send ( " %s : %s - please refund your account to continue playing " % ( link . user . nick , reason ) )
def ResetBlackjackStats ( link , cmd ) :
identity = link . identity ( )
sidentity = GetParam ( cmd , 1 )
if sidentity :
sidentity = IdentityFromString ( link , sidentity )
if sidentity and sidentity != identity :
if not IsAdmin ( link ) :
log_error ( ' %s is not admin, cannot see blackjack stats for %s ' % ( identity , sidentity ) )
link . send ( ' Access denied ' )
return
else :
sidentity = identity
try :
ResetGameStats ( link , sidentity , " blackjack " )
except Exception , e :
link . send ( " An error occured " )
def ShowBlackjackStats ( link , sidentity , title ) :
return ShowGameStats ( link , sidentity , title , " blackjack " )
def GetBlackjackStats ( link , cmd ) :
identity = link . identity ( )
sidentity = GetParam ( cmd , 1 )
if sidentity :
sidentity = IdentityFromString ( link , sidentity )
if sidentity and sidentity != identity :
if not IsAdmin ( link ) :
log_error ( ' %s is not admin, cannot see blackjack stats for %s ' % ( identity , sidentity ) )
link . send ( ' Access denied ' )
return
else :
sidentity = identity
2015-01-21 22:00:22 +00:00
ShowBlackjackStats ( link , sidentity , NickFromIdentity ( sidentity ) )
ShowBlackjackStats ( link , " reset: " + sidentity , ' %s since reset ' % NickFromIdentity ( sidentity ) )
2015-01-12 21:52:05 +00:00
ShowBlackjackStats ( link , ' ' , ' overall ' )
def PlayerSeed ( link , cmd ) :
identity = link . identity ( )
fair_string = GetParam ( cmd , 1 )
if not fair_string :
link . send ( " Usage: !playerseed <string> " )
return
try :
SetPlayerSeed ( link , ' blackjack ' , fair_string )
except Exception , e :
log_error ( ' Failed to save player seed for %s : %s ' % ( identity , str ( e ) ) )
link . send ( ' An error occured ' )
def FairCheck ( link , cmd ) :
identity = link . identity ( )
try :
seed = GetServerSeed ( link , ' blackjack ' )
except Exception , e :
log_error ( ' Failed to get server seed for %s : %s ' % ( identity , str ( e ) ) )
link . send ( ' An error has occured ' )
return
try :
GenerateServerSeed ( link , ' blackjack ' )
except Exception , e :
log_error ( ' Failed to generate server seed for %s : %s ' % ( identity , str ( e ) ) )
link . send ( ' An error has occured ' )
return
link . send ( ' %s : your server seed was %s - it has now been reset; see !fair for details ' % ( link . user . nick , str ( seed ) ) )
def Seeds ( link , cmd ) :
identity = link . identity ( )
try :
sh = GetServerSeedHash ( link , ' blackjack ' )
ps = GetPlayerSeed ( link , ' blackjack ' )
except Exception , e :
log_error ( ' Failed to get server seed for %s : %s ' % ( identity , str ( e ) ) )
link . send ( ' An error has occured ' )
return
link . send ( ' %s : your server seed hash is %s ' % ( link . user . nick , str ( sh ) ) )
if ps == " " :
link . send ( ' %s : you have not set a player seed ' % link . user . nick )
else :
link . send ( ' %s : your player seed hash is %s ' % ( link . user . nick , str ( ps ) ) )
def UseUTF8 ( link , cmd ) :
identity = link . identity ( )
onoff = GetParam ( cmd , 1 )
if not onoff :
if identity in utf8users :
link . send ( ' %s : utf8 is enabled ' % link . user . nick )
else :
link . send ( ' %s : utf8 is disabled ' % link . user . nick )
elif onoff == " on " :
utf8users . add ( identity )
link . send ( ' %s : utf8 is now enabled ' % link . user . nick )
elif onoff == " off " :
utf8users . discard ( identity )
link . send ( ' %s : utf8 is now disabled ' % link . user . nick )
else :
link . send ( ' usage: !utf8 [on|off] ' )
def Fair ( link , cmd ) :
link . send_private ( " %s ' s blackjack betting is provably fair " % config . tipbot_name )
link . send_private ( " The deck shuffling is determined by three pieces of information: " )
link . send_private ( " - your server seed. You can see its hash with !seeds " )
link . send_private ( " - your player seed. Empty by default, you can set it with !playerseed " )
link . send_private ( " - the game number, displayed with each game you make " )
link . send_private ( " To verify past games were fair, use !faircheck " )
link . send_private ( " You will be given your server seed, and a new one will be generated " )
link . send_private ( " for future games. Then follow these steps: " )
link . send_private ( " Create a deck: 234567890JQKA - repeated %d times (4 suits, %d decks) " % ( 4 * config . blackjack_decks , config . blackjack_decks ) )
link . send_private ( " Calculate the SHA-256 sum of serverseed:playerseed:gamenumber " )
link . send_private ( " Use the resulting string as the seed for the Mersenne Twister PRNG " )
link . send_private ( " Shuffle the deck using the Fisher-Yates algorithm with that PRNG " )
link . send_private ( " Starting cards are dealt in the order: player, dealer, player, dealer " )
link . send_private ( " See !faircode for Python code implementing this check " )
def FairCode ( link , cmd ) :
link . send_private ( " This Python 2 code takes the seeds and game number and outputs the shuffled " )
link . send_private ( " deck used in the corresponding game. Run it with three arguments: server seed, " )
link . send_private ( " player seed (use ' ' if you did not set any), and game number. " )
link . send_private ( " import sys,hashlib,random " )
link . send_private ( " try: " )
link . send_private ( " deck=[ ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' 10 ' , ' J ' , ' Q ' , ' K ' , ' A ' ]* %s " % ( 4 * config . blackjack_decks ) )
link . send_private ( " s=hashlib.sha256(sys.argv[1]+ ' : ' +sys.argv[2]+ ' : ' +sys.argv[3]).hexdigest() " )
link . send_private ( " random.Random(s).shuffle(deck) " )
link . send_private ( " print str(deck) " )
link . send_private ( " except: " )
link . send_private ( " print ' need serverseed, playerseed, and game number ' " )
# rough house edges:
# over13: 7%
# under13: 10%
# pair: 6%
# climber: 3%
# buster: 5%
# splits: 8%
# match: 5%
# addup: 8%
def SideBets ( link , cmd ) :
link . send_private ( " Side bets are made by adding their name after the !blackjack <amount> command, eg: " )
link . send_private ( " !blackjack 1 buster over13 - bets 0.5 for dealer busting, and 0.5 for first 2 cards sum over 13 " )
link . send_private ( " Each side bet wager is for half of the amount wagered for the main blackjack game " )
link . send_private ( " Payouts depend on the side bet: " )
if " over13 " in config . blackjack_sidebets :
link . send_private ( " * over13 - 1:1 - Player ' s first two cards scores over 13 (aces count as 1) " )
if " under13 " in config . blackjack_sidebets :
link . send_private ( " * under13 - 1:1 - Player ' s first two cards scores under 13 (aces count as 1) " )
if " pair " in config . blackjack_sidebets :
link . send_private ( " * pair - 12:1 - Player ' s first two cards are a pair " )
if " climber " in config . blackjack_sidebets :
link . send_private ( " * climber - 2:1 to 21:1 - Player ' s first two cards scores 20, payout as dealer ' s first card ' s score, ace pays 21:1 " )
if " buster " in config . blackjack_sidebets :
link . send_private ( " * buster - 3:2 to 21:1 - Dealer busts with 3 cards (3:2), 4 (3:1), 5 (5:1), 6 (11:1), or 7+ (21:1) " )
if " splits " in config . blackjack_sidebets :
link . send_private ( " * splits - 5:1 to 21:1 - Split your hand to 2 (5:1), 3 (11:1), or 4 (21:1) " )
if " match " in config . blackjack_sidebets :
link . send_private ( " * match - 5:1 to 21:1 - Match the dealer ' s first card with one (5:1) or both (21:1) or the player ' s first two cards " )
if " addup " in config . blackjack_sidebets :
link . send_private ( " * addup - 27:1 - Sum of player ' s first two cards ' scores match the dealer ' s first card ' s score " )
def BlackjackHelp ( link ) :
link . send_private ( " The blackjack module is a provably fair %s blackjack betting game " % coinspecs . name )
link . send_private ( " Basic usage: !blackjack <amount> " )
link . send_private ( " The goal is to get a hand totalling as close to 21 without going over " )
link . send_private ( " and have a total higher than the dealer. Suits do not matter. " )
link . send_private ( " Available moves are: !hit (get a new card), !stand (finish playing the curent), " )
link . send_private ( " hand, !double (double your bet and take a final card), !split (split a hand of " )
link . send_private ( " two cards with equal value), and !insurance (when the dealer ' s first card is an ace " )
link . send_private ( " See !fair and !faircode for a description of the provable fairness of the game " )
link . send_private ( " See !faircheck to get the server seed to check past games were fair " )
if len ( config . blackjack_sidebets ) > 0 :
link . send_private ( " See !sidebets for a list of available side bets and how to use them " )
random . seed ( time . time ( ) )
RegisterModule ( {
' name ' : __name__ ,
' help ' : BlackjackHelp ,
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' blackjack ' ,
2015-01-24 16:58:14 +00:00
' parms ' : ' <amount-in- %s > ' % coinspecs . name if len ( config . blackjack_sidebets ) == 0 else ' <amount-in- %s > [sidebet1 [sidebet2...]] ' % coinspecs . name ,
2015-01-12 21:52:05 +00:00
' function ' : Blackjack ,
' registered ' : True ,
' help ' : " start a blackjack game - blackjack pays 3:2 "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' hit ' ,
' function ' : Hit ,
' registered ' : True ,
' help ' : " Hit (draw a new card on the current hand) "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' double ' ,
' function ' : Double ,
' registered ' : True ,
' help ' : " Double down (double bet and draw a final card on the current hand) "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' stand ' ,
' function ' : Stand ,
' registered ' : True ,
' help ' : " Stand (finish the current hand) "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' split ' ,
' function ' : Split ,
' registered ' : True ,
' help ' : " Split current hand if first two cards are a pair - split to %d max " % config . blackjack_split_to
} )
if config . blackjack_insurance :
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' insurance ' ,
' function ' : Insurance ,
' registered ' : True ,
' help ' : " Insure against a dealer blackjack with half your bet (offered if the dealer ' s first card in an ace) - paid 2:1 "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' hand ' ,
' function ' : Hand ,
' registered ' : True ,
' help ' : " Show your and the dealer ' s current hands "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' stats ' ,
' parms ' : ' [<name>] ' ,
' function ' : GetBlackjackStats ,
' registered ' : True ,
' help ' : " displays your blackjack stats "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' resetstats ' ,
' parms ' : ' [<name>] ' ,
' function ' : ResetBlackjackStats ,
' registered ' : True ,
' help ' : " resets your Blackjack stats "
} )
if len ( config . blackjack_sidebets ) > 0 :
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' sidebets ' ,
' function ' : SideBets ,
2015-01-21 19:18:56 +00:00
' registered ' : True ,
2015-01-12 21:52:05 +00:00
' help ' : " List the available side bets "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' playerseed ' ,
' parms ' : ' <string> ' ,
' function ' : PlayerSeed ,
' registered ' : True ,
' help ' : " set a custom seed to use in the hash calculation "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' seeds ' ,
' function ' : Seeds ,
' registered ' : True ,
' help ' : " Show hash of your current server seed and your player seed "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' utf8 ' ,
' parms ' : ' [on|off] ' ,
' function ' : UseUTF8 ,
' registered ' : True ,
' help ' : " Enable or disable use of UTF-8 to display cards "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' faircheck ' ,
' function ' : FairCheck ,
' registered ' : True ,
' help ' : " Check provably fair rolls "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' fair ' ,
' function ' : Fair ,
2015-01-21 19:18:56 +00:00
' registered ' : True ,
2015-01-12 21:52:05 +00:00
' help ' : " describe the provably fair blackjack game "
} )
RegisterCommand ( {
' module ' : __name__ ,
' name ' : ' faircode ' ,
' function ' : FairCode ,
2015-01-21 19:18:56 +00:00
' registered ' : True ,
2015-01-12 21:52:05 +00:00
' help ' : " Show sample Python code to check game fairness "
} )