«[Figlio dell'uomo] Porgi l'orecchio e ascolta le parole di KGB
e applica la tua mente alla SUA istruzione
» Pv. 22,17

Qui si straparla di vari argomenti:
1. Il genere dei pezzi è segnalato da varie immagini, vedi Legenda
2. Istruzioni per i nuovi lettori (occasionali e non) qui
3. L'ultimo corto è questo

venerdì 4 febbraio 2011

Puke-Poker-2

Ricordate il post I kamikaze del poker?
In esso esprimevo una mia teoria secondo la quale un giocatore di poker bravo in un tavolo con altri 8 principianti che giocano a casaccio rischia di perdere perché il gioco diventa troppo casuale.

La mia teoria si basava su poche partite nelle quali, pur giocando bene, uscivo sconfitto contro avversari che giocavano molto male e compivano scelte illogiche.

Concludevo il post con la mezza idea di costruire una simulazione per confermare questa mia teoria (*1). Bene, poco dopo costruii effettivamente un modello per effettuare la simulazione. Di seguito i miei risultati.

Idealmente avrei dovuto costruire un modello che rispecchiasse tutte le caratteristiche del poker ma, ovviamente, sarebbe stato troppo difficile. Così ho adottato un modello semplificato che evidenziasse solo le caratteristiche che reputavo fondamentali. Così ho immaginato un nuovo gioco chiamato Puke-Poker (*2). In questo gioco ogni giocatore riceve una mano con forza da 20 a 100. Ogni giocatore può poi decidere se scommettere oppure abbandonare. Fra tutti i giocatori che scommettono vince chi ha la mano più forte e tutti gli altri sono eliminati. Il gioco continua col vincitore della mano e tutti quelli che non avevano scommesso.
Nella mia simulazione ogni giocatore è caratterizzato da un certo livello di abilità. In base al livello di abilità il giocatore deciderà se scommettere oppure no. In particolare se la forza della mano è superiore all'abilità allora il giocatore scommetterà. Ad esempio un giocatore con abilità 30 giocherà mani di forza da 31 in su. Un giocatore di abilità 65 giocherà solo le mani di forza da 66 in su. In pratica i giocatori deboli giocheranno quasi tutte le mani mentre quelli bravi giocheranno solo le mani più forti.

Ecco i risultati ottenuti simulando 10000 tornei con giocatori di tutti i livelli di abilità:

Tornei disputati: 10000
Giocatore 1, Skill 70: Mani-> 8141 Tornei-> 3083
Giocatore 2, Skill 65: Mani-> 8856 Tornei-> 2100
Giocatore 3, Skill 60: Mani-> 7977 Tornei-> 1535
Giocatore 4, Skill 55: Mani-> 6054 Tornei-> 972
Giocatore 5, Skill 50: Mani-> 5206 Tornei-> 708
Giocatore 6, Skill 45: Mani-> 4470 Tornei-> 552
Giocatore 7, Skill 40: Mani-> 3648 Tornei-> 397
Giocatore 8, Skill 35: Mani-> 3387 Tornei-> 336
Giocatore 9, Skill 30: Mani-> 3155 Tornei-> 317

Il giocatore più bravo, prevedibilmente, vince più tornei (quasi il 31%). Il giocatore più scadente si deve accontentare invece di vincere solo il 3% dei tornei. Da notare come il giocatore 2, di poco più debole del più forte, vinca più mani ma di gran lunga meno tornei del primo (21%).

Poi ho provato a vedere cosa succedeva a sostituire i giocatori più deboli con altri via via ancor più deboli.
Nel seguente caso ho abbassato l'abilità dei giocatori 6, 7 e 8 a 30:

Tornei disputati: 10000
Giocatore 1, Skill 70: Mani-> 8406 Tornei-> 3109
Giocatore 2, Skill 65: Mani-> 9325 Tornei-> 2221
Giocatore 3, Skill 60: Mani-> 8013 Tornei-> 1485
Giocatore 4, Skill 55: Mani-> 6511 Tornei-> 1090
Giocatore 5, Skill 50: Mani-> 4983 Tornei-> 723
Giocatore 6, Skill 30: Mani-> 3082 Tornei-> 320
Giocatore 7, Skill 30: Mani-> 3392 Tornei-> 346
Giocatore 8, Skill 30: Mani-> 3501 Tornei-> 368
Giocatore 9, Skill 30: Mani-> 3207 Tornei-> 338

La percentuale di vittorie del giocatore 1 non cambia molto.
Infine ho lasciato solo il giocatore forte con 8 deboli:

Tornei disputati: 10000
Giocatore 1, Skill 70: Mani-> 4410 Tornei-> 4304 +40%
Giocatore 2, Skill 30: Mani-> 3526 Tornei-> 692
Giocatore 3, Skill 30: Mani-> 3588 Tornei-> 678
Giocatore 4, Skill 30: Mani-> 3538 Tornei-> 710
Giocatore 5, Skill 30: Mani-> 3444 Tornei-> 670
Giocatore 6, Skill 30: Mani-> 3615 Tornei-> 741
Giocatore 7, Skill 30: Mani-> 3586 Tornei-> 738
Giocatore 8, Skill 30: Mani-> 3632 Tornei-> 741
Giocatore 9, Skill 30: Mani-> 3534 Tornei-> 726 +29%

A questo punto la simulazione sembra smentire la mia teoria: il giocatore forte vince infatti il 40% di tornei in più rispetto al caso iniziale!

Non molto soddisfatto ho cercato di comprenderne il motivo e mi sono reso conto che il mio modello aveva una gravissima deficienza! Il modello non teneva conto che nel gioco del poker i giocatori deboli che giocano spesso si eliminano fra di loro ma colui che vince accumula chips...
Invece nel gioco del Puke-Poker i giocatori deboli tendono ad eliminarsi fra loro senza nessuna contropartita così, quando il giocatore 1 si decide a scommettere gioca contro pochi avversari che non hanno guadagnato nessun vantaggio ad essersi eliminati a vicenda.

Così ho creato un nuovo gioco: il Puke-Poker-2! In questo gioco ogni giocatore ha inizialmente una biglia e quando partecipa a una scommessa la mette in palio. Ogni giocatore potrà vincere da ogni singolo avversario al massimo tante biglie quante ne ha messe in palio e ne potrà perdere al massimo tante quante ne ha scommesse il vincitore. Sembra complicato ma è molto semplice!
Un esempio con tre giocatori:
G1 ha 4 biglie
G2 ha 2 biglie
G3 ha 1 biglia

Se vince G1 allora G2 e G3 perdono tutte le loro biglie e vengono eliminati; G1 avrà 7 biglie.
Se vince G2 allora G1 perde 2 biglie e G3 è eliminato; G1 avrà 2 biglie e G2 5 biglie.
Se vince G3 allora G1 e G2 perderanno 1 biglia; G1 avrà 3 biglie, G2 1 biglia e G3 avrà 3 biglie.

In questa maniera i giocatori che giocano più spesso corrono sì il rischio di essere eliminati facilmente ma, se vincono, guadagnano biglie che rendono più probabile la vittoria finale.

Ecco i risultati della nuova simulazione:

Tornei disputati (con Chips): 10000
Giocatore 1, Skill 70: Mani-> 7797 Tornei-> 1377
Giocatore 2, Skill 65: Mani-> 6856 Tornei-> 1318
Giocatore 3, Skill 60: Mani-> 5765 Tornei-> 1220
Giocatore 4, Skill 55: Mani-> 5038 Tornei-> 1132
Giocatore 5, Skill 50: Mani-> 4424 Tornei-> 1097
Giocatore 6, Skill 45: Mani-> 4163 Tornei-> 1073
Giocatore 7, Skill 40: Mani-> 3651 Tornei-> 939
Giocatore 8, Skill 35: Mani-> 3566 Tornei-> 945
Giocatore 9, Skill 30: Mani-> 3499 Tornei-> 899

In un torneo con giocatori di tutti i livelli il giocatore più forte vince ancora più tornei ma la percentuale di vittorie è nettamente più bassa che nella simulazione precedente (14% contro 31%). Analogamente il giocatore più debole vince molto più spesso (9% contro 3%).
Come prima ho poi iniziato a introdurre giocatori più deboli:

Tornei disputati (con Chips): 10000
Giocatore 1, Skill 70: Mani-> 8238 Tornei-> 1526
Giocatore 2, Skill 65: Mani-> 6644 Tornei-> 1264
Giocatore 3, Skill 60: Mani-> 5671 Tornei-> 1190
Giocatore 4, Skill 55: Mani-> 4982 Tornei-> 1108
Giocatore 5, Skill 50: Mani-> 4303 Tornei-> 1067
Giocatore 6, Skill 30: Mani-> 3413 Tornei-> 943
Giocatore 7, Skill 30: Mani-> 3490 Tornei-> 960
Giocatore 8, Skill 30: Mani-> 3523 Tornei-> 982
Giocatore 9, Skill 30: Mani-> 3592 Tornei-> 960

La percentuale di vittorie del giocatore più forte è aumentata di 1 punto percentuale...
Infine:

Tornei disputati (con Chips): 10000
Giocatore 1, Skill 70: Mani-> 9032 Tornei-> 1566 +10%
Giocatore 2, Skill 30: Mani-> 2118 Tornei-> 1039
Giocatore 3, Skill 30: Mani-> 2155 Tornei-> 1060
Giocatore 4, Skill 30: Mani-> 2214 Tornei-> 1089
Giocatore 5, Skill 30: Mani-> 2006 Tornei-> 1007
Giocatore 6, Skill 30: Mani-> 2059 Tornei-> 1018
Giocatore 7, Skill 30: Mani-> 2174 Tornei-> 1079
Giocatore 8, Skill 30: Mani-> 2110 Tornei-> 1039
Giocatore 9, Skill 30: Mani-> 2247 Tornei-> 1103 +23%

In questo caso, un giocatore forte alle prese con 8 principianti vince sì, un po' più spesso ma di molto poco (appena del 10%).
La conclusione mi pare piuttosto realistica: un giocatore molto forte contro 8 principianti non vince il 99% dei tornei ma solo circa il 50% in più rispetto a un novellino. Il motivo rimane la maggiore casualità delle singole giocate.

Per la cronaca nel secondo esempio del post I kamikaze del poker mi lamentavo del fatto che il giocatore forte ha il 70% di probabilità di vittoria contro un solo avversario mentre solo il 50% contro tre avversari e che questo alla lunga comportasse una perdita. Questo non è vero: infatti il calo delle probabilità di vittoria è ampiamente compensato dal fatto che la vincita è tre volte più grande!

In appendice aggiungo il codice della mia simulazione.
Qualche annotazione sparsa:
  1. il codice non è particolarmente curato perché ho puntato sulla semplicità.
  2. Da quando i Vector sono obsoleti!?
  3. Per cambiare le abilità (o il numero di giocatori per tavolo) basta editare l'array skills[]
  4. Per cambiare il numero di tornei simulati basta cambiare il valore della variabile total
  5. Le funzioni per calcolare i valori random le ho copiate da una mia classe quindi non sono particolarmente ottimizzate per lo scopo...

package pokermodel;

import java.security.SecureRandom;
import java.util.Vector;

public class PokerModel2
{
private static SecureRandom ran = null;

public static void main(String[] args)
{
//vars
int total=10000;
//int skills[]={70, 65, 60, 55, 50, 45, 40, 35, 30};
int skills[]={70, 30, 30, 30, 30, 30, 30, 30, 30};
//int skills[]={70, 65, 53, 52, 50, 48, 47, 33, 30};
//int skills[]={70, 65, 32, 39, 37, 32, 35, 33, 30};
Vector<Player> pList=new Vector();
Vector<Player> gamePlayers=new Vector();
Vector<Player> handPlayers=new Vector();
//init
fillList(pList, skills);
//mainloop
for(int a=0; a<total; a++)
{
gamePlayers.clear();
gamePlayers.addAll(pList);
resetChips(gamePlayers);
//gameloop
while(gamePlayers.size()>1)
{
handPlayers.clear();
int tothand=0;
//draw hands & select players
for(Player p : gamePlayers)
{
p.hand=genera(5,4)*5;
if(p.hand>=p.skill)
{
handPlayers.add(p);
tothand+=p.hand;
}
}
if(handPlayers.size()>1)
{
//ICM
int winner=genera(tothand,1);
Player handWinner=null;
for(Player p : handPlayers)
{
if(p.hand>=winner)
{
p.numWon++;
handWinner=p;
break;
}
else
{
winner-=p.hand;
}
}
int chipsWon=0;
for(Player p : handPlayers)
{
if(p!=handWinner)
{
int diff=Math.min(p.chips, handWinner.chips);
chipsWon+=diff;
p.chips-=diff;
if(p.chips<=0)
gamePlayers.remove(p);
}
}
handWinner.chips+=chipsWon;
}
}
gamePlayers.firstElement().gameWon++;
}
//output
System.out.println("Tornei disputati (con Chips): "+total);
for(Player p : pList)
System.out.println("Giocatore "+p.id+", Skill  "+p.skill+": Mani-> "+p.numWon+" Tornei-> "+p.gameWon);
}

private static void resetChips(Vector<Player> list)
{
for(Player r : list)
r.chips=1;
}

private static void fillList(Vector<Player> list, int val[])
{
int cc=0;
for(int v : val)
list.add(new Player(v,++cc));
}

public static int genera(int facce, int volte)
{
int result = 0;
if(facce<=0)
return 0;
if(ran == null)
try
{
ran = SecureRandom.getInstance("SHA1PRNG");
}
catch (Exception e) { System.out.println("Errore: " + e.getMessage()); }
for (int i=0; i<volte; i++)
result += ran.nextInt(facce) + 1;
return result;
}

public static boolean isWinner(float upTo)
{
if(ran == null)
try
{
ran = SecureRandom.getInstance("SHA1PRNG");
}
catch (Exception e) { System.out.println("Errore: " + e.getMessage()); }
if(ran.nextFloat()<=upTo)
return true;
return false;
}

private static class Player
{
int id;
int skill;
int numWon;
int gameWon;
int hand;
int chips;
Player(int pSkill, int pId)
{
skill=pSkill;
numWon=0;
gameWon=0;
id=pId;
chips=1;
}
}

}


Nota (*1): Sarebbe stato più corretto partire dall'ipotesi che la simulazione avrebbe potuto confermare o smentire la mia teoria ma io sono piuttosto sicuro di me...
Nota (*2): Puke-Poker = Poker-Vomitevole...

Nessun commento:

Posta un commento