package game; import bots.BotLoggingDecorator; import bots.demobots.AlwaysCallBot; import com.biotools.meerkat.Action; import com.biotools.meerkat.GameInfo; import com.biotools.meerkat.Player; import game.deck.Deck; import game.deck.MockDeck; import org.apache.commons.io.IOUtils; import org.junit.Test; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; /** * Tests the workings of the Dealer class */ public class DealerTest { /** * Tests that dealing a hand produces the right events * to GameObservers/Players<br> * The hand we play here was run in PokerAcademy, events that need * to be generated were 'recorded' with a LoggingBot so we test * for the same events and order * * @throws Exception */ @Test public void testGameEventsForPlayer() throws Exception { Deck deck = new MockDeck(new String[]{"Jh 9h 2h 3c 5h"}, new String[]{"As Ks|2s 8d|8h Qc"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 200, new FirstRaiseBot())); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 200, new AlwaysCallBot())); BotLoggingDecorator botLog = new BotLoggingDecorator(new AlwaysCallBot(), true); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 200, botLog)); gameInfo.setBlinds(0.05, 0.10); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog1.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * tests the win-amount - the last raiser doesn't 'win' his uncontested raise.<br> * all player limp the blind (pot =0.3) but one raises additional $5. * Nevertheless he just wins 0.3, and gets returned his raise<br> * We need to be this exact to not confuse PokerTracker and HoldEm-Manager * * @throws Exception */ @Test public void testWinAmount() throws Exception { Deck deck = new MockDeck(new String[]{"Jh 9h 2h 3c 5h"}, new String[]{"As Ks|2s 8d|8h Qc"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setBlinds(0.05, 0.10); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.callAction(0.10), // player2: call BB Action.raiseAction(0.05, 5), // player0 (SB): raise BB Action.foldAction(5.00), // player1 (BB): fold Action.foldAction(5.00) // player2 : fold ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0 Dealer", 200, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1 SB", 200, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2 BB", 200, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_winAmount.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); assertEquals(199.90, gameInfo.getPlayer(0).getBankRoll(), 0.001); assertEquals(200.20, gameInfo.getPlayer(1).getBankRoll(), 0.001); assertEquals(199.90, gameInfo.getPlayer(2).getBankRoll(), 0.001); } /** * This hand starts preflop with calls and on the flop with a raise. All players * fold, so the pot goes to the raise uncontested * * @throws Exception */ @Test public void testFoldedGameFlop() throws Exception { Deck deck = new MockDeck(new String[]{"Jh 9h 2h 3c 5h"}, new String[]{"As Ks|2s 8d|8h Qc"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setBlinds(0.05, 0.10); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.callAction(0.10), // player2: call BB Action.callAction(0.05), // player0 (SB): call BB Action.checkAction(), // player1 (BB): check // -- flop -- Action.betAction(0.10), // player0: bet Action.foldAction(0.10), // player1: fold Action.foldAction(0.10) // player2: fold ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 200, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 200, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 200, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_FoldedFlopGame.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * This hand starts preflop with folds.<br> * Thus the bigblind doesn't need to act and wins * * @throws Exception */ @Test public void testFoldedGamePreFlop() throws Exception { Deck deck = new MockDeck(new String[]{"Jh 9h 2h 3c 5h"}, new String[]{"As Ks|2s 8d|8h Qc"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setBlinds(0.05, 0.10); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.foldAction(0.10), // player2: fold Action.foldAction(0.05) // player0 (SB): fold ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 200, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 200, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 200, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_FoldedPreFlopGame.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * This hand starts preflop with calls and on the flop with an all-in. * One player calls.<br> * The players must now reveal cards, the game progresses to showdown ( * i.e. turn + river cards are revealed).<br> * The hand we play here was run in PokerAcademy, events that need * to be generated were 'recorded' with a LoggingBot so we test * for the same events and order * * @throws Exception */ @Test public void testAllInGame1() throws Exception { Deck deck = new MockDeck(new String[]{"Jh 9h 2h 3c 5h"}, new String[]{"As Ks|2s 8d|8h Qc"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setBlinds(0.05, 0.10); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.callAction(0.10), // player2: call BB Action.callAction(0.05), // player0 (SB): call BB Action.checkAction(), // player1 (BB): check // -- flop -- Action.betAction(0.90), // player0: all-in bet Action.callAction(0.90), // player1: all-in call Action.foldAction(0.90) // player2: fold ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 1, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 1, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 1, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("playerTestLog_AllInGame1.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * like {@link #testAllInGame1()} but other order of action.<br> * Here the first aggressor raises more than the second players bankroll.<br> * Second player just calls and a splitpot is created - this needs to cleared * instantly (uncalled bet returned to aggressor) and both players have to show * their cards before river. * * @throws Exception */ @Test public void testAllInGame2() throws Exception { Deck deck = new MockDeck(new String[]{"2d 3d Td 6h Ac"}, new String[]{"As Ks|2s 8d|8h Qc|2c 7c"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(4); gameInfo.setBlinds(0.01, 0.02); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.callAction(0.02), // player2: call BB Action.foldAction(0.02), // player3: fold Action.callAction(0.01), // player0 (SB): call BB Action.checkAction(), // player1 (BB): check // -- flop -- Action.betAction(0.02), // player0: bet Action.foldAction(0.02), // player1: fold Action.raiseAction(0.02, 0.03), // player2: raise Action.raiseAction(0.03, 0.15), // player0: raise Action.raiseAction(0.15, 0.83), // player2: raise Action.callAction(0.83), // player0: call // -- turn -- Action.checkAction(), // player0: check Action.betAction(0.71), // player2: bet Action.callAction(0.19) // player0: call (all-in) ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0 (SB)", 1.24, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1 (BB)", 1.72, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 4.88, botLog)); gameInfo.setPlayer(3, PublicPlayerInfo.create("player3", 20.88, mockPlayer)); Dealer dealer = new Dealer(deck, gameInfo); dealer.moveButton(); dealer.moveButton(); dealer.moveButton(); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_AllInGame2.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * test for tied pots with even money in the end * * @throws Exception */ @Test public void testTiedPotEvenMoney() throws Exception { Deck deck = new MockDeck(new String[]{"4d 2d 7h 5h Kh"}, new String[]{"2c 7s|As 7d|Ah 7c"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(4); gameInfo.setBlinds(0.01, 0.02); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.foldAction(0.02), // player0: fold Action.callAction(0.01), // player1 (SB): call Action.checkAction(), // player2 (BB): check // -- flop -- Action.betAction(0.02), // player1: bet Action.raiseAction(0.02, 9.74), // player2: raise (all-in) Action.callAction(9.74) // player1: call ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 38.35, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1 (SB)", 10.46, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2 (BB)", 9.78, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_tiedPotEvenMoney.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * test for tied pots with uneven money in the end.<br> * Some players get a cent more than others * * @throws Exception */ @Test public void testTiedPotUnevenMoney() throws Exception { Deck deck = new MockDeck(new String[]{"4d 2d 7h 5h Kh"}, new String[]{"2c 7s|As 7d|Ah 7c"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(4); gameInfo.setBlinds(0.01, 0.02); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.raiseAction(0.02, 0.05), // player0: raise Action.callAction(0.06), // player1 (SB): call Action.callAction(0.05), // player2 (BB): check // -- flop -- Action.betAction(0.02), // player1: bet Action.raiseAction(0.02, 9.69), // player2: raise (all-in) Action.foldAction(9.71), // player0: fold Action.callAction(9.69) // player1: call ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0 ", 38.35, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1 (SB)", 10.46, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2 (BB)", 9.78, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_tiedPotUnevenMoney.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * tests that the bigblind is able to bet/raise correctly preflop.<br> * * @throws Exception */ @Test public void testBigBlindRaise() throws Exception { Deck deck = new MockDeck(new String[]{"4d 2d 7h 5h Kh"}, new String[]{"2c 7s|As 7d|Ah 7c"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setBlinds(0.01, 0.02); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.foldAction(0.02), // player0: fold Action.callAction(0.01), // player1 (SB): call Action.betAction(0.05), // player2 (BB): bet/raise Action.callAction(0.05), // player1 (SB): call // -- flop -- Action.betAction(0.10), // player1: bet Action.foldAction(0.10) // player2: fold ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 38.35, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1 (SB)", 10.46, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2 (BB)", 9.78, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_bigBlindRaise.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } /** * see issue #30 * * @throws Exception */ @Test public void testIssue30() throws Exception { Deck deck = new MockDeck(new String[]{"4d 2d 7h 5h Kh"}, new String[]{"2c 7s|As 7d|Ah 7c"}); PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(3); gameInfo.setBlinds(0.1, 0.2); // we use one player at all seats Player mockPlayer = new PrerecordedPlayerMock( // Action.callAction(0.02), // p3 call Action.callAction(0.01), // p1 (SB) call Action.betAction(0.6), // p2 (BB): bet/raise Action.callAction(0.6), // p3 call Action.raiseAction(0.6, 0.2), // p1 - allin - raise Action.callAction(0.2), // p2 - call Action.callAction(0.2), // p3 - call // -- flop -- Action.betAction(0.5), // player2: bet Action.foldAction(0.5) // player3: fold ); gameInfo.setPlayer(0, PublicPlayerInfo.create("player1 (SB)", 1.00, mockPlayer)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player2 (BB)", 2.00, mockPlayer)); BotLoggingDecorator botLog = new BotLoggingDecorator(mockPlayer, false); gameInfo.setPlayer(2, PublicPlayerInfo.create("player3 ", 2.00, botLog)); Dealer dealer = new Dealer(deck, gameInfo); dealer.moveButton(); dealer.moveButton(); dealer.playHand(); String playerLog = IOUtils.toString(this.getClass().getResourceAsStream("./playerTestLog_issue30.txt")).replace("\r", ""); assertEquals(playerLog, botLog.getLog()); } @Test public void shouldSkipBustedPlayersWhenSelectingNewBigBlind() throws Exception { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(5); gameInfo.setPlayer(0, PublicPlayerInfo.create("player1 (D)", 2.00, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player2 (SB)", 2.00, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player3 (BB)", 2.00, null)); gameInfo.setPlayer(3, PublicPlayerInfo.create("player4", 2.00, null)); gameInfo.setPlayer(4, PublicPlayerInfo.create("player5", 2.00, null)); Dealer dealer = new Dealer(null, gameInfo); gameInfo.getPlayer(3).setBankroll(0.0); gameInfo.getPlayer(3).setSittingOut(true); dealer.moveButton(); assertThat(dealer.buttonSeat, is(1)); assertThat(dealer.smallBlindSeat, is(2)); assertThat(dealer.bigBlindSeat, is(4)); } @Test public void shouldSkipBustedPlayersWhenSelectingNewSmallBlind() throws Exception { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(5); gameInfo.setPlayer(0, PublicPlayerInfo.create("player1 (D)", 2.00, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player2 (SB)", 2.00, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player3 (BB)", 2.00, null)); gameInfo.setPlayer(3, PublicPlayerInfo.create("player4", 2.00, null)); gameInfo.setPlayer(4, PublicPlayerInfo.create("player5", 2.00, null)); Dealer dealer = new Dealer(null, gameInfo); gameInfo.getPlayer(2).setSittingOut(true); gameInfo.getPlayer(2).setBankroll(0.0); dealer.moveButton(); assertThat(dealer.buttonSeat, is(1)); assertThat(dealer.smallBlindSeat, is(3)); assertThat(dealer.bigBlindSeat, is(4)); } @Test public void shouldSkipBustedPlayersWhenSelectingNewButton() throws Exception { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setNumSeats(5); gameInfo.setPlayer(0, PublicPlayerInfo.create("player1 (D)", 2.00, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player2 (SB)", 2.00, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player3 (BB)", 2.00, null)); gameInfo.setPlayer(3, PublicPlayerInfo.create("player4", 2.00, null)); gameInfo.setPlayer(4, PublicPlayerInfo.create("player5", 2.00, null)); Dealer dealer = new Dealer(null, gameInfo); gameInfo.getPlayer(1).setSittingOut(true); gameInfo.getPlayer(1).setBankroll(0.0); dealer.moveButton(); assertThat(dealer.buttonSeat, is(2)); assertThat(dealer.smallBlindSeat, is(3)); assertThat(dealer.bigBlindSeat, is(4)); } /** * simple Testbot, whose first action is to raise */ class FirstRaiseBot extends AlwaysCallBot { private int counter = 0; private GameInfo gameInfo; @Override public void gameStartEvent(GameInfo gInfo) { this.gameInfo = gInfo; super.gameStartEvent(gInfo); } @Override public Action getAction() { if (counter++ == 0) { return Action.raiseAction(gameInfo, 0.1); } return super.getAction(); } } }