/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package bots.mctsbot.client.common.gamestate;
import java.util.HashSet;
import java.util.Set;
import bots.mctsbot.client.common.playerstate.PlayerState;
import bots.mctsbot.common.elements.player.PlayerId;
import bots.mctsbot.common.elements.table.SeatId;
import com.google.common.collect.ImmutableBiMap;
/**
* Abstract GameState partial implementation. Only methods that are a simple
* combination of other methods should be implemented here. This is the only
* place where you can safely call other methods in the same state.
*
* @author guy
*/
public abstract class AbstractGameState implements GameState {
public final int getDeficit(PlayerId playerId) {
return getLargestBet() - getPlayer(playerId).getBet();
}
public final int getCallValue(PlayerId playerId) {
PlayerState player = getPlayer(playerId);
return Math.min(getLargestBet() - player.getBet(), player.getStack());
}
public final boolean isAllowedToRaise(PlayerId playerId) {
PlayerState player = getPlayer(playerId);
if (getLargestBet() - player.getBet() >= player.getStack()) {
return false;
}
Set<PlayerState> otherPlayers = getAllSeatedPlayers();
for (PlayerState otherPlayer : otherPlayers) {
// check whether we are the only active player left in the game.
if (!otherPlayer.getPlayerId().equals(playerId) && otherPlayer.isActivelyPlaying()) {
return true;
}
}
return false;
}
public final int getLowerRaiseBound(PlayerId playerId) {
PlayerState player = getPlayer(playerId);
return Math.max(0, Math.min(getMinNextRaise(), player.getStack() - (getLargestBet() - player.getBet())));
}
public final int getUpperRaiseBound(PlayerId playerId) {
PlayerState player = getPlayer(playerId);
PlayerState tempPlayer;
PlayerId tempId = playerId;
int maxOtherBettableChips = 0;
loop: do {
//TODO fix infinite loop on double BB
tempPlayer = getNextActivePlayerAfter(tempId);
if (tempPlayer == null) {
break loop;
}
tempId = tempPlayer.getPlayerId();
if (!tempPlayer.getPlayerId().equals(playerId)) {
maxOtherBettableChips = Math.max(maxOtherBettableChips, tempPlayer.getBet() + tempPlayer.getStack());
} else {
break loop;
}
} while (true);
int betableChips = Math.min(player.getStack() + player.getBet(), maxOtherBettableChips);
return Math.max(0, betableChips - getLargestBet());
}
public final int getGamePotSize() {
return getPreviousRoundsPotSize() + getRoundPotSize();
}
public final boolean hasBet() {
return getLargestBet() > 0;
}
public final Set<PlayerState> getAllSeatedPlayers() {
Set<PlayerId> ids = getSeatMap().values();
HashSet<PlayerState> states = new HashSet<PlayerState>();
for (PlayerId id : ids) {
states.add(getPlayer(id));
}
return states;
}
@Override
public final PlayerState getDefaultWinner() {
Set<PlayerId> ids = getSeatMap().values();
PlayerState first = null;
for (PlayerId id : ids) {
PlayerState state = getPlayer(id);
if (!state.hasFolded()) {
if (first != null) {
return null;
} else {
first = state;
}
}
}
return first;
}
public final PlayerState getNextSeatedPlayerAfter(PlayerId startPlayer) {
ImmutableBiMap<SeatId, PlayerId> seatMap = getSeatMap();
int maxNbPlayers = getTableConfiguration().getMaxNbPlayers();
SeatId currentSeat = seatMap.inverse().get(startPlayer);
PlayerId currentPlayer;
do {
currentSeat = new SeatId((currentSeat.getId() + 1) % maxNbPlayers);
currentPlayer = seatMap.get(currentSeat);
} while (currentPlayer == null);
if (currentPlayer.equals(startPlayer)) {
return null;
}
return getPlayer(currentPlayer);
}
public final PlayerState getNextActivePlayerAfter(PlayerId startPlayerId) {
PlayerState currentPlayer;
PlayerId currentPlayerId = startPlayerId;
do {
currentPlayer = getNextSeatedPlayerAfter(currentPlayerId);
if (currentPlayer == null) {
return null;
}
currentPlayerId = currentPlayer.getPlayerId();
if (currentPlayerId.equals(startPlayerId)) {
return null;
}
} while (!currentPlayer.isActivelyPlaying());
return currentPlayer;
}
@Override
public void acceptHistoryVisitor(GameStateVisitor visitor, GameState start) {
if (this != start) {
getPreviousGameState().acceptHistoryVisitor(visitor, start);
acceptVisitor(visitor);
}
}
@Override
public String toString() {
return getLastEvent() + "\n" + getPreviousGameState();
}
}