diff --git a/71_Poker/java/Poker.java b/71_Poker/java/Poker.java new file mode 100644 index 00000000..426a71fd --- /dev/null +++ b/71_Poker/java/Poker.java @@ -0,0 +1,851 @@ +import java.util.Random; +import java.util.Scanner; + +import static java.lang.System.out; + +/** + * Port of CREATIVE COMPUTING Poker written in Commodore 64 Basic to plain Java + * + * Original source scanned from magazine: https://www.atariarchives.org/basicgames/showpage.php?page=129 + * + * I based my port on the OCR'ed source code here: https://github.com/coding-horror/basic-computer-games/blob/main/71_Poker/poker.bas + * + * Why? Because I remember typing this into my C64 when I was a tiny little developer and having great fun playing it! + * + * Goal: Keep the algorithms and UX more or less as-is; Improve the control flow a bit (no goto in Java!) and rename some stuff to be easier to follow. + * + * Result: There are probably bugs, please let me know. + */ +public class Poker { + + public static void main(String[] args) { + new Poker().run(); + } + + float[] cards = new float[50]; // Index 1-5 = Human hand, index 6-10 = Computer hand + float[] B = new float[15]; + + float playerValuables = 1; + float computerMoney = 200; + float humanMoney = 200; + float pot = 0; + + String J$ = ""; + float computerHandValue = 0; + + int K = 0; + float G = 0; + float T = 0; + int M = 0; + int D = 0; + + int U = 0; + float N = 1; + + float I = 0; + + float X = 0; + + int Z = 0; + + String handDescription = ""; + + float V; + + void run() { + printWelcome(); + playRound(); + startAgain(); + } + + void printWelcome() { + tab(33); + out.println("POKER"); + tab(15); + out.print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + out.println(); + out.println(); + out.println(); + out.println("WELCOME TO THE CASINO. WE EACH HAVE $200."); + out.println("I WILL OPEN THE BETTING BEFORE THE DRAW; YOU OPEN AFTER."); + out.println("TO FOLD BET 0; TO CHECK BET .5."); + out.println("ENOUGH TALK -- LET'S GET DOWN TO BUSINESS."); + out.println(); + } + + void tab(int number) { + System.out.print("\t".repeat(number)); + } + + int random0to10() { + return new Random().nextInt(10); + } + + int removeHundreds(long x) { + return _int(x - (100F * _int(x / 100F))); + } + + void startAgain() { + pot = 0; + playRound(); + } + + void playRound() { + if (computerMoney <= 5) { + computerBroke(); + } + + out.println("THE ANTE IS $5. I WILL DEAL:"); + out.println(); + + if (humanMoney <= 5) { + playerBroke(); + } + + pot = pot + 10; + humanMoney = humanMoney - 5; + computerMoney = computerMoney - 5; + for (int Z = 1; Z < 10; Z++) { + generateCards(Z); + } + out.println("YOUR HAND:"); + N = 1; + showHand(); + N = 6; + I = 2; + + describeHand(); + + out.println(); + + if (I != 6) { + if (U >= 13) { + if (U <= 16) { + Z = 35; + } else { + Z = 2; + if (random0to10() < 1) { + Z = 35; + } + } + computerOpens(); + playerMoves(); + } else if (random0to10() >= 2) { + computerChecks(); + } else { + I = 7; + Z = 23; + computerOpens(); + playerMoves(); + } + } else if (random0to10() <= 7) { + if (random0to10() <= 7) { + if (random0to10() >= 1) { + Z = 1; + K = 0; + out.print("I CHECK. "); + playerMoves(); + } else { + X = 11111; + I = 7; + Z = 23; + computerOpens(); + playerMoves(); + } + } else { + X = 11110; + I = 7; + Z = 23; + computerOpens(); + playerMoves(); + } + } else { + X = 11100; + I = 7; + Z = 23; + computerOpens(); + playerMoves(); + } + } + + void playerMoves() { + playersTurn(); + checkWinnerAfterFirstBet(); + promptPlayerDrawCards(); + } + + void computerOpens() { + V = Z + random0to10(); + computerMoves(); + out.print("I'LL OPEN WITH $" + V); + K = _int(V); + } + + @SuppressWarnings("StatementWithEmptyBody") + void computerMoves() { + if (computerMoney - G - V >= 0) { + } else if (G != 0) { + if (computerMoney - G >= 0) { + computerSees(); + } else { + computerBroke(); + } + } else { + V = computerMoney; + } + } + + void promptPlayerDrawCards() { + out.println(); + out.println("NOW WE DRAW -- HOW MANY CARDS DO YOU WANT"); + inputPlayerDrawCards(); + } + + void inputPlayerDrawCards() { + T = Integer.parseInt(readString()); + if (T == 0) { + computerDrawing(); + } else { + Z = 10; + if (T < 4) { + playerDrawsCards(); + } else { + out.println("YOU CAN'T DRAW MORE THAN THREE CARDS."); + inputPlayerDrawCards(); + } + } + } + + // line # 980 + void computerDrawing() { + Z = _int(10 + T); + for (U = 6; U <= 10; U++) { + if (_int((float) (X / Math.pow(10F, (U - 6F)))) == (10 * (_int((float) (X / Math.pow(10, (U - 5))))))) { + drawNextCard(); + } + } + out.print("I AM TAKING " + _int(Z - 10 - T) + " CARD"); + if (Z == 11 + T) { + out.println(); + } else { + out.println("S"); + } + + N = 6; + V = I; + I = 1; + describeHand(); + startPlayerBettingAndReaction(); + } + + void drawNextCard() { + Z = Z + 1; + drawCard(); + } + + @SuppressWarnings("StatementWithEmptyBody") + void drawCard() { + cards[Z] = 100 * new Random().nextInt(4) + new Random().nextInt(100); + if (_int(cards[Z] / 100) > 3) { + drawCard(); + } else if (cards[Z] - 100 * _int(cards[Z] / 100) > 12) { + drawCard(); + } else if (Z == 1) { + } else { + for (K = 1; K <= Z - 1; K++) { + if (cards[Z] == cards[K]) { + drawCard(); + } + } + if (Z <= 10) { + } else { + N = cards[U]; + cards[U] = cards[Z]; + cards[Z] = N; + } + } + } + + void playerDrawsCards() { + out.println("WHAT ARE THEIR NUMBERS:"); + for (int Q = 1; Q <= T; Q++) { + U = Integer.parseInt(readString()); + drawNextCard(); + } + + out.println("YOUR NEW HAND:"); + N = 1; + showHand(); + computerDrawing(); + } + + void startPlayerBettingAndReaction() { + computerHandValue = U; + M = D; + + if (V != 7) { + if (I != 6) { + if (U >= 13) { + if (U >= 16) { + Z = 2; + playerBetsAndComputerReacts(); + } else { + Z = 19; + if (random0to10() == 8) { + Z = 11; + } + playerBetsAndComputerReacts(); + } + } else { + Z = 2; + if (random0to10() == 6) { + Z = 19; + } + playerBetsAndComputerReacts(); + } + } else { + Z = 1; + playerBetsAndComputerReacts(); + } + } else { + Z = 28; + playerBetsAndComputerReacts(); + } + } + + void playerBetsAndComputerReacts() { + K = 0; + playersTurn(); + if (T != .5) { + checkWinnerAfterFirstBetAndCompareHands(); + } else if (V == 7 || I != 6) { + computerOpens(); + promptAndInputPlayerBet(); + checkWinnerAfterFirstBetAndCompareHands(); + } else { + out.println("I'LL CHECK"); + compareHands(); + } + } + + void checkWinnerAfterFirstBetAndCompareHands() { + checkWinnerAfterFirstBet(); + compareHands(); + } + + void compareHands() { + out.println("NOW WE COMPARE HANDS:"); + J$ = handDescription; + out.println("MY HAND:"); + N = 6; + showHand(); + N = 1; + describeHand(); + out.print("YOU HAVE "); + K = D; + printHandDescriptionResult(); + handDescription = J$; + K = M; + out.print(" AND I HAVE "); + printHandDescriptionResult(); + out.print(". "); + if (computerHandValue > U) { + computerWins(); + } else if (U > computerHandValue) { + humanWins(); + } else if (handDescription.contains("A FLUS")) { + someoneWinsWithFlush(); + } else if (removeHundreds(M) < removeHundreds(D)) { + humanWins(); + } else if (removeHundreds(M) > removeHundreds(D)) { + computerWins(); + } else { + handIsDrawn(); + } + } + + void printHandDescriptionResult() { + out.print(handDescription); + if (!handDescription.contains("A FLUS")) { + K = removeHundreds(K); + printCardValue(); + if (handDescription.contains("SCHMAL")) { + out.print(" HIGH"); + } else if (!handDescription.contains("STRAIG")) { + out.print("'S"); + } else { + out.print(" HIGH"); + } + } else { + K = K / 100; + printCardColor(); + out.println(); + } + } + + void handIsDrawn() { + out.print("THE HAND IS DRAWN."); + out.print("ALL $" + pot + " REMAINS IN THE POT."); + playRound(); + } + + void someoneWinsWithFlush() { + if (removeHundreds(M) > removeHundreds(D)) { + computerWins(); + } else if (removeHundreds(D) > removeHundreds(M)) { + humanWins(); + } else { + handIsDrawn(); + } + } + + @SuppressWarnings("StatementWithEmptyBody") + void checkWinnerAfterFirstBet() { + if (I != 3) { + if (I != 4) { + } else { + humanWins(); + } + } else { + out.println(); + computerWins(); + } + } + + void computerWins() { + out.print(". I WIN. "); + computerMoney = computerMoney + pot; + potStatusAndNextRoundPrompt(); + } + + void potStatusAndNextRoundPrompt() { + out.println("NOW I HAVE $" + computerMoney + " AND YOU HAVE $" + humanMoney); + out.print("DO YOU WISH TO CONTINUE"); + + if (yesFromPrompt()) { + startAgain(); + } else { + System.exit(0); + } + } + + private boolean yesFromPrompt() { + String h = readString(); + if (h != null) { + if (h.toLowerCase().matches("y|yes|yep|affirmative|yay")) { + return true; + } else if (h.toLowerCase().matches("n|no|nope|fuck off|nay")) { + return false; + } + } + out.println("ANSWER YES OR NO, PLEASE."); + return yesFromPrompt(); + } + + void computerChecks() { + Z = 0; + K = 0; + out.print("I CHECK. "); + playerMoves(); + } + + void humanWins() { + out.println("YOU WIN."); + humanMoney = humanMoney + pot; + potStatusAndNextRoundPrompt(); + } + + // line # 1740 + void generateCards(int Z) { + cards[Z] = (100 * new Random().nextInt(4)) + new Random().nextInt(100); + if (_int(cards[Z] / 100) > 3) { + generateCards(Z); + return; + } + if (cards[Z] - 100 * (_int(cards[Z] / 100)) > 12) { + generateCards(Z); + return; + } + if (Z == 1) {return;} + for (int K = 1; K <= Z - 1; K++) {// TO Z-1 + if (cards[Z] == cards[K]) { + generateCards(Z); + return; + } + } + if (Z <= 10) {return;} + float N = cards[U]; + cards[U] = cards[Z]; + cards[Z] = N; + } + + // line # 1850 + void showHand() { + for (int cardNumber = _int(N); cardNumber <= N + 4; cardNumber++) { + out.print(cardNumber + "-- "); + printCardValueAtIndex(cardNumber); + out.print(" OF"); + printCardColorAtIndex(cardNumber); + if (cardNumber / 2 == (cardNumber / 2)) { + out.println(); + } + } + } + + // line # 1950 + void printCardValueAtIndex(int Z) { + K = removeHundreds(_int(cards[Z])); + printCardValue(); + } + + void printCardValue() { + if (K == 9) { + out.print("JACK"); + } else if (K == 10) { + out.print("QUEEN"); + } else if (K == 11) { + out.print("KING"); + } else if (K == 12) { + out.print("ACE"); + } else if (K < 9) { + out.print(K + 2); + } + } + + // line # 2070 + void printCardColorAtIndex(int Z) { + K = _int(cards[Z] / 100); + printCardColor(); + } + + void printCardColor() { + if (K == 0) { + out.print(" CLUBS"); + } else if (K == 1) { + out.print(" DIAMONDS"); + } else if (K == 2) { + out.print(" HEARTS"); + } else if (K == 3) { + out.print(" SPADES"); + } + } + + // line # 2170 + void describeHand() { + U = 0; + for (Z = _int(N); Z <= N + 4; Z++) { + B[Z] = removeHundreds(_int(cards[Z])); + if (Z == N + 4) {continue;} + if (_int(cards[Z] / 100) != _int(cards[Z + 1] / 100)) {continue;} + U = U + 1; + } + if (U != 4) { + for (Z = _int(N); Z <= N + 3; Z++) { + for (K = Z + 1; K <= N + 4; K++) { + if (B[Z] <= B[K]) {continue;} + X = cards[Z]; + cards[Z] = cards[K]; + B[Z] = B[K]; + cards[K] = X; + B[K] = cards[K] - 100 * _int(cards[K] / 100); + } + } + X = 0; + for (Z = _int(N); Z <= N + 3; Z++) { + if (B[Z] != B[Z + 1]) {continue;} + X = (float) (X + 11 * Math.pow(10, (Z - N))); + D = _int(cards[Z]); + + if (U >= 11) { + if (U != 11) { + if (U > 12) { + if (B[Z] != B[Z - 1]) { + fullHouse(); + } else { + U = 17; + handDescription = "FOUR "; + } + } else { + fullHouse(); + } + } else if (B[Z] != B[Z - 1]) { + handDescription = "TWO PAIR, "; + U = 12; + } else { + handDescription = "THREE "; + U = 13; + } + } else { + U = 11; + handDescription = "A PAIR OF "; + } + } + + if (X != 0) { + schmaltzHand(); + } else { + if (B[_int(N)] + 3 == B[_int(N + 3)]) { + X = 1111; + U = 10; + } + if (B[_int(N + 1)] + 3 != B[_int(N + 4)]) { + schmaltzHand(); + } else if (U != 10) { + U = 10; + X = 11110; + schmaltzHand(); + } else { + U = 14; + handDescription = "STRAIGHT"; + X = 11111; + D = _int(cards[_int(N + 4)]); + } + } + } else { + X = 11111; + D = _int(cards[_int(N)]); + handDescription = "A FLUSH IN"; + U = 15; + } + } + + void schmaltzHand() { + if (U >= 10) { + if (U != 10) { + if (U > 12) {return;} + if (removeHundreds(D) <= 6) { + I = 6; + } + } else { + if (I == 1) { + I = 6; + } + } + } else { + D = _int(cards[_int(N + 4)]); + handDescription = "SCHMALTZ, "; + U = 9; + X = 11000; + I = 6; + } + } + + void fullHouse() { + U = 16; + handDescription = "FULL HOUSE, "; + } + + void playersTurn() { + G = 0; + promptAndInputPlayerBet(); + } + + String readString() { + Scanner sc = new Scanner(System.in); + return sc.nextLine(); + } + + @SuppressWarnings("StatementWithEmptyBody") + void promptAndInputPlayerBet() { + out.println("WHAT IS YOUR BET"); + T = readFloat(); + if (T - _int(T) == 0) { + processPlayerBet(); + } else if (K != 0) { + playerBetInvalidAmount(); + } else if (G != 0) { + playerBetInvalidAmount(); + } else if (T == .5) { + } else { + playerBetInvalidAmount(); + } + } + + private float readFloat() { + try { + return Float.parseFloat(readString()); + } catch (Exception ex) { + System.out.println("INVALID INPUT, PLEASE TYPE A FLOAT. "); + return readFloat(); + } + } + + void playerBetInvalidAmount() { + out.println("NO SMALL CHANGE, PLEASE."); + promptAndInputPlayerBet(); + } + + void processPlayerBet() { + if (humanMoney - G - T >= 0) { + humanCanAffordBet(); + } else { + playerBroke(); + promptAndInputPlayerBet(); + } + } + + void humanCanAffordBet() { + if (T != 0) { + if (G + T >= K) { + processComputerMove(); + } else { + out.println("IF YOU CAN'T SEE MY BET, THEN FOLD."); + promptAndInputPlayerBet(); + } + } else { + I = 3; + moveMoneyToPot(); + } + } + + void processComputerMove() { + G = G + T; + if (G == K) { + moveMoneyToPot(); + } else if (Z != 1) { + if (G > 3 * Z) { + computerRaisesOrSees(); + } else { + computerRaises(); + } + } else if (G > 5) { + if (T <= 25) { + computerRaisesOrSees(); + } else { + computerFolds(); + } + } else { + V = 5; + if (G > 3 * Z) { + computerRaisesOrSees(); + } else { + computerRaises(); + } + } + } + + void computerRaises() { + V = G - K + random0to10(); + computerMoves(); + out.println("I'LL SEE YOU, AND RAISE YOU" + V); + K = _int(G + V); + promptAndInputPlayerBet(); + } + + void computerFolds() { + I = 4; + out.println("I FOLD."); + } + + void computerRaisesOrSees() { + if (Z == 2) { + computerRaises(); + } else { + computerSees(); + } + } + + void computerSees() { + out.println("I'LL SEE YOU."); + K = _int(G); + moveMoneyToPot(); + } + + void moveMoneyToPot() { + humanMoney = humanMoney - G; + computerMoney = computerMoney - K; + pot = pot + G + K; + } + + void computerBusted() { + out.println("I'M BUSTED. CONGRATULATIONS!"); + System.exit(0); + } + + @SuppressWarnings("StatementWithEmptyBody") + private void computerBroke() { + if ((playerValuables / 2) == _int(playerValuables / 2) && playerBuyBackWatch()) { + } else if (playerValuables / 3 == _int(playerValuables / 3) && playerBuyBackTieRack()) { + } else { + computerBusted(); + } + } + + private int _int(float v) { + return (int) Math.floor(v); + } + + private boolean playerBuyBackWatch() { + out.println("WOULD YOU LIKE TO BUY BACK YOUR WATCH FOR $50"); + if (yesFromPrompt()) { + computerMoney = computerMoney + 50; + playerValuables = playerValuables / 2; + return true; + } else { + return false; + } + } + + private boolean playerBuyBackTieRack() { + out.println("WOULD YOU LIKE TO BUY BACK YOUR TIE TACK FOR $50"); + if (yesFromPrompt()) { + computerMoney = computerMoney + 50; + playerValuables = playerValuables / 3; + return true; + } else { + return false; + } + } + + // line # 3830 + @SuppressWarnings("StatementWithEmptyBody") + void playerBroke() { + out.println("YOU CAN'T BET WITH WHAT YOU HAVEN'T GOT."); + if (playerValuables / 2 != _int(playerValuables / 2) && playerSellWatch()) { + } else if (playerValuables / 3 != _int(playerValuables / 3) && playerSellTieTack()) { + } else { + playerBusted(); + } + } + + private void playerBusted() { + out.println("YOUR WAD IS SHOT. SO LONG, SUCKER!"); + System.exit(0); + } + + private boolean playerSellWatch() { + out.println("WOULD YOU LIKE TO SELL YOUR WATCH"); + if (yesFromPrompt()) { + if (random0to10() < 7) { + out.println("I'LL GIVE YOU $75 FOR IT."); + humanMoney = humanMoney + 75; + } else { + out.println("THAT'S A PRETTY CRUMMY WATCH - I'LL GIVE YOU $25."); + humanMoney = humanMoney + 25; + } + playerValuables = playerValuables * 2; + return true; + } else { + return false; + } + } + + private boolean playerSellTieTack() { + out.println("WILL YOU PART WITH THAT DIAMOND TIE TACK"); + + if (yesFromPrompt()) { + if (random0to10() < 6) { + out.println("YOU ARE NOW $100 RICHER."); + humanMoney = humanMoney + 100; + } else { + out.println("IT'S PASTE. $25."); + humanMoney = humanMoney + 25; + } + playerValuables = playerValuables * 3; + return true; + } else { + return false; + } + } + +}