fix other pot bug

This commit is contained in:
wzdwc
2020-04-12 23:41:17 +08:00
parent f5ab7f0ae0
commit 85f5275980
4 changed files with 169 additions and 79 deletions
+36 -8
View File
@@ -15,19 +15,35 @@ export enum ECommand {
FOLD = 'fold', FOLD = 'fold',
} }
export enum EPlayerType {
DEALER = 'dealer',
BIG_BLIND = 'big_blind',
SMALL_BLIND = 'small_blind',
}
export class Player { export class Player {
handCard: string[] = []; handCard: string[] = [];
position: number = 0; position: number = 0;
counter: number = 0; counter: number = 0;
userId: string = ''; userId: string = '';
actionSize: number; actionSize: number = 0;
evPot: number; type: string;
evPot: number = 0;
// commandRecord: Array<string> = []; // commandRecord: Array<string> = [];
constructor(config: IPlayer = { counter: 0, position: 0, userId: '' }) { constructor(config: IPlayer = { counter: 0, position: 0, userId: '' }) {
this.counter = config.counter; this.counter = config.counter;
this.position = config.position; this.position = config.position;
this.userId = config.userId; this.userId = config.userId;
if (this.position === 0) {
this.type = EPlayerType.DEALER;
}
if (this.position === 1) {
this.type = EPlayerType.SMALL_BLIND;
}
if (this.position === 2) {
this.type = EPlayerType.BIG_BLIND;
}
} }
setHandCard(card: string) { setHandCard(card: string) {
@@ -49,6 +65,12 @@ export class Player {
const command = commandArr[0]; const command = commandArr[0];
const raiseSize = Number(commandArr[1]); const raiseSize = Number(commandArr[1]);
let size = 0; let size = 0;
console.log('action----', prevSize, raiseSize, this.counter, this.actionSize);
if (command !== ECommand.ALL_IN
&& (prevSize > (this.counter + this.actionSize) || raiseSize > this.counter)) {
throw 'error action, overflow action size';
}
// BLIND // BLIND
if (command === ECommand.SMALL_BLIND || command === ECommand.BIG_BLIND) { if (command === ECommand.SMALL_BLIND || command === ECommand.BIG_BLIND) {
size = raiseSize; size = raiseSize;
@@ -67,8 +89,8 @@ export class Player {
// player raise,get the raise size // player raise,get the raise size
if (command === ECommand.RAISE) { if (command === ECommand.RAISE) {
// raise must double to prevSize // raise must double to prevSize
if (raiseSize >= prevSize * 2) { if ((raiseSize + this.actionSize) >= prevSize * 2) {
size = raiseSize; size = raiseSize + this.actionSize;
} else { } else {
throw 'error action: raise size too small'; throw 'error action: raise size too small';
} }
@@ -79,14 +101,20 @@ export class Player {
} }
if (command === ECommand.CALL) { if (command === ECommand.CALL) {
size = prevSize; size = prevSize - this.actionSize;
} }
if (command === ECommand.CHECK || command === ECommand.FOLD) { if (command === ECommand.CHECK) {
size = -1;
}
if (command === ECommand.FOLD) {
size = 0; size = 0;
} }
this.counter -= size; if (size > 0) {
this.actionSize = size; this.counter -= size;
}
this.actionSize += size;
return size; return size;
} }
+84 -61
View File
@@ -2,7 +2,7 @@
* Created by jorky on 2020/2/23. * Created by jorky on 2020/2/23.
*/ */
import { Poker } from './Poker'; import { Poker } from './Poker';
import { ECommand, IPlayer, Player } from './Player'; import { ECommand, EPlayerType, IPlayer, Player } from './Player';
import { PokerStyle } from './PokerStyle'; import { PokerStyle } from './PokerStyle';
import { ILinkNode, Link } from '../../utils/Link'; import { ILinkNode, Link } from '../../utils/Link';
@@ -11,7 +11,7 @@ interface IPokerGame {
smallBlind: number; smallBlind: number;
} }
enum EGameStatus { export enum EGameStatus {
GAME_READY, GAME_READY,
GAME_START, GAME_START,
GAME_FLOP, GAME_FLOP,
@@ -25,9 +25,9 @@ enum EGameStatus {
export class PokerGame { export class PokerGame {
commonCard: string[] = []; commonCard: string[] = [];
fireCards: string[] = []; fireCards: string[] = [];
players: Link<Player>; playerLink: Link<Player>;
allPlayer: Player[] = [];
poker = new Poker(); poker = new Poker();
pots: number[] = [];
pot: number; pot: number;
status: EGameStatus; status: EGameStatus;
currPlayer: ILinkNode<Player>; currPlayer: ILinkNode<Player>;
@@ -38,7 +38,7 @@ export class PokerGame {
allInPlayers: Player[] = []; allInPlayers: Player[] = [];
currActionAllinPlayer: Player[] = []; currActionAllinPlayer: Player[] = [];
hasStraddle = false; hasStraddle = false;
winner: Player; winner: Player[][];
constructor(config: IPokerGame) { constructor(config: IPokerGame) {
this.smallBlind = config.smallBlind; this.smallBlind = config.smallBlind;
@@ -47,18 +47,19 @@ export class PokerGame {
init(users: IPlayer[]) { init(users: IPlayer[]) {
this.status = EGameStatus.GAME_READY; this.status = EGameStatus.GAME_READY;
// init players // init playerLink
this.players = this.setPlayer(users); this.playerLink = this.setPlayer(users);
this.playerSize = users.length; this.playerSize = users.length;
// set SB, BB,Straddle // set SB, BB,Straddle
this.getBlind(); this.getBlind();
// utg // utg
this.currPlayer = this.players.getNode(3); this.currPlayer = this.playerLink.getNode(3);
console.log(this.currPlayer, '--------------------');
} }
getBlind() { getBlind() {
// sb blind // sb blind
const SBPlayerNode = this.players.getNode(1); const SBPlayerNode = this.playerLink.getNode(1);
const SBPlayer = SBPlayerNode.node; const SBPlayer = SBPlayerNode.node;
// big blind // big blind
const BBPlayerNode = SBPlayerNode.next; const BBPlayerNode = SBPlayerNode.next;
@@ -79,52 +80,64 @@ export class PokerGame {
action(commandString: string) { action(commandString: string) {
if (this.status === EGameStatus.GAME_ACTION) { if (this.status === EGameStatus.GAME_ACTION) {
console.log('this.currPlayer', this.currPlayer);
const commandArr = commandString.split(':'); const commandArr = commandString.split(':');
const command = commandArr[0]; const command = commandArr[0];
let size = Number(commandArr[1]); let size = Number(commandArr[1]);
if (command === ECommand.ALL_IN) { if (command === ECommand.ALL_IN) {
size = this.currPlayer.node.counter; size = this.currPlayer.node.counter > this.prevSize ?
this.currPlayer.node.counter : this.prevSize;
this.allIn(); this.allIn();
this.pot += size; this.pot += this.currPlayer.node.counter;
// other pot // other pot
} }
if (command === ECommand.CALL) { if (command === ECommand.CALL) {
// counter small then raise size,must be all in size = this.prevSize;
if (size > this.currPlayer.node.counter) { this.pot += size - this.currPlayer.node.actionSize;
size = this.currPlayer.node.counter;
this.allIn();
} else {
size = this.prevSize;
this.pot += size;
}
} }
if (command === ECommand.FOLD) { if (command === ECommand.FOLD) {
size = this.prevSize; size = this.prevSize;
this.removePlayer(this.currPlayer.node); this.removePlayer(this.currPlayer.node);
} }
// if (command === ECommand.CHECK) { if (command === ECommand.CHECK) {
// // prev player must be check console.log(this.currPlayer.node.type === EPlayerType.BIG_BLIND
// if (this.prevSize === 0) { && this.prevSize === this.smallBlind * 2, 'big blind', this.currPlayer);
// size = 0; // prev player must be check
// } else { if (!(this.prevSize === 0 ||
// throw 'action incorrect'; (this.currPlayer.node.type === EPlayerType.BIG_BLIND
// } && this.prevSize === this.smallBlind * 2))) {
// } throw 'incorrect action: check';
if (command === ECommand.RAISE) {
if (size < this.prevSize * 2) {
throw 'action incorrect';
} }
}
if (command === ECommand.RAISE) {
console.log(size, 'prevSize', this.prevSize);
this.pot += size; this.pot += size;
// 3 bet
size += this.currPlayer.node.actionSize;
if ((size + this.currPlayer.node.actionSize) < this.prevSize * 2) {
throw 'incorrect action: raise';
}
} }
this.currPlayer.node.action(commandString, this.prevSize); this.currPlayer.node.action(commandString, this.prevSize);
this.prevSize = size; this.prevSize = size;
const nextPlayer = this.currPlayer.next.node; const nextPlayer = this.currPlayer.next.node;
if (nextPlayer.actionSize === this.currPlayer.node.actionSize) { // all check actionSize === -1
// all player allin
// only 2 player ,one player fold
// pre flop big blind check and other player call
if (this.playerSize === 0
|| (this.playerSize === 2 && command === ECommand.FOLD)
|| nextPlayer.actionSize === this.currPlayer.node.actionSize
|| (this.commonCard.length === 0
&& this.currPlayer.node.type === EPlayerType.BIG_BLIND
&& command === ECommand.CHECK)) {
this.actionComplete(); this.actionComplete();
return;
} }
this.currPlayer = this.currPlayer.next; this.currPlayer = this.currPlayer.next;
} else { } else {
throw 'error action'; throw 'incorrect action flow';
} }
} }
allIn() { allIn() {
@@ -133,28 +146,37 @@ export class PokerGame {
} }
private actionComplete() { private actionComplete() {
console.log('pre flop,', this.commonCard.length, this.currPlayer.node);
// pre flop
if (this.commonCard.length === 0
&& this.currPlayer.node.actionSize === this.smallBlind * 2
&& this.currPlayer.node.type !== EPlayerType.BIG_BLIND) {
this.currPlayer = this.currPlayer.next;
return;
}
// action has allin, sum the allin player ev_pot // action has allin, sum the allin player ev_pot
if (this.currActionAllinPlayer.length !== 0) { if (this.currActionAllinPlayer.length !== 0) {
let currAllinPlayerPot = 0; let currAllinPlayerPot = 0;
const players = this.getPlayers(); this.currActionAllinPlayer.forEach(allinPlayer => {
this.currActionAllinPlayer.forEach(actionP => { this.allPlayer.forEach(p => {
players.forEach(p => { if (p.actionSize < allinPlayer.actionSize) {
if (p.actionSize < actionP.actionSize) {
currAllinPlayerPot += p.actionSize; currAllinPlayerPot += p.actionSize;
} else { } else {
currAllinPlayerPot += actionP.actionSize; currAllinPlayerPot += allinPlayer.actionSize;
} }
}); });
actionP.evPot = this.prevPot + currAllinPlayerPot; allinPlayer.evPot = this.prevPot + currAllinPlayerPot;
currAllinPlayerPot = 0;
}); });
this.allInPlayers.concat(this.currActionAllinPlayer); this.allInPlayers = [ ...this.allInPlayers, ...this.currActionAllinPlayer ];
} }
// action complete clear player actionSize = 0 // action complete clear player actionSize = 0
this.clearPlayerAction(); this.clearPlayerAction();
this.currActionAllinPlayer = []; this.currActionAllinPlayer = [];
this.prevSize = 0; this.prevSize = 0;
this.prevPot = this.pot; this.prevPot = this.pot;
// new action ring first action is sb
this.currPlayer = this.playerLink.getNode(1);
if (this.commonCard.length === 0) { if (this.commonCard.length === 0) {
this.status = EGameStatus.GAME_FLOP; this.status = EGameStatus.GAME_FLOP;
} }
@@ -173,16 +195,22 @@ export class PokerGame {
sendCard() { sendCard() {
if (this.status === EGameStatus.GAME_START) { if (this.status === EGameStatus.GAME_START) {
this.setHandCard(); this.setHandCard();
this.status = EGameStatus.GAME_ACTION;
return;
} }
if (this.status === EGameStatus.GAME_FLOP) { if (this.status === EGameStatus.GAME_FLOP) {
this.fireCards.push(this.poker.getCard()); this.fireCards.push(this.poker.getCard());
this.flop(); this.flop();
this.status = EGameStatus.GAME_ACTION;
return;
} }
if (this.status === EGameStatus.GAME_TURN || this.status === EGameStatus.GAME_RIVER) { if (this.status === EGameStatus.GAME_TURN || this.status === EGameStatus.GAME_RIVER) {
this.fireCards.push(this.poker.getCard()); this.fireCards.push(this.poker.getCard());
this.commonCard.push(this.poker.getCard()); this.commonCard.push(this.poker.getCard());
this.status = EGameStatus.GAME_ACTION;
return;
} }
this.status = EGameStatus.GAME_ACTION; throw 'error flow sendCard';
} }
flop() { flop() {
@@ -208,17 +236,19 @@ export class PokerGame {
} }
setPlayer(users: IPlayer[]) { setPlayer(users: IPlayer[]) {
const players: Player [] = []; users.forEach((u, position) => {
users.forEach(u => { const player = new Player({
const player = new Player(u); ...u,
players.push(player); position,
});
this.allPlayer.push(player);
}); });
return new Link<Player>(players); return new Link<Player>(this.allPlayer);
} }
getPlayers(type= 'all') { getPlayers(type= 'all') {
const players = []; const players = [];
let nextPlayer = this.players.link; let nextPlayer = this.playerLink.link;
let i = 0; let i = 0;
while (i < this.playerSize) { while (i < this.playerSize) {
players.push(nextPlayer.node); players.push(nextPlayer.node);
@@ -229,19 +259,13 @@ export class PokerGame {
} }
private clearPlayerAction() { private clearPlayerAction() {
let playerLink = this.players.link; this.allPlayer.forEach(player => {
let player: Player;
let j = 0;
while (j < this.playerSize) {
player = playerLink.node;
player.clearActionSize(); player.clearActionSize();
playerLink = playerLink.next; });
j++;
}
} }
removePlayer(currPlayer: Player) { removePlayer(currPlayer: Player) {
let playerLink = this.players.link; let playerLink = this.playerLink.link;
let player: Player; let player: Player;
while (playerLink.next) { while (playerLink.next) {
player = playerLink.next.node; player = playerLink.next.node;
@@ -256,7 +280,7 @@ export class PokerGame {
getWinner() { getWinner() {
if (this.allInPlayers.length === 0 && this.playerSize === 1) { if (this.allInPlayers.length === 0 && this.playerSize === 1) {
this.winner = this.currPlayer.node; this.winner.push([ this.currPlayer.node ]);
return; return;
} }
while (this.status !== EGameStatus.GAME_SHOWDOWN) { while (this.status !== EGameStatus.GAME_SHOWDOWN) {
@@ -265,15 +289,14 @@ export class PokerGame {
} }
// compare allin player and last player // compare allin player and last player
const allPlayers = this.getPlayers(); const allPlayers = this.getPlayers();
const winner = [];
const maxPlayers = this.maxPlayers(allPlayers); const maxPlayers = this.maxPlayers(allPlayers);
winner.push(maxPlayers); this.winner.push(maxPlayers);
const hasSecondWinner = maxPlayers.filter(p => p.evPot !== 0).length === 0; const hasSecondWinner = maxPlayers.filter(p => p.evPot !== 0).length === 0;
// all of winner is all in, must get max curr player // all of winner is all in, must get max curr player
if (hasSecondWinner) { if (hasSecondWinner) {
const lastPlayer = this.getPlayers(''); const lastPlayer = this.getPlayers('');
const maxLastPlayer = this.maxPlayers(lastPlayer); const maxLastPlayer = this.maxPlayers(lastPlayer);
winner.push(maxLastPlayer); this.winner.push(maxLastPlayer);
} }
} }
@@ -297,7 +320,7 @@ export class PokerGame {
setHandCard() { setHandCard() {
// send card start by small blind // send card start by small blind
let playerLink = this.players.link; let playerLink = this.playerLink.link;
let player: Player; let player: Player;
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
let j = 0; let j = 0;
+48 -10
View File
@@ -1,4 +1,4 @@
import { PokerGame } from '../../../src/app/core/PokerGame'; import { PokerGame, EGameStatus } from '../../../src/app/core/PokerGame';
// @ts-ignore // @ts-ignore
import { expect } from 'chai'; import { expect } from 'chai';
import { IPlayer } from '../../../src/app/core/Player'; import { IPlayer } from '../../../src/app/core/Player';
@@ -7,14 +7,24 @@ describe('test/app/core/pokerGame.test.ts', () => {
const users: IPlayer[] = [ const users: IPlayer[] = [
{ {
userId: '1', userId: '1',
position: 0,
counter: 200, counter: 200,
}, },
{ {
userId: '2', userId: '2',
position: 1,
counter: 200, counter: 200,
}, },
{
userId: '3',
counter: 50,
},
{
userId: '4',
counter: 400,
},
{
userId: '5',
counter: 1200,
},
]; ];
/** /**
@@ -25,11 +35,13 @@ describe('test/app/core/pokerGame.test.ts', () => {
smallBlind: 1, smallBlind: 1,
users, users,
}); });
expect(game.status).to.equal(0); game.play();
expect(game.currPlayer.node.counter).to.equal(199); expect(game.status).to.equal(EGameStatus.GAME_ACTION);
expect(game.currPlayer.node.actionSize).to.equal(1); console.log(game.currPlayer, 'currPlayer');
expect(game.pots[0]).to.equal(3); expect(game.currPlayer.node.actionSize).to.equal(0);
expect(game.pots[0]).to.equal(3); expect(game.pot).to.equal(3);
expect(game.pot).to.equal(3);
expect(game.playerLink.getNode(1).node.actionSize).to.equal(1);
}); });
/** /**
@@ -42,10 +54,36 @@ describe('test/app/core/pokerGame.test.ts', () => {
}); });
game.play(); game.play();
console.log(game.currPlayer.node.handCard) console.log(game.currPlayer.node.handCard)
console.log(game.commonCard); game.action('call');
game.action('call');
game.action('call');
game.action('call');
game.action('check');
game.sendCard();
console.log(game.status, '------a');
console.log(game.currPlayer, '------b')
game.action('raise:10'); game.action('raise:10');
game.action('raise:20'); game.action('raise:20');
console.log(game.pots); game.action('call');
game.action('call');
game.action('raise:40');
game.action('call');
game.action('call');
game.action('call');
game.action('call');
game.sendCard();
console.log(game.status, '------c');
console.log(game.currPlayer, '------c')
game.action('allin');
game.action('allin');
game.action('allin');
game.action('allin');
game.action('allin');
console.log(game.status, '---------b')
// game.action('raise:10');
console.log(game.commonCard);
console.log(game.pot);
console.log(game.getPlayers());
}); });
// flop // flop
// turn // turn
+1
View File
@@ -9,6 +9,7 @@ describe('test/utils/link.test.ts', () => {
const person4 = new Player({ counter: 2, position: 4, userId: '4' }); const person4 = new Player({ counter: 2, position: 4, userId: '4' });
// const person5 = new Player({ counter: 2, position: 5, userId: '5' }); // const person5 = new Player({ counter: 2, position: 5, userId: '5' });
const link = new Link<Player>([ person1, person2, person3, person4 ], false); const link = new Link<Player>([ person1, person2, person3, person4 ], false);
console.log(link.getNode(0), 'link--------')
console.log(link.link); console.log(link.link);
}); });