Um concurso de BlackJack KOTH

13

BlackJack

Como eu me diverti muito trabalhando no desafio KOTH original, eu queria criar outro. Para mim, a diversão desses desafios de IA é refinar um bot comparativamente simples que joga um jogo muito simples sutilmente. Devido à natureza probabilística dos jogos de cartas, acho que o blackjack poderia ser um jogo KOTH interessante, como o TPD.

Todas as regras são derivadas da descrição deste site do BlackJack com sapatos

Regras relativas às cartas e ao baralho

  • Bots jogam em mesas de quatro (4) competidores e um (1) croupier
  • Um (1) sapato (um baralho embaralhado) é compartilhado por todos os jogadores e pelo dealer até que se esgote; nesse ponto, um novo baralho embaralhado aleatoriamente será adicionado e o jogo continuará. Os bots NÃO SÃO (atualmente) NOTIFICADOS com a adição deste novo baralho. Essa notificação pode ser adicionada se a falta desse recurso causar sofrimento / problemas suficientes.
  • Há um buy-in de 10 por rodada e os cartões são gratuitos
  • A mão perfeita / ideal tem uma pontuação de 21
  • Todas as cartas de cara têm um valor de 10
  • Todos os cartões numéricos valem seu número
  • Ases valem 11 ou 1. isso será tratado automaticamente pela estrutura, não pelos bots.
  • De acordo com as regras , todas as cartas dos jogadores são viradas para cima e são visíveis. Uma das cartas do dealer está voltada para baixo e a outra, voltada para cima.

Pontuação

  • Pontuações acima de 21 que usam um ás como 11 forçam o ás a reduzir em valor para 1
  • pontuações acima de 21, que não podem ser coagidas abaixo do limiar de 21, "rebentam" o bot

O negociante

  • O carteador empata até que ele bote ou ultrapasse uma pontuação de 17 , quando é forçado a ficar

Apostas e fichas

  • No início de cada rodada, é cobrado um buy-in de 10, para que haja uma aposta mínima de 10 e uma aposta mínima de 1. NOTA - a aposta é o valor absoluto do argumento da aposta, portanto, não se preocupe tentando apostas negativas.
  • Bots que não podem pagar o buy-in são removidos do concurso
  • Ao fazer apostas, os bots não podem apostar mais do que as fichas que possuem
  • Se a aposta for possível, as fichas apostadas são removidas imediatamente do bot e adicionadas à aposta
  • Ganhar uma aposta dá ao bot 2x fichas. No entanto, como a aposta é subtraída das fichas do bot, o bot é equilibrado e ganha 1x a aposta.
  • Os bots vencem apostas apenas se a pontuação for maior que a do croupier

Repartição da jogabilidade

Uma mão

  1. Quando o jogo começa, cada jogador recebe iterativamente uma carta e tem a taxa de buy-in de $ 10 / aposta mínima subtraída de suas fichas.
  2. O revendedor desenha
  3. Um segundo passe é feito e outra carta é distribuída a todos os jogadores.
  4. O revendedor desenha
  5. Então (na mesma ordem em que foram distribuídos) cada bot é executado conforme descrito na seção "Interface do programador" e deve fazer um movimento ou permanecer em pé. Apostar é considerado uma jogada. OBSERVAÇÃO QUE A APOSTA NÃO AFETA A CAPACIDADE DO BOTS DE FAZER MAIS MOVIMENTOS. É muito possível apostar e depois comprar uma carta, e é possível comprar várias cartas e elas apostam antes de ficar de pé.
  6. Quando todos os bots foram eliminados, o dealer joga até o limiar de 17
  7. A pontuação dos bots é então comparada com a do dealer, as apostas são ganhas e perdidas

Uma rodada

É considerado constituído por cinco (5) mãos. Entre as mãos, a lista de participantes é classificada para remover jogadores e depois processada para garantir que todos os bots joguem o mesmo número de mãos (uma provisão para o fato de que o número de entradas não será dividido igualmente entre as mesas de quatro bot )

Interface do programador e movimentos legais

Conforme documentado no arquivo CardShark:

#   DOCUMENTATION
#       INPUT SPECIFICATION
#          $ ./foo.bar <hand-score> <hand> <visible cards> <stake> <chips>
#          <hand-score>     is the present integer value of the player's hand.
#          <hand>           is a space-free string of the characters [1-9],A,J,Q,K
#          <visible cards>  every dealt card on the table. when new shoes are brought
#                           into play, cards drawn therefrom are simply added to this list
#                           NOTE: the first TWO (2) cards in this list belong to the dealer.
#                             one however will be "hidden" by a "#". the other is visible.
#                           !!! THE LIST IS CLEARED AT THE END OF HANDS, NOT SHOES !!!
#          <stake>          the  number of chips which the bot has bet this hand
#          <chips>          the number of chips which the bot has
#       SAMPLE INPUT
#          $ ./foo.bar 21 KJA KQKJA3592A 25 145
#
#       OUTPUT SPECIFICATION
#          "H"|"S"|"D"|"B"  (no quotes in output)
#          "H"              HIT - deal a card
#          "S"              STAND - the dealer's turn
#          "D"              DOUBLEDOWN - double the bet, take one card. FIRST MOVE ONLY
#          "B 15"           BET - raises the bot's stakes by $15.

Como (agora) documentado no arquivo Cards:

#       class CARD
#           card is a container for representing paper playing cards in
#           otherwise fairly functional programming.
#           letter()
#               gets the letter used to identify the card in a string  
#               LETTER MAPPINGS  
#                   Ace     :   'A'
#                   Two     :   '2'
#                   Three   :   '3'
#                   Four    :   '4'
#                   Five    :   '5'
#                   Six     :   '6'
#                   Seven   :   '7'
#                   Eight   :   '8'
#                   Nine    :   '9'
#                   Ten     :   'T'
#                   Jack    :   'J'
#                   Queen   :   'Q'
#                   King    :   'K'
#                   "Hidden":   '#'

O código fonte do sistema de pontuação está AQUI

Bots de amostra

Lim 17

#!/usr/bin/env python
import sys
s = sys.argv
if int(s[1]) < 17:
    print "H"
else:
    print "S"

Idiomas de Entrada

Atualmente, Java, c / c ++, Python e Lisp são suportados. Será feito um esforço razoável para incluir envios em outros idiomas, mas lembre-se de que o concurso final será realizado em uma caixa Linux.

Seleção de Vencedores

O vencedor seria o autor do bot, que acumulava consistentemente o maior número de fichas em um número ainda determinado de mesas e rodadas. O vencedor será anunciado em 3 de junho, mas o anúncio poderá ser adiado se ainda houver envios. Concurso prorrogado por tempo indeterminado.

arrdem
fonte
Pergunta: as cartas visíveis incluem as da mão do próprio jogador?
dmckee --- ex-moderador gatinho
Segunda pergunta: sabemos quantas cartas foram distribuídas que não podemos ver?
dmckee --- gatinho ex-moderador 28/05
Responda a # 1 - sim; Resposta ao número 2 - da maneira como esse mecanismo é implementado, não há cartões ocultos. Cartões visíveis são todos os cartões distribuídos por todos os sapatos consumidos durante a rodada atual. os retornos de cartões visíveis não são limpos em sapatos novos (porque parte do sapato antigo provavelmente ainda está em jogo), mas em vez disso, na finalização da rodada. Essa é uma escolha de arquitetura que fiz para simplificar, que pode ser revisada se você achar a falta de cartões ocultos problemática.
Arrdem 28/05
Atualização: verifique o link das regras. O mecanismo agora implementa cartões ocultos, mas o único cartão oculto atualmente é um dos cartões básicos do revendedor.
Arrdem 28/05
Como os bots podem distinguir qual cartão visível é o revendedor?
Cthom06 02/06

Respostas:

3

BlackJackDavey

Chato, antiquado c. Compilador deve sob ANSI ou c99.

/* BlackJackDavey
 *
 * A entry for
 * http://codegolf.stackexchange.com/questions/2698/a-blackjack-koth-contest
 * copyright 2011 
 *
 * Currently expects a slightly extended version of the spec. Two
 * expected changes:
 * - Tens will be represented as 'T'
 * - The visible card string will include '#' for those cards whose
 *     *backs* we can see (slight improvement in card counting technique)
 * 
 * No disaster if neither feature is present, just sligtly degraded
 * performance.
 */
#include <stdio.h>
#include <string.h>

/* A full deck has a total value of 4*( (11*5) + (3*10) + ace ) where
 * ace is 11 or according to our need.
 **/
int fullWeight(const int current){
  int ace = (current>10) ? 1 : 11;
  return 4 * ( 11*5 + 3*10 + ace);
}
/* Return the value of a particular card in the context of our
 * current score
 */
int cardWeight(const char c, const int current){
 switch (c) {
 case '1': case '2': case '3': case '4': case '5':
 case '6': case '7': case '8': case '9':
   return (c - '0');
 case 'T': case 'J': case 'Q': case 'K':
   return 10;
 case 'A':
   return current>10 ? 1 : 11;
 }
 return 0;
}
/* returns the mean card *value* to be expected from the deck 
 *
 * Works by computing the currently unknown value and diviing by the
 * number of remaining cards 
 */
float weight(const char*known, const int current){
  int weight = fullWeight(current);
  int count=52;
  int uCount=0;
  const char*p=known;
  while (*p != '\0') {
    if (*p == '#') { /* Here '#' is a stand in for the back of a card */
      uCount++;
    } else {
      weight -= cardWeight(*p,current);
    }
    count--;
    p++;
    if ( count==0 && *p != '\0') {
      count += 52;
      weight += fullWeight(current);
    }
  }
  return (1.0 * weight)/(count+uCount);
}


int main(int argc, char*argv[]){
  int score=atoi(argv[1]);
  const char*hand=argv[2];
  const char*visible=argv[3];
  int stake=atoi(argv[4]);
  int chips=atoi(argv[5]);

  /* If current stake is less than 10, bet all the rest because a loss
     does not leave us enough to continue */
  if (chips < 10 && chips > 0) {
    printf("B %d\n",chips);
    return 0;
  }
  /* First round stategy differs from the rest of the game */
  if (strlen(hand)==2 && stake==10) {
    switch(score){
    case 10:
    case 11: /* Double down on particularly strong hands */
      if (chips >= 10) {
    printf("D\n");
    return 0;
      }
      break;
    default:
      break;
    };
  }
  /* In future rounds or when first round spcialls don't apply it is
     all about maximizing chance of getting a high score */
  if ((score + weight(visible,score)) <= 21) {
    /* if the oods are good for getting away with it, hit */
    printf("H\n");
    return 0;
  }
  /* Here odd are we bust if we hit, but if we are too low, the dealer
     probably makes it.*/
  printf("%c\n", score>14 ? 'S' : 'H');
  return 0;
}

A estratégia aqui está documentada nos comentários, mas é muito direta. Apostas adicionais são feitas em apenas dois casos (não há aposta suficiente para a próxima rodada ou dobram), e isso pode precisar mudar.

O jogo difere alguns dos guias oferecidos aos jogadores de cassino, pois não há informações específicas sobre o cartão de apresentação do negociante (ou podemos ser a última entrada em visible?), Portanto, alguns dos números mágicos são adivinhações.

Pode ser necessário um pouco de modéstia, dependendo da resposta a duas perguntas nos comentários.

Nome do jogo, meu primeiro nome e a velha balada folclórica .

dmckee --- gatinho ex-moderador
fonte
O cartão dez é representado pelo caractere T. Atualiza a postagem do concurso com a lista.
Arrdem 28/05
3

Aposta Linear

#!/usr/bin/env python
from __future__ import division
import sys
s = sys.argv

c=150    # chip modifier
f=15     # stand score

if int(s[1]) < f:
    print "H"
else:
    if int(s[4]) == 10:
        print "B", (int(s[1])/21)*c
    else:
        print "S"

Este bot é uma modificação da estratégia 17. Este bot empata até exceder a pontuação de 15 (f) e depois aposta int (c * (score / 21)) fichas. Desta forma, o bot apostará agressivamente sempre que possível.

arrdem
fonte