Du bist nicht angemeldet.

Werbeanzeige

rewb0rn

Supermoderator

  • »rewb0rn« ist der Autor dieses Themas

Beiträge: 2 869

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

1

10.07.2013, 14:57

#16: Skat-KI für www.skat-palast.de (500 € Preisgeld), Spezial, verlängert: 07.08.2013)

Hallo Community,

wie angekündigt, gibt es einen neuen Community-Wettbewerb: das Schreiben einer Skat-KI. Jeder kann mitmachen! Die KI ist in C++ zu programmieren. Hierfür habe ich ein Testbed geschrieben, dieses findet ihr hier.

Bitte meldet Probleme oder Bugs mit dem Testbed. Wer den Hauptpreis gewinnen will, muss den Teilnahmebedingungen zustimmen. Für die beste KI ist eine Integration in die Website www.skat-palast.de geplant, falls der Gewinner einverstanden ist (Voraussetzung für das Preisgeld). Wer das nicht möchte, kann aber natürlich trotzdem mitmachen.


Wie das Testbed funktioniert

Zunächst sollte das Testbed wie vorliegend kompilieren und starten und dann eine Reihe von Zahlen ausgeben. Das Testbed simuliert 10.000 Runden und gibt den Punkte-Schnitt der vorliegenden Spieler über 36 Runden aus.

Wenn ihr die Datei main.cpp öffnet, seht ihr dort die Parameter beim Erstellen des Tables: Rundenanzahl, die KI-Spieler und 2 Booleans. Der erste Boolean gibt an, ob im Gegenspieler-Modus gespielt wird (siehe Auswertung), und kann erstmal ignoriert werden. Der 2. Boolean gibt an, ob das Spiel alle Informationen ausgeben soll. Für den Start ist es empfehlenswert, diesen Parameter auf true zu setzen, dann wird jeder Zug eurer KI in der Konsole ausgegeben, und ihr könnt die einzelnen Schritte besser nachvollziehen.


Wie die eigene KI angelegt wird

Als beispielhafte Implementierung liegt dem Spiel die Klasse AiRandomPlayer bei. Ich empfehle, diese Klasse zu duplizieren und von hier aus zu starten. Bitte verwendet für alle eure Klassen einen Unterordner und einen eigenen Namespace (idealerweise euren Nickname, kein using namespace in Headern), damit es später nicht zu Konflikten kommt, wenn alle Spieler gegeneinander antreten.

Ihr seht nun in der Datei AiRandomPlayer.cpp die Methoden, die ihr implementieren sollt, damit eure KI funktioniert. Wenn ihr all diese Methoden implementiert, spielt eure KI regelkonform.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
void AiPlayerRandom::newRound(void)
{
    //eine neue runde startet
    //evtl. möchtest du etwas resetten?
}


unsigned short AiPlayerRandom::decideCall(unsigned short currentValue)
{
    //du bist dran zu reizen. sag einen höheren wert als den aktuellen um zu reizen
    return 18;
}

bool AiPlayerRandom::decideAccept(unsigned short currentValue)
{
    //hältst du den aktuellen reizwert des ansagenden?
    return false;
}

bool AiPlayerRandom::decideHandspiel(void)
{
    //entscheide dich ob du hand spielst (gewinnstufe + 1) oder die beiden skat-karten aufnimmst und 2 andere zurücklegst
    return rand() % 2 == 0;
}


SkatCardSet AiPlayerRandom::getDrueckung(void)
{
    //zu diesem zeitpunkt besteht deine hand aus 12 karten (deine 10 startkarten und die 2 karten aus dem skat)
    //wähle 2, die du zurück in den skat legst
    SkatCardSet drueckung;

    drueckung.push_back(cards()[0]);
    drueckung.push_back(cards()[1]);

    return drueckung;
}

void AiPlayerRandom::decideAnsage(GameType& outGameType, AnsageLevel& outAnsageLevel)
{
    //sag das spiel an, dass du spielen willst, und die gewinnstufe. 
    //beim nullspiel sind nur normal und ouvert möglich. 
    //alle anderen spiele dürfen nur dann höhere gewinnstufe erhalten, wenn ein handspiel angesagt wurde
    outGameType = GameType(rand() % 6);
    outAnsageLevel = AL_NORMAL;
}


Card* AiPlayerRandom::playCard(void)
{
    //spiele deine Karte. noch geben wir einfach die erste gültige Karte zurück.
    for (std::vector<Card*>::const_iterator it = cards().begin(); it != cards().end(); ++it)
    {
        if (game()->gameRound()->isValidCard(*it, cards())) return *it;
    }

    return 0;
}

void AiPlayerRandom::userAction(unsigned short player, UserAction action)
{
    //eine aktion eines spielers hat stattgefunden, bspw. ein spieler hat gereizt oder eine karte gelegt
    //wir können diese information nun verarbeiten, um z.b. das blatt des gegners neu einzuschätzen
}



Wie wird der Spielstatus abgefragt?

In eurer KI-Klasse habt ihr Zugriff auf die Methoden game() und cards() aus der Basisklasse. Über cards() erhaltet ihr euer eigenes Blatt, game() gibt eine Instanz der Klasse SkatGame zurück, über die ihr zusätzliche Informationen erhaltet:

SkatGame bietet euch unter anderem die Methoden:

- reizen(): Gibt euch Informationen über den aktuellen Reizstatus, z.B. aktueller Reizwert und aktueller Reiz-Gewinner
- gameRound(): Nach Spielansage findet ihr hier Infos über die angesagte Spielrunde, z.B. gameType(), trick() (aktueller Stich), und weitere, nützliche Methoden, die zur Auswertung der eigenen Karten helfen. Beispielsweise isTrump(Card*), getBetterCard(Card*, Card*) und viele weitere.


Tipps

- Organisiert eure KI frühzeitig über weitere Klassen, es gibt kein Limit.
- Fangt als allererstes mit dem Spieltyp Grand an, er ist am leichtesten, da hier nur die Buben Trumpf sind.
- Macht das Nullspiel, wenn überhaupt, als letztes, es macht max. 5% aller Spiele aus.
- In der Klasse SkatUtils findet ihr eine Hilfsfunktion zum Bestimmen des Reizwertes eines Blattes.

Viel Erfolg, meldet euch bei Fragen!

Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von »rewb0rn« (18.03.2014, 21:26)


2

11.07.2013, 14:52

Wenn ich dein Programm compiliere stürzt es direkt ab (out_of_range Fehler in Seat.cpp Zeile 26).

Wie sieht es mit Compilern aus. Msvc110 erlaubt, oder muss es der msvc100 sein?
Besucht mich und meinen Blog unter:
www.simple-world.org

Du magst Tower Defense?
Dann probier doch mal Coregrounds aus ;)

rewb0rn

Supermoderator

  • »rewb0rn« ist der Autor dieses Themas

Beiträge: 2 869

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

3

11.07.2013, 15:19

Hey, ändere bitte mal in Zeile 9 in Seat.cpp i < 5 zu i < 6 und sag Bescheid ob es dann klappt. Merkwürdig nur, dass es bei mir geht. Compiler ist egal, solange es bei mir am Ende läuft.

4

11.07.2013, 16:37

Jo, soweit war ich auch schon, das hilft natürlich ;) Wollte dich das nur wissen lassen, nicht dass das noch weitreichendere Probleme mit sich bringt.
Ist es normal, das dort nur negativ Werte in der Konsole auftauchen?

Zitat

Spiel 100, 0: -1059.12, 1: -627.48, 2: -1159.2
Spiel 200, 0: -926.1, 1: -740.52, 2: -1124.28
Spiel 300, 0: -1010.28, 1: -601.2, 2: -1057.2
Spiel 400, 0: -751.59, 1: -563.76, 2: -1099.98
Spiel 500, 0: -758.16, 1: -549.504, 2: -1095.12
Spiel 600, 0: -727.92, 1: -729.12, 2: -979.56
Spiel 700, 0: -828.103, 1: -716.606, 2: -922.629
Spiel 800, 0: -817.38, 1: -788.805, 2: -889.56
Spiel 900, 0: -869.16, 1: -753.88, 2: -891.08
Spiel 1000, 0: -857.628, 1: -758.052, 2: -899.604
Spiel 1100, 0: -887.924, 1: -747.589, 2: -876.927
Spiel 1200, 0: -898.71, 1: -766.89, 2: -895.83
Spiel 1300, 0: -926.889, 1: -800.003, 2: -881.086
Spiel 1400, 0: -931.294, 1: -827.511, 2: -885.214
Spiel 1500, 0: -958.272, 1: -766.296, 2: -918.168
Spiel 1600, 0: -967.365, 1: -764.797, 2: -921.06
Spiel 1700, 0: -951.247, 1: -801.042, 2: -907.962
Spiel 1800, 0: -968.48, 1: -814.22, 2: -911.48
Spiel 1900, 0: -984.922, 1: -789.632, 2: -890.716
Spiel 2000, 0: -1018.48, 1: -794.466, 2: -932.58
Spiel 2100, 0: -1003.22, 1: -795.634, 2: -903.994
Spiel 2200, 0: -1012.11, 1: -802.604, 2: -896.285
Spiel 2300, 0: -1021.9, 1: -791.28, 2: -896.854
Spiel 2400, 0: -1016.67, 1: -821.73, 2: -890.97
Spiel 2500, 0: -1011.6, 1: -828.259, 2: -913.594
Spiel 2600, 0: -1016.34, 1: -831.822, 2: -894.365
Spiel 2700, 0: -1007.03, 1: -860.12, 2: -895.213
Spiel 2800, 0: -1010.69, 1: -857.713, 2: -895.474
Spiel 2900, 0: -999.881, 1: -860.872, 2: -882.646
Spiel 3000, 0: -1009.84, 1: -875.232, 2: -888.288
Spiel 3100, 0: -999.557, 1: -880.769, 2: -907.688
Spiel 3200, 0: -996.626, 1: -881.91, 2: -920.419
Spiel 3300, 0: -982.985, 1: -887.585, 2: -929.149
Spiel 3400, 0: -972.36, 1: -892.144, 2: -910.779
Spiel 3500, 0: -991.646, 1: -891.658, 2: -915.202
Spiel 3600, 0: -970.84, 1: -910.29, 2: -920.28
Spiel 3700, 0: -969.898, 1: -922.369, 2: -913.446
Spiel 3800, 0: -959.125, 1: -928.468, 2: -927.72
Spiel 3900, 0: -951.332, 1: -923.418, 2: -921.618
Spiel 4000, 0: -968.013, 1: -923.166, 2: -916.686
Spiel 4100, 0: -966.811, 1: -930.38, 2: -922.777
Spiel 4200, 0: -967.269, 1: -929.469, 2: -923.374
Spiel 4300, 0: -967.127, 1: -916.87, 2: -927.352
Spiel 4400, 0: -969.955, 1: -924.979, 2: -934.454
Spiel 4500, 0: -957.936, 1: -923.584, 2: -929.72
Spiel 4600, 0: -962.296, 1: -915.637, 2: -937.244
Spiel 4700, 0: -956.819, 1: -915.932, 2: -946.754
Spiel 4800, 0: -955.095, 1: -920.265, 2: -946.965
Spiel 4900, 0: -956.652, 1: -921.762, 2: -943.016
Spiel 5000, 0: -971.107, 1: -907.466, 2: -946.951
Spiel 5100, 0: -981.148, 1: -907.715, 2: -954.275
Spiel 5200, 0: -985.957, 1: -907.816, 2: -955.35
Spiel 5300, 0: -975.58, 1: -912.783, 2: -954.401
Spiel 5400, 0: -973.14, 1: -918.8, 2: -957.02
Spiel 5500, 0: -973.839, 1: -924.964, 2: -951.703
Spiel 5600, 0: -968.676, 1: -924.024, 2: -950.612
Spiel 5700, 0: -972.12, 1: -928.263, 2: -950.747
Spiel 5800, 0: -975.532, 1: -930.234, 2: -952.442
Spiel 5900, 0: -981.25, 1: -925.218, 2: -938.337
Spiel 6000, 0: -986.628, 1: -931.806, 2: -934.614
Spiel 6100, 0: -985.751, 1: -925.513, 2: -935.675
Spiel 6200, 0: -988.502, 1: -914.081, 2: -935.263
Spiel 6300, 0: -980.457, 1: -921.766, 2: -929.16
Spiel 6400, 0: -988.268, 1: -916.329, 2: -932.822
Spiel 6500, 0: -983.924, 1: -921.727, 2: -928.889
Spiel 6600, 0: -976.293, 1: -910.244, 2: -937.544
Spiel 6700, 0: -962.645, 1: -914.948, 2: -944.871
Spiel 6800, 0: -964.546, 1: -917.058, 2: -940.325
Spiel 6900, 0: -964.017, 1: -920.703, 2: -936.558
Spiel 7000, 0: -956.767, 1: -920.643, 2: -931.963
Spiel 7100, 0: -967.173, 1: -925.717, 2: -931.3
Spiel 7200, 0: -957.665, 1: -925.13, 2: -934.51
Spiel 7300, 0: -958.039, 1: -921.758, 2: -943.417
Spiel 7400, 0: -970.429, 1: -918.749, 2: -937.61
Spiel 7500, 0: -966.523, 1: -921.072, 2: -934.613
Spiel 7600, 0: -971.493, 1: -918.369, 2: -935.588
Spiel 7700, 0: -968.115, 1: -917.144, 2: -935.799
Spiel 7800, 0: -967.02, 1: -923.82, 2: -945.512
Spiel 7900, 0: -970.104, 1: -922.543, 2: -949.858
Spiel 8000, 0: -976.095, 1: -923.013, 2: -943.591
Spiel 8100, 0: -976.116, 1: -927.307, 2: -939.587
Spiel 8200, 0: -980.491, 1: -917.104, 2: -938.832
Spiel 8300, 0: -978.983, 1: -911.928, 2: -943.638
Spiel 8400, 0: -977.173, 1: -907.157, 2: -944.73
Spiel 8500, 0: -976.163, 1: -907.111, 2: -953.818
Spiel 8600, 0: -973.62, 1: -902.934, 2: -956.022
Spiel 8700, 0: -965.218, 1: -906.579, 2: -955.585
Spiel 8800, 0: -966.244, 1: -914.032, 2: -953.202
Spiel 8900, 0: -970.613, 1: -916.964, 2: -953.575
Spiel 9000, 0: -975.676, 1: -914.7, 2: -945.732
Spiel 9100, 0: -972.028, 1: -915.164, 2: -945.059
Spiel 9200, 0: -973.213, 1: -911.285, 2: -943.012
Spiel 9300, 0: -982.235, 1: -906.526, 2: -949.707
Spiel 9400, 0: -979.637, 1: -904.849, 2: -951.243
Spiel 9500, 0: -976.881, 1: -903.88, 2: -956.198
Spiel 9600, 0: -983.482, 1: -903.532, 2: -959.55
Spiel 9700, 0: -981.174, 1: -901.596, 2: -959.953
Spiel 9800, 0: -979.189, 1: -900.882, 2: -954.176
Spiel 9900, 0: -977.851, 1: -901.978, 2: -949.204
Spiel 10000, 0: -976.223, 1: -898.978, 2: -949.324

***** Final Evaluation *****
10000 rounds played
0: Average: -976.223, Losses: 62.5563%, gamesPlayed:33.33%
1: Average: -898.978, Losses: 61.8362%, gamesPlayed:33.33%
2: Average: -949.324, Losses: 63.0174%, gamesPlayed:33.34%
total Average: -941.508


Kenne die Skatregeln leider noch nicht, deswegen weiß ich nicht genau, ob das ein Fehler ist oder nicht, sieht auf jeden Fall seltsam aus.
Besucht mich und meinen Blog unter:
www.simple-world.org

Du magst Tower Defense?
Dann probier doch mal Coregrounds aus ;)

TrommlBomml

Community-Fossil

Beiträge: 2 143

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

5

11.07.2013, 16:41

Das sind deine Durchschnittspunkte. Beim Skat kann man Minuspunkte sammeln ;)

rewb0rn

Supermoderator

  • »rewb0rn« ist der Autor dieses Themas

Beiträge: 2 869

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

6

11.07.2013, 17:07

Genau, der Dummy spielt nur zufällige Karten und verliert dauernd, daher ein negativer Schnitt. Ich habe den Fehler korrigiert und eine neue Version hochgeladen, danke für den Hinweis!

xyqa

Frischling

Beiträge: 18

Beruf: Schüler

  • Private Nachricht senden

7

11.07.2013, 20:18

Mal eine Frage an die erfahrenen von euch: Glaubt ihr es macht als Anfänger Sinn mitzumachen (dass ich nicht gewinnen werde ist mir klar, ich möchte halt nur was haben dass läuft). Bzw. meint ihr, dass es an 5 Ferientagen möglich ist sowas halbwegs auf die Beine zu stellen (C++ sollte dafür reichen muss jedoch Skat erstmal lernen)
Eine der wichtigsten Erfahrungen als Programmierer: Wenn alles auf Anhieb funktioniert hat man definitiv etwas falsch gemacht ;)

Käsekönig

1x Contest-Sieger

  • Private Nachricht senden

8

11.07.2013, 20:44

Sinn macht es auf alle Fälle. Ich hab auch mal als Anfänger an einem Contest mitgemacht und mich dabei richtig rein gehängt, weils einfach Spaß gemacht hat. :)
Und du wirst bestimmt einiges dabei lernen. Ob das zeitlich möglich ist, kann ich nicht sagen, aber ich bezweifle, dass da gut was raus kommt (schließlich wirst du ja nicht den ganzen Tag dran sitzen wollen).

9

11.07.2013, 20:48

Du lernst garantiert eine Menge dabei - gibt sicherlich schlechtere Möglichkeiten seine Ferien zu verbringen ;)
Und mit 5 "ganzen" Tagen wirst du wohl mehr Zeit als die meisten hier haben...

...und, klar kannst du gewinnen - immer schön optimistisch sein^^

rewb0rn

Supermoderator

  • »rewb0rn« ist der Autor dieses Themas

Beiträge: 2 869

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

10

15.07.2013, 16:08

Hallo,

ich habe eine neue Version der Test-Umgebung hochgeladen: http://evil-software.com/Skat_Testbed_1-2.zip

Es wurde ein Fehler bei der Auswertung des Nullspiels behoben und ich habe ein paar Stellen im Code optimiert, außerdem gibt es nun eine bessere Spielauswertung, so sieht man z.B. für jeden Spieler die prozentuale Ansage von Spielen, den Anteil von verlorenen Spielen und wie die einzelnen Spieltypen verteilt waren.

Hat denn sonst schon außer mir jemand etwas angefangen? Mein Spieler kommt derzeit im Spiel gegen sich selbst auf durchschnittlich 570 Punkte, gute menschliche Spieler schaffen allerdings mehr als 1200. Ich habe noch ein paar Ideen zur Verbesserung, Ansätze mit neuronalen Netzen zur Bewertung des Kartenblatts waren bisher leider nicht erfolgreich, ich versuche mich erstmal an weiteren Heuristiken (Automaten KI).

Falls ihr Fragen habt (auch zum Skatspiel an sich) meldet euch.
Viele Grüße

Werbeanzeige