Initial Commit. Moving all the stuff to gitea

main
Jakob 2025-01-09 13:34:31 +01:00
parent c61645303a
commit 20e5f92168
25 changed files with 2158 additions and 0 deletions

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-14">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
Poker_PR1/.project 100644
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Poker_PR1</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,149 @@
package action;
import game.PokerGame;
import player.PokerPlayer;
public class ActionLegalChecker {
// hard todo
PokerAction action;
PokerPlayer player;
PokerGame game;
boolean legal;
String info = "default info";
public ActionLegalChecker(PokerAction action, PokerPlayer player, PokerGame game) {
this.action = action;
this.player = player;
this.game = game;
compute();
}
private void compute() {
if (action instanceof UnknownAction) {
legal = false;
info = ((UnknownAction) action).getInfo();
return;
}
if (action instanceof Fold) {
legal = true;
info = "Player mugs his hand";
return;
}
if (action instanceof Check) {
//Can only check when there is no bet yet or when player is BigBlind and already payed the money
if (game.getBetThisRound(player) == game.getHighestBetThisRound()) {
legal = true;
info = "There is no Bet yet or Player is Bigblind and everybody limped.";
} else {
legal = false;
info = "Player tried to check but there was a bet.";
}
return;
}
if (action instanceof Bet) {
Bet bet = (Bet) action;
if (game.getHighestBetThisRound() != 0) {
legal = false;
info = "Player can only bet when nobody has bet yet.";
return;
}
if (bet.getBB() > game.getBBLeftFromPlayer(player)) {
legal = false;
info = "Player doesn't have enough BB for this bet.";
return;
}
if (bet.getBB() < game.minBet) {
legal = false;
info = "The Bet has to be atleast " + game.minBet + "BB. The player bet " + bet.getBB() + "BB.";
return;
}
legal = true;
info = "Player made a legal Bet";
return;
}
if (action instanceof Call) {
//is there a way this is illegal?
//player has money, even if he doesn't have enough, he can still call all-in -> side pot opens
legal = true;
info = "Player called";
return;
}
if (action instanceof Raise) {
Raise raise = (Raise) action;
if (raise.getBB() > game.getBBLeftFromPlayer(player)) {
legal = false;
info = "Player doesn't have enough BB for this Raise.";
return;
}
if (raise.getBB() < game.getHighestBetOrRaise() * 2) {
legal = false;
info = "The Raise has to be atleast " + game.getHighestBetOrRaise() * 2 + "BB. The player raised " + raise.getBB() + "BB.";
return;
}
legal = true;
info = "Legal Raise";
return;
}
legal = false;
info = "Actually unknown Pokeraction (404)";
}
public boolean isLegal() {
return legal;
}
public String getInfo() {
return info;
}
}

View File

@ -0,0 +1,17 @@
package action;
public class Bet extends PokerAction {
private float bb;
public Bet(float bb) {
this.bb = bb;
}
public float getBB() {
return bb;
}
}

View File

@ -0,0 +1,17 @@
package action;
public class Call extends PokerAction {
private float bb;
public Call(float bb) {
this.bb = bb;
}
public float getBB() {
return bb;
}
}

View File

@ -0,0 +1,5 @@
package action;
public class Check extends PokerAction {
}

View File

@ -0,0 +1,5 @@
package action;
public class Fold extends PokerAction {
}

View File

@ -0,0 +1,7 @@
package action;
public abstract class PokerAction {
public PokerAction() { }
}

View File

@ -0,0 +1,17 @@
package action;
public class Raise extends PokerAction {
private float bb;
public Raise(float bb) {
this.bb = bb;
}
public float getBB() {
return bb;
}
}

View File

@ -0,0 +1,17 @@
package action;
public class UnknownAction extends PokerAction {
private String info;
public UnknownAction(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}

View File

@ -0,0 +1,39 @@
package announcer;
import java.util.HashMap;
import cards.Card;
import game.Hand;
import player.PokerPlayer;
public interface Broadcaster {
public void gameStarts(HashMap<PokerPlayer, Float> bigBlinds, PokerPlayer dealer, PokerPlayer smallBlind, PokerPlayer bigBlind);
public void blindsPayed(PokerPlayer smallBlind, PokerPlayer bigBlind);
/** @round 0 preflop, 1 flop, 2 turn, 3 river **/
public void bettingRoundStarts(int round);
public void playerIsToAct(PokerPlayer player);
public void broadcastFlop(Card card1, Card card2, Card card3);
public void broadcastTurn(Card card);
public void broadcastRiver(Card card);
public void playerFolded(PokerPlayer player);
public void playerChecked(PokerPlayer player);
public void playerBet(PokerPlayer player, float bb);
public void playerBetAllIn(PokerPlayer player, float bb);
public void playerCalled(PokerPlayer player, float bb);
public void playerCalledAllIn(PokerPlayer player, float bb);
public void playerRaised(PokerPlayer player, float bb);
public void playerRaisedAllIn(PokerPlayer player, float bb);
public void revealResult_Showdown(PokerPlayer winner, float winningBB, Hand winningHand);
public void revealResult_Folded(PokerPlayer winner, float winningBB);
public void playerHasNotEnoughBigBlinds(PokerPlayer player);
public void gameEnds();
public void playerLeavesTable(PokerPlayer player);
public void allRoundsPlayed();
}

View File

@ -0,0 +1,161 @@
package announcer;
import java.util.HashMap;
import cards.Card;
import game.Hand;
import player.PokerPlayer;
public class ConsoleBroadcaster implements Broadcaster {
String prefix = "Poker PR_1 von Jakob Feuerstein > ";
private void broadcast(String message) {
System.out.println(prefix + message);
}
@Override
public void gameStarts(HashMap<PokerPlayer, Float> bigBlinds, PokerPlayer dealer, PokerPlayer smallBlind,
PokerPlayer bigBlind) {
broadcast("A new poker game has started! " + dealer.getName() + " is the Dealer this round.");
}
@Override
public void blindsPayed(PokerPlayer smallBlind, PokerPlayer bigBlind) {
broadcast(smallBlind.getName() + " has paid the small blind");
broadcast(bigBlind.getName() + " has paid the big blind");
}
@Override
public void bettingRoundStarts(int round) {
if (round == 0) {
broadcast("The Preflop betting round has begun");
} else if (round == 1) {
broadcast("The Flop betting round has begun");
} else if (round == 2) {
broadcast("The Turn betting round has begun");
} else {
broadcast("The River betting round has begun");
}
}
@Override
public void playerIsToAct(PokerPlayer player) {
broadcast("It is the turn of " + player.getName());
}
@Override
public void broadcastFlop(Card card1, Card card2, Card card3) {
broadcast("The Flop is " + card1.toSymbol() + " " + card2.toSymbol() + " " + card3.toSymbol());
}
@Override
public void broadcastTurn(Card card) {
broadcast("The Turn Card is " + card.toSymbol());
}
@Override
public void broadcastRiver(Card card) {
broadcast("The River Card is " + card.toSymbol());
}
@Override
public void playerFolded(PokerPlayer player) {
broadcast(player.getName() + " folds");
}
@Override
public void playerChecked(PokerPlayer player) {
broadcast(player.getName() + " checks");
}
@Override
public void playerBet(PokerPlayer player, float bb) {
broadcast(player.getName() + " bets " + bb + "BB");
}
@Override
public void playerBetAllIn(PokerPlayer player, float bb) {
broadcast(player.getName() + " bets ALL-IN with his remaining " + bb + "BB");
}
@Override
public void playerCalled(PokerPlayer player, float bb) {
broadcast(player.getName() + " calls the " + bb + "BB");
}
@Override
public void playerCalledAllIn(PokerPlayer player, float bb) {
broadcast(player.getName() + " calls ALL-IN with " + bb + "BB");
}
@Override
public void playerRaised(PokerPlayer player, float bb) {
broadcast(player.getName() + " raises to " + bb + "BB");
}
@Override
public void playerRaisedAllIn(PokerPlayer player, float bb) {
broadcast(player.getName() + " goes ALL-IN with " + bb + "BB");
}
@Override
public void revealResult_Showdown(PokerPlayer winner, float winningBB, Hand winningHand) {
System.out.println("The Pokerplayer " + winner.getName() + " has won with the Hand " + winningHand + ". He wins " + winningBB + "BB.");
}
@Override
public void revealResult_Folded(PokerPlayer winner, float winningBB) {
System.out.println("The Pokerplayer " + winner.getName() + " has won, because everyone else mugged their hand. He wins " + winningBB + "BB.");
}
@Override
public void playerHasNotEnoughBigBlinds(PokerPlayer player) {
// TODO Auto-generated method stub
}
@Override
public void gameEnds() {
// TODO Auto-generated method stub
}
@Override
public void playerLeavesTable(PokerPlayer player) {
// TODO Auto-generated method stub
}
@Override
public void allRoundsPlayed() {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,45 @@
package cards;
public class Card {
private final CardValue value;
private final CardColor color;
public Card(CardValue value, CardColor color) {
this.value = value;
this.color = color;
}
public boolean isSameCard(Card card) {
return value == card.value && color == card.color;
}
public CardValue getValue() {
return value;
}
public String getFullName() {
return value.getSymbol() + " of " + color.getName();
}
public CardColor getColor() {
return color;
}
@Override
public String toString() {
return value.getSymbol() + color.getSymbol();
}
public String toSymbol() {
return value.getSymbol() + color.getSymbol();
}
}

View File

@ -0,0 +1,29 @@
package cards;
public enum CardColor {
CLUBS('♣', "Clubs"),
SPADES('♠', "Spades"),
HEARTS('♥', "Hearts"),
DIAMONDS('♦', "Diamonds");
private final char symbol;
private final String name;
CardColor(char symbol, String name) {
this.symbol = symbol;
this.name = name;
}
public char getSymbol() {
return symbol;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,52 @@
package cards;
public enum CardValue {
TWO("2", "Two", 1, (short) 1),
THREE("3", "Three", 2, (short) 2),
FOUR("4", "Four", 3, (short) 4),
FIVE("5", "Five", 4, (short) 8),
SIX("6", "Six", 5, (short) 16),
SEVEN("7", "Seven", 6, (short) 32),
EIGHT("8", "Eight", 7, (short) 64),
NINE("9", "Nine", 8, (short) 128),
TEN("10", "Ten", 9, (short) 256),
JACK("J", "Jack", 10, (short) 512),
QUEEN("Q", "Queen", 11, (short) 1024),
KING("K", "King", 12, (short) 2048),
ACE("A", "Ace", 13, (short) 4096);
private final String symbol;
private final String name;
private final int value;
private final short compareValue;
CardValue(String symbol, String name, int value, short compareValue) {
this.symbol = symbol;
this.name = name;
this.value = value;
this.compareValue = compareValue;
}
public String getSymbol() {
return symbol;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
public short getCompareValue() {
return compareValue;
}
}

View File

@ -0,0 +1,59 @@
package cards;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class Deck {
private List<Card> cards;
private Deck(List<Card> cards) {
this.cards = cards;
}
public void shuffle() {
Collections.shuffle(cards);
}
public void print() {
for (Card card : cards) {
System.out.println(card);
}
}
public static Deck generatePokerDeck() {
List<Card> cards = new ArrayList<>();
for (CardColor color : CardColor.values()) {
for (CardValue value : CardValue.values()) {
cards.add(new Card(value, color));
}
}
return new Deck(cards);
}
public Card drawRandomCard() {
Random random = new Random();
Card card = cards.get(random.nextInt(cards.size()));
cards.remove(card);
return card;
}
}

View File

@ -0,0 +1,30 @@
package core;
import java.util.LinkedHashMap;
import announcer.ConsoleBroadcaster;
import game.PokerGame;
import player.ConsolePokerPlayer;
import player.PokerPlayer;
public class Main {
public static void main(String[] args) {
System.out.println("Poker Application started.");
LinkedHashMap<PokerPlayer, Float> bb = new LinkedHashMap<>();
bb.put(new ConsolePokerPlayer("Jakob1"), 100f);
bb.put(new ConsolePokerPlayer("Jakob2"), 10f);
bb.put(new ConsolePokerPlayer("Jakob3"), 10f);
bb.put(new ConsolePokerPlayer("Jakob4"), 10f);
bb.put(new ConsolePokerPlayer("Jakob5"), 10f);
PokerGame game = new PokerGame(new ConsoleBroadcaster(), 1, bb, 0);
game.start();
}
}

View File

@ -0,0 +1,7 @@
package game;
public enum GameType {
NO_LIMIT_HOLDEM;
}

View File

@ -0,0 +1,423 @@
package game;
import java.util.ArrayList;
import cards.Card;
import cards.CardColor;
import cards.CardValue;
public class Hand {
private ArrayList<Card> cards;
private HandType type;
private String name;
private int strength;
public Hand(ArrayList<Card> cards, HandType type, String name, int strength) {
this.cards = cards;
this.type = type;
this.name = name;
this.strength = strength;
}
public boolean isSameHand(Hand hand) {
return cards.equals(hand.cards);
}
public ArrayList<Card> getHandmakingCards() {
return cards;
}
public HandType getHandType() {
return type;
}
@Override
public String toString() {
return name;
}
public int getStrength() {
return strength;
}
public static Hand calculateHand(ArrayList<Card> cards) {
if (cards.isEmpty()) {
return null;
}
// MEGA TODO
ArrayList<Hand> potentialHands = new ArrayList<>();
@SuppressWarnings("unchecked")
ArrayList<Card>[] valueSortedCards = new ArrayList[14];
for (int i = 0; i < 14; i++) {
valueSortedCards[i] = new ArrayList<Card>();
}
// Put cards into the arraylist of their CardValue, Ace into 1 and 13
for (Card card : cards) {
// Allow Broadways
if (card.getValue() == CardValue.ACE) {
valueSortedCards[0].add(card);
}
valueSortedCards[card.getValue().getValue()].add(card);
}
// Straight can start on ace (1) to 10
for (int i = 0; i <= 9; i++) {
boolean straight = true;
// check if every there is atleast one card with that value in all 5 straight
// positions
for (int c = 0; c < 5; c++) {
if (valueSortedCards[i + c].size() == 0) {
straight = false;
}
}
if (straight) {
for (int firstCard = 0; firstCard < valueSortedCards[i].size(); firstCard++) {
for (int secondCard = 0; secondCard < valueSortedCards[i + 1].size(); secondCard++) {
for (int thirdCard = 0; thirdCard < valueSortedCards[i + 2].size(); thirdCard++) {
for (int fourthCard = 0; fourthCard < valueSortedCards[i + 3].size(); fourthCard++) {
for (int fifthCard = 0; fifthCard < valueSortedCards[i + 4].size(); fifthCard++) {
ArrayList<Card> straightHandList = new ArrayList<>();
straightHandList.add(valueSortedCards[i].get(firstCard));
straightHandList.add(valueSortedCards[i + 1].get(secondCard));
straightHandList.add(valueSortedCards[i + 2].get(thirdCard));
straightHandList.add(valueSortedCards[i + 3].get(fourthCard));
straightHandList.add(valueSortedCards[i + 4].get(fifthCard));
Hand straightHand = new Hand(straightHandList, HandType.STRAIGHT,
"Straight " + valueSortedCards[i].get(firstCard).getValue() + " to "
+ valueSortedCards[i + 4].get(fifthCard).getValue(),
50000 + valueSortedCards[i + 4].get(0).getValue().getValue());
potentialHands.add(straightHand);
}
}
}
}
}
}
}
// check 4, 3, pair, highcard
boolean onlyHighCard = true;
ArrayList<Card> triple = null;
ArrayList<ArrayList<Card>> pairs = new ArrayList<>();
for (int i = 1; i < 14; i++) {
if (valueSortedCards[i].size() == 4) {
onlyHighCard = false;
Hand fourOfAKind = new Hand(valueSortedCards[i], HandType.FOUR_OF_A_KIND,
"Four of Kind: " + valueSortedCards[i].get(0).getValue(),
80000 + valueSortedCards[i].get(0).getValue().getValue());
potentialHands.add(fourOfAKind);
} else
if (valueSortedCards[i].size() == 3) {
onlyHighCard = false;
triple = valueSortedCards[i];
Hand threeOfAKind = new Hand(valueSortedCards[i], HandType.THREE_OF_A_KIND,
"Three of Kind: " + valueSortedCards[i].get(0).getValue(),
40000 + valueSortedCards[i].get(0).getValue().getValue());
potentialHands.add(threeOfAKind);
} else
if (valueSortedCards[i].size() == 2) {
onlyHighCard = false;
pairs.add(valueSortedCards[i]);
Hand pair = new Hand(valueSortedCards[i], HandType.PAIR,
"Pair: " + valueSortedCards[i].get(0).getValue(),
20000 + valueSortedCards[i].get(0).getValue().getValue());
potentialHands.add(pair);
}
}
if (onlyHighCard) {
Card highestCard = cards.get(0);
for (Card card : cards) {
if (highestCard.getValue().getValue() < card.getValue().getValue()) {
highestCard = card;
}
}
ArrayList<Card> highestCards = xHighestCards(cards.size(), cards);
int strength = 0;
for (Card card : highestCards) {
// macht das so mathemässig sinn?
strength += card.getValue().getCompareValue();
}
Hand highCardHand = new Hand(highestCards, HandType.HIGH_CARD, "Highcard " + highestCard, 10000 + strength);
potentialHands.add(highCardHand);
} else if (triple != null) {
if (!pairs.isEmpty()) {
ArrayList<Card> fullHouse = new ArrayList<>();
fullHouse.addAll(pairs.get(0));
fullHouse.addAll(triple);
Hand fullHouseHand = new Hand(fullHouse, HandType.FULL_HOUSE, "Full House", 70000);
potentialHands.add(fullHouseHand);
}
if (pairs.size() >= 1) {
ArrayList<Card> fullHouse = new ArrayList<>();
fullHouse.addAll(pairs.get(1));
fullHouse.addAll(triple);
Hand fullHouseHand = new Hand(fullHouse, HandType.FULL_HOUSE, "Full House", 70000);
potentialHands.add(fullHouseHand);
}
}
if (pairs.size() >= 2) {
// es zählt noch nicht erst das größte Paar ...
for (int firstPairIndex = 0; firstPairIndex < pairs.size() - 1; firstPairIndex++) {
for (int secondPairIndex = firstPairIndex + 1; secondPairIndex < pairs.size(); secondPairIndex++) {
ArrayList<Card> twoPair = new ArrayList<>();
twoPair.addAll(pairs.get(firstPairIndex));
twoPair.addAll(pairs.get(secondPairIndex));
Hand twoPairHand = new Hand(twoPair, HandType.TWO_PAIR,
"Two Pair " + pairs.get(firstPairIndex).get(0).getValue().getName() + " and "
+ pairs.get(secondPairIndex).get(0).getValue().getName(),
30000 + pairs.get(firstPairIndex).get(0).getValue().getCompareValue()
+ pairs.get(secondPairIndex).get(0).getValue().getCompareValue());
potentialHands.add(twoPairHand);
}
}
}
// check flush
for (CardColor color : CardColor.values()) {
ArrayList<Card> coloredCards = new ArrayList<>();
for (Card card : cards) {
if (card.getColor() == color) {
coloredCards.add(card);
}
}
coloredCards = xHighestCards(5, coloredCards);
if (coloredCards.get(0) == null) {
continue;
}
// Geht das so?
int strength = 0;
for (Card card : coloredCards) {
strength += card.getValue().getCompareValue();
}
Hand flush = new Hand(coloredCards, HandType.FLUSH,
coloredCards.get(4).getValue() + " high Flush of " + color.getSymbol(), 60000 + strength);
for (Hand potentialHand : potentialHands) {
if (potentialHand.isSameHand(flush) && potentialHand.type == HandType.STRAIGHT) {
boolean hasAce = false; // Broadway or Royal
boolean hasTen = false; // If hasAce -> Royal
for (Card card : flush.cards) {
if (card.getValue() == CardValue.ACE) {
hasAce = true;
} else
if (card.getValue() == CardValue.TEN) {
hasTen = true;
}
}
if (hasAce) {
if (hasTen) {
flush.type = HandType.ROYAL_FLUSH;
flush.name = "Royal Flush of " + color.getName();
flush.strength = 100000;
} else {
// Just so ace strength doesn't fuck up my strength rating
flush.type = HandType.STRAIGHT_FLUSH;
flush.name = "(Broadway) Straight Flush of " + color.getName();
flush.strength = 90000;
}
} else {
flush.type = HandType.STRAIGHT_FLUSH;
flush.name = "Straight Flush of flushs" + color.getName();
flush.strength = 90000 + strength;
}
}
}
potentialHands.add(flush);
}
//finding the hand with the highest Strength
int highestStrength = 0;
Hand bestHand = null;
for (Hand oneHand : potentialHands) {
if (oneHand.getStrength() > highestStrength) {
highestStrength = oneHand.getStrength();
bestHand = oneHand;
}
}
return bestHand;
}
public static ArrayList<Card> combineCards(ArrayList<Card> sharedCards, Card[] pocketCards) {
ArrayList<Card> combinedCards = new ArrayList<>();
combinedCards.add(pocketCards[0]);
combinedCards.add(pocketCards[1]);
combinedCards.addAll(sharedCards);
return combinedCards;
}
public static ArrayList<Card> xHighestCards(int x, ArrayList<Card> cards) {
Card[] fiveBiggestCards = new Card[x];
for (Card card : cards) {
int insertAt = x - 1;
for (int i = x - 1; i > 0; i--) {
if (fiveBiggestCards[i] == null && i == x - 1) {
insertAt = x - 1;
break;
}
if (fiveBiggestCards[i].getValue().getValue() < card.getValue().getValue()) {
insertAt = i;
break;
}
if (fiveBiggestCards[i - 1] == null) {
insertAt = i - 1;
break;
}
}
if (insertAt != -1) {
for (int p = 0; p < insertAt; p++) {
fiveBiggestCards[p] = fiveBiggestCards[p + 1];
}
}
fiveBiggestCards[insertAt] = card;
}
ArrayList<Card> handCards = new ArrayList<>();
for (int i = 0; i < x; i++) {
handCards.add(fiveBiggestCards[i]);
}
return handCards;
}
}

View File

@ -0,0 +1,16 @@
package game;
public enum HandType {
HIGH_CARD(),
PAIR(),
TWO_PAIR(),
THREE_OF_A_KIND(),
STRAIGHT(),
FLUSH(),
FULL_HOUSE(),
FOUR_OF_A_KIND(),
STRAIGHT_FLUSH(),
ROYAL_FLUSH();
}

View File

@ -0,0 +1,743 @@
package game;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import action.ActionLegalChecker;
import action.Bet;
import action.Call;
import action.Check;
import action.Fold;
import action.PokerAction;
import action.Raise;
import announcer.Broadcaster;
import announcer.ConsoleBroadcaster;
import cards.Card;
import cards.Deck;
import player.PokerPlayer;
public class PokerGame {
private Broadcaster caster;
private int rounds;
private int playerNumber;
private LinkedHashMap<PokerPlayer, Float> bbPerPlayer;
private PokerPlayer[] players;
private int dealerPosition;
private Deck deck;
private ArrayList<Card> sharedCards;
private HashMap<PokerPlayer, Card[]> pocketCards;
private int bettingRound;
private float pot;
private boolean running;
private HashMap<PokerPlayer, Float> betsThisRound;
private float biggestBet;
private ArrayList<PokerPlayer> foldedPlayers;
private int playerActing;
private boolean bigBlindActedOnPreflop;
private boolean dealerActed;
public final float minBet = 1;
public PokerGame(Broadcaster caster, int rounds, LinkedHashMap<PokerPlayer, Float> bbPerPlayer, int dealerPosition) {
this.caster = caster;
this.rounds = rounds;
this.bbPerPlayer = bbPerPlayer;
this.dealerPosition = dealerPosition;
initialize();
}
private void initialize() {
playerNumber = bbPerPlayer.keySet().size();
generatePlayerArray();
}
private void generatePlayerArray() {
//make players-Array be [0] small blind [1] big Blind [playerNumber - 1] Dealer etc.
players = new PokerPlayer[playerNumber];
for (int i = 0; i < playerNumber; i++) {
int playerIndex = i + 1 + dealerPosition;
if (playerIndex >= playerNumber) {
playerIndex = playerIndex % playerNumber;
}
players[i] = (PokerPlayer) bbPerPlayer.keySet().toArray()[playerIndex];
}
}
public float getHighestBetOrRaise() {
return biggestBet;
}
public float getBetThisRound(PokerPlayer player) {
return betsThisRound.get(player);
}
public float getBBLeftFromPlayer(PokerPlayer player) {
return bbPerPlayer.get(player);
}
public float getHighestBetThisRound() {
float highestBet = 0;
for (float bet : betsThisRound.values()) {
if (bet > highestBet) {
highestBet = bet;
}
}
return highestBet;
}
public void start() {
caster.gameStarts(bbPerPlayer, players[playerNumber - 1], players[0], players[1]);
running = true;
deck = Deck.generatePokerDeck();
sharedCards = new ArrayList<Card>();
pocketCards = new HashMap<PokerPlayer, Card[]>();
bettingRound = 0;
pot = 0;
bigBlindActedOnPreflop = false;
betsThisRound = new HashMap<PokerPlayer, Float>();
foldedPlayers = new ArrayList<>();
notifyPlayersOfStart();
payBlinds();
drawCards();
startNextBettingRound();
}
private void notifyPlayersOfStart() {
//double notifications when dealer is big blind?
for (int i = 0; i < playerNumber; i++) {
if (i == 0) {
players[i].notifyStart(Position.SMALL_BLIND, bbPerPlayer.get(players[i]));
} else if (i == 1) {
players[i].notifyStart(Position.BIG_BLIND, bbPerPlayer.get(players[i]));
} else if (i != playerNumber - 1){
players[i].notifyStart(Position.UNNAMED, bbPerPlayer.get(players[i]));
} else {
players[i].notifyStart(Position.DEALER, bbPerPlayer.get(players[i]));
}
}
}
private void payBlinds() {
//already checked that all players have atleast a bigblind?
//players get notified which position they play. Every or just button and blinds?
//dealer gets position info
//-0.5 bb from small blind
bbPerPlayer.put(players[0], bbPerPlayer.get(players[0]) - 0.5f);
pot += 0.5;
//-1 bb from big blind
bbPerPlayer.put(players[1], bbPerPlayer.get(players[1]) - 1f);
pot += 1.0;
caster.blindsPayed(players[0], players[1]);
}
private void drawCards() {
for (PokerPlayer player : players) {
Card card1 = deck.drawRandomCard();
Card card2 = deck.drawRandomCard();
pocketCards.put(player, new Card[]{card1, card2});
player.giveCards(card1, card2);
}
}
private void startNextBettingRound() {
//even for the folded
for (PokerPlayer player : bbPerPlayer.keySet()) {
betsThisRound.put(player, 0f);
}
biggestBet = 0;
bettingRound++;
playerActing = 0;
dealerActed = false;
//preflop just works differently
caster.bettingRoundStarts(bettingRound - 1);
if (bettingRound == 1) {
//pre-flop
betsThisRound.put(players[0], 0.5f);
betsThisRound.put(players[1], 1f);
biggestBet = 1f;
if (playerNumber > 2) {
playerActing = 2;
}
} else if (bettingRound == 2) {
//flop
Card card1 = deck.drawRandomCard();
Card card2 = deck.drawRandomCard();
Card card3 = deck.drawRandomCard();
ArrayList<Card> flop = new ArrayList<>();
flop.add(card1);
flop.add(card2);
flop.add(card3);
sharedCards.addAll(flop);
caster.broadcastFlop(card1, card2, card3);
for (PokerPlayer player : players) {
player.revealFlop(flop);
}
} else if (bettingRound == 3) {
//turn
Card card = deck.drawRandomCard();
sharedCards.add(card);
caster.broadcastTurn(card);
for (PokerPlayer player : players) {
player.revealTurn(card);
}
} else {
//river
Card card = deck.drawRandomCard();
sharedCards.add(card);
caster.broadcastRiver(card);
for (PokerPlayer player : players) {
player.revealRiver(card);
}
}
setNextPlayerActing();
while (running && (!areAllBetsEqual() || !allPlayersHaveActed())) {
System.out.println("Are all bets equal?: " + areAllBetsEqual());
System.out.println("Have all players acted: " + allPlayersHaveActed());
PokerPlayer actingPlayer = players[playerActing];
//correct action check
for (PokerPlayer player : betsThisRound.keySet()) {
boolean folded = false;
boolean allIn = false;
if (foldedPlayers.contains(player)) {
folded = true;
}
if (bbPerPlayer.get(player) == 0) {
allIn = true;
}
//Debug
System.out.println("Current bet of player " + player.getName() + " : " + betsThisRound.get(player) + "BB (folded: " + folded + ", all-in: " + allIn + ")");
}
caster.playerIsToAct(actingPlayer);
PokerAction action = actingPlayer.isToAct(biggestBet, bbPerPlayer.get(actingPlayer), betsThisRound.get(actingPlayer));
ActionLegalChecker checker = new ActionLegalChecker(action, actingPlayer, this);
while (!checker.isLegal()) {
actingPlayer.notifyIllegalAction(checker.getInfo());
action = actingPlayer.isToAct(biggestBet, bbPerPlayer.get(actingPlayer), betsThisRound.get(actingPlayer));
checker = new ActionLegalChecker(action, actingPlayer, this);
}
if (bettingRound == 1 && playerActing == 1 && !bigBlindActedOnPreflop) {
bigBlindActedOnPreflop = true;
}
if (playerActing + 1 == playerNumber) {
dealerActed = true;
}
executeAction(action, actingPlayer);
if (running) {
playerActing++;
setNextPlayerActing();
}
}
if (running) {
if (bettingRound == 4) {
//river setzrunde ist passiert
PokerPlayer winner = calculateWinner();
Hand winningHand = Hand.calculateHand(Hand.combineCards(sharedCards, pocketCards.get(winner)));
revealResultShowdown(winner, winningHand);
} else {
startNextBettingRound();
}
}
}
private boolean isCurrentPlayerAlive() {
if (foldedPlayers.contains(players[playerActing])) {
return false;
}
return true;
}
private boolean isCurrentPlayerAllIn() {
if (bbPerPlayer.get(players[playerActing]) == 0) {
return true;
}
return false;
}
private boolean isThereMoreThanOnePlayerActable() {
int sumFoldedAndAllInPlayers = 0;
for (PokerPlayer player : players) {
if (foldedPlayers.contains(player)) {
sumFoldedAndAllInPlayers++;
} else {
if (bbPerPlayer.get(player) == 0) {
sumFoldedAndAllInPlayers++;
}
}
}
System.out.println("There are " + sumFoldedAndAllInPlayers + " players remaining");
if (sumFoldedAndAllInPlayers > 1) {
return true;
} else {
return false;
}
}
//needs to be alive and not all in
private void setNextPlayerActing() {
//all Bets equal -> start next betting round
if (playerActing >= playerNumber) {
playerActing = playerActing % playerNumber;
}
while (!isCurrentPlayerAlive() || isCurrentPlayerAllIn()) {
playerActing++;
if (!isThereMoreThanOnePlayerActable()) {
break;
}
setNextPlayerActing();
}
}
private boolean areAllBetsEqual() {
//alle Spieler müssen einen von den drei Dingen haben
/*- bb bezahlt
* - folded
* - all in
*/
float highestBet = 0;
//For All-IN Players
for (PokerPlayer player : players) {
if (bbPerPlayer.get(player) != 0) {
continue;
}
if (betsThisRound.get(player) > highestBet) {
highestBet = betsThisRound.get(player);
}
}
for (PokerPlayer player : players) {
if (foldedPlayers.contains(player)) {
continue;
}
if (bbPerPlayer.get(player) == 0) {
continue;
}
if (highestBet == 0) {
highestBet = betsThisRound.get(player);
continue;
}
if (highestBet != betsThisRound.get(player)) {
return false;
}
}
return true;
}
private boolean allPlayersHaveActed() {
if (bettingRound == 1 && bigBlindActedOnPreflop || bettingRound != 1 && dealerActed) {
return true;
}
return false;
}
private void executeAction(PokerAction action, PokerPlayer actingPlayer) {
if (action instanceof Fold) {
foldedPlayers.add(actingPlayer);
caster.playerFolded(actingPlayer);
if (foldedPlayers.size() == playerNumber - 1) {
for (PokerPlayer player : players) {
if (!foldedPlayers.contains(player)) {
revealResultFolded(player);
running = false;
}
}
}
} else if (action instanceof Check) {
caster.playerChecked(actingPlayer);
} else if (action instanceof Bet) {
Bet bet = (Bet) action;
pot = pot + bet.getBB();
//es ist ja legal
float currentBB = bbPerPlayer.get(actingPlayer);
bbPerPlayer.put(actingPlayer, currentBB - bet.getBB());
//muss man da bei float berechnung aufpassen?
if (currentBB - bet.getBB() == 0) {
caster.playerBetAllIn(actingPlayer, bet.getBB());
} else {
caster.playerBet(actingPlayer, bet.getBB());
}
//bei Bet gibt es ja davor keine BetSum die Runde, oder?
betsThisRound.put(actingPlayer, bet.getBB());
biggestBet = bet.getBB();
} else if (action instanceof Call) {
Call call = (Call) action;
float amount = call.getBB() - betsThisRound.get(actingPlayer);
pot = pot + amount;
float currentBB = bbPerPlayer.get(actingPlayer);
bbPerPlayer.put(actingPlayer, currentBB - amount);
if (currentBB - amount == 0) {
caster.playerCalledAllIn(actingPlayer, amount);
} else {
caster.playerCalled(actingPlayer, amount);
}
//brauche ich das noch?
//float previousBetSum = betsThisRound.get(actingPlayer);
betsThisRound.put(actingPlayer, call.getBB());
} else if (action instanceof Raise) {
Raise raise = (Raise) action;
System.out.println("Raise BB: " + raise.getBB());
System.out.println("Current BB: " + bbPerPlayer.get(actingPlayer));
pot = pot + raise.getBB();
float currentBB = bbPerPlayer.get(actingPlayer);
float updatedBB = currentBB - raise.getBB();
bbPerPlayer.put(actingPlayer, currentBB - raise.getBB());
System.out.println("Updated BB: " + bbPerPlayer.get(actingPlayer));
if (updatedBB == 0) {
caster.playerRaisedAllIn(actingPlayer, raise.getBB());
} else {
caster.playerRaised(actingPlayer, raise.getBB());
}
float previousBetSum = betsThisRound.get(actingPlayer);
betsThisRound.put(actingPlayer, raise.getBB() + previousBetSum);
biggestBet = raise.getBB() + previousBetSum;
} else {
//???
}
}
private PokerPlayer calculateWinner() {
int highestStrength = 0;
PokerPlayer currentWinner = null;
int alsoWinnerStrength = 0;
ArrayList<PokerPlayer> alsoWinners = new ArrayList<>();
for (PokerPlayer player : players) {
if (foldedPlayers.contains(player)) {
continue;
}
int strength = Hand.calculateHand(Hand.combineCards(sharedCards, pocketCards.get(player))).getStrength();
//>= wirklich? Was wenn die gleich sind
if (strength > highestStrength) {
highestStrength = strength;
currentWinner = player;
alsoWinners.clear();
}
if (strength == highestStrength) {
alsoWinnerStrength = highestStrength;
}
}
if (alsoWinnerStrength == highestStrength) {
//mach ich sp<73>ter
}
return currentWinner;
}
private void revealResultShowdown(PokerPlayer winner, Hand winningHand) {
caster.revealResult_Showdown(winner, pot, winningHand);
//<2F>berlegen was mit shared pots passiert, wenn Gewinner all-in ist und nicht alles gewinnen kann
bbPerPlayer.put(winner, bbPerPlayer.get(winner) + pot);
endGame();
}
private void revealResultFolded(PokerPlayer winner) {
caster.revealResult_Folded(winner, pot);
bbPerPlayer.put(winner, bbPerPlayer.get(winner) + pot);
endGame();
}
private void endGame() {
if (rounds > 0) {
rounds--;
LinkedHashMap<PokerPlayer, Float> newbbPerPlayer = new LinkedHashMap<>();
for (PokerPlayer player : bbPerPlayer.keySet()) {
if (player.playAgain()) {
if (bbPerPlayer.get(player) >= 1) {
newbbPerPlayer.put(player, bbPerPlayer.get(player));
} else {
caster.playerHasNotEnoughBigBlinds(player);
}
} else {
caster.playerLeavesTable(player);
}
}
//schwierig wenn unten Leute wegfallen und es nochmal der gleiche Dealer ist oder es sogar zur<75>ck geht
int newdealerPosition = dealerPosition + 1;
if (newdealerPosition >= newbbPerPlayer.size()) {
newdealerPosition = newdealerPosition % newbbPerPlayer.size();
}
new PokerGame(new ConsoleBroadcaster(), rounds, newbbPerPlayer, newdealerPosition);
} else {
caster.allRoundsPlayed();
}
}
}

View File

@ -0,0 +1,30 @@
package game;
public enum Position {
DEALER("Dealer"),
SMALL_BLIND("Small Blind"),
BIG_BLIND("Big Blind"),
UNNAMED("Unnamed");
//needs to be added later
private String name;
private Position(String name) {
this.name = name;
}
public static Position getPositionByIndex(int index) {
return Position.values()[index];
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,54 @@
package input;
import java.util.Scanner;
public class InputManager {
public static void startInputReader() {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
String[] arguments = input.split(" ");
String command = arguments[0];
if (command.equalsIgnoreCase("start")) {
System.out.println("soweit so gut");
System.out.println("args length ist " + arguments.length);
if (arguments.length != 2) {
System.out.println("Syntax: /start <Number of Players>");
}
try {
Integer playerNumber = Integer.parseInt(arguments[1]);
if (playerNumber < 2 || playerNumber > 8) {
System.out.println("Only 2 to 8 Players are allowed");
}
System.out.println("Erfolg!");
} catch (NumberFormatException ex) {
System.out.println("Number of Players has to be a whole number!");
}
}
System.out.println("Unknown command!");
sc.close();
}
}

View File

@ -0,0 +1,186 @@
package player;
import java.util.ArrayList;
import java.util.Scanner;
import action.Bet;
import action.Call;
import action.Check;
import action.Fold;
import action.PokerAction;
import action.Raise;
import action.UnknownAction;
import cards.Card;
import game.Hand;
import game.Position;
public class ConsolePokerPlayer implements PokerPlayer {
private String name;
private Card firstCard;
private Card secondCard;
private ArrayList<Card> communityCards;
Scanner scanner;
public ConsolePokerPlayer(String name) {
this.name = name;
communityCards = new ArrayList<>();
scanner = new Scanner(System.in);
}
@Override
public String toString() {
return name;
}
@Override
public String getName() {
return name;
}
private void message(String message) {
System.out.println("[" + name + "]: " + message);
}
@Override
public void notifyStart(Position position, float bigBlinds) {
message("The Pokergame has started. You are in position " + position.getName() + " with " + bigBlinds + " BB.");
}
@Override
public void giveCards(Card firstCard, Card secondCard) {
message("You have been dealt the following cards: " + firstCard.toSymbol() + " " + secondCard.toSymbol());
this.firstCard = firstCard;
this.secondCard = secondCard;
}
@Override
public PokerAction isToAct(float biggestBet, float currentBB, float bbFromPreviousRounds) {
//only execute after cards are dealt
message("You are now to act! The previously highest Bet is " + biggestBet + "BB.");
message("These are your cards: " + firstCard.toSymbol() + " " + secondCard.toSymbol() + " (" + Hand.calculateHand(Hand.combineCards(communityCards, new Card[]{firstCard, secondCard})) + ")");
message("You have " + currentBB + "BB remaining.");
float bbToCall = biggestBet - bbFromPreviousRounds;
if (bbToCall == 0) {
message("You can check, bet or fold. (Folding makes no sense)");
} else {
if (currentBB <= bbToCall) {
message("You can call ALL-IN (" + currentBB + "BB) or fold.");
} else {
message("You can call (" + bbToCall + "BB), raise or fold.");
}
}
String[] arguments = scanner.nextLine().split(" ");
PokerAction action = new UnknownAction("Unknown Command");
if (arguments.length == 1) {
String command = arguments[0];
if (command.equalsIgnoreCase("fold")) {
action = new Fold();
} else if (command.equalsIgnoreCase("check")) {
action = new Check();
} else if (command.equalsIgnoreCase("call")) {
if (biggestBet > currentBB) {
//call All-IN
action = new Call(currentBB);
}
action = new Call(biggestBet);
}
} else if (arguments.length == 2) {
try {
Float bb = Float.parseFloat(arguments[1]);
String command = arguments[0];
if (command.equalsIgnoreCase("bet")) {
action = new Bet(bb);
} else if (command.equalsIgnoreCase("raise")) {
action = new Raise(bb);
}
} catch (NumberFormatException exception) {
action = new UnknownAction("Second argument has to be a number!");
}
}
return action;
}
@Override
public void notifyIllegalAction(String info) {
message("Your last Poker Action was illegal! Explanation: " + info);
}
@Override
public boolean playAgain() {
return true;
//Todo
}
@Override
public void notEnoughBigBlinds() {
message("You don't enough big blinds to continue. Sorry!");
}
@Override
public void revealFlop(ArrayList<Card> cards) {
communityCards.addAll(cards);
}
@Override
public void revealTurn(Card card) {
communityCards.add(card);
}
@Override
public void revealRiver(Card card) {
communityCards.add(card);
}
}

View File

@ -0,0 +1,23 @@
package player;
import java.util.ArrayList;
import action.PokerAction;
import cards.Card;
import game.Position;
public interface PokerPlayer {
@Override
public String toString();
public String getName();
public void notifyStart(Position position, float bigBlinds);
public void giveCards(Card firstCard, Card secondCard);
public void revealFlop(ArrayList<Card> cards);
public void revealTurn(Card card);
public void revealRiver(Card card);
public PokerAction isToAct(float biggestBet, float bb, float bbFromPreviousRounds);
public void notifyIllegalAction(String info);
public boolean playAgain();
public void notEnoughBigBlinds();
}