Merge branch 'coding-horror:main' into 48_High_IQ_Python

This commit is contained in:
Thomas Kwashnak
2022-01-05 11:33:43 -05:00
committed by GitHub
14 changed files with 980 additions and 78 deletions

View File

@@ -15,4 +15,5 @@ As published in Basic Computer Games (1978):
Downloaded from Vintage Basic at
http://www.vintage-basic.net/games.html
A Common Lisp port is [here](https://github.com/koalahedron/lisp-computer-games/blob/master/01%20Acey%20Ducey/common-lisp/acey-deucy.lisp).
#### External Links
- Common Lisp: https://github.com/koalahedron/lisp-computer-games/blob/master/01%20Acey%20Ducey/common-lisp/acey-deucy.lisp

View File

@@ -167,6 +167,6 @@ public class AceyDucey {
System.out.println("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING");
System.out.println("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE");
System.out.println("A VALUE BETWEEN THE FIRST TWO.");
System.out.println("IF YOU DO NOT WANT TO BET, INPUT A 0");
System.out.println("IF YOU DO NOT WANT TO BET, INPUT: 0");
}
}

View File

@@ -28,17 +28,15 @@ If you do not want to bet, input a 0. If you want to quit, input a -1.
END_INSTRUCTIONS
my @cards = (1 .. 13); # That is, Ace through King.
my @cards = ( 1 .. 13 ); # That is, Ace through King.
my $keepPlaying = 1;
GAME:
while ($keepPlaying)
{
my $playerBalance = 100; # The player starts with $100
while ($keepPlaying) {
my $playerBalance = 100; # The player starts with $100
HAND:
while (1)
{
HAND:
while (1) {
print "\nYou now have $playerBalance dollars.\n\n";
# We'll create a new array that is a shuffled version of the deck.
@@ -48,19 +46,17 @@ while ($keepPlaying)
# that those will be unique. This way we don't have to keep drawing
# if we get, say, two queens. We sort them as we pull them to make
# sure that the first card is lower than the second one.
my ($firstCard, $secondCard) = sort { $a <=> $b } @shuffledDeck[ 0 .. 1 ];
my ( $firstCard, $secondCard ) = sort { $a <=> $b } @shuffledDeck[ 0 .. 1 ];
print "I drew ", nameOfCard($firstCard), " and ", nameOfCard($secondCard), ".\n";
my $bet = getValidBet($playerBalance);
if ($bet == 0)
{
if ( $bet == 0 ) {
print "Chicken!\n\n";
next HAND;
}
if ($bet < 0)
{
if ( $bet < 0 ) {
last GAME;
}
@@ -72,19 +68,16 @@ while ($keepPlaying)
print "I drew ", nameOfCard($thirdCard), "!\n";
if (($firstCard < $thirdCard) && ($thirdCard < $secondCard))
{
if ( ( $firstCard < $thirdCard ) && ( $thirdCard < $secondCard ) ) {
print "You win!\n\n";
$playerBalance += $bet;
}
else
{
else {
print "You lose!\n\n";
$playerBalance -= $bet;
}
if ($playerBalance <= 0)
{
if ( $playerBalance <= 0 ) {
print "Sorry, buddy, you blew your wad!\n\n";
last HAND;
}
@@ -96,49 +89,43 @@ while ($keepPlaying)
print "Thanks for playing!\n";
###############
sub getValidBet
{
sub getValidBet {
my $maxBet = shift;
print "\nWhat's your bet? ";
my $input = <STDIN>;
chomp $input;
# This regular expression will validate that the player entered an integer.
# The !~ match operate *negates* the match, so if the player did NOT enter
# an integer, they'll be given an error and prompted again.
if ($input !~ /^ # Match the beginning of the string
[+-]? # Optional plus or minus...
\d+ # followed by one more more digits...
$ # and then the end of the string
/x # The x modifier ignores whitespace in this regex...
)
INPUT:
{
print "Sorry, numbers only!\n";
$input = getValidBet($maxBet);
}
print "\nWhat's your bet? ";
if ($input > $maxBet)
{
print "Sorry, my friend, you can't bet more money than you have.\n";
print "You only have $maxBet dollars to spend!\n";
$input = getValidBet($maxBet);
}
chomp( my $input = <STDIN> );
if ($input != int($input))
{
print "Sorry, you must bet in whole dollars. No change!\n";
$input = getValidBet($maxBet);
}
# This regular expression will validate that the player entered an integer.
# The !~ match operate *negates* the match, so if the player did NOT enter
# an integer, they'll be given an error and prompted again.
if (
$input !~ /^ # Match the beginning of the string
[+-]? # Optional plus or minus...
\d+ # followed by one more more digits...
$ # and then the end of the string
/x # The x modifier ignores whitespace in this regex...
)
{
print "Sorry, numbers only!\n";
redo INPUT;
}
return $input;
if ( $input > $maxBet ) {
print "Sorry, my friend, you can't bet more money than you have.\n";
print "You only have $maxBet dollars to spend!\n";
redo INPUT;
}
return $input;
}
}
# Since arrays in Perl are 0-based, we need to convert the value that we drew from
# the array to its proper position in the deck.
sub nameOfCard
{
sub nameOfCard {
my $value = shift;
# Note that the Joker isn't used in this game, but since arrays in Perl are
@@ -150,25 +137,21 @@ sub nameOfCard
return $cardlist[$value];
}
sub promptUserToKeepPlaying
{
print "Try again (Y/N)? ";
my $input = <STDIN>;
chomp $input;
sub promptUserToKeepPlaying {
YESNO:
{
print "Try again (Y/N)? ";
my $keepGoing;
if (uc($input) eq 'Y')
{
$keepGoing = 1;
}
elsif (uc($input) eq 'N')
{
$keepGoing = 0;
}
else
{
$keepGoing = promptUserToKeepPlaying();
}
chomp( my $input = uc <STDIN> );
return $keepGoing;
if ( $input eq 'Y' ) {
return 1;
}
elsif ( $input eq 'N' ) {
return 0;
}
else {
redo YESNO;
}
}
}

159
02_Amazing/perl/amazing.pl Executable file
View File

@@ -0,0 +1,159 @@
#! /usr/bin/perl
use strict;
use warnings;
# Translated from BASIC by Alex Kapranoff
use feature qw/say/;
# width and height of the maze
my ($width, $height) = input_dimensions();
# wall masks for all cells
my @walls;
# flags of previous visitation for all cells
my %is_visited;
# was the path out of the maze found?
my $path_found = 0;
# column of entry to the maze in the top line
my $entry_col = int(rand($width));
# cell coordinates for traversal
my $col = $entry_col;
my $row = 0;
$is_visited{$row, $col} = 1;
# looping until we visit every cell
while (keys %is_visited < $width * $height) {
if (my @dirs = get_possible_directions()) {
my $dir = $dirs[rand @dirs];
# modify current cell wall if needed
$walls[$row]->[$col] |= $dir->[2];
# move the position
$row += $dir->[0];
$col += $dir->[1];
# we found the exit!
if ($row == $height) {
$path_found = 1;
--$row;
if ($walls[$row]->[$col] == 1) {
($row, $col) = get_next_branch(0, 0);
}
}
else {
# modify the new cell wall if needed
$walls[$row]->[$col] |= $dir->[3];
$is_visited{$row, $col} = 1;
}
}
else {
($row, $col) = get_next_branch($row, $col);
}
}
unless ($path_found) {
$walls[-1]->[rand $width] |= 1;
}
print_maze();
sub input_dimensions {
# Print the banner and returns the dimensions as two integers > 1.
# The integers are parsed from the first line of standard input.
say ' ' x 28, 'AMAZING PROGRAM';
say ' ' x 15, 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY';
print "\n" x 4;
my ($w, $h) = (0, 0);
while ($w <= 1 || $h <= 1) {
print 'WHAT ARE YOUR WIDTH AND LENGTH? ';
($w, $h) = <STDIN> =~ / \d+ /xg;
if ($w < 1 || $h < 1) {
say "MEANINGLESS DIMENSIONS. TRY AGAIN."
}
}
print "\n" x 4;
return ($w, $h);
}
sub get_possible_directions {
# Returns a list of all directions that are available to go to
# from the current coordinates. "Down" is available on the last line
# until we go there once and mark it as the path through the maze.
#
# Each returned direction element contains changes to the coordindates and to
# the wall masks of the previous and next cell after the move.
my @rv;
# up
if ($row > 0 && !$is_visited{$row - 1, $col}) {
push @rv, [-1, 0, 0, 1];
}
# left
if ($col > 0 && !$is_visited{$row, $col - 1}) {
push @rv, [0, -1, 0, 2];
}
# right
if ($col < $width - 1 && !$is_visited{$row, $col + 1}) {
push @rv, [0, 1, 2, 0];
}
# down
if ($row < $height - 1 && !$is_visited{$row + 1, $col}
|| $row == $height - 1 && !$path_found
) {
push @rv, [1, 0, 1, 0];
}
return @rv;
}
sub get_next_branch {
# Returns the cell coordinates to start a new maze branch from.
# It looks for a visited cell starting from passed position and
# going down in the natural traversal order incrementing column and
# rows with a rollover to start at the bottom right corner.
my ($y, $x) = @_;
do {
if ($x < $width - 1) {
++$x;
} elsif ($y < $height - 1) {
($y, $x) = ($y + 1, 0);
} else {
($y, $x) = (0, 0);
}
} while (!$is_visited{$y, $x});
return ($y, $x);
}
sub print_maze {
# Print the full maze based on wall masks.
# For each cell, we mark the absense of the wall to the right with
# bit 2 and the absense of the wall down with bit 1. Full table:
# 0 -> both walls are present
# 1 -> wall down is absent
# 2 -> wall to the right is absent
# 3 -> both walls are absent
say join('.', '', map { $_ == $entry_col ? ' ' : '--' } 0 .. $width - 1), '.';
for my $row (@walls) {
say join(' ', map { $_ & 2 ? ' ' : 'I' } 0, @$row);
say join(':', '', map { $_ & 1 ? ' ' : '--' } @$row), '.';
}
return;
}

View File

@@ -13,4 +13,5 @@ As published in Basic Computer Games (1978):
Downloaded from Vintage Basic at
http://www.vintage-basic.net/games.html
[Conversion to C](https://github.com/ericfischer/basic-computer-games/blob/main/24%20Chemist/c/chemist.c)
#### External Links
- C: https://github.com/ericfischer/basic-computer-games/blob/main/24%20Chemist/c/chemist.c

View File

@@ -21,6 +21,6 @@ As published in Basic Computer Games (1978):
Downloaded from Vintage Basic at
http://www.vintage-basic.net/games.html
[Port to C language](https://github.com/beyonddream/hamurabi)
[Port to Rust language](https://github.com/beyonddream/hamurabi.rs)
#### External Links
- C: https://github.com/beyonddream/hamurabi
- Rust: https://github.com/beyonddream/hamurabi.rs

223
44_Hangman/perl/hangman.pl Executable file
View File

@@ -0,0 +1,223 @@
#!/usr/bin/perl
use strict;
use warnings;
# global variables defined here
my(@WORDS) = qw(
GUM SIN FOR CRY LUG BYE FLY
UGLY EACH FROM WORK TALK WITH SELF
PIZZA THING FEIGN FIEND ELBOW FAULT DIRTY
BUDGET SPIRIT QUAINT MAIDEN ESCORT PICKAX
EXAMPLE TENSION QUININE KIDNEY REPLICA SLEEPER
TRIANGLE KANGAROO MAHOGANY SERGEANT SEQUENCE
MOUSTACHE DANGEROUS SCIENTIST DIFFERENT QUIESCENT
MAGISTRATE ERRONEOUSLY LOUDSPEAKER PHYTOTOXIC
MATRIMONIAL PARASYMPATHOMIMETIC THIGMOTROPISM
);
my(@PIC,$board,@guessedLetters,$guessCount,$hangCount);
my(%GUESSED);
# Subroutines defined here.
# init_variables: initialize all of the variables needed
# (this covers lines 50-90 in the original BASIC program)
sub init_variables {
@guessedLetters = ();
@PIC = (
'XXXXXXX ',
'X X ',
'X ',
'X ',
'X ',
'X ',
'X ',
'X ',
'X ',
'X ',
'X ',
'X ',
);
$guessCount = 0; %GUESSED = ();
$hangCount = 0;
}
# addchar: given a row & column, put the specified char in that place in @PIC
sub addchar {
my($row,$col, $c) = @_;
substr($PIC[$row],$col,1) = $c;
}
# main code starts here
print ' 'x31; print "Hangman\n";
print ' 'x14; print "Creative Computing Morristown, New Jersey\n\n\n\n";
# an iteration of the PLAY block is one complete game.
# There is a continue block that will ask if the user
# wants to play another game.
PLAY: while (1) {
init_variables();
# Any words left?
if (@WORDS == 0) {
print "You did all the words!\n";
last PLAY;
}
# splice a random word out of the @WORDS array
my($thisWord) = splice(@WORDS, int(rand(scalar @WORDS)),1);
# $board is the "game board" of the filled-out word
# that the user is working on
$board = '.'x(length $thisWord);
# GUESS loop is run for every time the user guesses a letter
GUESS: while(1) {
print "Here are the letters you used:\n";
printf("%s\n", join(',',@guessedLetters));
printf("\n\n%s\n", $board);
print "What is your guess for a letter ? ";
chomp(my $guess = <STDIN>);
# The %GUESSED hash allows us to quickly identify
# letters that have already been guessed
if ($GUESSED{lc $guess}) {
print "You guessed that letter before!\n\n";
redo GUESS;
}
# save the guessed letter
push @guessedLetters, $guess;
$GUESSED{lc $guess} = 1;
++$guessCount;
# now look for the letter in the $thisWord var
# and put it into the $board var wherever it
# shows up. $foundLetter is a flag that indicates
# whether or not the letter is found.
my $foundLetter = 0;
for (my $i = 0; $i < length $thisWord; ++$i) {
if (lc substr($thisWord,$i,1) eq lc $guess) {
$foundLetter = 1;
substr($board, $i, 1) = substr($thisWord, $i, 1);
}
}
# The user found a letter in the solution!
if ($foundLetter) {
# Are there any '.' chars left in the board?
if (index($board, '.') < 0) {
print "You found the word!\n\n";
} else {
printf("%s\n\n", $board);
print "What is your guess for the word ? ";
chomp(my $guessword = <STDIN>);
if (lc $thisWord ne lc $guessword) {
print "Wrong. Try another letter.\n";
# Go to the next iteration of the GUESS loop
next GUESS;
}
printf("Right! It took you %d %s!\n", $guessCount, ($guessCount == 1 ? 'guess' : 'guesses'));
}
# At this point the user has discovered the word and won.
# This "next" statement takes execution down to the
# continue block for the PLAY loop;
next PLAY;
} else { # didn't find a letter
++$hangCount;
print "\n\n\nSorry, that letter isn't in the word.\n";
# The addchar() calls in the block below piece together the
# hangman graphic, depending on how many wrong letters
# the user has.
if ($hangCount == 1) {
print "First, we draw a head\n";
addchar(2,5,"-");addchar(2,6,"-");addchar(2,7,"-");
addchar(3,4,"("); addchar(3,5,"."); addchar(3,7,"."); addchar(3,8,")");
addchar(4,5,"-");addchar(4,6,"-");addchar(4,7,"-");
}
if ($hangCount == 2) {
print "Now we draw a body.\n";
for (5 .. 8) {
addchar($_, 6, "X");
}
}
if ($hangCount == 3) {
print "Next we draw an arm.\n";
for (3 .. 6) {
addchar($_, $_-1, "\\");
}
}
if ($hangCount == 4) {
print "This time it's the other arm.\n";
addchar(3,10, "/");
addchar(4, 9, "/");
addchar(5, 8, "/");
addchar(6, 7, "/");
}
if ($hangCount == 5) {
print "Now, let's draw the right leg.\n";
addchar( 9,5, "/");
addchar(10,4, "/");
}
if ($hangCount == 6) {
print "This time we draw the left leg.\n";
addchar(9,7,"\\");
addchar(10,8,"\\");
}
if ($hangCount == 7) {
print "Now we put up a hand.\n";
addchar(2,10,"\\");
}
if ($hangCount == 8) {
print "Next the other hand.\n";
addchar(2,2,"/");
}
if ($hangCount == 9) {
print "Now we draw one foot\n";
addchar(11,9,"\\");
addchar(11,10, "-");
}
if ($hangCount == 10) {
print "Here's the other foot -- you're hung!!\n";
addchar(11,2,"-");
addchar(11,3, "/");
}
printf("$_\n") for @PIC;
print "\n\n";
# Next guess if the user has not lost
if ($hangCount < 10) {
next GUESS;
}
printf("Sorry, you lose. The word was %s\n", $thisWord);
next PLAY;
} # didn't find a letter block
} # GUESS block
} # PLAY block
# This block is reached either by the player winning (see the "next PLAY")
# statement) or by the user losing (as the PLAY block is complete and
# execution naturally comes to this continue block).
continue {
print "Want another word ? ";
chomp(my $in = <STDIN>);
if ($in !~ m/^y/i) {
# Exit the PLAY loop
print "\nIt's been fun! Bye for now.\n\n";
last PLAY;
}
# At this point execution goes to the start of the PLAY block,
# meaning a new game
}

View File

@@ -1,3 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Oracle Java](https://openjdk.java.net/)
Conversion to [Java](https://openjdk.java.net/)

View File

@@ -0,0 +1,348 @@
import java.util.*;
/**
* SPLAT simulates a parachute jump in which you try to open your parachute at the last possible moment without going
* splat! You may select your own terminal velocity or let the computer do it for you. You many also select the
* acceleration due to gravity or, again, let the computer do it in which case you might wind up on any of eight
* planets (out to Neptune), the moon, or the sun.
* <p>
* The computer then tells you the height youre jumping from and asks for the seconds of free fall. It then divides
* your free fall time into eight intervals and gives you progress reports on your way down. The computer also keeps
* track of all prior jumps in the array A and lets you know how you compared with previous successful jumps. If you
* want to recall information from previous runs, then you should store array A in a disk or take file and read it
* before each run.
* <p>
* John Yegge created this program while at the Oak Ridge Associated Universities.
* <p>
* Ported from BASIC by jason plumb (@breedx2)
* </p>
*/
public class Splat {
private static final Random random = new Random();
private final Scanner scanner = new Scanner(System.in);
private final List<Float> pastSuccessfulJumpDistances = new ArrayList<>();
public static void main(String[] args) {
new Splat().run();
}
public void run() {
showIntroduction();
while (true) {
InitialJumpConditions initial = buildInitialConditions();
System.out.println();
System.out.printf(" ALTITUDE = %d FT\n", initial.getAltitude());
System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", initial.getOriginalTerminalVelocity());
System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", initial.getOriginalAcceleration());
System.out.println("SET THE TIMER FOR YOUR FREEFALL.");
System.out.print("HOW MANY SECONDS ");
float freefallTime = scanner.nextFloat();
System.out.println("HERE WE GO.\n");
System.out.println("TIME (SEC) DIST TO FALL (FT)");
System.out.println("========== =================");
JumpResult jump = executeJump(initial, freefallTime);
showJumpResults(initial, jump);
if (!playAgain()) {
System.out.println("SSSSSSSSSS.");
return;
}
}
}
private void showIntroduction() {
System.out.printf("%33s%s\n", " ", "SPLAT");
System.out.printf("%15s%s\n", " ", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
System.out.print("\n\n\n");
System.out.println("WELCOME TO 'SPLAT' -- THE GAME THAT SIMULATES A PARACHUTE");
System.out.println("JUMP. TRY TO OPEN YOUR CHUTE AT THE LAST POSSIBLE");
System.out.println("MOMENT WITHOUT GOING SPLAT.");
}
private InitialJumpConditions buildInitialConditions() {
System.out.print("\n\n");
float terminalVelocity = promptTerminalVelocity();
float acceleration = promptGravitationalAcceleration();
return InitialJumpConditions.create(terminalVelocity, acceleration);
}
private float promptTerminalVelocity() {
if (askYesNo("SELECT YOUR OWN TERMINAL VELOCITY")) {
System.out.print("WHAT TERMINAL VELOCITY (MI/HR) ");
return mphToFeetPerSec(scanner.nextFloat());
}
float terminalVelocity = (int) (1000 * random.nextFloat());
System.out.printf("OK. TERMINAL VELOCITY = %.2f MI/HR\n", terminalVelocity);
return mphToFeetPerSec(terminalVelocity);
}
private float promptGravitationalAcceleration() {
if (askYesNo("WANT TO SELECT ACCELERATION DUE TO GRAVITY")) {
System.out.print("WHAT ACCELERATION (FT/SEC/SEC) ");
return scanner.nextFloat();
}
return chooseRandomAcceleration();
}
private JumpResult executeJump(InitialJumpConditions initial, float chuteOpenTime) {
JumpResult jump = new JumpResult(initial.getAltitude());
for (float time = 0.0f; time < chuteOpenTime; time += chuteOpenTime / 8) {
if (!jump.hasReachedTerminalVelocity() && time > initial.getTimeOfTerminalAccelerationReached()) {
jump.setReachedTerminalVelocity();
System.out.printf("TERMINAL VELOCITY REACHED AT T PLUS %f SECONDS.\n", initial.getTimeOfTerminalAccelerationReached());
}
float newDistance = computeDistance(initial, time, jump.hasReachedTerminalVelocity());
jump.setDistance(newDistance);
if (jump.isSplat()) {
return jump;
}
System.out.printf("%10.2f %f\n", time, jump.getDistance());
}
return jump;
}
private float computeDistance(InitialJumpConditions initial, float i, boolean hasReachedTerminalVelocity) {
final float V = initial.getTerminalVelocity();
final float A = initial.getAcceleration();
if (hasReachedTerminalVelocity) {
return initial.getAltitude() - ((V * V / (2 * A)) + (V * (i - (V / A))));
}
return initial.getAltitude() - ((A / 2) * i * i);
}
private void showJumpResults(InitialJumpConditions initial, JumpResult jump) {
if (jump.isSplat()) {
showSplatMessage(initial, jump);
showCleverSplatMessage();
return;
}
System.out.println("CHUTE OPEN");
int worseJumpCount = countWorseHistoricalJumps(jump);
int successfulJumpCt = pastSuccessfulJumpDistances.size();
pastSuccessfulJumpDistances.add(jump.getDistance());
if (pastSuccessfulJumpDistances.size() <= 2) {
List<String> ordinals = Arrays.asList("1ST", "2ND", "3RD");
System.out.printf("AMAZING!!! NOT BAD FOR YOUR %s SUCCESSFUL JUMP!!!\n", ordinals.get(successfulJumpCt));
return;
}
int betterThanCount = successfulJumpCt - worseJumpCount;
if (betterThanCount <= 0.1 * successfulJumpCt) {
System.out.printf("WOW! THAT'S SOME JUMPING. OF THE %d SUCCESSFUL JUMPS\n", successfulJumpCt);
System.out.printf("BEFORE YOURS, ONLY %d OPENED THEIR CHUTES LOWER THAN\n", betterThanCount);
System.out.println("YOU DID.");
} else if (betterThanCount <= 0.25 * successfulJumpCt) {
System.out.printf("PRETTY GOOD! %d SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n", successfulJumpCt);
System.out.printf("%d OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n", betterThanCount);
System.out.println("OPENED.");
} else if (betterThanCount <= 0.5 * successfulJumpCt) {
System.out.printf("NOT BAD. THERE HAVE BEEN %d SUCCESSFUL JUMPS BEFORE YOURS.\n", successfulJumpCt);
System.out.printf("YOU WERE BEATEN OUT BY %d OF THEM.\n", betterThanCount);
} else if (betterThanCount <= 0.75 * successfulJumpCt) {
System.out.printf("CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY %d IN THE\n", betterThanCount);
System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.\n", successfulJumpCt);
} else if (betterThanCount <= -0.9 * successfulJumpCt) {
System.out.println("HUMPH! DON'T YOU HAVE ANY SPORTING BLOOD? THERE WERE");
System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS AND YOU CAME IN %d JUMPS\n", successfulJumpCt, worseJumpCount);
System.out.println("BETTER THAN THE WORST. SHAPE UP!!!\n");
} else {
System.out.printf("HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. %d SUCCESSFUL\n", successfulJumpCt);
System.out.printf("JUMPS BEFORE YOURS AND YOU CAME IN NUMBER %d! GET WITH IT!\n", betterThanCount);
}
}
private void showSplatMessage(InitialJumpConditions initial, JumpResult jump) {
double timeOfSplat = computeTimeOfSplat(initial, jump);
System.out.printf("%10.2f SPLAT\n", timeOfSplat);
}
/**
* Returns the number of jumps for which this jump was better
*/
private double computeTimeOfSplat(InitialJumpConditions initial, JumpResult jump) {
final float V = initial.getTerminalVelocity();
final float A = initial.getAcceleration();
if (jump.hasReachedTerminalVelocity()) {
return (V / A) + ((initial.getAltitude() - (V * V / (2 * A))) / V);
}
return Math.sqrt(2 * initial.getAltitude() / A);
}
private int countWorseHistoricalJumps(JumpResult jump) {
return (int) pastSuccessfulJumpDistances.stream()
.filter(distance -> jump.getDistance() < distance)
.count();
}
private void showCleverSplatMessage() {
List<String> messages = Arrays.asList(
"REQUIESCAT IN PACE.",
"MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE.",
"REST IN PEACE.",
"SON-OF-A-GUN.",
"#$%&&%!$",
"A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT.",
"HMMM. SHOULD HAVE PICKED A SHORTER TIME.",
"MUTTER. MUTTER. MUTTER.",
"PUSHING UP DAISIES.",
"EASY COME, EASY GO."
);
System.out.println(messages.get(random.nextInt(10)));
}
private boolean playAgain() {
if (askYesNo("DO YOU WANT TO PLAY AGAIN ")) {
return true;
}
return askYesNo("PLEASE");
}
private float mphToFeetPerSec(float speed) {
return speed * (5280.0f / 3600.0f);
}
private boolean askYesNo(String prompt) {
System.out.printf("%s (YES OR NO) ", prompt);
while (true) {
String answer = scanner.next();
switch (answer) {
case "YES":
return true;
case "NO":
return false;
default:
System.out.print("YES OR NO ");
}
}
}
private float chooseRandomAcceleration() {
Planet planet = Planet.pickRandom();
System.out.printf("%s %s. ACCELERATION=%.2f FT/SEC/SEC.\n", planet.getMessage(), planet.name(), planet.getAcceleration());
return planet.getAcceleration();
}
enum Planet {
MERCURY("FINE. YOU'RE ON", 12.2f),
VENUS("ALL RIGHT. YOU'RE ON", 28.3f),
EARTH("THEN YOU'RE ON", 32.16f),
MOON("FINE. YOU'RE ON THE", 5.15f),
MARS("ALL RIGHT. YOU'RE ON", 12.5f),
JUPITER("THEN YOU'RE ON", 85.2f),
SATURN("FINE. YOU'RE ON", 37.6f),
URANUS("ALL RIGHT. YOU'RE ON", 33.8f),
NEPTUNE("THEN YOU'RE ON", 39.6f),
SUN("FINE. YOU'RE ON THE", 896.0f);
private static final Random random = new Random();
private final String message;
private final float acceleration;
Planet(String message, float acceleration) {
this.message = message;
this.acceleration = acceleration;
}
static Planet pickRandom() {
return values()[random.nextInt(Planet.values().length)];
}
String getMessage() {
return message;
}
float getAcceleration() {
return acceleration;
}
}
// Mutable
static class JumpResult {
private boolean reachedTerminalVelocity = false;
private float distance; // from the ground
public JumpResult(float distance) {
this.distance = distance;
}
boolean isSplat() {
return distance <= 0;
}
boolean hasReachedTerminalVelocity() {
return reachedTerminalVelocity;
}
float getDistance() {
return distance;
}
void setDistance(float distance) {
this.distance = distance;
}
void setReachedTerminalVelocity() {
reachedTerminalVelocity = true;
}
}
// Immutable
static class InitialJumpConditions {
private final float originalTerminalVelocity;
private final float originalAcceleration;
private final float terminalVelocity;
private final float acceleration;
private final int altitude;
private InitialJumpConditions(float originalTerminalVelocity, float originalAcceleration,
float terminalVelocity, float acceleration, int altitude) {
this.originalTerminalVelocity = originalTerminalVelocity;
this.originalAcceleration = originalAcceleration;
this.terminalVelocity = terminalVelocity;
this.acceleration = acceleration;
this.altitude = altitude;
}
// Create initial jump conditions with adjusted velocity/acceleration and a random initial altitude
private static InitialJumpConditions create(float terminalVelocity, float gravitationalAcceleration) {
final int altitude = (int) (9001.0f * random.nextFloat() + 1000);
return new InitialJumpConditions(terminalVelocity, gravitationalAcceleration,
plusMinus5Percent(terminalVelocity), plusMinus5Percent(gravitationalAcceleration), altitude);
}
private static float plusMinus5Percent(float value) {
return value + ((value * random.nextFloat()) / 20.0f) - ((value * random.nextFloat()) / 20.0f);
}
float getOriginalTerminalVelocity() {
return originalTerminalVelocity;
}
float getOriginalAcceleration() {
return originalAcceleration;
}
float getTerminalVelocity() {
return terminalVelocity;
}
float getAcceleration() {
return acceleration;
}
int getAltitude() {
return altitude;
}
float getTimeOfTerminalAccelerationReached() {
return terminalVelocity / acceleration;
}
}
}

View File

@@ -101,4 +101,4 @@ Instructions in this directory at
instructions.txt
#### External Links
- Super Star Trek in C++ : https://www.codeproject.com/Articles/28399/The-Object-Oriented-Text-Star-Trek-Game-in-C
- C++: https://www.codeproject.com/Articles/28399/The-Object-Oriented-Text-Star-Trek-Game-in-C

2
96_Word/d/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.exe
*.obj

15
96_Word/d/README.md Normal file
View File

@@ -0,0 +1,15 @@
Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html)
Converted to [D](https://dlang.org/) by [Bastiaan Veelo](https://github.com/veelo).
The Basic original required words to be exactly five letters in length for the program to behave correctly.
This version does not replicate that limitation, and the test for that requirement is commented out.
## Running the code
Assuming the reference [dmd](https://dlang.org/download.html#dmd) compiler:
```shell
dmd -dip1000 -run word.d
```
[Other compilers](https://dlang.org/download.html) also exist.

85
96_Word/d/word.d Normal file
View File

@@ -0,0 +1,85 @@
@safe: // Make @safe the default for this file, enforcing memory-safety.
import std;
void main()
{
enum width = 80;
writeln(center("Word", width));
writeln(center("(After Creative Computing Morristown, New Jersey)\n\n\n", width));
writeln(wrap("I am thinking of a word -- you guess it. I will give you " ~
"clues to help you get it. Good luck!!\n\n", width));
string[] words = ["dinky", "smoke", "water", "grass", "train", "might", "first",
"candy", "champ", "would", "clump", "dopey"];
playLoop: while (true)
{
writeln("\n\nYou are starting a new game...");
string word = words[uniform(0, $-1)]; // $ is a short-hand for words.length.
int guesses = 0;
string knownLetters = '-'.repeat(word.length).array;
while (true)
{
writeln("Guess a ", word.length, " letter word");
string guess = readString.toLower;
if (guess == "?")
{
writeln("The secret word is ", word, "\n");
continue playLoop; // Start a new game.
}
/* Uncomment this for equivalence with Basic.
if (guess.length != 5)
{
writeln("You must guess a 5 letter word. Start again.");
continue; // Ask for new guess.
}
*/
guesses++;
if (guess == word)
break; // Done guessing
string commonLetters;
foreach (i, wordLetter; word)
foreach (j, guessLetter; guess)
if (guessLetter == wordLetter)
{
commonLetters ~= guessLetter;
if (i == j)
knownLetters.replaceInPlace(i, i + 1, [guessLetter]);
}
writeln("There were ", commonLetters.length, " matches and the common letters were... ", commonLetters);
writeln("From the exact letter matches, you know................ ", knownLetters);
if (knownLetters == word)
break; // Done guessing
if (commonLetters.length < 2)
writeln("If you give up, type '?' for your next guess.");
writeln;
}
writeln("You have guessed the word. It took ", guesses, " guesses!");
write("\n\nWant to play again? ");
if (readString.toLower != "yes")
break; // Terminate playLoop
}
}
/// Read a string from standard input, stripping newline and other enclosing whitespace.
string readString() nothrow
{
try
return trustedReadln.strip;
catch (Exception) // readln throws on I/O and Unicode errors, which we handle here.
return "";
}
/** An @trusted wrapper around readln.
*
* This is the only function that formally requires manual review for memory-safety.
* [Arguably readln should be safe already](https://forum.dlang.org/post/rab398$1up$1@digitalmars.com)
* which would remove the need to have any @trusted code in this program.
*/
string trustedReadln() @trusted
{
return readln;
}

85
HOW_TO_RUN_THE_GAMES.md Normal file
View File

@@ -0,0 +1,85 @@
# How to run the games
The games in this repository have been translated into a number of different languages. How to run them depends on the target language.
## csharp
### dotnet command-line
The best cross-platform method for running the csharp examples is with the `dotnet` command-line tool. This can be downloaded for **MacOS**, **Windows** and **Linux** from [dotnet.microsoft.com](https://dotnet.microsoft.com/).
From there, the program can be run by
1. Opening a terminal window
1. Navigating to the corresponding directory
1. Starting with `dotnet run`
### Visual Studio
Alternatively, for non-dotnet compatible translations, you will need [Visual Studio](https://visualstudio.microsoft.com/vs/community/) which can be used to both open the project and run the example.
1. Open the corresponding `.csproj` or `.sln` file
1. Click `Run` from within the Visual Studio IDE
## java
The Java translations can be run via the command line or from an IDE such as [Eclipse](https://www.eclipse.org/downloads/packages/release/kepler/sr1/eclipse-ide-java-developers) or [IntelliJ](https://www.jetbrains.com/idea/)
To run from the command line, you will need a Java SDK (eg. [Oracle JDK](https://www.oracle.com/java/technologies/downloads/) or [Open JDK](https://openjdk.java.net/)).
1. Navigate to the corresponding directory.
1. Compile the program with `javac`:
* eg. `javac AceyDuceyGame.java`
1. Run the compiled program with `java`:
* eg. `java AceyDuceyGame`
## javascript
The javascript examples can be run from within your web browser:
1. Simply open the corresponding `.html` file from your web browser.
## pascal
The pascal examples can be run using [Free Pascal](https://www.freepascal.org/). Additionally, `.lsi` project files can be opened with the [Lazarus Project IDE](https://www.lazarus-ide.org/).
The pascal examples include both *simple* (single-file) and *object-oriented* (in the `/object-pascal`directories) examples.
1. You can compile the program from the command line with the `fpc` command.
* eg. `fpc amazing.pas`
1. The output is an executable file that can be run directly.
## perl
The perl translations can be run using a perl interpreter (a copy can be downloaded from [perl.org](https://www.perl.org/)) if not already installed.
1. From the command-line, navigate to the corresponding directory.
1. Invoke with the `perl` command.
* eg. `perl aceyducey.pl`
## python
The python translations can be run from the command line by using the `py` interpreter. If not already installed, a copy can be downloaded from [python.org](https://www.python.org/downloads/) for **Windows**, **MacOS** and **Linux**.
1. From the command-line, navigate to the corresponding directory.
1. Invoke with the `py` or `python` interpreter (depending on your python version).
* eg. `py acey_ducey_oo.py`
* eg. `python aceyducey.py`
**Note**
Some translations include multiple versions for python, such as `acey ducey` which features versions for Python 2 (`aceyducey.py`) and Python 3 (`acey_ducey.py`) as well as an extra object-oriented version (`acey_ducey_oo.py`).
You can manage and use different versions of python with [pip](https://pypi.org/project/pip/).
## ruby
If you don't already have a ruby interpreter, you can download it from the [ruby project site](https://www.ruby-lang.org/en/).
1. From the command-line, navigate to the corresponding directory.
1. Invoke with the `ruby` tool.
* eg. `ruby aceyducey.rb`
## vbnet
Follow the same steps as for the [csharp](#csharp) translations. This can be run with `dotnet` or `Visual Studio`.