diff --git a/.gitignore b/.gitignore index 4707e8fb..d2115efc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.class */.vs *.suo diff --git a/01_Acey_Ducey/javascript/aceyducey.js b/01_Acey_Ducey/javascript/aceyducey.js index 8bf5e9e1..9969ebbf 100644 --- a/01_Acey_Ducey/javascript/aceyducey.js +++ b/01_Acey_Ducey/javascript/aceyducey.js @@ -90,19 +90,23 @@ async function main() { print('\nWHAT IS YOUR BET? '); bet = parseInt(await input(), 10); let minimumRequiredBet = 0; - if (bet > minimumRequiredBet) { + if (bet >= minimumRequiredBet) { if (bet > availableDollars) { print('SORRY, MY FRIEND, BUT YOU BET TOO MUCH.'); print(`YOU HAVE ONLY ${availableDollars} DOLLARS TO BET.`); } else { validBet = true; } - } else { - // Does not meet minimum required bet - print('CHICKEN!!'); - print(''); } } + if (bet == 0) + { + // User chose not to bet. + print('CHICKEN!!'); + print(''); + // Don't draw a third card, draw a new set of 2 cards. + continue; + } print('\n\nHERE IS THE CARD WE DREW: '); print(getCardValue(cardThree)); @@ -127,7 +131,7 @@ async function main() { print(''); print(''); - if (isValidYesNoString(tryAgainInput)) { + if (isValidYesString(tryAgainInput)) { availableDollars = 100; } else { print('O.K., HOPE YOU HAD FUN!'); diff --git a/12_Bombs_Away/java/src/BombsAway.java b/12_Bombs_Away/java/src/BombsAway.java index e156ea73..b084ddcb 100644 --- a/12_Bombs_Away/java/src/BombsAway.java +++ b/12_Bombs_Away/java/src/BombsAway.java @@ -4,10 +4,16 @@ import java.util.Scanner; * Game of Bombs Away * * Based on the Basic game of Bombs Away here - * https://github.com/coding-horror/basic-computer-games/blob/main/12%20Bombs%20Away/bombsaway.bas + * https://github.com/coding-horror/basic-computer-games/blob/main/12_Bombs_Away/bombsaway.bas + * + * Note: The idea was to create a version of the 1970's Basic game in Java, without adding new features. + * Obvious bugs where found have been fixed, but the playability and overlook and feel + * of the game have been faithfully reproduced. + * + * Modern Java coding conventions have been employed and JDK 11 used for maximum compatibility. + * + * Java port by https://github.com/journich * - * Note: The idea was to create a version of the 1970's Basic game in Java, without introducing - * new features - no additional text, error checking, etc has been added. */ public class BombsAway { @@ -116,8 +122,9 @@ public class BombsAway { private int missions; - private int chanceToHit; + private int chanceToBeHit; private int percentageHitRateOfGunners; + private boolean liar; public BombsAway() { @@ -139,8 +146,9 @@ public class BombsAway { // Show an introduction the first time the game is played. case START: intro(); - chanceToHit = 0; + chanceToBeHit = 0; percentageHitRateOfGunners = 0; + liar = false; gameState = GAME_STATE.CHOOSE_SIDE; break; @@ -267,7 +275,7 @@ public class BombsAway { break; case CHOOSE_ENEMY_DEFENCES: - boolean bothWeapons = true; + percentageHitRateOfGunners = 0; ENEMY_DEFENCES enemyDefences = getEnemyDefences("DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3) ? "); if(enemyDefences == null) { @@ -275,31 +283,38 @@ public class BombsAway { } else { switch(enemyDefences) { case MISSILES: - case GUNS: - bothWeapons = false; + chanceToBeHit = 35; + break; - // fall through on purpose to BOTH since its pretty much identical code other than the chance to hit - // increasing if both weapons are part of the defence. + case GUNS: + + // fall through (no break) on purpose to case BOTH + // since it's identical code for GUNS or BOTH weapons case BOTH: + chanceToBeHit = 0; percentageHitRateOfGunners = getNumberFromKeyboard("WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)? "); if(percentageHitRateOfGunners < 10) { System.out.println("YOU LIE, BUT YOU'LL PAY..."); - } - if(bothWeapons) { - chanceToHit = 35; - + liar = true; } break; } } - gameState = GAME_STATE.PROCESS_FLAK; + // If player didn't lie when entering percentage hit rate of gunners continue with game + // Otherwise shoot down the player. + if(!liar) { + gameState = GAME_STATE.PROCESS_FLAK; + } else { + gameState = GAME_STATE.SHOT_DOWN; + } + break; - // Determine if the players airplan makes it through the Flak. + // Determine if the player's airplane makes it through the Flak. case PROCESS_FLAK: double calc = (CHANCE_OF_BEING_SHOT_DOWN_BASE * randomNumber(1)); - if ((chanceToHit + percentageHitRateOfGunners) > calc) { + if ((chanceToBeHit + percentageHitRateOfGunners) > calc) { gameState = GAME_STATE.SHOT_DOWN; } else { gameState = GAME_STATE.MADE_IT_THROUGH_FLAK; @@ -462,7 +477,7 @@ public class BombsAway { /** * Check whether a string equals one of a variable number of values * Useful to check for Y or YES for example - * Comparison is case insensitive. + * Comparison is case-insensitive. * * @param text source string * @param values a range of values to compare against the source string diff --git a/12_Bombs_Away/javascript/bombsaway.js b/12_Bombs_Away/javascript/bombsaway.js index 835a2608..84831856 100644 --- a/12_Bombs_Away/javascript/bombsaway.js +++ b/12_Bombs_Away/javascript/bombsaway.js @@ -45,6 +45,8 @@ function tab(space) // Main program async function main() { + s = 0; + t = 0; while (1) { print("YOU ARE A PILOT IN A WORLD WAR II BOMBER.\n"); while (1) { diff --git a/51_Hurkle/perl/hurkle.pl b/51_Hurkle/perl/hurkle.pl new file mode 100755 index 00000000..1497e50c --- /dev/null +++ b/51_Hurkle/perl/hurkle.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +# global variables + +my($GRID) = 10; +my($TRIES) = 5; + + +# main program starts here + +# print instructions +print <); + # Use a regex to attempt to parse out + # two integers separated by a comma. + if ($in =~ m{(\d+)\s*,\s*(\d+)}) { + $G1 = $1; $G2 = $2; + last CHECK; + } + # Input not accepted, please try again + print "Please enter two numbers separated by a comma ? "; + } + + if (abs($H1 - $G1) + abs($H2 - $G2) != 0) { + + # print directional info + printf("Go %s%s\n\n", + ($G2 == $H2 ? '' : $G2 < $H2 ? 'north' : 'south'), + ($G1 == $H1 ? '' : $G1 < $H1 ? 'east' : 'west' ), + ); + } else { + # win! + printf("\nYou found him in %d tries!\n", $i); + # move to the continue block + next PLAY; + } + } # tries loop + + # No more guesses + printf("Sorry, that's %d guesses.\n", $TRIES); + printf("The Hurkle is at %d, %d\n", $H1, $H2); +} + +# Execution comes here either from the "next PLAY" +# statement, or by the PLAY block naturally ending +# after the player has lost. +continue { + print "\nLet's play again. Hurkle is hiding.\n\n"; +} 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; + } + } + +} diff --git a/72_Queen/perl/queen.pl b/72_Queen/perl/queen.pl new file mode 100644 index 00000000..62682210 --- /dev/null +++ b/72_Queen/perl/queen.pl @@ -0,0 +1,209 @@ +#!/usr/bin/env perl +use v5.24; +use warnings; +use experimental 'signatures'; +no warnings 'experimental::signatures'; + +use constant TARGET => 158; + +main(@ARGV); + +sub main (@args) { + welcome(); + help() if ask_yes_no('DO YOU WANT INSTRUCTIONS'); + do { one_match() } while ask_yes_no('ANYONE ELSE CARE TO TRY'); + __exit(); +} + +sub one_match { + print_board(); + + # the player can choose the starting position in the top row or the + # right column + my $move = ask_first_move() or return forfeit(); + + # we alternate moves between computer or player from now on + while ('playing') { + $move = computer_move($move); + say "COMPUTER MOVES TO SQUARE $move"; + return print_computer_victory() if $move == TARGET; + + $move = ask_player_move($move) or return forfeit(); + return print_player_victory() if $move == TARGET; + } +} + +sub is_valid_move ($move, $current, $skip_prevalidation = 0) { + + # pre-validation is needed for moves coming from the user + if (! $skip_prevalidation) { + state $valid_position = { map { $_ => 1 } board_identifiers() }; + return 0 unless $move =~ m{\A [1-9]\d+ \z}mxs; + return 1 if $move == 0; + return 0 unless $valid_position->{$move}; + return 0 if $move <= $current; + } + + # the move might be valid in general, let's check from $current + my $delta = $move - $current; + + # a valid move differs from the current position by a multiple of 10, + # or 11, or 21. If dividing by all of them yields a remainder, then + # the move is not valid + return 0 if $delta % 10 && $delta % 11 && $delta % 21; + + # otherwise it is + return 1; +} + +sub ask_player_move ($current) { + while ('necessary') { + my $move = ask_input('WHAT IS YOUR MOVE'); + return $move if is_valid_move($move, $current); + say "\nY O U C H E A T . . . TRY AGAIN"; + } +} + +sub computer_move ($current) { + + # this game has some optimal/safe positions from where it's possible + # to win with the right strategy. We will aim for them, if possible + state $optimals = [ 158, 127, 126, 75, 73 ]; + for my $optimal ($optimals->@*) { + + # moves can only increase, if we did not find any optimal move so far + # then there's no point going on + last if $optimal <= $current; + + # computer moves are "syntactically" valid, skip pre-validation + return $optimal if is_valid_move($optimal, $current, 'skip'); + + } + + # cannot reach an optimal position... resort to randomness + my $z = rand(); + return $current + 11 if $z > 0.6; # move down + return $current + 21 if $z > 0.3; # move diagonally + return $current + 10; ; # move horizontally +} + +sub board_identifiers { + return ( + 81, 71, 61, 51, 41, 31, 21, 11, + 92, 82, 72, 62, 52, 42, 32, 22, + 103, 93, 83, 73, 63, 53, 43, 33, + 114, 104, 94, 84, 74, 64, 54, 44, + 125, 115, 105, 95, 85, 75, 65, 55, + 136, 126, 116, 106, 96, 86, 76, 66, + 147, 137, 127, 117, 107, 97, 87, 77, + 158, 148, 138, 128, 118, 108, 98, 88, + ); +} + +sub print_player_victory { + print <<'END'; + +C O N G R A T U L A T I O N S . . . + +YOU HAVE WON--VERY WELL PLAYED. +IT LOOKS LIKE I HAVE MET MY MATCH. +THANKS FOR PLAYING---I CAN'T WIN ALL THE TIME. + +END +} + +sub print_computer_victory { + print <<'END'; + +NICE TRY, BUT IT LOOKS LIKE I HAVE WON. +THANKS FOR PLAYING. + +END +} + +sub forfeit { say "\nIT LOOKS LIKE I HAVE WON BY FORFEIT.\n" } + +sub ask_input ($prompt) { + print "$prompt? "; + defined(my $input = ) or __exit(); + + # remove spaces from the input (including newlines), they are not used + $input =~ s{\s+}{}gmxs; + + return $input; +} + +sub ask_yes_no ($prompt) { + while ('necessary') { + my $input = ask_input($prompt); + return 1 if $input =~ m{\A (?: yes | y) \z}imxs; + return 0 if $input =~ m{\A (?: no | n) \z}imxs; + say q{PLEASE ANSWER 'YES' OR 'NO'.}; + } +} + +sub ask_first_move { + while ('necessary') { + my $input = ask_input('WHERE WOULD YOU LIKE TO START'); + if ($input =~ m{\A (?: 0 | [1-9]\d+) \z}mxs) { + return 0 unless $input; + my $diagonal = int($input / 10); + my $row = $input % 10; + return $input if $row == 1 || $row == $diagonal; + } + say <<'END' +PLEASE READ THE DIRECTIONS AGAIN. +YOU HAVE BEGUN ILLEGALLY. + +END + } +} + +sub __exit { + say "\nOK --- THANKS AGAIN."; + exit 0; +} + +sub welcome { + print <<'END' + QUEEN + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + +END +} + +sub help { + print <<'END'; +WE ARE GOING TO PLAY A GAME BASED ON ONE OF THE CHESS +MOVES. OUR QUEEN WILL BE ABLE TO MOVE ONLY TO THE LEFT, +DOWN, OR DIAGONALLY DOWN AND TO THE LEFT. + +THE OBJECT OF THE GAME IS TO PLACE THE QUEEN IN THE LOWER +LEFT HAND SQUARE BY ALTERNATING MOVES BETWEEN YOU AND THE +COMPUTER. THE FIRST ONE TO PLACE THE QUEEN THERE WINS. + +YOU GO FIRST AND PLACE THE QUEEN IN ANY ONE OF THE SQUARES +ON THE TOP ROW OR RIGHT HAND COLUMN. +THAT WILL BE YOUR FIRST MOVE. +WE ALTERNATE MOVES. +YOU MAY FORFEIT BY TYPING '0' AS YOUR MOVE. +BE SURE TO PRESS THE RETURN KEY AFTER EACH RESPONSE. + + +END +} + +sub print_board { + say ''; + my @ids = board_identifiers(); + my $row_template = join ' ', ($ENV{ORIGINAL} ? '%d' : '%3d') x 8; + for my $A (0 .. 7) { + my $start = $A * 8; + my @range = $start .. $start + 7; + say ' ', sprintf $row_template, @ids[@range]; + say "\n"; + } + say ''; +} diff --git a/76_Russian_Roulette/ruby/russianroulette.rb b/76_Russian_Roulette/ruby/russianroulette.rb new file mode 100644 index 00000000..abb3ad35 --- /dev/null +++ b/76_Russian_Roulette/ruby/russianroulette.rb @@ -0,0 +1,73 @@ +puts <<~INSTRUCTIONS + RUSSIAN ROULETTE + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + +THIS IS A GAME OF >>>>>>>>>>RUSSIAN ROULETTE. + +HERE IS A REVOLVER. + +INSTRUCTIONS + +NUMBER_OF_ROUNDS = 9 + +def parse_input + correct_input = false + + while not correct_input + puts " ?" + inp = gets.chomp + if inp == "1" or inp == "2" + correct_input = true + end + end + + inp +end + +while true + + dead = false + n = 0 + + puts "TYPE \'1\' TO SPIN CHAMBER AND PULL TRIGGER" + puts "TYPE \'2\' TO GIVE UP" + puts "GO" + + while not dead + + inp = parse_input + + if inp == "2" + break + end + + if rand > 0.8333333333333334 + dead = true + else + puts "- CLICK -" + n += 1 + end + + if n > NUMBER_OF_ROUNDS + break + end + + end + + if dead + puts "BANG!!!!! You're Dead!" + puts "Condolences will be sent to your relatives.\n\n\n" + puts "...Next victim..." + else + if n > NUMBER_OF_ROUNDS + puts "You win!!!!!" + puts "Let someone else blow his brain out.\n" + else + puts " Chicken!!!!!\n\n\n" + puts "...Next victim...." + end + end + +end diff --git a/92_Trap/csharp/Program.cs b/92_Trap/csharp/Program.cs new file mode 100644 index 00000000..6cd74d10 --- /dev/null +++ b/92_Trap/csharp/Program.cs @@ -0,0 +1,119 @@ +using System; + +namespace trap_cs +{ + class Program + { + const int maxGuesses = 6; + const int maxNumber = 100; + static void Main(string[] args) + { + int lowGuess = 0; + int highGuess = 0; + + Random randomNumberGenerator = new (); + + Print("TRAP"); + Print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Print(); + Print(); + Print(); + + PrintInstructions(); + + int numberToGuess = randomNumberGenerator.Next(1, maxNumber); + + for (int nGuess = 1; nGuess <= maxGuesses + 1; nGuess++) + { + if (nGuess > maxGuesses) + { + Print(string.Format("SORRY, THAT'S {0} GUESSES. THE NUMBER WAS {1}", maxGuesses, numberToGuess)); + Print(); + break; + } + + GetGuesses(nGuess, ref lowGuess, ref highGuess); + + if(lowGuess == highGuess && lowGuess == numberToGuess) + { + Print("YOU GOT IT!!!"); + Print(); + Print("TRY AGAIN."); + Print(); + break; + } + if (highGuess < numberToGuess) + { + Print("MY NUMBER IS LARGER THAN YOUR TRAP NUMBERS."); + } + else if (lowGuess > numberToGuess) + { + Print("MY NUMBER IS SMALLER THAN YOUR TRAP NUMBERS."); + } + else + { + Print("YOU HAVE TRAPPED MY NUMBER."); + } + } + } + +// TRAP +// REM - STEVE ULLMAN, 8 - 1 - 72 + static void PrintInstructions() + { + Print("INSTRUCTIONS ?"); + + char response = Console.ReadKey().KeyChar; + if (response == 'Y') + { + Print(string.Format("I AM THINKING OF A NUMBER BETWEEN 1 AND {0}", maxNumber)); + Print("TRY TO GUESS MY NUMBER. ON EACH GUESS,"); + Print("YOU ARE TO ENTER 2 NUMBERS, TRYING TO TRAP"); + Print("MY NUMBER BETWEEN THE TWO NUMBERS. I WILL"); + Print("TELL YOU IF YOU HAVE TRAPPED MY NUMBER, IF MY"); + Print("NUMBER IS LARGER THAN YOUR TWO NUMBERS, OR IF"); + Print("MY NUMBER IS SMALLER THAN YOUR TWO NUMBERS."); + Print("IF YOU WANT TO GUESS ONE SINGLE NUMBER, TYPE"); + Print("YOUR GUESS FOR BOTH YOUR TRAP NUMBERS."); + Print(string.Format("YOU GET {0} GUESSES TO GET MY NUMBER.", maxGuesses)); + } + } + static void Print(string stringToPrint) + { + Console.WriteLine(stringToPrint); + } + static void Print() + { + Console.WriteLine(); + } + static void GetGuesses(int nGuess, ref int lowGuess, ref int highGuess) + { + Print(); + Print(string.Format("GUESS #{0}", nGuess)); + + lowGuess = GetIntFromConsole("Type low guess"); + highGuess = GetIntFromConsole("Type high guess"); + + if(lowGuess > highGuess) + { + int tempGuess = lowGuess; + + lowGuess = highGuess; + highGuess = tempGuess; + } + } + static int GetIntFromConsole(string prompt) + { + + Console.Write( prompt + " > "); + string intAsString = Console.ReadLine(); + + if(int.TryParse(intAsString, out int intValue) ==false) + { + intValue = 1; + } + + return intValue; + } + } +}