package game; import com.biotools.meerkat.Action; import com.biotools.meerkat.GameInfo; import com.biotools.meerkat.Hand; import com.biotools.meerkat.Player; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.*; import static org.mockito.Mockito.*; /** * Tests the PublicGameInfo */ public class PublicGameInfoTest { /** * tests correct working of the {@link GameInfo#getNumToAct()} method. * We play a game to the turn and check for correct results<br> * - preflop: is complicated, because SB+BB count double (posting the blinds and calling/checking) * - flop: all check * - turn: a bet and a reraise - getNumToAct alternates */ @Test public void testNumToAct() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setBlinds(0.01, 0.02); gameInfo.setNumSeats(4); gameInfo.setPlayer(0, PublicPlayerInfo.create("player1", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player2", 100, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player3", 100, null)); gameInfo.setPlayer(3, PublicPlayerInfo.create("player4", 100, null)); gameInfo.newHand(0, 1, 2); // preflop // ------- // as long as noone calls, we wait for everyone to the SB: // (player1: post SB, player2: post BB, player3: ??, player0: ??, player(SB): ??) assertEquals(5, gameInfo.getNumToAct()); gameInfo.update(Action.smallBlindAction(0.01), 1); assertEquals(4, gameInfo.getNumToAct()); gameInfo.update(Action.bigBlindAction(0.02), 2); // pl-3: ??, pl-0: ??, pl-1 (SB): ??, assertEquals(3, gameInfo.getNumToAct()); // now someone calls - this make the bigblind need to check gameInfo.update(Action.callAction(0.02), 3); // pl-0: ??, pl-1 (SB): ??, pl-2(BB) (check/raise??) assertEquals(3, gameInfo.getNumToAct()); gameInfo.update(Action.callAction(0.02), 0); assertEquals(2, gameInfo.getNumToAct()); gameInfo.update(Action.callAction(0.01), 1); gameInfo.update(Action.checkAction(), 2); assertEquals(0, gameInfo.getNumToAct()); // flop // ------- gameInfo.nextStage(new Hand("8s 8c 8h")); // 4 players, all check assertEquals(4, gameInfo.getNumToAct()); gameInfo.update(Action.checkAction(), 1); gameInfo.update(Action.checkAction(), 2); assertEquals(2, gameInfo.getNumToAct()); gameInfo.update(Action.checkAction(), 3); gameInfo.update(Action.checkAction(), 0); assertEquals(0, gameInfo.getNumToAct()); // turn // ------- gameInfo.nextStage(new Hand("8d")); // 4 players, 2 check, 1 raise, all other have to call assertEquals(4, gameInfo.getNumToAct()); gameInfo.update(Action.checkAction(), 1); gameInfo.update(Action.checkAction(), 2); assertEquals(2, gameInfo.getNumToAct()); // one bet, so remaining 3 have to call (or fold) gameInfo.update(Action.betAction(0.2), 3); assertEquals(3, gameInfo.getNumToAct()); gameInfo.update(Action.callAction(0.02), 0); gameInfo.update(Action.foldAction(0.02), 1); assertEquals(1, gameInfo.getNumToAct()); // reraise - one folded so two are left to call gameInfo.update(Action.raiseAction(0.02, 0.02), 2); assertEquals(2, gameInfo.getNumToAct()); gameInfo.update(Action.callAction(0.02), 3); gameInfo.update(Action.callAction(0.02), 0); assertEquals(0, gameInfo.getNumToAct()); } /** * Test for issue #19. * When one player is all-in and the other decides to raise, * getNumToAct should be 0 for this round. */ @Test public void testNumToActAllInRaise() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setBlinds(0.01, 0.02); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player1", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player2", 100, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player3", 200, null)); gameInfo.newHand(0, 1, 2); gameInfo.update(Action.smallBlindAction(0.01), 1); gameInfo.update(Action.bigBlindAction(0.02), 2); gameInfo.update(Action.foldAction(0.02), 0); gameInfo.update(Action.callAction(0.01), 1); // flop // ------- gameInfo.nextStage(new Hand("8s 8c 8h")); assertEquals(2, gameInfo.getNumToAct()); gameInfo.update(Action.betAction(99.98), 1); // all-in assertEquals(1, gameInfo.getNumToAct()); gameInfo.update(Action.raiseAction(99.98, 50), 2); // strange raise, but the other one is all-in so noone to act anymore assertEquals(0, gameInfo.getNumToAct()); } /** * Tests correct work of {@link GameInfo#getAmountToCall(int)}.<br> * AmountToCall is the difference of the current players bet compared to * the highest bet.<br> * In PokerAcademy it is also capped to */ @Test public void testGetAmountToCall() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 50, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 100, null)); gameInfo.newHand(0, 1, 2); gameInfo.update(Action.smallBlindAction(5), 1); gameInfo.update(Action.bigBlindAction(10), 2); assertEquals(10, gameInfo.getAmountToCall(0), 0.001); assertEquals(5, gameInfo.getAmountToCall(1), 0.001); assertEquals(0, gameInfo.getAmountToCall(2), 0.001); gameInfo.update(Action.raiseAction(10, 90), 0); assertEquals(0, gameInfo.getAmountToCall(0), 0.001); // player 1 posted SB, but is capped to a call of 50 assertEquals(45, gameInfo.getAmountToCall(1), 0.001); // player 2 has 90 left and can call assertEquals(90, gameInfo.getAmountToCall(2), 0.001); } /** * Tests the building of SidePots. Here we create sort of a worst * case scenario: * player 2+3: small+bigblind 5/10 * player 0 raise 100: * mainpot(player1)=5+10+100 * player 1 call 50 (all-in): * mainpot(player1+2)=5+10+50+50, sidepot1(player1)=50 * player 2 call 70 (5SB+70=all-in): * mainPot(player1+2+3)=50+50+50, sidepot1(player1+3)=25+25, sidepot2(player1)=25 * player 3 call 10 (10BB+10=all-in): * mainPot(player1+2+3+4)=20+20+20+20, sidePot1=(player1+2+3)=30+30+30,sidepot2(player1+3)=25+25, sidepot3(player1)=25 */ @Test public void testPotHandling() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(4); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 200, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 50, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 75, null)); gameInfo.setPlayer(3, PublicPlayerInfo.create("player3", 20, null)); gameInfo.newHand(1, 2, 3); gameInfo.update(Action.smallBlindAction(5), 2); gameInfo.update(Action.bigBlindAction(10), 3); gameInfo.update(Action.raiseAction(10, 90), 0); assertEquals(115, gameInfo.getMainPotSize(), 0.001); // player 1, call 50 (all-in) // mainpot(player 2(SB),3(BB),0,1(caller)=5+10+50+50, sidepot1(player 0)=50 gameInfo.update(Action.callAction(50), 1); assertEquals(5 + 10 + 50 + 50, gameInfo.getMainPotSize(), 0.001); assertEquals(50, gameInfo.getSidePotSize(0), 0.001); // player 2, call 70 (all-in) // mainPot(player 2(SB), 3(BB), 0,1)=50+10+50+50, sidepot1(player 0, 2)=25+25, sidepot2(player0)=25 gameInfo.update(Action.callAction(70), 2); assertEquals(50 + 10 + 50 + 50, gameInfo.getMainPotSize(), 0.001); assertEquals(25 + 25, gameInfo.getSidePotSize(0), 0.001); assertEquals(25, gameInfo.getSidePotSize(1), 0.001); // player 3 call 10 (10BB+10=all-in): // mainPot(player 2(SB), 3(BB), 0,1)=20+20+20+20, sidepot1(player 2, 0, 1)=30+30+30, sidepot2(player0+2)=25+25, sidepot3(player0)=25 gameInfo.update(Action.callAction(10), 3); assertEquals(20 + 20 + 20 + 20, gameInfo.getMainPotSize(), 0.001); assertEquals(30 + 30 + 30, gameInfo.getSidePotSize(0), 0.001); assertEquals(25 + 25, gameInfo.getSidePotSize(1), 0.001); assertEquals(25, gameInfo.getSidePotSize(2), 0.001); } /** * TestMinRaiseSizes for NoLimit: * always bigblind at the beginning of a stage, otherwise last raise-amount */ @Test public void testMinRaiseSizeNoLimit() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 200, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 200, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 200, null)); gameInfo.newHand(0, 1, 2); gameInfo.update(Action.smallBlindAction(5), 1); gameInfo.update(Action.bigBlindAction(10), 2); assertEquals("minraise bigblind", 10, gameInfo.getMinRaise(), 0.001); gameInfo.update(Action.raiseAction(10, 50), 0); assertEquals("minraise 50", 50, gameInfo.getMinRaise(), 0.001); gameInfo.update(Action.foldAction(55), 1); gameInfo.update(Action.callAction(50), 2); gameInfo.nextStage(new Hand("7c 7s 7h")); assertEquals("minraise bigblind", 10, gameInfo.getMinRaise(), 0.001); gameInfo.update(Action.betAction(60), 2); assertEquals("minraise 60", 60, gameInfo.getMinRaise(), 0.001); gameInfo.update(Action.callAction(60), 0); gameInfo.nextStage(new Hand("7d")); assertEquals("minraise bigblind", 10, gameInfo.getMinRaise(), 0.001); } /** * TestMinRaiseSizes for Limit: * bigblind for preflop+flop, bigbet for turn and river */ @Test public void testMinRaiseSizeLimit() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.FIXED_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 100, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 100, null)); gameInfo.newHand(0, 1, 2); gameInfo.update(Action.smallBlindAction(5), 1); gameInfo.update(Action.bigBlindAction(10), 2); assertEquals("minraise bigblind", 10, gameInfo.getMinRaise(), 0.001); gameInfo.nextStage(new Hand("7c 7s 7h")); assertEquals("minraise bigblind", 10, gameInfo.getMinRaise(), 0.001); gameInfo.nextStage(new Hand("7d")); assertEquals("minraise bigbet", 20, gameInfo.getMinRaise(), 0.001); } /** * Test the values of {@link PublicGameInfo#getNumRaises()}. * According to issue #29, PokerAcademy also counts sb * and bets as 'numRaise'. * Also after each round numRaises starts at 0 */ @Test public void testNumRaises() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 100, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 100, null)); gameInfo.newHand(0, 1, 2); gameInfo.update(Action.smallBlindAction(5), 1); assertEquals("sb counts as raise", 1, gameInfo.getNumRaises()); gameInfo.update(Action.bigBlindAction(10), 2); assertEquals("bb no extra raise", 1, gameInfo.getNumRaises()); gameInfo.update(Action.callAction(10), 0); gameInfo.nextStage(new Hand("7c 7s 7h")); assertEquals("num raises = 0 after stage", 0, gameInfo.getNumRaises()); gameInfo.update(Action.betAction(10), 1); assertEquals("bet is raise", 1, gameInfo.getNumRaises()); } @Test public void testBigBlindPlayerDoesNotHaveEnoughToCallTheBlind() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 20, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 20, null)); // SB gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 2, null)); // BB gameInfo.newHand(0, 1, 2); gameInfo.update(Action.smallBlindAction(5), 1); gameInfo.update(Action.bigBlindAction(10), 2); assertThat("A new side pot is created", gameInfo.getPotManager().getNumPots(), is(2)); assertThat("Main pot has all-in BB plus the same value from SB", gameInfo.getPotManager().getPot(0).getValue(), is(4.0)); assertThat("Side pot has SB minus all-in BB", gameInfo.getPotManager().getPot(1).getValue(), is(3.0)); assertThat("BB has no money left", gameInfo.getPlayer(2).getBankRoll(), is(0.0)); assertThat("There is one all-in player (the BB)", gameInfo.getNumberOfAllInPlayers(), is(1)); assertThat(gameInfo.getAmountToCall(0), is(5.0)); assertThat(gameInfo.getCurrentBetSize(), is(10.0)); gameInfo.update(Action.foldAction(10), 0); gameInfo.update(Action.foldAction(5), 1); gameInfo.payout(); assertThat("BB received the uncalled bet from main pot", gameInfo.getPlayer(2).getBankRoll(), is(4.0)); assertThat("SB received the uncalled bet from side pot", gameInfo.getPlayer(1).getBankRoll(), is(18.0)); } @Test public void shouldRemovePlayerFromGame() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 100, null)); Player bot2 = mock(Player.class); PublicPlayerInfo player2 = PublicPlayerInfo.create("player2", 100, bot2); player2.setSittingOut(true); gameInfo.setPlayer(2, player2); gameInfo.removePlayer(player2); assertThat(gameInfo.getNumActivePlayers(), is(2)); assertThat(gameInfo.getPlayer(2), is(nullValue())); gameInfo.observersFireGameOverEvent(); verify(bot2, never()).gameOverEvent(); } @Test public void shouldOnlyRemovePlayerFromGameWhenHesSittingOut() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(1); PublicPlayerInfo player0 = PublicPlayerInfo.create("player0", 100, null); gameInfo.setPlayer(0, player0); try { gameInfo.removePlayer(player0); assertFalse("IllegalArgumentException not thrown!", false); } catch (IllegalArgumentException e) { } player0.setSittingOut(true); gameInfo.removePlayer(player0); assertThat(gameInfo.getNumActivePlayers(), is(0)); } @Test public void shouldSeatANewPlayerInAnAvailableSeat() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 100, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 100, null)); gameInfo.getPlayer(2).setSittingOut(true); gameInfo.seatPlayer(PublicPlayerInfo.create("player3", 100, null)); assertThat(gameInfo.getPlayer(2).getName(), is("player3")); } @Test public void shouldSetSittingOutToFalseWhenSeatingPlayer() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); PublicPlayerInfo player = PublicPlayerInfo.create("player", 100, null); player.setSittingOut(true); gameInfo.seatPlayer(player); assertThat(gameInfo.getPlayer(0).getName(), is("player")); assertThat(gameInfo.getPlayer(0).isSittingOut(), is(false)); } @Test public void shouldSeatANewPlayerInANewPlaceIfNoneIsAvailable() { PublicGameInfo gameInfo = new PublicGameInfo(); gameInfo.setLimit(PublicGameInfo.NO_LIMIT); gameInfo.setBlinds(5, 10); gameInfo.setNumSeats(3); gameInfo.setPlayer(0, PublicPlayerInfo.create("player0", 100, null)); gameInfo.setPlayer(1, PublicPlayerInfo.create("player1", 100, null)); gameInfo.setPlayer(2, PublicPlayerInfo.create("player2", 100, null)); int seat = gameInfo.seatPlayer(PublicPlayerInfo.create("player3", 100, null)); assertThat(seat, is(3)); assertThat(gameInfo.getPlayer(3).getName(), is("player3")); } }