Zend - The PHP Company




Games

Add Code


Blackjack Player  

Type: application
Added by: codewalkers
Entered: 13/05/2004
Last modified: 05/12/2003
Rating: - (fewer than 3 votes)
Views: 8621
This is a winner of the Codewalkers.com Coding Contest. This script will play blackjack.


<?
/* *******************************************************************************************
* Artificial Black Jack Player by Thomas Ilsche for codewalkers.com contest

* Author: Thomas Ilsche
* Date: 29 FEB 2004 {1078086447}

* Notes:
* I removed the comments to hide my poor language skills, they were in german anyway.
* Alot of the coding is sloppy due to me having so few time.
* At some parts the readability is sacrificed to performance.
*
* License Information:
* - This may be placed on codewalkers.com and zend.com.
* - Commercial use or any use with the intention to make any kind of profit is scritly prohibited.
* - This software is provided 'as-is', without any express or implied warranty.
* - The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
* - This notice may not be removed or altered from any source distribution.
* *******************************************************************************************/

include('blackjacklib.php');

$default_comp_stats = array ( => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.057045406195118 => 0.19948734603319 => 0.34214642965220 => 0.4855143591421 => 0.86061584285822 => 0.139384157142, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.1300091907918 => 0.26541778193819 => 0.39733865813720 => 0.52299515329621 => 0.64340657414422 => 0.356593425856, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.12545713347518 => 0.25736969309519 => 0.38364480020320 => 0.506218200321 => 0.62278219269422 => 0.377217807306, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.12251428264918 => 0.24598364964119 => 0.36846572983220 => 0.48627759048421 => 0.60011271733322 => 0.399887282667, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.11781399873318 => 0.2409962941219 => 0.35906612832520 => 0.47010820324221 => 0.57836578032922 => 0.421634219671, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.11528476923618 => 0.22963110831619 => 0.34487836090420 => 0.45494571142421 => 0.56097795051822 => 0.439022049482, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.36984538344818 => 0.50790906252419 => 0.5861329064320 => 0.66486657046121 => 0.738454044497,
22 => 0.261545955503, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.1293166640818 => 0.48988688817119 => 0.61876280582120 => 0.68780233129221 => 0.75734427165622 => 0.242655728344, ), => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.12062470466518 => 0.23531333765719 => 0.58826296835220 => 0.70900552285921 => 0.76993381732822 => 0.230066182672, ), 10 => array ( => 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 0=> 010 => 011 => 012 => 013 => 014 => 015 => 016 => 017 => 0.11240736625318 => 0.22431993289619 => 0.3367922800120 => 0.67461100025321 => 0.78716827466122 => 0.212831725339, ), );

function 
get_microtime()
{
    list(
$usec$sec) = explode(' 'microtime());
    return ((float)
$usec + (float)$sec);
}

function 
best_val($hand)
{
    
$sum 0;
    
$aces 0;
    foreach(
$hand as $card)
    {
        if (
$card 9)
        {
            
$sum += 10;
        }
        else
        {
            if (
$card == 1)
            {
                
$sum++;
                
$aces++;
            }
            else
            {
                
$sum += $card;
            }
        }
    }
    while (
$aces && ($sum 10) <= 21)
    {
        
$sum += 10;
        
$aces--;
    }
    return 
$sum;
}

$sub_start get_microtime();
$rules StartGame();
$x $rules['decks'] * 4;
$deck = array(1=>$x,2=>$x,3=>$x,4=>$x,5=>$x,6=>$x,7=>$x,8=>$x,9=>$x,10=>4*$x);

while (
1)
{
    if (isset(
$result)) $bet min($rules['maximumbet'],$result['money']);
    else 
$bet $rules['maximumbet'];
    
$result MakeBet($bet);
    
    
$deck[min(10,$result['dealercards'][0])]--;
    
$deck[min(10,$result['yourcards'][0][0])]--;
    
$deck[min(10,$result['yourcards'][0][1])]--;
    
    
$first true;
    
$comp_stats_calced false;
      while (
$result['status'] == 'YOURTURN')
      {
    
$e_win = array();
    
$last_was_hit false;

    
$hand_points 0;
    
$aces 0;
    foreach(
$result['yourcards'][$result['activehand']] as $card)
    {
        if (
$card 9)
        {
            
$hand_points += 10;
        }
        else
        {
            if (
$card == 1)
            {
                
$hand_points++;
                
$aces++;
            }
            else
            {
                
$hand_points += $card;
            }
        }
    }

    
$best_hand_points $hand_points;
    
$best_aces $aces;
    while (
$best_aces && ($best_hand_points+10) <= 21)
    {
        
$best_hand_points += 10;
        
$best_aces--;
    }

    if (
$best_hand_points == 21)
    {
        
$result PlayStand();
    }
    else
    {
        
$activehand_count count($result['yourcards'][$result['activehand']]);
        
        if (
$rules['double'] && $first && ( $result['money'] >= $result['currentbet']) ) {
            
check_comp_stats();
            
$e_win['double'] = expected_win_double($hand_points$deck$aces);
        }
        else {
            
$e_win['double'] = -1;
        }

        if ( 
$rules['split'] && ( $activehand_count == ) && ($result['yourcards'][$result['activehand']][0] == $result['yourcards'][$result['activehand']][1])  && ( $result['money'] >= $result['currentbet']) ) {
            
check_comp_stats();
            
$recursion 0;

            
$deck_cards_left array_sum($deck) - 1;
            if (
$deck_cards_left >= 7) {
                
$e_win['split'] = expected_win_draw_low($hand_points/2$deck$aces/2)*1;
            }
            elseif (
$deck_cards_left == 2) {
                
$e_win['split'] = expected_win_double($hand_points/2$deck$aces/2)*1;
            }
            elseif (
$deck_cards_left 2) {
                
$e_win['split'] = -1;
            }
            elseif (
$deck_cards_left == 0) {
                
$cardsleft $deck_cards_left 2;
                
$e_win['split'] = expected_win_draw_cardsleft($hand_points/2$deck$aces/2)*1;
            }
            else {
                
$cardsleft floor($deck_cards_left 2);
                
$e_win['split'] = expected_win_draw_cardsleft($hand_points/2$deck$aces/2);
                
$cardsleft++;
                
$e_win['split'] += expected_win_draw_cardsleft($hand_points/2$deck$aces/2) - 1;
            }
        }
        else {
            
$e_win['split'] = -1;
        }

        if ( (
$hand_points 12) && ($aces == 0) && ( array_sum($deck) > 15 ) )
        {
            if ( ( 
$e_win['split'] > ) || ( $e_win['double'] > ) ) {
                
$recursion 0;
                
$e_win['hit'] = expected_win_draw_low($hand_points$deck$aces);
            }
            
$e_win['hit'] = 1;
            
$e_win['stand'] = -1;
        }
        else
        {
            
$checked check_comp_stats();
            if ( ( 
array_sum($deck) < 11 ) &&  ( get_microtime() - $sub_start 45 ) )
            {
                if (!
$checked) {
                    
check_comp_stats(true);
                }
                
$e_win['hit'] = expected_win_draw_total_enum($hand_points$deck$aces);
                
$e_win['stand'] = expected_win_stop($hand_points,$deck,$aces);
            }
            elseif ( ( 
array_sum($deck) < 50) && ( get_microtime() - $sub_start 45 ) )
            {
                if (!
$checked) {
                    
check_comp_stats(true);
                }
                
$recursion 0;
                
$e_win['stand'] = expected_win_stop($hand_points,$deck,$aces);
                
$e_win['hit'] = expected_win_draw_slow($hand_points,$deck,$aces);
            }
            elseif ( ( 
get_microtime() - $sub_start ) > 45 * ( array_sum($deck) / ( $rules['decks'] * 52 ) ) )
            {
                
$recursion 0;
                
$e_win['stand'] = expected_win_stop($hand_points,$deck,$aces);
                
$e_win['hit'] = expected_win_draw_hurry($hand_points,$deck,$aces);
            }
            else
            {
                
$recursion 0;
                
$e_win['stand'] = expected_win_stop($hand_points,$deck,$aces);
                
$e_win['hit'] = expected_win_draw($hand_points,$deck,$aces);

                if (
abs($e_win['stand'] - $e_win['hit']) < 0.1) {
                    if (!
$checked) {
                        
check_comp_stats(true);
                    }
                    
$e_win['hit'] = expected_win_draw_slow($hand_points,$deck,$aces);
                    
$e_win['stand'] = expected_win_stop($hand_points,$deck,$aces);
                }
            }
        }
        if (
$first && $rules['surrender'] && ( max($e_win) < 0.5 ) ) {
            
$last_decition 'surrender';
            
$result PlaySurrender();
        }
        elseif (
$e_win['stand'] == max($e_win))                    
        {
            
$result PlayStand();
        }
        elseif (
$e_win['double'] == max($e_win))
        {
            
$last_active_hand $result['activehand'];
            
$result PlayDouble();
            
$deck[min(10,end($result['yourcards'][$last_active_hand]))]--;
        }
        elseif (
$e_win['hit'] == max($e_win))
        {
            
$last_active_hand $result['activehand'];
            
$result PlayHit();
            
$deck[min(10,end($result['yourcards'][$last_active_hand]))]--;
        }
        elseif (
$e_win['split'] == max($e_win))
        {
            
$last_active_hand $result['activehand'];
            
$result PlaySplit();
            
$deck[min(10,end($result['yourcards'][$last_active_hand]))]--;
            
$deck[min(10,end($result['yourcards'][$last_active_hand+1]))]--;
        }
    }
    
$first false;
    }
    for (
$i 1;$i count($result['dealercards']); $i++)
    {
        
$deck[min(10,$result['dealercards'][$i])]--;
    }
}

function 
expected_win_draw_slow($hand_points,$deck,$aces)
{
    if ( ( 
$hand_points 20 ) || ( $aces ) || ( $hand_points == 11 && $aces ) )
    {
        return 
expected_win_stop($hand_points$aces);
    }

    
$cards_in_deck array_sum($deck);
    if ( 
$cards_in_deck <= ) {
        return 
expected_win_stop($hand_points$aces);
    }
    
    
$e_w 0;
    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            if (
$hand_points $points 20) {
                
$e_w += expected_win_stop($hand_points $points,$aces) * $count $cards_in_deck;
            }
            else {
                
$deck[$points]--;
                
$e_w += max(expected_win_stop($hand_points $points,$aces), expected_win_draw_slow($hand_points $points,$deck,$aces) ) * $count $cards_in_deck;
                
$deck[$points]++;
            }
        }
        if (
$points == 1$aces--;
    }
    return 
$e_w;
}

function 
expected_win_draw($hand_points,$deck,$aces)
{
    if ( ( 
$hand_points 20) || ( $hand_points == 11 && $aces ) )
    {
        return 
expected_win_stop($hand_points$deck$aces);
    }
    
    if ( ( (
$GLOBALS['recursion'] + $aces ) > 4) && ($hand_points 18 || $aces 1) ) {
        return 
expected_win_stop($hand_points$aces);
    }
    
    
$cards_in_deck array_sum($deck);
    
$e_w 0;
    
$GLOBALS['recursion']++;
    
    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            if (
$hand_points $points 20) {
                
$e_w += expected_win_stop($hand_points $points,$aces) * $count $cards_in_deck;
            }
            else {
                
$deck[$points]--;
                
$e_w += max(expected_win_stop($hand_points $points,$aces), expected_win_draw($hand_points $points,$deck,$aces) ) * $count $cards_in_deck;
                
$deck[$points]++;
            }
        }
        if (
$points == 1$aces--;
    }
    
$GLOBALS['recursion']--;
    return 
$e_w;
}


function 
expected_win_stop($hand_points,$aces)
{
    if (
$hand_points 21) {
        return 
$GLOBALS['comp_stats'][22];
    }
    while (
$aces && ($hand_points+10) <= 21)
    {
        
$hand_points += 10;
        
$aces--;
    }

    return 
$GLOBALS['comp_stats'][$hand_points-1] + $GLOBALS['comp_stats'][$hand_points] + $GLOBALS['comp_stats'][22] * 2;
}


function 
calc_comp_stats($hand_points$deck$aces$p)
{
    
$best_hand_points $hand_points;
    
$best_aces $aces;
    while (
$best_aces && ($best_hand_points+10) <= 21)
    {
        
$best_hand_points += 10;
        
$best_aces--;
    }
    if ((
$best_hand_points 17) || ( $best_hand_points == 17 && ( $GLOBALS['rules']['standsoft17'] || ( $hand_points == $best_hand_points ) ) ) ) {
        
$GLOBALS['comp_stats'][min($best_hand_points,22)] += $p;
    }
    else
    {
        
$cards_in_deck array_sum($deck);
        if (
$cards_in_deck 0)
        {
            foreach (
$deck as $points => $count)
            {
                if (
$count 0) {
                    
$deck[$points]--;
                    
calc_comp_stats($hand_points+$points$deck, ($points == 1) ? $aces+$aces$p $count $cards_in_deck);
                    
$deck[$points]++;
                }
            }
        }
        else
        {
            
$GLOBALS['comp_stats'][min($best_hand_points,22)] += $p;
        }
    }
}

function 
expected_win_draw_hurry($hand_points,$deck,$aces)
{
    if (
$hand_points 20)
    {
        return 
expected_win_stop($hand_points$aces);
    }
    
    if ( ( (
$GLOBALS['recursion'] + $aces ) > 3) && ($hand_points 17 || $aces 0) ) {
        return 
expected_win_stop($hand_points$aces);
    }
    
    
$cards_in_deck array_sum($deck);
    
$e_w 0;
    
$GLOBALS['recursion']++;
    
    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            if (
$hand_points $points 20) {
                
$e_w += expected_win_stop($hand_points $points,$aces) * $count $cards_in_deck;
            }
            else {
                
$deck[$points]--;
                
$e_w += max(expected_win_stop($hand_points $points,$aces), expected_win_draw_hurry($hand_points $points,$deck,$aces) ) * $count $cards_in_deck;
                
$deck[$points]++;
            }
        }
        if (
$points == 1$aces--;
    }
    
$GLOBALS['recursion']--;
    return 
$e_w;
}

function 
expected_win_draw_cardsleft($hand_points,$deck,$aces)
{
    if (
$hand_points 20)
    {
        return 
expected_win_stop($hand_points$aces);
    }

    if ( 
$GLOBALS['recursion'] >= $GLOBALS['cardsleft'] ) {
        return 
expected_win_stop($hand_points$aces);
    }
    
    
$cards_in_deck array_sum($deck);
    
$e_w 0;
    
$GLOBALS['recursion']++;
    
    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            if (
$hand_points $points 20) {
                
$e_w += expected_win_stop($hand_points $points,$aces) * $count $cards_in_deck;
            }
            else {
                
$deck[$points]--;
                
$e_w += max(expected_win_stop($hand_points $points,$aces), expected_win_draw_cardsleft($hand_points $points,$deck,$aces) ) * $count $cards_in_deck;
                
$deck[$points]++;
            }
        }
        if (
$points == 1$aces--;
    }
    
$GLOBALS['recursion']--;
    return 
$e_w;
}


function 
expected_win_double($hand_points,$deck,$aces)
{
    
$cards_in_deck array_sum($deck);
    
$e_w 0;

    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            
$e_w += expected_win_stop($hand_points $points,$aces) * $count $cards_in_deck;
        }
        if (
$points == 1$aces--;
    }
    return 
$e_w*2-1;
}


function 
check_comp_stats($enforce false)
{
    global 
$comp_stats_calced;
    if (!
$comp_stats_calced || $enforce) {
        global 
$deck,$default_comp_stats,$comp_stats,$result,$deck;
        if (
array_sum($deck) > 70) {
            
$comp_stats $default_comp_stats[min(10,$result['dealercards'][0])];
        }
        else
        {
            
$comp_stats = array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
            
calc_comp_stats(min(10,$result['dealercards'][0]),$deck,($result['dealercards'][0]==1)?1:0,1);
            
$s 0;
            for (
$i 0;$i 22;$i++)
            {
                
$s += $comp_stats[$i];
                
$comp_stats[$i] = $s;
            }
        }
        
$comp_stats_calced true;
        return 
true;
    }
    else return 
false;
}

function 
expected_win_draw_total_enum($hand_points,$deck,$aces)
{
    if (
$hand_points 20)
    {
        return 
expected_win_stop_total_enum($hand_points$deck$aces);
    }
    
    
$cards_in_deck array_sum($deck);

    if (
$cards_in_deck <= 1)
    {
        return 
expected_win_stop_total_enum($hand_points$deck$aces);
    }


    
$e_w 0;

    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            if (
$hand_points $points 20) {
                
$e_w += expected_win_stop_total_enum($hand_points $points,$deck,$aces) * $count $cards_in_deck;
            }
            else {
                
$deck[$points]--;
                
$e_w += max(expected_win_stop_total_enum($hand_points $points,$deck,$aces), expected_win_draw_total_enum($hand_points $points,$deck,$aces) ) * $count $cards_in_deck;
                
$deck[$points]++;
            }
        }
        if (
$points == 1$aces--;
    }
    return 
$e_w;
}

function 
expected_win_stop_total_enum($hand_points,$deck,$aces)
{
    global 
$result;
    if (
$hand_points 21) {
        return 
calc_comp_stats_total_enum_burst(min(10,$result['dealercards'][0]), $deck, (min(10,$result['dealercards'][0]) == 1) ? 01);
    }
    while (
$aces && ($hand_points+10) <= 21)
    {
        
$hand_points += 10;
        
$aces--;
    }
    
$GLOBALS['total_enmum_hand_points'] = $hand_points;
    return 
calc_comp_stats_total_enum(min(10,$result['dealercards'][0]), $deck,(min(10,$result['dealercards'][0]) == 1) ? 01);
}

function 
calc_comp_stats_total_enum($hand_points$deck$aces$p)
{
    
$best_hand_points $hand_points;
    
$best_aces $aces;
    while (
$best_aces && ($best_hand_points+10) <= 21)
    {
        
$best_hand_points += 10;
        
$best_aces--;
    }
    if ((
$best_hand_points 17) || ( $best_hand_points == 17 && ( $GLOBALS['rules']['standsoft17'] || ( $hand_points == $best_hand_points ) ) ) ) {
        if (
$best_hand_points 21) {
            return 
$p;
        }
        elseif (
$best_hand_points $GLOBALS['total_enmum_hand_points']) {
            return 
0;
        }
        elseif (
$best_hand_points $GLOBALS['total_enmum_hand_points']) {
            return 
$p;
        }
        elseif (
$best_hand_points == $GLOBALS['total_enmum_hand_points']) {
            return 
$p;
        }
    }
    else
    {
        
$cards_in_deck array_sum($deck);
        if (
$cards_in_deck 0)
        {
            
$player_win 0;
            foreach (
$deck as $points => $count)
            {
                if (
$count 0) {
                    
$deck[$points]--;
                    
$player_win += calc_comp_stats_total_enum($hand_points+$points$deck, ($points == 1) ? $aces+$aces$p $count $cards_in_deck);
                    
$deck[$points]++;
                }
            }
            return 
$player_win;
        }
        else
        {
            if (
$best_hand_points 21) {
                return 
$p;
            }
            elseif (
$best_hand_points $GLOBALS['total_enmum_hand_points']) {
                return 
0;
            }
            elseif (
$best_hand_points $GLOBALS['total_enmum_hand_points']) {
                return 
$p;
            }
            elseif (
$best_hand_points == $GLOBALS['total_enmum_hand_points']) {
                return 
$p;
            }
        }
    }
}

function 
calc_comp_stats_total_enum_burst($hand_points$deck$aces$p)
{
    
$best_hand_points $hand_points;
    
$best_aces $aces;
    while (
$best_aces && ($best_hand_points+10) <= 21)
    {
        
$best_hand_points += 10;
        
$best_aces--;
    }
    if ((
$best_hand_points 17) || ( $best_hand_points == 17 && ( $GLOBALS['rules']['standsoft17'] || ( $hand_points == $best_hand_points ) ) ) ) {
        if (
$best_hand_points 21) {
            return 
$p;
        }
        else {
            return 
0;
        }
    }
    else
    {
        
$cards_in_deck array_sum($deck);
        if (
$cards_in_deck 0)
        {
            
$player_win 0;
            foreach (
$deck as $points => $count)
            {
                if (
$count 0) {
                    
$deck[$points]--;
                    
$player_win += calc_comp_stats_total_enum_burst($hand_points+$points$deck, ($points == 1) ? $aces+$aces$p $count $cards_in_deck);
                    
$deck[$points]++;
                }
            }
            return 
$player_win;
        }
        else
        {
            if (
$best_hand_points 21) {
                return 
$p;
            }
            else {
                return 
0;
            }
        }
    }
}

function 
expected_win_draw_low($hand_points,$deck,$aces)
{
    if (
$hand_points 20)
    {
        return 
expected_win_stop($hand_points$deck$aces);
    }

    if ( ( (
$GLOBALS['recursion'] + $aces ) > 4) && ($hand_points 18 || $aces 1) ) {
        return 
expected_win_stop($hand_points$deck$aces);
    }
    
    if ( 
$GLOBALS['recursion'] == 3) {
        for (
$i 3;$i 8;$i+=2)
        {
            
$deck[$i] += $deck[$i-1];
            
$deck[$i-1] = 0;
        }
    }
    if ( 
$GLOBALS['recursion'] == 4) {
        
$deck[4] += $deck[3] + $deck[5];
        
$deck[3] = 0;
        
$deck[5] = 0;
    }

    
    
$cards_in_deck array_sum($deck);
    
$e_w 0;
    
$GLOBALS['recursion']++;
    
    
$aces++;
    foreach (
$deck as $points => $count)
    {
        if (
$count 0) {
            if (
$hand_points $points 20) {
                
$e_w += expected_win_stop($hand_points $points,$aces) * $count $cards_in_deck;
            }
            else {
                
$deck[$points]--;
                
$e_w += max(expected_win_stop($hand_points $points,$aces), expected_win_draw_low($hand_points $points,$deck,$aces) ) * $count $cards_in_deck;
                
$deck[$points]++;
            }
        }
        if (
$points == 1$aces--;
    }
    
$GLOBALS['recursion']--;
    return 
$e_w;
}
?>


Usage Example


See the example


Rate This Script





Search



This Category All Categories