Ein BlackJack KOTH-Wettbewerb

13

BlackJack

Da ich viel an der ursprünglichen KOTH-Herausforderung gearbeitet habe, wollte ich mir eine neue ausdenken. Für mich besteht der Spaß an diesen KI-Herausforderungen darin, einen vergleichsweise einfachen Bot zu verfeinern, der ein sehr einfaches Spiel auf subtile Weise spielt. Aufgrund der Wahrscheinlichkeit von Kartenspielen denke ich, dass Blackjack genau wie TPD ein interessantes KOTH-Spiel sein könnte.

Alle Regeln leiten sich aus der Beschreibung dieser Website von BlackJack mit Schuhen ab

Regeln bezüglich Karten und Deck

  • Bots spielen an Tischen von vier (4) Teilnehmern und einem (1) Geber
  • Ein (1) Schuh (ein gemischtes Deck) wird von allen Spielern und dem Geber geteilt, bis er erschöpft ist. Dann wird ein neues zufällig gemischtes Deck hinzugefügt und das Spiel fortgesetzt. Die Bots werden (derzeit) NICHT über das Hinzufügen dieses neuen Decks benachrichtigt. Eine solche Benachrichtigung kann hinzugefügt werden, wenn das Fehlen dieser Funktion zu ausreichenden Problemen führt.
  • Es gibt ein Buy-In von 10 pro Runde und die Karten sind kostenlos
  • Die perfekte / ideale Hand hat eine Punktzahl von 21
  • Alle Bildkarten haben einen Wert von 10
  • Alle Zahlenkarten sind ihre Nummer wert
  • Asse sind 11 oder 1 wert. Dies wird automatisch vom Framework und nicht von den Bots behandelt.
  • Gemäß den Regeln werden die Karten aller Spieler offen ausgeteilt und sind sichtbar. Eine der Karten des Dealers ist verdeckt und die andere offen.

Wertung

  • Werte über 21, die ein Ass als 11 verwenden, zwingen das Ass, seinen Wert auf 1 zu verringern
  • Punkte von mehr als 21, die nicht unter die Schwelle von 21 gezwungen werden können, sprengen den Bot

Der Händler

  • Der Dealer zieht, bis er pleite ist oder eine Punktzahl von 17 überschreitet, an welcher Stelle er gezwungen ist, zu stehen

Wetten und Chips

  • Zu Beginn jeder Runde ein Buy-in von 10 geladen ist, so ist es eine Mindestbeteiligung von 10 und eine minimale Wette von 1. HINWEIS - die Wette ist der absolute Wert der Wette Argument, also nicht stören versuchen negative Wetten.
  • Bots, die sich das Buy-In nicht leisten können, werden vom Wettbewerb ausgeschlossen
  • Bei Wetten können Bots nicht mehr als die Chips setzen, die sie haben
  • Wenn der Einsatz möglich ist, werden die Chips-Einsätze sofort vom Bot entfernt und dem Einsatz hinzugefügt
  • Wenn Sie eine Wette gewinnen, erhalten Sie 2x Chips. Da der Einsatz jedoch von den Chips des Bots abgezogen wird, macht der Bot eine Gewinnschwelle und gewinnt dann 1x den Einsatz.
  • Bots gewinnen Wetten nur, wenn ihre Punktzahl höher ist als die des Dealers

Gameplay-Aufschlüsselung

Eine Hand

  1. Zu Beginn des Spiels erhält jeder Spieler iterativ eine Karte und die Buy-In-Gebühr in Höhe von 10 USD / Mindesteinsatz wird von seinen Chips abgezogen.
  2. Der Dealer zieht
  3. Es wird ein zweiter Pass gespielt und allen Spielern eine weitere Karte ausgeteilt.
  4. Der Dealer zieht
  5. Dann wird (in der gleichen Reihenfolge, in der sie behandelt wurden) jeder Bot ausgeführt, wie im Abschnitt "Programmierschnittstelle" beschrieben, und muss eine Bewegung ausführen oder stehen. Wetten gilt als Zug. HINWEIS, DASS WETTEN DIE FÄHIGKEIT VON BOTS, WEITERE ZÜGE ZU MACHEN, NICHT BEEINTRÄCHTIGT. Es ist sehr gut möglich, eine Karte zu setzen und dann zu ziehen, und es ist möglich, mehrere Karten zu ziehen und diese vor dem Stehen zu setzen.
  6. Wenn alle Bots geplatzt sind oder gestanden haben, spielt der Dealer bis zu seiner Schwelle von 17
  7. Die Punktzahlen der Bots werden dann mit denen des Dealers verglichen, Wetten werden gewonnen und verloren

Eine Runde

Wird als fünf (5) Hände angesehen. Zwischen den Händen wird die Liste der Teilnehmer sortiert, um die Spieler zu entfernen, und dann weiter verarbeitet, um sicherzustellen, dass alle Bots die gleiche Anzahl von Händen spielen (eine Voraussetzung dafür, dass die Anzahl der Einträge bei Tischen mit vier Bots nicht gleichmäßig verteilt ist ).

Programmierschnittstelle und rechtliche Schritte

Wie in der CardShark-Datei dokumentiert:

#   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.

Wie (jetzt) ​​in der Kartendatei dokumentiert:

#       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":   '#'

Der Quellcode für das Scoring-System ist HIER

Beispiel-Bots

Lim 17

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

Eingabesprachen

Derzeit werden Java, C / C ++, Python und Lisp unterstützt. Es werden angemessene Anstrengungen unternommen, um Einsendungen in anderen Sprachen einzubeziehen. Denken Sie jedoch daran, dass der finale Wettbewerb auf einer Linux-Box ausgeführt wird.

Gewinner Auswahl

Der Gewinner wäre der Autor des Bots, der über eine noch zu bestimmende Anzahl von Tischen und Runden konstant die meisten Chips angesammelt hat. Der Gewinner wird am 3. Juni bekannt gegeben. Die Bekanntgabe kann sich jedoch verzögern, wenn noch weitere Einsendungen eingehen. Der Wettbewerb wurde auf unbestimmte Zeit verlängert.

arrdem
quelle
Frage: Enthalten sichtbare Karten die Karten in der Hand des Spielers?
dmckee --- Ex-Moderator Kätzchen
Zweite Frage: Wissen wir, wie viele Karten ausgeteilt wurden, die wir nicht sehen können?
dmckee --- Ex-Moderator Kätzchen
Antwort auf # 1 - ja; Antwort auf # 2 - wie diese Engine implementiert ist, gibt es keine versteckten Karten. Sichtbare Karten ist jede Karte, die von jedem Schuh ausgeteilt wurde, der in der aktuellen Runde verbraucht wurde. Sichtbare Karten werden nicht auf neuen Schuhen gelöscht (da ein Teil des alten Schuhs wahrscheinlich noch im Spiel ist), sondern bei Beendigung der Runde. Dies ist eine Architekturentscheidung, die ich der Einfachheit halber getroffen habe. Sie kann überarbeitet werden, wenn Sie das Fehlen versteckter Karten als problematisch empfinden.
arrdem
Update: Überprüfen Sie den Link zu den Regeln. Die Engine implementiert jetzt versteckte Karten, aber die einzige versteckte Karte ist derzeit eine der Basiskarten des Dealers.
Arrdem
Wie können Bots erkennen, welche sichtbare Karte der Dealer ist?
cthom06

Antworten:

3

BlackJackDavey

Langweilig, altmodisch c. Sollte Compiler unter ANSI oder 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;
}

Die Strategie hier ist in den Kommentaren dokumentiert, geht aber sehr direkt voran. Zusätzliche Wetten werden nur in zwei Fällen abgeschlossen (nicht genügend Einsatz für die nächste Runde oder Verdoppelung), und dies muss möglicherweise geändert werden.

Das Spiel unterscheidet sich in einigen Punkten von den für Casino-Spieler angebotenen Anleitungen darin, dass es keine spezifischen Informationen zum Kartenausweis des Dealers gibt (oder können wir das als letzten Eintrag angeben visible?), So dass einige der magischen Zahlen Vermutungen sind.

Je nach der Antwort auf zwei Fragen in den Kommentaren kann ein bescheidenes Hin und Her erforderlich sein.

Name aus dem Spiel, mein Vorname und die alte Volksballade .

dmckee --- Ex-Moderator Kätzchen
quelle
Die Zehnerkarte wird durch das T-Zeichen dargestellt. Aktualisiert den Wettbewerbsbeitrag mit der Liste.
Arrdem
3

Lineare Wette

#!/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"

Dieser Bot ist eine Modifikation der 17-Strategie. Dieser Bot zieht, bis er eine Punktzahl von 15 (f) überschreitet, und setzt dann int (c * (score / 21)) Chips. Auf diese Weise setzt der Bot, wo immer möglich, aggressiv.

arrdem
quelle