From 89eb74fa3cf097e3379a3643ccbd7110f6a207c2 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 20 Feb 2021 16:09:01 +1100 Subject: [PATCH 001/749] Create console project --- .gitignore | 3 ++ 84 Super Star Trek/csharp/Program.cs | 12 +++++++ .../csharp/SuperStarTrek.csproj | 8 +++++ 84 Super Star Trek/csharp/SuperStarTrek.sln | 34 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 84 Super Star Trek/csharp/Program.cs create mode 100644 84 Super Star Trek/csharp/SuperStarTrek.csproj create mode 100644 84 Super Star Trek/csharp/SuperStarTrek.sln diff --git a/.gitignore b/.gitignore index 53e00acd..42752d61 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ /01 Acey Ducey/csharp/bin/Debug/netcoreapp3.1 /33 Dice/csharp/bin/Debug/net5.0 /basic-computer-games-dot-net/.vs/basic-computer-games-dot-net/v16 + +*/csharp/bin +*/csharp/obj diff --git a/84 Super Star Trek/csharp/Program.cs b/84 Super Star Trek/csharp/Program.cs new file mode 100644 index 00000000..d88fa19e --- /dev/null +++ b/84 Super Star Trek/csharp/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace SuperStarTrek +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/84 Super Star Trek/csharp/SuperStarTrek.csproj b/84 Super Star Trek/csharp/SuperStarTrek.csproj new file mode 100644 index 00000000..c73e0d16 --- /dev/null +++ b/84 Super Star Trek/csharp/SuperStarTrek.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/84 Super Star Trek/csharp/SuperStarTrek.sln b/84 Super Star Trek/csharp/SuperStarTrek.sln new file mode 100644 index 00000000..7a17477a --- /dev/null +++ b/84 Super Star Trek/csharp/SuperStarTrek.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperStarTrek", "SuperStarTrek.csproj", "{ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Debug|x64.ActiveCfg = Debug|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Debug|x64.Build.0 = Debug|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Debug|x86.ActiveCfg = Debug|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Debug|x86.Build.0 = Debug|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Release|Any CPU.Build.0 = Release|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Release|x64.ActiveCfg = Release|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Release|x64.Build.0 = Release|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Release|x86.ActiveCfg = Release|Any CPU + {ACB0A7F5-A4DC-4A2F-8D3D-104E83A0417F}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal From 1f08470006a164c5f8e9bf94df41baa1ffae6a62 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 20 Feb 2021 23:41:05 +1100 Subject: [PATCH 002/749] Add string resources --- .../csharp/Resources/Enterprise.txt | 24 ++++ .../csharp/Resources/Instructions.txt | 105 ++++++++++++++++++ 84 Super Star Trek/csharp/Resources/Title.txt | 27 +++++ 84 Super Star Trek/csharp/Strings.cs | 26 +++++ .../csharp/SuperStarTrek.csproj | 6 +- 5 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 84 Super Star Trek/csharp/Resources/Enterprise.txt create mode 100644 84 Super Star Trek/csharp/Resources/Instructions.txt create mode 100644 84 Super Star Trek/csharp/Resources/Title.txt create mode 100644 84 Super Star Trek/csharp/Strings.cs diff --git a/84 Super Star Trek/csharp/Resources/Enterprise.txt b/84 Super Star Trek/csharp/Resources/Enterprise.txt new file mode 100644 index 00000000..4310ca91 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Enterprise.txt @@ -0,0 +1,24 @@ + + + + + + + + + + + + ,------*------, + ,------------- '--- ------' + '-------- --' / / + ,---' '-------/ /--, + '----------------' + + THE USS ENTERPRISE --- NCC-1701 + + + + + + diff --git a/84 Super Star Trek/csharp/Resources/Instructions.txt b/84 Super Star Trek/csharp/Resources/Instructions.txt new file mode 100644 index 00000000..51f40cf6 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Instructions.txt @@ -0,0 +1,105 @@ + INSTRUCTIONS FOR 'SUPER STAR TREK' + +1. When you see "Command ?" printed, enter one of the legal + commands (NAV, SRS, LRS, PHA, TOR, SHE, DAM, COM, OR XXX). +2. If you should type in an illegal command, you'll get a short + list of the legal commands printed out. +3. Some commands require you to enter data (for example, the + 'NAV' command comes back with 'Course (1-9) ?'.) If you + type in illegal data (like negative numbers), then command + will be aborted. + + The galaxy is divided into an 8 X 8 quadrant grid, +and each quadrant is further divided into an 8 X 8 sector grid. + + You will be assigned a starting point somewhere in the +galaxy to begin a tour of duty as commander of the starship +Enterprise; your mission: to seek and destroy the fleet of +Klingon warships which are menacing the United Federation of +Planets. + + You have the following commands available to you as captain +of the starship Enterprise: + +NAV command = Warp Engine Control + Course is in a circular numerical 4 3 2 + vector arrangement as shown . . . + integer and real values may be ... + used. (Thus course 1.5 is half- 5 ---*--- 1 + way between 1 and 2. ... + . . . + Values may approach 9.0, which 6 7 8 + itself is equivalent to 1.0 + COURSE + One warp factor is the size of + one quadrant. Therefore, to get + from quadrant 6,5 to 5,5, you WOULD + use course 3, warp factor 1. + +SRS command = Short Range Sensor Scan + Shows you a scan of your present quadrant. + + Symbology on your sensor screen is as follows: + <*> = Your starship's position + +K+ = Klingon battle cruiser + >!< = Federation starbase (refuel/repair/re-arm here!) + * = Star + + A condensed 'status report' will also be presented. + +LRS command = Long Range Sensor Scan + Shows conditions in space for one quadrant on each side + of the Enterprise (which is in the middle of the scan). + The scan is coded in the form ###, where the units digit + is the number of stars, the tens digit is the number of + starbases, and the hundreds digit is the number of + Kilngons. + + Example - 207 = 2 Klingons, No starbases, & 7 stars. + +PHA command = Phaser Control + Allows you to destroy the Klingon battle cruisers by + zapping them with suitably large units of energy to + deplete their shield power. (Remember, Klingons have + phasers, too!) + +TOR command = Photon Torpedo Control + Torpedo course is the same as used in warp engine control. + If you hit the Klingon vessel, he is destroyed and + cannot fire back at you. If you miss, you are subject to + his phaser fire. In either case, you are also subject to + the phaser fire of all other Klingons in the quadrant. + + The library-computer (COM command) has an option to + compute torpedo trajectory for you (Option 2). + +SHE command = Shield Control + Defines the number of energy units to be assigned to the + shields. Energy is taken from total ship's energy. Note + that the status display total energy includes shield energy. + +DAM command = Damage Control Report + Gives the state of repair of all devices. Where a negative + 'state of repair' shows that the device is temporarily + damaged. + +COM command = Library-Computer + The library-computer contains six options: + Option 0 = Cumulative Galactic Record + This option shows computer memory of the results of all + previous short and long range sensor scans. + Option 1 = Status Report + This option shows the number of Klingons, Stardates, + and starbases remaining in the game. + Option 2 = Photon Torpedo Data + Which gives directions and distance from the Enterprise + to all Klingons in your quadrant. + Option 3 = Starbase Nav Data + This option gives direction and distance to any + starbase within your quadrant. + Option 4 = Direction/Distance Calculator + This option allows you to enter coordinates for + direction/distance calculations. + Option 5 = Galactic Region Name Map + This option prints the names of the sixteen major + galactic regions referred to in the game. diff --git a/84 Super Star Trek/csharp/Resources/Title.txt b/84 Super Star Trek/csharp/Resources/Title.txt new file mode 100644 index 00000000..ccd86774 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Title.txt @@ -0,0 +1,27 @@ + + + + + + + + + + + + + ************************************* + * * + * * + * * * SUPER STAR TREK * * * + * * + * * + ************************************* + + + + + + + + diff --git a/84 Super Star Trek/csharp/Strings.cs b/84 Super Star Trek/csharp/Strings.cs new file mode 100644 index 00000000..45241225 --- /dev/null +++ b/84 Super Star Trek/csharp/Strings.cs @@ -0,0 +1,26 @@ +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; + +using static System.StringComparison; + +namespace SuperStarTrek +{ + internal static class Strings + { + public static string Title => GetResource(); + public static string Instructions => GetResource(); + public static string Enterprise => GetResource(); + + private static string GetResource([CallerMemberName] string name = "") + { + var streamName = $"SuperStarTrek.Resources.{name}.txt"; + using var stream = Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(streamName); + using var reader = new StreamReader(stream); + + return reader.ReadToEnd(); + } + } +} diff --git a/84 Super Star Trek/csharp/SuperStarTrek.csproj b/84 Super Star Trek/csharp/SuperStarTrek.csproj index c73e0d16..c0de0594 100644 --- a/84 Super Star Trek/csharp/SuperStarTrek.csproj +++ b/84 Super Star Trek/csharp/SuperStarTrek.csproj @@ -2,7 +2,11 @@ Exe - netcoreapp3.1 + net5.0 + + + + From be14ba13c14f9bb5edc0ffbab4558a65d4582d8f Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 20 Feb 2021 23:41:59 +1100 Subject: [PATCH 003/749] Implement introduction --- 84 Super Star Trek/csharp/Program.cs | 45 ++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/84 Super Star Trek/csharp/Program.cs b/84 Super Star Trek/csharp/Program.cs index d88fa19e..0a5b6268 100644 --- a/84 Super Star Trek/csharp/Program.cs +++ b/84 Super Star Trek/csharp/Program.cs @@ -1,4 +1,31 @@ -using System; +// SUPER STARTREK - MAY 16,1978 - REQUIRES 24K MEMORY +// +// **** **** STAR TREK **** **** +// **** SIMULATION OF A MISSION OF THE STARSHIP ENTERPRISE, +// **** AS SEEN ON THE STAR TREK TV SHOW. +// **** ORIGIONAL PROGRAM BY MIKE MAYFIELD, MODIFIED VERSION +// **** PUBLISHED IN DEC'S "101 BASIC GAMES", BY DAVE AHL. +// **** MODIFICATIONS TO THE LATTER (PLUS DEBUGGING) BY BOB +// **** LEEDOM - APRIL & DECEMBER 1974, +// **** WITH A LITTLE HELP FROM HIS FRIENDS . . . +// **** COMMENTS, EPITHETS, AND SUGGESTIONS SOLICITED -- +// **** SEND TO: R. C. LEEDOM +// **** WESTINGHOUSE DEFENSE & ELECTRONICS SYSTEMS CNTR. +// **** BOX 746, M.S. 338 +// **** BALTIMORE, MD 21203 +// **** +// **** CONVERTED TO MICROSOFT 8 K BASIC 3/16/78 BY JOHN GORDERS +// **** LINE NUMBERS FROM VERSION STREK7 OF 1/12/75 PRESERVED AS +// **** MUCH AS POSSIBLE WHILE USING MULTIPLE STATEMENTS PER LINE +// **** SOME LINES ARE LONGER THAN 72 CHARACTERS; THIS WAS DONE +// **** BY USING "?" INSTEAD OF "PRINT" WHEN ENTERING LINES +// **** +// **** CONVERTED TO MICROSOFT C# 2/20/21 BY ANDREW COOPER +// **** + +using System; + +using static System.StringComparison; namespace SuperStarTrek { @@ -6,7 +33,21 @@ namespace SuperStarTrek { static void Main(string[] args) { - Console.WriteLine("Hello World!"); + Console.WriteLine(Strings.Title); + + Console.Write("Do you need instructions (Y/N)? "); + var response = Console.ReadLine(); + Console.WriteLine(); + + if (!response.Equals("N", InvariantCultureIgnoreCase)) + { + Console.WriteLine(Strings.Instructions); + + Console.WriteLine("Press to continue..."); + Console.ReadLine(); + } + + Console.WriteLine(Strings.Enterprise); } } } From 3f2b810cebb41e3716cde6725c0ef2364081abaa Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Tue, 23 Feb 2021 08:49:33 +1030 Subject: [PATCH 004/749] Removed debugging output showing the location of the Hurkle. --- 51 Hurkle/java/src/Hurkle.java | 1 - 1 file changed, 1 deletion(-) diff --git a/51 Hurkle/java/src/Hurkle.java b/51 Hurkle/java/src/Hurkle.java index 644218b3..7fc2ed1e 100644 --- a/51 Hurkle/java/src/Hurkle.java +++ b/51 Hurkle/java/src/Hurkle.java @@ -64,7 +64,6 @@ public class Hurkle { hurkleXPos = randomNumber(); hurkleYPos = randomNumber(); - System.out.println("HURKLE AT : " + hurkleXPos + "," + hurkleYPos); guesses = 1; gameState = GAME_STATE.GUESSING; From 918b9a09030578f356448da9cd9f48bbb8849794 Mon Sep 17 00:00:00 2001 From: NezumiRonin Date: Mon, 22 Feb 2021 22:51:09 -0600 Subject: [PATCH 005/749] Create sinewave.pl Sinewave.bas converted to Perl. --- 78 Sine Wave/perl/sinewave.pl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 78 Sine Wave/perl/sinewave.pl diff --git a/78 Sine Wave/perl/sinewave.pl b/78 Sine Wave/perl/sinewave.pl new file mode 100644 index 00000000..a28d3865 --- /dev/null +++ b/78 Sine Wave/perl/sinewave.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl +use strict; +use warnings; + +print ' ' x 30 ."SINE WAVE\n"; +print ' ' x 15 ."CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n\n\n"; + +my $B=0; + +for (my $T=0; $T<40; $T+=.25) { + my $A=int(26+25*sin($T)); + print ' ' x $A; + if ($B==0) { print "CREATIVE\n"; } + if ($B==1) { print "COMPUTING\n"; } + $B= !$B; #Toggle + } From 1a449b1f3c6a465e31740c60690c92aefd0eab8e Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Tue, 23 Feb 2021 16:05:46 +1030 Subject: [PATCH 006/749] Java version of Bombs Away --- 12 Bombs Away/java/src/BombsAway.java | 505 ++++++++++++++++++++++ 12 Bombs Away/java/src/BombsAwayGame.java | 8 + 2 files changed, 513 insertions(+) create mode 100644 12 Bombs Away/java/src/BombsAway.java create mode 100644 12 Bombs Away/java/src/BombsAwayGame.java diff --git a/12 Bombs Away/java/src/BombsAway.java b/12 Bombs Away/java/src/BombsAway.java new file mode 100644 index 00000000..e156ea73 --- /dev/null +++ b/12 Bombs Away/java/src/BombsAway.java @@ -0,0 +1,505 @@ +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 + * + * 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 { + + public static final int MAX_PILOT_MISSIONS = 160; + public static final int MAX_CASUALTIES = 100; + public static final int MISSED_TARGET_CONST_1 = 2; + public static final int MISSED_TARGET_CONST_2 = 30; + public static final int CHANCE_OF_BEING_SHOT_DOWN_BASE = 100; + public static final double SIXTY_FIVE_PERCENT = .65; + + private enum GAME_STATE { + START, + CHOOSE_SIDE, + CHOOSE_PLANE, + CHOOSE_TARGET, + CHOOSE_MISSIONS, + CHOOSE_ENEMY_DEFENCES, + FLY_MISSION, + DIRECT_HIT, + MISSED_TARGET, + PROCESS_FLAK, + SHOT_DOWN, + MADE_IT_THROUGH_FLAK, + PLAY_AGAIN, + GAME_OVER + } + + public enum SIDE { + ITALY(1), + ALLIES(2), + JAPAN(3), + GERMANY(4); + + private final int value; + + SIDE(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + + } + + public enum TARGET { + ALBANIA(1), + GREECE(2), + NORTH_AFRICA(3), + RUSSIA(4), + ENGLAND(5), + FRANCE(6); + + private final int value; + + TARGET(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + public enum ENEMY_DEFENCES { + GUNS(1), + MISSILES(2), + BOTH(3); + + private final int value; + + ENEMY_DEFENCES(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + public enum AIRCRAFT { + LIBERATOR(1), + B29(2), + B17(3), + LANCASTER(4); + + private final int value; + + AIRCRAFT(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + // Used for keyboard input + private final Scanner kbScanner; + + // Current game state + private GAME_STATE gameState; + + private SIDE side; + + private int missions; + + private int chanceToHit; + private int percentageHitRateOfGunners; + + public BombsAway() { + + gameState = GAME_STATE.START; + + // Initialise kb scanner + kbScanner = new Scanner(System.in); + } + + /** + * Main game loop + * + */ + public void play() { + + do { + switch (gameState) { + + // Show an introduction the first time the game is played. + case START: + intro(); + chanceToHit = 0; + percentageHitRateOfGunners = 0; + + gameState = GAME_STATE.CHOOSE_SIDE; + break; + + case CHOOSE_SIDE: + side = getSide("WHAT SIDE -- ITALY(1), ALLIES(2), JAPAN(3), GERMANY(4) ? "); + if (side == null) { + System.out.println("TRY AGAIN..."); + } else { + // Different game paths depending on which side was chosen + switch (side) { + case ITALY: + case GERMANY: + gameState = GAME_STATE.CHOOSE_TARGET; + break; + case ALLIES: + case JAPAN: + gameState = GAME_STATE.CHOOSE_PLANE; + break; + } + } + break; + + case CHOOSE_TARGET: + String prompt; + if (side == SIDE.ITALY) { + prompt = "YOUR TARGET -- ALBANIA(1), GREECE(2), NORTH AFRICA(3) ? "; + } else { + // Germany + System.out.println("A NAZI, EH? OH WELL. ARE YOU GOING FOR RUSSIA(1),"); + prompt = "ENGLAND(2), OR FRANCE(3) ? "; + } + TARGET target = getTarget(prompt); + if (target == null) { + System.out.println("TRY AGAIN..."); + } else { + displayTargetMessage(target); + gameState = GAME_STATE.CHOOSE_MISSIONS; + } + + case CHOOSE_MISSIONS: + missions = getNumberFromKeyboard("HOW MANY MISSIONS HAVE YOU FLOWN? "); + + if(missions <25) { + System.out.println("FRESH OUT OF TRAINING, EH?"); + gameState = GAME_STATE.FLY_MISSION; + } else if(missions < 100) { + System.out.println("THAT'S PUSHING THE ODDS!"); + gameState = GAME_STATE.FLY_MISSION; + } else if(missions >=160) { + System.out.println("MISSIONS, NOT MILES..."); + System.out.println("150 MISSIONS IS HIGH EVEN FOR OLD-TIMERS."); + System.out.println("NOW THEN, "); + } else { + // No specific message if missions is 100-159, but still valid + gameState = GAME_STATE.FLY_MISSION; + } + break; + + case CHOOSE_PLANE: + switch(side) { + case ALLIES: + AIRCRAFT plane = getPlane("AIRCRAFT -- LIBERATOR(1), B-29(2), B-17(3), LANCASTER(4)? "); + if(plane == null) { + System.out.println("TRY AGAIN..."); + } else { + switch(plane) { + + case LIBERATOR: + System.out.println("YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI."); + break; + case B29: + System.out.println("YOU'RE DUMPING THE A-BOMB ON HIROSHIMA."); + break; + case B17: + System.out.println("YOU'RE CHASING THE BISMARK IN THE NORTH SEA."); + break; + case LANCASTER: + System.out.println("YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR."); + break; + } + + gameState = GAME_STATE.CHOOSE_MISSIONS; + } + break; + + case JAPAN: + System.out.println("YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON."); + if(yesEntered(displayTextAndGetInput("YOUR FIRST KAMIKAZE MISSION(Y OR N) ? "))) { + if(randomNumber(1) > SIXTY_FIVE_PERCENT) { + gameState = GAME_STATE.DIRECT_HIT; + } else { + // It's a miss + gameState = GAME_STATE.MISSED_TARGET; + } + } else { + gameState = GAME_STATE.PROCESS_FLAK; + } + break; + } + break; + + case FLY_MISSION: + double missionResult = (MAX_PILOT_MISSIONS * randomNumber(1)); + if(missions > missionResult) { + gameState = GAME_STATE.DIRECT_HIT; + } else { + gameState = GAME_STATE.MISSED_TARGET; + } + + break; + + case DIRECT_HIT: + System.out.println("DIRECT HIT!!!! " + (int) Math.round(randomNumber(MAX_CASUALTIES)) + " KILLED."); + System.out.println("MISSION SUCCESSFUL."); + gameState = GAME_STATE.PLAY_AGAIN; + break; + + case MISSED_TARGET: + System.out.println("MISSED TARGET BY " + (int) Math.round(MISSED_TARGET_CONST_1 + MISSED_TARGET_CONST_2 * (randomNumber(1))) + " MILES!"); + System.out.println("NOW YOU'RE REALLY IN FOR IT !!"); + System.out.println(); + gameState = GAME_STATE.CHOOSE_ENEMY_DEFENCES; + break; + + case CHOOSE_ENEMY_DEFENCES: + boolean bothWeapons = true; + + ENEMY_DEFENCES enemyDefences = getEnemyDefences("DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3) ? "); + if(enemyDefences == null) { + System.out.println("TRY AGAIN..."); + } else { + switch(enemyDefences) { + case MISSILES: + case GUNS: + bothWeapons = false; + + // 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 BOTH: + 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; + + } + break; + } + } + gameState = GAME_STATE.PROCESS_FLAK; + + // Determine if the players airplan makes it through the Flak. + case PROCESS_FLAK: + double calc = (CHANCE_OF_BEING_SHOT_DOWN_BASE * randomNumber(1)); + + if ((chanceToHit + percentageHitRateOfGunners) > calc) { + gameState = GAME_STATE.SHOT_DOWN; + } else { + gameState = GAME_STATE.MADE_IT_THROUGH_FLAK; + } + break; + + case SHOT_DOWN: + System.out.println("* * * * BOOM * * * *"); + System.out.println("YOU HAVE BEEN SHOT DOWN....."); + System.out.println("DEARLY BELOVED, WE ARE GATHERED HERE TODAY TO PAY OUR"); + System.out.println("LAST TRIBUTE..."); + gameState = GAME_STATE.PLAY_AGAIN; + break; + + case MADE_IT_THROUGH_FLAK: + System.out.println("YOU MADE IT THROUGH TREMENDOUS FLAK!!"); + gameState = GAME_STATE.PLAY_AGAIN; + break; + + case PLAY_AGAIN: + if(yesEntered(displayTextAndGetInput("ANOTHER MISSION (Y OR N) ? "))) { + gameState = GAME_STATE.START; + } else { + System.out.println("CHICKEN !!!"); + gameState = GAME_STATE.GAME_OVER; + } + break; + } + } while (gameState != GAME_STATE.GAME_OVER) ; + } + + /** + * Display a (brief) intro + */ + public void intro() { + System.out.println("YOU ARE A PILOT IN A WORLD WAR II BOMBER."); + } + + /** + * Determine the side the player is going to play on. + * @param message displayed before the kb input + * @return the SIDE enum selected by the player + */ + private SIDE getSide(String message) { + int valueEntered = getNumberFromKeyboard(message); + for(SIDE side : SIDE.values()) { + if(side.getValue() == valueEntered) { + return side; + } + } + + // Input out of range + return null; + } + + /** + * Determine the target the player is going for. + * @param message displayed before the kb input + * @return the TARGET enum selected by the player + */ + private TARGET getTarget(String message) { + int valueEntered = getNumberFromKeyboard(message); + + for(TARGET target : TARGET.values()) { + if(target.getValue() == valueEntered) { + return target; + } + } + + // Input out of range + return null; + } + + /** + * Determine the airplane the player is going to fly. + * @param message displayed before the kb input + * @return the AIRCRAFT enum selected by the player + */ + private AIRCRAFT getPlane(String message) { + int valueEntered = getNumberFromKeyboard(message); + + for(AIRCRAFT plane : AIRCRAFT.values()) { + if(plane.getValue() == valueEntered) { + return plane; + } + } + + // Input out of range + return null; + + } + + /** + * Select the type of enemy defences. + * + * @param message displayed before kb input + * @return the ENEMY_DEFENCES enum as selected by player + */ + private ENEMY_DEFENCES getEnemyDefences(String message) { + int valueEntered = getNumberFromKeyboard(message); + for (ENEMY_DEFENCES enemyDefences : ENEMY_DEFENCES.values()) { + if(enemyDefences.getValue() == valueEntered) { + return enemyDefences; + } + } + + // Input out of range + return null; + } + + // output a specific message based on the target selected + private void displayTargetMessage(TARGET target) { + + switch (target) { + + case ALBANIA: + System.out.println("SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE."); + break; + case GREECE: + System.out.println("BE CAREFUL!!!"); + break; + case NORTH_AFRICA: + System.out.println("YOU'RE GOING FOR THE OIL, EH?"); + break; + case RUSSIA: + System.out.println("YOU'RE NEARING STALINGRAD."); + break; + case ENGLAND: + System.out.println("NEARING LONDON. BE CAREFUL, THEY'VE GOT RADAR."); + break; + case FRANCE: + System.out.println("NEARING VERSAILLES. DUCK SOUP. THEY'RE NEARLY DEFENSELESS."); + break; + } + } + + /** + * Accepts a string from the keyboard, and converts to an int + * + * @param message displayed text on screen before keyboard input + * + * @return the number entered by the player + */ + private int getNumberFromKeyboard(String message) { + + String answer = displayTextAndGetInput(message); + return Integer.parseInt(answer); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + // Cycle through the variable number of values and test each + for(String val:values) { + if(text.equalsIgnoreCase(val)) { + return true; + } + } + + // no matches + return false; + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Generate random number + * Used as a single digit of the computer player + * + * @return random number + */ + private double randomNumber(int range) { + return (Math.random() + * (range)); + } +} \ No newline at end of file diff --git a/12 Bombs Away/java/src/BombsAwayGame.java b/12 Bombs Away/java/src/BombsAwayGame.java new file mode 100644 index 00000000..cfa05cd7 --- /dev/null +++ b/12 Bombs Away/java/src/BombsAwayGame.java @@ -0,0 +1,8 @@ +public class BombsAwayGame { + + public static void main(String[] args) { + + BombsAway bombsAway = new BombsAway(); + bombsAway.play(); + } +} From 16a80064d9e0ce983fa4eeb8b610f062a2652290 Mon Sep 17 00:00:00 2001 From: NezumiRonin Date: Tue, 23 Feb 2021 00:14:05 -0600 Subject: [PATCH 007/749] Create 3dplot.pl 3D Plot made with perl! --- 87 3-D Plot/perl/3dplot.pl | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 87 3-D Plot/perl/3dplot.pl diff --git a/87 3-D Plot/perl/3dplot.pl b/87 3-D Plot/perl/3dplot.pl new file mode 100644 index 00000000..a7cfb1c6 --- /dev/null +++ b/87 3-D Plot/perl/3dplot.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +use strict; +use warnings; + +print ' 'x32 ."3D PLOT\n"; +print ' 'x15 ."CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; + +sub FNA { + my ($Z)= @_; + return 30*exp(-$Z*$Z/100); + } + +print "\n"; + +for (my $X=-30; $X<=30; $X+=1.5) { + my $L=0; + my $Line=" "x80; #Empty buffer string; + my $Y1=5*int(sqrt(900-$X*$X)/5); + for (my $Y=$Y1; $Y>=-$Y1; $Y-=5) { + my $Z=int(25+&FNA(sqrt($X*$X+$Y*$Y))-.7*$Y); + if ($Z<=$L) { next; } + $L= $Z; + substr $Line, $Z, 1, "*"; #Plot on the line by sustitution. + } + print "$Line\n"; #Now print the line. + } From b6a25f0c81af2330f9094b353adb0f0b6a85810f Mon Sep 17 00:00:00 2001 From: NezumiRonin Date: Tue, 23 Feb 2021 01:23:16 -0600 Subject: [PATCH 008/749] Create train.pl Converted from BASIC to Perl --- 91 Train/perl/train.pl | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 91 Train/perl/train.pl diff --git a/91 Train/perl/train.pl b/91 Train/perl/train.pl new file mode 100644 index 00000000..d628b12c --- /dev/null +++ b/91 Train/perl/train.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +use strict; +use warnings; + +print ' 'x33 ."TRAIN\n"; +print ' 'x15 ."CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; +print "TIME - SPEED DISTANCE EXERCISE\n"; print "\n"; + + +my $A= ""; #We must declare this before... +do { + my $C= int(25*rand(1))+40; + my $D= int(15*rand(1))+5; + my $T= int(19*rand(1))+20; + + print " A CAR TRAVELING $C MPH CAN MAKE A CERTAIN TRIP IN\n"; + print "$D HOURS LESS THAN A TRAIN TRAVELING AT $T MPH.\n"; + print "HOW LONG DOES THE TRIP TAKE BY CAR\n"; + chomp ($A = ); + + my $V= $D*$T/($C-$T); + my $E= int(abs(($V-$A)*100/$A)+.5); + if ($E>5) { + print "SORRY. YOU WERE OFF BY $E PERCENT.\n"; + } else { + print "GOOD! ANSWER WITHIN $E PERCENT.\n"; + } + + print "CORRECT ANSWER IS $V HOURS.\n"; + print "\n"; + print "ANOTHER PROBLEM (YES OR NO)\n"; + chomp ($A = uc()); #Uppercased + } until ($A ne "YES"); From aa346ee36c94f7823d2de008c8b550ac0089fe3e Mon Sep 17 00:00:00 2001 From: Jesse McDowell <384601+jessemcdowell@users.noreply.github.com> Date: Sat, 20 Feb 2021 21:56:58 -0800 Subject: [PATCH 009/749] Implement Blackjack (game 10) in C# --- 10 Blackjack/csharp/Blackjack.csproj | 9 ++ 10 Blackjack/csharp/Card.cs | 32 ++++ 10 Blackjack/csharp/Deck.cs | 56 +++++++ 10 Blackjack/csharp/Game.cs | 232 +++++++++++++++++++++++++++ 10 Blackjack/csharp/Hand.cs | 67 ++++++++ 10 Blackjack/csharp/Player.cs | 27 ++++ 10 Blackjack/csharp/Program.cs | 41 +++++ 10 Blackjack/csharp/Prompt.cs | 58 +++++++ 8 files changed, 522 insertions(+) create mode 100644 10 Blackjack/csharp/Blackjack.csproj create mode 100644 10 Blackjack/csharp/Card.cs create mode 100644 10 Blackjack/csharp/Deck.cs create mode 100644 10 Blackjack/csharp/Game.cs create mode 100644 10 Blackjack/csharp/Hand.cs create mode 100644 10 Blackjack/csharp/Player.cs create mode 100644 10 Blackjack/csharp/Program.cs create mode 100644 10 Blackjack/csharp/Prompt.cs diff --git a/10 Blackjack/csharp/Blackjack.csproj b/10 Blackjack/csharp/Blackjack.csproj new file mode 100644 index 00000000..796a6731 --- /dev/null +++ b/10 Blackjack/csharp/Blackjack.csproj @@ -0,0 +1,9 @@ + + + + Exe + Blackjack + net5.0 + + + diff --git a/10 Blackjack/csharp/Card.cs b/10 Blackjack/csharp/Card.cs new file mode 100644 index 00000000..a2b6b6bd --- /dev/null +++ b/10 Blackjack/csharp/Card.cs @@ -0,0 +1,32 @@ +namespace Blackjack +{ + public class Card + { + private static readonly string[] _names = new[] {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}; + + public Card(int index) + { + Index = index; + } + + public int Index { get; private set; } + + public string Name => _names[Index]; + + public string IndefiniteArticle => (Index == 0 || Index == 7) ? "an" : "a"; + + public bool IsAce => Index == 0; + + public int Value + { + get + { + if (IsAce) + return 11; + if (Index > 8) + return 10; + return Index + 1; + } + } + } +} diff --git a/10 Blackjack/csharp/Deck.cs b/10 Blackjack/csharp/Deck.cs new file mode 100644 index 00000000..21b1e9ef --- /dev/null +++ b/10 Blackjack/csharp/Deck.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace Blackjack +{ + public class Deck + { + private static readonly Random _random = new Random(); + + private readonly List _cards = new List(52); + private readonly List _discards = new List(52); + + public Deck() + { + for (var index = 0; index < 12; index++) + { + for (var suit = 0; suit < 4; suit++) + { + _discards.Add(new Card(index)); + } + } + Reshuffle(); + } + + private void Reshuffle() + { + Console.WriteLine("Reshuffling"); + + _cards.AddRange(_discards); + _discards.Clear(); + + for (var index1 = _cards.Count - 1; index1 > 0; index1--) + { + var index2 = _random.Next(0, index1); + var swapCard = _cards[index1]; + _cards[index1] = _cards[index2]; + _cards[index2] = swapCard; + } + } + + public Card DrawCard() + { + if (_cards.Count < 2) + Reshuffle(); + + var card = _cards[_cards.Count - 1]; + _cards.RemoveAt(_cards.Count - 1); + return card; + } + + public void Discard(IEnumerable cards) + { + _discards.AddRange(cards); + } + } +} diff --git a/10 Blackjack/csharp/Game.cs b/10 Blackjack/csharp/Game.cs new file mode 100644 index 00000000..7bb16350 --- /dev/null +++ b/10 Blackjack/csharp/Game.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Blackjack +{ + public class Game + { + private readonly Deck _deck = new Deck(); + private readonly int _numberOfPlayers; + private readonly Player[] _players; + private readonly Hand _dealerHand; + + public Game(int numberOfPlayers) + { + _numberOfPlayers = numberOfPlayers; + _players = new Player[_numberOfPlayers]; + for (var playerIndex = 0; playerIndex < _numberOfPlayers; playerIndex++) + _players[playerIndex] = new Player(playerIndex); + _dealerHand = new Hand(); + } + + public void PlayGame() + { + while (true) + { + PlayRound(); + TallyResults(); + ResetRoundState(); + Console.WriteLine(); + } + } + + public void PlayRound() + { + GetPlayerBets(); + + DealHands(); + + // Test for insurance + var dealerIsShowingAce = _dealerHand.Cards[0].IsAce; + if (dealerIsShowingAce && Prompt.ForYesNo("Any insurance?")) + { + Console.WriteLine("Insurance bets"); + var insuranceBets = new int[_numberOfPlayers]; + foreach (var player in _players) + insuranceBets[player.Index] = Prompt.ForInteger($"# {player.Index + 1} ?", 0, player.RoundBet / 2); + + var insuranceEffectMultiplier = _dealerHand.IsBlackjack ? 2 : -1; + foreach (var player in _players) + player.RoundWinnings += insuranceBets[player.Index] * insuranceEffectMultiplier; + } + + // Test for dealer blackjack + var concealedCard = _dealerHand.Cards[0]; + if (_dealerHand.IsBlackjack) + { + Console.WriteLine(); + Console.WriteLine("Dealer has {0} {1} in the hole for blackjack.", concealedCard.IndefiniteArticle, concealedCard.Name); + return; + } + else if (dealerIsShowingAce) + { + Console.WriteLine(); + Console.WriteLine("No dealer blackjack."); + } + + foreach (var player in _players) + PlayHand(player); + + // Dealer hand + var allPlayersBusted = _players.All(p => p.Hand.IsBusted && (!p.SecondHand.Exists || p.SecondHand.IsBusted)); + if (allPlayersBusted) + Console.WriteLine("Dealer had {0} {1} concealed.", concealedCard.IndefiniteArticle, concealedCard.Name); + else + { + Console.WriteLine("Dealer has {0} {1} concealed for a total of {2}", concealedCard.IndefiniteArticle, concealedCard.Name, _dealerHand.Total); + if (_dealerHand.Total < 17) + { + Console.Write("Draws"); + while (_dealerHand.Total < 17) + { + var card = _dealerHand.AddCard(_deck.DrawCard()); + Console.Write(" {0}", card.Name); + } + if (_dealerHand.IsBusted) + Console.WriteLine(" ...Busted"); + else + Console.WriteLine(" ---Total is {0}", _dealerHand.Total); + } + } + } + + private void GetPlayerBets() + { + Console.WriteLine("Bets:"); + foreach (var player in _players) + player.RoundBet = Prompt.ForInteger($"# {player.Name} ?", 1, 500); + } + + private void DealHands() + { + Console.Write("Player "); + foreach (var player in _players) + Console.Write("{0} ", player.Name); + Console.WriteLine("Dealer"); + + for (var cardIndex = 0; cardIndex < 2; cardIndex++) + { + Console.Write(" "); + foreach (var player in _players) + Console.Write(" {0,-4}", player.Hand.AddCard(_deck.DrawCard()).Name); + var dealerCard = _dealerHand.AddCard(_deck.DrawCard()); + Console.Write(" {0,-4}", (cardIndex == 0) ? "XX" : dealerCard.Name); + + Console.WriteLine(); + } + } + + private void PlayHand(Player player) + { + var hand = player.Hand; + + Console.Write("Player {0} ", player.Name); + + var playerCanSplit = hand.Cards[0].Value == hand.Cards[1].Value; + var command = Prompt.ForCommandCharacter("?", playerCanSplit ? "HSD/" : "HSD"); + switch (command) + { + case "D": + player.RoundBet *= 2; + goto case "H"; + + case "H": + while (TakeHit(hand) && PromptForAnotherHit()) + { } + if (!hand.IsBusted) + Console.WriteLine("Total is {0}", hand.Total); + break; + + case "S": + if (hand.IsBlackjack) + { + Console.WriteLine("Blackjack!"); + player.RoundWinnings = (int)(1.5 * player.RoundBet + 0.5); + player.RoundBet = 0; + } + else + Console.WriteLine("Total is {0}", hand.Total); + break; + + case "/": + hand.SplitHand(player.SecondHand); + var card = hand.AddCard(_deck.DrawCard()); + Console.WriteLine("First hand receives {0} {1}", card.IndefiniteArticle, card.Name); + card = player.SecondHand.AddCard(_deck.DrawCard()); + Console.WriteLine("Second hand receives {0} {1}", card.IndefiniteArticle, card.Name); + + for (int handNumber = 1; handNumber <= 2; handNumber++) + { + hand = (handNumber == 1) ? player.Hand : player.SecondHand; + + Console.Write("Hand {0}", handNumber); + while (PromptForAnotherHit() && TakeHit(hand)) + { } + if (!hand.IsBusted) + Console.WriteLine("Total is {0}", hand.Total); + } + break; + } + } + + private bool TakeHit(Hand hand) + { + var card = hand.AddCard(_deck.DrawCard()); + Console.Write("Received {0,-6}", $"{card.IndefiniteArticle} {card.Name}"); + if (hand.IsBusted) + { + Console.WriteLine("...Busted"); + return false; + } + return true; + } + + private bool PromptForAnotherHit() + { + return String.Equals(Prompt.ForCommandCharacter(" Hit?", "HS"), "H"); + } + + private void TallyResults() + { + Console.WriteLine(); + foreach (var player in _players) + { + player.RoundWinnings += CalculateWinnings(player, player.Hand); + if (player.SecondHand.Exists) + player.RoundWinnings += CalculateWinnings(player, player.SecondHand); + player.TotalWinnings += player.RoundWinnings; + + Console.WriteLine("Player {0} {1,-6} {2,3} Total= {3,5}", + player.Name, + (player.RoundWinnings > 0) ? "wins" : (player.RoundWinnings) < 0 ? "loses" : "pushes", + (player.RoundWinnings != 0) ? Math.Abs(player.RoundWinnings).ToString() : "", + player.TotalWinnings); + } + Console.WriteLine("Dealer's total= {0}", -_players.Sum(p => p.TotalWinnings)); + } + + private int CalculateWinnings(Player player, Hand hand) + { + if (hand.IsBusted) + return -player.RoundBet; + if (hand.Total == _dealerHand.Total) + return 0; + if (_dealerHand.IsBusted || hand.Total > _dealerHand.Total) + return player.RoundBet; + return -player.RoundBet; + } + + private void ResetRoundState() + { + foreach (var player in _players) + { + player.RoundWinnings = 0; + player.RoundBet = 0; + player.Hand.Discard(_deck); + player.SecondHand.Discard(_deck); + } + _dealerHand.Discard(_deck); + } + } +} diff --git a/10 Blackjack/csharp/Hand.cs b/10 Blackjack/csharp/Hand.cs new file mode 100644 index 00000000..49b945bb --- /dev/null +++ b/10 Blackjack/csharp/Hand.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; + +namespace Blackjack +{ + public class Hand + { + private readonly List _cards = new List(12); + private int _cachedTotal = 0; + + public Card AddCard(Card card) + { + _cards.Add(card); + _cachedTotal = 0; + return card; + } + + public void Discard(Deck deck) + { + deck.Discard(_cards); + _cards.Clear(); + _cachedTotal = 0; + } + + public void SplitHand(Hand secondHand) + { + if (Count != 2 || secondHand.Count != 0) + throw new InvalidOperationException(); + secondHand.AddCard(_cards[1]); + _cards.RemoveAt(1); + _cachedTotal = 0; + } + + public IReadOnlyList Cards => _cards; + + public int Count => _cards.Count; + + public bool Exists => _cards.Count > 0; + + public int Total + { + get + { + if (_cachedTotal == 0) + { + var aceCount = 0; + foreach (var card in _cards) + { + _cachedTotal += card.Value; + if (card.IsAce) + aceCount++; + } + while (_cachedTotal > 21 && aceCount > 0) + { + _cachedTotal -= 10; + aceCount--; + } + } + return _cachedTotal; + } + } + + public bool IsBlackjack => Total == 21 && Count == 2; + + public bool IsBusted => Total > 21; + } +} diff --git a/10 Blackjack/csharp/Player.cs b/10 Blackjack/csharp/Player.cs new file mode 100644 index 00000000..58664f1d --- /dev/null +++ b/10 Blackjack/csharp/Player.cs @@ -0,0 +1,27 @@ +namespace Blackjack +{ + public class Player + { + public Player(int index) + { + Index = index; + Name = (index + 1).ToString(); + Hand = new Hand(); + SecondHand = new Hand(); + } + + public int Index { get; private set; } + + public string Name { get; private set; } + + public Hand Hand { get; private set; } + + public Hand SecondHand { get; private set;} + + public int RoundBet { get; set; } + + public int RoundWinnings { get; set; } + + public int TotalWinnings { get; set; } + } +} diff --git a/10 Blackjack/csharp/Program.cs b/10 Blackjack/csharp/Program.cs new file mode 100644 index 00000000..dac7da86 --- /dev/null +++ b/10 Blackjack/csharp/Program.cs @@ -0,0 +1,41 @@ +using System; + +namespace Blackjack +{ + static class Program + { + static void Main(string[] args) + { + Console.WriteLine("{0}BLACK JACK", new string(' ', 31)); + Console.WriteLine("{0}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", new string(' ', 15)); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + + OfferInstructions(); + + var numberOfPlayers = Prompt.ForInteger("Number of players?", 1, 6); + var game = new Game(numberOfPlayers); + game.PlayGame(); + } + + private static void OfferInstructions() + { + if (!Prompt.ForYesNo("Do you want instructions?")) + return; + + Console.WriteLine("This is the game of 21. As many as 7 players may play the"); + Console.WriteLine("game. On each deal, bets will be asked for, and the"); + Console.WriteLine("players' bets should be typed in. The cards will then be"); + Console.WriteLine("dealt, and each player in turn plays his hand. The"); + Console.WriteLine("first response should be either 'D', indicating that the"); + Console.WriteLine("player is doubling down, 'S', indicating that he is"); + Console.WriteLine("standing, 'H', indicating he wants another card, or '/',"); + Console.WriteLine("indicating that he wants to split his cards. After the"); + Console.WriteLine("initial response, all further responses should be 's' or"); + Console.WriteLine("'H', unless the cards were split, in which case doubling"); + Console.WriteLine("down is again permitted. In order to collect for"); + Console.WriteLine("Blackjack, the initial response should be 'S'."); + } + } +} diff --git a/10 Blackjack/csharp/Prompt.cs b/10 Blackjack/csharp/Prompt.cs new file mode 100644 index 00000000..9f798965 --- /dev/null +++ b/10 Blackjack/csharp/Prompt.cs @@ -0,0 +1,58 @@ +using System; + +namespace Blackjack +{ + public static class Prompt + { + public static bool ForYesNo(string prompt) + { + while(true) + { + Console.Write("{0} ", prompt); + var input = Console.ReadLine(); + if (input.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)) + return true; + if (input.StartsWith("n", StringComparison.InvariantCultureIgnoreCase)) + return false; + WriteNotUnderstood(); + } + } + + public static int ForInteger(string prompt, int minimum = 1, int maximum = int.MaxValue) + { + while (true) + { + Console.Write("{0} ", prompt); + if (!int.TryParse(Console.ReadLine(), out var number)) + WriteNotUnderstood(); + else if (number < minimum || number > maximum) + Console.WriteLine("Sorry, I need a number between {0} and {1}.", minimum, maximum); + else + return number; + } + } + + public static string ForCommandCharacter(string prompt, string allowedCharacters) + { + while (true) + { + Console.Write("{0} ", prompt); + var input = Console.ReadLine(); + if (input.Length > 0) + { + var character = input.Substring(0, 1); + var characterIndex = allowedCharacters.IndexOf(character, StringComparison.InvariantCultureIgnoreCase); + if (characterIndex != -1) + return allowedCharacters.Substring(characterIndex, 1); + } + + Console.WriteLine("Type one of {0} please", String.Join(", ", allowedCharacters.ToCharArray())); + } + } + + private static void WriteNotUnderstood() + { + Console.WriteLine("Sorry, I didn't understand."); + } + } +} From 5be29886d8fdb3a422bfd77cbca5d52572a67d12 Mon Sep 17 00:00:00 2001 From: nanochess Date: Tue, 23 Feb 2021 11:39:43 -0600 Subject: [PATCH 010/749] Ported WAR, WEEKDAY, and WORD to Javascript --- 94 War/javascript/war.html | 9 ++ 94 War/javascript/war.js | 136 +++++++++++++++++++ 95 Weekday/javascript/weekday.html | 9 ++ 95 Weekday/javascript/weekday.js | 208 +++++++++++++++++++++++++++++ 96 Word/javascript/word.html | 9 ++ 96 Word/javascript/word.js | 150 +++++++++++++++++++++ 96 Word/word.bas | 2 +- 7 files changed, 522 insertions(+), 1 deletion(-) create mode 100644 94 War/javascript/war.html create mode 100644 94 War/javascript/war.js create mode 100644 95 Weekday/javascript/weekday.html create mode 100644 95 Weekday/javascript/weekday.js create mode 100644 96 Word/javascript/word.html create mode 100644 96 Word/javascript/word.js diff --git a/94 War/javascript/war.html b/94 War/javascript/war.html new file mode 100644 index 00000000..67cab7d2 --- /dev/null +++ b/94 War/javascript/war.html @@ -0,0 +1,9 @@ + + +WAR + + +

+
+
+
diff --git a/94 War/javascript/war.js b/94 War/javascript/war.js
new file mode 100644
index 00000000..eb74fb0c
--- /dev/null
+++ b/94 War/javascript/war.js	
@@ -0,0 +1,136 @@
+// WAR
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a = [, "S-2","H-2","C-2","D-2","S-3","H-3","C-3","D-3",
+         "S-4","H-4","C-4","D-4","S-5","H-5","C-5","D-5",
+         "S-6","H-6","C-6","D-6","S-7","H-7","C-7","D-7",
+         "S-8","H-8","C-8","D-8","S-9","H-9","C-9","D-9",
+         "S-10","H-10","C-10","D-10","S-J","H-J","C-J","D-J",
+         "S-Q","H-Q","C-Q","D-Q","S-K","H-K","C-K","D-K",
+         "S-A","H-A","C-A","D-A"];
+
+var l = [];
+
+// Main control section
+async function main()
+{
+    print(tab(33) + "WAR\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS IS THE CARD GAME OF WAR.  EACH CARD IS GIVEN BY SUIT-#\n");
+    print("AS S-7 FOR SPADE 7.  ");
+    while (1) {
+        print("DO YOU WANT DIRECTIONS");
+        str = await input();
+        if (str == "YES") {
+            print("THE COMPUTER GIVES YOU AND IT A 'CARD'.  THE HIGHER CARD\n");
+            print("(NUMERICALLY) WINS.  THE GAME ENDS WHEN YOU CHOOSE NOT TO\n");
+            print("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n");
+            break;
+        }
+        if (str == "NO")
+            break;
+        print("YES OR NO, PLEASE.  ");
+    }
+    print("\n");
+    print("\n");
+    
+    a1 = 0;
+    b1 = 0;
+    p = 0;
+    
+    // Generate a random deck
+    for (j = 1; j <= 52; j++) {
+        do {
+            l[j] = Math.floor(52 * Math.random()) + 1;
+            for (k = 1; k < j; k++) {
+                if (l[k] == l[j])   // Already in deck?
+                    break;
+            }
+        } while (j != 1 && k < j) ;
+    }
+    l[j] = 0;   // Mark the end of the deck
+    
+    while (1) {
+        m1 = l[++p];    // Take a card
+        m2 = l[++p];    // Take a card
+        print("\n");
+        print("YOU: " + a[m1] + "\tCOMPUTER: " + a[m2] + "\n");
+        n1 = Math.floor((m1 - 0.5) / 4);
+        n2 = Math.floor((m2 - 0.5) / 4);
+        if (n1 < n2) {
+            a1++;
+            print("THE COMPUTER WINS!!! YOU HAVE " + b1 + " AND THE COMPUTER HAS " + a1 + "\n");
+        } else if (n1 > n2) {
+            b1++;
+            print("YOU WIN. YOU HAVE " + b1 + " AND THE COMPUTER HAS " + a1 + "\n");
+        } else {
+            print("TIE.  NO SCORE CHANGE.\n");
+        }
+        if (l[p + 1] == 0) {
+            print("\n");
+            print("\n");
+            print("WE HAVE RUN OUT OF CARDS.  FINAL SCORE:  YOU: " + b1 + "  THE COMPUTER: " + a1 + "\n");
+            print("\n");
+            break;
+        }
+        while (1) {
+            print("DO YOU WANT TO CONTINUE");
+            str = await input();
+            if (str == "YES")
+                break;
+            if (str == "NO")
+                break;
+            print("YES OR NO, PLEASE.  ");
+        }
+        if (str == "NO")
+            break;
+    }
+    print("THANKS FOR PLAYING.  IT WAS FUN.\n");
+    print("\n");
+}
+
+main();
diff --git a/95 Weekday/javascript/weekday.html b/95 Weekday/javascript/weekday.html
new file mode 100644
index 00000000..928df878
--- /dev/null
+++ b/95 Weekday/javascript/weekday.html	
@@ -0,0 +1,9 @@
+
+
+WEEKDAY
+
+
+

+
+
+
diff --git a/95 Weekday/javascript/weekday.js b/95 Weekday/javascript/weekday.js
new file mode 100644
index 00000000..276e1817
--- /dev/null
+++ b/95 Weekday/javascript/weekday.js	
@@ -0,0 +1,208 @@
+// WEEKDAY
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+function fna(arg) {
+    return Math.floor(arg / 4);
+}
+
+function fnb(arg) {
+    return Math.floor(arg / 7);
+}
+
+var t = [, 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5];
+
+var k5;
+var k6;
+var k7;
+
+function time_spent(f, a8)
+{
+    k1 = Math.floor(f * a8);
+    i5 = Math.floor(k1 / 365);
+    k1 -= i5 * 365;
+    i6 = Math.floor(k1 / 30);
+    i7 = k1 - (i6 * 30);
+    k5 -= i5;
+    k6 -= i6;
+    k7 -= i7;
+    if (k7 < 0) {
+        k7 += 30;
+        k6--;
+    }
+    if (k6 <= 0) {
+        k6 += 12;
+        k5--;
+    }
+    print(i5 + "\t" + i6 + "\t" + i7 + "\n");
+}
+
+// Main control section
+async function main()
+{
+    print(tab(32) + "WEEKDAY\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("WEEKDAY IS A COMPUTER DEMONSTRATION THAT\n");
+    print("GIVES FACTS ABOUT A DATE OF INTEREST TO YOU.\n");
+    print("\n");
+    print("ENTER TODAY'S DATE IN THE FORM: 3,24,1979  ");
+    str = await input();
+    m1 = parseInt(str);
+    d1 = parseInt(str.substr(str.indexOf(",") + 1));
+    y1 = parseInt(str.substr(str.lastIndexOf(",") + 1));
+    // This program determines the day of the week
+    //  for a date after 1582
+    print("ENTER DAY OF BIRTH (OR OTHER DAY OF INTEREST)");
+    str = await input();
+    m = parseInt(str);
+    d = parseInt(str.substr(str.indexOf(",") + 1));
+    y = parseInt(str.substr(str.lastIndexOf(",") + 1));
+    print("\n");
+    i1 = Math.floor((y - 1500) / 100);
+    // Test for date before current calendar.
+    if (y - 1582 < 0) {
+        print("NOT PREPARED TO GIVE DAY OF WEEK PRIOR TO MDLXXXII.\n");
+    } else {
+        a = i1 * 5 + (i1 + 3) / 4;
+        i2 = Math.floor(a - fnb(a) * 7);
+        y2 = Math.floor(y / 100);
+        y3 = Math.floor(y - y2 * 100);
+        a = y3 / 4 + y3 + d + t[m] + i2;
+        b = Math.floor(a - fnb(a) * 7) + 1;
+        if (m <= 2) {
+            if (y3 != 0) {
+                t1 = Math.floor(y - fna(y) * 4);
+            } else {
+                a = i1 - 1;
+                t1 = Math.floor(a - fna(a) * 4);
+            }
+            if (t1 == 0) {
+                if (b == 0)
+                    b = 6;
+                b--;
+            }
+        }
+        if (b == 0)
+            b = 7;
+        if ((y1 * 12 + m1) * 31 + d1 < (y * 12 + m) * 31 + d) {
+            print(m + "/" + d + "/" + y + " WILL BE A ");
+        } else if ((y1 * 12 + m1) * 31 + d1 == (y * 12 + m) * 31 + d) {
+            print(m + "/" + d + "/" + y + " IS A ");
+        } else {
+            print(m + "/" + d + "/" + y + " WAS A ");
+        }
+        switch (b) {
+            case 1: print("SUNDAY.\n"); break;
+            case 2: print("MONDAY.\n"); break;
+            case 3: print("TUESDAY.\n"); break;
+            case 4: print("WEDNESDAY.\n"); break;
+            case 5: print("THURSDAY.\n"); break;
+            case 6:
+                if (d == 13) {
+                    print("FRIDAY THE THIRTEENTH---BEWARE!\n");
+                } else {
+                    print("FRIDAY.\n");
+                }
+                break;
+            case 7: print("SATURDAY.\n"); break;
+        }
+        if ((y1 * 12 + m1) * 31 + d1 != (y * 12 + m) * 31 + d) {
+            i5 = y1 - y;
+            print("\n");
+            i6 = m1 - m;
+            i7 = d1 - d;
+            if (i7 < 0) {
+                i6--;
+                i7 += 30;
+            }
+            if (i6 < 0) {
+                i5--;
+                i6 += 12;
+            }
+            if (i5 >= 0) {
+                if (i7 == 0 && i6 == 0)
+                    print("***HAPPY BIRTHDAY***\n");
+                print("                        \tYEARS\tMONTHS\tDAYS\n");
+                print("                        \t-----\t------\t----\n");
+                print("YOUR AGE (IF BIRTHDATE) \t" + i5 + "\t" + i6 + "\t" + i7 + "\n");
+                a8 = (i5 * 365) + (i6 * 30) + i7 + Math.floor(i6 / 2);
+                k5 = i5;
+                k6 = i6;
+                k7 = i7;
+                // Calculate retirement date.
+                e = y + 65;
+                // Calculate time spent in the following functions.
+                print("YOU HAVE SLEPT \t\t\t");
+                time_spent(0.35, a8);
+                print("YOU HAVE EATEN \t\t\t");
+                time_spent(0.17, a8);
+                if (k5 <= 3) {
+                    print("YOU HAVE PLAYED \t\t\t");
+                } else if (k5 <= 9) {
+                    print("YOU HAVE PLAYED/STUDIED \t\t");
+                } else {
+                    print("YOU HAVE WORKED/PLAYED \t\t");
+                }
+                time_spent(0.23, a8);
+                if (k6 == 12) {
+                    k5++;
+                    k6 = 0;
+                }
+                print("YOU HAVE RELAXED \t\t" + k5 + "\t" + k6 + "\t" + k7 + "\n");
+                print("\n");
+                print(tab(16) + "***  YOU MAY RETIRE IN " + e + " ***\n");
+                print("\n");
+            }
+        }
+    }
+    print("\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("\n");
+}
+
+main();
diff --git a/96 Word/javascript/word.html b/96 Word/javascript/word.html
new file mode 100644
index 00000000..ddc88134
--- /dev/null
+++ b/96 Word/javascript/word.html	
@@ -0,0 +1,9 @@
+
+
+WORD
+
+
+

+
+
+
diff --git a/96 Word/javascript/word.js b/96 Word/javascript/word.js
new file mode 100644
index 00000000..6e5acf50
--- /dev/null
+++ b/96 Word/javascript/word.js	
@@ -0,0 +1,150 @@
+// WORD
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var words = ["DINKY", "SMOKE", "WATER", "GLASS", "TRAIN",
+             "MIGHT", "FIRST", "CANDY", "CHAMP", "WOULD",
+             "CLUMP", "DOPEY"];
+
+var s = [];
+var a = [];
+var l = [];
+var d = [];
+var p = [];
+
+// Main control section
+async function main()
+{
+    print(tab(33) + "WORD\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("I AM THINKING OF A WORD -- YOU GUESS IT.  I WILL GIVE YOU\n");
+    print("CLUE TO HELP YO GET IT.  GOOD LUCK!!\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("\n");
+        print("\n");
+        print("YOU ARE STARTING A NEW GAME...\n");
+        n = words.length;
+        ss = words[Math.floor(Math.random() * n)];
+        g = 0;
+        s[0] = ss.length;
+        for (i = 1; i <= ss.length; i++)
+            s[i] = ss.charCodeAt(i - 1);
+        for (i = 1; i <= 5; i++)
+            a[i] = 45;
+        for (j = 1; j <= 5; j++)
+            p[j] = 0;
+        while (1) {
+            print("GUESS A FIVE LETTER WORD");
+            ls = await input();
+            g++;
+            if (ss == ls)
+                break;
+            for (i = 1; i <= 7; i++)
+                p[i] = 0;
+            l[0] = ls.length;
+            for (i = 1; i <= ls.length; i++) {
+                l[i] = ls.charCodeAt(i - 1);
+            }
+            if (l[1] == 63) {
+                print("THE SECRET WORD IS " + ss + "\n");
+                print("\n");
+                break;
+            }
+            if (l[0] != 5) {
+                print("YOU MUST GUESS A 5 LETTER WORD.  START AGAIN.\n");
+                print("\n");
+                g--;
+                continue;
+            }
+            m = 0;
+            q = 1;
+            for (i = 1; i <= 5; i++) {
+                for (j = 1; j <= 5; j++) {
+                    if (s[i] == l[j]) {
+                        p[q] = l[j];
+                        q++;
+                        if (i == j)
+                            a[j] = l[j];
+                        m++;
+                    }
+                }
+            }
+            a[0] = 5;
+            p[0] = m;
+            as = "";
+            for (i = 1; i <= a[0]; i++)
+                as += String.fromCharCode(a[i]);
+            ps = "";
+            for (i = 1; i <= p[0]; i++)
+                ps += String.fromCharCode(p[i]);
+            print("THERE WERE " + m + " MATCHES AND THE COMMON LETTERS WERE... " + ps + "\n");
+            print("FROM THE EXACT LETTER MATCHES, YOU KNOW............ " + as + "\n");
+            if (as == ss) {
+                ls = as;
+                break;
+            }
+            if (m <= 1) {
+                print("\n");
+                print("IF YOU GIVE UP, TYPE '?' FOR YOUR NEXT GUESS.\n");
+                print("\n");
+            }
+        }
+        if (ss == ls) {
+            print("YOU HAVE GUESSED THE WORD.  IT TOOK " + g + " GUESSES!\n");
+            print("\n");
+        } else {
+            continue;
+        }
+        print("WANT TO PLAY AGAIN");
+        qs = await input();
+        if (qs != "YES")
+            break;
+    }
+}
+
+main();
diff --git a/96 Word/word.bas b/96 Word/word.bas
index 8435310f..46e69061 100644
--- a/96 Word/word.bas	
+++ b/96 Word/word.bas	
@@ -24,7 +24,7 @@
 150 PRINT "GUESS A FIVE LETTER WORD";
 160 INPUT L$
 170 G=G+1
-172 IF S$=G$ THEN 500
+172 IF S$=L$ THEN 500
 173 FOR I=1 TO 7: P(I)=0: NEXT I
 175 L(0)=LEN(L$)
 180 FOR I=1 TO LEN(L$): L(I)=ASC(MID$(L$,I,1)): NEXT I

From edef05af17f03ed1dd2a049fed1ed15bf3675a43 Mon Sep 17 00:00:00 2001
From: Frank Palazzolo 
Date: Tue, 23 Feb 2021 13:53:01 -0500
Subject: [PATCH 011/749] Added python version of AMAZING, with bug fix from
 BASIC version

---
 02 Amazing/python/amazing.py | 121 +++++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)
 create mode 100644 02 Amazing/python/amazing.py

diff --git a/02 Amazing/python/amazing.py b/02 Amazing/python/amazing.py
new file mode 100644
index 00000000..dc9da380
--- /dev/null
+++ b/02 Amazing/python/amazing.py	
@@ -0,0 +1,121 @@
+import random
+            
+# Python translation by Frank Palazzolo - 2/2021
+    
+print(' '*28+'AMAZING PROGRAM')
+print(' '*15+'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY')
+print()
+print()
+print()
+
+while True:
+    width, length = input('What are your width and length?').split(',')
+    width = int(width)
+    length = int(length)
+    if width != 1 and length != 1:
+        break
+    print('Meaningless dimensions. Try again.')
+
+# Build two 2D arrays
+#
+# used:
+#   Initially set to zero, unprocessed cells
+#   Filled in with consecutive non-zero numbers as cells are processed
+#
+# walls:
+#   Initially set to zero, (all paths blocked)
+#   Remains 0 if there is no exit down or right
+#   Set to 1 if there is an exit down
+#   Set to 2 if there is an exit right
+#   Set to 3 if there are exits down and right
+
+used = []
+walls = []
+for i in range(length):
+    used.append([0]*width)
+    walls.append([0]*width)
+
+# Use direction variables with nice names
+GO_LEFT,GO_UP,GO_RIGHT,GO_DOWN=[0,1,2,3]
+# Give Exit directions nice names
+EXIT_DOWN = 1
+EXIT_RIGHT = 2
+
+# Pick a random entrance, mark as used
+enter_col=random.randint(0,width-1)
+row,col=0,enter_col
+count=1
+used[row][col]=count
+count=count+1
+
+while count!=width*length+1:
+    # remove possible directions that are blocked or
+    # hit cells that we have already processed
+    possible_dirs = [GO_LEFT,GO_UP,GO_RIGHT,GO_DOWN]
+    if col==0 or used[row][col-1]!=0:
+        possible_dirs.remove(GO_LEFT)
+    if row==0 or used[row-1][col]!=0:
+        possible_dirs.remove(GO_UP)
+    if col==width-1 or used[row][col+1]!=0: 
+        possible_dirs.remove(GO_RIGHT)
+    if row==length-1 or used[row+1][col]!=0:
+        possible_dirs.remove(GO_DOWN)   
+
+    # If we can move in a direction, move and make opening
+    if len(possible_dirs)!=0:
+        direction=random.choice(possible_dirs) 
+        if direction==GO_LEFT:
+            col=col-1
+            walls[row][col]=EXIT_RIGHT
+        elif direction==GO_UP:
+            row=row-1 
+            walls[row][col]=EXIT_DOWN
+        elif direction==GO_RIGHT:
+            walls[row][col]=walls[row][col]+EXIT_RIGHT    
+            col=col+1
+        elif direction==GO_DOWN:
+            walls[row][col]=walls[row][col]+EXIT_DOWN
+            row=row+1
+        used[row][col]=count
+        count=count+1
+    # otherwise, move to the next used cell, and try again
+    else:
+        while True:
+            if col!=width-1:
+                col=col+1
+            elif row!=length-1:
+                row,col=row+1,0
+            else:
+                row,col=0,0
+            if used[row][col]!=0:
+                break
+
+# Add a random exit
+col=random.randint(0,width-1)
+row=length-1
+walls[row][col]=walls[row][col]+1
+    
+# Print the maze
+for col in range(width):
+    if col==enter_col:
+        print('.  ',end='')
+    else:
+        print('.--',end='')
+print('.')
+for row in range(length):
+    print('I',end='')
+    for col in range(width):
+        if walls[row][col]<2:
+            print('  I',end='')
+        else:
+            print('   ',end='')
+    print()
+    for col in range(width):
+        if walls[row][col]==0 or walls[row][col]==2:
+            print(':--',end='')
+        else:
+            print(':  ',end='')    
+    print('.')
+
+        
+        
\ No newline at end of file

From ab670b1fca59c238bee86af6514dce2868163ae3 Mon Sep 17 00:00:00 2001
From: Kyle Hale 
Date: Tue, 23 Feb 2021 13:32:51 -0600
Subject: [PATCH 012/749] Uploading mastermind.py

in beta, several TODOs for some of the control, error handling of user input
---
 60 Mastermind/python/mastermind.py | 253 +++++++++++++++++++++++++++++
 1 file changed, 253 insertions(+)
 create mode 100644 60 Mastermind/python/mastermind.py

diff --git a/60 Mastermind/python/mastermind.py b/60 Mastermind/python/mastermind.py
new file mode 100644
index 00000000..adb62be3
--- /dev/null
+++ b/60 Mastermind/python/mastermind.py	
@@ -0,0 +1,253 @@
+import random
+
+def main():
+
+    global colors, color_letters, num_positions, num_colors, human_score, computer_score
+    colors = ["BLACK", "WHITE", "RED", "GREEN", "ORANGE", "YELLOW", "PURPLE", "TAN"]
+    color_letters = "BWRGOYPT"
+    
+    num_colors = 100
+    human_score = 0 
+    computer_score = 0
+
+    # get user inputs for game conditions
+    print("Mastermind")
+    print('Creative Computing Morristown, New Jersey')
+    while (num_colors > 8):
+        num_colors = int(input("Number of colors (max 8): ")) # C9 in BASIC
+    # TODO no more than 8 colors
+    num_positions = int(input("Number of positions: ")) # P9 in BASIC
+    num_rounds = int(input("Number of rounds: ")) # R9 in BASIC
+    possibilities = num_colors**num_positions
+    all_possibilities = [1] * possibilities
+    
+    print("Number of possibilities {}".format(possibilities))
+    #TODO tab fixed formatting
+    print('Color     Letter')
+    print('=====     ======')
+    for element in range(0, num_colors):
+        print("{}     {}".format(colors[element], colors[element][0]))
+    
+    num_moves = 1
+    guesses = []
+    current_round = 1
+    
+    while current_round <= num_rounds:
+        print('Round number {}'.format(current_round))
+        num_moves = 1
+        turn_over = False
+        print('Guess my combination ...')
+        answer = int(possibilities * random.random()) # A in BASIC
+        numeric_answer = init_possibility()
+        for i in range(0, answer):
+            numeric_answer = get_possibility(numeric_answer)
+        #debug
+        print("{} - {}".format(numeric_answer, make_human_readable(numeric_answer)))
+        #human_readable_answer = make_human_readable(numeric_answer)
+        while (num_moves < 10 and not(turn_over)):
+            print('Move # {} Guess : '.format(num_moves))
+            user_command = input('Guess ')
+            if user_command == "BOARD":
+                print_board(guesses) #2000
+            elif user_command == "QUIT":
+                quit_game(numeric_answer) #2500
+                quit()
+            elif len(user_command) != num_positions: #410
+                print("BAD NUMBER OF POSITIONS")
+            else:
+                invalid_letters = get_invalid_letters(user_command)
+                if (invalid_letters > ""):
+                    print("INVALID GUESS: {}".format(invalid_letters))
+                else:
+                    guess_results = compare_two_positions(user_command, make_human_readable(numeric_answer))
+                    print("Results: {}".format(guess_results))
+                    if (guess_results[1] == num_positions): # correct guess
+                        turn_over = True
+                        print("You guessed it in {} moves!".format(num_moves))
+                        human_score = human_score + num_moves
+                        print_score()
+                    else:
+                        print("You have {} blacks and {} whites".format(guess_results[1], guess_results[2]))
+                        num_moves = num_moves + 1
+                        guesses.append(guess_results)
+        if (not(turn_over)): # RAN OUT OF MOVES
+            print ("YOU RAN OUT OF MOVES! THAT'S ALL YOU GET!")
+            print("THE ACTUAL COMBINATION WAS: {}".format(make_human_readable(numeric_answer)))
+            human_score = human_score + num_moves
+            print_score()
+       
+        # COMPUTER TURN
+        turn_over = False
+        all_possibilities = [1] * possibilities
+        num_moves = 1
+        print ("NOW I GUESS. THINK OF A COMBINATION.")
+        player_ready = input("HIT RETURN WHEN READY: ")
+        while (num_moves < 10 and not(turn_over)):
+            foundGuess = False
+            computer_guess = int(possibilities * random.random())
+            if (all_possibilities[computer_guess] == 1): # random guess is possible, use it
+                foundGuess = True
+                guess = computer_guess
+            else:
+                for i in range (computer_guess, possibilities):
+                    if (all_possibilities[i] == 1):
+                        foundGuess = True
+                        guess = i
+                        break
+                if (not(foundGuess)):
+                    for i in range (0, computer_guess):
+                        if (all_possibilities[i] == 1):
+                            foundGuess = True
+                            guess = i
+                            break
+            if (not(foundGuess)): # inconsistent info from user
+                print('YOU HAVE GIVEN ME INCONSISTENT INFORMATION.')
+                print('TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL.')
+                quit()
+                # TODO start computer turn over
+            else:
+                numeric_guess = init_possibility()
+                for i in range(0, guess):
+                    numeric_guess = get_possibility(numeric_guess)
+                human_readable_guess = make_human_readable(numeric_guess)
+                print('My guess is: {}'.format(human_readable_guess))
+                blacks, whites = input("Enter blacks, whites (e.g. 1,2): ").split(",")
+                blacks = int(blacks)
+                whites = int(whites)
+                if (blacks == num_positions): #Correct guess
+                    print('I GOT IT IN {} moves'.format(num_moves))
+                    turn_over = True
+                    computer_score = computer_score + num_moves
+                    print_score()
+                else:
+                    num_moves += 1
+                    for i in range (0, possibilities):   
+                        if(all_possibilities[i] == 0): #already ruled out
+                            continue
+                        numeric_possibility = init_possibility()
+                        for j in range (0, i):
+                            numeric_possibility = get_possibility(numeric_possibility)
+                        human_readable_possibility = make_human_readable(numeric_possibility) #4000
+                        comparison = compare_two_positions(human_readable_possibility, human_readable_guess)
+                        print("{} {} {}".format(human_readable_guess, human_readable_possibility, comparison))
+                        if ((blacks != comparison[1]) or (whites != comparison[2])):
+                            all_possibilities[i] = 0
+        if (not(turn_over)): # COMPUTER DID NOT GUESS
+            print("I USED UP ALL MY MOVES!")
+            print("I GUESS MY CPU IS JUST HAVING AN OFF DAY.")
+            computer_score = computer_score + num_moves
+            print_score()
+        current_round += 1
+
+def get_invalid_letters(user_command):
+    #TODO
+    return ""
+
+def validate_human_guess(user_input):
+   
+    guess_results = compare_two_positions(user_input, answer)
+    return guess_results
+
+#2000
+def print_board(guesses):
+    print("Board")
+    print("Move Guess Black White")
+    for guess in guesses:
+        print('{} {} {} {}'.format(guess[0], guess[0], guess[1], guess[2]))
+
+#2500
+def quit_game(numeric_answer):
+    human_readable_answer = make_human_readable(numeric_answer)
+    print('QUITTER! MY COMBINATION WAS: {}'.format(human_readable_answer))
+    print('GOOD BYE')
+
+#3000
+def init_possibility():
+    possibility = [0] * num_positions
+    return possibility
+
+#3500
+def get_possibility(possibility):
+    if possibility[0] > 0: #3530
+            current_position = 0 # Python arrays are zero-indexed
+            while (True):
+                if possibility[current_position] < num_colors:
+                    possibility[current_position] += 1
+                    return possibility
+                else:
+                    possibility[current_position] = 1
+                    current_position += 1
+    else: #3524
+        possibility = [1] * num_positions
+    return possibility
+
+#4000
+def convert_q_to_a():
+    return map_num_to_vals(q, color_letters)
+
+#4500
+def compare_two_positions(guess, answer):
+    f = 0
+    b = 0
+    w = 0
+    initial_guess = guess
+    for pos in range(0, num_positions):
+        if (guess[pos] != answer[pos]):
+            for pos2 in range(0, num_positions):
+                if not(guess[pos] != answer[pos2] or guess[pos2] == answer[pos2]): # correct color but not correct place
+                    w = w + 1
+                    answer = answer[:pos2] + chr(f) + answer[pos2+1:]
+                    guess = guess[:pos] + chr(f+1) + guess[pos+1:]
+                    f = f + 2
+        else: #correct color and placement
+            b = b + 1
+            # THIS IS DEVIOUSLY CLEVER
+            guess = guess[:pos] + chr(f+1) + guess[pos+1:]
+            answer = answer[:pos] + chr(f) + answer[pos+1:]
+            f = f + 2
+    return [initial_guess, b, w]
+    
+    
+
+
+
+#5000
+def print_score(is_final_score=False):
+    if (is_final_score):
+        print("GAME OVER")
+        print("FINAL SCORE:")
+    else:
+        print("SCORE:")
+    print("     COMPUTER {}".format(computer_score))
+    print("     HUMAN    {}".format(human_score))
+
+#5500
+def convert_q_to_g():
+    return map_num_to_vals(q, g)
+
+#6000
+def convert_q_to_h():
+    return map_num_to_vals(q, h)
+
+#6500
+def copy_g_to_h():
+        g = h
+
+def make_human_readable(num):
+    retval = ''
+    for z in range(0, len(num)):
+        retval = retval + color_letters[int(num[z])]
+    return retval
+
+
+def map_num_to_vals(num, v):
+    retval = ''
+    print(len(num))
+    for z in range(0, len(num)):
+        print(num[z])
+        print(v[int(num[z])])
+        retval = retval + v[int(num[z])]
+    return retval
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file

From e904c279e4c0cb183173ba739edddb5f91822dbd Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Tue, 23 Feb 2021 18:40:07 -0300
Subject: [PATCH 013/749] Added main logic of slots

---
 80 Slots/python/slots.py | 109 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100644 80 Slots/python/slots.py

diff --git a/80 Slots/python/slots.py b/80 Slots/python/slots.py
new file mode 100644
index 00000000..d650d8f4
--- /dev/null
+++ b/80 Slots/python/slots.py	
@@ -0,0 +1,109 @@
+from random import choices
+from collections import Counter
+import sys
+
+
+def initial_message():
+    print(" "*30 + "Slots")
+    print(" "*15 + "Creative Computing Morrison, New Jersey")
+    print("\n"*3)
+    print("You are in the H&M Casino, in front of one of our")
+    print("one-arm Bandits. Bet from $1 to $100.")
+    print("To pull the arm, punch the return key after making your bet.")
+
+
+def input_betting():
+    print("\n")
+    b = -1
+    while b < 1 or b > 100:
+        b = int(input("Your bet:"))
+        if b > 100:
+            print("House limits are $100")
+        elif b < 1:
+            print("Minium bet is $1")
+    beeping()
+    return int(b)
+
+
+def beeping():
+    # Function to produce a beep sound.
+    # In the original program is the subroutine at 1270
+    for _ in range(5):
+        sys.stdout.write('\a')
+        sys.stdout.flush()
+
+
+def spin_wheels():
+    possible_fruits = ["Bar", "Bell", "Orange", "Lemon", "Plum", "Cherry"]
+    wheel = choices(possible_fruits, k=3)
+
+    print(*wheel)
+    beeping()
+
+    return wheel
+
+
+def adjust_profits(wheel, m, profits):
+    # we remove the duplicates
+    s = set(wheel)
+
+    if len(s) == 1:
+        # the three fruits are the same
+        fruit = s.pop()
+
+        if fruit == "Bar":
+            print("\n***Jackpot***")
+            profits = (((100*m)+m)+profits)
+        else:
+            print("\n**Top Dollar**")
+            profits = (((10*m)+m)+profits)
+
+        print("You Won!")
+    elif len(s) == 2:
+        # two fruits are equal
+        c = Counter(wheel)
+        # we get the fruit that appears two times
+        fruit = sorted(c.items(), key=lambda x: x[1], reverse=True)[0][0]
+
+        if fruit == "Bar":
+            print("\n*Double Bar*")
+            profits = (((5*m)+m)+profits)
+        else:
+            print("\nDouble!!")
+            profits = (((2*m)+m)+profits)
+
+        print("You Won!")
+    else:
+        # three different fruits
+        print("\nYou Lost.")
+        profits = profits - m
+
+    return profits
+
+
+def final_message(profits):
+    if profits < 0:
+        print("Pay up!  Please leave your money on the terminal")
+    elif profits == 0:
+        print("Hey, You broke even.")
+    else:
+        print("Collect your winings from the H&M cashier.")
+
+
+profits = 0
+keep_betting = True
+
+initial_message()
+while keep_betting:
+    m = input_betting()
+    w = spin_wheels()
+    profits = adjust_profits(w, m, profits)
+
+    print("Your standings are ${}".format(profits))
+    answer = input("Again?")
+
+    if not answer[0].lower() == "y":
+        keep_betting = False
+
+
+final_message(profits)

From e74fd2202e9db453ca3967fc651ed82625cedb67 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Tue, 23 Feb 2021 19:00:37 -0300
Subject: [PATCH 014/749] Added input error handling

---
 80 Slots/python/slots.py | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/80 Slots/python/slots.py b/80 Slots/python/slots.py
index d650d8f4..fbd36184 100644
--- a/80 Slots/python/slots.py	
+++ b/80 Slots/python/slots.py	
@@ -16,7 +16,10 @@ def input_betting():
     print("\n")
     b = -1
     while b < 1 or b > 100:
-        b = int(input("Your bet:"))
+        try:
+            b = int(input("Your bet:"))
+        except ValueError:
+            b = -1
         if b > 100:
             print("House limits are $100")
         elif b < 1:
@@ -27,7 +30,7 @@ def input_betting():
 
 def beeping():
     # Function to produce a beep sound.
-    # In the original program is the subroutine at 1270
+    # In the original program is the subroutine at line 1270
     for _ in range(5):
         sys.stdout.write('\a')
         sys.stdout.flush()
@@ -102,8 +105,10 @@ while keep_betting:
     print("Your standings are ${}".format(profits))
     answer = input("Again?")
 
-    if not answer[0].lower() == "y":
+    try:
+        if not answer[0].lower() == "y":
+            keep_betting = False
+    except IndexError:
         keep_betting = False
 
-
 final_message(profits)

From 2d445cab5005f461c780a06946c92fd639464d78 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Tue, 23 Feb 2021 20:03:44 -0300
Subject: [PATCH 015/749] Added history and porting comments

---
 80 Slots/python/slots.py | 45 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/80 Slots/python/slots.py b/80 Slots/python/slots.py
index fbd36184..fbae665b 100644
--- a/80 Slots/python/slots.py	
+++ b/80 Slots/python/slots.py	
@@ -1,3 +1,36 @@
+########################################################
+#
+# Slots
+#
+# From Basic Computer Games (1978)
+#
+#    "The slot machine or one-arm bandit is a mechanical
+#   device that will absorb coins just about as fast as
+#   you can feed it. After inserting a coin, you pull a
+#   handle that sets three indepent reels spining. If the
+#   reels stop with certain symbols appearing in the pay
+#   line, you get a certain payoff. The original slot
+#   machine, called the Liberty bell, was invented in 1895
+#   by Charles Fey in San Francisco. Fey refused to sell
+#   or lease the manufacturing rights, so H.S. Mills in
+#   Chicago built a similar, but much improved, machine
+#   called the Operators Bell. This has survived nearly
+#   unchanged to today.
+#     On the operators Bell and other standard slot
+#   machines, there are 20 symbols on each wheel but they
+#   are not distributed evenly among the objects(cherries,
+#   bar, apples, etc). Of the 8000 possible combinations,
+#   the expected payoff(to the player) is 7049 or $89.11
+#   for every $100.00 put in, one of the lowest expected
+#   payoffs of all casino games.
+#     In the program here, the payoff is considerably more
+#   liberal; indeed it appears to favor the player by 11%
+#   -- i.e., an expected payoff of $111 for each $100 bet."
+#     The program was originally written by Fred Mirabelle
+#   and Bob Harper
+#
+########################################################
+
 from random import choices
 from collections import Counter
 import sys
@@ -112,3 +145,15 @@ while keep_betting:
         keep_betting = False
 
 final_message(profits)
+
+
+######################################################################
+#
+# Porting notes
+#
+#   The selections of the fruits(Bar, apples, lemon, etc.) are made
+#   with equal probability, accordingly to random.choices documentation.
+#   It could be added a weights list to the function and therefore
+#   adjust the expected payoff
+#
+######################################################################

From a7182ed402f665bbbafa3c6addb055b880f2e803 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Wed, 24 Feb 2021 11:48:12 +1030
Subject: [PATCH 016/749] Java version of the Bug Basic game

---
 16 Bug/java/src/Bug.java         | 254 +++++++++++++++++++++
 16 Bug/java/src/BugGame.java     |  10 +
 16 Bug/java/src/ComputerBug.java |  15 ++
 16 Bug/java/src/Insect.java      | 363 +++++++++++++++++++++++++++++++
 16 Bug/java/src/PlayerBug.java   |  18 ++
 5 files changed, 660 insertions(+)
 create mode 100644 16 Bug/java/src/Bug.java
 create mode 100644 16 Bug/java/src/BugGame.java
 create mode 100644 16 Bug/java/src/ComputerBug.java
 create mode 100644 16 Bug/java/src/Insect.java
 create mode 100644 16 Bug/java/src/PlayerBug.java

diff --git a/16 Bug/java/src/Bug.java b/16 Bug/java/src/Bug.java
new file mode 100644
index 00000000..626615de
--- /dev/null
+++ b/16 Bug/java/src/Bug.java	
@@ -0,0 +1,254 @@
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * Game of Bug
+ * 

+ * Based on the Basic game of Bug here + * https://github.com/coding-horror/basic-computer-games/blob/main/16%20Bug/bug.bas + *

+ * 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 Bug { + + // Dice roll + public static final int SIX = 6; + + private enum GAME_STATE { + START, + PLAYER_TURN, + COMPUTER_TURN, + CHECK_FOR_WINNER, + GAME_OVER + } + + // Used for keyboard input + private final Scanner kbScanner; + + // Current game state + private GAME_STATE gameState; + + + private final Insect playersBug; + + private final Insect computersBug; + + // Used to show the result of dice roll. + private final String[] ROLLS = new String[]{"BODY", "NECK", "HEAD", "FEELERS", "TAIL", "LEGS"}; + + public Bug() { + + playersBug = new PlayerBug(); + computersBug = new ComputerBug(); + + gameState = GAME_STATE.START; + + // Initialise kb scanner + kbScanner = new Scanner(System.in); + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + // Show an introduction the first time the game is played. + // And optionally instructions. + case START: + intro(); + if (!noEntered(displayTextAndGetInput("DO YOU WANT INSTRUCTIONS? "))) { + instructions(); + } + + gameState = GAME_STATE.PLAYER_TURN; + break; + + case PLAYER_TURN: + int playersRoll = randomNumber(); + System.out.println("YOU ROLLED A " + playersRoll + "=" + ROLLS[playersRoll - 1]); + switch (playersRoll) { + case 1: + System.out.println(playersBug.addBody()); + break; + case 2: + System.out.println(playersBug.addNeck()); + break; + case 3: + System.out.println(playersBug.addHead()); + break; + case 4: + System.out.println(playersBug.addFeelers()); + break; + case 5: + System.out.println(playersBug.addTail()); + break; + case 6: + System.out.println(playersBug.addLeg()); + break; + } + + gameState = GAME_STATE.COMPUTER_TURN; + break; + + case COMPUTER_TURN: + int computersRoll = randomNumber(); + System.out.println("I ROLLED A " + computersRoll + "=" + ROLLS[computersRoll - 1]); + switch (computersRoll) { + case 1: + System.out.println(computersBug.addBody()); + break; + case 2: + System.out.println(computersBug.addNeck()); + break; + case 3: + System.out.println(computersBug.addHead()); + break; + case 4: + System.out.println(computersBug.addFeelers()); + break; + case 5: + System.out.println(computersBug.addTail()); + break; + case 6: + System.out.println(computersBug.addLeg()); + break; + } + + gameState = GAME_STATE.CHECK_FOR_WINNER; + break; + + case CHECK_FOR_WINNER: + boolean gameOver = false; + + if (playersBug.complete()) { + System.out.println("YOUR BUG IS FINISHED."); + gameOver = true; + } else if (computersBug.complete()) { + System.out.println("MY BUG IS FINISHED."); + gameOver = true; + } + + if (noEntered(displayTextAndGetInput("DO YOU WANT THE PICTURES? "))) { + gameState = GAME_STATE.PLAYER_TURN; + } else { + System.out.println("*****YOUR BUG*****"); + System.out.println(); + draw(playersBug); + + System.out.println(); + System.out.println("*****MY BUG*****"); + System.out.println(); + draw(computersBug); + gameState = GAME_STATE.PLAYER_TURN; + + if (gameOver) { + System.out.println("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!"); + gameState = GAME_STATE.GAME_OVER; + } + } + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + /** + * Draw the bug (player or computer) based on what has + * already been added to it. + * + * @param bug The bug to be drawn. + */ + private void draw(Insect bug) { + ArrayList insectOutput = bug.draw(); + for (String s : insectOutput) { + System.out.println(s); + } + } + + /** + * Display an intro + */ + private void intro() { + System.out.println("BUG"); + System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THE GAME BUG"); + System.out.println("I HOPE YOU ENJOY THIS GAME."); + } + + private void instructions() { + System.out.println("THE OBJECT OF BUG IS TO FINISH YOUR BUG BEFORE I FINISH"); + System.out.println("MINE. EACH NUMBER STANDS FOR A PART OF THE BUG BODY."); + System.out.println("I WILL ROLL THE DIE FOR YOU, TELL YOU WHAT I ROLLED FOR YOU"); + System.out.println("WHAT THE NUMBER STANDS FOR, AND IF YOU CAN GET THE PART."); + System.out.println("IF YOU CAN GET THE PART I WILL GIVE IT TO YOU."); + System.out.println("THE SAME WILL HAPPEN ON MY TURN."); + System.out.println("IF THERE IS A CHANGE IN EITHER BUG I WILL GIVE YOU THE"); + System.out.println("OPTION OF SEEING THE PICTURES OF THE BUGS."); + System.out.println("THE NUMBERS STAND FOR PARTS AS FOLLOWS:"); + System.out.println("NUMBER\tPART\tNUMBER OF PART NEEDED"); + System.out.println("1\tBODY\t1"); + System.out.println("2\tNECK\t1"); + System.out.println("3\tHEAD\t1"); + System.out.println("4\tFEELERS\t2"); + System.out.println("5\tTAIL\t1"); + System.out.println("6\tLEGS\t6"); + System.out.println(); + + } + + /** + * Checks whether player entered N or NO to a question. + * + * @param text player string from kb + * @return true if N or NO was entered, otherwise false + */ + private boolean noEntered(String text) { + return stringIsAnyValue(text, "N", "NO"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + // Cycle through the variable number of values and test each + for (String val : values) { + if (text.equalsIgnoreCase(val)) { + return true; + } + } + + // no matches + return false; + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Generate random number + * + * @return random number + */ + private int randomNumber() { + return (int) (Math.random() + * (SIX) + 1); + } +} \ No newline at end of file diff --git a/16 Bug/java/src/BugGame.java b/16 Bug/java/src/BugGame.java new file mode 100644 index 00000000..074ff45e --- /dev/null +++ b/16 Bug/java/src/BugGame.java @@ -0,0 +1,10 @@ + + +public class BugGame { + + public static void main(String[] args) { + + Bug bug = new Bug(); + bug.play(); + } +} diff --git a/16 Bug/java/src/ComputerBug.java b/16 Bug/java/src/ComputerBug.java new file mode 100644 index 00000000..fe232364 --- /dev/null +++ b/16 Bug/java/src/ComputerBug.java @@ -0,0 +1,15 @@ +public class ComputerBug extends Insect { + + // Create messages specific to the computer player. + + public ComputerBug() { + // Call superclass constructor for initialization. + super(); + addMessages(new String[]{"I GET A FEELER.", "I HAVE " + MAX_FEELERS + " FEELERS ALREADY.", "I DO NOT HAVE A HEAD."}, PARTS.FEELERS); + addMessages(new String[]{"I NEEDED A HEAD.", "I DO NOT NEED A HEAD.", "I DO NOT HAVE A NECK."}, PARTS.HEAD); + addMessages(new String[]{"I NOW HAVE A NECK.", "I DO NOT NEED A NECK.", "I DO NOT HAVE A BODY."}, PARTS.NECK); + addMessages(new String[]{"I NOW HAVE A BODY.", "I DO NOT NEED A BODY."}, PARTS.BODY); + addMessages(new String[]{"I NOW HAVE A TAIL.", "I DO NOT NEED A TAIL.", "I DO NOT HAVE A BODY."}, PARTS.TAIL); + addMessages(new String[]{"I NOW HAVE ^^^" + " LEG", "I HAVE " + MAX_LEGS + " FEET.", "I DO NOT HAVE A BODY."}, PARTS.LEGS); + } +} diff --git a/16 Bug/java/src/Insect.java b/16 Bug/java/src/Insect.java new file mode 100644 index 00000000..08e9414f --- /dev/null +++ b/16 Bug/java/src/Insect.java @@ -0,0 +1,363 @@ +import java.util.ArrayList; +import java.util.Arrays; + +/** + * This tracks the insect (bug) and has methods to + * add body parts, create an array of output so it + * can be drawn and to determine if a bug is complete. + * N.B. This is a super class for ComputerBug and PlayerBug + */ +public class Insect { + + public static final int MAX_FEELERS = 2; + public static final int MAX_LEGS = 6; + + public static final int ADDED = 0; + public static final int NOT_ADDED = 1; + public static final int MISSING = 2; + + // Various parts of the bug + public enum PARTS { + FEELERS, + HEAD, + NECK, + BODY, + TAIL, + LEGS + } + + // Tracks what parts of the bug have been added + private boolean body; + private boolean neck; + private boolean head; + private int feelers; + private boolean tail; + private int legs; + + // Messages about for various body parts + // These are set in the subclass ComputerBug or PlayerBug + private String[] bodyMessages; + private String[] neckMessages; + private String[] headMessages; + private String[] feelerMessages; + private String[] tailMessages; + private String[] legMessages; + + public Insect() { + init(); + } + + /** + * Add a body to the bug if there is not one already added. + * + * @return return an appropriate message about the status of the operation. + */ + public String addBody() { + + boolean currentState = false; + + if (!body) { + body = true; + currentState = true; + } + + return addBodyMessage(currentState); + } + + /** + * Create output based on adding the body or it being already added previously + * + * @return contains the output message + */ + + private String addBodyMessage(boolean wasAdded) { + + // Return the appropriate message depending on whether the + // body was added or not. + if (wasAdded) { + return bodyMessages[ADDED]; + } else { + return bodyMessages[NOT_ADDED]; + } + } + + /** + * Add a neck if a) a body has previously been added and + * b) a neck has not previously been added. + * + * @return text containing the status of the operation + */ + public String addNeck() { + + int status = NOT_ADDED; // Default is not added + + if (!body) { + // No body, cannot add a neck + status = MISSING; + } else if (!neck) { + neck = true; + status = ADDED; + } + + return neckMessages[status]; + } + + /** + * Add a head to the bug if a) there already exists a neck and + * b) a head has not previously been added + * + * @return text outlining the success of the operation + */ + public String addHead() { + + int status = NOT_ADDED; // Default is not added + + if (!neck) { + // No neck, cannot add a head + status = MISSING; + } else if (!head) { + head = true; + status = ADDED; + } + + return headMessages[status]; + } + + /** + * Add a feeler to the head if a) there has been a head added to + * the bug previously, and b) there are not already 2 (MAX_FEELERS) + * feelers previously added to the bug. + * + * @return text outlining the status of the operation + */ + public String addFeelers() { + + int status = NOT_ADDED; // Default is not added + + if (!head) { + // No head, cannot add a feeler + status = MISSING; + } else if (feelers < MAX_FEELERS) { + feelers++; + status = ADDED; + } + + return feelerMessages[status]; + } + + /** + * Add a tail to the bug if a) there is already a body previously added + * to the bug and b) there is not already a tail added. + * + * @return text outlining the status of the operation. + */ + public String addTail() { + + int status = NOT_ADDED; // Default is not added + + if (!body) { + // No body, cannot add a tail + status = MISSING; + } else if (!tail) { + tail = true; + status = ADDED; + } + + return tailMessages[status]; + } + + /** + * Add a leg to the bug if a) there is already a body previously added + * b) there are less than 6 (MAX_LEGS) previously added. + * + * @return text outlining status of the operation. + */ + public String addLeg() { + + int status = NOT_ADDED; // Default is not added + + if (!body) { + // No body, cannot add a leg + status = MISSING; + } else if (legs < MAX_LEGS) { + legs++; + status = ADDED; + } + + String message = ""; + + // Create a string showing the result of the operation + + switch(status) { + case ADDED: + // Replace # with number of legs + message = legMessages[status].replace("^^^", String.valueOf(legs)); + // Add text S. if >1 leg, or just . if one leg. + if (legs > 1) { + message += "S."; + } else { + message += "."; + } + break; + + case NOT_ADDED: + + // Deliberate fall through to next case as its the + // same code to be executed + case MISSING: + message = legMessages[status]; + break; + } + + return message; + } + + /** + * Initialise + */ + public void init() { + body = false; + neck = false; + head = false; + feelers = 0; + tail = false; + legs = 0; + } + + /** + * Add unique messages depending on type of player + * A subclass of this class calls this method + * e.g. See ComputerBug or PlayerBug classes + * + * @param messages an array of messages + * @param bodyPart the bodypart the messages relate to. + */ + public void addMessages(String[] messages, PARTS bodyPart) { + + switch (bodyPart) { + case FEELERS: + feelerMessages = messages; + break; + + case HEAD: + headMessages = messages; + break; + + case NECK: + neckMessages = messages; + break; + + case BODY: + bodyMessages = messages; + break; + + case TAIL: + tailMessages = messages; + break; + + case LEGS: + legMessages = messages; + break; + } + } + + /** + * Returns a string array containing + * the "bug" that can be output to console + * + * @return the bug ready to draw + */ + public ArrayList draw() { + ArrayList bug = new ArrayList<>(); + StringBuilder lineOutput; + + // Feelers + if (feelers > 0) { + for (int i = 0; i < 4; i++) { + lineOutput = new StringBuilder(addSpaces(10)); + for (int j = 0; j < feelers; j++) { + lineOutput.append("A "); + } + bug.add(lineOutput.toString()); + } + } + + if (head) { + lineOutput = new StringBuilder(addSpaces(8) + "HHHHHHH"); + bug.add(lineOutput.toString()); + lineOutput = new StringBuilder(addSpaces(8) + "H" + addSpaces(5) + "H"); + bug.add(lineOutput.toString()); + lineOutput = new StringBuilder(addSpaces(8) + "H O O H"); + bug.add(lineOutput.toString()); + lineOutput = new StringBuilder(addSpaces(8) + "H" + addSpaces(5) + "H"); + bug.add(lineOutput.toString()); + lineOutput = new StringBuilder(addSpaces(8) + "H" + addSpaces(2) + "V" + addSpaces(2) + "H"); + bug.add(lineOutput.toString()); + lineOutput = new StringBuilder(addSpaces(8) + "HHHHHHH"); + bug.add(lineOutput.toString()); + } + + if (neck) { + for (int i = 0; i < 2; i++) { + lineOutput = new StringBuilder(addSpaces(10) + "N N"); + bug.add(lineOutput.toString()); + } + } + + if (body) { + lineOutput = new StringBuilder(addSpaces(5) + "BBBBBBBBBBBB"); + bug.add(lineOutput.toString()); + for (int i = 0; i < 2; i++) { + lineOutput = new StringBuilder(addSpaces(5) + "B" + addSpaces(10) + "B"); + bug.add(lineOutput.toString()); + } + if (tail) { + lineOutput = new StringBuilder("TTTTTB" + addSpaces(10) + "B"); + bug.add(lineOutput.toString()); + } + lineOutput = new StringBuilder(addSpaces(5) + "BBBBBBBBBBBB"); + bug.add(lineOutput.toString()); + } + + if (legs > 0) { + for (int i = 0; i < 2; i++) { + lineOutput = new StringBuilder(addSpaces(5)); + for (int j = 0; j < legs; j++) { + lineOutput.append(" L"); + } + bug.add(lineOutput.toString()); + } + } + + return bug; + } + + /** + * Check if the bug is complete i.e. it has + * 2 (MAX_FEELERS) feelers, a head, a neck, a body + * a tail and 6 (MAX_FEET) feet. + * + * @return true if complete. + */ + public boolean complete() { + return (feelers == MAX_FEELERS) + && head + && neck + && body + && tail + && (legs == MAX_LEGS); + } + + /** + * Simulate tabs be creating a string of X spaces. + * + * @param number contains number of spaces needed. + * @return a String containing the spaces + */ + private String addSpaces(int number) { + char[] spaces = new char[number]; + Arrays.fill(spaces, ' '); + return new String(spaces); + + } +} \ No newline at end of file diff --git a/16 Bug/java/src/PlayerBug.java b/16 Bug/java/src/PlayerBug.java new file mode 100644 index 00000000..1a82e8b3 --- /dev/null +++ b/16 Bug/java/src/PlayerBug.java @@ -0,0 +1,18 @@ +public class PlayerBug extends Insect { + + // Create messages specific to the player. + + public PlayerBug() { + // Call superclass constructor for initialization. + super(); + addMessages(new String[]{"I NOW GIVE YOU A FEELER.", "YOU HAVE " + MAX_FEELERS + " FEELERS ALREADY.", "YOU DO NOT HAVE A HEAD."}, PARTS.FEELERS); + addMessages(new String[]{"YOU NEEDED A HEAD.", "YOU HAVE A HEAD.", "YOU DO NOT HAVE A NECK."}, PARTS.HEAD); + addMessages(new String[]{"YOU NOW HAVE A NECK.", "YOU DO NOT NEED A NECK.", "YOU DO NOT HAVE A BODY."}, PARTS.NECK); + addMessages(new String[]{"YOU NOW HAVE A BODY.", "YOU DO NOT NEED A BODY."}, PARTS.BODY); + addMessages(new String[]{"I NOW GIVE YOU A TAIL.", "YOU ALREADY HAVE A TAIL.", "YOU DO NOT HAVE A BODY."}, PARTS.TAIL); + addMessages(new String[]{"YOU NOW HAVE ^^^ LEG", "YOU HAVE " + MAX_LEGS + " FEET ALREADY.", "YOU DO NOT HAVE A BODY."}, PARTS.LEGS); + } + + +} + From 260c12fb845bfece15ec1e5ad22cad19e3bebd12 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 24 Feb 2021 12:16:47 +1030 Subject: [PATCH 017/749] Fix gameover Fix issue with gameOver code being executed in only one chain. --- 16 Bug/java/src/Bug.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/16 Bug/java/src/Bug.java b/16 Bug/java/src/Bug.java index 626615de..861afc5a 100644 --- a/16 Bug/java/src/Bug.java +++ b/16 Bug/java/src/Bug.java @@ -144,11 +144,10 @@ public class Bug { System.out.println(); draw(computersBug); gameState = GAME_STATE.PLAYER_TURN; - - if (gameOver) { - System.out.println("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!"); - gameState = GAME_STATE.GAME_OVER; - } + } + if (gameOver) { + System.out.println("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!"); + gameState = GAME_STATE.GAME_OVER; } } } while (gameState != GAME_STATE.GAME_OVER); From b6265cd9db4627aaecc51a4aa56764efdb0a88fa Mon Sep 17 00:00:00 2001 From: Kyle Hale Date: Tue, 23 Feb 2021 20:23:19 -0600 Subject: [PATCH 018/749] Cleaned up TODOs --- 60 Mastermind/python/mastermind.py | 297 +++++++++++++---------------- 1 file changed, 137 insertions(+), 160 deletions(-) diff --git a/60 Mastermind/python/mastermind.py b/60 Mastermind/python/mastermind.py index adb62be3..ccc2ae9c 100644 --- a/60 Mastermind/python/mastermind.py +++ b/60 Mastermind/python/mastermind.py @@ -1,67 +1,66 @@ -import random +import random, sys + + def main(): global colors, color_letters, num_positions, num_colors, human_score, computer_score colors = ["BLACK", "WHITE", "RED", "GREEN", "ORANGE", "YELLOW", "PURPLE", "TAN"] color_letters = "BWRGOYPT" - + num_colors = 100 - human_score = 0 + human_score = 0 computer_score = 0 # get user inputs for game conditions print("Mastermind") print('Creative Computing Morristown, New Jersey') - while (num_colors > 8): + while num_colors > 8: num_colors = int(input("Number of colors (max 8): ")) # C9 in BASIC - # TODO no more than 8 colors num_positions = int(input("Number of positions: ")) # P9 in BASIC num_rounds = int(input("Number of rounds: ")) # R9 in BASIC possibilities = num_colors**num_positions all_possibilities = [1] * possibilities - + print("Number of possibilities {}".format(possibilities)) - #TODO tab fixed formatting - print('Color Letter') - print('===== ======') + print('Color\tLetter') + print('=====\t======') for element in range(0, num_colors): - print("{} {}".format(colors[element], colors[element][0])) - - num_moves = 1 - guesses = [] + print("{}\t{}".format(colors[element], colors[element][0])) + current_round = 1 - + while current_round <= num_rounds: print('Round number {}'.format(current_round)) num_moves = 1 + guesses = [] turn_over = False print('Guess my combination ...') - answer = int(possibilities * random.random()) # A in BASIC - numeric_answer = init_possibility() + answer = int(possibilities * random.random()) + numeric_answer = [-1] * num_positions for i in range(0, answer): numeric_answer = get_possibility(numeric_answer) - #debug - print("{} - {}".format(numeric_answer, make_human_readable(numeric_answer))) #human_readable_answer = make_human_readable(numeric_answer) - while (num_moves < 10 and not(turn_over)): + while (num_moves < 10 and not turn_over ): print('Move # {} Guess : '.format(num_moves)) user_command = input('Guess ') if user_command == "BOARD": print_board(guesses) #2000 - elif user_command == "QUIT": - quit_game(numeric_answer) #2500 + elif user_command == "QUIT": #2500 + human_readable_answer = make_human_readable(numeric_answer) + print('QUITTER! MY COMBINATION WAS: {}'.format(human_readable_answer)) + print('GOOD BYE') quit() elif len(user_command) != num_positions: #410 print("BAD NUMBER OF POSITIONS") else: invalid_letters = get_invalid_letters(user_command) - if (invalid_letters > ""): + if invalid_letters > "": print("INVALID GUESS: {}".format(invalid_letters)) else: guess_results = compare_two_positions(user_command, make_human_readable(numeric_answer)) print("Results: {}".format(guess_results)) - if (guess_results[1] == num_positions): # correct guess + if guess_results[1] == num_positions: # correct guess turn_over = True print("You guessed it in {} moves!".format(num_moves)) human_score = human_score + num_moves @@ -70,150 +69,148 @@ def main(): print("You have {} blacks and {} whites".format(guess_results[1], guess_results[2])) num_moves = num_moves + 1 guesses.append(guess_results) - if (not(turn_over)): # RAN OUT OF MOVES + if not turn_over: # RAN OUT OF MOVES print ("YOU RAN OUT OF MOVES! THAT'S ALL YOU GET!") print("THE ACTUAL COMBINATION WAS: {}".format(make_human_readable(numeric_answer))) human_score = human_score + num_moves print_score() - + # COMPUTER TURN + guesses = [] turn_over = False - all_possibilities = [1] * possibilities - num_moves = 1 - print ("NOW I GUESS. THINK OF A COMBINATION.") - player_ready = input("HIT RETURN WHEN READY: ") - while (num_moves < 10 and not(turn_over)): - foundGuess = False - computer_guess = int(possibilities * random.random()) - if (all_possibilities[computer_guess] == 1): # random guess is possible, use it - foundGuess = True - guess = computer_guess - else: - for i in range (computer_guess, possibilities): - if (all_possibilities[i] == 1): - foundGuess = True - guess = i - break - if (not(foundGuess)): - for i in range (0, computer_guess): - if (all_possibilities[i] == 1): - foundGuess = True + inconsistent_information = False + while(not turn_over and not inconsistent_information ): + all_possibilities = [1] * possibilities + num_moves = 1 + inconsistent_information = False + print ("NOW I GUESS. THINK OF A COMBINATION.") + player_ready = input("HIT RETURN WHEN READY: ") + while (num_moves < 10 and not turn_over and not inconsistent_information): + found_guess = False + computer_guess = int(possibilities * random.random()) + if all_possibilities[computer_guess] == 1: # random guess is possible, use it + found_guess = True + guess = computer_guess + else: + for i in range (computer_guess, possibilities): + if all_possibilities[i] == 1: + found_guess = True guess = i break - if (not(foundGuess)): # inconsistent info from user - print('YOU HAVE GIVEN ME INCONSISTENT INFORMATION.') - print('TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL.') - quit() - # TODO start computer turn over - else: - numeric_guess = init_possibility() - for i in range(0, guess): - numeric_guess = get_possibility(numeric_guess) - human_readable_guess = make_human_readable(numeric_guess) - print('My guess is: {}'.format(human_readable_guess)) - blacks, whites = input("Enter blacks, whites (e.g. 1,2): ").split(",") - blacks = int(blacks) - whites = int(whites) - if (blacks == num_positions): #Correct guess - print('I GOT IT IN {} moves'.format(num_moves)) + if not found_guess: + for i in range (0, computer_guess): + if all_possibilities[i] == 1: + found_guess = True + guess = i + break + if not found_guess: # inconsistent info from user + print('YOU HAVE GIVEN ME INCONSISTENT INFORMATION.') + print('TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL.') turn_over = True - computer_score = computer_score + num_moves - print_score() + inconsistent_information = True else: - num_moves += 1 - for i in range (0, possibilities): - if(all_possibilities[i] == 0): #already ruled out - continue - numeric_possibility = init_possibility() - for j in range (0, i): - numeric_possibility = get_possibility(numeric_possibility) - human_readable_possibility = make_human_readable(numeric_possibility) #4000 - comparison = compare_two_positions(human_readable_possibility, human_readable_guess) - print("{} {} {}".format(human_readable_guess, human_readable_possibility, comparison)) - if ((blacks != comparison[1]) or (whites != comparison[2])): - all_possibilities[i] = 0 - if (not(turn_over)): # COMPUTER DID NOT GUESS - print("I USED UP ALL MY MOVES!") - print("I GUESS MY CPU IS JUST HAVING AN OFF DAY.") - computer_score = computer_score + num_moves - print_score() + numeric_guess = [-1] * num_positions + for i in range(0, guess): + numeric_guess = get_possibility(numeric_guess) + human_readable_guess = make_human_readable(numeric_guess) + print('My guess is: {}'.format(human_readable_guess)) + blacks, whites = input("ENTER BLACKS, WHITES (e.g. 1,2): ").split(",") + blacks = int(blacks) + whites = int(whites) + if blacks == num_positions: #Correct guess + print('I GOT IT IN {} MOVES'.format(num_moves)) + turn_over = True + computer_score = computer_score + num_moves + print_score() + else: + num_moves += 1 + for i in range (0, possibilities): + if all_possibilities[i] == 0: #already ruled out + continue + numeric_possibility = [-1] * num_positions + for j in range (0, i): + numeric_possibility = get_possibility(numeric_possibility) + human_readable_possibility = make_human_readable(numeric_possibility) #4000 + comparison = compare_two_positions(human_readable_possibility, human_readable_guess) + print(comparison) + if ((blacks != comparison[1]) or (whites != comparison[2])): + all_possibilities[i] = 0 + if not turn_over: # COMPUTER DID NOT GUESS + print("I USED UP ALL MY MOVES!") + print("I GUESS MY CPU IS JUST HAVING AN OFF DAY.") + computer_score = computer_score + num_moves + print_score() current_round += 1 + print_score(is_final_score=True) + sys.exit() +#470 def get_invalid_letters(user_command): - #TODO - return "" - -def validate_human_guess(user_input): - - guess_results = compare_two_positions(user_input, answer) - return guess_results + """Makes sure player input consists of valid colors for selected game configuration.""" + valid_colors = color_letters[:num_colors] + invalid_letters = "" + for letter in user_command: + if letter not in valid_colors: + invalid_letters = invalid_letters + letter + return invalid_letters #2000 def print_board(guesses): + """Prints previous guesses within the round.""" print("Board") - print("Move Guess Black White") - for guess in guesses: - print('{} {} {} {}'.format(guess[0], guess[0], guess[1], guess[2])) - -#2500 -def quit_game(numeric_answer): - human_readable_answer = make_human_readable(numeric_answer) - print('QUITTER! MY COMBINATION WAS: {}'.format(human_readable_answer)) - print('GOOD BYE') - -#3000 -def init_possibility(): - possibility = [0] * num_positions - return possibility + print("Move\tGuess\tBlack White") + for idx, guess in enumerate(guesses): + print('{}\t{}\t{} {}'.format(idx+1, guess[0], guess[1], guess[2])) #3500 +# Easily the place for most optimization, since they generate every possibility +# every time when checking for potential solutions +# From the original article: +# "We did try a version that kept an actual list of all possible combinations +# (as a string array), which was significantly faster than this versionn but +# which ate tremendous amounts of memory." def get_possibility(possibility): - if possibility[0] > 0: #3530 - current_position = 0 # Python arrays are zero-indexed - while (True): - if possibility[current_position] < num_colors: - possibility[current_position] += 1 - return possibility - else: - possibility[current_position] = 1 - current_position += 1 + #print(possibility) + if possibility[0] > -1: #3530 + current_position = 0 # Python arrays are zero-indexed + while True: + if possibility[current_position] < num_colors-1: # zero-index again + possibility[current_position] += 1 + return possibility + else: + possibility[current_position] = 0 + current_position += 1 else: #3524 - possibility = [1] * num_positions + possibility = [0] * num_positions return possibility -#4000 -def convert_q_to_a(): - return map_num_to_vals(q, color_letters) - #4500 def compare_two_positions(guess, answer): - f = 0 - b = 0 - w = 0 + """Returns blacks (correct color and position) and whites (correct color only) for candidate position (guess) versus reference position (answer).""" + increment = 0 + blacks = 0 + whites = 0 initial_guess = guess for pos in range(0, num_positions): - if (guess[pos] != answer[pos]): + if guess[pos] != answer[pos]: for pos2 in range(0, num_positions): if not(guess[pos] != answer[pos2] or guess[pos2] == answer[pos2]): # correct color but not correct place - w = w + 1 - answer = answer[:pos2] + chr(f) + answer[pos2+1:] - guess = guess[:pos] + chr(f+1) + guess[pos+1:] - f = f + 2 + whites = whites + 1 + answer = answer[:pos2] + chr(increment) + answer[pos2+1:] + guess = guess[:pos] + chr(increment+1) + guess[pos+1:] + increment = increment + 2 else: #correct color and placement - b = b + 1 + blacks = blacks + 1 # THIS IS DEVIOUSLY CLEVER - guess = guess[:pos] + chr(f+1) + guess[pos+1:] - answer = answer[:pos] + chr(f) + answer[pos+1:] - f = f + 2 - return [initial_guess, b, w] - - - - - -#5000 + guess = guess[:pos] + chr(increment+1) + guess[pos+1:] + answer = answer[:pos] + chr(increment) + answer[pos+1:] + increment = increment + 2 + return [initial_guess, blacks, whites] + +#5000 + logic from 1160 def print_score(is_final_score=False): - if (is_final_score): + """Prints score after each turn ends, including final score at end of game.""" + if is_final_score: print("GAME OVER") print("FINAL SCORE:") else: @@ -221,33 +218,13 @@ def print_score(is_final_score=False): print(" COMPUTER {}".format(computer_score)) print(" HUMAN {}".format(human_score)) -#5500 -def convert_q_to_g(): - return map_num_to_vals(q, g) - -#6000 -def convert_q_to_h(): - return map_num_to_vals(q, h) - -#6500 -def copy_g_to_h(): - g = h - +#4000, 5500, 6000 subroutines are all identical def make_human_readable(num): + """Make the numeric representation of a position human readable.""" retval = '' - for z in range(0, len(num)): - retval = retval + color_letters[int(num[z])] - return retval - - -def map_num_to_vals(num, v): - retval = '' - print(len(num)) - for z in range(0, len(num)): - print(num[z]) - print(v[int(num[z])]) - retval = retval + v[int(num[z])] + for i in range(0, len(num)): + retval = retval + color_letters[int(num[i])] return retval if __name__ == "__main__": - main() \ No newline at end of file + main() From ccab485148eb22f03c53b7173e01a1317bd71175 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:35:13 +1030 Subject: [PATCH 019/749] Java version of Train --- 91 Train/java/src/Train.java | 109 +++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 91 Train/java/src/Train.java diff --git a/91 Train/java/src/Train.java b/91 Train/java/src/Train.java new file mode 100644 index 00000000..0fc5ff12 --- /dev/null +++ b/91 Train/java/src/Train.java @@ -0,0 +1,109 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Train + *

+ * Based on the Basic program Train here + * https://github.com/coding-horror/basic-computer-games/blob/main/91%20Train/train.bas + *

+ * Note: The idea was to create a version of the 1970's Basic program in Java, without introducing + * new features - no additional text, error checking, etc has been added. + */ +public class Train { + + private final Scanner kbScanner; + + public Train() { + kbScanner = new Scanner(System.in); + } + + public void process() { + + intro(); + + boolean gameOver = false; + + do { + double carMph = (int) (25 * Math.random() + 40); + double hours = (int) (15 * Math.random() + 5); + double train = (int) (19 * Math.random() + 20); + + System.out.println(" A CAR TRAVELING " + (int) carMph + " MPH CAN MAKE A CERTAIN TRIP IN"); + System.out.println((int) hours + " HOURS LESS THAN A TRAIN TRAVELING AT " + (int) train + " MPH."); + + double howLong = Double.parseDouble(displayTextAndGetInput("HOW LONG DOES THE TRIP TAKE BY CAR? ")); + + double hoursAnswer = hours * train / (carMph - train); + int percentage = (int) (Math.abs((hoursAnswer - howLong) * 100 / howLong) + .5); + if (percentage > 5) { + System.out.println("SORRY. YOU WERE OFF BY " + percentage + " PERCENT."); + } else { + System.out.println("GOOD! ANSWER WITHIN " + percentage + " PERCENT."); + } + System.out.println("CORRECT ANSWER IS " + hoursAnswer + " HOURS."); + + System.out.println(); + if (!yesEntered(displayTextAndGetInput("ANOTHER PROBLEM (YES OR NO)? "))) { + gameOver = true; + } + + } while (!gameOver); + + + } + + private void intro() { + System.out.println("TRAIN"); + System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("TIME - SPEED DISTANCE EXERCISE"); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + + } + + /** + * Program startup. + * + * @param args not used (from command line). + */ + public static void main(String[] args) { + Train train = new Train(); + train.process(); + } +} From b3e017e8fdabebd31d974a2224d970d32b29ff80 Mon Sep 17 00:00:00 2001 From: nanochess Date: Wed, 24 Feb 2021 14:19:31 -0600 Subject: [PATCH 020/749] Ported BOMBARDMENT, BOMBS AWAY and BOUNCE to Javascript --- 11 Bombardment/javascript/bombardment.html | 9 + 11 Bombardment/javascript/bombardment.js | 167 +++++++++++++++++ 12 Bombs Away/javascript/bombsaway.html | 9 + 12 Bombs Away/javascript/bombsaway.js | 205 +++++++++++++++++++++ 13 Bounce/javascript/bounce.html | 9 + 13 Bounce/javascript/bounce.js | 112 +++++++++++ 6 files changed, 511 insertions(+) create mode 100644 11 Bombardment/javascript/bombardment.html create mode 100644 11 Bombardment/javascript/bombardment.js create mode 100644 12 Bombs Away/javascript/bombsaway.html create mode 100644 12 Bombs Away/javascript/bombsaway.js create mode 100644 13 Bounce/javascript/bounce.html create mode 100644 13 Bounce/javascript/bounce.js diff --git a/11 Bombardment/javascript/bombardment.html b/11 Bombardment/javascript/bombardment.html new file mode 100644 index 00000000..5255cdd9 --- /dev/null +++ b/11 Bombardment/javascript/bombardment.html @@ -0,0 +1,9 @@ + + +BOMBARDMENT + + +


+
+
+
diff --git a/11 Bombardment/javascript/bombardment.js b/11 Bombardment/javascript/bombardment.js
new file mode 100644
index 00000000..3cd0a5d7
--- /dev/null
+++ b/11 Bombardment/javascript/bombardment.js	
@@ -0,0 +1,167 @@
+// BOMBARDMENT
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "BOMBARDMENT\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU\n");
+    print("HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED.\n");
+    print("YOU CAN ONLY PLACE ONE PLATOON AT ANY ONE OUTPOST.\n");
+    print("THE COMPUTER DOES THE SAME WITH ITS FOUR PLATOONS.\n");
+    print("\n");
+    print("THE OBJECT OF THE GAME IS TO FIRE MISSILES AT THE\n");
+    print("OUTPOSTS OF THE COMPUTER.  IT WILL DO THE SAME TO YOU.\n");
+    print("THE ONE WHO DESTROYS ALL FOUR OF THE ENEMY'S PLATOONS\n");
+    print("FIRST IS THE WINNER.\n");
+    print("\n");
+    print("GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT!\n");
+    print("\n");
+    // "TEAR OFF" because it supposed this to be printed on a teletype
+    print("TEAR OFF MATRIX AND USE IT TO CHECK OFF THE NUMBERS.\n");
+    for (r = 1; r <= 5; r++)
+        print("\n");
+    ma = [];
+    for (r = 1; r <= 100; r++)
+        ma[r] = 0;
+    p = 0;
+    q = 0;
+    z = 0;
+    for (r = 1; r <= 5; r++) {
+        i = (r - 1) * 5 + 1;
+        print(i + "\t" + (i + 1) + "\t" + (i + 2) + "\t" + (i + 3) + "\t" + (i + 4) + "\n");
+    }
+    for (r = 1; r <= 10; r++)
+        print("\n");
+    c = Math.floor(Math.random() * 25) + 1;
+    do {
+        d = Math.floor(Math.random() * 25) + 1;
+        e = Math.floor(Math.random() * 25) + 1;
+        f = Math.floor(Math.random() * 25) + 1;
+    } while (c == d || c == e || c == f || d == e || d == f || e == f) ;
+    print("WHAT ARE YOUR FOUR POSITIONS");
+    str = await input();
+    g = parseInt(str);
+    str = str.substr(str.indexOf(",") + 1);
+    h = parseInt(str);
+    str = str.substr(str.indexOf(",") + 1);
+    k = parseInt(str);
+    str = str.substr(str.indexOf(",") + 1);
+    l = parseInt(str);
+    print("\n");
+    // Another "bug" your outpost can be in the same position as a computer outpost
+    // Let us suppose both live in a different matrix.
+    while (1) {
+        // The original game didn't limited the input to 1-25
+        do {
+            print("WHERE DO YOU WISH TO FIRE YOUR MISSLE");
+            y = parseInt(await input());
+        } while (y < 0 || y > 25) ;
+        if (y == c || y == d || y == e || y == f) {
+            
+            // The original game has a bug. You can shoot the same outpost
+            // several times. This solves it.
+            if (y == c)
+                c = 0;
+            if (y == d)
+                d = 0;
+            if (y == e)
+                e = 0;
+            if (y == f)
+                f = 0;
+            q++;
+            if (q == 1) {
+                print("ONE DOWN. THREE TO GO.\n");
+            } else if (q == 2) {
+                print("TWO DOWN. TWO TO GO.\n");
+            } else if (q == 3) {
+                print("THREE DOWN. ONE TO GO.\n");
+            } else {
+                print("YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN\n");
+                print("MY TRANSISTO&S RECUP%RA*E!\n");
+                break;
+            }
+        } else {
+            print("HA, HA YOU MISSED. MY TURN NOW:\n");
+        }
+        print("\n");
+        print("\n");
+        do {
+            m = Math.floor(Math.random() * 25 + 1);
+            p++;
+            n = p - 1;
+            for (t = 1; t <= n; t++) {
+                if (m == ma[t])
+                    break;
+            }
+        } while (t <= n) ;
+        x = m;
+        ma[p] = m;
+        if (x == g || x == h || x == l || x == k) {
+            z++;
+            if (z < 4)
+                print("I GOT YOU. IT WON'T BE LONG NOW. POST " + x + " WAS HIT.\n");
+            if (z == 1) {
+                print("YOU HAVE ONLY THREE OUTPOSTS LEFT.\n");
+            } else if (z == 2) {
+                print("YOU HAVE ONLY TWO OUTPOSTS LEFT.\n");
+            } else if (z == 3) {
+                print("YOU HAVE ONLY ONE OUTPOST LEFT.\n");
+            } else {
+                print("YOU'RE DEAD. YOUR LAST OUTPOST WAS AT " + x + ". HA, HA, HA.\n");
+                print("BETTER LUCK NEXT TIME.\n");
+            }
+        } else {
+            print("I MISSED YOU, YOU DIRTY RAT. I PICKED " + m + ". YOUR TURN:\n");
+        }
+        print("\n");
+        print("\n");
+    }
+}
+
+main();
diff --git a/12 Bombs Away/javascript/bombsaway.html b/12 Bombs Away/javascript/bombsaway.html
new file mode 100644
index 00000000..c58c753f
--- /dev/null
+++ b/12 Bombs Away/javascript/bombsaway.html	
@@ -0,0 +1,9 @@
+
+
+BOMBARDMENT
+
+
+

+
+
+
diff --git a/12 Bombs Away/javascript/bombsaway.js b/12 Bombs Away/javascript/bombsaway.js
new file mode 100644
index 00000000..835a2608
--- /dev/null
+++ b/12 Bombs Away/javascript/bombsaway.js	
@@ -0,0 +1,205 @@
+// BOMBS AWAY
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    while (1) {
+        print("YOU ARE A PILOT IN A WORLD WAR II BOMBER.\n");
+        while (1) {
+            print("WHAT SIDE -- ITALY(1), ALLIES(2), JAPAN(3), GERMANY(4)");
+            a = parseInt(await input());
+            if (a < 1 || a > 4)
+                print("TRY AGAIN...\n");
+            else
+                break;
+        }
+        if (a == 1) {
+            while (1) {
+                print("YOUR TARGET -- ALBANIA(1), GREECE(2), NORTH AFRICA(3)");
+                b = parseInt(await input());
+                if (b < 1 || b > 3)
+                    print("TRY AGAIN...\n");
+                else
+                    break;
+            }
+            print("\n");
+            if (b == 1) {
+                print("SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE.\n");
+            } else if (b == 2) {
+                print("BE CAREFUL!!!\n");
+            } else {
+                print("YOU'RE GOING FOR THE OIL, EH?\n");
+            }
+        } else if (a == 2) {
+            while (1) {
+                print("AIRCRAFT -- LIBERATOR(1), B-29(2), B-17(3), LANCASTER(4)");
+                g = parseInt(await input());
+                if (g < 1 || g > 4)
+                    print("TRY AGAIN...\n");
+                else
+                    break;
+            }
+            print("\n");
+            if (g == 1) {
+                print("YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI.\n");
+            } else if (g == 2) {
+                print("YOU'RE DUMPING THE A-BOMB ON HIROSHIMA.\n");
+            } else if (g == 3) {
+                print("YOU'RE CHASING THE BISMARK IN THE NORTH SEA.\n");
+            } else {
+                print("YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR.\n");
+            }
+        } else if (a == 3) {
+            print("YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON.\n");
+            print("YOUR FIRST KAMIKAZE MISSION(Y OR N)");
+            str = await input();
+            if (str == "N") {
+                s = 0;
+            } else {
+                s = 1;
+                print("\n");
+            }
+        } else {
+            while (1) {
+                print("A NAZI, EH?  OH WELL.  ARE YOU GOING FOR RUSSIA(1),\n");
+                print("ENGLAND(2), OR FRANCE(3)");
+                m = parseInt(await input());
+                if (m < 1 || m > 3)
+                    print("TRY AGAIN...\n");
+                else
+                    break;
+            }
+            print("\n");
+            if (m == 1) {
+                print("YOU'RE NEARING STALINGRAD.\n");
+            } else if (m == 2) {
+                print("NEARING LONDON.  BE CAREFUL, THEY'VE GOT RADAR.\n");
+            } else if (m == 3) {
+                print("NEARING VERSAILLES.  DUCK SOUP.  THEY'RE NEARLY DEFENSELESS.\n");
+            }
+        }
+        if (a != 3) {
+            print("\n");
+            while (1) {
+                print("HOW MANY MISSIONS HAVE YOU FLOWN");
+                d = parseInt(await input());
+                if (d < 160)
+                    break;
+                print("MISSIONS, NOT MILES...\n");
+                print("150 MISSIONS IS HIGH EVEN FOR OLD-TIMERS.\n");
+                print("NOW THEN, ");
+            }
+            print("\n");
+            if (d >= 100) {
+                print("THAT'S PUSHING THE ODDS!\n");
+            } else if (d < 25) {
+                print("FRESH OUT OF TRAINING, EH?\n");
+            }
+            print("\n");
+            if (d >= 160 * Math.random())
+                hit = true;
+            else
+                hit = false;
+        } else {
+            if (s == 0) {
+                hit = false;
+            } else if (Math.random() > 0.65) {
+                hit = true;
+            } else {
+                hit = false;
+                s = 100;
+            }
+        }
+        if (hit) {
+            print("DIRECT HIT!!!! " + Math.floor(100 * Math.random()) + " KILLED.\n");
+            print("MISSION SUCCESSFUL.\n");
+        } else {
+            t = 0;
+            if (a != 3) {
+                print("MISSED TARGET BY " + Math.floor(2 + 30 * Math.random()) + " MILES!\n");
+                print("NOW YOU'RE REALLY IN FOR IT !!\n");
+                print("\n");
+                while (1) {
+                    print("DOES THE ENEMY HAVE GUNS(1), MISSILE(2), OR BOTH(3)");
+                    r = parseInt(await input());
+                    if (r < 1 || r > 3)
+                        print("TRY AGAIN...\n");
+                    else
+                        break;
+                }
+                print("\n");
+                if (r != 2) {
+                    print("WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)");
+                    s = parseInt(await input());
+                    if (s < 10)
+                        print("YOU LIE, BUT YOU'LL PAY...\n");
+                    print("\n");
+                }
+                print("\n");
+                if (r > 1)
+                    t = 35;
+            }
+            if (s + t <= 100 * Math.random()) {
+                print("YOU MADE IT THROUGH TREMENDOUS FLAK!!\n");
+            } else {
+                print("* * * * BOOM * * * *\n");
+                print("YOU HAVE BEEN SHOT DOWN.....\n");
+                print("DEARLY BELOVED, WE ARE GATHERED HERE TODAY TO PAY OUR\n");
+                print("LAST TRIBUTE...\n");
+            }
+        }
+        print("\n");
+        print("\n");
+        print("\n");
+        print("ANOTHER MISSION (Y OR N)");
+        str = await input();
+        if (str != "Y")
+            break;
+    }
+    print("CHICKEN !!!\n");
+    print("\n");
+}
+
+main();
diff --git a/13 Bounce/javascript/bounce.html b/13 Bounce/javascript/bounce.html
new file mode 100644
index 00000000..b1e8c529
--- /dev/null
+++ b/13 Bounce/javascript/bounce.html	
@@ -0,0 +1,9 @@
+
+
+BOUNCE
+
+
+

+
+
+
diff --git a/13 Bounce/javascript/bounce.js b/13 Bounce/javascript/bounce.js
new file mode 100644
index 00000000..d9cac590
--- /dev/null
+++ b/13 Bounce/javascript/bounce.js	
@@ -0,0 +1,112 @@
+// BOUNCE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "BOUNCE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    ta = [];
+    print("THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY\n");
+    print("OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF\n");
+    print("ELASTICITY OF THE BALL.  PLEASE USE A DECIMAL FRACTION\n");
+    print("COEFFICIENCY (LESS THAN 1).\n");
+    print("\n");
+    print("YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN\n");
+    print("'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY).\n");
+    print("\n");
+    while (1) {
+        print("TIME INCREMENT (SEC)");
+        s2 = parseFloat(await input());
+        print("\n");
+        print("VELOCITY (FPS)");
+        v = parseFloat(await input());
+        print("\n");
+        print("COEFFICIENT");
+        c = parseFloat(await input());
+        print("\n");
+        print("FEET\n");
+        print("\n");
+        s1 = Math.floor(70 / (v / (16 * s2)));
+        for (i = 1; i <= s1; i++)
+            ta[i] = v * Math.pow(c, i - 1) / 16;
+        for (h = Math.floor(-16 * Math.pow(v / 32, 2) + Math.pow(v, 2) / 32 + 0.5); h >= 0; h -= 0.5) {
+            str = "";
+            if (Math.floor(h) == h)
+                str += " " + h + " ";
+            l = 0;
+            for (i = 1; i <= s1; i++) {
+                for (t = 0; t <= ta[i]; t += s2) {
+                    l += s2;
+                    if (Math.abs(h - (0.5 * (-32) * Math.pow(t, 2) + v * Math.pow(c, i - 1) * t)) <= 0.25) {
+                        while (str.length < l / s2)
+                            str += " ";
+                        str += "0";
+                    }
+                }
+                t = ta[i + 1] / 2;
+                if (-16 * Math.pow(t, 2) + v * Math.pow(c, i - 1) * t < h)
+                    break;
+            }
+            print(str + "\n");
+        }
+        str = " ";
+        for (i = 1; i < Math.floor(l + 1) / s2 + 1; i++)
+            str += ".";
+        print(str + "\n");
+        str = " 0";
+        for (i = 1; i < Math.floor(l + 0.9995); i++) {
+            while (str.length < Math.floor(i / s2))
+                str += " ";
+            str += i;
+        }
+        print(str + "\n");
+        print(tab(Math.floor(l + 1) / (2 * s2) - 2) + "SECONDS\n");
+    }
+}
+
+main();

From 56c87b6c0c89629b0e25f949c8eb2b61b3e70ff4 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Thu, 25 Feb 2021 10:27:16 +1030
Subject: [PATCH 021/749] Java version of BatNum game

---
 08 Batnum/java/src/BatNum.java     | 292 +++++++++++++++++++++++++++++
 08 Batnum/java/src/BatNumGame.java |   8 +
 2 files changed, 300 insertions(+)
 create mode 100644 08 Batnum/java/src/BatNum.java
 create mode 100644 08 Batnum/java/src/BatNumGame.java

diff --git a/08 Batnum/java/src/BatNum.java b/08 Batnum/java/src/BatNum.java
new file mode 100644
index 00000000..4211d74d
--- /dev/null
+++ b/08 Batnum/java/src/BatNum.java	
@@ -0,0 +1,292 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of BatNum
+ * 

+ * Based on the Basic game of BatNum here + * https://github.com/coding-horror/basic-computer-games/blob/main/08%20Batnum/batnum.bas + *

+ * 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 BatNum { + + private enum GAME_STATE { + STARTING, + START_GAME, + CHOOSE_PILE_SIZE, + SELECT_WIN_OPTION, + CHOOSE_MIN_AND_MAX, + SELECT_WHO_STARTS_FIRST, + PLAYERS_TURN, + COMPUTERS_TURN, + ANNOUNCE_WINNER, + GAME_OVER + } + + // Used for keyboard input + private final Scanner kbScanner; + + // Current game state + private GAME_STATE gameState; + + private int pileSize; + + // How to win the game options + enum WIN_OPTION { + TAKE_LAST, + AVOID_LAST + } + + // Tracking the winner + enum WINNER { + COMPUTER, + PLAYER + } + + private WINNER winner; + + private WIN_OPTION winOption; + + private int minSelection; + private int maxSelection; + + // Used by computer for optimal move + private int rangeOfRemovals; + + public BatNum() { + + gameState = GAME_STATE.STARTING; + + // Initialise kb scanner + kbScanner = new Scanner(System.in); + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + // Show an introduction and optional instructions the first time the game is played. + case STARTING: + intro(); + gameState = GAME_STATE.START_GAME; + break; + + // Start new game + case START_GAME: + gameState = GAME_STATE.CHOOSE_PILE_SIZE; + break; + + case CHOOSE_PILE_SIZE: + System.out.println(); + System.out.println(); + pileSize = displayTextAndGetNumber("ENTER PILE SIZE "); + if (pileSize >= 1) { + gameState = GAME_STATE.SELECT_WIN_OPTION; + } + break; + + case SELECT_WIN_OPTION: + int winChoice = displayTextAndGetNumber("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: "); + if (winChoice == 1) { + winOption = WIN_OPTION.TAKE_LAST; + gameState = GAME_STATE.CHOOSE_MIN_AND_MAX; + } else if (winChoice == 2) { + winOption = WIN_OPTION.AVOID_LAST; + gameState = GAME_STATE.CHOOSE_MIN_AND_MAX; + } + break; + + case CHOOSE_MIN_AND_MAX: + String range = displayTextAndGetInput("ENTER MIN AND MAX "); + minSelection = getDelimitedValue(range, 0); + maxSelection = getDelimitedValue(range, 1); + if (maxSelection > minSelection && minSelection >= 1) { + gameState = GAME_STATE.SELECT_WHO_STARTS_FIRST; + } + + // Used by computer in its turn + rangeOfRemovals = minSelection + maxSelection; + break; + + case SELECT_WHO_STARTS_FIRST: + int playFirstChoice = displayTextAndGetNumber("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST "); + if (playFirstChoice == 1) { + gameState = GAME_STATE.COMPUTERS_TURN; + } else if (playFirstChoice == 2) { + gameState = GAME_STATE.PLAYERS_TURN; + } + break; + + case PLAYERS_TURN: + int playersMove = displayTextAndGetNumber("YOUR MOVE "); + + if (playersMove == 0) { + System.out.println("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT."); + winner = WINNER.COMPUTER; + gameState = GAME_STATE.ANNOUNCE_WINNER; + break; + } + + if (playersMove == pileSize && winOption == WIN_OPTION.AVOID_LAST) { + winner = WINNER.COMPUTER; + gameState = GAME_STATE.ANNOUNCE_WINNER; + break; + } + + // Check if players move is with the min and max possible + if (playersMove >= minSelection && playersMove <= maxSelection) { + // Valid so reduce pileSize by amount player entered + pileSize -= playersMove; + + // Did this move result in there being no more objects on pile? + if (pileSize == 0) { + // Was the game setup so the winner was whoever took the last object + if (winOption == WIN_OPTION.TAKE_LAST) { + // Player won + winner = WINNER.PLAYER; + } else { + // Computer one + winner = WINNER.COMPUTER; + } + gameState = GAME_STATE.ANNOUNCE_WINNER; + } else { + // There are still items left. + gameState = GAME_STATE.COMPUTERS_TURN; + } + } else { + // Invalid move + System.out.println("ILLEGAL MOVE, REENTER IT "); + } + break; + + case COMPUTERS_TURN: + int pileSizeLeft = pileSize; + if (winOption == WIN_OPTION.TAKE_LAST) { + if (pileSize > maxSelection) { + + int objectsToRemove = calculateComputersTurn(pileSizeLeft); + + pileSize -= objectsToRemove; + System.out.println("COMPUTER TAKES " + objectsToRemove + " AND LEAVES " + pileSize); + gameState = GAME_STATE.PLAYERS_TURN; + } else { + System.out.println("COMPUTER TAKES " + pileSize + " AND WINS."); + winner = WINNER.COMPUTER; + gameState = GAME_STATE.ANNOUNCE_WINNER; + } + } else { + pileSizeLeft--; + if (pileSize > minSelection) { + int objectsToRemove = calculateComputersTurn(pileSizeLeft); + pileSize -= objectsToRemove; + System.out.println("COMPUTER TAKES " + objectsToRemove + " AND LEAVES " + pileSize); + gameState = GAME_STATE.PLAYERS_TURN; + } else { + System.out.println("COMPUTER TAKES " + pileSize + " AND LOSES."); + winner = WINNER.PLAYER; + gameState = GAME_STATE.ANNOUNCE_WINNER; + } + } + break; + + case ANNOUNCE_WINNER: + switch (winner) { + case PLAYER: + System.out.println("CONGRATULATIONS, YOU WIN."); + break; + case COMPUTER: + System.out.println("TOUGH LUCK, YOU LOSE."); + break; + } + gameState = GAME_STATE.START_GAME; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + /** + * Figure out the computers turn - i.e. how many objects to remove + * + * @param pileSizeLeft current size + * @return the number of objects to remove. + */ + private int calculateComputersTurn(int pileSizeLeft) { + int computersNumberToRemove = pileSizeLeft - rangeOfRemovals * (pileSizeLeft / rangeOfRemovals); + if (computersNumberToRemove < minSelection) { + computersNumberToRemove = minSelection; + } + if (computersNumberToRemove > maxSelection) { + computersNumberToRemove = maxSelection; + } + + return computersNumberToRemove; + } + + private void intro() { + System.out.println(simulateTabs(33) + "BATNUM"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE"); + System.out.println("COMPUTER IS YOUR OPPONENT."); + System.out.println(); + System.out.println("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU"); + System.out.println("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE."); + System.out.println("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR"); + System.out.println("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS."); + System.out.println("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME."); + System.out.println("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Accepts a string delimited by comma's and returns the nth delimited + * value (starting at count 0). + * + * @param text - text with values separated by comma's + * @param pos - which position to return a value for + * @return the int representation of the value + */ + private int getDelimitedValue(String text, int pos) { + String[] tokens = text.split(","); + return Integer.parseInt(tokens[pos]); + } +} \ No newline at end of file diff --git a/08 Batnum/java/src/BatNumGame.java b/08 Batnum/java/src/BatNumGame.java new file mode 100644 index 00000000..b84b61c1 --- /dev/null +++ b/08 Batnum/java/src/BatNumGame.java @@ -0,0 +1,8 @@ +public class BatNumGame { + + public static void main(String[] args) { + + BatNum batNum = new BatNum(); + batNum.play(); + } +} From 0e0c0ada2fd858ec5312dbe248879c5b66dcbab8 Mon Sep 17 00:00:00 2001 From: JBanana <9792206+jbanana@users.noreply.github.com> Date: Thu, 25 Feb 2021 01:38:03 +0000 Subject: [PATCH 022/749] Added Java version of Buzzword --- 20 Buzzword/java/src/Buzzword.java | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100755 20 Buzzword/java/src/Buzzword.java diff --git a/20 Buzzword/java/src/Buzzword.java b/20 Buzzword/java/src/Buzzword.java new file mode 100755 index 00000000..82ed9100 --- /dev/null +++ b/20 Buzzword/java/src/Buzzword.java @@ -0,0 +1,41 @@ +import java.util.Scanner; +import static java.lang.System.out; + +// This is very close to the original BASIC. Changes: +// 1) the array indexing is adjusted by 1 +// 2) the user can enter a lower case "y" +// 3) moved the word list to the top 8~) +public class Buzzword { + private static final String[] A = { + "ABILITY","BASAL","BEHAVIORAL","CHILD-CENTERED", + "DIFFERENTIATED","DISCOVERY","FLEXIBLE","HETEROGENEOUS", + "HOMOGENEOUS","MANIPULATIVE","MODULAR","TAVISTOCK", + "INDIVIDUALIZED","LEARNING","EVALUATIVE","OBJECTIVE", + "COGNITIVE","ENRICHMENT","SCHEDULING","HUMANISTIC", + "INTEGRATED","NON-GRADED","TRAINING","VERTICAL AGE", + "MOTIVATIONAL","CREATIVE","GROUPING","MODIFICATION", + "ACCOUNTABILITY","PROCESS","CORE CURRICULUM","ALGORITHM", + "PERFORMANCE","REINFORCEMENT","OPEN CLASSROOM","RESOURCE", + "STRUCTURE","FACILITY","ENVIRONMENT" + }; + private static Scanner scanner = new Scanner( System.in ); + + public static void main( final String [] args ) { + out.println( " BUZZWORD GENERATOR" ); + out.println( " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" ); + out.println();out.println();out.println(); + out.println( "THIS PROGRAM PRINTS HIGHLY ACCEPTABLE PHRASES IN" ); + out.println( "'EDUCATOR-SPEAK' THAT YOU CAN WORK INTO REPORTS" ); + out.println( "AND SPEECHES. WHENEVER A QUESTION MARK IS PRINTED," ); + out.println( "TYPE A 'Y' FOR ANOTHER PHRASE OR 'N' TO QUIT." ); + out.println();out.println();out.println( "HERE'S THE FIRST PHRASE:" ); + do { + out.print( A[ (int)( 13 * Math.random() ) ] + " " ); + out.print( A[ (int)( 13 * Math.random() + 13 ) ] + " " ); + out.print( A[ (int)( 13 * Math.random() + 26 ) ] ); out.println(); + out.print( "?" ); + } + while ( "Y".equals( scanner.nextLine().toUpperCase() ) ); + out.println( "COME BACK WHEN YOU NEED HELP WITH ANOTHER REPORT!" ); + } +} From 28041f40313312d14fead194f1c41c07818fb169 Mon Sep 17 00:00:00 2001 From: Brian Young Date: Wed, 24 Feb 2021 18:23:13 -0800 Subject: [PATCH 023/749] Added csharp version of Russion Roulette --- .../csharp/RussianRoulette/Program.cs | 106 ++++++++++++++++++ .../RussianRoulette/RussianRoulette.csproj | 8 ++ .../RussianRoulette/RussianRoulette.sln | 25 +++++ 3 files changed, 139 insertions(+) create mode 100644 76 Russian Roulette/csharp/RussianRoulette/Program.cs create mode 100644 76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.csproj create mode 100644 76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.sln diff --git a/76 Russian Roulette/csharp/RussianRoulette/Program.cs b/76 Russian Roulette/csharp/RussianRoulette/Program.cs new file mode 100644 index 00000000..43a8d4bc --- /dev/null +++ b/76 Russian Roulette/csharp/RussianRoulette/Program.cs @@ -0,0 +1,106 @@ +using System; + +namespace RussianRoulette +{ + public class Program + { + public static void Main(string[] args) + { + PrintTitle(); + + var includeRevolver = true; + while (true) + { + PrintInstructions(includeRevolver); + switch (PlayGame()) + { + case GameResult.Win: + includeRevolver = true; + break; + case GameResult.Chicken: + case GameResult.Dead: + includeRevolver = false; + break; + } + } + } + + private static void PrintTitle() + { + Console.WriteLine(" Russian Roulette"); + Console.WriteLine("Creative Computing Morristown, New Jersey"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("This is a game of >>>>>>>>>>Russian Roulette."); + } + + private static void PrintInstructions(bool includeRevolver) + { + Console.WriteLine(); + if (includeRevolver) + { + Console.WriteLine("Here is a revolver."); + } + else + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("...Next Victim..."); + } + Console.WriteLine("Type '1' to spin chamber and pull trigger."); + Console.WriteLine("Type '2' to give up."); + } + + private static GameResult PlayGame() + { + var rnd = new Random(); + var round = 0; + while (true) + { + round++; + Console.Write("Go: "); + var input = Console.ReadKey().KeyChar; + Console.WriteLine(); + if (input != '2') + { + // Random.Next will retun a value that is the same or greater than the minimum and + // less than the maximum. + // A revolver has 6 rounds. + if (rnd.Next(1, 7) == 6) + { + Console.WriteLine(" Bang!!!!! You're dead!"); + Console.WriteLine("Condolences will be sent to your relatives."); + return GameResult.Dead; + } + else + { + if (round > 10) + { + Console.WriteLine("You win!!!!!"); + Console.WriteLine("Let someone else blow their brains out."); + return GameResult.Win; + } + else + { + Console.WriteLine("- CLICK -"); + Console.WriteLine(); + } + } + } + else + { + Console.WriteLine(" CHICKEN!!!!!"); + return GameResult.Chicken; + } + } + } + + private enum GameResult + { + Win, + Chicken, + Dead + } + } +} diff --git a/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.csproj b/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.sln b/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.sln new file mode 100644 index 00000000..1e4b621e --- /dev/null +++ b/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31019.35 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RussianRoulette", "RussianRoulette.csproj", "{9F052B4A-FA33-4BBE-9D9D-3CF8152569F1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F052B4A-FA33-4BBE-9D9D-3CF8152569F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F052B4A-FA33-4BBE-9D9D-3CF8152569F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F052B4A-FA33-4BBE-9D9D-3CF8152569F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F052B4A-FA33-4BBE-9D9D-3CF8152569F1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {97F5B1B0-A80A-4C1F-9F76-8D68B4A49E82} + EndGlobalSection +EndGlobal From dbb36f25ad5bc71787c3aaf697dda77ef378b6de Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Thu, 25 Feb 2021 13:38:20 +1030 Subject: [PATCH 024/749] Java version of Change --- 22 Change/java/src/Change.java | 187 +++++++++++++++++++++++++++++ 22 Change/java/src/ChangeGame.java | 6 + 2 files changed, 193 insertions(+) create mode 100644 22 Change/java/src/Change.java create mode 100644 22 Change/java/src/ChangeGame.java diff --git a/22 Change/java/src/Change.java b/22 Change/java/src/Change.java new file mode 100644 index 00000000..7498be8a --- /dev/null +++ b/22 Change/java/src/Change.java @@ -0,0 +1,187 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Change + *

+ * Based on the Basic game of Change here + * https://github.com/coding-horror/basic-computer-games/blob/main/22%20Change/change.bas + *

+ * 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 Change { + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + INPUT, + CALCULATE, + END_GAME, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + // Amount of change needed to be given + private double change; + + public Change() { + kbScanner = new Scanner(System.in); + + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + case START_GAME: + intro(); + gameState = GAME_STATE.INPUT; + break; + + case INPUT: + + double costOfItem = displayTextAndGetNumber("COST OF ITEM "); + double amountPaid = displayTextAndGetNumber("AMOUNT OF PAYMENT "); + change = amountPaid - costOfItem; + if (change == 0) { + // No change needed + System.out.println("CORRECT AMOUNT, THANK YOU."); + gameState = GAME_STATE.END_GAME; + } else if (change < 0) { + System.out.println("YOU HAVE SHORT-CHANGES ME $" + (costOfItem - amountPaid)); + // Don't change game state so it will loop back and try again + } else { + // Change needed. + gameState = GAME_STATE.CALCULATE; + } + break; + + case CALCULATE: + System.out.println("YOUR CHANGE, $" + change); + calculateChange(); + gameState = GAME_STATE.END_GAME; + break; + + case END_GAME: + System.out.println("THANK YOU, COME AGAIN"); + System.out.println(); + gameState = GAME_STATE.INPUT; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + /** + * Calculate and output the change required for the purchase based on + * what money was paid. + */ + private void calculateChange() { + + double originalChange = change; + + int tenDollarBills = (int) change / 10; + if (tenDollarBills > 0) { + System.out.println(tenDollarBills + " TEN DOLLAR BILL(S)"); + } + change = originalChange - (tenDollarBills * 10); + + int fiveDollarBills = (int) change / 5; + if (fiveDollarBills > 0) { + System.out.println(fiveDollarBills + " FIVE DOLLAR BILL(S)"); + } + change = originalChange - (tenDollarBills * 10 + fiveDollarBills * 5); + + int oneDollarBills = (int) change; + if (oneDollarBills > 0) { + System.out.println(oneDollarBills + " ONE DOLLAR BILL(S)"); + } + change = originalChange - (tenDollarBills * 10 + fiveDollarBills * 5 + oneDollarBills); + + change = change * 100; + double cents = change; + + int halfDollars = (int) change / 50; + if (halfDollars > 0) { + System.out.println(halfDollars + " ONE HALF DOLLAR(S)"); + } + change = cents - (halfDollars * 50); + + int quarters = (int) change / 25; + if (quarters > 0) { + System.out.println(quarters + " QUARTER(S)"); + } + + change = cents - (halfDollars * 50 + quarters * 25); + + int dimes = (int) change / 10; + if (dimes > 0) { + System.out.println(dimes + " DIME(S)"); + } + + change = cents - (halfDollars * 50 + quarters * 25 + dimes * 10); + + int nickels = (int) change / 5; + if (nickels > 0) { + System.out.println(nickels + " NICKEL(S)"); + } + + change = cents - (halfDollars * 50 + quarters * 25 + dimes * 10 + nickels * 5); + + int pennies = (int) (change + .5); + if (pennies > 0) { + System.out.println(pennies + " PENNY(S)"); + } + + } + + private void intro() { + System.out.println(simulateTabs(33) + "CHANGE"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("I, YOUR FRIENDLY MICROCOMPUTER, WILL DETERMINE"); + System.out.println("THE CORRECT CHANGE FOR ITEMS COSTING UP TO $100."); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private double displayTextAndGetNumber(String text) { + return Double.parseDouble(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } +} diff --git a/22 Change/java/src/ChangeGame.java b/22 Change/java/src/ChangeGame.java new file mode 100644 index 00000000..c2863914 --- /dev/null +++ b/22 Change/java/src/ChangeGame.java @@ -0,0 +1,6 @@ +public class ChangeGame { + public static void main(String[] args) { + Change change = new Change(); + change.play(); + } +} From a352035027bb0d1790b69ca8db64f407ae0dec3c Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Thu, 25 Feb 2021 15:17:11 +1030 Subject: [PATCH 025/749] Java version of Chemist and documentation fix for method in Change --- 22 Change/java/src/Change.java | 2 +- 24 Chemist/java/src/Chemist.java | 143 +++++++++++++++++++++++++++ 24 Chemist/java/src/ChemistGame.java | 6 ++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 24 Chemist/java/src/Chemist.java create mode 100644 24 Chemist/java/src/ChemistGame.java diff --git a/22 Change/java/src/Change.java b/22 Change/java/src/Change.java index 7498be8a..38177245 100644 --- a/22 Change/java/src/Change.java +++ b/22 Change/java/src/Change.java @@ -153,7 +153,7 @@ public class Change { /* * Print a message on the screen, then accept input from Keyboard. - * Converts input to Integer + * Converts input to a Double * * @param text message to be displayed on screen. * @return what was typed by the player. diff --git a/24 Chemist/java/src/Chemist.java b/24 Chemist/java/src/Chemist.java new file mode 100644 index 00000000..137b3ce5 --- /dev/null +++ b/24 Chemist/java/src/Chemist.java @@ -0,0 +1,143 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Chemist + *

+ * Based on the Basic game of Chemist here + * https://github.com/coding-horror/basic-computer-games/blob/main/24%20Chemist/chemist.bas + *

+ * 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 Chemist { + + public static final int MAX_LIVES = 9; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + INPUT, + BLOWN_UP, + SURVIVED, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private int timesBlownUp; + + public Chemist() { + kbScanner = new Scanner(System.in); + + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case START_GAME: + intro(); + timesBlownUp = 0; + gameState = GAME_STATE.INPUT; + break; + + case INPUT: + + int amountOfAcid = (int) (Math.random() * 50); + int correctAmountOfWater = (7 * amountOfAcid) / 3; + int water = displayTextAndGetNumber(amountOfAcid + " LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER? "); + + // Calculate if the player mixed enough water + int result = Math.abs(correctAmountOfWater - water); + + // Ratio of water wrong? + if (result > (correctAmountOfWater / 20)) { + gameState = GAME_STATE.BLOWN_UP; + } else { + // Got the ratio correct + gameState = GAME_STATE.SURVIVED; + } + break; + + case BLOWN_UP: + System.out.println(" SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB"); + System.out.println(" OF QUIVERING PROTOPLASM!"); + + timesBlownUp++; + + if (timesBlownUp < MAX_LIVES) { + System.out.println(" HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE."); + gameState = GAME_STATE.INPUT; + } else { + System.out.println(" YOUR " + MAX_LIVES + " LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR"); + System.out.println(" YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY."); + gameState = GAME_STATE.GAME_OVER; + } + + break; + + case SURVIVED: + System.out.println(" GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!"); + System.out.println(); + gameState = GAME_STATE.INPUT; + break; + + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(33) + "CHEMIST"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THE FICTITIOUS CHEMICAL KRYPTOCYANIC ACID CAN ONLY BE"); + System.out.println("DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID."); + System.out.println("IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE"); + System.out.println("AND SOON EXPLODES. GIVEN THE AMOUNT OF ACID, YOU MUST"); + System.out.println("DECIDE WHO MUCH WATER TO ADD FOR DILUTION. IF YOU MISS"); + System.out.println("YOU FACE THE CONSEQUENCES."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } +} diff --git a/24 Chemist/java/src/ChemistGame.java b/24 Chemist/java/src/ChemistGame.java new file mode 100644 index 00000000..494959a3 --- /dev/null +++ b/24 Chemist/java/src/ChemistGame.java @@ -0,0 +1,6 @@ +public class ChemistGame { + public static void main(String[] args) { + Chemist chemist = new Chemist(); + chemist.play(); + } +} From 9d0e16265e656b18935523e4a38cc31ea53628ed Mon Sep 17 00:00:00 2001 From: nanochess Date: Thu, 25 Feb 2021 15:06:21 -0600 Subject: [PATCH 026/749] Ported BASKETBALL, BATNUM and CHOMP to Javascript --- 07 Basketball/javascript/basketball.html | 9 + 07 Basketball/javascript/basketball.js | 384 +++++++++++++++++++++++ 08 Batnum/javascript/batnum.html | 9 + 08 Batnum/javascript/batnum.js | 161 ++++++++++ 26 Chomp/chomp.bas | 2 +- 26 Chomp/javascript/chomp.html | 9 + 26 Chomp/javascript/chomp.js | 175 +++++++++++ 7 files changed, 748 insertions(+), 1 deletion(-) create mode 100644 07 Basketball/javascript/basketball.html create mode 100644 07 Basketball/javascript/basketball.js create mode 100644 08 Batnum/javascript/batnum.html create mode 100644 08 Batnum/javascript/batnum.js create mode 100644 26 Chomp/javascript/chomp.html create mode 100644 26 Chomp/javascript/chomp.js diff --git a/07 Basketball/javascript/basketball.html b/07 Basketball/javascript/basketball.html new file mode 100644 index 00000000..e9eedab3 --- /dev/null +++ b/07 Basketball/javascript/basketball.html @@ -0,0 +1,9 @@ + + +BASKETBALL + + +


+
+
+
diff --git a/07 Basketball/javascript/basketball.js b/07 Basketball/javascript/basketball.js
new file mode 100644
index 00000000..5b0b73e7
--- /dev/null
+++ b/07 Basketball/javascript/basketball.js	
@@ -0,0 +1,384 @@
+// BASKETBALL
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var s = [0, 0];
+var z;
+var d;
+var p;
+var your_turn;
+var game_restart;
+
+function two_minutes()
+{
+    print("\n");
+    print("   *** TWO MINUTES LEFT IN THE GAME ***\n");
+    print("\n");
+}
+
+function show_scores()
+{
+    print("SCORE: " + s[1] + " TO " + s[0] + "\n");
+}
+
+function score_computer()
+{
+    s[0] = s[0] + 2;
+    show_scores();
+}
+
+function score_player()
+{
+    s[1] = s[1] + 2;
+    show_scores();
+}
+
+function half_time()
+{
+    print("\n");
+    print("   ***** END OF FIRST HALF *****\n");
+    print("SCORE: DARMOUTH: " + s[1] + "  " + os + ": " + s[0] + "\n");
+    print("\n");
+    print("\n");
+}
+
+function foul()
+{
+    if (Math.random() <= 0.49) {
+        print("SHOOTER MAKES BOTH SHOTS.\n");
+        s[1 - p] = s[1 - p] + 2;
+        show_scores();
+    } else if (Math.random() <= 0.75) {
+        print("SHOOTER MAKES ONE SHOT AND MISSES ONE.\n");
+        s[1 - p] = s[1 - p] + 1;
+        show_scores();
+    } else {
+        print("BOTH SHOTS MISSED.\n");
+        show_scores();
+    }
+}
+
+function player_play()
+{
+    if (z == 1 || z == 2) {
+        t++;
+        if (t == 50) {
+            half_time();
+            game_restart = 1;
+            return;
+        }
+        if (t == 92)
+            two_minutes();
+        print("JUMP SHOT\n");
+        if (Math.random() <= 0.341 * d / 8) {
+            print("SHOT IS GOOD.\n");
+            score_player();
+            return;
+        }
+        if (Math.random() <= 0.682 * d / 8) {
+            print("SHOT IS OFF TARGET.\n");
+            if (d / 6 * Math.random() >= 0.45) {
+                print("REBOUND TO " + os + "\n");
+                return;
+            }
+            print("DARTMOUTH CONTROLS THE REBOUND.\n");
+            if (Math.random() > 0.4) {
+                if (d == 6) {
+                    if (Math.random() > 0.6) {
+                        print("PASS STOLEN BY " + os + " EASY LAYUP.\n");
+                        score_computer();
+                        return;
+                    }
+                }
+                print("BALL PASSED BACK TO YOU. ");
+                your_turn = 1;
+                return;
+            }
+        } else if (Math.random() <= 0.782 * d / 8) {
+            print("SHOT IS BLOCKED.  BALL CONTROLLED BY ");
+            if (Math.random() <= 0.5) {
+                print("DARTMOUTH.\n");
+                your_turn = 1;
+                return;
+            }
+            print(os + ".\n");
+            return;
+        } else if (Math.random() <= 0.843 * d / 8) {
+            print("SHOOTER IS FOULED.  TWO SHOTS.\n");
+            foul();
+            return;
+            // In original code but lines 1180-1195 aren't used (maybe replicate from computer's play)
+            //        } else if (Math.random() <= 0.9 * d / 8) {
+            //            print("PLAYER FOULED, TWO SHOTS.\n");
+            //            foul();
+            //            return;
+        } else {
+            print("CHARGING FOUL.  DARTMOUTH LOSES BALL.\n");
+            return;
+        }
+    }
+    while (1) {
+        if (++t == 50) {
+            half_time();
+            game_restart = 1;
+            return;
+        }
+        if (t == 92)
+            two_minutes();
+        if (z == 0) {
+            your_turn = 2;
+            return;
+        }
+        if (z <= 3)
+            print("LAY UP.\n");
+        else
+            print("SET SHOT.\n");
+        if (7 / d * Math.random() <= 0.4) {
+            print("SHOT IS GOOD.  TWO POINTS.\n");
+            score_player();
+            return;
+        }
+        if (7 / d * Math.random() <= 0.7) {
+            print("SHOT IS OFF THE RIM.\n");
+            if (Math.random() <= 2.0 / 3.0) {
+                print(os + " CONTROLS THE REBOUND.\n");
+                return;
+            }
+            print("DARMOUTH CONTROLS THE REBOUND.\n");
+            if (Math.random() <= 0.4)
+                continue;
+            print("BALL PASSED BACK TO YOU.\n");
+            your_turn = 1;
+            return;
+        }
+        if (7 /d * Math.random() <= 0.875) {
+            print("SHOOTER FOULED.  TWO SHOTS.\n");
+            foul();
+            return;
+        }
+        if (7 /d * Math.random() <= 0.925) {
+            print("SHOT BLOCKED. " + os + "'S BALL.\n");
+            return;
+        }
+        print("CHARGING FOUL.  DARTHMOUTH LOSES THE BALL.\n");
+        return;
+    }
+}
+
+function computer_play()
+{
+    rebound = 0;
+    while (1) {
+        p = 1;
+        if (++t == 50) {
+            half_time();
+            game_restart = 1;
+            return;
+        }
+        print("\n");
+        z1 = 10 / 4 * Math.random() + 1;
+        if (z1 <= 2) {
+            print("JUMP SHOT.\n");
+            if (8 / d * Math.random() <= 0.35) {
+                print("SHOT IS GOOD.\n");
+                score_computer();
+                return;
+            }
+            if (8 / d * Math.random() <= 0.75) {
+                print("SHOT IS OFF RIM.\n");
+                if (d / 6 * Math.random() <= 0.5) {
+                    print("DARMOUTH CONTROLS THE REBOUND.\n");
+                    return;
+                }
+                print(os + " CONTROLS THE REBOUND.\n");
+                if (d == 6) {
+                    if (Math.random() <= 0.75) {
+                        print("BALL STOLEN.  EASY LAP UP FOR DARTMOUTH.\n");
+                        score_player();
+                        continue;
+                    }
+                    if (Math.random() > 0.6) {
+                        print("PASS STOLEN BY " + os + " EASY LAYUP.\n");
+                        score_computer();
+                        return;
+                    }
+                    print("BALL PASSED BACK TO YOU. ");
+                    return;
+                }
+                if (Math.random() <= 0.5) {
+                    print("PASS BACK TO " + os + " GUARD.\n");
+                    continue;
+                }
+            } else if (8 / d * Math.random() <= 0.90) {
+                print("PLAYER FOULED.  TWO SHOTS.\n");
+                foul();
+                return;
+            } else {
+                print("OFFENSIVE FOUL.  DARTMOUTH'S BALL.\n");
+                return;
+            }
+        }
+        while (1) {
+            if (z1 > 3) {
+                print("SET SHOT.\n");
+            } else {
+                print("LAY UP.\n");
+            }
+            if (7 / d * Math.random() <= 0.413) {
+                print("SHOT IS GOOD.\n");
+                score_computer();
+                return;
+            }
+            print("SHOT IS MISSED.\n");
+            // Spaguetti jump, better to replicate code
+            if (d / 6 * Math.random() <= 0.5) {
+                print("DARMOUTH CONTROLS THE REBOUND.\n");
+                return;
+            }
+            print(os + " CONTROLS THE REBOUND.\n");
+            if (d == 6) {
+                if (Math.random() <= 0.75) {
+                    print("BALL STOLEN.  EASY LAP UP FOR DARTMOUTH.\n");
+                    score_player();
+                    break;
+                }
+                if (Math.random() > 0.6) {
+                    print("PASS STOLEN BY " + os + " EASY LAYUP.\n");
+                    score_computer();
+                    return;
+                }
+                print("BALL PASSED BACK TO YOU. ");
+                return;
+            }
+            if (Math.random() <= 0.5) {
+                print("PASS BACK TO " + os + " GUARD.\n");
+                break;
+            }
+        }
+    }
+}
+
+// Main program
+async function main()
+{
+    print(tab(31) + "BASKETBALL\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS IS DARTMOUTH COLLEGE BASKETBALL.  YOU WILL BE DARTMOUTH\n");
+    print(" CAPTAIN AND PLAYMAKER.  CALL SHOTS AS FOLLOWS:  1. LONG\n");
+    print(" (30 FT.) JUMP SHOT; 2. SHORT (15 FT.) JUMP SHOT; 3. LAY\n");
+    print(" UP; 4. SET SHOT.\n");
+    print("BOTH TEAMS WILL USE THE SAME DEFENSE.  CALL DEFENSE AS\n");
+    print("FOLLOWS:  6. PRESS; 6.5 MAN-TO MAN; 7. ZONE; 7.5 NONE.\n");
+    print("TO CHANGE DEFENSE, JUST TYPE 0 AS YOUR NEXT SHOT.\n");
+    print("YOUR STARTING DEFENSE WILL BE");
+    t = 0;
+    p = 0;
+    d = parseFloat(await input());
+    if (d < 6) {
+        your_turn = 2;
+    } else {
+        print("\n");
+        print("CHOOSE YOUR OPPONENT");
+        os = await input();
+        game_restart = 1;
+    }
+    while (1) {
+        if (game_restart) {
+            game_restart = 0;
+            print("CENTER JUMP\n");
+            if (Math.random() > 3.0 / 5.0) {
+                print("DARMOUTH CONTROLS THE TAP.\n");
+            } else {
+                print(os + " CONTROLS THE TAP.\n");
+                computer_play();
+            }
+        }
+        if (your_turn == 2) {
+            print("YOUR NEW DEFENSIVE ALLIGNMENT IS");
+            d = parseFloat(await input());
+        }
+        print("\n");
+        while (1) {
+            print("YOUR SHOT");
+            z = parseInt(await input());
+            p = 0;
+            if (z != Math.floor(z) || z < 0 || z > 4)
+                print("INCORRECT ANSWER.  RETYPE IT. ");
+            else
+                break;
+        }
+        if (Math.random() < 0.5 || t < 100) {
+            game_restart = 0;
+            your_turn = 0;
+            player_play();
+            if (game_restart == 0 && your_turn == 0)
+                computer_play();
+        } else {
+            print("\n");
+            if (s[1] == s[0]) {
+                print("\n");
+                print("   ***** END OF SECOND HALF *****\n");
+                print("\n");
+                print("SCORE AT END OF REGULATION TIME:\n");
+                print("        DARTMOUTH: " + s[1] + "  " + os + ": " + s[0] + "\n");
+                print("\n");
+                print("BEGIN TWO MINUTE OVERTIME PERIOD\n");
+                t = 93;
+                print("CENTER JUMP\n");
+                if (Math.random() > 3.0 / 5.0)
+                    print("DARMOUTH CONTROLS THE TAP.\n");
+                else
+                    print(os + " CONTROLS THE TAP.\n");
+            } else {
+                print("   ***** END OF GAME *****\n");
+                print("FINAL SCORE: DARMOUTH: " + s[1] + "  " + os + ": " + s[0] + "\n");
+                break;
+            }
+        }
+    }
+}
+
+main();
diff --git a/08 Batnum/javascript/batnum.html b/08 Batnum/javascript/batnum.html
new file mode 100644
index 00000000..51d8dd11
--- /dev/null
+++ b/08 Batnum/javascript/batnum.html	
@@ -0,0 +1,9 @@
+
+
+BATNUM
+
+
+

+
+
+
diff --git a/08 Batnum/javascript/batnum.js b/08 Batnum/javascript/batnum.js
new file mode 100644
index 00000000..c7d25b78
--- /dev/null
+++ b/08 Batnum/javascript/batnum.js	
@@ -0,0 +1,161 @@
+// BATNUM
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "BATNUM\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE\n");
+    print("COMPUTER IS YOUR OPPONENT.\n");
+    print("\n");
+    print("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU\n");
+    print("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.\n");
+    print("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR\n");
+    print("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.\n");
+    print("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.\n");
+    print("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.\n");
+    print("\n");
+    first_time = 1;
+    while (1) {
+        while (1) {
+            if (first_time == 1) {
+                first_time = 0;
+            } else {
+                for (i = 1; i <= 10; i++)
+                    print("\n");
+            }
+            print("ENTER PILE SIZE");
+            n = parseInt(await input());
+            if (n >= 1)
+                break;
+        }
+        while (1) {
+            print("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ");
+            m = parseInt(await input());
+            if (m == 1 || m == 2)
+                break;
+        }
+        while (1) {
+            print("ENTER MIN AND MAX ");
+            str = await input();
+            a = parseInt(str);
+            b = parseInt(str.substr(str.indexOf(",") + 1));
+            if (a <= b && a >= 1)
+                break;
+        }
+        while (1) {
+            print("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ");
+            s = parseInt(await input());
+            print("\n");
+            print("\n");
+            if (s == 1 || s == 2)
+                break;
+        }
+        w = 0;
+        c = a + b;
+        while (1) {
+            if (s == 1) {
+                // Computer's turn
+                q = n;
+                if (m != 1)
+                    q--;
+                if (m != 1 && n <= a) {
+                    w = 1;
+                    print("COMPUTER TAKES " + n + " AND LOSES.\n");
+                } else if (m == 1 && n <= b) {
+                    w = 1;
+                    print("COMPUTER TAKES " + n + " AND WINS.\n");
+                } else {
+                    p = q - c * Math.floor(q / c);
+                    if (p < a)
+                        p = a;
+                    if (p > b)
+                        p = b;
+                    n -= p;
+                    print("COMPUTER TAKES " + p + " AND LEAVES " + n + "\n");
+                    w = 0;
+                }
+                s = 2;
+            }
+            if (w)
+                break;
+            if (s == 2) {
+                while (1) {
+                    print("\n");
+                    print("YOUR MOVE ");
+                    p = parseInt(await input());
+                    if (p == 0) {
+                        print("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.\n");
+                        w = 1;
+                        break;
+                    } else if (p >= a && p <= b && n - p >= 0) {
+                        break;
+                    }
+                }
+                if (p != 0) {
+                    n -= p;
+                    if (n == 0) {
+                        if (m != 1) {
+                            print("TOUGH LUCK, YOU LOSE.\n");
+                        } else {
+                            print("CONGRATULATIONS, YOU WIN.\n");
+                        }
+                        w = 1;
+                    } else {
+                        w = 0;
+                    }
+                }
+                s = 1;
+            }
+            if (w)
+                break;
+        }
+    }
+}
+
+main();
diff --git a/26 Chomp/chomp.bas b/26 Chomp/chomp.bas
index 26d0296b..50e5e232 100644
--- a/26 Chomp/chomp.bas	
+++ b/26 Chomp/chomp.bas	
@@ -99,6 +99,6 @@
 1010 PRINT "YOU LOSE, PLAYER";P1
 1020 PRINT 
 1030 PRINT "AGAIN (1=YES, 0=NO!)";
-1040 INPUT R$
+1040 INPUT R
 1050 IF R=1 THEN 340
 1060 END
diff --git a/26 Chomp/javascript/chomp.html b/26 Chomp/javascript/chomp.html
new file mode 100644
index 00000000..b749afe3
--- /dev/null
+++ b/26 Chomp/javascript/chomp.html	
@@ -0,0 +1,9 @@
+
+
+CHOMP
+
+
+

+
+
+
diff --git a/26 Chomp/javascript/chomp.js b/26 Chomp/javascript/chomp.js
new file mode 100644
index 00000000..652023e6
--- /dev/null
+++ b/26 Chomp/javascript/chomp.js	
@@ -0,0 +1,175 @@
+// CHOMP
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a = [];
+var r;
+var c;
+
+function init_board()
+{
+    for (i = 1; i <= r; i++)
+        for (j = 1; j <= c; j++)
+            a[i][j] = 1;
+    a[1][1] = -1;
+}
+
+function show_board()
+{
+    print("\n");
+    print(tab(7) + "1 2 3 4 5 6 7 8 9\n");
+    for (i = 1; i <= r; i++) {
+        str = i + tab(6);
+        for (j = 1; j <= c; j++) {
+            if (a[i][j] == -1)
+                str += "P ";
+            else if (a[i][j] == 0)
+                break;
+            else
+                str += "* ";
+        }
+        print(str + "\n");
+    }
+    print("\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "CHOMP\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 1; i <= 10; i++)
+        a[i] = [];
+    // *** THE GAME OF CHOMP *** COPYRIGHT PCC 1973 ***
+    print("\n");
+    print("THIS IS THE GAME OF CHOMP (SCIENTIFIC AMERICAN, JAN 1973)\n");
+    print("DO YOU WANT THE RULES (1=YES, 0=NO!)");
+    r = parseInt(await input());
+    if (r != 0) {
+        f = 1;
+        r = 5;
+        c = 7;
+        print("CHOMP IS FOR 1 OR MORE PLAYERS (HUMANS ONLY).\n");
+        print("\n");
+        print("HERE'S HOW A BOARD LOOKS (THIS ONE IS 5 BY 7):\n");
+        init_board();
+        show_board();
+        print("\n");
+        print("THE BOARD IS A BIG COOKIE - R ROWS HIGH AND C COLUMNS\n");
+        print("WIDE. YOU INPUT R AND C AT THE START. IN THE UPPER LEFT\n");
+        print("CORNER OF THE COOKIE IS A POISON SQUARE (P). THE ONE WHO\n");
+        print("CHOMPS THE POISON SQUARE LOSES. TO TAKE A CHOMP, TYPE THE\n");
+        print("ROW AND COLUMN OF ONE OF THE SQUARES ON THE COOKIE.\n");
+        print("ALL OF THE SQUARES BELOW AND TO THE RIGHT OF THAT SQUARE\n");
+        print("INCLUDING THAT SQUARE, TOO) DISAPPEAR -- CHOMP!!\n");
+        print("NO FAIR CHOMPING SQUARES THAT HAVE ALREADY BEEN CHOMPED,\n");
+        print("OR THAT ARE OUTSIDE THE ORIGINAL DIMENSIONS OF THE COOKIE.\n");
+        print("\n");
+    }
+    while (1) {
+        print("HERE WE GO...\n");
+        f = 0;
+        for (i = 1; i <= 10; i++) {
+            a[i] = [];
+            for (j = 1; j <= 10; j++) {
+                a[i][j] = 0;
+            }
+        }
+        print("\n");
+        print("HOW MANY PLAYERS");
+        p = parseInt(await input());
+        i1 = 0;
+        while (1) {
+            print("HOW MANY ROWS");
+            r = parseInt(await input());
+            if (r <= 9)
+                break;
+            print("TOO MANY ROWS (9 IS MAXIMUM). NOW ");
+        }
+        while (1) {
+            print("HOW MANY COLUMNS");
+            c = parseInt(await input());
+            if (c <= 9)
+                break;
+            print("TOO MANY COLUMNS (9 IS MAXIMUM). NOW ");
+        }
+        print("\n");
+        init_board();
+        while (1) {
+            // Print the board
+            show_board();
+            // Get chomps for each player in turn
+            i1++;
+            p1 = i1 - Math.floor(i1 / p) * p;
+            if (p1 == 0)
+                p1 = p;
+            while (1) {
+                print("PLAYER " + p1 + "\n");
+                print("COORDINATES OF CHOMP (ROW,COLUMN)");
+                str = await input();
+                r1 = parseInt(str);
+                c1 = parseInt(str.substr(str.indexOf(",") + 1));
+                if (r1 >= 1 && r1 <= r && c1 >= 1 && c1 <= c && a[r1][c1] != 0)
+                    break;
+                print("NO FAIR. YOU'RE TRYING TO CHOMP ON EMPTY SPACE!\n");
+            }
+            if (a[r1][c1] == -1)
+                break;
+            for (i = r1; i <= r; i++)
+                for (j = c1; j <= c; j++)
+                    a[i][j] = 0;
+        }
+        // End of game detected
+        print("YOU LOSE, PLAYER " + p1 + "\n");
+        print("\n");
+        print("AGAIN (1=YES, 0=NO!)");
+        r = parseInt(await input());
+        if (r != 1)
+            break;
+    }
+}
+
+main();

From e56119809147c4f827f9d3527208dcf91ac70678 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Fri, 26 Feb 2021 07:41:40 +1030
Subject: [PATCH 027/749] Java version of dice

---
 33 Dice/java/src/Dice.java     | 146 +++++++++++++++++++++++++++++++++
 33 Dice/java/src/DiceGame.java |   6 ++
 2 files changed, 152 insertions(+)
 create mode 100644 33 Dice/java/src/Dice.java
 create mode 100644 33 Dice/java/src/DiceGame.java

diff --git a/33 Dice/java/src/Dice.java b/33 Dice/java/src/Dice.java
new file mode 100644
index 00000000..739b2084
--- /dev/null
+++ b/33 Dice/java/src/Dice.java	
@@ -0,0 +1,146 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Dice
+ * 

+ * Based on the Basic game of Dice here + * https://github.com/coding-horror/basic-computer-games/blob/main/33%20Dice/dice.bas + *

+ * 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 Dice { + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + INPUT_AND_CALCULATE, + RESULTS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private int[] spots; + + public Dice() { + kbScanner = new Scanner(System.in); + + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case START_GAME: + intro(); + spots = new int[12]; + gameState = GAME_STATE.INPUT_AND_CALCULATE; + break; + + case INPUT_AND_CALCULATE: + + int howManyRolls = displayTextAndGetNumber("HOW MANY ROLLS? "); + for (int i = 0; i < howManyRolls; i++) { + int diceRoll = (int) (Math.random() * 6 + 1) + (int) (Math.random() * 6 + 1); + // save dice roll in zero based array + spots[diceRoll - 1]++; + } + gameState = GAME_STATE.RESULTS; + break; + + case RESULTS: + System.out.println("TOTAL SPOTS" + simulateTabs(8) + "NUMBER OF TIMES"); + for (int i = 1; i < 12; i++) { + // show output using zero based array + System.out.println(simulateTabs(5) + (i + 1) + simulateTabs(20) + spots[i]); + } + System.out.println(); + if (yesEntered(displayTextAndGetInput("TRY AGAIN? "))) { + gameState = GAME_STATE.START_GAME; + } else { + gameState = GAME_STATE.GAME_OVER; + } + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(34) + "DICE"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THIS PROGRAM SIMULATES THE ROLLING OF A"); + System.out.println("PAIR OF DICE."); + System.out.println("YOU ENTER THE NUMBER OF TIMES YOU WANT THE COMPUTER TO"); + System.out.println("'ROLL' THE DICE. WATCH OUT, VERY LARGE NUMBERS TAKE"); + System.out.println("A LONG TIME. IN PARTICULAR, NUMBERS OVER 5000."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } +} diff --git a/33 Dice/java/src/DiceGame.java b/33 Dice/java/src/DiceGame.java new file mode 100644 index 00000000..97f24e61 --- /dev/null +++ b/33 Dice/java/src/DiceGame.java @@ -0,0 +1,6 @@ +public class DiceGame { + public static void main(String[] args) { + Dice dice = new Dice(); + dice.play(); + } +} From c53b02b95eb9f2476295028f11fceb85723ff9cb Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Fri, 26 Feb 2021 08:11:01 +1030 Subject: [PATCH 028/749] Java version of Guess --- 41 Guess/java/src/Guess.java | 161 +++++++++++++++++++++++++++++++ 41 Guess/java/src/GuessGame.java | 6 ++ 2 files changed, 167 insertions(+) create mode 100644 41 Guess/java/src/Guess.java create mode 100644 41 Guess/java/src/GuessGame.java diff --git a/41 Guess/java/src/Guess.java b/41 Guess/java/src/Guess.java new file mode 100644 index 00000000..6e23b5f2 --- /dev/null +++ b/41 Guess/java/src/Guess.java @@ -0,0 +1,161 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Guess + *

+ * Based on the Basic game of Dice here + * https://github.com/coding-horror/basic-computer-games/blob/main/41%20Guess/guess.bas + *

+ * 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 Guess { + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + STARTUP, + INPUT_RANGE, + DEFINE_COMPUTERS_NUMBER, + GUESS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + // User supplied maximum number to guess + private int limit; + + // Computers calculated number for the player to guess + + private int computersNumber; + + // Number of turns the player has had guessing + private int tries; + + // Optimal number of turns it should take to guess + private int calculatedTurns; + + public Guess() { + kbScanner = new Scanner(System.in); + + gameState = GAME_STATE.STARTUP; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case STARTUP: + intro(); + gameState = GAME_STATE.INPUT_RANGE; + break; + + case INPUT_RANGE: + + limit = displayTextAndGetNumber("WHAT LIMIT DO YOU WANT? "); + calculatedTurns = (int) (Math.log(limit) / Math.log(2)) + 1; + gameState = GAME_STATE.DEFINE_COMPUTERS_NUMBER; + break; + + case DEFINE_COMPUTERS_NUMBER: + + tries = 1; + System.out.println("I'M THINKING OF A NUMBER BETWEEN 1 AND " + limit); + computersNumber = (int) (Math.random() * limit + 1); + + gameState = GAME_STATE.GUESS; + break; + + case GUESS: + int playersGuess = displayTextAndGetNumber("NOW YOU TRY TO GUESS WHAT IT IS "); + + // Allow player to restart game with entry of 0 + if (playersGuess == 0) { + linePadding(); + gameState = GAME_STATE.STARTUP; + break; + } + + if (playersGuess == computersNumber) { + System.out.println("THAT'S IT! YOU GOT IT IN " + tries + " TRIES."); + if (tries < calculatedTurns) { + System.out.println("VERY "); + } + System.out.println("GOOD."); + System.out.println("YOU SHOULD HAVE BEEN ABLE TO GET IT IN ONLY " + calculatedTurns); + linePadding(); + gameState = GAME_STATE.DEFINE_COMPUTERS_NUMBER; + break; + } else if (playersGuess < computersNumber) { + System.out.println("TOO LOW. TRY A BIGGER ANSWER."); + } else { + System.out.println("TOO HIGH. TRY A SMALLER ANSWER."); + } + tries++; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(33) + "GUESS"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THIS IS A NUMBER GUESSING GAME. I'LL THINK"); + System.out.println("OF A NUMBER BETWEEN 1 AND ANY LIMIT YOU WANT."); + System.out.println("THEN YOU HAVE TO GUESS WHAT IT IS."); + } + + /** + * Print a predefined number of blank lines + * + */ + private void linePadding() { + for (int i = 1; i <= 5; i++) { + System.out.println(); + } + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + +} diff --git a/41 Guess/java/src/GuessGame.java b/41 Guess/java/src/GuessGame.java new file mode 100644 index 00000000..603cdbfb --- /dev/null +++ b/41 Guess/java/src/GuessGame.java @@ -0,0 +1,6 @@ +public class GuessGame { + public static void main(String[] args) { + Guess guess = new Guess(); + guess.play(); + } +} From 9da95259134680e3626495c74275382522297aac Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Fri, 26 Feb 2021 08:12:49 +1030 Subject: [PATCH 029/749] Adjust game name in comment --- 41 Guess/java/src/Guess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/41 Guess/java/src/Guess.java b/41 Guess/java/src/Guess.java index 6e23b5f2..667411ab 100644 --- a/41 Guess/java/src/Guess.java +++ b/41 Guess/java/src/Guess.java @@ -4,7 +4,7 @@ import java.util.Scanner; /** * Game of Guess *

- * Based on the Basic game of Dice here + * Based on the Basic game of Guess here * https://github.com/coding-horror/basic-computer-games/blob/main/41%20Guess/guess.bas *

* Note: The idea was to create a version of the 1970's Basic game in Java, without introducing From 9bb8fa49fc1ec1d211da3feb0034c8bbaf17b5f6 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Fri, 26 Feb 2021 13:42:39 +1030 Subject: [PATCH 030/749] Java version of Kinema --- 52 Kinema/java/src/Kinema.java | 176 +++++++++++++++++++++++++++++ 52 Kinema/java/src/KinemaGame.java | 7 ++ 2 files changed, 183 insertions(+) create mode 100644 52 Kinema/java/src/Kinema.java create mode 100644 52 Kinema/java/src/KinemaGame.java diff --git a/52 Kinema/java/src/Kinema.java b/52 Kinema/java/src/Kinema.java new file mode 100644 index 00000000..afbacbe8 --- /dev/null +++ b/52 Kinema/java/src/Kinema.java @@ -0,0 +1,176 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Kinema + *

+ * Based on the Basic game of Kinema here + * https://github.com/coding-horror/basic-computer-games/blob/main/52%20Kinema/kinema.bas + *

+ * 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 Kinema { + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + STARTUP, + INIT, + HOW_HIGH, + SECONDS_TILL_IT_RETURNS, + ITS_VELOCITY, + RESULTS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private int numberAnswersCorrect; + + // How many meters per second a ball is thrown + private int velocity; + + public Kinema() { + kbScanner = new Scanner(System.in); + + gameState = GAME_STATE.STARTUP; + } + + /** + * Main game loop + */ + public void play() { + + double playerAnswer; + double correctAnswer; + do { + switch (gameState) { + + case STARTUP: + intro(); + gameState = GAME_STATE.INIT; + break; + + case INIT: + numberAnswersCorrect = 0; + + // calculate a random velocity for the player to use in the calculations + velocity = 5 + (int) (35 * Math.random()); + System.out.println("A BALL IS THROWN UPWARDS AT " + velocity + " METERS PER SECOND."); + gameState = GAME_STATE.HOW_HIGH; + break; + + case HOW_HIGH: + + playerAnswer = displayTextAndGetNumber("HOW HIGH WILL IT GO (IN METERS)? "); + + // Calculate the correct answer to how high it will go + correctAnswer = 0.05 * Math.pow(velocity, 2); + if (calculate(playerAnswer, correctAnswer)) { + numberAnswersCorrect++; + } + gameState = GAME_STATE.ITS_VELOCITY; + break; + + case ITS_VELOCITY: + + playerAnswer = displayTextAndGetNumber("HOW LONG UNTIL IT RETURNS (IN SECONDS)? "); + + // Calculate current Answer for how long until it returns to the ground in seconds + correctAnswer = (double) velocity / 5; + if (calculate(playerAnswer, correctAnswer)) { + numberAnswersCorrect++; + } + gameState = GAME_STATE.SECONDS_TILL_IT_RETURNS; + break; + + case SECONDS_TILL_IT_RETURNS: + + // Calculate random number of seconds for 3rd question + double seconds = 1 + (Math.random() * (2 * velocity)) / 10; + + // Round to one decimal place. + double scale = Math.pow(10, 1); + seconds = Math.round(seconds * scale) / scale; + + playerAnswer = displayTextAndGetNumber("WHAT WILL ITS VELOCITY BE AFTER " + seconds + " SECONDS? "); + + // Calculate the velocity after the given number of seconds + correctAnswer = velocity - (10 * seconds); + if (calculate(playerAnswer, correctAnswer)) { + numberAnswersCorrect++; + } + gameState = GAME_STATE.RESULTS; + break; + + case RESULTS: + System.out.println(numberAnswersCorrect + " RIGHT OUT OF 3"); + if (numberAnswersCorrect > 1) { + System.out.println(" NOT BAD."); + } + gameState = GAME_STATE.STARTUP; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(33) + "KINEMA"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + } + + private boolean calculate(double playerAnswer, double correctAnswer) { + + boolean gotItRight = false; + + if (Math.abs((playerAnswer - correctAnswer) / correctAnswer) < 0.15) { + System.out.println("CLOSE ENOUGH"); + gotItRight = true; + } else { + System.out.println("NOT EVEN CLOSE"); + } + System.out.println("CORRECT ANSWER IS " + correctAnswer); + System.out.println(); + + return gotItRight; + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to a Double + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private double displayTextAndGetNumber(String text) { + return Double.parseDouble(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + +} diff --git a/52 Kinema/java/src/KinemaGame.java b/52 Kinema/java/src/KinemaGame.java new file mode 100644 index 00000000..b84d0019 --- /dev/null +++ b/52 Kinema/java/src/KinemaGame.java @@ -0,0 +1,7 @@ +public class KinemaGame { + public static void main(String[] args) { + + Kinema kinema = new Kinema(); + kinema.play(); + } +} From 528b4d7a4a8f55d71607ff5d331dd9b973745797 Mon Sep 17 00:00:00 2001 From: nanochess Date: Thu, 25 Feb 2021 22:16:47 -0600 Subject: [PATCH 031/749] Ported BOWLING, BOXING and BUG to Javascript --- 14 Bowling/javascript/bowling.html | 9 + 14 Bowling/javascript/bowling.js | 179 +++++++++++++++ 15 Boxing/javascript/boxing.html | 9 + 15 Boxing/javascript/boxing.js | 212 ++++++++++++++++++ 16 Bug/javascript/bug.html | 9 + 16 Bug/javascript/bug.js | 347 +++++++++++++++++++++++++++++ 6 files changed, 765 insertions(+) create mode 100644 14 Bowling/javascript/bowling.html create mode 100644 14 Bowling/javascript/bowling.js create mode 100644 15 Boxing/javascript/boxing.html create mode 100644 15 Boxing/javascript/boxing.js create mode 100644 16 Bug/javascript/bug.html create mode 100644 16 Bug/javascript/bug.js diff --git a/14 Bowling/javascript/bowling.html b/14 Bowling/javascript/bowling.html new file mode 100644 index 00000000..bb5d3225 --- /dev/null +++ b/14 Bowling/javascript/bowling.html @@ -0,0 +1,9 @@ + + +BOWLING + + +


+
+
+
diff --git a/14 Bowling/javascript/bowling.js b/14 Bowling/javascript/bowling.js
new file mode 100644
index 00000000..056397cb
--- /dev/null
+++ b/14 Bowling/javascript/bowling.js	
@@ -0,0 +1,179 @@
+// BOWLING
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "BOWL\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    c = [];
+    a = [];
+    for (i = 0; i <= 15; i++)
+        c[i] = 0;
+    print("WELCOME TO THE ALLEY\n");
+    print("BRING YOUR FRIENDS\n");
+    print("OKAY LET'S FIRST GET ACQUAINTED\n");
+    print("\n");
+    print("THE INSTRUCTIONS (Y/N)\n");
+    str = await input();
+    if (str.substr(0, 1) == "Y") {
+        print("THE GAME OF BOWLING TAKES MIND AND SKILL.DURING THE GAME\n");
+        print("THE COMPUTER WILL KEEP SCORE.YOU MAY COMPETE WITH\n");
+        print("OTHER PLAYERS[UP TO FOUR].YOU WILL BE PLAYING TEN FRAMES\n");
+        print("ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE\n");
+        print("PIN IS STANDING.AFTER THE GAME THE COMPUTER WILL SHOW YOUR\n");
+        print("SCORES .\n");
+    }
+    print("FIRST OF ALL...HOW MANY ARE PLAYING");
+    r = parseInt(await input());
+    while (1) {
+        print("\n");
+        print("VERY GOOD...\n");
+        for (i = 1; i <= 100; i++) {
+            a[i] = [];
+            for (j = 1; j <= 6; j++)
+                a[i][j] = 0;
+        }
+        f = 1;
+        do {
+            for (p = 1; p <= r; p++) {
+                // m = 0; // Repeated in original
+                b = 1;
+                m = 0;
+                q = 0;
+                for (i = 1; i <= 15; i++)
+                    c[i] = 0;
+                while (1) {
+                    // Ball generator using mod '15' system
+                    print("TYPE ROLL TO GET THE BALL GOING.\n");
+                    ns = await input();
+                    k = 0;
+                    d = 0;
+                    for (i = 1; i <= 20; i++) {
+                        x = Math.floor(Math.random() * 100);
+                        for (j = 1; j <= 10; j++)
+                            if (x < 15 * j)
+                                break;
+                        c[15 * j - x] = 1;
+                    }
+                    // Pin diagram
+                    print("PLAYER: " + p + " FRAME: " + f + " BALL: " + b + "\n");
+                    print("\n");
+                    for (i = 0; i <= 3; i++) {
+                        str = "";
+                        for (j = 1; j <= 4 - i; j++) {
+                            k++;
+                            while (str.length < i)
+                                str += " ";
+                            if (c[k] == 1)
+                                str += "O ";
+                            else
+                                str += "+ ";
+                        }
+                        print(str + "\n");
+                    }
+                    // Roll analysis
+                    for (i = 1; i <= 10; i++)
+                        d += c[i];
+                    if (d - m == 0)
+                        print("GUTTER!!\n");
+                    if (b == 1 && d == 10) {
+                        print("STRIKE!!!!!\n");
+                        q = 3;
+                    }
+                    if (b == 2 && d == 10) {
+                        print("SPARE!!!!\n");
+                        q = 2;
+                    }
+                    if (b == 2 && d < 10) {
+                        print("ERROR!!!\n");
+                        q = 1;
+                    }
+                    if (b == 1 && d < 10) {
+                        print("ROLL YOUR 2ND BALL\n");
+                    }
+                    // Storage of the scores
+                    print("\n");
+                    a[f * p][b] = d;
+                    if (b != 2) {
+                        b = 2;
+                        m = d;
+                        if (q == 3) {
+                            a[f * p][b] = d;
+                        } else {
+                            a[f * p][b] = d - m;
+                            if (q == 0) // ROLL
+                                continue;
+                        }
+                    }
+                    break;
+                }
+                a[f * p][3] = q;
+            }
+        } while (++f < 11) ;
+        print("FRAMES\n");
+        for (i = 1; i <= 10; i++)
+            print(" " + i + " ");
+        print("\n");
+        for (p = 1; p <= r; p++) {
+            for (i = 1; i <= 3; i++) {
+                for (j = 1; j <= 10; j++) {
+                    print(" " + a[j * p][i] + " ");
+                }
+                print("\n");
+            }
+            print("\n");
+        }
+        print("DO YOU WANT ANOTHER GAME");
+        str = await input();
+        if (str.substr(0, 1) != "Y")
+            break;
+        // Bug in original game, jumps to 2610, without restarting P variable
+    }
+}
+
+main();
diff --git a/15 Boxing/javascript/boxing.html b/15 Boxing/javascript/boxing.html
new file mode 100644
index 00000000..f72e1eb4
--- /dev/null
+++ b/15 Boxing/javascript/boxing.html	
@@ -0,0 +1,9 @@
+
+
+BOXING
+
+
+

+
+
+
diff --git a/15 Boxing/javascript/boxing.js b/15 Boxing/javascript/boxing.js
new file mode 100644
index 00000000..12620f77
--- /dev/null
+++ b/15 Boxing/javascript/boxing.js	
@@ -0,0 +1,212 @@
+// BOWLING
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "BOXING\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("BOXING OLYMPIC STYLE (3 ROUNDS -- 2 OUT OF 3 WINS)\n");
+    j = 0;
+    l = 0;
+    print("\n");
+    print("WHAT IS YOUR OPPONENT'S NAME");
+    js = await input();
+    print("INPUT YOUR MAN'S NAME");
+    ls = await input();
+    print("DIFFERENT PUNCHES ARE: (1) FULL SWING; (2) HOOK; (3) UPPERCUT; (4) JAB.\n");
+    print("WHAT IS YOUR MANS BEST");
+    b = parseInt(await input());
+    print("WHAT IS HIS VULNERABILITY");
+    d = parseInt(await input());
+    do {
+        b1 = Math.floor(4 * Math.random() + 1);
+        d1 = Math.floor(4 * Math.random() + 1);
+    } while (b1 == d1) ;
+    print(js + "'S ADVANTAGE IS " + b1 + " AND VULNERABILITY IS SECRET.\n");
+    print("\n");
+    knocked = 0;
+    for (r = 1; r <= 3; r++) {
+        if (j >= 2)
+            break;
+        if (l >= 2)
+            break;
+        x = 0;
+        y = 0;
+        print("ROUND " + r + " BEGIN...\n");
+        for (r1 = 1; r1 <= 7; r1++) {
+            i = Math.floor(10 * Math.random() + 1);
+            if (i <= 5) {
+                print(ls + "'S PUNCH");
+                p = parseInt(await input());
+                if (p == b)
+                    x += 2;
+                if (p == 1) {
+                    print(ls + " SWINGS AND ");
+                    x3 = Math.floor(30 * Math.random() + 1);
+                    if (d1 == 4 || x3 < 10) {
+                        print("HE CONNECTS!\n");
+                        if (x > 35) {
+                            r = 3;
+                            break;
+                        }
+                        x += 15;
+                    } else {
+                        print("HE MISSES \n");
+                        if (x != 1)
+                            print("\n\n");
+                    }
+                } else if (p == 2) {
+                    print(ls + " GIVES THE HOOK... ");
+                    h1 = Math.floor(2 * Math.random() + 1);
+                    if (d1 == 2) {
+                        x += 7;
+                    } else if (h1 != 1) {
+                        print("CONNECTS...\n");
+                        x += 7;
+                    } else {
+                        print("BUT IT'S BLOCKED!!!!!!!!!!!!!\n");
+                    }
+                } else if (p == 3) {
+                    print(ls + " TRIES AN UPPERCUT ");
+                    d5 = Math.floor(100 * Math.random() + 1);
+                    if (d1 == 3 || d5 < 51) {
+                        print("AND HE CONNECTS!\n");
+                        x += 4;
+                    } else {
+                        print("AND IT'S BLOCKED (LUCKY BLOCK!)\n");
+                    }
+                } else {
+                    print(ls + " JABS AT " + js + "'S HEAD ");
+                    c = Math.floor(8 * Math.random() + 1);
+                    if (d1 == 4 || c >= 4) {
+                        x += 3;
+                    } else {
+                        print("IT'S BLOCKED.\n");
+                    }
+                }
+            } else {
+                j7 = Math.random(4 * Math.random() + 1);
+                if (j7 == b1)
+                    y += 2;
+                if (j7 == 1) {
+                    print(js + " TAKES A FULL SWING AND");
+                    r6 = Math.floor(60 * Math.random() + 1);
+                    if (d == 1 || r6 < 30) {
+                        print(" POW!!!!! HE HITS HIM RIGHT IN THE FACE!\n");
+                        if (y > 35) {
+                            knocked = 1;
+                            r = 3;
+                            break;
+                        }
+                        y += 15;
+                    } else {
+                        print(" IT'S BLOCKED!\n");
+                    }
+                } else if (j7 == 2 || j7 == 3) {
+                    if (j7 == 2) {
+                        print(js + " GETS " + ls + " IN THE JAW (OUCH!)\n");
+                        y += 7;
+                        print("....AND AGAIN!\n");
+                        y += 5;
+                        if (y > 35) {
+                            knocked = 1;
+                            r = 3;
+                            break;
+                        }
+                        print("\n");
+                        // From original, it goes over from handling 2 to handling 3
+                    }
+                    print(ls + " IS ATTACKED BY AN UPPERCUT (OH,OH)...\n");
+                    q4 = Math.floor(200 * Math.random() + 1);
+                    if (d == 3 || q4 <= 75) {
+                        print("AND " + js + " CONNECTS...\n");
+                        y += 8;
+                    } else {
+                        print(" BLOCKS AND HITS " + js + " WITH A HOOK.\n");
+                        x += 5;
+                    }
+                } else {
+                    print(js + " JABS AND ");
+                    z4 = Math.floor(7 * Math.random() + 1);
+                    if (d == 4)
+                        y += 5;
+                    else if (z4 > 4) {
+                        print(" BLOOD SPILLS !!!\n");
+                        y += 5;
+                    } else {
+                        print("IT'S BLOCKED!\n");
+                    }
+                }
+            }
+        }
+        if (x > y) {
+            print("\n");
+            print(ls + " WINS ROUND " + r + "\n");
+            l++;
+        } else {
+            print("\n");
+            print(js + " WINS ROUND " + r + "\n");
+            j++;
+        }
+    }
+    if (j >= 2) {
+        print(js + " WINS (NICE GOING, " + js + ").\n");
+    } else if (l >= 2) {
+        print(ls + " AMAZINGLY WINS!!\n");
+    } else if (knocked) {
+        print(ls + " IS KNOCKED COLD AND " + js + " IS THE WINNER AND CHAMP!\n");
+    } else {
+        print(js + " IS KNOCKED COLD AND " + ls + " IS THE WINNER AND CHAMP!\n");
+    }
+    print("\n");
+    print("\n");
+    print("AND NOW GOODBYE FROM THE OLYMPIC ARENA.\n");
+    print("\n");
+}
+
+main();
diff --git a/16 Bug/javascript/bug.html b/16 Bug/javascript/bug.html
new file mode 100644
index 00000000..0e718cd5
--- /dev/null
+++ b/16 Bug/javascript/bug.html	
@@ -0,0 +1,9 @@
+
+
+BUG
+
+
+

+
+
+
diff --git a/16 Bug/javascript/bug.js b/16 Bug/javascript/bug.js
new file mode 100644
index 00000000..2d99d90c
--- /dev/null
+++ b/16 Bug/javascript/bug.js	
@@ -0,0 +1,347 @@
+// BUG
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+function draw_head()
+{
+    print("        HHHHHHH\n");
+    print("        H     H\n");
+    print("        H O O H\n");
+    print("        H     H\n");
+    print("        H  V  H\n");
+    print("        HHHHHHH\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "BUG\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    a = 0;
+    b = 0;
+    h = 0;
+    l = 0;
+    n = 0;
+    p = 0;
+    q = 0;
+    r = 0;
+    s = 0;
+    t = 0;
+    u = 0;
+    v = 0;
+    y = 0;
+    print("THE GAME BUG\n");
+    print("I HOPE YOU ENJOY THIS GAME.\n");
+    print("\n");
+    print("DO YOU WANT INSTRUCTIONS");
+    str = await input();
+    if (str != "NO") {
+        print("THE OBJECT OF BUG IS TO FINISH YOUR BUG BEFORE I FINISH\n");
+        print("MINE. EACH NUMBER STANDS FOR A PART OF THE BUG BODY.\n");
+        print("I WILL ROLL THE DIE FOR YOU, TELL YOU WHAT I ROLLED FOR YOU\n");
+        print("WHAT THE NUMBER STANDS FOR, AND IF YOU CAN GET THE PART.\n");
+        print("IF YOU CAN GET THE PART I WILL GIVE IT TO YOU.\n");
+        print("THE SAME WILL HAPPEN ON MY TURN.\n");
+        print("IF THERE IS A CHANGE IN EITHER BUG I WILL GIVE YOU THE\n");
+        print("OPTION OF SEEING THE PICTURES OF THE BUGS.\n");
+        print("THE NUMBERS STAND FOR PARTS AS FOLLOWS:\n");
+        print("NUMBER\tPART\tNUMBER OF PART NEEDED\n");
+        print("1\tBODY\t1\n");
+        print("2\tNECK\t1\n");
+        print("3\tHEAD\t1\n");
+        print("4\tFEELERS\t2\n");
+        print("5\tTAIL\t1\n");
+        print("6\tLEGS\t6\n");
+        print("\n");
+        print("\n");
+    }
+    while (y == 0) {
+        z = Math.floor(6 * Math.random() + 1);
+        c = 1;
+        print("YOU ROLLED A " + z + "\n");
+        switch (z) {
+            case 1:
+                print("1=BODY\n");
+                if (b == 0) {
+                    print("YOU NOW HAVE A BODY.\n");
+                    b = 1;
+                    c = 0;
+                } else {
+                    print("YOU DO NOT NEED A BODY.\n");
+                }
+                break;
+            case 2:
+                print("2=NECK\n");
+                if (n == 0) {
+                    if (b == 0) {
+                        print("YOU DO NOT HAVE A BODY.\n");
+                    } else {
+                        print("YOU NOW HAVE A NECK.\n");
+                        n = 1;
+                        c = 0;
+                    }
+                } else {
+                    print("YOU DO NOT NEED A NECK.\n");
+                }
+                break;
+            case 3:
+                print("3=HEAD\n");
+                if (n == 0) {
+                    print("YOU DO NOT HAVE A NECK.\n");
+                } else if (h == 0) {
+                    print("YOU NEEDED A HEAD.\n");
+                    h = 1;
+                    c = 0;
+                } else {
+                    print("YOU HAVE A HEAD.\n");
+                }
+                break;
+            case 4:
+                print("4=FEELERS\n");
+                if (h == 0) {
+                    print("YOU DO NOT HAVE A HEAD.\n");
+                } else if (a == 2) {
+                    print("YOU HAVE TWO FEELERS ALREADY.\n");
+                } else {
+                    print("I NOW GIVE YOU A FEELER.\n");
+                    a++;
+                    c = 0;
+                }
+                break;
+            case 5:
+                print("5=TAIL\n");
+                if (b == 0) {
+                    print("YOU DO NOT HAVE A BODY.\n");
+                } else if (t == 1) {
+                    print("YOU ALREADY HAVE A TAIL.\n");
+                } else {
+                    print("I NOW GIVE YOU A TAIL.\n");
+                    t++;
+                    c = 0;
+                }
+                break;
+            case 6:
+                print("6=LEG\n");
+                if (l == 6) {
+                    print("YOU HAVE 6 FEET ALREADY.\n");
+                } else if (b == 0) {
+                    print("YOU DO NOT HAVE A BODY.\n");
+                } else {
+                    l++;
+                    c = 0;
+                    print("YOU NOW HAVE " + l + " LEGS.\n");
+                }
+                break;
+        }
+        x = Math.floor(6 * Math.random() + 1) ;
+        print("\n");
+        date = new Date().valueOf;
+        while (date - new Date().valueOf < 1000000) ;
+        print("I ROLLED A " + x + "\n");
+        switch (x) {
+            case 1:
+                print("1=BODY\n");
+                if (p == 1) {
+                    print("I DO NOT NEED A BODY.\n");
+                } else {
+                    print("I NOW HAVE A BODY.\n");
+                    c = 0;
+                    p = 1;
+                }
+                break;
+            case 2:
+                print("2=NECK\n");
+                if (q == 1) {
+                    print("I DO NOT NEED A NECK.\n");
+                } else if (p == 0) {
+                    print("I DO NOT HAVE A BODY.\n");
+                } else {
+                    print("I NOW HAVE A NECK.\n");
+                    q = 1;
+                    c = 0;
+                }
+                break;
+            case 3:
+                print("3=HEAD\n");
+                if (q == 0) {
+                    print("I DO NOT HAVE A NECK.\n");
+                } else if (r == 1) {
+                    print("I DO NOT NEED A HEAD.\n");
+                } else {
+                    print("I NEEDED A HEAD.\n");
+                    r = 1;
+                    c = 0;
+                }
+                break;
+            case 4:
+                print("4=FEELERS\n");
+                if (r == 0) {
+                    print("I DO NOT HAVE A HEAD.\n");
+                } else if (s == 2) {
+                    print("I HAVE 2 FEELERS ALREADY.\n");
+                } else {
+                    print("I GET A FEELER.\n");
+                    s++;
+                    c = 0;
+                }
+                break;
+            case 5:
+                print("5=TAIL\n");
+                if (p == 0) {
+                    print("I DO NOT HAVE A BODY.\n");
+                } else if (u == 1) {
+                    print("I DO NOT NEED A TAIL.\n");
+                } else {
+                    print("I NOW HAVE A TAIL.\n");
+                    u = 1;
+                    c = 0;
+                }
+                break;
+            case 6:
+                print("6=LEGS\n");
+                if (v == 6) {
+                    print("I HAVE 6 FEET.\n");
+                } else if (p == 0) {
+                    print("I DO NOT HAVE A BODY.\n");
+                } else {
+                    v++;
+                    c = 0;
+                    print("I NOW HAVE " + v + " LEGS.\n");
+                }
+                break;
+        }
+        if (a == 2 && t == 1 && l == 6) {
+            print("YOUR BUG IS FINISHED.\n");
+            y++;
+        }
+        if (s == 2 && p == 1 && v == 6) {
+            print("MY BUG IS FINISHED.\n");
+            y += 2;
+        }
+        if (c == 1)
+            continue;
+        print("DO YOU WANT THE PICTURES");
+        str = await input();
+        if (str == "NO")
+            continue;
+        print("*****YOUR BUG*****\n");
+        print("\n");
+        print("\n");
+        if (a != 0) {
+            for (z = 1; z <= 4; z++) {
+                print(tab(10));
+                for (x = 1; x <= a; x++) {
+                    print("A ");
+                }
+                print("\n");
+            }
+        }
+        if (h != 0)
+            draw_head();
+        if (n != 0) {
+            for (z = 1; z <= 2; z++)
+                print("          N N\n");
+        }
+        if (b != 0) {
+            print("     BBBBBBBBBBBB\n");
+            for (z = 1; z <= 2; z++)
+                print("     B          B\n");
+            if (t == 1)
+                print("TTTTTB          B\n");
+            print("     BBBBBBBBBBBB\n");
+        }
+        if (l != 0) {
+            for (z = 1; z <= 2; z++) {
+                print(tab(5));
+                for (x = 1; x <= l; x++)
+                    print(" L");
+                print("\n");
+            }
+        }
+        for (z = 1; z <= 4; z++)
+            print("\n");
+        print("*****MY BUG*****\n");
+        print("\n");
+        print("\n");
+        print("\n");
+        if (s != 0) {
+            for (z = 1; z <= 4; z++) {
+                print(tab(10));
+                for (x = 1; x <= s; x++) {
+                    print("F ");
+                }
+                print("\n");
+            }
+        }
+        if (r != 0)
+            draw_head();
+        if (q != 0) {
+            for (z = 1; z <= 2; z++)
+                print("          N N\n");
+        }
+        if (p != 0) {
+            print("     BBBBBBBBBBBB\n");
+            for (z = 1; z <= 2; z++)
+                print("     B          B\n");
+            if (u == 1)
+                print("TTTTTB          B\n");
+            print("     BBBBBBBBBBBB\n");
+        }
+        if (v != 0) {
+            for (z = 1; z <= 2; z++) {
+                print(tab(5));
+                for (x = 1; x <= v; x++)
+                    print(" L");
+                print("\n");
+            }
+        }
+        for (z = 1; z <= 4; z++)
+            print("\n");
+    }
+    print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!\n");
+}
+
+main();

From 1df4187777b952c0f491859c325fd8bf6476b670 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Fri, 26 Feb 2021 16:32:38 +1030
Subject: [PATCH 032/749] Java version of Letter

---
 54 Letter/java/src/Letter.java     | 142 +++++++++++++++++++++++++++++
 54 Letter/java/src/LetterGame.java |   8 ++
 2 files changed, 150 insertions(+)
 create mode 100644 54 Letter/java/src/Letter.java
 create mode 100644 54 Letter/java/src/LetterGame.java

diff --git a/54 Letter/java/src/Letter.java b/54 Letter/java/src/Letter.java
new file mode 100644
index 00000000..149c51f6
--- /dev/null
+++ b/54 Letter/java/src/Letter.java	
@@ -0,0 +1,142 @@
+import java.awt.*;
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Letter
+ * 

+ * Based on the Basic game of Letter here + * https://github.com/coding-horror/basic-computer-games/blob/main/54%20Letter/letter.bas + *

+ * 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 Letter { + + public static final int OPTIMAL_GUESSES = 5; + public static final int ASCII_A = 65; + public static final int ALL_LETTERS = 26; + + private enum GAME_STATE { + STARTUP, + INIT, + GUESSING, + RESULTS, + GAME_OVER + } + + // Used for keyboard input + private final Scanner kbScanner; + + // Current game state + private GAME_STATE gameState; + + // Players guess count; + private int playerGuesses; + + // Computers ascii code for a random letter between A..Z + private int computersLetter; + + public Letter() { + + gameState = GAME_STATE.INIT; + + // Initialise kb scanner + kbScanner = new Scanner(System.in); + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + // Show an introduction the first time the game is played. + case STARTUP: + intro(); + gameState = GAME_STATE.INIT; + break; + + case INIT: + playerGuesses = 0; + computersLetter = ASCII_A + (int) (Math.random() * ALL_LETTERS); + System.out.println("O.K., I HAVE A LETTER. START GUESSING."); + gameState = GAME_STATE.GUESSING; + break; + + // Player guesses the number until they get it or run out of guesses + case GUESSING: + String playerGuess = displayTextAndGetInput("WHAT IS YOUR GUESS? ").toUpperCase(); + + // Convert first character of input string to ascii + int toAscii = playerGuess.charAt(0); + playerGuesses++; + if (toAscii == computersLetter) { + gameState = GAME_STATE.RESULTS; + break; + } + + if (toAscii > computersLetter) { + System.out.println("TOO HIGH. TRY A LOWER LETTER."); + } else { + System.out.println("TOO LOW. TRY A HIGHER LETTER."); + } + break; + + // Play again, or exit game? + case RESULTS: + System.out.println(); + System.out.println("YOU GOT IT IN " + playerGuesses + " GUESSES!!"); + if (playerGuesses <= OPTIMAL_GUESSES) { + System.out.println("GOOD JOB !!!!!"); + // Original game beeped 15 tims if you guessed in the optimal guesses or less + // Changed this to do a single beep only + Toolkit.getDefaultToolkit().beep(); + } else { + // Took more than optimal number of guesses + System.out.println("BUT IT SHOULDN'T TAKE MORE THAN " + OPTIMAL_GUESSES + " GUESSES!"); + } + System.out.println(); + System.out.println("LET'S PLAN AGAIN....."); + gameState = GAME_STATE.INIT; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + public void intro() { + System.out.println(simulateTabs(33) + "LETTER"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("LETTER GUESSING GAME"); + System.out.println(); + System.out.println("I'LL THINK OF A LETTER OF THE ALPHABET, A TO Z."); + System.out.println("TRY TO GUESS MY LETTER AND I'LL GIVE YOU CLUES"); + System.out.println("AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER."); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } +} \ No newline at end of file diff --git a/54 Letter/java/src/LetterGame.java b/54 Letter/java/src/LetterGame.java new file mode 100644 index 00000000..fa023329 --- /dev/null +++ b/54 Letter/java/src/LetterGame.java @@ -0,0 +1,8 @@ +public class LetterGame { + + public static void main(String[] args) { + + Letter letter = new Letter(); + letter.play(); + } +} From 6cb4c1064a7765059fc98c692d6de67f29503887 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:38:21 +1030 Subject: [PATCH 033/749] Ensure initial title is shown before game starts --- 54 Letter/java/src/Letter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/54 Letter/java/src/Letter.java b/54 Letter/java/src/Letter.java index 149c51f6..36582894 100644 --- a/54 Letter/java/src/Letter.java +++ b/54 Letter/java/src/Letter.java @@ -39,7 +39,7 @@ public class Letter { public Letter() { - gameState = GAME_STATE.INIT; + gameState = GAME_STATE.STARTUP; // Initialise kb scanner kbScanner = new Scanner(System.in); From 98eaa2ff4534995ef8973ae404fa27559db879f2 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:55:10 +1030 Subject: [PATCH 034/749] Java version of Literature Quiz --- .../java/src/LiteratureQuiz.java | 176 ++++++++++++++++++ .../java/src/LiteratureQuizGame.java | 8 + 2 files changed, 184 insertions(+) create mode 100644 57 Literature Quiz/java/src/LiteratureQuiz.java create mode 100644 57 Literature Quiz/java/src/LiteratureQuizGame.java diff --git a/57 Literature Quiz/java/src/LiteratureQuiz.java b/57 Literature Quiz/java/src/LiteratureQuiz.java new file mode 100644 index 00000000..d98d58a8 --- /dev/null +++ b/57 Literature Quiz/java/src/LiteratureQuiz.java @@ -0,0 +1,176 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Literature Quiz + *

+ * Based on the Basic game of Literature Quiz here + * https://github.com/coding-horror/basic-computer-games/blob/main/57%20Literature%20Quiz/litquiz.bas + *

+ * 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 LiteratureQuiz { + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + STARTUP, + QUESTIONS, + RESULTS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + // Players correct answers + private int correctAnswers; + + public LiteratureQuiz() { + + gameState = GAME_STATE.STARTUP; + + // Initialise kb scanner + kbScanner = new Scanner(System.in); + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + // Show an introduction the first time the game is played. + case STARTUP: + intro(); + correctAnswers = 0; + gameState = GAME_STATE.QUESTIONS; + break; + + // Ask the player four questions + case QUESTIONS: + + // Question 1 + System.out.println("IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT"); + int question1Answer = displayTextAndGetNumber("1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO ? "); + if (question1Answer == 3) { + System.out.println("VERY GOOD! HERE'S ANOTHER."); + correctAnswers++; + } else { + System.out.println("SORRY...FIGARO WAS HIS NAME."); + } + + System.out.println(); + + // Question 2 + System.out.println("FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?"); + int question2Answer = displayTextAndGetNumber("1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S ? "); + if (question2Answer == 2) { + System.out.println("PRETTY GOOD!"); + correctAnswers++; + } else { + System.out.println("TOO BAD...IT WAS ELMER FUDD'S GARDEN."); + } + + System.out.println(); + + // Question 3 + System.out.println("IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED"); + int question3Answer = displayTextAndGetNumber("1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO ? "); + if (question3Answer == 4) { + System.out.println("YEA! YOU'RE A REAL LITERATURE GIANT."); + correctAnswers++; + } else { + System.out.println("BACK TO THE BOOKS,...TOTO WAS HIS NAME."); + } + + System.out.println(); + + // Question 4 + System.out.println("WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE"); + int question4Answer = displayTextAndGetNumber("1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY ? "); + if (question4Answer == 3) { + System.out.println("GOOD MEMORY!"); + correctAnswers++; + } else { + System.out.println("OH, COME ON NOW...IT WAS SNOW WHITE."); + } + + System.out.println(); + gameState = GAME_STATE.RESULTS; + break; + + // How did the player do? + case RESULTS: + if (correctAnswers == 4) { + // All correct + System.out.println("WOW! THAT'S SUPER! YOU REALLY KNOW YOUR NURSERY"); + System.out.println("YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE"); + System.out.println("LITERATURE (HA, HA, HA)"); + // one or none correct + } else if (correctAnswers < 2) { + System.out.println("UGH. THAT WAS DEFINITELY NOT TOO SWIFT. BACK TO"); + System.out.println("NURSERY SCHOOL FOR YOU, MY FRIEND."); + // two or three correct + } else { + System.out.println("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME"); + System.out.println("READING THE NURSERY GREATS."); + } + gameState = GAME_STATE.GAME_OVER; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + public void intro() { + System.out.println(simulateTabs(25) + "LITERATURE QUIZ"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("LITERATURE QUIZ"); + System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE."); + System.out.println("THIS IS A MULTIPLE-CHOICE QUIZ."); + System.out.println("TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK."); + System.out.println(); + System.out.println("GOOD LUCK!"); + System.out.println(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } +} \ No newline at end of file diff --git a/57 Literature Quiz/java/src/LiteratureQuizGame.java b/57 Literature Quiz/java/src/LiteratureQuizGame.java new file mode 100644 index 00000000..3f7d9fd4 --- /dev/null +++ b/57 Literature Quiz/java/src/LiteratureQuizGame.java @@ -0,0 +1,8 @@ +public class LiteratureQuizGame { + + public static void main(String[] args) { + + LiteratureQuiz literatureQuiz = new LiteratureQuiz(); + literatureQuiz.play(); + } +} From 5c82481fbac784eb9b6d7083a790a846ff764080 Mon Sep 17 00:00:00 2001 From: nanochess Date: Fri, 26 Feb 2021 22:10:52 -0600 Subject: [PATCH 035/749] Ported BULLFIGHT to Javascript --- 17 Bullfight/bullfight.bas | 6 +- 17 Bullfight/javascript/bullfight.html | 9 + 17 Bullfight/javascript/bullfight.js | 315 +++++++++++++++++++++++++ 3 files changed, 327 insertions(+), 3 deletions(-) create mode 100644 17 Bullfight/javascript/bullfight.html create mode 100644 17 Bullfight/javascript/bullfight.js diff --git a/17 Bullfight/bullfight.bas b/17 Bullfight/bullfight.bas index bb2ab4f6..32b04b89 100644 --- a/17 Bullfight/bullfight.bas +++ b/17 Bullfight/bullfight.bas @@ -21,7 +21,7 @@ 330 PRINT 340 PRINT "THE CROWD WILL DETERMINE WHAT AWARD YOU DESERVE" 350 PRINT "(POSTHUMOUSLY IF NECESSARY)." -360 PRINT "THE BRAVER YOU ARE, THE BETTER THE AWARD YOU RECIEVE." +360 PRINT "THE BRAVER YOU ARE, THE BETTER THE AWARD YOU RECEIVE." 370 PRINT 380 PRINT "THE BETTER THE JOB THE PICADORES AND TOREADORES DO," 390 PRINT "THE BETTER YOUR CHANCES ARE." @@ -112,7 +112,7 @@ 1190 PRINT "YOU PANICKED. THE BULL GORED YOU." 1220 GOTO 970 1230 K=(6-A)*10*RND(1)/((D(1)+D(2))*5*D(3)) -1240 IF J=4 THEN 1290 +1240 IF H=4 THEN 1290 1250 IF K>.2 THEN 960 1260 PRINT "YOU KILLED THE BULL!" 1270 D(5)=2 @@ -125,7 +125,7 @@ 1340 IF D(4)<>0 THEN 1390 1350 PRINT "THE CROWD BOOS FOR TEN MINUTES. IF YOU EVER DARE TO SHOW" 1360 PRINT "YOUR FACE IN A RING AGAIN, THEY SWEAR THEY WILL KILL YOU--" -1370 PRINT "UNLES THE BULL DOES FIRST." +1370 PRINT "UNLESS THE BULL DOES FIRST." 1380 GOTO 1580 1390 DEF FNC(Q)=FND(Q)*RND(1) 1395 DEF FND(Q)=(4.5+L/6-(D(1)+D(2))*2.5+4*D(4)+2*D(5)-D(3)^2/120-A) diff --git a/17 Bullfight/javascript/bullfight.html b/17 Bullfight/javascript/bullfight.html new file mode 100644 index 00000000..8d23d40e --- /dev/null +++ b/17 Bullfight/javascript/bullfight.html @@ -0,0 +1,9 @@ + + +BULLFIGHT + + +


+
+
+
diff --git a/17 Bullfight/javascript/bullfight.js b/17 Bullfight/javascript/bullfight.js
new file mode 100644
index 00000000..c3e02252
--- /dev/null
+++ b/17 Bullfight/javascript/bullfight.js	
@@ -0,0 +1,315 @@
+// BULLFIGHT
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a;
+var b;
+var c;
+var l;
+var t;
+var as;
+var bs;
+var d = [];
+var ls = [, "SUPERB", "GOOD", "FAIR", "POOR", "AWFUL"];
+
+function af(k)
+{
+    return Math.floor(Math.random() * 2 + 1);
+}
+
+function cf(q)
+{
+    return df(q) * Math.random();
+}
+
+function df(q)
+{
+    return (4.5 + l / 6 - (d[1] + d[2]) * 2.5 + 4 * d[4] + 2 * d[5] - Math.pow(d[3], 2) / 120 - a);
+}
+
+function setup_helpers()
+{
+    b = 3 / a * Math.random();
+    if (b < 0.37)
+        c = 0.5;
+    else if (b < 0.5)
+        c = 0.4;
+    else if (b < 0.63)
+        c = 0.3;
+    else if (b < 0.87)
+        c = 0.2;
+    else
+        c = 0.1;
+    t = Math.floor(10 * c + 0.2);
+    print("THE " + as + bs + " DID A " + ls[t] + " JOB.\n");
+    if (4 <= t) {
+        if (5 != t) {
+            // Lines 1800 and 1810 of original program are unreachable
+            switch (af(0)) {
+                case 1:
+                    print("ONE OF THE " + as + bs + " WAS KILLED.\n");
+                    break;
+                case 2:
+                    print("NO " + as + b + " WERE KILLED.\n");
+                    break;
+            }
+        } else {
+            if (as != "TOREAD")
+                print(af(0) + " OF THE HORSES OF THE " + as + bs + " KILLED.\n");
+            print(af(0) + " OF THE " + as + bs + " KILLED.\n");
+        }
+    }
+    print("\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "BULL\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    l = 1;
+    print("DO YOU WANT INSTRUCTIONS");
+    str = await input();
+    if (str != "NO") {
+        print("HELLO, ALL YOU BLOODLOVERS AND AFICIONADOS.\n");
+        print("HERE IS YOUR BIG CHANCE TO KILL A BULL.\n");
+        print("\n");
+        print("ON EACH PASS OF THE BULL, YOU MAY TRY\n");
+        print("0 - VERONICA (DANGEROUS INSIDE MOVE OF THE CAPE)\n");
+        print("1 - LESS DANGEROUS OUTSIDE MOVE OF THE CAPE\n");
+        print("2 - ORDINARY SWIRL OF THE CAPE.\n");
+        print("\n");
+        print("INSTEAD OF THE ABOVE, YOU MAY TRY TO KILL THE BULL\n");
+        print("ON ANY TURN: 4 (OVER THE HORNS), 5 (IN THE CHEST).\n");
+        print("BUT IF I WERE YOU,\n");
+        print("I WOULDN'T TRY IT BEFORE THE SEVENTH PASS.\n");
+        print("\n");
+        print("THE CROWD WILL DETERMINE WHAT AWARD YOU DESERVE\n");
+        print("(POSTHUMOUSLY IF NECESSARY).\n");
+        print("THE BRAVER YOU ARE, THE BETTER THE AWARD YOU RECEIVE.\n");
+        print("\n");
+        print("THE BETTER THE JOB THE PICADORES AND TOREADORES DO,\n");
+        print("THE BETTER YOUR CHANCES ARE.\n");
+    }
+    print("\n");
+    print("\n");
+    d[5] = 1;
+    d[4] = 1;
+    d[3] = 0;
+    a = Math.floor(Math.random() * 5 + 1);
+    print("YOU HAVE DRAWN A " + ls[a] + " BULL.\n");
+    if (a > 4) {
+        print("YOU'RE LUCKY.\n");
+    } else if (a < 2) {
+        print("GOOD LUCK.  YOU'LL NEED IT.\n");
+        print("\n");
+    }
+    print("\n");
+    as = "PICADO";
+    bs = "RES";
+    setup_helpers();
+    d[1] = c;
+    as = "TOREAD";
+    bs = "ORES";
+    setup_helpers();
+    d[2] = c;
+    print("\n");
+    print("\n");
+    z = 0;
+    while (z == 0) {
+        d[3]++;
+        print("PASS NUMBER " + d[3] + "\n");
+        if (d[3] >= 3) {
+            print("HERE COMES THE BULL.  TRY FOR A KILL");
+            while (1) {
+                str = await input();
+                if (str != "YES" && str != "NO")
+                    print("INCORRECT ANSWER - - PLEASE TYPE 'YES' OR 'NO'.\n");
+                else
+                    break;
+            }
+            z1 = (str == "YES") ? 1 : 2;
+            if (z1 != 1) {
+                print("CAPE MOVE");
+            }
+        } else {
+            print("THE BULL IS CHARGING AT YOU!  YOU ARE THE MATADOR--\n");
+            print("DO YOU WANT TO KILL THE BULL");
+            while (1) {
+                str = await input();
+                if (str != "YES" && str != "NO")
+                    print("INCORRECT ANSWER - - PLEASE TYPE 'YES' OR 'NO'.\n");
+                else
+                    break;
+            }
+            z1 = (str == "YES") ? 1 : 2;
+            if (z1 != 1) {
+                print("WHAT MOVE DO YOU MAKE WITH THE CAPE");
+            }
+        }
+        gore = 0;
+        if (z1 != 1) {
+            while (1) {
+                e = parseInt(await input());
+                if (e >= 3) {
+                    print("DON'T PANIC, YOU IDIOT!  PUT DOWN A CORRECT NUMBER\n");
+                } else {
+                    break;
+                }
+            }
+            if (e == 0)
+                m = 3;
+            else if (e == 1)
+                m = 2;
+            else
+                m = 0.5;
+            l += m;
+            f = (6 - a + m / 10) * Math.random() / ((d[1] + d[2] + d[3] / 10) * 5);
+            if (f < 0.51)
+                continue;
+            gore = 1;
+        } else {
+            z = 1;
+            print("\n");
+            print("IT IS THE MOMENT OF THE TRUTH.\n");
+            print("\n");
+            print("HOW DO YOU TRY TO KILL THE BULL");
+            h = parseInt(await input());
+            if (h != 4 && h != 5) {
+                print("YOU PANICKED.  THE BULL GORED YOU.\n");
+                gore = 2;
+            } else {
+                k = (6 - a) * 10 * Math.random() / ((d[1] + d[2]) * 5 * d[3]);
+                if (h != 4) {   // Bug in original game, it says J instead of H
+                    if (k > 0.2)
+                        gore = 1;
+                } else {
+                    if (k > 0.8)
+                        gore = 1;
+                }
+                if (gore == 0) {
+                    print("YOU KILLED THE BULL!\n");
+                    d[5] = 2;
+                    break;
+                }
+            }
+        }
+        if (gore) {
+            if (gore == 1)
+                print("THE BULL HAS GORED YOU!\n");
+            kill = false;
+            while (1) {
+                if (af(0) == 1) {
+                    print("YOU ARE DEAD.\n");
+                    d[4] = 1.5;
+                    kill = true;
+                    break;
+                }
+                print("YOU ARE STILL ALIVE.\n");
+                print("\n");
+                print("DO YOU RUN FROM THE RING");
+                while (1) {
+                    str = await input();
+                    if (str != "YES" && str != "NO")
+                        print("INCORRECT ANSWER - - PLEASE TYPE 'YES' OR 'NO'.\n");
+                    else
+                        break;
+                }
+                z1 = (str == "YES") ? 1 : 2;
+                if (z1 != 2) {
+                    print("COWARD\n");
+                    d[4] = 0;
+                    kill = true;
+                    break;
+                }
+                print("YOU ARE BRAVE.  STUPID, BUT BRAVE.\n");
+                if (af(0) == 1) {
+                    d[4] = 2;
+                    kill = false;
+                    break;
+                }
+                print("YOU ARE GORED AGAIN!\n");
+            }
+            if (kill)
+                break;
+            continue;
+        }
+    }
+    print("\n");
+    print("\n");
+    print("\n");
+    if (d[4] == 0) {
+        print("THE CROWD BOOS FOR TEN MINUTES.  IF YOU EVER DARE TO SHOW\n");
+        print("YOUR FACE IN A RING AGAIN, THEY SWEAR THEY WILL KILL YOU--\n");
+        print("UNLESS THE BULL DOES FIRST.\n");
+    } else {
+        if (d[4] == 2) {
+            print("THE CROWD CHEERS WILDLY!\n");
+        } else if (d[5] == 2) {
+            print("THE CROWD CHEERS!\n");
+            print("\n");
+        }
+        print("THE CROWD AWARDS YOU\n");
+        if (cf(0) < 2.4) {
+            print("NOTHING AT ALL.\n");
+        } else if (cf(0) < 4.9) {
+            print("ONE EAR OF THE BULL.\n");
+        } else if (cf(0) < 7.4) {
+            print("BOTH EARS OF THE BULL!\n");
+            print("OLE!\n");
+        } else {
+            print("OLE!  YOU ARE 'MUY HOMBRE'!! OLE!  OLE!\n");
+        }
+        print("\n");
+        print("ADIOS\n");
+        print("\n");
+        print("\n");
+        print("\n");
+    }
+}
+
+
+main();

From 4d1a9176ec7d7364c19fd17d5fb457c467a87d48 Mon Sep 17 00:00:00 2001
From: Andrew Cooper 
Date: Sat, 27 Feb 2021 17:32:04 +1100
Subject: [PATCH 036/749] Main game loop with Short Range Scan and Shield
 Control

---
 84 Super Star Trek/csharp/Command.cs          |  34 ++++++
 .../csharp/CommandExtensions.cs               |  14 +++
 84 Super Star Trek/csharp/Game.cs             |  97 +++++++++++++++++
 84 Super Star Trek/csharp/Input.cs            |  76 +++++++++++++
 .../csharp/Objects/Enterprise.cs              | 103 ++++++++++++++++++
 84 Super Star Trek/csharp/Objects/Klingon.cs  |  14 +++
 84 Super Star Trek/csharp/Objects/Star.cs     |   7 ++
 84 Super Star Trek/csharp/Objects/Starbase.cs |   7 ++
 84 Super Star Trek/csharp/Output.cs           |  15 +++
 84 Super Star Trek/csharp/Program.cs          |  25 ++---
 84 Super Star Trek/csharp/Random.cs           |  25 +++++
 .../csharp/Resources/AcceptCommand.txt        |   0
 .../csharp/Resources/CombatArea.txt           |   1 +
 .../csharp/Resources/Instructions.txt         |   3 +-
 .../csharp/Resources/LowShields.txt           |   1 +
 .../csharp/Resources/Orders.txt               |   6 +
 .../csharp/Resources/ReplayPrompt.txt         |   3 +
 .../csharp/Resources/ShieldsDropped.txt       |   1 +
 .../csharp/Resources/ShortRangeSensorsOut.txt |   1 +
 .../csharp/Resources/StartText.txt            |   5 +
 .../csharp/{ => Resources}/Strings.cs         |  15 ++-
 84 Super Star Trek/csharp/Space/Coordinate.cs |  27 +++++
 84 Super Star Trek/csharp/Space/Course.cs     |  50 +++++++++
 84 Super Star Trek/csharp/Space/Galaxy.cs     |  34 ++++++
 84 Super Star Trek/csharp/Space/Quadrant.cs   |  79 ++++++++++++++
 .../csharp/Space/QuadrantInfo.cs              |  40 +++++++
 .../csharp/Systems/ShieldControl.cs           |  53 +++++++++
 .../csharp/Systems/ShortRangeSensors.cs       |  59 ++++++++++
 .../csharp/Systems/Subsystem.cs               |  20 ++++
 29 files changed, 791 insertions(+), 24 deletions(-)
 create mode 100644 84 Super Star Trek/csharp/Command.cs
 create mode 100644 84 Super Star Trek/csharp/CommandExtensions.cs
 create mode 100644 84 Super Star Trek/csharp/Game.cs
 create mode 100644 84 Super Star Trek/csharp/Input.cs
 create mode 100644 84 Super Star Trek/csharp/Objects/Enterprise.cs
 create mode 100644 84 Super Star Trek/csharp/Objects/Klingon.cs
 create mode 100644 84 Super Star Trek/csharp/Objects/Star.cs
 create mode 100644 84 Super Star Trek/csharp/Objects/Starbase.cs
 create mode 100644 84 Super Star Trek/csharp/Output.cs
 create mode 100644 84 Super Star Trek/csharp/Random.cs
 create mode 100644 84 Super Star Trek/csharp/Resources/AcceptCommand.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/CombatArea.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/LowShields.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/Orders.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/ReplayPrompt.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/ShieldsDropped.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/ShortRangeSensorsOut.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/StartText.txt
 rename 84 Super Star Trek/csharp/{ => Resources}/Strings.cs (61%)
 create mode 100644 84 Super Star Trek/csharp/Space/Coordinate.cs
 create mode 100644 84 Super Star Trek/csharp/Space/Course.cs
 create mode 100644 84 Super Star Trek/csharp/Space/Galaxy.cs
 create mode 100644 84 Super Star Trek/csharp/Space/Quadrant.cs
 create mode 100644 84 Super Star Trek/csharp/Space/QuadrantInfo.cs
 create mode 100644 84 Super Star Trek/csharp/Systems/ShieldControl.cs
 create mode 100644 84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs
 create mode 100644 84 Super Star Trek/csharp/Systems/Subsystem.cs

diff --git a/84 Super Star Trek/csharp/Command.cs b/84 Super Star Trek/csharp/Command.cs
new file mode 100644
index 00000000..33d9fd01
--- /dev/null
+++ b/84 Super Star Trek/csharp/Command.cs	
@@ -0,0 +1,34 @@
+using System.ComponentModel;
+
+namespace SuperStarTrek
+{
+    internal enum Command
+    {
+        [Description("To set course")]
+        NAV,
+
+        [Description("For short range sensor scan")]
+        SRS,
+
+        [Description("For long range sensor scan")]
+        LRS,
+
+        [Description("To fire phasers")]
+        PHA,
+
+        [Description("To fire photon torpedoes")]
+        TOR,
+
+        [Description("To raise or lower shields")]
+        SHE,
+
+        [Description("For damage control reports")]
+        DAM,
+
+        [Description("To call on library-computer")]
+        COM,
+
+        [Description("To resign your command")]
+        XXX
+    }
+}
diff --git a/84 Super Star Trek/csharp/CommandExtensions.cs b/84 Super Star Trek/csharp/CommandExtensions.cs
new file mode 100644
index 00000000..2b69ea31
--- /dev/null
+++ b/84 Super Star Trek/csharp/CommandExtensions.cs	
@@ -0,0 +1,14 @@
+using System.Reflection;
+using System.ComponentModel;
+
+namespace SuperStarTrek
+{
+    internal static class CommandExtensions
+    {
+        internal static string GetDescription(this Command command) =>
+            typeof(Command)
+                .GetField(command.ToString())
+                .GetCustomAttribute()
+                .Description;
+    }
+}
diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs
new file mode 100644
index 00000000..d97b8198
--- /dev/null
+++ b/84 Super Star Trek/csharp/Game.cs	
@@ -0,0 +1,97 @@
+using System;
+using SuperStarTrek.Objects;
+using SuperStarTrek.Resources;
+using SuperStarTrek.Space;
+using SuperStarTrek.Systems;
+using static System.StringComparison;
+
+namespace SuperStarTrek
+{
+    internal class Game
+    {
+        private readonly Output _output;
+        private readonly Input _input;
+
+        private int _initialStardate;
+        private int _finalStarDate;
+        private double _currentStardate;
+        private Coordinates _currentQuadrant;
+        private Coordinates _currentSector;
+        private Galaxy _galaxy;
+        private int _initialKlingonCount;
+        private Enterprise _enterprise;
+
+        public Game()
+        {
+            _output = new Output();
+            _input = new Input(_output);
+        }
+
+        public double Stardate => _currentStardate;
+
+        public void DoIntroduction()
+        {
+            _output.Write(Strings.Title);
+
+            _output.Write("Do you need instructions (Y/N)? ");
+            var response = Console.ReadLine();
+            _output.WriteLine();
+
+            if (!response.Equals("N", InvariantCultureIgnoreCase))
+            {
+                _output.Write(Strings.Instructions);
+
+                _input.WaitForAnyKeyButEnter("to continue");
+            }
+        }
+
+        public void Play()
+        {
+            var quadrant = Initialise();
+            var gameOver = false;
+
+            _output.Write(Strings.Enterprise);
+            _output.Write(
+                Strings.Orders,
+                _galaxy.KlingonCount,
+                _finalStarDate,
+                _finalStarDate - _initialStardate,
+                _galaxy.StarbaseCount > 1 ? "are" : "is",
+                _galaxy.StarbaseCount,
+                _galaxy.StarbaseCount > 1 ? "s" : "");
+
+            _input.WaitForAnyKeyButEnter("when ready to accept command");
+
+            _enterprise.Enter(quadrant, Strings.StartText);
+
+            while (!gameOver)
+            {
+                var command = _input.GetCommand();
+
+                gameOver = command == Command.XXX || _enterprise.Execute(command);
+            }
+        }
+
+        private Quadrant Initialise()
+        {
+            var random = new Random();
+
+            _currentStardate = _initialStardate = random.GetInt(20, 40) * 100;
+            _finalStarDate = _initialStardate + random.GetInt(25, 35);
+
+            _currentQuadrant = random.GetCoordinate();
+            _currentSector = random.GetCoordinate();
+
+            _galaxy = new Galaxy();
+            _initialKlingonCount = _galaxy.KlingonCount;
+
+            _enterprise = new Enterprise(3000, random.GetCoordinate());
+            _enterprise.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
+                .Add(new ShieldControl(_enterprise, _output, _input));
+
+            return new Quadrant(_galaxy[_currentQuadrant], _enterprise);
+        }
+
+        public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye");
+    }
+}
diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs
new file mode 100644
index 00000000..98e5b297
--- /dev/null
+++ b/84 Super Star Trek/csharp/Input.cs	
@@ -0,0 +1,76 @@
+using System;
+using System.Linq;
+using static System.StringComparison;
+
+namespace SuperStarTrek
+{
+    internal class Input
+    {
+        private readonly Output _output;
+
+        public Input(Output output)
+        {
+            _output = output;
+        }
+
+        public void WaitForAnyKeyButEnter(string prompt)
+        {
+            _output.Write($"Hit any key but Enter {prompt} ");
+            while (Console.ReadKey(intercept: true).Key == ConsoleKey.Enter);
+        }
+
+        public string GetString(string prompt)
+        {
+            _output.Prompt(prompt);
+            return Console.ReadLine();
+        }
+
+        public double GetNumber(string prompt)
+        {
+            _output.Prompt(prompt);
+
+            while (true)
+            {
+                var response = Console.ReadLine();
+                if (double.TryParse(response, out var value))
+                {
+                    return value;
+                }
+
+                _output.WriteLine("!Number expected - retry input line");
+                _output.Prompt();
+            }
+        }
+
+        public bool TryGetNumber(string prompt, double minValue, double maxValue, out double value)
+        {
+            value = GetNumber($"{prompt} ({minValue}-{maxValue})");
+
+            return value >= minValue && value <= maxValue;
+        }
+
+        internal bool GetString(string replayPrompt, string trueValue)
+            => GetString(replayPrompt).Equals(trueValue, InvariantCultureIgnoreCase);
+
+        public Command GetCommand()
+        {
+            while(true)
+            {
+                var response = GetString("Command");
+
+                if (response != "" &&
+                    Enum.TryParse(response.Substring(0, 3), ignoreCase: true, out Command parsedCommand))
+                {
+                    return parsedCommand;
+                }
+
+                _output.WriteLine("Enter one of the following:");
+                foreach (var command in Enum.GetValues(typeof(Command)).OfType())
+                {
+                    _output.WriteLine($"  {command}  ({command.GetDescription()})");
+                }
+                _output.WriteLine();
+            }
+        }
+    }
+}
diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs
new file mode 100644
index 00000000..4f6055cc
--- /dev/null
+++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs	
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using SuperStarTrek.Resources;
+using SuperStarTrek.Space;
+using SuperStarTrek.Systems;
+
+namespace SuperStarTrek.Objects
+{
+    internal class Enterprise
+    {
+        private readonly int _maxEnergy;
+        private readonly List _systems;
+        private readonly Dictionary _commandExecutors;
+        private Quadrant _quadrant;
+        private ShieldControl _shieldControl;
+
+        public Enterprise(int maxEnergy, Coordinates sector)
+        {
+            Sector = sector;
+            TotalEnergy = _maxEnergy = maxEnergy;
+
+            _systems = new List();
+            _commandExecutors = new Dictionary();
+        }
+
+        public Coordinates Quadrant => _quadrant.Coordinates;
+        public Coordinates Sector { get; }
+        public string Condition => GetCondition();
+        public double Shields => _shieldControl.Energy;
+        public double Energy => TotalEnergy - Shields;
+        public double TotalEnergy { get; private set; }
+        public int TorpedoCount { get; }
+
+        public bool IsDocked { get; private set; }
+
+        public Enterprise Add(Subsystem system)
+        {
+            _systems.Add(system);
+            _commandExecutors[system.Command] = system;
+
+            if (system is ShieldControl shieldControl) { _shieldControl = shieldControl; }
+
+            return this;
+        }
+
+        public string GetDamageReport()
+        {
+            var report = new StringBuilder();
+            report.AppendLine().AppendLine().AppendLine("Device             State of Repair");
+            foreach (var system in _systems)
+            {
+                report.Append(system.Name.PadRight(25)).AppendLine(system.Condition.ToString(" 0.00;-0.00"));
+            }
+            report.AppendLine();
+            return report.ToString();
+        }
+
+        public void Enter(Quadrant quadrant, string entryTextFormat)
+        {
+            _quadrant = quadrant;
+
+            var _output = new Output();
+            _output.Write(entryTextFormat, quadrant);
+
+            if (quadrant.HasKlingons)
+            {
+                _output.Write(Strings.CombatArea);
+                if (Shields <= 200) { _output.Write(Strings.LowShields); }
+            }
+
+            IsDocked = quadrant.EnterpriseIsNextToStarbase;
+
+            Execute(Command.SRS);
+        }
+
+        private string GetCondition() =>
+            (_quadrant.HasKlingons, Energy / _maxEnergy) switch
+            {
+                (true, _) => "*Red*",
+                (_, < 0.1) => "Yellow",
+                _ => "Green"
+            };
+
+        public bool Execute(Command command)
+        {
+            _commandExecutors[command].ExecuteCommand(_quadrant);
+            return false;
+        }
+
+        internal bool Recognises(string command)
+        {
+            throw new NotImplementedException();
+        }
+
+        internal string GetCommandList()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override string ToString() => "<*>";
+    }
+}
diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs
new file mode 100644
index 00000000..fdf47031
--- /dev/null
+++ b/84 Super Star Trek/csharp/Objects/Klingon.cs	
@@ -0,0 +1,14 @@
+namespace SuperStarTrek.Objects
+{
+    internal class Klingon
+    {
+        private double _energy;
+
+        public Klingon()
+        {
+            _energy = new Random().GetDouble(100, 300);
+        }
+
+        public override string ToString() => "+K+";
+    }
+}
diff --git a/84 Super Star Trek/csharp/Objects/Star.cs b/84 Super Star Trek/csharp/Objects/Star.cs
new file mode 100644
index 00000000..1d9eef6f
--- /dev/null
+++ b/84 Super Star Trek/csharp/Objects/Star.cs	
@@ -0,0 +1,7 @@
+namespace SuperStarTrek.Objects
+{
+    internal class Star
+    {
+        public override string ToString() => " * ";
+    }
+}
diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs
new file mode 100644
index 00000000..33110837
--- /dev/null
+++ b/84 Super Star Trek/csharp/Objects/Starbase.cs	
@@ -0,0 +1,7 @@
+namespace SuperStarTrek.Objects
+{
+    internal class Starbase
+    {
+        public override string ToString() => ">!<";
+    }
+}
diff --git a/84 Super Star Trek/csharp/Output.cs b/84 Super Star Trek/csharp/Output.cs
new file mode 100644
index 00000000..77e5e919
--- /dev/null
+++ b/84 Super Star Trek/csharp/Output.cs	
@@ -0,0 +1,15 @@
+using System;
+
+namespace SuperStarTrek
+{
+    internal class Output
+    {
+        public void Write(string text) => Console.Write(text);
+        public void Write(string format, params object[] args) => Console.Write(format, args);
+        public void WriteLine(string text = "") => Console.WriteLine(text);
+
+        public void NextLine() => Console.WriteLine();
+
+        public void Prompt(string text = "") => Console.Write($"{text}? ");
+    }
+}
diff --git a/84 Super Star Trek/csharp/Program.cs b/84 Super Star Trek/csharp/Program.cs
index 0a5b6268..30360ee0 100644
--- a/84 Super Star Trek/csharp/Program.cs	
+++ b/84 Super Star Trek/csharp/Program.cs	
@@ -23,31 +23,20 @@
 // ****  CONVERTED TO MICROSOFT C# 2/20/21 BY ANDREW COOPER
 // ****
 
-using System;
-
-using static System.StringComparison;
-
 namespace SuperStarTrek
 {
-    class Program
+    internal class Program
     {
-        static void Main(string[] args)
+        static void Main()
         {
-            Console.WriteLine(Strings.Title);
+            var game = new Game();
 
-            Console.Write("Do you need instructions (Y/N)? ");
-            var response = Console.ReadLine();
-            Console.WriteLine();
+            game.DoIntroduction();
 
-            if (!response.Equals("N", InvariantCultureIgnoreCase))
+            do
             {
-                Console.WriteLine(Strings.Instructions);
-
-                Console.WriteLine("Press  to continue...");
-                Console.ReadLine();
-            }
-
-            Console.WriteLine(Strings.Enterprise);
+                game.Play();
+            } while (game.Replay());
         }
     }
 }
diff --git a/84 Super Star Trek/csharp/Random.cs b/84 Super Star Trek/csharp/Random.cs
new file mode 100644
index 00000000..9b7e1bff
--- /dev/null
+++ b/84 Super Star Trek/csharp/Random.cs	
@@ -0,0 +1,25 @@
+using SuperStarTrek.Space;
+
+namespace SuperStarTrek
+{
+    internal class Random
+    {
+        private static readonly System.Random _random = new();
+
+        public Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive(), Get1To8Inclusive());
+
+        // Duplicates the algorithm used in the original code to get an integer value from 1 to 8, inclusive:
+        //     475 DEF FNR(R)=INT(RND(R)*7.98+1.01)
+        // Returns a value from 1 to 8, inclusive.
+        // Note there's a slight bias away from the extreme values, 1 and 8.
+        public int Get1To8Inclusive() => (int)(_random.NextDouble() * 7.98 + 1.01);
+
+        public int GetInt(int inclusiveMinValue, int exclusiveMaxValue) =>
+            _random.Next(inclusiveMinValue, exclusiveMaxValue);
+
+        public double GetDouble() => _random.NextDouble();
+
+        public double GetDouble(double inclusiveMinValue, double exclusiveMaxValue)
+            => _random.NextDouble() * (exclusiveMaxValue - inclusiveMinValue) + inclusiveMinValue;
+    }
+}
diff --git a/84 Super Star Trek/csharp/Resources/AcceptCommand.txt b/84 Super Star Trek/csharp/Resources/AcceptCommand.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/84 Super Star Trek/csharp/Resources/CombatArea.txt b/84 Super Star Trek/csharp/Resources/CombatArea.txt
new file mode 100644
index 00000000..ea27a826
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/CombatArea.txt	
@@ -0,0 +1 @@
+COMBAT AREA      CONDITION RED
diff --git a/84 Super Star Trek/csharp/Resources/Instructions.txt b/84 Super Star Trek/csharp/Resources/Instructions.txt
index 51f40cf6..fd74857e 100644
--- a/84 Super Star Trek/csharp/Resources/Instructions.txt	
+++ b/84 Super Star Trek/csharp/Resources/Instructions.txt	
@@ -53,7 +53,7 @@ LRS command = Long Range Sensor Scan
      The scan is coded in the form ###, where the units digit
      is the number of stars, the tens digit is the number of
      starbases, and the hundreds digit is the number of
-     Kilngons.
+     Klingons.
 
      Example - 207 = 2 Klingons, No starbases, & 7 stars.
 
@@ -103,3 +103,4 @@ COM command = Library-Computer
      Option 5 = Galactic Region Name Map
         This option prints the names of the sixteen major
         galactic regions referred to in the game.
+
diff --git a/84 Super Star Trek/csharp/Resources/LowShields.txt b/84 Super Star Trek/csharp/Resources/LowShields.txt
new file mode 100644
index 00000000..b449b6eb
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/LowShields.txt	
@@ -0,0 +1 @@
+   SHIELDS DANGEROUSLY LOW
diff --git a/84 Super Star Trek/csharp/Resources/Orders.txt b/84 Super Star Trek/csharp/Resources/Orders.txt
new file mode 100644
index 00000000..7dc14b24
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/Orders.txt	
@@ -0,0 +1,6 @@
+Your orders are as follows:
+    Destroy the {0} Klingon warships which have invaded
+  the galaxy before they can attack federation headquarters
+  on stardate {1}. This gives you {2} days. There {3}
+  {4} starbase{5} in the galaxy for resupplying your ship.
+
diff --git a/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt b/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt
new file mode 100644
index 00000000..52aca0d1
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt	
@@ -0,0 +1,3 @@
+The Federation is in need of a new starship commander
+for a similar mission -- if there is a volunteer
+let him step forward and enter 'Aye'
\ No newline at end of file
diff --git a/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt b/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt
new file mode 100644
index 00000000..acc87f59
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt	
@@ -0,0 +1 @@
+Shields dropped for docking purposes
diff --git a/84 Super Star Trek/csharp/Resources/ShortRangeSensorsOut.txt b/84 Super Star Trek/csharp/Resources/ShortRangeSensorsOut.txt
new file mode 100644
index 00000000..1c958cab
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/ShortRangeSensorsOut.txt	
@@ -0,0 +1 @@
+*** Short Range Sensors are out ***
diff --git a/84 Super Star Trek/csharp/Resources/StartText.txt b/84 Super Star Trek/csharp/Resources/StartText.txt
new file mode 100644
index 00000000..3c6028a5
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/StartText.txt	
@@ -0,0 +1,5 @@
+
+
+Your mission begins with your starship located
+in the galactic quadrant, '{0}'.
+
diff --git a/84 Super Star Trek/csharp/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs
similarity index 61%
rename from 84 Super Star Trek/csharp/Strings.cs
rename to 84 Super Star Trek/csharp/Resources/Strings.cs
index 45241225..930f1663 100644
--- a/84 Super Star Trek/csharp/Strings.cs	
+++ b/84 Super Star Trek/csharp/Resources/Strings.cs	
@@ -2,15 +2,20 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-using static System.StringComparison;
-
-namespace SuperStarTrek
+namespace SuperStarTrek.Resources
 {
     internal static class Strings
     {
-        public static string Title => GetResource();
-        public static string Instructions => GetResource();
+        public static string CombatArea => GetResource();
         public static string Enterprise => GetResource();
+        public static string Instructions => GetResource();
+        public static string LowShields => GetResource();
+        public static string Orders => GetResource();
+        public static string ReplayPrompt => GetResource();
+        public static string ShieldsDropped => GetResource();
+        public static string ShortRangeSensorsOut => GetResource();
+        public static string StartText => GetResource();
+        public static string Title => GetResource();
 
         private static string GetResource([CallerMemberName] string name = "")
         {
diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinate.cs
new file mode 100644
index 00000000..b3328c24
--- /dev/null
+++ b/84 Super Star Trek/csharp/Space/Coordinate.cs	
@@ -0,0 +1,27 @@
+using System;
+
+namespace SuperStarTrek.Space
+{
+    // Represents the corrdintate of a quadrant in the galaxy, or a sector in a quadrant.
+    // Note that the origin is top-left, x increase downwards, and y increases to the right.
+    internal record Coordinates
+    {
+        public Coordinates(int x, int y)
+        {
+            X = Validated(x, nameof(x));
+            Y = Validated(y, nameof(y));
+        }
+
+        public int X { get; }
+        public int Y { get; }
+
+        private int Validated(int value, string argumentName)
+        {
+            if (value >= 1 && value <= 8) { return value; }
+
+            throw new ArgumentOutOfRangeException(argumentName, value, "Must be 1 to 8 inclusive");
+        }
+
+        public override string ToString() => $"{X} , {Y}";
+    }
+}
diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs
new file mode 100644
index 00000000..dd9ecfba
--- /dev/null
+++ b/84 Super Star Trek/csharp/Space/Course.cs	
@@ -0,0 +1,50 @@
+using System;
+
+namespace SuperStarTrek.Space
+{
+    // Implements the course calculations from the original code:
+    //     530 FORI=1TO9:C(I,1)=0:C(I,2)=0:NEXTI
+    //     540 C(3,1)=-1:C(2,1)=-1:C(4,1)=-1:C(4,2)=-1:C(5,2)=-1:C(6,2)=-1
+    //     600 C(1,2)=1:C(2,2)=1:C(6,1)=1:C(7,1)=1:C(8,1)=1:C(8,2)=1:C(9,2)=1
+    //
+    //     3110 X1=C(C1,1)+(C(C1+1,1)-C(C1,1))*(C1-INT(C1))
+    //     3140 X2=C(C1,2)+(C(C1+1,2)-C(C1,2))*(C1-INT(C1))
+    internal class Course
+    {
+        private static readonly (int DeltaX, int DeltaY)[] cardinals = new[]
+        {
+            (0, 1),
+            (-1, 1),
+            (-1, 0),
+            (-1, -1),
+            (0, -1),
+            (1, -1),
+            (1, 0),
+            (1, 1),
+            (0, 1)
+        };
+
+        public Course(double direction)
+        {
+            if (direction < 1 || direction > 9)
+            {
+                throw new ArgumentOutOfRangeException(
+                    nameof(direction),
+                    direction,
+                    "Must be between 1 and 9, inclusive.");
+            }
+
+            var cardinalDirection = (int)(direction - 1) % 8;
+            var fractionalDirection = direction - (int)direction;
+
+            var baseCardinal = cardinals[cardinalDirection];
+            var nextCardinal = cardinals[cardinalDirection + 1];
+
+            DeltaX = baseCardinal.DeltaX + (nextCardinal.DeltaX - baseCardinal.DeltaX) * fractionalDirection;
+            DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
+        }
+
+        public double DeltaX { get; }
+        public double DeltaY { get; }
+    }
+}
diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs
new file mode 100644
index 00000000..171ecdea
--- /dev/null
+++ b/84 Super Star Trek/csharp/Space/Galaxy.cs	
@@ -0,0 +1,34 @@
+using System.Linq;
+
+namespace SuperStarTrek.Space
+{
+    internal class Galaxy
+    {
+        private readonly QuadrantInfo[][] _quadrants;
+
+        public Galaxy()
+        {
+            var random = new Random();
+
+            _quadrants = Enumerable.Range(1, 8).Select(x =>
+                Enumerable.Range(1, 8).Select(y => QuadrantInfo.Create(new Coordinates(x, y), "")).ToArray())
+                .ToArray();
+
+            if (StarbaseCount == 0)
+            {
+                var randomQuadrant = this[random.GetCoordinate()];
+                randomQuadrant.AddStarbase();
+
+                if (randomQuadrant.KlingonCount < 2)
+                {
+                    randomQuadrant.AddKlingon();
+                }
+            }
+        }
+
+        public QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X - 1][coordinate.Y - 1];
+
+        public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount);
+        public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
+    }
+}
diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs
new file mode 100644
index 00000000..2aa45b6d
--- /dev/null
+++ b/84 Super Star Trek/csharp/Space/Quadrant.cs	
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using SuperStarTrek.Objects;
+
+namespace SuperStarTrek.Space
+{
+    internal class Quadrant
+    {
+        private readonly QuadrantInfo _info;
+        private readonly Random _random;
+        private readonly Dictionary _sectors;
+        private readonly Coordinates _enterpriseSector;
+        private readonly Coordinates _starbaseSector;
+
+        public Quadrant(QuadrantInfo info, Enterprise enterprise)
+        {
+            _info = info;
+            _random = new Random();
+
+            _enterpriseSector = enterprise.Sector;
+            _sectors = new Dictionary { [enterprise.Sector] = enterprise };
+            PositionObject(() => new Klingon(), _info.KlingonCount);
+            if (_info.HasStarbase)
+            {
+                _starbaseSector = PositionObject(() => new Starbase());
+            }
+            PositionObject(() => new Star(), _info.StarCount);
+        }
+
+        public Coordinates Coordinates => _info.Coordinates;
+        public bool HasKlingons => _info.KlingonCount > 0;
+        public bool HasStarbase => _info.HasStarbase;
+        public bool EnterpriseIsNextToStarbase =>
+            _info.HasStarbase &&
+            Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 &&
+            Math.Abs(_enterpriseSector.Y - _starbaseSector.Y) <= 1;
+
+        public override string ToString() => _info.Name;
+
+        private Coordinates PositionObject(Func objectFactory)
+        {
+            var sector = GetRandomEmptySector();
+            _sectors[sector] = objectFactory.Invoke();
+            return sector;
+        }
+
+        private void PositionObject(Func objectFactory, int count)
+        {
+            for (int i = 0; i < count; i++)
+            {
+                PositionObject(objectFactory);
+            }
+        }
+
+        private Coordinates GetRandomEmptySector()
+        {
+            while (true)
+            {
+                var sector = _random.GetCoordinate();
+                if (!_sectors.ContainsKey(sector))
+                {
+                    return sector;
+                }
+            }
+        }
+
+        public IEnumerable GetDisplayLines() => Enumerable.Range(1, 8).Select(x => GetDisplayLine(x));
+
+        private string GetDisplayLine(int x)
+            => string.Join(
+                " ",
+                Enumerable
+                    .Range(1, 8)
+                    .Select(y => new Coordinates(x, y))
+                    .Select(c => _sectors.GetValueOrDefault(c))
+                    .Select(o => o?.ToString() ?? "   "));
+    }
+}
diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs
new file mode 100644
index 00000000..ed9ed3fa
--- /dev/null
+++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs	
@@ -0,0 +1,40 @@
+namespace SuperStarTrek.Space
+{
+    internal class QuadrantInfo
+    {
+        private QuadrantInfo(Coordinates coordinates, string name, int klingonCount, int starCount, bool hasStarbase)
+        {
+            Coordinates = coordinates;
+            Name = name;
+            KlingonCount = klingonCount;
+            StarCount = starCount;
+            HasStarbase = hasStarbase;
+        }
+
+        public Coordinates Coordinates { get; }
+        public string Name { get; }
+        public int KlingonCount { get; private set; }
+        public bool HasStarbase { get; private set; }
+        public int StarCount { get; }
+
+        public static QuadrantInfo Create(Coordinates coordinates, string name)
+        {
+            var random = new Random();
+            var klingonCount = random.GetDouble() switch
+            {
+                > 0.98 => 3,
+                > 0.95 => 2,
+                > 0.80 => 1,
+                _ => 0
+            };
+            var hasStarbase = random.GetDouble() > 0.96;
+            var starCount = random.Get1To8Inclusive();
+
+            return new QuadrantInfo(coordinates, name, klingonCount, starCount, hasStarbase);
+        }
+
+        internal void AddKlingon() => KlingonCount += 1;
+
+        internal void AddStarbase() => HasStarbase = true;
+    }
+}
diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs
new file mode 100644
index 00000000..e7aca413
--- /dev/null
+++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
@@ -0,0 +1,53 @@
+using SuperStarTrek.Objects;
+using SuperStarTrek.Space;
+
+namespace SuperStarTrek.Systems
+{
+    internal class ShieldControl : Subsystem
+    {
+        private readonly Enterprise _enterprise;
+        private readonly Output _output;
+        private readonly Input _input;
+
+        public ShieldControl(Enterprise enterprise, Output output, Input input)
+            : base("Shield Control", Command.SHE)
+        {
+            _enterprise = enterprise;
+            _output = output;
+            _input = input;
+        }
+
+        public double Energy { get; private set; }
+
+        public override void ExecuteCommand(Quadrant quadrant)
+        {
+            if (Condition < 0)
+            {
+                _output.WriteLine("Shield Control inoperable");
+                return;
+            }
+
+            _output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
+            var requested = _input.GetNumber($"Number of units to shields");
+
+            if (Validate(requested))
+            {
+                Energy = requested;
+                return;
+            }
+
+            _output.WriteLine("");
+        }
+
+        private bool Validate(double requested)
+        {
+            if (requested > _enterprise.TotalEnergy)
+            {
+                _output.WriteLine("Shield Control reports, 'This is not the Federation Treasury.'");
+                return false;
+            }
+
+            return requested >= 0 && requested != Energy;
+        }
+    }
+}
diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs
new file mode 100644
index 00000000..d22dda70
--- /dev/null
+++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs	
@@ -0,0 +1,59 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using SuperStarTrek.Objects;
+using SuperStarTrek.Resources;
+using SuperStarTrek.Space;
+
+namespace SuperStarTrek.Systems
+{
+    internal class ShortRangeSensors : Subsystem
+    {
+        private readonly Enterprise _enterprise;
+        private readonly Galaxy _galaxy;
+        private readonly Game _game;
+        private readonly Output _output;
+
+        public ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, Output output)
+            : base("Short Range Sensors", Command.SRS)
+        {
+            _enterprise = enterprise;
+            _galaxy = galaxy;
+            _game = game;
+            _output = output;
+        }
+
+        public override void ExecuteCommand(Quadrant quadrant)
+        {
+            if (_enterprise.IsDocked)
+            {
+                _output.WriteLine(Strings.ShieldsDropped);
+            }
+
+            if (Condition < 0)
+            {
+                _output.WriteLine(Strings.ShortRangeSensorsOut);
+            }
+
+            _output.WriteLine("---------------------------------");
+            quadrant.GetDisplayLines()
+                .Zip(GetStatusLines(), (sectors, status) => $" {sectors}         {status}")
+                .ToList()
+                .ForEach(l => _output.WriteLine(l));
+            _output.WriteLine("---------------------------------");
+        }
+
+        public IEnumerable GetStatusLines()
+        {
+            yield return $"Stardate           {_game.Stardate}";
+            yield return $"Condition          {_enterprise.Condition}";
+            yield return $"Quadrant           {_enterprise.Quadrant}";
+            yield return $"Sector             {_enterprise.Sector}";
+            yield return $"Photon torpedoes   {_enterprise.TorpedoCount}";
+            yield return $"Total energy       {Math.Ceiling(_enterprise.Energy)}";
+            yield return $"Shields            {(int)_enterprise.Shields}";
+            yield return $"Klingons remaining {_galaxy.KlingonCount}";
+        }
+    }
+}
diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs
new file mode 100644
index 00000000..ae2ef7d6
--- /dev/null
+++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs	
@@ -0,0 +1,20 @@
+using SuperStarTrek.Space;
+
+namespace SuperStarTrek.Systems
+{
+    internal abstract class Subsystem
+    {
+        protected Subsystem(string name, Command command)
+        {
+            Name = name;
+            Command = command;
+            Condition = 0;
+        }
+
+        public string Name { get; }
+        public double Condition { get; }
+        public Command Command { get; }
+
+        public abstract void ExecuteCommand(Quadrant quadrant);
+    }
+}

From b68f5c97fa0ac0b588370242132c71a053f4e1a2 Mon Sep 17 00:00:00 2001
From: Adam Jones 
Date: Sat, 27 Feb 2021 13:26:16 +0100
Subject: [PATCH 037/749] Initial version

---
 08 Batnum/csharp/Batnum.csproj                |  24 ++
 08 Batnum/csharp/Batnum.sln                   |  25 ++
 08 Batnum/csharp/BatnumGame.cs                | 114 +++++++++
 08 Batnum/csharp/ConsoleUtilities.cs          | 111 +++++++++
 08 Batnum/csharp/Program.cs                   |  30 +++
 .../csharp/Properties/Resources.Designer.cs   | 216 ++++++++++++++++++
 08 Batnum/csharp/Properties/Resources.en.resx | 171 ++++++++++++++
 08 Batnum/csharp/Properties/Resources.fr.resx | 171 ++++++++++++++
 08 Batnum/csharp/Properties/Resources.resx    | 171 ++++++++++++++
 08 Batnum/csharp/README.md                    |   8 +
 10 files changed, 1041 insertions(+)
 create mode 100644 08 Batnum/csharp/Batnum.csproj
 create mode 100644 08 Batnum/csharp/Batnum.sln
 create mode 100644 08 Batnum/csharp/BatnumGame.cs
 create mode 100644 08 Batnum/csharp/ConsoleUtilities.cs
 create mode 100644 08 Batnum/csharp/Program.cs
 create mode 100644 08 Batnum/csharp/Properties/Resources.Designer.cs
 create mode 100644 08 Batnum/csharp/Properties/Resources.en.resx
 create mode 100644 08 Batnum/csharp/Properties/Resources.fr.resx
 create mode 100644 08 Batnum/csharp/Properties/Resources.resx

diff --git a/08 Batnum/csharp/Batnum.csproj b/08 Batnum/csharp/Batnum.csproj
new file mode 100644
index 00000000..8a87960b
--- /dev/null
+++ b/08 Batnum/csharp/Batnum.csproj	
@@ -0,0 +1,24 @@
+
+
+  
+    Exe
+    net5.0
+    en-US
+  
+
+  
+    
+      True
+      True
+      Resources.resx
+    
+  
+
+  
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+  
+
+
diff --git a/08 Batnum/csharp/Batnum.sln b/08 Batnum/csharp/Batnum.sln
new file mode 100644
index 00000000..1e80320b
--- /dev/null
+++ b/08 Batnum/csharp/Batnum.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31019.35
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Batnum", "Batnum.csproj", "{64F32165-9D67-42B1-B04C-953CC756A170}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{64F32165-9D67-42B1-B04C-953CC756A170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{64F32165-9D67-42B1-B04C-953CC756A170}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{64F32165-9D67-42B1-B04C-953CC756A170}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{64F32165-9D67-42B1-B04C-953CC756A170}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {73E40CC2-0E4E-48CF-8BDD-D6B6E995C14F}
+	EndGlobalSection
+EndGlobal
diff --git a/08 Batnum/csharp/BatnumGame.cs b/08 Batnum/csharp/BatnumGame.cs
new file mode 100644
index 00000000..1c702840
--- /dev/null
+++ b/08 Batnum/csharp/BatnumGame.cs	
@@ -0,0 +1,114 @@
+using Batnum.Properties;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Batnum
+{
+    public enum WinOptions
+    {
+        /// 
+        /// Last person to play wins
+        /// 
+        WinWithTakeLast = 1,
+        /// 
+        /// Last person to play loses
+        /// 
+        WinWithAvoidLast = 2
+    }
+
+    public enum Players
+    {
+        Computer = 1,
+        Human = 2
+    }
+
+    public class BatnumGame
+    {
+        public BatnumGame(int pileSize, WinOptions winCriteria, int minTake, int maxtake, Players firstPlayer, FuncaskPlayerCallback)
+        {
+            this.pileSize = pileSize;
+            this.winCriteria = winCriteria;
+            this.minTake = minTake;
+            this.maxTake = maxtake;
+            this.currentPlayer = firstPlayer;
+            this.askPlayerCallback = askPlayerCallback;
+        }
+
+        private int pileSize;
+        private WinOptions winCriteria;
+        private int minTake;
+        private int maxTake;
+        private Players currentPlayer;
+        private Func askPlayerCallback;
+
+        /// 
+        /// Returns true if the game is running
+        /// 
+        public bool IsRunning => pileSize > 0;
+
+        /// 
+        /// Takes the next turn
+        /// 
+        /// A message to be displayed to the player
+        public string TakeTurn()
+        {
+            //Edge condition - can occur when minTake is more > 1 
+            if (pileSize < minTake)
+            {
+                pileSize = 0;
+                return string.Format(Resources.END_DRAW, minTake);
+            }
+            return currentPlayer == Players.Computer ? ComputerTurn() : PlayerTurn();
+        }
+
+        private string PlayerTurn()
+        {
+            int draw = askPlayerCallback(Resources.INPUT_TURN);
+            if (draw == 0)
+            {
+                pileSize = 0;
+                return Resources.INPUT_ZERO;
+            }
+            if (draw < minTake || draw > maxTake || draw > pileSize)
+            {
+                return Resources.INPUT_ILLEGAL;
+            }
+            pileSize = pileSize - draw;
+            if (pileSize == 0)
+            {
+                return winCriteria == WinOptions.WinWithTakeLast ? Resources.END_PLAYERWIN : Resources.END_PLAYERLOSE;
+            }
+            currentPlayer = Players.Computer;
+            return "";
+        }
+
+        private string ComputerTurn()
+        {
+            //first calculate the move to play
+            int sumTake = minTake + maxTake;
+            int draw = pileSize - sumTake * (int)(pileSize / (float)sumTake);
+            draw = Math.Clamp(draw, minTake, maxTake);
+
+            //detect win/lose conditions
+            switch (winCriteria)
+            {
+                case WinOptions.WinWithAvoidLast when (pileSize == minTake): //lose condition
+                    pileSize = 0;
+                    return string.Format(Resources.END_COMPLOSE, minTake);
+                case WinOptions.WinWithAvoidLast when (pileSize <= maxTake): //avoid automatic loss on next turn
+                    draw = Math.Clamp(draw, minTake, pileSize - 1);
+                    break;
+                case WinOptions.WinWithTakeLast when pileSize <= maxTake: // win condition
+                    draw = Math.Min(pileSize, maxTake);
+                    pileSize = 0;
+                    return string.Format(Resources.END_COMPWIN, draw);
+            }
+            pileSize -= draw;
+            currentPlayer = Players.Human;
+            return string.Format(Resources.COMPTURN, draw, pileSize);
+        }
+    }
+}
diff --git a/08 Batnum/csharp/ConsoleUtilities.cs b/08 Batnum/csharp/ConsoleUtilities.cs
new file mode 100644
index 00000000..2dd5f09b
--- /dev/null
+++ b/08 Batnum/csharp/ConsoleUtilities.cs	
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Batnum
+{
+    public static class ConsoleUtilities
+    {
+        /// 
+        /// Ask the user a question and expects a comma separated pair of numbers representing a number range in response
+        /// the range provided must have a maximum which is greater than the minimum 
+        /// 
+        /// The question to ask
+        /// The minimum value expected
+        /// The maximum value expected
+        /// A pair of numbers representing the minimum and maximum of the range
+        public static (int min, int max) AskNumberRangeQuestion(string question, Func Validate)
+        {
+            while (true)
+            {
+                Console.Write(question);
+                Console.Write(" ");
+                string[] rawInput = Console.ReadLine().Split(',');
+                if (rawInput.Length == 2)
+                {
+                    if (int.TryParse(rawInput[0], out int min) && int.TryParse(rawInput[1], out int max))
+                    {
+                        if (Validate(min, max))
+                        {
+                            return (min, max);
+                        }
+                    }
+                }
+                Console.WriteLine();
+            }
+        }
+
+        /// 
+        /// Ask the user a question and expects a number in response
+        /// 
+        /// The question to ask
+        /// A minimum value expected
+        /// A maximum value expected
+        /// The number the user entered
+        public static int AskNumberQuestion(string question, Func Validate)
+        {
+            while (true)
+            {
+                Console.Write(question);
+                Console.Write(" ");
+                string rawInput = Console.ReadLine();
+                if (int.TryParse(rawInput, out int number))
+                {
+                    if (Validate(number))
+                    {
+                        return number;
+                    }
+                }
+                Console.WriteLine();
+            }
+        }
+
+        /// 
+        /// Align content to center of console.
+        /// 
+        /// Content to center
+        /// Center aligned text
+        public static string CenterText(string content)
+        {
+            int windowWidth = Console.WindowWidth;
+            return String.Format("{0," + ((windowWidth / 2) + (content.Length / 2)) + "}", content);
+        }
+
+        /// 
+        ///     Writes the specified data, followed by the current line terminator, to the standard output stream, while wrapping lines that would otherwise break words.
+        ///     source: https://stackoverflow.com/questions/20534318/make-console-writeline-wrap-words-instead-of-letters
+        /// 
+        /// The value to write.
+        /// The value that indicates the column width of tab characters.
+        public static void WriteLineWordWrap(string paragraph, int tabSize = 4)
+        {
+            string[] lines = paragraph
+                .Replace("\t", new String(' ', tabSize))
+                .Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
+
+            for (int i = 0; i < lines.Length; i++)
+            {
+                string process = lines[i];
+                List wrapped = new List();
+
+                while (process.Length > Console.WindowWidth)
+                {
+                    int wrapAt = process.LastIndexOf(' ', Math.Min(Console.WindowWidth - 1, process.Length));
+                    if (wrapAt <= 0) break;
+
+                    wrapped.Add(process.Substring(0, wrapAt));
+                    process = process.Remove(0, wrapAt + 1);
+                }
+
+                foreach (string wrap in wrapped)
+                {
+                    Console.WriteLine(wrap);
+                }
+
+                Console.WriteLine(process);
+            }
+        }
+    }
+}
diff --git a/08 Batnum/csharp/Program.cs b/08 Batnum/csharp/Program.cs
new file mode 100644
index 00000000..08e6b304
--- /dev/null
+++ b/08 Batnum/csharp/Program.cs	
@@ -0,0 +1,30 @@
+using Batnum;
+using Batnum.Properties;
+using System;
+
+Console.WriteLine(ConsoleUtilities.CenterText(Resources.GAME_NAME));
+Console.WriteLine(ConsoleUtilities.CenterText(Resources.INTRO_HEADER));
+Console.WriteLine();
+Console.WriteLine();
+Console.WriteLine();
+ConsoleUtilities.WriteLineWordWrap(Resources.INTRO_PART1);
+Console.WriteLine();
+ConsoleUtilities.WriteLineWordWrap(Resources.INTRO_PART2);
+
+while (true)
+{
+    Console.WriteLine();
+    int pileSize = ConsoleUtilities.AskNumberQuestion(Resources.START_QUESTION_PILESIZE, (n) => n > 1);
+    WinOptions winOption = (WinOptions)ConsoleUtilities.AskNumberQuestion(Resources.START_QUESTION_WINOPTION, (n) => Enum.IsDefined(typeof(WinOptions), n));
+    (int minTake, int maxTake) = ConsoleUtilities.AskNumberRangeQuestion(Resources.START_QUESTION_DRAWMINMAX, (min,max) => min >= 1 && max < pileSize && max > min);
+    Players currentPlayer = (Players)ConsoleUtilities.AskNumberQuestion(Resources.START_QUESTION_WHOSTARTS, (n) => Enum.IsDefined(typeof(Players), n));
+
+    BatnumGame game = new BatnumGame(pileSize, winOption, minTake, maxTake, currentPlayer, (question) => ConsoleUtilities.AskNumberQuestion(question, (c) => true));
+    while(game.IsRunning)
+    {
+        string message = game.TakeTurn();
+        Console.WriteLine(message);
+    }
+
+}
+
diff --git a/08 Batnum/csharp/Properties/Resources.Designer.cs b/08 Batnum/csharp/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..b0cc5dd9
--- /dev/null
+++ b/08 Batnum/csharp/Properties/Resources.Designer.cs	
@@ -0,0 +1,216 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace Batnum.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Batnum.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to COMPUTER TAKES {0} AND  LEAVES {1}.
+        /// 
+        internal static string COMPTURN {
+            get {
+                return ResourceManager.GetString("COMPTURN", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to COMPUTER TAKES {0} AND LOSES.
+        /// 
+        internal static string END_COMPLOSE {
+            get {
+                return ResourceManager.GetString("END_COMPLOSE", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to COMPUTER TAKES {0} AND WINS.
+        /// 
+        internal static string END_COMPWIN {
+            get {
+                return ResourceManager.GetString("END_COMPWIN", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT.
+        /// 
+        internal static string END_DRAW {
+            get {
+                return ResourceManager.GetString("END_DRAW", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to TOUGH LUCK, YOU LOSE..
+        /// 
+        internal static string END_PLAYERLOSE {
+            get {
+                return ResourceManager.GetString("END_PLAYERLOSE", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to CONGRATULATIONS, YOU WIN..
+        /// 
+        internal static string END_PLAYERWIN {
+            get {
+                return ResourceManager.GetString("END_PLAYERWIN", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to BATNUM.
+        /// 
+        internal static string GAME_NAME {
+            get {
+                return ResourceManager.GetString("GAME_NAME", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to ILLEGAL MOVE, RENETER IT.
+        /// 
+        internal static string INPUT_ILLEGAL {
+            get {
+                return ResourceManager.GetString("INPUT_ILLEGAL", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to YOUR MOVE ?.
+        /// 
+        internal static string INPUT_TURN {
+            get {
+                return ResourceManager.GetString("INPUT_TURN", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT..
+        /// 
+        internal static string INPUT_ZERO {
+            get {
+                return ResourceManager.GetString("INPUT_ZERO", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to CREATIVE COMPUTING MORRISTOWN, NEW JERSEY.
+        /// 
+        internal static string INTRO_HEADER {
+            get {
+                return ResourceManager.GetString("INTRO_HEADER", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to THIS PROGRAM IS A 'BATTLE' OF NUMBERS GAME, WHERE THE COMPUTER IS YOUR OPPONENT.
+        /// 
+        internal static string INTRO_PART1 {
+            get {
+                return ResourceManager.GetString("INTRO_PART1", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE. WINNNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINING CONDITIONS. DON'T USER ZERO, HOWWEVER, IN PLAYING THE GAME..
+        /// 
+        internal static string INTRO_PART2 {
+            get {
+                return ResourceManager.GetString("INTRO_PART2", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to ENTER MIN AND MAX ?.
+        /// 
+        internal static string START_QUESTION_DRAWMINMAX {
+            get {
+                return ResourceManager.GetString("START_QUESTION_DRAWMINMAX", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to ENTER PILE SIZE ?.
+        /// 
+        internal static string START_QUESTION_PILESIZE {
+            get {
+                return ResourceManager.GetString("START_QUESTION_PILESIZE", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ?.
+        /// 
+        internal static string START_QUESTION_WHOSTARTS {
+            get {
+                return ResourceManager.GetString("START_QUESTION_WHOSTARTS", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?.
+        /// 
+        internal static string START_QUESTION_WINOPTION {
+            get {
+                return ResourceManager.GetString("START_QUESTION_WINOPTION", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/08 Batnum/csharp/Properties/Resources.en.resx b/08 Batnum/csharp/Properties/Resources.en.resx
new file mode 100644
index 00000000..746d8a12
--- /dev/null
+++ b/08 Batnum/csharp/Properties/Resources.en.resx	
@@ -0,0 +1,171 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    COMPUTER TAKES {0} AND  LEAVES {1}
+  
+  
+    COMPUTER TAKES {0} AND LOSES
+  
+  
+    COMPUTER TAKES {0} AND WINS
+  
+  
+    ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT
+  
+  
+    TOUGH LUCK, YOU LOSE.
+  
+  
+    CONGRATULATIONS, YOU WIN.
+  
+  
+    BATNUM
+  
+  
+    ILLEGAL MOVE, RENETER IT
+  
+  
+    YOUR MOVE ?
+  
+  
+    I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.
+  
+  
+    CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
+  
+  
+    THIS PROGRAM IS A 'BATTLE' OF NUMBERS GAME, WHERE THE COMPUTER IS YOUR OPPONENT
+  
+  
+    THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE. WINNNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINING CONDITIONS. DON'T USER ZERO, HOWWEVER, IN PLAYING THE GAME.
+  
+  
+    ENTER MIN AND MAX ?
+  
+  
+    ENTER PILE SIZE ?
+  
+  
+    ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ?
+  
+  
+    ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?
+  
+
\ No newline at end of file
diff --git a/08 Batnum/csharp/Properties/Resources.fr.resx b/08 Batnum/csharp/Properties/Resources.fr.resx
new file mode 100644
index 00000000..410562e2
--- /dev/null
+++ b/08 Batnum/csharp/Properties/Resources.fr.resx	
@@ -0,0 +1,171 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    L'ORDINATEUR PREND {0} ET LAISSE {1}
+  
+  
+    L'ORDINATEUR PREND {0} ET PERD
+  
+  
+    L'ORDINATEUR PREND {0} ET GAGNE
+  
+  
+    MATCH NUL, IL RESTE SEULEMENT {0} PIECES
+  
+  
+    PAS DE CHANCE. TU AS PERDU.
+  
+  
+    BRAVO! TU AS GAGNE
+  
+  
+    BATNUM
+  
+  
+    CE COUP EST INTERDIT. RE-ESSAIE
+  
+  
+    TON TOUR ?
+  
+  
+    JE TE DIS DE NE PAS UTILISER LE ZERO! L'ORDINATEUR GAGNE PAR DEFAUT.
+  
+  
+    CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
+  
+  
+    CE PROGRAMME EST UN JEU 'BATAILLE' DE NOMBRES, OU L'ORDINATEUR EST TON ADVERSAIRE
+  
+  
+    LE JEU COMMENCE AVEC UNE NOMBRE D'OBJETS DEFINI. TOI ET TON ADVERSAIRE ENLEVEZ EN ALTERNANCE UN NOMBRE D'OBJETS. LES CONDITIONS DE VICTOIRE SON DÉFINIES À L'AVANCE COMME PRENDRE OU NE PAS PRENDRE LE DERNIER OBJET. VOUS POUVEZ ÉGALEMENT PRÉCISER D'AUTRES CONDITIONS DES LE DÉBUT. TOUTEFOIS, N'UTILISEZ PAS LE CHIFFRE ZERO.
+  
+  
+    ENTRE LE MINIMUM ET MAXIMUM D'OBJETS A RETIRER POUR CHAQUE TOUR ?
+  
+  
+    ENTRE LE NOMBRE D'OBJETS ?
+  
+  
+    ENTRE QUI COMMENCE - 1 L'ORDINATEUR, 2 TOI ?
+  
+  
+    ENTRE LA CONDITION DE VICTOIRE - 1 PRENDRE LA DERNIERE PIECE, 2 EVITER LA DERNIERE PIECE ?
+  
+
\ No newline at end of file
diff --git a/08 Batnum/csharp/Properties/Resources.resx b/08 Batnum/csharp/Properties/Resources.resx
new file mode 100644
index 00000000..746d8a12
--- /dev/null
+++ b/08 Batnum/csharp/Properties/Resources.resx	
@@ -0,0 +1,171 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    COMPUTER TAKES {0} AND  LEAVES {1}
+  
+  
+    COMPUTER TAKES {0} AND LOSES
+  
+  
+    COMPUTER TAKES {0} AND WINS
+  
+  
+    ITS A DRAW, THERE ARE ONLY {0} PIECES LEFT
+  
+  
+    TOUGH LUCK, YOU LOSE.
+  
+  
+    CONGRATULATIONS, YOU WIN.
+  
+  
+    BATNUM
+  
+  
+    ILLEGAL MOVE, RENETER IT
+  
+  
+    YOUR MOVE ?
+  
+  
+    I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.
+  
+  
+    CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
+  
+  
+    THIS PROGRAM IS A 'BATTLE' OF NUMBERS GAME, WHERE THE COMPUTER IS YOUR OPPONENT
+  
+  
+    THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE. WINNNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINING CONDITIONS. DON'T USER ZERO, HOWWEVER, IN PLAYING THE GAME.
+  
+  
+    ENTER MIN AND MAX ?
+  
+  
+    ENTER PILE SIZE ?
+  
+  
+    ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ?
+  
+  
+    ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ?
+  
+
\ No newline at end of file
diff --git a/08 Batnum/csharp/README.md b/08 Batnum/csharp/README.md
index 4daabb5c..cd054abd 100644
--- a/08 Batnum/csharp/README.md	
+++ b/08 Batnum/csharp/README.md	
@@ -1,3 +1,11 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
 Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/)
+
+This conversion uses C#9 and is built for .net 5.0
+
+Functional changes from Original
+- handle edge condition for end game where the minimum draw amount is greater than the number of items remaining in the pile
+- Takes into account the width of the console
+- Mulilingual Support (English/French currently)
+

From 8fdbf0470ac5b4efd49da0517dd09c94f702714e Mon Sep 17 00:00:00 2001
From: Darren Jones 
Date: Sat, 27 Feb 2021 12:27:26 +0000
Subject: [PATCH 038/749] Added python version of MATHDICE

---
 61 Math Dice/python/mathdice.py | 79 +++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)
 create mode 100644 61 Math Dice/python/mathdice.py

diff --git a/61 Math Dice/python/mathdice.py b/61 Math Dice/python/mathdice.py
new file mode 100644
index 00000000..ca84555c
--- /dev/null
+++ b/61 Math Dice/python/mathdice.py	
@@ -0,0 +1,79 @@
+from random import randint
+print("Math Dice")
+print("https://github.com/coding-horror/basic-computer-games")
+print()
+print("""This program generates images of two dice.
+When two dice and an equals sign followed by a question
+mark have been printed, type your answer, and hit the ENTER
+key.
+To conclude the program, type 0.
+""")
+
+def print_dice(n):
+    
+    def print_0():
+        print("|     |")
+    def print_2():
+        print("| * * |")
+
+    print(" ----- ")
+
+    if n in [4,5,6]:
+        print_2()
+    elif n in [2,3]:
+        print("| *   |")
+    else:
+        print_0()
+
+    if n in [1,3,5]:
+        print("|  *  |")
+    elif n in [2,4]:
+        print_0()
+    else:
+        print_2()
+
+    if n in [4,5,6]:
+        print_2()
+    elif n in [2,3]:
+        print("|   * |")
+    else:
+        print_0()
+
+    print(" ----- ")
+
+def main():
+
+    while True:
+        d1 = randint(1,6)
+        d2 = randint(1,6)
+        guess = 13
+
+        print_dice(d1)
+        print("   +")
+        print_dice(d2)
+        print("   =")
+
+        tries = 0
+        while guess != (d1 + d2) and tries < 2:
+            if tries == 1:
+                print("No, count the spots and give another answer.")
+            try:
+                guess = int(input())
+            except ValueError:
+                print("That's not a number!")
+            if guess == 0:
+                exit()
+            tries += 1
+
+        if guess != (d1 + d2):
+            print(f"No, the answer is {d1 + d2}!")
+        else:
+            print("Correct!")
+
+
+        print("The dice roll again....")
+
+
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file

From 7ab928afb8675129851f505455cbfd01e6ae7488 Mon Sep 17 00:00:00 2001
From: Adam Jones 
Date: Sat, 27 Feb 2021 13:36:04 +0100
Subject: [PATCH 039/749] fix spacing

---
 08 Batnum/csharp/Properties/Resources.Designer.cs | 2 +-
 08 Batnum/csharp/Properties/Resources.en.resx     | 2 +-
 08 Batnum/csharp/Properties/Resources.resx        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/08 Batnum/csharp/Properties/Resources.Designer.cs b/08 Batnum/csharp/Properties/Resources.Designer.cs
index b0cc5dd9..2c2fac7f 100644
--- a/08 Batnum/csharp/Properties/Resources.Designer.cs	
+++ b/08 Batnum/csharp/Properties/Resources.Designer.cs	
@@ -61,7 +61,7 @@ namespace Batnum.Properties {
         }
         
         /// 
-        ///   Looks up a localized string similar to COMPUTER TAKES {0} AND  LEAVES {1}.
+        ///   Looks up a localized string similar to COMPUTER TAKES {0} AND LEAVES {1}.
         /// 
         internal static string COMPTURN {
             get {
diff --git a/08 Batnum/csharp/Properties/Resources.en.resx b/08 Batnum/csharp/Properties/Resources.en.resx
index 746d8a12..beed709a 100644
--- a/08 Batnum/csharp/Properties/Resources.en.resx	
+++ b/08 Batnum/csharp/Properties/Resources.en.resx	
@@ -118,7 +118,7 @@
     System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   
   
-    COMPUTER TAKES {0} AND  LEAVES {1}
+    COMPUTER TAKES {0} AND LEAVES {1}
   
   
     COMPUTER TAKES {0} AND LOSES
diff --git a/08 Batnum/csharp/Properties/Resources.resx b/08 Batnum/csharp/Properties/Resources.resx
index 746d8a12..beed709a 100644
--- a/08 Batnum/csharp/Properties/Resources.resx	
+++ b/08 Batnum/csharp/Properties/Resources.resx	
@@ -118,7 +118,7 @@
     System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   
   
-    COMPUTER TAKES {0} AND  LEAVES {1}
+    COMPUTER TAKES {0} AND LEAVES {1}
   
   
     COMPUTER TAKES {0} AND LOSES

From 004e73d414e41d02a654bbdc8f9844fe155c8600 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sat, 27 Feb 2021 11:52:11 -0800
Subject: [PATCH 040/749] Ported Weekday to Python

used the BASIC algorithms, mostly, made variable names more descriptive. Includes test harness.
---
 95 Weekday/weekday.py | 288 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 288 insertions(+)
 create mode 100644 95 Weekday/weekday.py

diff --git a/95 Weekday/weekday.py b/95 Weekday/weekday.py
new file mode 100644
index 00000000..29750279
--- /dev/null
+++ b/95 Weekday/weekday.py	
@@ -0,0 +1,288 @@
+"""
+WEEKDAY
+
+Calculates which weekday an entered date is.
+
+Also estimates how long a person has done certain activities, if they
+entered their birthday.
+
+Also calculates the year of retirement, assuming retiring at age 65.
+
+Ported by Dave LeCompte.
+"""
+
+import datetime
+
+GET_TODAY_FROM_SYSTEM = True
+
+
+def print_with_tab(space_count, s):
+    if space_count > 0:
+        spaces = " " * space_count
+    else:
+        spaces = ""
+    print(spaces + s)
+
+
+def get_date_from_user(prompt):
+    while True:
+        print(prompt)
+        date_str = input()
+        try:
+            month_num, day_num, year_num = [int(x) for x in date_str.split(",")]
+        except Exception as e:
+            print("I COULDN'T UNDERSTAND THAT. TRY AGAIN.")
+        return month_num, day_num, year_num
+
+
+def get_date_from_system():
+    dt = datetime.datetime.today()
+    return dt.month, dt.day, dt.year
+
+
+def get_day_of_week(weekday_index, day):
+    day_names = {
+        1: "SUNDAY",
+        2: "MONDAY",
+        3: "TUESDAY",
+        4: "WEDNESDAY",
+        5: "THURSDAY",
+        6: "FRIDAY",
+        7: "SATURDAY",
+    }
+
+    if weekday_index == 6 and day == 13:
+        return "FRIDAY THE THIRTEENTH---BEWARE!"
+    return day_names[weekday_index]
+
+
+def previous_day(b):
+    if b == 0:
+        b = 6
+    return b - 1
+
+
+def is_leap_year(year):
+    if (year % 4) != 0:
+        return False
+    if (year % 100) != 0:
+        return True
+    if (year % 400) != 0:
+        return False
+    return True
+
+
+def adjust_day_for_leap_year(b, year):
+    if is_leap_year(year):
+        b = previous_day(b)
+    return b
+
+
+def adjust_weekday(b, month, year):
+    if month <= 2:
+        b = adjust_day_for_leap_year(b, year)
+    if b == 0:
+        b = 7
+    return b
+
+
+def calc_day_value(year, month, day):
+    return (year * 12 + month) * 31 + day
+
+
+def deduct_time(frac, days, years_remain, months_remain, days_remain):
+    # CALCULATE TIME IN YEARS, MONTHS, AND DAYS
+    days_available = int(frac * days)
+    years_used = int(days_available / 365)
+    days_available -= years_used * 365
+    months_used = int(days_available / 30)
+    days_used = days_available - (months_used * 30)
+    years_remain = years_remain - years_used
+    months_remain = months_remain - months_used
+    days_remain = days_remain - days_used
+
+    while days_remain < 0:
+        days_remain += 30
+        months_remain -= 1
+
+    while months_remain < 0 and years_remain > 0:
+        months_remain += 12
+        years_remain -= 1
+    return years_remain, months_remain, days_remain, years_used, months_used, days_used
+
+
+def time_report(msg, years, months, days):
+    leading_spaces = 23 - len(msg)
+    print_with_tab(leading_spaces, msg + f"\t{years}\t{months}\t{days}")
+
+
+def make_occupation_label(years):
+    if years <= 3:
+        return "PLAYED"
+    elif years <= 9:
+        return "PLAYED/STUDIED"
+    else:
+        return "WORKED/PLAYED"
+
+
+def calculate_day_of_week(year, month, day):
+    # Initial values for months
+    month_table = [0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5]
+
+    i1 = int((year - 1500) / 100)
+    a = i1 * 5 + (i1 + 3) / 4
+    i2 = int(a - int(a / 7) * 7)
+    y2 = int(year / 100)
+    y3 = int(year - y2 * 100)
+    a = y3 / 4 + y3 + day + month_table[month - 1] + i2
+    b = int(a - int(a / 7) * 7) + 1
+    b = adjust_weekday(b, month, year)
+
+    return b
+
+
+def end():
+    for i in range(5):
+        print()
+
+
+def main():
+    print_with_tab(32, "WEEKDAY")
+    print_with_tab(15, "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+    print("WEEKDAY IS A COMPUTER DEMONSTRATION THAT")
+    print("GIVES FACTS ABOUT A DATE OF INTEREST TO YOU.")
+    print()
+
+    if GET_TODAY_FROM_SYSTEM:
+        month_today, day_today, year_today = get_date_from_system()
+    else:
+        month_today, day_today, year_today = get_date_from_user(
+            "ENTER TODAY'S DATE IN THE FORM: 3,24,1979"
+        )
+
+    # This program determines the day of the week
+    # for a date after 1582
+
+    print()
+
+    month, day, year = get_date_from_user(
+        "ENTER DAY OF BIRTH (OR OTHER DAY OF INTEREST) (like MM,DD,YYYY)"
+    )
+
+    print()
+
+    # Test for date before current calendar
+    if year < 1582:
+        print("NOT PREPARED TO GIVE DAY OF WEEK PRIOR TO MDLXXXII.")
+        end()
+        return
+
+    b = calculate_day_of_week(year, month, day)
+
+    today_day_value = calc_day_value(year_today, month_today, day_today)
+    target_day_value = calc_day_value(year, month, day)
+
+    is_today = False
+    is_future = False
+
+    if today_day_value < target_day_value:
+        label = "WILL BE A"
+        is_future = False
+    elif today_day_value == target_day_value:
+        label = "IS A"
+        is_today = True
+    else:
+        label = "WAS A"
+
+    day_name = get_day_of_week(b, day)
+
+    # print the day of the week the date falls on.
+    print(f"{month}/{day}/{year} {label} {day_name}.")
+
+    if is_today:
+        # nothing to report for today
+        end()
+        return
+
+    print()
+
+    el_years = year_today - year
+    el_months = month_today - month
+    el_days = day_today - day
+
+    if el_days < 0:
+        el_months = el_months - 1
+        el_days = el_days + 30
+    if el_months < 0:
+        el_years = el_years - 1
+        el_months = el_months + 12
+    if el_years < 0:
+        # target date is in the future
+        end()
+        return
+
+    if (el_months == 0) and (el_days == 0):
+        print("***HAPPY BIRTHDAY***")
+
+    # print report
+    print_with_tab(23, "\tYEARS\tMONTHS\tDAYS")
+    print_with_tab(23, "\t-----\t------\t----")
+    print(f"YOUR AGE (IF BIRTHDATE)\t{el_years}\t{el_months}\t{el_days}")
+
+    life_days = (el_years * 365) + (el_months * 30) + el_days + int(el_months / 2)
+    rem_years = el_years
+    rem_months = el_months
+    rem_days = el_days
+
+    rem_years, rem_months, rem_days, used_years, used_months, used_days = deduct_time(
+        0.35, life_days, rem_years, rem_months, rem_days
+    )
+    time_report("YOU HAVE SLEPT", used_years, used_months, used_days)
+    rem_years, rem_months, rem_days, used_years, used_months, used_days = deduct_time(
+        0.17, life_days, rem_years, rem_months, rem_days
+    )
+    time_report("YOU HAVE EATEN", used_years, used_months, used_days)
+
+    label = make_occupation_label(rem_years)
+    rem_years, rem_months, rem_days, used_years, used_months, used_days = deduct_time(
+        0.23, life_days, rem_years, rem_months, rem_days
+    )
+    time_report("YOU HAVE " + label, used_years, used_months, used_days)
+    time_report("YOU HAVE RELAXED", rem_years, rem_months, rem_days)
+
+    print()
+
+    # Calculate retirement date
+    e = year + 65
+    print_with_tab(16, f"***  YOU MAY RETIRE IN {e} ***")
+    end()
+
+
+def test_weekday_calc(year, month, day):
+    dt = datetime.date(year, month, day)
+    python_weekday = dt.weekday()  # Monday = 0, Sunday = 6
+
+    basic_weekday = calculate_day_of_week(year, month, day)  # Sunday = 1, Saturday = 7
+
+    test = ((python_weekday + 2) % 7) == (basic_weekday % 7)
+    if test == False:
+        print(f"testing yr {year} month {month} day {day}")
+        print(f"python says {python_weekday}")
+        print(f"BASIC says {basic_weekday}")
+        assert False
+
+
+def test_harness():
+    for yr in range(1600, 2021):
+        for m in range(1, 12):
+            for d in range(1, 28):
+                test_weekday_calc(yr, m, d)
+
+
+if __name__ == "__main__":
+    main()
+
+    # test_harness()

From ac5636b7a55bc987c228303b8c4c815629a29aa3 Mon Sep 17 00:00:00 2001
From: Darren Jones 
Date: Sat, 27 Feb 2021 19:52:39 +0000
Subject: [PATCH 041/749] Add Python version of MUGWUMP

---
 62 Mugwump/python/mugwump.py | 80 ++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
 create mode 100644 62 Mugwump/python/mugwump.py

diff --git a/62 Mugwump/python/mugwump.py b/62 Mugwump/python/mugwump.py
new file mode 100644
index 00000000..fdcc2945
--- /dev/null
+++ b/62 Mugwump/python/mugwump.py	
@@ -0,0 +1,80 @@
+from math import sqrt
+from random import randint
+
+
+def introduction():
+    print(
+        """The object of this game is to find 4 mugwumps
+hidden on a 10*10 grid.  Homebase is position 0,0.
+Any guess you make must be two numbers with each 
+number between 0 and 9 inclusive.  First number
+is distance to right of homebase, and second number
+is the distance above homebase."""
+    )
+
+    print(
+        """You get 10 tries.  After each try, I will tell
+you how far you are from each mugwump."""
+    )
+
+
+def generate_mugwumps(n=4):
+    mugwumps = []
+    for _ in range(n):
+        current = [randint(0, 9), randint(0, 9)]
+        mugwumps.append(current)
+    return mugwumps
+
+
+def reveal_mugwumps(mugwumps):
+    print("Sorry, that's 10 tries.  Here's where they're hiding.")
+    for idx, mugwump in enumerate(mugwumps, 1):
+        if mugwump[0] != -1:
+            print(f"Mugwump {idx} is at {mugwump[0]},{mugwump[1]}")
+
+
+def calculate_distance(guess, mugwump):
+    d = sqrt(((mugwump[0] - guess[0]) ** 2) + ((mugwump[1] - guess[1]) ** 2))
+    return d
+
+def play_again():
+    print("THAT WAS FUN! LET'S PLAY AGAIN.......")
+    choice = input("Press Enter to play again, any other key then Enter to quit.")
+    if choice == "":
+        print("Four more mugwumps are now in hiding.")
+    else:
+        exit()
+
+def play_round():
+    mugwumps = generate_mugwumps()
+    turns = 1
+    score = 0
+    while turns <= 10 and score != 4:
+        m = -1
+        while m == -1:
+            try:
+                m, n = map(int, input(f"Turn {turns} - what is your guess? ").split())
+            except ValueError:
+                m = -1
+        for idx, mugwump in enumerate(mugwumps):
+            if m == mugwump[0] and n == mugwump[1]:
+                print(f"You found mugwump {idx + 1}")
+                mugwumps[idx][0] = -1
+                score += 1
+            if mugwump[0] == -1:
+                continue
+            print(
+                f"You are {calculate_distance((m, n), mugwump):.1f} units from mugwump {idx + 1}"
+            )
+        turns += 1
+    if score == 4:
+        print(f"Well done! You got them all in {turns} turns.")
+    else:
+        reveal_mugwumps(mugwumps)
+
+
+if __name__ == "__main__":
+    introduction()
+    while True:
+        play_round()
+        play_again()

From 339c83da140bd4e180a83d0b3271d98df2334a64 Mon Sep 17 00:00:00 2001
From: Jeff Atwood 
Date: Sat, 27 Feb 2021 12:57:24 -0800
Subject: [PATCH 042/749] Update README.md

---
 README.md | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 73ed7027..fb0cf13d 100644
--- a/README.md
+++ b/README.md
@@ -12,14 +12,16 @@ I have moved all [the original BASIC source code](http://www.vintage-basic.net/g
 
 > I've included all the games here for your tinkering pleasure. I've tested and tweaked each one of them to make sure they'll run with Vintage BASIC, though you may see a few oddities. That's part of the fun of playing with BASIC: it never works quite the same on two machines. The games will play better if you keep CAPS LOCK on, as they were designed to be used with capital-letter input.
 
-Each project has subfolders corresponding to the languages we'd like to see the games ported to:
+Each project has subfolders corresponding to the languages we'd like to see the games ported to. This is based on the [February 2021 TIOBE index of top languages](https://www.tiobe.com/tiobe-index/) that are _memory safe_ and _general purpose scripting language_ per [this post](https://discourse.codinghorror.com/t/updating-101-basic-computer-games-for-2021/7927/34)
 
-- C#
 - Java
-- JavaScript
 - Python
-- Ruby
+- C#
 - VB.NET
+- JavaScript
+- Ruby
+- Delphi / Object Pascal
+- Perl
 
 ### Project goals
 
@@ -31,8 +33,10 @@ Feel free to begin converting these classic games into the above list of modern,
 
 - **Please DO update for modern coding conventions**. Support uppercase and lowercase. Use structured programming. Use subroutines. Try to be an example of good, modern coding practices!
 
+- **Use lots of comments to explain what is going on**. Comment liberally! If there were clever tricks in the original code, decompose those tricks into simpler (even if more verbose) code, and use comments to explain what's happening and why.
+
 - **Don't get _too_ fancy**. Definitely use the most recent versions and features of the target language, but also try to keep the code samples simple and explainable -- the goal is to teach programming in the target language, not necessarily demonstrate the cleverest one-line tricks.
 
 ### Have fun!
 
-Thank you for taking part in this project to update a classic programming book -- maybe the most influential programming book in computing history -- for 2021!
\ No newline at end of file
+Thank you for taking part in this project to update a classic programming book -- one of the most influential programming books in computing history -- for 2021!

From 6a0086d2dda3edacbbcceb53604b6adce6848be9 Mon Sep 17 00:00:00 2001
From: Jeff Atwood 
Date: Sat, 27 Feb 2021 12:57:44 -0800
Subject: [PATCH 043/749] Update README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index fb0cf13d..6b368c4b 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ I have moved all [the original BASIC source code](http://www.vintage-basic.net/g
 
 > I've included all the games here for your tinkering pleasure. I've tested and tweaked each one of them to make sure they'll run with Vintage BASIC, though you may see a few oddities. That's part of the fun of playing with BASIC: it never works quite the same on two machines. The games will play better if you keep CAPS LOCK on, as they were designed to be used with capital-letter input.
 
-Each project has subfolders corresponding to the languages we'd like to see the games ported to. This is based on the [February 2021 TIOBE index of top languages](https://www.tiobe.com/tiobe-index/) that are _memory safe_ and _general purpose scripting language_ per [this post](https://discourse.codinghorror.com/t/updating-101-basic-computer-games-for-2021/7927/34)
+Each project has subfolders corresponding to the languages we'd like to see the games ported to. This is based on the [February 2021 TIOBE index of top languages](https://www.tiobe.com/tiobe-index/) that are _memory safe_ and _general purpose scripting language_ per [this post](https://discourse.codinghorror.com/t/updating-101-basic-computer-games-for-2021/7927/34):
 
 - Java
 - Python

From 9504391a9da882eb97aa6b65aa6097d3fdced6b9 Mon Sep 17 00:00:00 2001
From: Jeff Atwood 
Date: Sat, 27 Feb 2021 13:17:04 -0800
Subject: [PATCH 044/749] remove Raku port per new guidelines

feel free to link this port via the readme.md in the program's root folder!
---
 01 Acey Ducey/raku/README.md | 3 ---
 1 file changed, 3 deletions(-)
 delete mode 100644 01 Acey Ducey/raku/README.md

diff --git a/01 Acey Ducey/raku/README.md b/01 Acey Ducey/raku/README.md
deleted file mode 100644
index 47ef380b..00000000
--- a/01 Acey Ducey/raku/README.md	
+++ /dev/null
@@ -1,3 +0,0 @@
-Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
-
-Conversion to [Raku](https://raku.org/)

From 18963ea719d342be4de758c7618a9d538ca94cdb Mon Sep 17 00:00:00 2001
From: Jeff Atwood 
Date: Sat, 27 Feb 2021 13:33:14 -0800
Subject: [PATCH 045/749] add pascal and perl folders for all programs

---
 01 Acey Ducey/pascal/README.md                |  3 +
 01 Acey Ducey/perl/README.md                  |  3 +
 02 Amazing/pascal/README.md                   |  3 +
 02 Amazing/perl/README.md                     |  3 +
 03 Animal/pascal/README.md                    |  3 +
 03 Animal/perl/README.md                      |  3 +
 04 Awari/pascal/README.md                     |  3 +
 04 Awari/perl/README.md                       |  3 +
 05 Bagels/pascal/README.md                    |  3 +
 05 Bagels/perl/README.md                      |  3 +
 06 Banner/pascal/README.md                    |  3 +
 06 Banner/perl/README.md                      |  3 +
 07 Basketball/pascal/README.md                |  3 +
 07 Basketball/perl/README.md                  |  3 +
 08 Batnum/pascal/README.md                    |  3 +
 08 Batnum/perl/README.md                      |  3 +
 09 Battle/pascal/README.md                    |  3 +
 09 Battle/perl/README.md                      |  3 +
 10 Blackjack/pascal/README.md                 |  3 +
 10 Blackjack/perl/README.md                   |  3 +
 11 Bombardment/pascal/README.md               |  3 +
 11 Bombardment/perl/README.md                 |  3 +
 12 Bombs Away/pascal/README.md                |  3 +
 12 Bombs Away/perl/README.md                  |  3 +
 13 Bounce/pascal/README.md                    |  3 +
 13 Bounce/perl/README.md                      |  3 +
 14 Bowling/pascal/README.md                   |  3 +
 14 Bowling/perl/README.md                     |  3 +
 15 Boxing/pascal/README.md                    |  3 +
 15 Boxing/perl/README.md                      |  3 +
 16 Bug/pascal/README.md                       |  3 +
 16 Bug/perl/README.md                         |  3 +
 17 Bullfight/pascal/README.md                 |  3 +
 17 Bullfight/perl/README.md                   |  3 +
 18 Bullseye/pascal/README.md                  |  3 +
 18 Bullseye/perl/README.md                    |  3 +
 19 Bunny/pascal/README.md                     |  3 +
 19 Bunny/perl/README.md                       |  3 +
 20 Buzzword/pascal/README.md                  |  3 +
 20 Buzzword/perl/README.md                    |  3 +
 21 Calendar/pascal/README.md                  |  3 +
 21 Calendar/perl/README.md                    |  3 +
 22 Change/pascal/README.md                    |  3 +
 22 Change/perl/README.md                      |  3 +
 23 Checkers/pascal/README.md                  |  3 +
 23 Checkers/perl/README.md                    |  3 +
 24 Chemist/pascal/README.md                   |  3 +
 24 Chemist/perl/README.md                     |  3 +
 25 Chief/pascal/README.md                     |  3 +
 25 Chief/perl/README.md                       |  3 +
 26 Chomp/pascal/README.md                     |  3 +
 26 Chomp/perl/README.md                       |  3 +
 27 Civil War/pascal/README.md                 |  3 +
 27 Civil War/perl/README.md                   |  3 +
 28 Combat/pascal/README.md                    |  3 +
 28 Combat/perl/README.md                      |  3 +
 29 Craps/pascal/README.md                     |  3 +
 29 Craps/perl/README.md                       |  3 +
 30 Cube/pascal/README.md                      |  3 +
 30 Cube/perl/README.md                        |  3 +
 31 Depth Charge/pascal/README.md              |  3 +
 32 Diamond/pascal/README.md                   |  3 +
 32 Diamond/perl/README.md                     |  3 +
 33 Dice/pascal/README.md                      |  3 +
 33 Dice/perl/README.md                        |  3 +
 34 Digits/pascal/README.md                    |  3 +
 34 Digits/perl/README.md                      |  3 +
 35 Even Wins/pascal/README.md                 |  3 +
 35 Even Wins/perl/README.md                   |  3 +
 36 Flip Flop/pascal/README.md                 |  3 +
 36 Flip Flop/perl/README.md                   |  3 +
 37 Football/pascal/README.md                  |  3 +
 37 Football/perl/README.md                    |  3 +
 38 Fur Trader/pascal/README.md                |  3 +
 38 Fur Trader/perl/README.md                  |  3 +
 39 Golf/pascal/README.md                      |  3 +
 39 Golf/perl/README.md                        |  3 +
 40 Gomoko/pascal/README.md                    |  3 +
 40 Gomoko/perl/README.md                      |  3 +
 41 Guess/pascal/README.md                     |  3 +
 41 Guess/perl/README.md                       |  3 +
 42 Gunner/pascal/README.md                    |  3 +
 42 Gunner/perl/README.md                      |  3 +
 43 Hammurabi/pascal/README.md                 |  3 +
 43 Hammurabi/perl/README.md                   |  3 +
 44 Hangman/pascal/README.md                   |  3 +
 44 Hangman/perl/README.md                     |  3 +
 45 Hello/pascal/README.md                     |  3 +
 45 Hello/perl/README.md                       |  3 +
 46 Hexapawn/pascal/README.md                  |  3 +
 46 Hexapawn/perl/README.md                    |  3 +
 47 Hi-Lo/pascal/README.md                     |  3 +
 47 Hi-Lo/perl/README.md                       |  3 +
 48 High IQ/pascal/README.md                   |  3 +
 48 High IQ/perl/README.md                     |  3 +
 49 Hockey/pascal/README.md                    |  3 +
 49 Hockey/perl/README.md                      |  3 +
 50 Horserace/pascal/README.md                 |  3 +
 50 Horserace/perl/README.md                   |  3 +
 51 Hurkle/pascal/README.md                    |  3 +
 51 Hurkle/perl/README.md                      |  3 +
 52 Kinema/pascal/README.md                    |  3 +
 52 Kinema/perl/README.md                      |  3 +
 53 King/pascal/README.md                      |  3 +
 53 King/perl/README.md                        |  3 +
 54 Letter/pascal/README.md                    |  3 +
 54 Letter/perl/README.md                      |  3 +
 55 Life/pascal/README.md                      |  3 +
 55 Life/perl/README.md                        |  3 +
 56 Life for Two/pascal/README.md              |  3 +
 56 Life for Two/perl/README.md                |  3 +
 57 Literature Quiz/pascal/README.md           |  3 +
 57 Literature Quiz/perl/README.md             |  3 +
 58 Love/pascal/README.md                      |  3 +
 58 Love/perl/README.md                        |  3 +
 59 Lunar LEM Rocket/pascal/README.md          |  3 +
 59 Lunar LEM Rocket/perl/README.md            |  3 +
 60 Mastermind/pascal/README.md                |  3 +
 60 Mastermind/perl/README.md                  |  3 +
 61 Math Dice/pascal/README.md                 |  3 +
 61 Math Dice/perl/README.md                   |  3 +
 62 Mugwump/pascal/README.md                   |  3 +
 62 Mugwump/perl/README.md                     |  3 +
 63 Name/pascal/README.md                      |  3 +
 63 Name/perl/README.md                        |  3 +
 64 Nicomachus/pascal/README.md                |  3 +
 64 Nicomachus/perl/README.md                  |  3 +
 65 Nim/pascal/README.md                       |  3 +
 65 Nim/perl/README.md                         |  3 +
 66 Number/pascal/README.md                    |  3 +
 66 Number/perl/README.md                      |  3 +
 67 One Check/pascal/README.md                 |  3 +
 67 One Check/perl/README.md                   |  3 +
 68 Orbit/pascal/README.md                     |  3 +
 68 Orbit/perl/README.md                       |  3 +
 69 Pizza/pascal/README.md                     |  3 +
 69 Pizza/perl/README.md                       |  3 +
 70 Poetry/pascal/README.md                    |  3 +
 70 Poetry/perl/README.md                      |  3 +
 71 Poker/pascal/README.md                     |  3 +
 71 Poker/perl/README.md                       |  3 +
 72 Queen/pascal/README.md                     |  3 +
 72 Queen/perl/README.md                       |  3 +
 73 Reverse/pascal/README.md                   |  3 +
 73 Reverse/perl/README.md                     |  3 +
 74 Rock Scissors Paper/pascal/README.md       |  3 +
 74 Rock Scissors Paper/perl/README.md         |  3 +
 75 Roulette/pascal/README.md                  |  3 +
 75 Roulette/perl/README.md                    |  3 +
 76 Russian Roulette/pascal/README.md          |  3 +
 76 Russian Roulette/perl/README.md            |  3 +
 77 Salvo/pascal/README.md                     |  3 +
 77 Salvo/perl/README.md                       |  3 +
 78 Sine Wave/pascal/README.md                 |  3 +
 78 Sine Wave/perl/README.md                   |  3 +
 79 Slalom/pascal/README.md                    |  3 +
 79 Slalom/perl/README.md                      |  3 +
 80 Slots/pascal/README.md                     |  3 +
 80 Slots/perl/README.md                       |  3 +
 81 Splat/pascal/README.md                     |  3 +
 81 Splat/perl/README.md                       |  3 +
 82 Stars/pascal/README.md                     |  3 +
 82 Stars/perl/README.md                       |  3 +
 83 Stock Market/pascal/README.md              |  3 +
 83 Stock Market/perl/README.md                |  3 +
 84 Super Star Trek/pascal/README.md           |  3 +
 84 Super Star Trek/perl/README.md             |  3 +
 85 Synonym/pascal/README.md                   |  3 +
 85 Synonym/perl/README.md                     |  3 +
 86 Target/pascal/README.md                    |  3 +
 86 Target/perl/README.md                      |  3 +
 87 3-D Plot/pascal/README.md                  |  3 +
 87 3-D Plot/perl/README.md                    |  3 +
 88 3-D Tic-Tac-Toe/pascal/README.md           |  3 +
 88 3-D Tic-Tac-Toe/perl/README.md             |  3 +
 89 Tic-Tac-Toe/pascal/README.md               |  3 +
 89 Tic-Tac-Toe/perl/README.md                 |  3 +
 90 Tower/pascal/README.md                     |  3 +
 90 Tower/perl/README.md                       |  3 +
 91 Train/pascal/README.md                     |  3 +
 91 Train/perl/README.md                       |  3 +
 92 Trap/pascal/README.md                      |  3 +
 92 Trap/perl/README.md                        |  3 +
 93 23 Matches/pascal/README.md                |  3 +
 93 23 Matches/perl/README.md                  |  3 +
 94 War/pascal/README.md                       |  3 +
 94 War/perl/README.md                         |  3 +
 95 Weekday/pascal/README.md                   |  3 +
 95 Weekday/perl/README.md                     |  3 +
 96 Word/pascal/README.md                      |  3 +
 96 Word/perl/README.md                        |  3 +
 .../basic-computer-games-dot-net.sln          | 69 -------------------
 192 files changed, 573 insertions(+), 69 deletions(-)
 create mode 100644 01 Acey Ducey/pascal/README.md
 create mode 100644 01 Acey Ducey/perl/README.md
 create mode 100644 02 Amazing/pascal/README.md
 create mode 100644 02 Amazing/perl/README.md
 create mode 100644 03 Animal/pascal/README.md
 create mode 100644 03 Animal/perl/README.md
 create mode 100644 04 Awari/pascal/README.md
 create mode 100644 04 Awari/perl/README.md
 create mode 100644 05 Bagels/pascal/README.md
 create mode 100644 05 Bagels/perl/README.md
 create mode 100644 06 Banner/pascal/README.md
 create mode 100644 06 Banner/perl/README.md
 create mode 100644 07 Basketball/pascal/README.md
 create mode 100644 07 Basketball/perl/README.md
 create mode 100644 08 Batnum/pascal/README.md
 create mode 100644 08 Batnum/perl/README.md
 create mode 100644 09 Battle/pascal/README.md
 create mode 100644 09 Battle/perl/README.md
 create mode 100644 10 Blackjack/pascal/README.md
 create mode 100644 10 Blackjack/perl/README.md
 create mode 100644 11 Bombardment/pascal/README.md
 create mode 100644 11 Bombardment/perl/README.md
 create mode 100644 12 Bombs Away/pascal/README.md
 create mode 100644 12 Bombs Away/perl/README.md
 create mode 100644 13 Bounce/pascal/README.md
 create mode 100644 13 Bounce/perl/README.md
 create mode 100644 14 Bowling/pascal/README.md
 create mode 100644 14 Bowling/perl/README.md
 create mode 100644 15 Boxing/pascal/README.md
 create mode 100644 15 Boxing/perl/README.md
 create mode 100644 16 Bug/pascal/README.md
 create mode 100644 16 Bug/perl/README.md
 create mode 100644 17 Bullfight/pascal/README.md
 create mode 100644 17 Bullfight/perl/README.md
 create mode 100644 18 Bullseye/pascal/README.md
 create mode 100644 18 Bullseye/perl/README.md
 create mode 100644 19 Bunny/pascal/README.md
 create mode 100644 19 Bunny/perl/README.md
 create mode 100644 20 Buzzword/pascal/README.md
 create mode 100644 20 Buzzword/perl/README.md
 create mode 100644 21 Calendar/pascal/README.md
 create mode 100644 21 Calendar/perl/README.md
 create mode 100644 22 Change/pascal/README.md
 create mode 100644 22 Change/perl/README.md
 create mode 100644 23 Checkers/pascal/README.md
 create mode 100644 23 Checkers/perl/README.md
 create mode 100644 24 Chemist/pascal/README.md
 create mode 100644 24 Chemist/perl/README.md
 create mode 100644 25 Chief/pascal/README.md
 create mode 100644 25 Chief/perl/README.md
 create mode 100644 26 Chomp/pascal/README.md
 create mode 100644 26 Chomp/perl/README.md
 create mode 100644 27 Civil War/pascal/README.md
 create mode 100644 27 Civil War/perl/README.md
 create mode 100644 28 Combat/pascal/README.md
 create mode 100644 28 Combat/perl/README.md
 create mode 100644 29 Craps/pascal/README.md
 create mode 100644 29 Craps/perl/README.md
 create mode 100644 30 Cube/pascal/README.md
 create mode 100644 30 Cube/perl/README.md
 create mode 100644 31 Depth Charge/pascal/README.md
 create mode 100644 32 Diamond/pascal/README.md
 create mode 100644 32 Diamond/perl/README.md
 create mode 100644 33 Dice/pascal/README.md
 create mode 100644 33 Dice/perl/README.md
 create mode 100644 34 Digits/pascal/README.md
 create mode 100644 34 Digits/perl/README.md
 create mode 100644 35 Even Wins/pascal/README.md
 create mode 100644 35 Even Wins/perl/README.md
 create mode 100644 36 Flip Flop/pascal/README.md
 create mode 100644 36 Flip Flop/perl/README.md
 create mode 100644 37 Football/pascal/README.md
 create mode 100644 37 Football/perl/README.md
 create mode 100644 38 Fur Trader/pascal/README.md
 create mode 100644 38 Fur Trader/perl/README.md
 create mode 100644 39 Golf/pascal/README.md
 create mode 100644 39 Golf/perl/README.md
 create mode 100644 40 Gomoko/pascal/README.md
 create mode 100644 40 Gomoko/perl/README.md
 create mode 100644 41 Guess/pascal/README.md
 create mode 100644 41 Guess/perl/README.md
 create mode 100644 42 Gunner/pascal/README.md
 create mode 100644 42 Gunner/perl/README.md
 create mode 100644 43 Hammurabi/pascal/README.md
 create mode 100644 43 Hammurabi/perl/README.md
 create mode 100644 44 Hangman/pascal/README.md
 create mode 100644 44 Hangman/perl/README.md
 create mode 100644 45 Hello/pascal/README.md
 create mode 100644 45 Hello/perl/README.md
 create mode 100644 46 Hexapawn/pascal/README.md
 create mode 100644 46 Hexapawn/perl/README.md
 create mode 100644 47 Hi-Lo/pascal/README.md
 create mode 100644 47 Hi-Lo/perl/README.md
 create mode 100644 48 High IQ/pascal/README.md
 create mode 100644 48 High IQ/perl/README.md
 create mode 100644 49 Hockey/pascal/README.md
 create mode 100644 49 Hockey/perl/README.md
 create mode 100644 50 Horserace/pascal/README.md
 create mode 100644 50 Horserace/perl/README.md
 create mode 100644 51 Hurkle/pascal/README.md
 create mode 100644 51 Hurkle/perl/README.md
 create mode 100644 52 Kinema/pascal/README.md
 create mode 100644 52 Kinema/perl/README.md
 create mode 100644 53 King/pascal/README.md
 create mode 100644 53 King/perl/README.md
 create mode 100644 54 Letter/pascal/README.md
 create mode 100644 54 Letter/perl/README.md
 create mode 100644 55 Life/pascal/README.md
 create mode 100644 55 Life/perl/README.md
 create mode 100644 56 Life for Two/pascal/README.md
 create mode 100644 56 Life for Two/perl/README.md
 create mode 100644 57 Literature Quiz/pascal/README.md
 create mode 100644 57 Literature Quiz/perl/README.md
 create mode 100644 58 Love/pascal/README.md
 create mode 100644 58 Love/perl/README.md
 create mode 100644 59 Lunar LEM Rocket/pascal/README.md
 create mode 100644 59 Lunar LEM Rocket/perl/README.md
 create mode 100644 60 Mastermind/pascal/README.md
 create mode 100644 60 Mastermind/perl/README.md
 create mode 100644 61 Math Dice/pascal/README.md
 create mode 100644 61 Math Dice/perl/README.md
 create mode 100644 62 Mugwump/pascal/README.md
 create mode 100644 62 Mugwump/perl/README.md
 create mode 100644 63 Name/pascal/README.md
 create mode 100644 63 Name/perl/README.md
 create mode 100644 64 Nicomachus/pascal/README.md
 create mode 100644 64 Nicomachus/perl/README.md
 create mode 100644 65 Nim/pascal/README.md
 create mode 100644 65 Nim/perl/README.md
 create mode 100644 66 Number/pascal/README.md
 create mode 100644 66 Number/perl/README.md
 create mode 100644 67 One Check/pascal/README.md
 create mode 100644 67 One Check/perl/README.md
 create mode 100644 68 Orbit/pascal/README.md
 create mode 100644 68 Orbit/perl/README.md
 create mode 100644 69 Pizza/pascal/README.md
 create mode 100644 69 Pizza/perl/README.md
 create mode 100644 70 Poetry/pascal/README.md
 create mode 100644 70 Poetry/perl/README.md
 create mode 100644 71 Poker/pascal/README.md
 create mode 100644 71 Poker/perl/README.md
 create mode 100644 72 Queen/pascal/README.md
 create mode 100644 72 Queen/perl/README.md
 create mode 100644 73 Reverse/pascal/README.md
 create mode 100644 73 Reverse/perl/README.md
 create mode 100644 74 Rock Scissors Paper/pascal/README.md
 create mode 100644 74 Rock Scissors Paper/perl/README.md
 create mode 100644 75 Roulette/pascal/README.md
 create mode 100644 75 Roulette/perl/README.md
 create mode 100644 76 Russian Roulette/pascal/README.md
 create mode 100644 76 Russian Roulette/perl/README.md
 create mode 100644 77 Salvo/pascal/README.md
 create mode 100644 77 Salvo/perl/README.md
 create mode 100644 78 Sine Wave/pascal/README.md
 create mode 100644 78 Sine Wave/perl/README.md
 create mode 100644 79 Slalom/pascal/README.md
 create mode 100644 79 Slalom/perl/README.md
 create mode 100644 80 Slots/pascal/README.md
 create mode 100644 80 Slots/perl/README.md
 create mode 100644 81 Splat/pascal/README.md
 create mode 100644 81 Splat/perl/README.md
 create mode 100644 82 Stars/pascal/README.md
 create mode 100644 82 Stars/perl/README.md
 create mode 100644 83 Stock Market/pascal/README.md
 create mode 100644 83 Stock Market/perl/README.md
 create mode 100644 84 Super Star Trek/pascal/README.md
 create mode 100644 84 Super Star Trek/perl/README.md
 create mode 100644 85 Synonym/pascal/README.md
 create mode 100644 85 Synonym/perl/README.md
 create mode 100644 86 Target/pascal/README.md
 create mode 100644 86 Target/perl/README.md
 create mode 100644 87 3-D Plot/pascal/README.md
 create mode 100644 87 3-D Plot/perl/README.md
 create mode 100644 88 3-D Tic-Tac-Toe/pascal/README.md
 create mode 100644 88 3-D Tic-Tac-Toe/perl/README.md
 create mode 100644 89 Tic-Tac-Toe/pascal/README.md
 create mode 100644 89 Tic-Tac-Toe/perl/README.md
 create mode 100644 90 Tower/pascal/README.md
 create mode 100644 90 Tower/perl/README.md
 create mode 100644 91 Train/pascal/README.md
 create mode 100644 91 Train/perl/README.md
 create mode 100644 92 Trap/pascal/README.md
 create mode 100644 92 Trap/perl/README.md
 create mode 100644 93 23 Matches/pascal/README.md
 create mode 100644 93 23 Matches/perl/README.md
 create mode 100644 94 War/pascal/README.md
 create mode 100644 94 War/perl/README.md
 create mode 100644 95 Weekday/pascal/README.md
 create mode 100644 95 Weekday/perl/README.md
 create mode 100644 96 Word/pascal/README.md
 create mode 100644 96 Word/perl/README.md
 delete mode 100644 basic-computer-games-dot-net/basic-computer-games-dot-net.sln

diff --git a/01 Acey Ducey/pascal/README.md b/01 Acey Ducey/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/01 Acey Ducey/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/01 Acey Ducey/perl/README.md b/01 Acey Ducey/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/01 Acey Ducey/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/02 Amazing/pascal/README.md b/02 Amazing/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/02 Amazing/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/02 Amazing/perl/README.md b/02 Amazing/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/02 Amazing/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/03 Animal/pascal/README.md b/03 Animal/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/03 Animal/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/03 Animal/perl/README.md b/03 Animal/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/03 Animal/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/04 Awari/pascal/README.md b/04 Awari/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/04 Awari/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/04 Awari/perl/README.md b/04 Awari/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/04 Awari/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/05 Bagels/pascal/README.md b/05 Bagels/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/05 Bagels/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/05 Bagels/perl/README.md b/05 Bagels/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/05 Bagels/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/06 Banner/pascal/README.md b/06 Banner/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/06 Banner/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/06 Banner/perl/README.md b/06 Banner/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/06 Banner/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/07 Basketball/pascal/README.md b/07 Basketball/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/07 Basketball/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/07 Basketball/perl/README.md b/07 Basketball/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/07 Basketball/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/08 Batnum/pascal/README.md b/08 Batnum/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/08 Batnum/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/08 Batnum/perl/README.md b/08 Batnum/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/08 Batnum/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/09 Battle/pascal/README.md b/09 Battle/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/09 Battle/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/09 Battle/perl/README.md b/09 Battle/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/09 Battle/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/10 Blackjack/pascal/README.md b/10 Blackjack/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/10 Blackjack/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/10 Blackjack/perl/README.md b/10 Blackjack/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/10 Blackjack/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/11 Bombardment/pascal/README.md b/11 Bombardment/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/11 Bombardment/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/11 Bombardment/perl/README.md b/11 Bombardment/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/11 Bombardment/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/12 Bombs Away/pascal/README.md b/12 Bombs Away/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/12 Bombs Away/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/12 Bombs Away/perl/README.md b/12 Bombs Away/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/12 Bombs Away/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/13 Bounce/pascal/README.md b/13 Bounce/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/13 Bounce/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/13 Bounce/perl/README.md b/13 Bounce/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/13 Bounce/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/14 Bowling/pascal/README.md b/14 Bowling/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/14 Bowling/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/14 Bowling/perl/README.md b/14 Bowling/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/14 Bowling/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/15 Boxing/pascal/README.md b/15 Boxing/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/15 Boxing/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/15 Boxing/perl/README.md b/15 Boxing/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/15 Boxing/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/16 Bug/pascal/README.md b/16 Bug/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/16 Bug/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/16 Bug/perl/README.md b/16 Bug/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/16 Bug/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/17 Bullfight/pascal/README.md b/17 Bullfight/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/17 Bullfight/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/17 Bullfight/perl/README.md b/17 Bullfight/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/17 Bullfight/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/18 Bullseye/pascal/README.md b/18 Bullseye/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/18 Bullseye/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/18 Bullseye/perl/README.md b/18 Bullseye/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/18 Bullseye/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/19 Bunny/pascal/README.md b/19 Bunny/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/19 Bunny/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/19 Bunny/perl/README.md b/19 Bunny/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/19 Bunny/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/20 Buzzword/pascal/README.md b/20 Buzzword/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/20 Buzzword/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/20 Buzzword/perl/README.md b/20 Buzzword/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/20 Buzzword/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/21 Calendar/pascal/README.md b/21 Calendar/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/21 Calendar/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/21 Calendar/perl/README.md b/21 Calendar/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/21 Calendar/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/22 Change/pascal/README.md b/22 Change/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/22 Change/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/22 Change/perl/README.md b/22 Change/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/22 Change/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/23 Checkers/pascal/README.md b/23 Checkers/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/23 Checkers/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/23 Checkers/perl/README.md b/23 Checkers/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/23 Checkers/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/24 Chemist/pascal/README.md b/24 Chemist/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/24 Chemist/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/24 Chemist/perl/README.md b/24 Chemist/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/24 Chemist/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/25 Chief/pascal/README.md b/25 Chief/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/25 Chief/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/25 Chief/perl/README.md b/25 Chief/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/25 Chief/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/26 Chomp/pascal/README.md b/26 Chomp/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/26 Chomp/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/26 Chomp/perl/README.md b/26 Chomp/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/26 Chomp/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/27 Civil War/pascal/README.md b/27 Civil War/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/27 Civil War/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/27 Civil War/perl/README.md b/27 Civil War/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/27 Civil War/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/28 Combat/pascal/README.md b/28 Combat/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/28 Combat/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/28 Combat/perl/README.md b/28 Combat/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/28 Combat/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/29 Craps/pascal/README.md b/29 Craps/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/29 Craps/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/29 Craps/perl/README.md b/29 Craps/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/29 Craps/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/30 Cube/pascal/README.md b/30 Cube/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/30 Cube/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/30 Cube/perl/README.md b/30 Cube/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/30 Cube/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/31 Depth Charge/pascal/README.md b/31 Depth Charge/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/31 Depth Charge/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/32 Diamond/pascal/README.md b/32 Diamond/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/32 Diamond/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/32 Diamond/perl/README.md b/32 Diamond/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/32 Diamond/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/33 Dice/pascal/README.md b/33 Dice/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/33 Dice/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/33 Dice/perl/README.md b/33 Dice/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/33 Dice/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/34 Digits/pascal/README.md b/34 Digits/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/34 Digits/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/34 Digits/perl/README.md b/34 Digits/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/34 Digits/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/35 Even Wins/pascal/README.md b/35 Even Wins/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/35 Even Wins/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/35 Even Wins/perl/README.md b/35 Even Wins/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/35 Even Wins/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/36 Flip Flop/pascal/README.md b/36 Flip Flop/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/36 Flip Flop/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/36 Flip Flop/perl/README.md b/36 Flip Flop/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/36 Flip Flop/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/37 Football/pascal/README.md b/37 Football/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/37 Football/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/37 Football/perl/README.md b/37 Football/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/37 Football/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/38 Fur Trader/pascal/README.md b/38 Fur Trader/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/38 Fur Trader/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/38 Fur Trader/perl/README.md b/38 Fur Trader/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/38 Fur Trader/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/39 Golf/pascal/README.md b/39 Golf/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/39 Golf/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/39 Golf/perl/README.md b/39 Golf/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/39 Golf/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/40 Gomoko/pascal/README.md b/40 Gomoko/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/40 Gomoko/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/40 Gomoko/perl/README.md b/40 Gomoko/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/40 Gomoko/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/41 Guess/pascal/README.md b/41 Guess/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/41 Guess/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/41 Guess/perl/README.md b/41 Guess/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/41 Guess/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/42 Gunner/pascal/README.md b/42 Gunner/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/42 Gunner/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/42 Gunner/perl/README.md b/42 Gunner/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/42 Gunner/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/43 Hammurabi/pascal/README.md b/43 Hammurabi/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/43 Hammurabi/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/43 Hammurabi/perl/README.md b/43 Hammurabi/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/43 Hammurabi/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/44 Hangman/pascal/README.md b/44 Hangman/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/44 Hangman/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/44 Hangman/perl/README.md b/44 Hangman/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/44 Hangman/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/45 Hello/pascal/README.md b/45 Hello/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/45 Hello/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/45 Hello/perl/README.md b/45 Hello/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/45 Hello/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/46 Hexapawn/pascal/README.md b/46 Hexapawn/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/46 Hexapawn/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/46 Hexapawn/perl/README.md b/46 Hexapawn/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/46 Hexapawn/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/47 Hi-Lo/pascal/README.md b/47 Hi-Lo/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/47 Hi-Lo/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/47 Hi-Lo/perl/README.md b/47 Hi-Lo/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/47 Hi-Lo/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/48 High IQ/pascal/README.md b/48 High IQ/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/48 High IQ/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/48 High IQ/perl/README.md b/48 High IQ/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/48 High IQ/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/49 Hockey/pascal/README.md b/49 Hockey/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/49 Hockey/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/49 Hockey/perl/README.md b/49 Hockey/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/49 Hockey/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/50 Horserace/pascal/README.md b/50 Horserace/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/50 Horserace/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/50 Horserace/perl/README.md b/50 Horserace/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/50 Horserace/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/51 Hurkle/pascal/README.md b/51 Hurkle/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/51 Hurkle/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/51 Hurkle/perl/README.md b/51 Hurkle/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/51 Hurkle/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/52 Kinema/pascal/README.md b/52 Kinema/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/52 Kinema/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/52 Kinema/perl/README.md b/52 Kinema/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/52 Kinema/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/53 King/pascal/README.md b/53 King/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/53 King/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/53 King/perl/README.md b/53 King/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/53 King/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/54 Letter/pascal/README.md b/54 Letter/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/54 Letter/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/54 Letter/perl/README.md b/54 Letter/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/54 Letter/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/55 Life/pascal/README.md b/55 Life/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/55 Life/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/55 Life/perl/README.md b/55 Life/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/55 Life/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/56 Life for Two/pascal/README.md b/56 Life for Two/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/56 Life for Two/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/56 Life for Two/perl/README.md b/56 Life for Two/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/56 Life for Two/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/57 Literature Quiz/pascal/README.md b/57 Literature Quiz/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/57 Literature Quiz/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/57 Literature Quiz/perl/README.md b/57 Literature Quiz/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/57 Literature Quiz/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/58 Love/pascal/README.md b/58 Love/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/58 Love/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/58 Love/perl/README.md b/58 Love/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/58 Love/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/59 Lunar LEM Rocket/pascal/README.md b/59 Lunar LEM Rocket/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/59 Lunar LEM Rocket/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/59 Lunar LEM Rocket/perl/README.md b/59 Lunar LEM Rocket/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/59 Lunar LEM Rocket/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/60 Mastermind/pascal/README.md b/60 Mastermind/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/60 Mastermind/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/60 Mastermind/perl/README.md b/60 Mastermind/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/60 Mastermind/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/61 Math Dice/pascal/README.md b/61 Math Dice/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/61 Math Dice/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/61 Math Dice/perl/README.md b/61 Math Dice/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/61 Math Dice/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/62 Mugwump/pascal/README.md b/62 Mugwump/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/62 Mugwump/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/62 Mugwump/perl/README.md b/62 Mugwump/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/62 Mugwump/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/63 Name/pascal/README.md b/63 Name/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/63 Name/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/63 Name/perl/README.md b/63 Name/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/63 Name/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/64 Nicomachus/pascal/README.md b/64 Nicomachus/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/64 Nicomachus/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/64 Nicomachus/perl/README.md b/64 Nicomachus/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/64 Nicomachus/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/65 Nim/pascal/README.md b/65 Nim/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/65 Nim/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/65 Nim/perl/README.md b/65 Nim/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/65 Nim/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/66 Number/pascal/README.md b/66 Number/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/66 Number/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/66 Number/perl/README.md b/66 Number/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/66 Number/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/67 One Check/pascal/README.md b/67 One Check/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/67 One Check/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/67 One Check/perl/README.md b/67 One Check/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/67 One Check/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/68 Orbit/pascal/README.md b/68 Orbit/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/68 Orbit/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/68 Orbit/perl/README.md b/68 Orbit/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/68 Orbit/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/69 Pizza/pascal/README.md b/69 Pizza/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/69 Pizza/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/69 Pizza/perl/README.md b/69 Pizza/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/69 Pizza/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/70 Poetry/pascal/README.md b/70 Poetry/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/70 Poetry/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/70 Poetry/perl/README.md b/70 Poetry/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/70 Poetry/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/71 Poker/pascal/README.md b/71 Poker/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/71 Poker/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/71 Poker/perl/README.md b/71 Poker/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/71 Poker/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/72 Queen/pascal/README.md b/72 Queen/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/72 Queen/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/72 Queen/perl/README.md b/72 Queen/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/72 Queen/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/73 Reverse/pascal/README.md b/73 Reverse/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/73 Reverse/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/73 Reverse/perl/README.md b/73 Reverse/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/73 Reverse/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/74 Rock Scissors Paper/pascal/README.md b/74 Rock Scissors Paper/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/74 Rock Scissors Paper/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/74 Rock Scissors Paper/perl/README.md b/74 Rock Scissors Paper/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/74 Rock Scissors Paper/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/75 Roulette/pascal/README.md b/75 Roulette/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/75 Roulette/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/75 Roulette/perl/README.md b/75 Roulette/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/75 Roulette/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/76 Russian Roulette/pascal/README.md b/76 Russian Roulette/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/76 Russian Roulette/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/76 Russian Roulette/perl/README.md b/76 Russian Roulette/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/76 Russian Roulette/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/77 Salvo/pascal/README.md b/77 Salvo/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/77 Salvo/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/77 Salvo/perl/README.md b/77 Salvo/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/77 Salvo/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/78 Sine Wave/pascal/README.md b/78 Sine Wave/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/78 Sine Wave/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/78 Sine Wave/perl/README.md b/78 Sine Wave/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/78 Sine Wave/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/79 Slalom/pascal/README.md b/79 Slalom/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/79 Slalom/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/79 Slalom/perl/README.md b/79 Slalom/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/79 Slalom/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/80 Slots/pascal/README.md b/80 Slots/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/80 Slots/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/80 Slots/perl/README.md b/80 Slots/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/80 Slots/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/81 Splat/pascal/README.md b/81 Splat/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/81 Splat/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/81 Splat/perl/README.md b/81 Splat/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/81 Splat/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/82 Stars/pascal/README.md b/82 Stars/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/82 Stars/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/82 Stars/perl/README.md b/82 Stars/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/82 Stars/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/83 Stock Market/pascal/README.md b/83 Stock Market/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/83 Stock Market/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/83 Stock Market/perl/README.md b/83 Stock Market/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/83 Stock Market/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/84 Super Star Trek/pascal/README.md b/84 Super Star Trek/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/84 Super Star Trek/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/84 Super Star Trek/perl/README.md b/84 Super Star Trek/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/84 Super Star Trek/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/85 Synonym/pascal/README.md b/85 Synonym/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/85 Synonym/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/85 Synonym/perl/README.md b/85 Synonym/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/85 Synonym/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/86 Target/pascal/README.md b/86 Target/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/86 Target/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/86 Target/perl/README.md b/86 Target/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/86 Target/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/87 3-D Plot/pascal/README.md b/87 3-D Plot/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/87 3-D Plot/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/87 3-D Plot/perl/README.md b/87 3-D Plot/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/87 3-D Plot/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/88 3-D Tic-Tac-Toe/pascal/README.md b/88 3-D Tic-Tac-Toe/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/88 3-D Tic-Tac-Toe/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/88 3-D Tic-Tac-Toe/perl/README.md b/88 3-D Tic-Tac-Toe/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/88 3-D Tic-Tac-Toe/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/89 Tic-Tac-Toe/pascal/README.md b/89 Tic-Tac-Toe/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/89 Tic-Tac-Toe/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/89 Tic-Tac-Toe/perl/README.md b/89 Tic-Tac-Toe/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/89 Tic-Tac-Toe/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/90 Tower/pascal/README.md b/90 Tower/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/90 Tower/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/90 Tower/perl/README.md b/90 Tower/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/90 Tower/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/91 Train/pascal/README.md b/91 Train/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/91 Train/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/91 Train/perl/README.md b/91 Train/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/91 Train/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/92 Trap/pascal/README.md b/92 Trap/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/92 Trap/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/92 Trap/perl/README.md b/92 Trap/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/92 Trap/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/93 23 Matches/pascal/README.md b/93 23 Matches/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/93 23 Matches/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/93 23 Matches/perl/README.md b/93 23 Matches/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/93 23 Matches/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/94 War/pascal/README.md b/94 War/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/94 War/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/94 War/perl/README.md b/94 War/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/94 War/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/95 Weekday/pascal/README.md b/95 Weekday/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/95 Weekday/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/95 Weekday/perl/README.md b/95 Weekday/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/95 Weekday/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/96 Word/pascal/README.md b/96 Word/pascal/README.md
new file mode 100644
index 00000000..aa1b3ae5
--- /dev/null
+++ b/96 Word/pascal/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
diff --git a/96 Word/perl/README.md b/96 Word/perl/README.md
new file mode 100644
index 00000000..e69c8b81
--- /dev/null
+++ b/96 Word/perl/README.md	
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Perl](https://www.perl.org/)
diff --git a/basic-computer-games-dot-net/basic-computer-games-dot-net.sln b/basic-computer-games-dot-net/basic-computer-games-dot-net.sln
deleted file mode 100644
index f32f088d..00000000
--- a/basic-computer-games-dot-net/basic-computer-games-dot-net.sln
+++ /dev/null
@@ -1,69 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.31004.235
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01 Acey Ducey", "01 Acey Ducey", "{63FEF89A-DAF1-42C6-B86B-AAD51E885553}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{9ADA338C-DAB6-4EE8-8F53-F3F711BEA985}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AceyDucey", "..\01 Acey Ducey\csharp\AceyDucey.csproj", "{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "33 Dice", "33 Dice", "{3C6771F4-513C-4B8D-A042-15E18EB27740}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{AC302ACD-C3B2-460D-BA1A-0A511C36A848}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dice", "..\33 Dice\csharp\Dice.csproj", "{26D086DE-0BBD-4A18-AC63-2476A7DB52D3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "47 Hi-Lo", "47 Hi-Lo", "{A2BC8E4A-B977-46A6-B897-7E675ACB96F0}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{04298EE8-0EF3-475C-9427-E04C267BBEFB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "hi-lo", "..\47 Hi-Lo\csharp\hi-lo.csproj", "{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05 Bagels", "05 Bagels", "{946C0E7C-8A83-4C7F-9959-1AF0AEF4A027}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{91DA95EE-DD42-4AEC-A886-07F834061BFC}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bagels", "..\05 Bagels\csharp\Bagels.csproj", "{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Release|Any CPU.Build.0 = Release|Any CPU
-		{26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Release|Any CPU.Build.0 = Release|Any CPU
-		{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6}.Release|Any CPU.Build.0 = Release|Any CPU
-		{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-	GlobalSection(NestedProjects) = preSolution
-		{9ADA338C-DAB6-4EE8-8F53-F3F711BEA985} = {63FEF89A-DAF1-42C6-B86B-AAD51E885553}
-		{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3} = {9ADA338C-DAB6-4EE8-8F53-F3F711BEA985}
-		{AC302ACD-C3B2-460D-BA1A-0A511C36A848} = {3C6771F4-513C-4B8D-A042-15E18EB27740}
-		{26D086DE-0BBD-4A18-AC63-2476A7DB52D3} = {AC302ACD-C3B2-460D-BA1A-0A511C36A848}
-		{04298EE8-0EF3-475C-9427-E04C267BBEFB} = {A2BC8E4A-B977-46A6-B897-7E675ACB96F0}
-		{9B8FB4D6-EB62-47CC-A89D-96D330E96FF6} = {04298EE8-0EF3-475C-9427-E04C267BBEFB}
-		{91DA95EE-DD42-4AEC-A886-07F834061BFC} = {946C0E7C-8A83-4C7F-9959-1AF0AEF4A027}
-		{DC32ED10-ACEA-4B09-8B2A-54E1F7277C0A} = {91DA95EE-DD42-4AEC-A886-07F834061BFC}
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-		SolutionGuid = {703D538E-7F20-4DD0-A3DD-7BBE36AC82AF}
-	EndGlobalSection
-EndGlobal

From 3a902ffd6444aa4a9b9c77c022861bf5a405f0e0 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Sun, 28 Feb 2021 08:14:17 +1030
Subject: [PATCH 046/749] Java version of Slots

---
 .gitignore                       |   5 +
 80 Slots/java/src/Slots.java     | 297 +++++++++++++++++++++++++++++++
 80 Slots/java/src/SlotsGame.java |   6 +
 3 files changed, 308 insertions(+)
 create mode 100644 80 Slots/java/src/Slots.java
 create mode 100644 80 Slots/java/src/SlotsGame.java

diff --git a/.gitignore b/.gitignore
index e69de29b..0bbe112f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1,5 @@
+
+.DS_Store
+*.iml
+.idea
+out
diff --git a/80 Slots/java/src/Slots.java b/80 Slots/java/src/Slots.java
new file mode 100644
index 00000000..9d96d94f
--- /dev/null
+++ b/80 Slots/java/src/Slots.java	
@@ -0,0 +1,297 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Slots
+ * 

+ * Based on the Basic game of Slots here + * https://github.com/coding-horror/basic-computer-games/blob/main/80%20Slots/slots.bas + *

+ * 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 Slots { + + public static final String[] SLOT_SYMBOLS = {"BAR", "BELL", "ORANGE", "LEMON", "PLUM", "CHERRY"}; + + public static final int NUMBER_SYMBOLS = SLOT_SYMBOLS.length; + + // Jackpot symbol (BAR) + public static final int BAR_SYMBOL = 0; + + // Indicator that the current spin won nothing + public static final int NO_WINNER = -1; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + ONE_SPIN, + RESULTS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + // Different types of spin results + private enum WINNINGS { + JACKPOT(100), + TOP_DOLLAR(10), + DOUBLE_BAR(5), + REGULAR(2), + NO_WIN(0); + + private final int multiplier; + + WINNINGS(int mult) { + multiplier = mult; + } + + // No win returns the negative amount of net + // otherwise calculate winnings based on + // multiplier + public int calculateWinnings(int bet) { + + if (multiplier == 0) { + return -bet; + } else { + // Return original bet plus a multipler + // of the win type + return (multiplier * bet) + bet; + } + } + } + + private int playerBalance; + + public Slots() { + + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() { + + int[] slotReel = new int[3]; + + do { + // Results of a single spin + WINNINGS winnings; + + switch (gameState) { + + case START_GAME: + intro(); + playerBalance = 0; + gameState = GAME_STATE.ONE_SPIN; + break; + + case ONE_SPIN: + + int playerBet = displayTextAndGetNumber("YOUR BET? "); + + slotReel[0] = randomSymbol(); + slotReel[1] = randomSymbol(); + slotReel[2] = randomSymbol(); + + // Store which symbol (if any) matches at least one other reel + int whichSymbolWon = winningSymbol(slotReel[0], slotReel[1], slotReel[2]); + + // Display the three randomly drawn symbols + StringBuilder output = new StringBuilder(); + for (int i = 0; i < 3; i++) { + if (i > 0) { + output.append(" "); + } + output.append(SLOT_SYMBOLS[slotReel[i]]); + } + + System.out.println(output); + + // Calculate results + + if (whichSymbolWon == NO_WINNER) { + // No symbols match = nothing won + winnings = WINNINGS.NO_WIN; + } else if (slotReel[0] == slotReel[1] && slotReel[0] == slotReel[2]) { + // Top dollar, 3 matching symbols + winnings = WINNINGS.TOP_DOLLAR; + if (slotReel[0] == BAR_SYMBOL) { + // All 3 symbols are BAR. Jackpot! + winnings = WINNINGS.JACKPOT; + } + } else { + // At this point the remaining options are a regular win + // or a double, since the rest (including not winning) have already + // been checked above. + // Assume a regular win + winnings = WINNINGS.REGULAR; + + // But if it was the BAR symbol that matched, its a double bar + if (slotReel[0] == BAR_SYMBOL) { + winnings = WINNINGS.DOUBLE_BAR; + } + + } + + // Update the players balance with the amount won or lost on this spin + playerBalance += winnings.calculateWinnings(playerBet); + + System.out.println(); + + // Output what happened on this spin + switch (winnings) { + case NO_WIN: + System.out.println("YOU LOST."); + break; + + case REGULAR: + System.out.println("DOUBLE!!"); + System.out.println("YOU WON!"); + break; + + case DOUBLE_BAR: + System.out.println("*DOUBLE BAR*"); + System.out.println("YOU WON!"); + break; + + case TOP_DOLLAR: + System.out.println(); + System.out.println("**TOP DOLLAR**"); + System.out.println("YOU WON!"); + break; + + case JACKPOT: + System.out.println(); + System.out.println("***JACKPOT***"); + System.out.println("YOU WON!"); + break; + + } + + System.out.println("YOUR STANDINGS ARE $" + playerBalance); + + // If player does not elect to play again, show results of session + if (!yesEntered(displayTextAndGetInput("AGAIN? "))) { + gameState = GAME_STATE.RESULTS; + + } + break; + + case RESULTS: + if (playerBalance == 0) { + System.out.println("HEY, YOU BROKE EVEN."); + } else if (playerBalance > 0) { + System.out.println("COLLECT YOUR WINNINGS FROM THE H&M CASHIER."); + } else { + // Lost + System.out.println("PAY UP! PLEASE LEAVE YOUR MONEY ON THE TERMINAL."); + } + + gameState = GAME_STATE.GAME_OVER; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(30) + "SLOTS"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("YOU ARE IN THE H&M CASINO,IN FRONT OF ONE OF OUR"); + System.out.println("ONE-ARM BANDITS. BET FROM $1 TO $100."); + System.out.println("TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Find the symbol that won this round i.e. the first reel that matched another reel + * + * @param reel1 reel1 spin result + * @param reel2 reel2 spin result + * @param reel3 reel3 spin result + * @return NO_WINNER if no reels match otherwise an int 0-2 to indicate the reel that matches another + */ + private int winningSymbol(int reel1, int reel2, int reel3) { + if (reel1 == reel2) { + return 0; + } else if (reel1 == reel3) { + return 0; + } else if (reel2 == reel3) { + return 1; + } else { + return NO_WINNER; + } + } + + /** + * Random symbol for a slot wheel + * + * @return number between 0-5 + */ + private int randomSymbol() { + return (int) (Math.random() * NUMBER_SYMBOLS); + } +} diff --git a/80 Slots/java/src/SlotsGame.java b/80 Slots/java/src/SlotsGame.java new file mode 100644 index 00000000..05617cf7 --- /dev/null +++ b/80 Slots/java/src/SlotsGame.java @@ -0,0 +1,6 @@ +public class SlotsGame { + public static void main(String[] args) { + Slots slots = new Slots(); + slots.play(); + } +} From cae335093bc124f26ee0ca7c8feec5b7a148e1bc Mon Sep 17 00:00:00 2001 From: Tim Buchalka <70119791+journich@users.noreply.github.com> Date: Sun, 28 Feb 2021 08:15:55 +1030 Subject: [PATCH 047/749] Delete .gitignore --- .gitignore | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0bbe112f..00000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ - -.DS_Store -*.iml -.idea -out From cb430380fef9614e26783a9dcdf49f101b9ae27d Mon Sep 17 00:00:00 2001 From: Gustavo Carreno Date: Sat, 27 Feb 2021 22:24:47 +0000 Subject: [PATCH 048/749] Pascal: Adding aceyducey --- 01 Acey Ducey/README.md | 4 - 01 Acey Ducey/pascal/.gitattributes | 36 +++++ 01 Acey Ducey/pascal/.gitignore | 63 ++++++++ .../pascal/object-pascal/aceyducey.lpi | 68 ++++++++ .../pascal/object-pascal/aceyducey.pas | 18 +++ 01 Acey Ducey/pascal/object-pascal/deck.pas | 111 +++++++++++++ 01 Acey Ducey/pascal/object-pascal/game.pas | 136 ++++++++++++++++ 01 Acey Ducey/pascal/simple/aceyducey.lpi | 58 +++++++ 01 Acey Ducey/pascal/simple/aceyducey.pas | 152 ++++++++++++++++++ 9 files changed, 642 insertions(+), 4 deletions(-) create mode 100644 01 Acey Ducey/pascal/.gitattributes create mode 100644 01 Acey Ducey/pascal/.gitignore create mode 100644 01 Acey Ducey/pascal/object-pascal/aceyducey.lpi create mode 100644 01 Acey Ducey/pascal/object-pascal/aceyducey.pas create mode 100644 01 Acey Ducey/pascal/object-pascal/deck.pas create mode 100644 01 Acey Ducey/pascal/object-pascal/game.pas create mode 100644 01 Acey Ducey/pascal/simple/aceyducey.lpi create mode 100644 01 Acey Ducey/pascal/simple/aceyducey.pas diff --git a/01 Acey Ducey/README.md b/01 Acey Ducey/README.md index 11c6b1a8..ad0bdbad 100644 --- a/01 Acey Ducey/README.md +++ b/01 Acey Ducey/README.md @@ -5,7 +5,3 @@ https://www.atariarchives.org/basicgames/showpage.php?page=2 Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html - -#### Other languages: - -- [Pascal/Object Pascal](https://github.com/gcarreno/basic-computer-games-in-pascal/tree/main/01%20Acey%20Ducey) \ No newline at end of file diff --git a/01 Acey Ducey/pascal/.gitattributes b/01 Acey Ducey/pascal/.gitattributes new file mode 100644 index 00000000..f59d5ede --- /dev/null +++ b/01 Acey Ducey/pascal/.gitattributes @@ -0,0 +1,36 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.inc text +*.pas text +*.pp text +*.lpk text +*.lpi text +*.lps text +*.lpr text +*.def text +*.css text +*.html text +*.xml text +*.sql text + +# Declare files that will always have CRLF line endings on checkout. +*.dpk text eol=crlf +*.dproj text eol=crlf + +# Declare files that will always have LF line endings on checkout. + + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.exe binary +*.res binary +*.ico binary +*.dll binary + +# Keep these files from archive/exports, mainly from production. +.gitignore export-ignore +.gitattributes export-ignore diff --git a/01 Acey Ducey/pascal/.gitignore b/01 Acey Ducey/pascal/.gitignore new file mode 100644 index 00000000..a95e39cf --- /dev/null +++ b/01 Acey Ducey/pascal/.gitignore @@ -0,0 +1,63 @@ +# Basic Computer Programs project specific +aceyducey +aceyducey.exe + +# Compiled l10n files: .mo should be ignored +*.mo + +# Ghostwriter backups +*.backup + +# nano editor backup files +*.swp + +# Uncomment these types if you want even more clean repository. But be careful. +# It can make harm to an existing project source. Read explanations below. +# +# Resource files are binaries containing manifest, project icon and version info. +# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. +*.res + +# Delphi/Lazarus compiler-generated binaries (safe to delete) +*.exe +*.dll +*.bpl +*.bpi +*.dcp +*.so +*.apk +*.drc +*.map +*.dres +*.rsm +*.tds +*.dcu +*.lib +*.[ao] +*.or +*.ppu +*.dbg +*.compiled + +# Delphi autogenerated files (duplicated info) +*.cfg +*Resource.rc + +# Delphi local files (user-specific info) +*.local +*.identcache +*.projdata +*.tvsconfig +*.dsk + +# Delphi history and backups +__history/ +*.~* + +# Lazarus history, backups and session +backup/ +*.bak +*.lps + +# Castalia statistics file +*.stat diff --git a/01 Acey Ducey/pascal/object-pascal/aceyducey.lpi b/01 Acey Ducey/pascal/object-pascal/aceyducey.lpi new file mode 100644 index 00000000..9e1a30e8 --- /dev/null +++ b/01 Acey Ducey/pascal/object-pascal/aceyducey.lpi @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + <Modes Count="0"/> + </RunParams> + <Units Count="3"> + <Unit0> + <Filename Value="aceyducey.pas"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="game.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Game"/> + </Unit1> + <Unit2> + <Filename Value="deck.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Deck"/> + </Unit2> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="aceyducey"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/01 Acey Ducey/pascal/object-pascal/aceyducey.pas b/01 Acey Ducey/pascal/object-pascal/aceyducey.pas new file mode 100644 index 00000000..733221f5 --- /dev/null +++ b/01 Acey Ducey/pascal/object-pascal/aceyducey.pas @@ -0,0 +1,18 @@ +program aceyducey; + +{$IFDEF FPC} +{$mode objfpc}{$H+} +{$ENDIF} + +uses + Game, Deck +; + +var + Acey_Ducey: TGame; + +begin + Acey_Ducey:= TGame.Create; + Acey_Ducey.Run; +end. + diff --git a/01 Acey Ducey/pascal/object-pascal/deck.pas b/01 Acey Ducey/pascal/object-pascal/deck.pas new file mode 100644 index 00000000..d5940fe2 --- /dev/null +++ b/01 Acey Ducey/pascal/object-pascal/deck.pas @@ -0,0 +1,111 @@ +unit Deck; + +{$IFDEF FPC} +{$mode objfpc}{$H+} +{$ENDIF} + +interface + +uses + Classes +, SysUtils +; + +type +{ TDeck } + TDeck = class + private + FDealerLow: Integer; + FDealerHigh: Integer; + FPlayer: Integer; + + procedure PrintCard(const ACard: Integer); + protected + public + property DealerLow: Integer + read FDealerLow; + property DealerHigh: Integer + read FDealerHigh; + property Player: Integer + read FPlayer; + + procedure DrawCards; + procedure ShowDealerCards; + procedure ShowPlayerCard; + function PlayerWins: Boolean; + published + end; + +implementation + +{ TDeck } + +procedure TDeck.PrintCard(const ACard: Integer); +begin + if ACard < 11 then + begin + Write(ACard); + end; + if ACard = 11 then + begin + Write('JACK'); + end; + if ACard = 12 then + begin + Write('QUEEN'); + end; + if ACard = 13 then + begin + Write('KING'); + end; + if ACard = 14 then + begin + Write('ACE'); + end; +end; + +procedure TDeck.DrawCards; +var + tmp: Integer; +begin + repeat + FDealerLow:= Random(14) + 2; + until (FDealerLow >= 2) and (FDealerLow <= 14); + repeat + FDealerHigh:= Random(14) + 2; + until (FDealerHigh >= 2) and (FDealerHigh <= 14) and (FDealerLow <> FDealerHigh); + if FDealerLow > FDealerHigh then + begin + tmp:= FDealerHigh; + FDealerHigh:= FDealerLow; + FDealerLow:= tmp; + end; + repeat + FPlayer:= Random(14) + 2; + until (FPlayer >= 2) and (FPlayer <= 14); +end; + +procedure TDeck.ShowDealerCards; +begin + Write('HERE ARE YOUR NEXT TWO CARDS: '); + PrintCard(FDealerLow); + Write(' '); + PrintCard(FDealerHigh); + WriteLN; + WriteLN; +end; + +procedure TDeck.ShowPlayerCard; +begin + PrintCard(FPlayer); + WriteLN; + WriteLN; +end; + +function TDeck.PlayerWins: Boolean; +begin + Result:= (FPlayer > FDealerLow) and (FPlayer < FDealerHigh); +end; + +end. + diff --git a/01 Acey Ducey/pascal/object-pascal/game.pas b/01 Acey Ducey/pascal/object-pascal/game.pas new file mode 100644 index 00000000..1a263159 --- /dev/null +++ b/01 Acey Ducey/pascal/object-pascal/game.pas @@ -0,0 +1,136 @@ +unit Game; + +{$IFDEF FPC} +{$mode objfpc}{$H+} +{$ENDIF} + +interface + +uses + Classes +, SysUtils +, Crt +, Deck +; + +type +{ TGame } + TGame = class + private + FStash: Integer; + FBet: Integer; + FDeck: TDeck; + + procedure PrintGreeting; + procedure PrintBalance; + function GetBet: Integer; + function TryAgain: Boolean; + protected + public + constructor Create; + destructor Destroy; override; + + procedure Run; + published + end; + +implementation + +{ TGame } + +procedure TGame.PrintGreeting; +begin + WriteLN(' ':26, 'ACEY DUCEY CARD GAME'); + WriteLN(' ':15, 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'); + WriteLN; + WriteLN; + WriteLN('ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER '); + WriteLN('THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP'); + WriteLN('YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING'); + WriteLN('ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE'); + WriteLN('A VALUE BETWEEN THE FIRST TWO.'); + WriteLN('IF YOU DO NOT WANT TO BET, INPUT A 0'); + WriteLN; +end; + +procedure TGame.PrintBalance; +begin + WriteLN('YOU NOW HAVE ', FStash,' DOLLARS.'); + WriteLN; +end; + +function TGame.GetBet: Integer; +begin + Result:= 0; + repeat + Write('WHAT IS YOUR BET: '); + ReadLN(Result); + if Result > FStash then + begin + WriteLn('SORRY, MY FRIEND, BUT YOU BET TOO MUCH.'); + WriteLn('YOU HAVE ONLY ', FStash,' DOLLARS TO BET.'); + end; + until (Result >=0) and (Result <= FStash); +end; + +function TGame.TryAgain: Boolean; +var + answer: String; +begin + Result:= False; + Write('TRY AGAIN (YES OR NO)'); + ReadLn(answer); + Result:= (LowerCase(answer)='yes') or (LowerCase(answer)='y'); +end; + +constructor TGame.Create; +begin + FDeck:= TDeck.Create; +end; + +destructor TGame.Destroy; +begin + FDeck.Free; + inherited Destroy; +end; + +procedure TGame.Run; +begin + ClrScr; + PrintGreeting; + repeat + Randomize; + FStash:= 100; + repeat + PrintBalance; + FDeck.DrawCards; + //DrawDealerCards; + FDeck.ShowDealerCards; + FBet:= GetBet; + if FBet = 0 then + begin + WriteLN('CHICKEN!!'); + continue; + end; + //DrawPlayerCard; + FDeck.ShowPlayerCard; + //if (FCardC > FCardA) and (FCardC < FCardB) then + if FDeck.PlayerWins then + begin + WriteLN('YOU WIN!!!'); + Inc(FStash, FBet) + end + else + begin + WriteLN('SORRY, YOU LOSE'); + Dec(FStash, FBet) + end; + until FStash = 0; + WriteLN('SORRY, FRIEND, BUT YOU BLEW YOUR WAD.'); + WriteLN; + until not TryAgain; + WriteLN('O.K., HOPE YOU HAD FUN!'); +end; + +end. + diff --git a/01 Acey Ducey/pascal/simple/aceyducey.lpi b/01 Acey Ducey/pascal/simple/aceyducey.lpi new file mode 100644 index 00000000..f80bb634 --- /dev/null +++ b/01 Acey Ducey/pascal/simple/aceyducey.lpi @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectOptions> + <Version Value="11"/> + <General> + <Flags> + <MainUnitHasCreateFormStatements Value="False"/> + <MainUnitHasTitleStatement Value="False"/> + <MainUnitHasScaledStatement Value="False"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <MainUnit Value="0"/> + <Title Value="aceyducey"/> + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + <Modes Count="0"/> + </RunParams> + <Units Count="1"> + <Unit0> + <Filename Value="aceyducey.pas"/> + <IsPartOfProject Value="True"/> + </Unit0> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="aceyducey"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/01 Acey Ducey/pascal/simple/aceyducey.pas b/01 Acey Ducey/pascal/simple/aceyducey.pas new file mode 100644 index 00000000..35a9dd64 --- /dev/null +++ b/01 Acey Ducey/pascal/simple/aceyducey.pas @@ -0,0 +1,152 @@ +program aceyducey; + +{$IFDEF FPC} +{$mode objfpc}{$H+} +{$ENDIF} + +uses + Crt; + +var + Stash: Integer; + CardA: Integer; + CardB: Integer; + CardC: Integer; + Bet: Integer; + +procedure PrintGreeting; +begin + WriteLN(' ':26, 'ACEY DUCEY CARD GAME'); + WriteLN(' ':15, 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'); + WriteLN; + WriteLN; + WriteLN('ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER '); + WriteLN('THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP'); + WriteLN('YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING'); + WriteLN('ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE'); + WriteLN('A VALUE BETWEEN THE FIRST TWO.'); + WriteLN('IF YOU DO NOT WANT TO BET, INPUT A 0'); + WriteLN; +end; + +procedure PrintBalance; +begin + WriteLN('YOU NOW HAVE ', Stash,' DOLLARS.'); + WriteLN; +end; + +procedure PrintCard(const ACard: Integer); +begin + if ACard < 11 then + begin + Write(ACard); + end; + if ACard = 11 then + begin + Write('JACK'); + end; + if ACard = 12 then + begin + Write('QUEEN'); + end; + if ACard = 13 then + begin + Write('KING'); + end; + if ACard = 14 then + begin + Write('ACE'); + end; +end; + +procedure DrawDealerCards; +var + tmp: Integer; +begin + Write('HERE ARE YOUR NEXT TWO CARDS: '); + repeat + CardA:= Random(14) + 2; + until (CardA >= 2) and (CardA <= 14); + repeat + CardB:= Random(14) + 2; + until (CardB >= 2) and (CardB <= 14) and (CardA <> CardB); + if CardA > CardB then + begin + tmp:= CardB; + CardB:= CardA; + CardA:= tmp; + end; + PrintCard(CardA); + Write(' '); + PrintCard(CardB); + WriteLN; + WriteLN; +end; + +procedure DrawPlayerCard; +begin + repeat + CardC:= Random(14) + 2; + until (CardC >= 2) and (CardC <= 14); + PrintCard(CardC); + WriteLN; + WriteLN; +end; + +function GetBet: Integer; +begin + Result:= 0; + repeat + Write('WHAT IS YOUR BET: '); + ReadLN(Result); + if Result > Stash then + begin + WriteLn('SORRY, MY FRIEND, BUT YOU BET TOO MUCH.'); + WriteLn('YOU HAVE ONLY ', Stash,' DOLLARS TO BET.'); + end; + until (Result >=0) and (Result <= Stash); +end; + +function TryAgain: Boolean; +var + answer: String; +begin + Result:= False; + Write('TRY AGAIN (YES OR NO)'); + ReadLn(answer); + Result:= (LowerCase(answer)='yes') or (LowerCase(answer)='y'); +end; + +begin + ClrScr; + PrintGreeting; + repeat + Randomize; + Stash:= 100; + repeat + PrintBalance; + DrawDealerCards; + Bet:= GetBet; + if Bet = 0 then + begin + WriteLN('CHICKEN!!'); + continue; + end; + DrawPlayerCard; + if (CardC > CardA) and (CardC < CardB) then + begin + WriteLN('YOU WIN!!!'); + Inc(Stash, Bet) + end + else + begin + WriteLN('SORRY, YOU LOSE'); + Dec(Stash, Bet) + end; + until Stash = 0; + WriteLN('SORRY, FRIEND, BUT YOU BLEW YOUR WAD.'); + WriteLN; + until not TryAgain; + WriteLN('O.K., HOPE YOU HAD FUN!'); +end. + From 567885c40566c458049d077766cb529b6dfae0ef Mon Sep 17 00:00:00 2001 From: Gustavo Carreno <guscarreno@gmail.com> Date: Sat, 27 Feb 2021 22:28:42 +0000 Subject: [PATCH 049/749] Pascal: Adding credit --- 01 Acey Ducey/pascal/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01 Acey Ducey/pascal/README.md b/01 Acey Ducey/pascal/README.md index aa1b3ae5..3f97be91 100644 --- a/01 Acey Ducey/pascal/README.md +++ b/01 Acey Ducey/pascal/README.md @@ -1,3 +1,3 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) -Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language)) +Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language)) by Gustavo Carreno [gcarreno@github](https://github.com/gcarreno) From 216e34b6228063484b17e56d495077150521611e Mon Sep 17 00:00:00 2001 From: epvanhouten <epvanhouten@gmail.com> Date: Sat, 27 Feb 2021 16:36:26 -0600 Subject: [PATCH 050/749] Bootstrapping empty console Generated using `dotnet new console --name hurkle`. --- 51 Hurkle/csharp/.gitignore | 360 ++++++++++++++++++++++ 51 Hurkle/csharp/src/hurkle/Program.cs | 12 + 51 Hurkle/csharp/src/hurkle/hurkle.csproj | 8 + 3 files changed, 380 insertions(+) create mode 100644 51 Hurkle/csharp/.gitignore create mode 100644 51 Hurkle/csharp/src/hurkle/Program.cs create mode 100644 51 Hurkle/csharp/src/hurkle/hurkle.csproj diff --git a/51 Hurkle/csharp/.gitignore b/51 Hurkle/csharp/.gitignore new file mode 100644 index 00000000..d417b186 --- /dev/null +++ b/51 Hurkle/csharp/.gitignore @@ -0,0 +1,360 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/csharp +# Edit at https://www.toptal.com/developers/gitignore?templates=csharp + +### Csharp ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*[.json, .xml, .info] + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# End of https://www.toptal.com/developers/gitignore/api/csharp \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51 Hurkle/csharp/src/hurkle/Program.cs new file mode 100644 index 00000000..42c8e1b5 --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace hurkle +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/51 Hurkle/csharp/src/hurkle/hurkle.csproj b/51 Hurkle/csharp/src/hurkle/hurkle.csproj new file mode 100644 index 00000000..1d2d39a9 --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/hurkle.csproj @@ -0,0 +1,8 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net5.0</TargetFramework> + </PropertyGroup> + +</Project> From d788854809572f866765ffb25049b76131255efb Mon Sep 17 00:00:00 2001 From: Dave LeCompte <tsmaster@gmail.com> Date: Sat, 27 Feb 2021 14:45:24 -0800 Subject: [PATCH 051/749] Python version of NAME uses Python operators for sorting and string manipulation --- 63 Name/python/name.py | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 63 Name/python/name.py diff --git a/63 Name/python/name.py b/63 Name/python/name.py new file mode 100644 index 00000000..5c567d5a --- /dev/null +++ b/63 Name/python/name.py @@ -0,0 +1,62 @@ +""" +NAME + +simple string manipulations on the user's name + +Ported by Dave LeCompte +""" + + +def print_with_tab(space_count, msg): + if space_count > 0: + spaces = " " * space_count + else: + spaces = "" + print(spaces + msg) + + +def is_yes_ish(answer): + cleaned = answer.strip().upper() + if cleaned == "Y" or cleaned == "YES": + return True + return False + + +def main(): + print_with_tab(34, "NAME") + print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + print("HELLO.") + print("MY NAME iS CREATIVE COMPUTER.") + name = input("WHAT'S YOUR NAME (FIRST AND LAST)?") + print() + name_as_list = list(name) + reversed_name = "".join(name_as_list[::-1]) + print(f"THANK YOU, {reversed_name}.") + print() + print("OOPS! I GUESS I GOT IT BACKWARDS. A SMART") + print("COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!") + print() + print() + print("BUT I JUST NOTICED YOUR LETTERS ARE OUT OF ORDER.") + + sorted_name = "".join(sorted(name_as_list)) + print(f"LET'S PUT THEM IN ORDER LIKE THIS: {sorted_name}") + print() + print() + + print("DON'T YOU LIKE THAT BETTER?") + like_answer = input() + print() + if is_yes_ish(like_answer): + print("I KNEW YOU'D AGREE!!") + else: + print("I'M SORRY YOU DON'T LIKE IT THAT WAY.") + print() + print(f"I REALLY ENJOYED MEETING YOU, {name}.") + print("HAVE A NICE DAY!") + + +main() From ee2f5c27b6d14125b0c080c22e2a805870399069 Mon Sep 17 00:00:00 2001 From: epvanhouten <epvanhouten@gmail.com> Date: Sat, 27 Feb 2021 16:50:59 -0600 Subject: [PATCH 052/749] Transscripting original source Pulled from https://www.atariarchives.org/basicgames/pages/page94.gif --- 51 Hurkle/csharp/src/hurkle/Program.cs | 52 +++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51 Hurkle/csharp/src/hurkle/Program.cs index 42c8e1b5..a9cd0f60 100644 --- a/51 Hurkle/csharp/src/hurkle/Program.cs +++ b/51 Hurkle/csharp/src/hurkle/Program.cs @@ -6,7 +6,57 @@ namespace hurkle { static void Main(string[] args) { - Console.WriteLine("Hello World!"); + /* + Original source transscription + 10 PRINT TAB(33);"HURKLE" + 20 PRINT TAB(15);"CREATIVE COMPUTING NORRISTOWN, NEW JERSEY" + 30 PRINT;PRINT;PRINT + 110 N=5 + 120 G=10 + 210 PRINT + 220 PRINT "A HURKLE IS HIDING ON A";G;"BY";G;"GRID. HOMEBASE" + 230 PRINT "ON THE GRID IS POINT 0,0 AND ANY GRIDPOINT IS A" + 240 PRINT "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. TRY TO" + 250 PRINT "GUESS THE HURKLE'S GRIDPOINT. YOU GET";N;"TRIES." + 260 PRINT "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE" + 270 PRINT "DIRECTION TO GO TO LOOK FOR THE HURKLE." + 280 PRINT + 285 A=INT(G*RND(1)) + 286 B=INT(G*RND(1)) + 310 FOR K=1 TO N + 320 PRINT "GUESS #";K; + 330 INPUT X,Y + 340 IF ABS(X-A)+ABS(Y-B)=0 THEN 500 + 350 REM PRINT INFO + 360 GOSUB 610 + 370 PRINT + 380 NEXT K + 410 PRINT + 420 PRINT "SORRY, THAT'S;N;"GUESSES." + 430 PRINT "THE HURKLE IS AT ";A;",";B + 440 PRINT + 450 PRINT "LET'S PLAY AGAIN. HURKLE IS HIDING." + 460 PRINT + 470 GOTO 285 + 500 REM + 510 PRINT + 520 PRINT "YOU FOUND HIM IN";K;GUESSES!" + 540 GOTO 440 + 610 PRINT "GO "; + 620 IF Y=B THEN 670 + 630 IF Y<B THEN 660 + 640 PRINT "SOUTH; + 650 GO TO 670 + 660 PRINT "NORTH"; + 670 IF X=A THEN 720 + 680 IF X<A THEN 710 + 690 PRINT "WEST"; + 700 GO TO 720 + 710 PRINT "EAST"; + 720 PRINT + 730 RETURN + 999 END + */ } } } From c860f7a9f5cfbf8521dc0003910a23a3e642c04b Mon Sep 17 00:00:00 2001 From: PeterQuinn925 <peterquinn925@gmail.com> Date: Sat, 27 Feb 2021 15:37:11 -0800 Subject: [PATCH 053/749] Port of Hamurabi to Python --- 43 Hammurabi/python/hamurabi.py | 183 ++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 43 Hammurabi/python/hamurabi.py diff --git a/43 Hammurabi/python/hamurabi.py b/43 Hammurabi/python/hamurabi.py new file mode 100644 index 00000000..24ebe581 --- /dev/null +++ b/43 Hammurabi/python/hamurabi.py @@ -0,0 +1,183 @@ +def GenRandom(C): + C=int(random()*5)+1 +def BadInput850(): + print ( "\nHAMURABI: I CANNOT DO WHAT YOU WISH.") + print ( "GET YOURSELF ANOTHER STEWARD!!!!!") + Z=99 +def BadInput710(S): + print ( "HAMURABI: THINK AGAIN. YOU HAVE ONLY") + print ( S,"BUSHELS OF GRAIN. NOW THEN,") +def BadInput720(A): + print ( "HAMURABI: THINK AGAIN. YOU OWN ONLY",A,"ACRES. NOW THEN,") +def BadInput710(S): + print ( "HAMURABI: THINK AGAIN. YOU HAVE ONLY") + print ( S,"BUSHELS OF GRAIN. NOW THEN,") +def NationalFink(): + print ( "DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY") + print ( "BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE") + print ( "ALSO BEEN DECLARED NATIONAL FINK!!!!") + +def B_input(promptstring): #emulate BASIC input. It rejects non-numeric values + x=input(promptstring) + while x.isalpha(): + x=input("?REDO FROM START\n? ") + return int(x) + +from random import random +from random import seed +seed() +title = "HAMURABI" +title = title.rjust(32,' ') +print (title) +attribution = "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" +attribution = attribution.rjust(15," ") +print (attribution) +print ('\n\n\n') +print ("TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA") +print ("FOR A TEN-YEAR TERM OF OFFICE.\n") +D1=0 +P1=0 +Z=0 #year +P=95 #population +S=2800 #grain stores +H=3000 +E=H-S #rats eaten +Y=3 #yield (amount of production from land). Reused as price per acre +A=H/Y #acres of land +I=5 #immigrants +Q=1 #boolean for plague, also input for buy/sell land +D=0 # people +while (Z<11): #line 270. main loop. while the year is less than 11 + print ("\n\n\nHAMURABI: I BEG TO REPORT TO YOU") + Z=Z+1 #year + print ( "IN YEAR",Z,",",D,"PEOPLE STARVED,",I,"CAME TO THE CITY,") + P=P+I + if Q==0: + P=int(P/2) + print ("A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED.") + print ("POPULATION IS NOW",P) + print ("THE CITY NOW OWNS",A,"ACRES.") + print ("YOU HARVESTED",Y,"BUSHELS PER ACRE.") + print ("THE RATS ATE",E,"BUSHELS.") + print ("YOU NOW HAVE ",S,"BUSHELS IN STORE.\n") + C=int(10*random()) #random number between 1 and 10 + Y=C+17 + print ("LAND IS TRADING AT",Y,"BUSHELS PER ACRE.") + Q=-99 #dummy value to track status + while Q==-99: #always run the loop once + Q = B_input("HOW MANY ACRES DO YOU WISH TO BUY? ") + if Q<0: + Q = -1 #to avoid the corner case of Q=-99 + BadInput850() + Z=99 #jump out of main loop and exit + elif Y*Q>S: #can't afford it + BadInput710(S) + Q=-99 # give'm a second change to get it right + elif Y*Q<=S: #normal case, can afford it + A=A+Q #increase the number of acres by Q + S=S-Y*Q #decrease the amount of grain in store to pay for it + C=0 #WTF is C for? + if Q ==0 and Z!=99: #maybe you want to sell some land? + Q = -99 + while Q==-99: + Q = B_input( "HOW MANY ACRES DO YOU WISH TO SELL? ") + if Q<0: + BadInput850() + Z=99 #jump out of main loop and exit + elif Q<=A:#normal case + A=A-Q # reduce the acres + S=S+Y*Q #add to grain stores + C=0 #still don't know what C is for + else: #Q>A error! + BadInput720() + Q=-99 #reloop + print ("\n") + Q=-99 + while Q==-99 and Z!=99: + Q = B_input("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? ") + if Q<0: + BadInput850() + #REM *** TRYING TO USE MORE GRAIN THAN IS IN SILOS? + elif Q>S: + BadInput710 + Q=-99 #try again! + else: #we're good. do the transaction + S=S-Q #remove the grain from the stores + C=1 #set the speed of light to 1. jk + print ("\n") + D=-99 #dummy value to force at least one loop + while D == -99 and Z!=99: + D = B_input("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? ") + if D<0: + BadInput850() + Z=99 + elif D>0: + if D>A: + #REM *** TRYING TO PLANT MORE ACRES THAN YOU OWN? + BadInput720(A) + D = -99 + elif int(D/2)>S: + #REM *** ENOUGH GRAIN FOR SEED? + BadInput710(S) + D = -99 + elif D>=10*P: + #REM *** ENOUGH PEOPLE TO TEND THE CROPS? + print ("BUT YOU HAVE ONLY",P,"PEOPLE TO TEND THE FIELDS! NOW THEN,") + D=-99 + else: #we're good. decrement the grain store + S=S-int(D/2) + GenRandom(C) + #REM *** A BOUNTIFUL HARVEST! + Y=C + H=D*Y + E=0 + GenRandom(C) + if int(C/2)==C/2: #even number. 50/50 chance + #REM *** RATS ARE RUNNING WILD!! + E=int(S/C) #calc losses due to rats, based on previous random number + S=S-E+H #deduct losses from stores + GenRandom(C) + #REM *** LET'S HAVE SOME BABIES + I=int(C*(20*A+S)/P/100+1) + #REM *** HOW MANY PEOPLE HAD FULL TUMMIES? + C=int(Q/20) + #REM *** HORROS, A 15% CHANCE OF PLAGUE + #yeah, should be HORRORS, but left it + Q=int(10*(2*random()-.3)) + if P>=C and Z!=99: #if there are some people without full bellies... + #REM *** STARVE ENOUGH FOR IMPEACHMENT? + D=P-C + if D>.45*P: + print ("\nYOU STARVED",D,"PEOPLE IN ONE YEAR!!!") + NationalFink() + Z=99 #exit the loop + P1=((Z-1)*P1+D*100/P)/Z + P=C + D1=D1+D +if Z!=99: + print ( "IN YOUR 10-YEAR TERM OF OFFICE,",P1,"PERCENT OF THE") + print ( "POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF") + print ( D1,"PEOPLE DIED!!") + L=A/P + print ( "YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH") + print ( L,"ACRES PER PERSON.\n") + if (P1>33 or L<7): + NationalFink() + elif (P1>10 or L<9): + print ( "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.") + print ( "THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,") + print ( "FRANKLY, HATE YOUR GUTS!!") + elif (P1>3 or L<10): + print ( "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT") + print ( "REALLY WASN'T TOO BAD AT ALL. ",int(P*.8*random()),"PEOPLE") + print ( "WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR") + print ( "TRIVIAL PROBLEMS.") + else: + print ( "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND") + print ( "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!\n") + for N in range(1,10): + print ( '\a') +print("\nSO LONG FOR NOW.\n") + + + From 4e0559a193f0791d2b7aae794faba3f67286941e Mon Sep 17 00:00:00 2001 From: nanochess <biyubi@gmail.com> Date: Sat, 27 Feb 2021 17:39:48 -0600 Subject: [PATCH 054/749] Ported POETRY to Javascript --- 70 Poetry/javascript/poetry.html | 9 ++ 70 Poetry/javascript/poetry.js | 173 +++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 70 Poetry/javascript/poetry.html create mode 100644 70 Poetry/javascript/poetry.js diff --git a/70 Poetry/javascript/poetry.html b/70 Poetry/javascript/poetry.html new file mode 100644 index 00000000..01dd59bf --- /dev/null +++ b/70 Poetry/javascript/poetry.html @@ -0,0 +1,9 @@ +<html> +<head> +<title>POETRY + + +


+
+
+
diff --git a/70 Poetry/javascript/poetry.js b/70 Poetry/javascript/poetry.js
new file mode 100644
index 00000000..885f1921
--- /dev/null
+++ b/70 Poetry/javascript/poetry.js	
@@ -0,0 +1,173 @@
+// POETRY
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(30) + "POETRY\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    
+    times = 0;
+    
+    i = 1;
+    j = 1;
+    k = 0;
+    u = 0;
+    while (1) {
+        if (j == 1) {
+            switch (i) {
+                case 1:
+                    print("MIDNIGHT DREARY");
+                    break;
+                case 2:
+                    print("FIERY EYES");
+                    break;
+                case 3:
+                    print("BIRD OF FIEND");
+                    break;
+                case 4:
+                    print("THING OF EVIL");
+                    break;
+                case 5:
+                    print("PROPHET");
+                    break;
+            }
+        } else if (j == 2) {
+            switch (i) {
+                case 1:
+                    print("BEGUILING ME");
+                    u = 2;
+                    break;
+                case 2:
+                    print("THRILLED ME");
+                    break;
+                case 3:
+                    print("STILL SITTING....");
+                    u = 0;
+                    break;
+                case 4:
+                    print("NEVER FLITTING");
+                    u = 2;
+                    break;
+                case 5:
+                    print("BURNED");
+                    break;
+            }
+        } else if (j == 3) {
+            switch (i) {
+                case 1:
+                    print("AND MY SOUL");
+                    break;
+                case 2:
+                    print("DARKNESS THERE");
+                    break;
+                case 3:
+                    print("SHALL BE LIFTED");
+                    break;
+                case 4:
+                    print("QUOTH THE RAVEN");
+                    break;
+                case 5:
+                    if (u == 0)
+                        break;
+                    print("SIGN OF PARTING");
+                    break;
+            }
+        } else if (j == 4) {
+            switch (i) {
+                case 1:
+                    print("NOTHING MORE");
+                    break;
+                case 2:
+                    print("YET AGAIN");
+                    break;
+                case 3:
+                    print("SLOWLY CREEPING");
+                    break;
+                case 4:
+                    print("...EVERMORE");
+                    break;
+                case 5:
+                    print("NEVERMORE");
+                    break;
+            }
+        }
+        if (u != 0 && Math.random() <= 0.19) {
+            print(",");
+            u = 2;
+        }
+        if (Math.random() <= 0.65) {
+            print(" ");
+            u++;
+        } else {
+            print("\n");
+            u = 0;
+        }
+        while (1) {
+            i = Math.floor(Math.floor(10 * Math.random()) / 2) + 1;
+            j++;
+            k++;
+            if (u == 0 && j % 2 == 0)
+                print("     ");
+            if (j != 5)
+                break;
+            j = 0;
+            print("\n");
+            if (k <= 20)
+                continue;
+            print("\n");
+            u = 0;
+            k = 0;
+            j = 2;
+            break;
+        }
+        if (u == 0 && k == 0 && j == 2 && ++times == 10)
+            break;
+    }
+}
+
+main();

From 6fb0b5c01fd909961864a44657bc11dfa1bbbcb5 Mon Sep 17 00:00:00 2001
From: epvanhouten 
Date: Sat, 27 Feb 2021 17:46:24 -0600
Subject: [PATCH 055/749] Literal conversion of original

Just taking the original BASIC program and converting it into C# without
adding types or modernizing the control flow.
---
 51 Hurkle/csharp/src/hurkle/Program.cs | 107 +++++++++++++++++++++++--
 1 file changed, 101 insertions(+), 6 deletions(-)

diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51 Hurkle/csharp/src/hurkle/Program.cs
index a9cd0f60..9e768b08 100644
--- a/51 Hurkle/csharp/src/hurkle/Program.cs	
+++ b/51 Hurkle/csharp/src/hurkle/Program.cs	
@@ -11,8 +11,16 @@ namespace hurkle
             10 PRINT TAB(33);"HURKLE"
             20 PRINT TAB(15);"CREATIVE COMPUTING NORRISTOWN, NEW JERSEY"
             30 PRINT;PRINT;PRINT
+            */
+            Console.WriteLine(new string(' ', 33) + @"HURKLE");
+            Console.WriteLine(new string(' ', 15) + @"CREATIVE COMPUTING NORRISTOWN, NEW JERSEY");
+            /*
             110 N=5
             120 G=10
+            */
+            var N=5;
+            var G=10;
+            /*
             210 PRINT
             220 PRINT "A HURKLE IS HIDING ON A";G;"BY";G;"GRID. HOMEBASE"
             230 PRINT "ON THE GRID IS POINT 0,0 AND ANY GRIDPOINT IS A"
@@ -21,8 +29,31 @@ namespace hurkle
             260 PRINT "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
             270 PRINT "DIRECTION TO GO TO LOOK FOR THE HURKLE."
             280 PRINT
+            */
+            // Using string formatting via the '$' string
+            Console.WriteLine();
+            Console.WriteLine($"A HURKLE IS HIDING ON A {G} BY {G} GRID. HOMEBASE");
+            Console.WriteLine(@"ON THE GRID IS POINT 0,0 AND ANY GRIDPOINT IS A");
+            Console.WriteLine(@"PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. TRY TO");
+            Console.WriteLine($"GUESS THE HURKLE'S GRIDPOINT. YOU GET {N} TRIES.");
+            Console.WriteLine(@"AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE");
+            Console.WriteLine(@"DIRECTION TO GO TO LOOK FOR THE HURKLE.");
+            Console.WriteLine();
+            
+            /*
             285 A=INT(G*RND(1))
             286 B=INT(G*RND(1))
+            */
+            // Get a pseudo number generator
+            var randomSource = new Random();
+            START:
+            // BASIC program was generating a float between 0 and 1
+            // then multiplying by the size of the grid to to a number
+            // between 1 and 10. C# allows you to do that directly.
+            var A = randomSource.Next(0,G);
+            var B = randomSource.Next(0,G);
+            
+            /*
             310 FOR K=1 TO N
             320 PRINT "GUESS #";K;
             330 INPUT X,Y
@@ -31,31 +62,95 @@ namespace hurkle
             360 GOSUB 610
             370 PRINT
             380 NEXT K
+            */
+            for(var K=1;K<=N;K++)
+            {
+                Console.WriteLine($"GUESS #{K}");
+                var inputLine = Console.ReadLine();
+                var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries);
+                var X = int.Parse(seperateStrings[0]);
+                var Y = int.Parse(seperateStrings[1]);
+                if(Math.Abs(X-A) + Math.Abs(Y-B) == 0)
+                {
+                    /*
+                    500 REM
+                    510 PRINT
+                    520 PRINT "YOU FOUND HIM IN";K;GUESSES!"
+                    540 GOTO 440
+                    */
+                    Console.WriteLine();
+                    Console.WriteLine($"YOU FOUND HIM IN {K} GUESSES!");
+                    goto END;
+                }
+
+                PrintInfo(X,Y,A,B);
+            }
+            
+            /*
             410 PRINT
             420 PRINT "SORRY, THAT'S;N;"GUESSES."
             430 PRINT "THE HURKLE IS AT ";A;",";B
+            */
+            Console.WriteLine();
+            Console.WriteLine($"SORRY, THAT'S {N} GUESSES");
+            Console.WriteLine($"THE HURKLE IS AT {A},{B}");
+            /*
             440 PRINT
             450 PRINT "LET'S PLAY AGAIN. HURKLE IS HIDING."
             460 PRINT
             470 GOTO 285
-            500 REM
-            510 PRINT
-            520 PRINT "YOU FOUND HIM IN";K;GUESSES!"
-            540 GOTO 440
+            */
+            END:
+            Console.WriteLine();
+            Console.WriteLine("LET'S PLAY AGAIN. HURKLE IS HIDING");
+            Console.WriteLine();
+            goto START;
+            
+            /*
+            999 END
+            */
+        }
+
+        private static void PrintInfo(int X, int Y, int A, int B)
+        {
+            
+            /*
             610 PRINT "GO ";
+            */
+            Console.Write("GO ");
+            /*
             620 IF Y=B THEN 670
             630 IF YB)
+            {
+                Console.Write("SOUTH");
+            }else if(YA)
+            {
+                Console.Write("WEST");
+            }
+
+            Console.WriteLine();
+            /*
             720 PRINT
             730 RETURN
-            999 END
             */
         }
     }

From f55fafbb3393e30d332c095ec83e69ee70b58e45 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 27 Feb 2021 18:08:32 -0600
Subject: [PATCH 056/749] Ported REVERSE to Javascript

---
 73 Reverse/javascript/reverse.html |   9 ++
 73 Reverse/javascript/reverse.js   | 159 +++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)
 create mode 100644 73 Reverse/javascript/reverse.html
 create mode 100644 73 Reverse/javascript/reverse.js

diff --git a/73 Reverse/javascript/reverse.html b/73 Reverse/javascript/reverse.html
new file mode 100644
index 00000000..3abddb0e
--- /dev/null
+++ b/73 Reverse/javascript/reverse.html	
@@ -0,0 +1,9 @@
+
+
+REVERSE
+
+
+

+
+
+
diff --git a/73 Reverse/javascript/reverse.js b/73 Reverse/javascript/reverse.js
new file mode 100644
index 00000000..44937b51
--- /dev/null
+++ b/73 Reverse/javascript/reverse.js	
@@ -0,0 +1,159 @@
+// REVERSE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a = [];
+var n;
+
+// Subroutine to print the rules
+function print_rules()
+{
+    print("\n");
+    print("THIS IS THE GAME OF 'REVERSE'.  TO WIN, ALL YOU HAVE\n");
+    print("TO DO IS ARRANGE A LIST OF NUMBERS (1 THROUGH " + n + ")\n");
+    print("IN NUMERICAL ORDER FROM LEFT TO RIGHT.  TO MOVE, YOU\n");
+    print("TELL ME HOW MANY NUMBERS (COUNTING FROM THE LEFT) TO\n");
+    print("REVERSE.  FOR EXAMPLE, IF THE CURRENT LIST IS:\n");
+    print("\n");
+    print("2 3 4 5 1 6 7 8 9\n");
+    print("\n");
+    print("AND YOU REVERSE 4, THE RESULT WILL BE:\n");
+    print("\n");
+    print("5 4 3 2 1 6 7 8 9\n");
+    print("\n");
+    print("NOW IF YOU REVERSE 5, YOU WIN!\n");
+    print("\n");
+    print("1 2 3 4 5 6 7 8 9\n");
+    print("\n");
+    print("NO DOUBT YOU WILL LIKE THIS GAME, BUT\n");
+    print("IF YOU WANT TO QUIT, REVERSE 0 (ZERO).\n");
+    print("\n");
+}
+
+// Subroutine to print list
+function print_list()
+{
+    print("\n");
+    for (k = 1; k <= n; k++)
+        print(" " + a[k] + " ");
+    print("\n");
+    print("\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(32) + "REVERSE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("REVERSE -- A GAME OF SKILL\n");
+    print("\n");
+    for (i = 0; i <= 20; i++)
+        a[i] = 0;
+    // *** N=NUMBER OF NUMBER
+    n = 9;
+    print("DO YOU WANT THE RULES");
+    str = await input();
+    if (str != "NO")
+        print_rules();
+    while (1) {
+        // *** Make a random list a(1) to a(n)
+        a[1] = Math.floor((n - 1) * Math.random() + 2);
+        for (k = 2; k <= n; k++) {
+            do {
+                a[k] = Math.floor(n * Math.random() + 1);
+                for (j = 1; j <= k - 1; j++) {
+                    if (a[k] == a[j])
+                        break;
+                }
+            } while (j <= k - 1) ;
+        }
+        // *** Print original list and start game
+        print("\n");
+        print("HERE WE GO ... THE LIST IS:\n");
+        t = 0;
+        print_list();
+        while (1) {
+            while (1) {
+                print("HOW MANY SHALL I REVERSE");
+                r = parseInt(await input());
+                if (r == 0)
+                    break;
+                if (r <= n)
+                    break;
+                print("OOPS! TOO MANY! I CAN REVERSE AT MOST " + n + "\n");
+            }
+            if (r == 0)
+                break;
+            t++;
+            // *** Reverse r numbers and print new list
+            for (k = 1; k <= Math.floor(r / 2); k++) {
+                z = a[k];
+                a[k] = a[r - k + 1];
+                a[r - k + 1] = z;
+            }
+            print_list();
+            // *** Check for a win
+            for (k = 1; k <= n; k++) {
+                if (a[k] != k)
+                    break;
+            }
+            if (k > n) {
+                print("YOU WON IT IN " + t + " MOVES!!!\n");
+                print("\n");
+                break;
+            }
+        }
+        print("\n");
+        print("TRY AGAIN (YES OR NO)");
+        str = await input();
+        if (str != "YES")
+            break;
+    }
+    print("\n");
+    print("O.K. HOPE YOU HAD FUN!!\n");
+}
+
+main();

From b77b7438cd73722350265b3973d51e204c4eb803 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Sun, 28 Feb 2021 11:20:00 +1030
Subject: [PATCH 057/749] Java version of Synonym

---
 85 Synonym/java/src/Synonym.java     | 137 +++++++++++++++++++++++++++
 85 Synonym/java/src/SynonymGame.java |   6 ++
 85 Synonym/java/src/SynonymList.java |  46 +++++++++
 3 files changed, 189 insertions(+)
 create mode 100644 85 Synonym/java/src/Synonym.java
 create mode 100644 85 Synonym/java/src/SynonymGame.java
 create mode 100644 85 Synonym/java/src/SynonymList.java

diff --git a/85 Synonym/java/src/Synonym.java b/85 Synonym/java/src/Synonym.java
new file mode 100644
index 00000000..2804bb49
--- /dev/null
+++ b/85 Synonym/java/src/Synonym.java	
@@ -0,0 +1,137 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Synonym
+ * 

+ * Based on the Basic game of Synonym here + * https://github.com/coding-horror/basic-computer-games/blob/main/85%20Synonym/synonym.bas + *

+ * 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 Synonym { + + public static final String[] RANDOM_ANSWERS = {"RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"}; + + // Used for keyboard input + private final Scanner kbScanner; + + // List of words and synonyms + private final ArrayList synonyms; + + private enum GAME_STATE { + INIT, + PLAY, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private int currentQuestion; + + public Synonym() { + + kbScanner = new Scanner(System.in); + synonyms = new ArrayList<>(); + + gameState = GAME_STATE.INIT; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case INIT: + intro(); + currentQuestion = 0; + + // Load data + synonyms.add(new SynonymList("FIRST", new String[]{"START", "BEGINNING", "ONSET", "INITIAL"})); + synonyms.add(new SynonymList("SIMILAR", new String[]{"SAME", "LIKE", "RESEMBLING"})); + synonyms.add(new SynonymList("MODEL", new String[]{"PATTERN", "PROTOTYPE", "STANDARD", "CRITERION"})); + synonyms.add(new SynonymList("SMALL", new String[]{"INSIGNIFICANT", "LITTLE", "TINY", "MINUTE"})); + synonyms.add(new SynonymList("STOP", new String[]{"HALT", "STAY", "ARREST", "CHECK", "STANDSTILL"})); + synonyms.add(new SynonymList("HOUSE", new String[]{"DWELLING", "RESIDENCE", "DOMICILE", "LODGING", "HABITATION"})); + synonyms.add(new SynonymList("PIT", new String[]{"HOLE", "HOLLOW", "WELL", "GULF", "CHASM", "ABYSS"})); + synonyms.add(new SynonymList("PUSH", new String[]{"SHOVE", "THRUST", "PROD", "POKE", "BUTT", "PRESS"})); + synonyms.add(new SynonymList("RED", new String[]{"ROUGE", "SCARLET", "CRIMSON", "FLAME", "RUBY"})); + synonyms.add(new SynonymList("PAIN", new String[]{"SUFFERING", "HURT", "MISERY", "DISTRESS", "ACHE", "DISCOMFORT"})); + + gameState = GAME_STATE.PLAY; + break; + + case PLAY: + + // Get the word and synonyms to ask a question about + SynonymList synonym = synonyms.get(currentQuestion); + String getAnswer = displayTextAndGetInput(" WHAT IS A SYNONYM OF " + synonym.getWord() + " ? "); + + // HELP is used to give a random synonym for the current word + if (getAnswer.equals("HELP")) { + int randomSynonym = (int) (Math.random() * synonym.size()); + System.out.println("**** A SYNONYM OF " + synonym.getWord() + " IS " + synonym.getSynonyms()[randomSynonym] + "."); + } else { + // Check if the entered word is in the synonym list + if (synonym.exists(getAnswer)) { + // If it is, give a random "correct" response + System.out.println(RANDOM_ANSWERS[(int) (Math.random() * RANDOM_ANSWERS.length)]); + currentQuestion++; + // Have we reached the final word/synonyms on file? + if (currentQuestion == synonyms.size()) { + // We have so end game. + System.out.println("SYNONYM DRILL COMPLETED."); + gameState = GAME_STATE.GAME_OVER; + } + } else { + // Word does not exist in the synonym list + System.out.println("TRY AGAIN."); + } + } + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(33) + "SYNONYM"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH"); + System.out.println("LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME"); + System.out.println(" MEANING."); + System.out.println("I CHOOSE A WORD -- YOU TYPE A SYNONYM."); + System.out.println("IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP'"); + System.out.println("AND I WILL TELL YOU A SYNONYM."); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to uppercase. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next().toUpperCase(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } +} diff --git a/85 Synonym/java/src/SynonymGame.java b/85 Synonym/java/src/SynonymGame.java new file mode 100644 index 00000000..8ad52f4b --- /dev/null +++ b/85 Synonym/java/src/SynonymGame.java @@ -0,0 +1,6 @@ +public class SynonymGame { + public static void main(String[] args) { + Synonym synonym = new Synonym(); + synonym.play(); + } +} diff --git a/85 Synonym/java/src/SynonymList.java b/85 Synonym/java/src/SynonymList.java new file mode 100644 index 00000000..d692d48a --- /dev/null +++ b/85 Synonym/java/src/SynonymList.java @@ -0,0 +1,46 @@ +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Stores a word and a list of synonyms for that word + */ +public class SynonymList { + + private final String word; + + private final ArrayList synonyms; + + public SynonymList(String word, String[] synonyms) { + this.word = word; + this.synonyms = new ArrayList<>(Arrays.asList(synonyms)); + } + + /** + * Check if the word passed to this method exists in the list of synonyms + * N.B. Case insensitive + * + * @param word word to search for + * @return true if found, otherwise false + */ + public boolean exists(String word) { + return synonyms.stream().anyMatch(str -> str.equalsIgnoreCase(word)); + } + + public String getWord() { + return word; + } + + public int size() { + return synonyms.size(); + } + + /** + * Returns all synonyms for this word in string array format + * + * @return + */ + public String[] getSynonyms() { + // Parameter to toArray method determines type of the resultant array + return synonyms.toArray(new String[0]); + } +} From 843ee97e9fa6a92520c81c4acc1aa8cedc45747f Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Sun, 28 Feb 2021 11:24:14 +1030 Subject: [PATCH 058/749] Revert "Merge branch 'main' of https://github.com/journich/basic-computer-games into main" This reverts commit 913bc1b91ffa84bfed62457470ee3c933f73fd21, reversing changes made to b77b7438cd73722350265b3973d51e204c4eb803. --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0bbe112f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ + +.DS_Store +*.iml +.idea +out From 75e7e25a056df3fe6bf1e698e864516b6b79eaf5 Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 18:02:47 -0600 Subject: [PATCH 059/749] Introduce game class Cleanup uses of goto and encapsulate game logic. --- 51 Hurkle/csharp/src/hurkle/HurkleGame.cs | 111 ++++++++++++++++++++ 51 Hurkle/csharp/src/hurkle/Program.cs | 117 ++-------------------- 2 files changed, 118 insertions(+), 110 deletions(-) create mode 100644 51 Hurkle/csharp/src/hurkle/HurkleGame.cs diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs new file mode 100644 index 00000000..7abeaad5 --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs @@ -0,0 +1,111 @@ +using System; + +namespace hurkle +{ + public class HurkleGame + { + private readonly Random _random = new Random(); + private readonly int guesses; + private readonly int gridSize; + + public HurkleGame(int guesses, int gridSize) + { + this.guesses = guesses; + this.gridSize = gridSize; + } + + public void PlayGame() + { + // BASIC program was generating a float between 0 and 1 + // then multiplying by the size of the grid to to a number + // between 1 and 10. C# allows you to do that directly. + var A = _random.Next(0,gridSize); + var B = _random.Next(0,gridSize); + + /* + 310 FOR K=1 TO N + 320 PRINT "GUESS #";K; + 330 INPUT X,Y + 340 IF ABS(X-A)+ABS(Y-B)=0 THEN 500 + 350 REM PRINT INFO + 360 GOSUB 610 + 370 PRINT + 380 NEXT K + */ + for(var K=1;K<=guesses;K++) + { + Console.WriteLine($"GUESS #{K}"); + var inputLine = Console.ReadLine(); + var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); + var X = int.Parse(seperateStrings[0]); + var Y = int.Parse(seperateStrings[1]); + if(Math.Abs(X-A) + Math.Abs(Y-B) == 0) + { + /* + 500 REM + 510 PRINT + 520 PRINT "YOU FOUND HIM IN";K;GUESSES!" + 540 GOTO 440 + */ + Console.WriteLine(); + Console.WriteLine($"YOU FOUND HIM IN {K} GUESSES!"); + return; + } + + PrintInfo(X,Y,A,B); + } + + /* + 410 PRINT + 420 PRINT "SORRY, THAT'S;N;"GUESSES." + 430 PRINT "THE HURKLE IS AT ";A;",";B + */ + Console.WriteLine(); + Console.WriteLine($"SORRY, THAT'S {guesses} GUESSES"); + Console.WriteLine($"THE HURKLE IS AT {A},{B}"); + } + + private static void PrintInfo(int X, int Y, int A, int B) + { + + /* + 610 PRINT "GO "; + */ + Console.Write("GO "); + /* + 620 IF Y=B THEN 670 + 630 IF YB) + { + Console.Write("SOUTH"); + }else if(YA) + { + Console.Write("WEST"); + } + + Console.WriteLine(); + /* + 720 PRINT + 730 RETURN + */ + } + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51 Hurkle/csharp/src/hurkle/Program.cs index 9e768b08..447fa547 100644 --- a/51 Hurkle/csharp/src/hurkle/Program.cs +++ b/51 Hurkle/csharp/src/hurkle/Program.cs @@ -39,119 +39,16 @@ namespace hurkle Console.WriteLine(@"AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"); Console.WriteLine(@"DIRECTION TO GO TO LOOK FOR THE HURKLE."); Console.WriteLine(); - - /* - 285 A=INT(G*RND(1)) - 286 B=INT(G*RND(1)) - */ - // Get a pseudo number generator - var randomSource = new Random(); - START: - // BASIC program was generating a float between 0 and 1 - // then multiplying by the size of the grid to to a number - // between 1 and 10. C# allows you to do that directly. - var A = randomSource.Next(0,G); - var B = randomSource.Next(0,G); - - /* - 310 FOR K=1 TO N - 320 PRINT "GUESS #";K; - 330 INPUT X,Y - 340 IF ABS(X-A)+ABS(Y-B)=0 THEN 500 - 350 REM PRINT INFO - 360 GOSUB 610 - 370 PRINT - 380 NEXT K - */ - for(var K=1;K<=N;K++) - { - Console.WriteLine($"GUESS #{K}"); - var inputLine = Console.ReadLine(); - var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); - var X = int.Parse(seperateStrings[0]); - var Y = int.Parse(seperateStrings[1]); - if(Math.Abs(X-A) + Math.Abs(Y-B) == 0) - { - /* - 500 REM - 510 PRINT - 520 PRINT "YOU FOUND HIM IN";K;GUESSES!" - 540 GOTO 440 - */ - Console.WriteLine(); - Console.WriteLine($"YOU FOUND HIM IN {K} GUESSES!"); - goto END; - } - PrintInfo(X,Y,A,B); - } - - /* - 410 PRINT - 420 PRINT "SORRY, THAT'S;N;"GUESSES." - 430 PRINT "THE HURKLE IS AT ";A;",";B - */ - Console.WriteLine(); - Console.WriteLine($"SORRY, THAT'S {N} GUESSES"); - Console.WriteLine($"THE HURKLE IS AT {A},{B}"); - /* - 440 PRINT - 450 PRINT "LET'S PLAY AGAIN. HURKLE IS HIDING." - 460 PRINT - 470 GOTO 285 - */ - END: - Console.WriteLine(); - Console.WriteLine("LET'S PLAY AGAIN. HURKLE IS HIDING"); - Console.WriteLine(); - goto START; - - /* - 999 END - */ - } + var hurkle = new HurkleGame(N,G); + while(true) + { + hurkle.PlayGame(); - private static void PrintInfo(int X, int Y, int A, int B) - { - - /* - 610 PRINT "GO "; - */ - Console.Write("GO "); - /* - 620 IF Y=B THEN 670 - 630 IF YB) - { - Console.Write("SOUTH"); - }else if(YA) - { - Console.Write("WEST"); - } - - Console.WriteLine(); - /* - 720 PRINT - 730 RETURN - */ } } } From 09436ff686e2d346d9a75d6ff5ed6d677cb99d63 Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 19:08:56 -0600 Subject: [PATCH 060/749] Add a bailout Forcing a SIGKILL is bad form, give some UI for playing again or bailing. --- 51 Hurkle/csharp/src/hurkle/Program.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51 Hurkle/csharp/src/hurkle/Program.cs index 447fa547..4c4040b7 100644 --- a/51 Hurkle/csharp/src/hurkle/Program.cs +++ b/51 Hurkle/csharp/src/hurkle/Program.cs @@ -45,9 +45,18 @@ namespace hurkle { hurkle.PlayGame(); - Console.WriteLine(); - Console.WriteLine("LET'S PLAY AGAIN. HURKLE IS HIDING"); - Console.WriteLine(); + Console.WriteLine("PLAY AGAIN? (Y)ES/(N)O"); + var playAgainResponse = Console.ReadLine(); + if(playAgainResponse.Trim().StartsWith("y", StringComparison.InvariantCultureIgnoreCase)) + { + Console.WriteLine(); + Console.WriteLine("LET'S PLAY AGAIN. HURKLE IS HIDING"); + Console.WriteLine(); + }else{ + Console.WriteLine("THANKS FOR PLAYING!"); + break; + } + } } } From c472ebb5c8921de5f92fbda8f08af23aab9d7a3b Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Sat, 27 Feb 2021 17:19:21 -0800 Subject: [PATCH 061/749] Ported DIAMOND to Python added more descriptive variable names --- 32 Diamond/python/diamond.py | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 32 Diamond/python/diamond.py diff --git a/32 Diamond/python/diamond.py b/32 Diamond/python/diamond.py new file mode 100644 index 00000000..a622eb58 --- /dev/null +++ b/32 Diamond/python/diamond.py @@ -0,0 +1,64 @@ +""" +DIAMOND + +Prints pretty diamond patterns to the screen. + +Ported by Dave LeCompte +""" + + +def print_with_tab(space_count, msg): + if space_count > 0: + spaces = " " * space_count + else: + spaces = "" + print(spaces + msg) + + +def print_diamond(begin_width, end_width, step, width, count): + edgeString = "CC" + fill = "!" + + n = begin_width + while True: + line_buffer = " " * ((width - n) // 2) + for across in range(count): + for a in range(n): + if a >= len(edgeString): + line_buffer += fill + else: + line_buffer += edgeString[a] + line_buffer += " " * ( + (width * (across + 1) + (width - n) // 2) - len(line_buffer) + ) + print(line_buffer) + if n == end_width: + return + n += step + + +def main(): + print_with_tab(33, "DIAMOND") + print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + print("FOR A PRETTY DIAMOND PATTERN,") + print("TYPE IN AN ODD NUMBER BETWEEN 5 AND 21") + width = int(input()) + print() + + PAGE_WIDTH = 60 + + count = int(PAGE_WIDTH / width) + + for down in range(count): + print_diamond(1, width, 2, width, count) + print_diamond(width - 2, 1, -2, width, count) + + print() + print() + + +if __name__ == "__main__": + main() From 8f613a02374dbf2b400b9512ad3f823625c9113f Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 19:19:32 -0600 Subject: [PATCH 062/749] Introduce domain object for ponts Game is centered around comparing an X,Y point to another X,Y point. Introduced a domain object to represent that pairing. --- 51 Hurkle/csharp/src/hurkle/HurkleGame.cs | 34 +++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs index 7abeaad5..38d1a158 100644 --- a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs +++ b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs @@ -19,8 +19,10 @@ namespace hurkle // BASIC program was generating a float between 0 and 1 // then multiplying by the size of the grid to to a number // between 1 and 10. C# allows you to do that directly. - var A = _random.Next(0,gridSize); - var B = _random.Next(0,gridSize); + var hurklePoint = new GamePoint{ + X = _random.Next(0, gridSize), + Y = _random.Next(0, gridSize) + }; /* 310 FOR K=1 TO N @@ -37,9 +39,11 @@ namespace hurkle Console.WriteLine($"GUESS #{K}"); var inputLine = Console.ReadLine(); var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); - var X = int.Parse(seperateStrings[0]); - var Y = int.Parse(seperateStrings[1]); - if(Math.Abs(X-A) + Math.Abs(Y-B) == 0) + var guessPoint = new GamePoint{ + X = int.Parse(seperateStrings[0]), + Y = int.Parse(seperateStrings[1]) + }; + if(Math.Abs(guessPoint.X-hurklePoint.X) + Math.Abs(guessPoint.Y-hurklePoint.Y) == 0) { /* 500 REM @@ -52,7 +56,7 @@ namespace hurkle return; } - PrintInfo(X,Y,A,B); + PrintInfo(guessPoint,hurklePoint); } /* @@ -62,10 +66,10 @@ namespace hurkle */ Console.WriteLine(); Console.WriteLine($"SORRY, THAT'S {guesses} GUESSES"); - Console.WriteLine($"THE HURKLE IS AT {A},{B}"); + Console.WriteLine($"THE HURKLE IS AT {hurklePoint.X},{hurklePoint.Y}"); } - private static void PrintInfo(int X, int Y, int A, int B) + private static void PrintInfo(GamePoint guess, GamePoint target) { /* @@ -79,10 +83,10 @@ namespace hurkle 650 GO TO 670 660 PRINT "NORTH"; */ - if(Y>B) + if(guess.Y>target.Y) { Console.Write("SOUTH"); - }else if(YA) + }else if(guess.X>target.X) { Console.Write("WEST"); } @@ -107,5 +111,11 @@ namespace hurkle 730 RETURN */ } + + private class GamePoint + { + public int X {get;init;} + public int Y {get;init;} + } } } \ No newline at end of file From 56f2770d740578198c0ced822ceca534d10b0c19 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Sun, 28 Feb 2021 11:55:35 +1030 Subject: [PATCH 063/749] Revert "Java version of Slots" This reverts commit 3a902ffd6444aa4a9b9c77c022861bf5a405f0e0. --- .gitignore | 5 - 80 Slots/java/src/Slots.java | 297 ------------------------------- 80 Slots/java/src/SlotsGame.java | 6 - 3 files changed, 308 deletions(-) delete mode 100644 80 Slots/java/src/Slots.java delete mode 100644 80 Slots/java/src/SlotsGame.java diff --git a/.gitignore b/.gitignore index 0bbe112f..e69de29b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +0,0 @@ - -.DS_Store -*.iml -.idea -out diff --git a/80 Slots/java/src/Slots.java b/80 Slots/java/src/Slots.java deleted file mode 100644 index 9d96d94f..00000000 --- a/80 Slots/java/src/Slots.java +++ /dev/null @@ -1,297 +0,0 @@ -import java.util.Arrays; -import java.util.Scanner; - -/** - * Game of Slots - *

- * Based on the Basic game of Slots here - * https://github.com/coding-horror/basic-computer-games/blob/main/80%20Slots/slots.bas - *

- * 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 Slots { - - public static final String[] SLOT_SYMBOLS = {"BAR", "BELL", "ORANGE", "LEMON", "PLUM", "CHERRY"}; - - public static final int NUMBER_SYMBOLS = SLOT_SYMBOLS.length; - - // Jackpot symbol (BAR) - public static final int BAR_SYMBOL = 0; - - // Indicator that the current spin won nothing - public static final int NO_WINNER = -1; - - // Used for keyboard input - private final Scanner kbScanner; - - private enum GAME_STATE { - START_GAME, - ONE_SPIN, - RESULTS, - GAME_OVER - } - - // Current game state - private GAME_STATE gameState; - - // Different types of spin results - private enum WINNINGS { - JACKPOT(100), - TOP_DOLLAR(10), - DOUBLE_BAR(5), - REGULAR(2), - NO_WIN(0); - - private final int multiplier; - - WINNINGS(int mult) { - multiplier = mult; - } - - // No win returns the negative amount of net - // otherwise calculate winnings based on - // multiplier - public int calculateWinnings(int bet) { - - if (multiplier == 0) { - return -bet; - } else { - // Return original bet plus a multipler - // of the win type - return (multiplier * bet) + bet; - } - } - } - - private int playerBalance; - - public Slots() { - - kbScanner = new Scanner(System.in); - gameState = GAME_STATE.START_GAME; - } - - /** - * Main game loop - */ - public void play() { - - int[] slotReel = new int[3]; - - do { - // Results of a single spin - WINNINGS winnings; - - switch (gameState) { - - case START_GAME: - intro(); - playerBalance = 0; - gameState = GAME_STATE.ONE_SPIN; - break; - - case ONE_SPIN: - - int playerBet = displayTextAndGetNumber("YOUR BET? "); - - slotReel[0] = randomSymbol(); - slotReel[1] = randomSymbol(); - slotReel[2] = randomSymbol(); - - // Store which symbol (if any) matches at least one other reel - int whichSymbolWon = winningSymbol(slotReel[0], slotReel[1], slotReel[2]); - - // Display the three randomly drawn symbols - StringBuilder output = new StringBuilder(); - for (int i = 0; i < 3; i++) { - if (i > 0) { - output.append(" "); - } - output.append(SLOT_SYMBOLS[slotReel[i]]); - } - - System.out.println(output); - - // Calculate results - - if (whichSymbolWon == NO_WINNER) { - // No symbols match = nothing won - winnings = WINNINGS.NO_WIN; - } else if (slotReel[0] == slotReel[1] && slotReel[0] == slotReel[2]) { - // Top dollar, 3 matching symbols - winnings = WINNINGS.TOP_DOLLAR; - if (slotReel[0] == BAR_SYMBOL) { - // All 3 symbols are BAR. Jackpot! - winnings = WINNINGS.JACKPOT; - } - } else { - // At this point the remaining options are a regular win - // or a double, since the rest (including not winning) have already - // been checked above. - // Assume a regular win - winnings = WINNINGS.REGULAR; - - // But if it was the BAR symbol that matched, its a double bar - if (slotReel[0] == BAR_SYMBOL) { - winnings = WINNINGS.DOUBLE_BAR; - } - - } - - // Update the players balance with the amount won or lost on this spin - playerBalance += winnings.calculateWinnings(playerBet); - - System.out.println(); - - // Output what happened on this spin - switch (winnings) { - case NO_WIN: - System.out.println("YOU LOST."); - break; - - case REGULAR: - System.out.println("DOUBLE!!"); - System.out.println("YOU WON!"); - break; - - case DOUBLE_BAR: - System.out.println("*DOUBLE BAR*"); - System.out.println("YOU WON!"); - break; - - case TOP_DOLLAR: - System.out.println(); - System.out.println("**TOP DOLLAR**"); - System.out.println("YOU WON!"); - break; - - case JACKPOT: - System.out.println(); - System.out.println("***JACKPOT***"); - System.out.println("YOU WON!"); - break; - - } - - System.out.println("YOUR STANDINGS ARE $" + playerBalance); - - // If player does not elect to play again, show results of session - if (!yesEntered(displayTextAndGetInput("AGAIN? "))) { - gameState = GAME_STATE.RESULTS; - - } - break; - - case RESULTS: - if (playerBalance == 0) { - System.out.println("HEY, YOU BROKE EVEN."); - } else if (playerBalance > 0) { - System.out.println("COLLECT YOUR WINNINGS FROM THE H&M CASHIER."); - } else { - // Lost - System.out.println("PAY UP! PLEASE LEAVE YOUR MONEY ON THE TERMINAL."); - } - - gameState = GAME_STATE.GAME_OVER; - break; - } - } while (gameState != GAME_STATE.GAME_OVER); - } - - private void intro() { - System.out.println(simulateTabs(30) + "SLOTS"); - System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - System.out.println(); - System.out.println("YOU ARE IN THE H&M CASINO,IN FRONT OF ONE OF OUR"); - System.out.println("ONE-ARM BANDITS. BET FROM $1 TO $100."); - System.out.println("TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET."); - } - - /* - * Print a message on the screen, then accept input from Keyboard. - * Converts input to an Integer - * - * @param text message to be displayed on screen. - * @return what was typed by the player. - */ - private int displayTextAndGetNumber(String text) { - return Integer.parseInt(displayTextAndGetInput(text)); - } - - /* - * Print a message on the screen, then accept input from Keyboard. - * - * @param text message to be displayed on screen. - * @return what was typed by the player. - */ - private String displayTextAndGetInput(String text) { - System.out.print(text); - return kbScanner.next(); - } - - /** - * Checks whether player entered Y or YES to a question. - * - * @param text player string from kb - * @return true of Y or YES was entered, otherwise false - */ - private boolean yesEntered(String text) { - return stringIsAnyValue(text, "Y", "YES"); - } - - /** - * 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. - * - * @param text source string - * @param values a range of values to compare against the source string - * @return true if a comparison was found in one of the variable number of strings passed - */ - private boolean stringIsAnyValue(String text, String... values) { - - return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); - } - - /** - * Simulate the old basic tab(xx) command which indented text by xx spaces. - * - * @param spaces number of spaces required - * @return String with number of spaces - */ - private String simulateTabs(int spaces) { - char[] spacesTemp = new char[spaces]; - Arrays.fill(spacesTemp, ' '); - return new String(spacesTemp); - } - - /** - * Find the symbol that won this round i.e. the first reel that matched another reel - * - * @param reel1 reel1 spin result - * @param reel2 reel2 spin result - * @param reel3 reel3 spin result - * @return NO_WINNER if no reels match otherwise an int 0-2 to indicate the reel that matches another - */ - private int winningSymbol(int reel1, int reel2, int reel3) { - if (reel1 == reel2) { - return 0; - } else if (reel1 == reel3) { - return 0; - } else if (reel2 == reel3) { - return 1; - } else { - return NO_WINNER; - } - } - - /** - * Random symbol for a slot wheel - * - * @return number between 0-5 - */ - private int randomSymbol() { - return (int) (Math.random() * NUMBER_SYMBOLS); - } -} diff --git a/80 Slots/java/src/SlotsGame.java b/80 Slots/java/src/SlotsGame.java deleted file mode 100644 index 05617cf7..00000000 --- a/80 Slots/java/src/SlotsGame.java +++ /dev/null @@ -1,6 +0,0 @@ -public class SlotsGame { - public static void main(String[] args) { - Slots slots = new Slots(); - slots.play(); - } -} From 9ed14228f0ef1b793c4e6a759d7e784baacc414f Mon Sep 17 00:00:00 2001 From: Gustavo Carreno Date: Sun, 28 Feb 2021 01:26:55 +0000 Subject: [PATCH 064/749] Moving weekday.py to python/weekday.py --- 95 Weekday/{ => python}/weekday.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 95 Weekday/{ => python}/weekday.py (100%) diff --git a/95 Weekday/weekday.py b/95 Weekday/python/weekday.py similarity index 100% rename from 95 Weekday/weekday.py rename to 95 Weekday/python/weekday.py From 165b0f5cffc637a4aeb90628bcf352e96284c410 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Sun, 28 Feb 2021 12:04:20 +1030 Subject: [PATCH 065/749] Java versions of Slots and Synonym --- 80 Slots/java/src/Slots.java | 297 +++++++++++++++++++++++++++ 80 Slots/java/src/SlotsGame.java | 6 + 85 Synonym/java/src/Synonym.java | 137 ------------ 85 Synonym/java/src/SynonymGame.java | 6 - 85 Synonym/java/src/SynonymList.java | 46 ----- 5 files changed, 303 insertions(+), 189 deletions(-) create mode 100644 80 Slots/java/src/Slots.java create mode 100644 80 Slots/java/src/SlotsGame.java delete mode 100644 85 Synonym/java/src/Synonym.java delete mode 100644 85 Synonym/java/src/SynonymGame.java delete mode 100644 85 Synonym/java/src/SynonymList.java diff --git a/80 Slots/java/src/Slots.java b/80 Slots/java/src/Slots.java new file mode 100644 index 00000000..9d96d94f --- /dev/null +++ b/80 Slots/java/src/Slots.java @@ -0,0 +1,297 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Slots + *

+ * Based on the Basic game of Slots here + * https://github.com/coding-horror/basic-computer-games/blob/main/80%20Slots/slots.bas + *

+ * 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 Slots { + + public static final String[] SLOT_SYMBOLS = {"BAR", "BELL", "ORANGE", "LEMON", "PLUM", "CHERRY"}; + + public static final int NUMBER_SYMBOLS = SLOT_SYMBOLS.length; + + // Jackpot symbol (BAR) + public static final int BAR_SYMBOL = 0; + + // Indicator that the current spin won nothing + public static final int NO_WINNER = -1; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + ONE_SPIN, + RESULTS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + // Different types of spin results + private enum WINNINGS { + JACKPOT(100), + TOP_DOLLAR(10), + DOUBLE_BAR(5), + REGULAR(2), + NO_WIN(0); + + private final int multiplier; + + WINNINGS(int mult) { + multiplier = mult; + } + + // No win returns the negative amount of net + // otherwise calculate winnings based on + // multiplier + public int calculateWinnings(int bet) { + + if (multiplier == 0) { + return -bet; + } else { + // Return original bet plus a multipler + // of the win type + return (multiplier * bet) + bet; + } + } + } + + private int playerBalance; + + public Slots() { + + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() { + + int[] slotReel = new int[3]; + + do { + // Results of a single spin + WINNINGS winnings; + + switch (gameState) { + + case START_GAME: + intro(); + playerBalance = 0; + gameState = GAME_STATE.ONE_SPIN; + break; + + case ONE_SPIN: + + int playerBet = displayTextAndGetNumber("YOUR BET? "); + + slotReel[0] = randomSymbol(); + slotReel[1] = randomSymbol(); + slotReel[2] = randomSymbol(); + + // Store which symbol (if any) matches at least one other reel + int whichSymbolWon = winningSymbol(slotReel[0], slotReel[1], slotReel[2]); + + // Display the three randomly drawn symbols + StringBuilder output = new StringBuilder(); + for (int i = 0; i < 3; i++) { + if (i > 0) { + output.append(" "); + } + output.append(SLOT_SYMBOLS[slotReel[i]]); + } + + System.out.println(output); + + // Calculate results + + if (whichSymbolWon == NO_WINNER) { + // No symbols match = nothing won + winnings = WINNINGS.NO_WIN; + } else if (slotReel[0] == slotReel[1] && slotReel[0] == slotReel[2]) { + // Top dollar, 3 matching symbols + winnings = WINNINGS.TOP_DOLLAR; + if (slotReel[0] == BAR_SYMBOL) { + // All 3 symbols are BAR. Jackpot! + winnings = WINNINGS.JACKPOT; + } + } else { + // At this point the remaining options are a regular win + // or a double, since the rest (including not winning) have already + // been checked above. + // Assume a regular win + winnings = WINNINGS.REGULAR; + + // But if it was the BAR symbol that matched, its a double bar + if (slotReel[0] == BAR_SYMBOL) { + winnings = WINNINGS.DOUBLE_BAR; + } + + } + + // Update the players balance with the amount won or lost on this spin + playerBalance += winnings.calculateWinnings(playerBet); + + System.out.println(); + + // Output what happened on this spin + switch (winnings) { + case NO_WIN: + System.out.println("YOU LOST."); + break; + + case REGULAR: + System.out.println("DOUBLE!!"); + System.out.println("YOU WON!"); + break; + + case DOUBLE_BAR: + System.out.println("*DOUBLE BAR*"); + System.out.println("YOU WON!"); + break; + + case TOP_DOLLAR: + System.out.println(); + System.out.println("**TOP DOLLAR**"); + System.out.println("YOU WON!"); + break; + + case JACKPOT: + System.out.println(); + System.out.println("***JACKPOT***"); + System.out.println("YOU WON!"); + break; + + } + + System.out.println("YOUR STANDINGS ARE $" + playerBalance); + + // If player does not elect to play again, show results of session + if (!yesEntered(displayTextAndGetInput("AGAIN? "))) { + gameState = GAME_STATE.RESULTS; + + } + break; + + case RESULTS: + if (playerBalance == 0) { + System.out.println("HEY, YOU BROKE EVEN."); + } else if (playerBalance > 0) { + System.out.println("COLLECT YOUR WINNINGS FROM THE H&M CASHIER."); + } else { + // Lost + System.out.println("PAY UP! PLEASE LEAVE YOUR MONEY ON THE TERMINAL."); + } + + gameState = GAME_STATE.GAME_OVER; + break; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(30) + "SLOTS"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("YOU ARE IN THE H&M CASINO,IN FRONT OF ONE OF OUR"); + System.out.println("ONE-ARM BANDITS. BET FROM $1 TO $100."); + System.out.println("TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Find the symbol that won this round i.e. the first reel that matched another reel + * + * @param reel1 reel1 spin result + * @param reel2 reel2 spin result + * @param reel3 reel3 spin result + * @return NO_WINNER if no reels match otherwise an int 0-2 to indicate the reel that matches another + */ + private int winningSymbol(int reel1, int reel2, int reel3) { + if (reel1 == reel2) { + return 0; + } else if (reel1 == reel3) { + return 0; + } else if (reel2 == reel3) { + return 1; + } else { + return NO_WINNER; + } + } + + /** + * Random symbol for a slot wheel + * + * @return number between 0-5 + */ + private int randomSymbol() { + return (int) (Math.random() * NUMBER_SYMBOLS); + } +} diff --git a/80 Slots/java/src/SlotsGame.java b/80 Slots/java/src/SlotsGame.java new file mode 100644 index 00000000..05617cf7 --- /dev/null +++ b/80 Slots/java/src/SlotsGame.java @@ -0,0 +1,6 @@ +public class SlotsGame { + public static void main(String[] args) { + Slots slots = new Slots(); + slots.play(); + } +} diff --git a/85 Synonym/java/src/Synonym.java b/85 Synonym/java/src/Synonym.java deleted file mode 100644 index 2804bb49..00000000 --- a/85 Synonym/java/src/Synonym.java +++ /dev/null @@ -1,137 +0,0 @@ -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Scanner; - -/** - * Game of Synonym - *

- * Based on the Basic game of Synonym here - * https://github.com/coding-horror/basic-computer-games/blob/main/85%20Synonym/synonym.bas - *

- * 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 Synonym { - - public static final String[] RANDOM_ANSWERS = {"RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"}; - - // Used for keyboard input - private final Scanner kbScanner; - - // List of words and synonyms - private final ArrayList synonyms; - - private enum GAME_STATE { - INIT, - PLAY, - GAME_OVER - } - - // Current game state - private GAME_STATE gameState; - - private int currentQuestion; - - public Synonym() { - - kbScanner = new Scanner(System.in); - synonyms = new ArrayList<>(); - - gameState = GAME_STATE.INIT; - } - - /** - * Main game loop - */ - public void play() { - - do { - switch (gameState) { - - case INIT: - intro(); - currentQuestion = 0; - - // Load data - synonyms.add(new SynonymList("FIRST", new String[]{"START", "BEGINNING", "ONSET", "INITIAL"})); - synonyms.add(new SynonymList("SIMILAR", new String[]{"SAME", "LIKE", "RESEMBLING"})); - synonyms.add(new SynonymList("MODEL", new String[]{"PATTERN", "PROTOTYPE", "STANDARD", "CRITERION"})); - synonyms.add(new SynonymList("SMALL", new String[]{"INSIGNIFICANT", "LITTLE", "TINY", "MINUTE"})); - synonyms.add(new SynonymList("STOP", new String[]{"HALT", "STAY", "ARREST", "CHECK", "STANDSTILL"})); - synonyms.add(new SynonymList("HOUSE", new String[]{"DWELLING", "RESIDENCE", "DOMICILE", "LODGING", "HABITATION"})); - synonyms.add(new SynonymList("PIT", new String[]{"HOLE", "HOLLOW", "WELL", "GULF", "CHASM", "ABYSS"})); - synonyms.add(new SynonymList("PUSH", new String[]{"SHOVE", "THRUST", "PROD", "POKE", "BUTT", "PRESS"})); - synonyms.add(new SynonymList("RED", new String[]{"ROUGE", "SCARLET", "CRIMSON", "FLAME", "RUBY"})); - synonyms.add(new SynonymList("PAIN", new String[]{"SUFFERING", "HURT", "MISERY", "DISTRESS", "ACHE", "DISCOMFORT"})); - - gameState = GAME_STATE.PLAY; - break; - - case PLAY: - - // Get the word and synonyms to ask a question about - SynonymList synonym = synonyms.get(currentQuestion); - String getAnswer = displayTextAndGetInput(" WHAT IS A SYNONYM OF " + synonym.getWord() + " ? "); - - // HELP is used to give a random synonym for the current word - if (getAnswer.equals("HELP")) { - int randomSynonym = (int) (Math.random() * synonym.size()); - System.out.println("**** A SYNONYM OF " + synonym.getWord() + " IS " + synonym.getSynonyms()[randomSynonym] + "."); - } else { - // Check if the entered word is in the synonym list - if (synonym.exists(getAnswer)) { - // If it is, give a random "correct" response - System.out.println(RANDOM_ANSWERS[(int) (Math.random() * RANDOM_ANSWERS.length)]); - currentQuestion++; - // Have we reached the final word/synonyms on file? - if (currentQuestion == synonyms.size()) { - // We have so end game. - System.out.println("SYNONYM DRILL COMPLETED."); - gameState = GAME_STATE.GAME_OVER; - } - } else { - // Word does not exist in the synonym list - System.out.println("TRY AGAIN."); - } - } - } - } while (gameState != GAME_STATE.GAME_OVER); - } - - private void intro() { - System.out.println(simulateTabs(33) + "SYNONYM"); - System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - System.out.println(); - System.out.println("A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH"); - System.out.println("LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME"); - System.out.println(" MEANING."); - System.out.println("I CHOOSE A WORD -- YOU TYPE A SYNONYM."); - System.out.println("IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP'"); - System.out.println("AND I WILL TELL YOU A SYNONYM."); - System.out.println(); - } - - /* - * Print a message on the screen, then accept input from Keyboard. - * Converts input to uppercase. - * - * @param text message to be displayed on screen. - * @return what was typed by the player. - */ - private String displayTextAndGetInput(String text) { - System.out.print(text); - return kbScanner.next().toUpperCase(); - } - - /** - * Simulate the old basic tab(xx) command which indented text by xx spaces. - * - * @param spaces number of spaces required - * @return String with number of spaces - */ - private String simulateTabs(int spaces) { - char[] spacesTemp = new char[spaces]; - Arrays.fill(spacesTemp, ' '); - return new String(spacesTemp); - } -} diff --git a/85 Synonym/java/src/SynonymGame.java b/85 Synonym/java/src/SynonymGame.java deleted file mode 100644 index 8ad52f4b..00000000 --- a/85 Synonym/java/src/SynonymGame.java +++ /dev/null @@ -1,6 +0,0 @@ -public class SynonymGame { - public static void main(String[] args) { - Synonym synonym = new Synonym(); - synonym.play(); - } -} diff --git a/85 Synonym/java/src/SynonymList.java b/85 Synonym/java/src/SynonymList.java deleted file mode 100644 index d692d48a..00000000 --- a/85 Synonym/java/src/SynonymList.java +++ /dev/null @@ -1,46 +0,0 @@ -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Stores a word and a list of synonyms for that word - */ -public class SynonymList { - - private final String word; - - private final ArrayList synonyms; - - public SynonymList(String word, String[] synonyms) { - this.word = word; - this.synonyms = new ArrayList<>(Arrays.asList(synonyms)); - } - - /** - * Check if the word passed to this method exists in the list of synonyms - * N.B. Case insensitive - * - * @param word word to search for - * @return true if found, otherwise false - */ - public boolean exists(String word) { - return synonyms.stream().anyMatch(str -> str.equalsIgnoreCase(word)); - } - - public String getWord() { - return word; - } - - public int size() { - return synonyms.size(); - } - - /** - * Returns all synonyms for this word in string array format - * - * @return - */ - public String[] getSynonyms() { - // Parameter to toArray method determines type of the resultant array - return synonyms.toArray(new String[0]); - } -} From 70b5a44fbaedbbf359d4fbabda32d86086dc26a8 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Sun, 28 Feb 2021 12:10:10 +1030 Subject: [PATCH 066/749] Java version of Synonym --- 85 Synonym/java/src/Synonym.java | 137 +++++++++++++++++++++++++++ 85 Synonym/java/src/SynonymGame.java | 6 ++ 85 Synonym/java/src/SynonymList.java | 46 +++++++++ 3 files changed, 189 insertions(+) create mode 100644 85 Synonym/java/src/Synonym.java create mode 100644 85 Synonym/java/src/SynonymGame.java create mode 100644 85 Synonym/java/src/SynonymList.java diff --git a/85 Synonym/java/src/Synonym.java b/85 Synonym/java/src/Synonym.java new file mode 100644 index 00000000..2804bb49 --- /dev/null +++ b/85 Synonym/java/src/Synonym.java @@ -0,0 +1,137 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Synonym + *

+ * Based on the Basic game of Synonym here + * https://github.com/coding-horror/basic-computer-games/blob/main/85%20Synonym/synonym.bas + *

+ * 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 Synonym { + + public static final String[] RANDOM_ANSWERS = {"RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"}; + + // Used for keyboard input + private final Scanner kbScanner; + + // List of words and synonyms + private final ArrayList synonyms; + + private enum GAME_STATE { + INIT, + PLAY, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private int currentQuestion; + + public Synonym() { + + kbScanner = new Scanner(System.in); + synonyms = new ArrayList<>(); + + gameState = GAME_STATE.INIT; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case INIT: + intro(); + currentQuestion = 0; + + // Load data + synonyms.add(new SynonymList("FIRST", new String[]{"START", "BEGINNING", "ONSET", "INITIAL"})); + synonyms.add(new SynonymList("SIMILAR", new String[]{"SAME", "LIKE", "RESEMBLING"})); + synonyms.add(new SynonymList("MODEL", new String[]{"PATTERN", "PROTOTYPE", "STANDARD", "CRITERION"})); + synonyms.add(new SynonymList("SMALL", new String[]{"INSIGNIFICANT", "LITTLE", "TINY", "MINUTE"})); + synonyms.add(new SynonymList("STOP", new String[]{"HALT", "STAY", "ARREST", "CHECK", "STANDSTILL"})); + synonyms.add(new SynonymList("HOUSE", new String[]{"DWELLING", "RESIDENCE", "DOMICILE", "LODGING", "HABITATION"})); + synonyms.add(new SynonymList("PIT", new String[]{"HOLE", "HOLLOW", "WELL", "GULF", "CHASM", "ABYSS"})); + synonyms.add(new SynonymList("PUSH", new String[]{"SHOVE", "THRUST", "PROD", "POKE", "BUTT", "PRESS"})); + synonyms.add(new SynonymList("RED", new String[]{"ROUGE", "SCARLET", "CRIMSON", "FLAME", "RUBY"})); + synonyms.add(new SynonymList("PAIN", new String[]{"SUFFERING", "HURT", "MISERY", "DISTRESS", "ACHE", "DISCOMFORT"})); + + gameState = GAME_STATE.PLAY; + break; + + case PLAY: + + // Get the word and synonyms to ask a question about + SynonymList synonym = synonyms.get(currentQuestion); + String getAnswer = displayTextAndGetInput(" WHAT IS A SYNONYM OF " + synonym.getWord() + " ? "); + + // HELP is used to give a random synonym for the current word + if (getAnswer.equals("HELP")) { + int randomSynonym = (int) (Math.random() * synonym.size()); + System.out.println("**** A SYNONYM OF " + synonym.getWord() + " IS " + synonym.getSynonyms()[randomSynonym] + "."); + } else { + // Check if the entered word is in the synonym list + if (synonym.exists(getAnswer)) { + // If it is, give a random "correct" response + System.out.println(RANDOM_ANSWERS[(int) (Math.random() * RANDOM_ANSWERS.length)]); + currentQuestion++; + // Have we reached the final word/synonyms on file? + if (currentQuestion == synonyms.size()) { + // We have so end game. + System.out.println("SYNONYM DRILL COMPLETED."); + gameState = GAME_STATE.GAME_OVER; + } + } else { + // Word does not exist in the synonym list + System.out.println("TRY AGAIN."); + } + } + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(33) + "SYNONYM"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH"); + System.out.println("LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME"); + System.out.println(" MEANING."); + System.out.println("I CHOOSE A WORD -- YOU TYPE A SYNONYM."); + System.out.println("IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP'"); + System.out.println("AND I WILL TELL YOU A SYNONYM."); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to uppercase. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next().toUpperCase(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } +} diff --git a/85 Synonym/java/src/SynonymGame.java b/85 Synonym/java/src/SynonymGame.java new file mode 100644 index 00000000..8ad52f4b --- /dev/null +++ b/85 Synonym/java/src/SynonymGame.java @@ -0,0 +1,6 @@ +public class SynonymGame { + public static void main(String[] args) { + Synonym synonym = new Synonym(); + synonym.play(); + } +} diff --git a/85 Synonym/java/src/SynonymList.java b/85 Synonym/java/src/SynonymList.java new file mode 100644 index 00000000..d692d48a --- /dev/null +++ b/85 Synonym/java/src/SynonymList.java @@ -0,0 +1,46 @@ +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Stores a word and a list of synonyms for that word + */ +public class SynonymList { + + private final String word; + + private final ArrayList synonyms; + + public SynonymList(String word, String[] synonyms) { + this.word = word; + this.synonyms = new ArrayList<>(Arrays.asList(synonyms)); + } + + /** + * Check if the word passed to this method exists in the list of synonyms + * N.B. Case insensitive + * + * @param word word to search for + * @return true if found, otherwise false + */ + public boolean exists(String word) { + return synonyms.stream().anyMatch(str -> str.equalsIgnoreCase(word)); + } + + public String getWord() { + return word; + } + + public int size() { + return synonyms.size(); + } + + /** + * Returns all synonyms for this word in string array format + * + * @return + */ + public String[] getSynonyms() { + // Parameter to toArray method determines type of the resultant array + return synonyms.toArray(new String[0]); + } +} From 691b82336cb6f438400d3e2adef6f1df1ae7b811 Mon Sep 17 00:00:00 2001 From: Topher Lamey Date: Sat, 27 Feb 2021 18:41:04 -0700 Subject: [PATCH 067/749] Initial take on Amazing for Java, gitignore update for IntelliJ --- .gitignore | 5 + 02 Amazing/java/Amazing.java | 181 +++++++++++++++++++++++++++++++ 02 Amazing/java/AmazingGame.java | 6 + 3 files changed, 192 insertions(+) create mode 100644 02 Amazing/java/Amazing.java create mode 100644 02 Amazing/java/AmazingGame.java diff --git a/.gitignore b/.gitignore index aa42e787..2973d79d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,8 @@ */csharp/bin */csharp/obj +.idea +*.iws +*.iml +*.ipr +out/ diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java new file mode 100644 index 00000000..d6b61f29 --- /dev/null +++ b/02 Amazing/java/Amazing.java @@ -0,0 +1,181 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Random; +import java.util.Scanner; +import static java.lang.System.in; +import static java.lang.System.out; + +public class Amazing { + + private final Scanner kbScanner; + + public Amazing() { + kbScanner = new Scanner(in); + } + + enum Direction { + GO_LEFT, + GO_UP, + GO_RIGHT, + GO_DOWN, + } + + public void play() { + out.println(tab(28) + "AMAZING PROGRAM"); + out.println(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + out.println(); + + int width = 0; + int length = 0; + + do { + String range = displayTextAndGetInput("WHAT ARE YOUR WIDTH AND LENGTH"); + if (range.indexOf(",") > 0) { + width = getDelimitedValue(range, 0); + length = getDelimitedValue(range, 1); + } + } while (width < 1 || length < 1); + + + Integer[][] used = new Integer[length][width]; + for (int i=0; i < length; i++) { + used[i] = new Integer[width]; + for (int j = 0; j < width; j++) { + used[i][j] = 0; + } + } + + Integer[][] walls = new Integer[length][width]; + for (int i=0; i < length; i++) { + walls[i] = new Integer[width]; + for (int j = 0; j < width; j++) { + walls[i][j] = 0; + } + } + + int EXIT_DOWN = 1; + int EXIT_RIGHT = 2; + + int enterCol = random(0, width); + int col = enterCol; + int row = 0; + int count = 1; + int totalWalls = width * length + 1; + + // set up entrance + used[row][col] = count; + count++; + + while (count != totalWalls) { + ArrayList possibleDirs = new ArrayList<>(Arrays.asList(Direction.values())); + + if (col == 0 || used[row][col - 1] != 0) { + possibleDirs.remove(Direction.GO_LEFT); + } + if (row == 0 || used[row - 1][col] != 0) { + possibleDirs.remove(Direction.GO_UP); + } + if (col == width - 1 || used[row][col + 1] != 0) { + possibleDirs.remove(Direction.GO_RIGHT); + } + if (row == length - 1 || used[row + 1][col] != 0) { + possibleDirs.remove(Direction.GO_DOWN); + } + + if (possibleDirs.size() != 0) { + Direction direction = possibleDirs.get(random(0, possibleDirs.size())); + if (direction == Direction.GO_LEFT) { + col = col - 1; + walls[row][col] = EXIT_RIGHT; + } else if (direction == Direction.GO_UP) { + row = row - 1; + walls[row][col] = EXIT_DOWN; + } else if (direction == Direction.GO_RIGHT) { + walls[row][col] = walls[row][col] + EXIT_RIGHT; + col = col + 1; + } else if (direction == Direction.GO_DOWN) { + walls[row][col] = walls[row][col] + EXIT_DOWN; + row = row + 1; + } + used[row][col] = count; + count++; + } else { + do { + if (col != width - 1) { + col++; + } else if (row != length - 1) { + row++; + col = 0; + } else { + row = 0; + col = 0; + } + } while (used[row][col] == 0); + } + } + + col = random(0, width - 1); + row = length - 1; + walls[row][col] = walls[row][col] + 1; + + for (int i=0; i < width; i++) { + if (i == enterCol) { + out.print(". "); + } else { + out.print(".--"); + } + } + out.println('.'); + + for (int i=0; i < length; i++) { + out.print("I"); + for (int j = 0; j < width; j++) { + if (walls[i][j] < 2) { + out.print(" I"); + } else { + out.print(" "); + } + } + out.println(); + for (int j = 0; j < width; j++) { + if (walls[i][j] == 0 || walls[i][j] == 2) { + out.print(":--"); + } else { + out.print(": "); + } + } + out.println("."); + } + } + + private String displayTextAndGetInput(String text) { + out.print(text); + return kbScanner.next(); + } + + private static int getDelimitedValue(String text, int pos) { + String[] tokens = text.split(","); + try { + return Integer.parseInt(tokens[pos]); + } catch (Exception ex) { + return 0; + } + } + + private static String tab(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + public static boolean random() { + Random random = new Random(); + return random.nextBoolean(); + } + + public static int random(int min, int max) { + Random random = new Random(); + return random.nextInt(max - min) + min; + } +} + diff --git a/02 Amazing/java/AmazingGame.java b/02 Amazing/java/AmazingGame.java new file mode 100644 index 00000000..a40056df --- /dev/null +++ b/02 Amazing/java/AmazingGame.java @@ -0,0 +1,6 @@ +public class AmazingGame { + public static void main(String[] args) { + Amazing amazing = new Amazing(); + amazing.play(); + } +} From c206605da5c74bfc53e187462c6578b9dfe3431c Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 19:50:56 -0600 Subject: [PATCH 068/749] Introduce enum for directions Instead of cleverly constructing the output string, explicitly test for what the resulting direction is. --- 51 Hurkle/csharp/src/hurkle/HurkleGame.cs | 123 ++++++++++++++++------ 1 file changed, 88 insertions(+), 35 deletions(-) diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs index 38d1a158..ed030587 100644 --- a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs +++ b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs @@ -43,7 +43,8 @@ namespace hurkle X = int.Parse(seperateStrings[0]), Y = int.Parse(seperateStrings[1]) }; - if(Math.Abs(guessPoint.X-hurklePoint.X) + Math.Abs(guessPoint.Y-hurklePoint.Y) == 0) + + if(guessPoint.GetDirectionTo(hurklePoint) == CardinalDirection.None) { /* 500 REM @@ -71,51 +72,103 @@ namespace hurkle private static void PrintInfo(GamePoint guess, GamePoint target) { - - /* - 610 PRINT "GO "; - */ Console.Write("GO "); - /* - 620 IF Y=B THEN 670 - 630 IF Ytarget.Y) + switch(guess.GetDirectionTo(target)) { - Console.Write("SOUTH"); - }else if(guess.Ytarget.X) - { - Console.Write("WEST"); + case CardinalDirection.East: + Console.WriteLine("EAST"); + break; + case CardinalDirection.North: + Console.WriteLine("NORTH"); + break; + case CardinalDirection.South: + Console.WriteLine("SOUTH"); + break; + case CardinalDirection.West: + Console.WriteLine("WEST"); + break; + case CardinalDirection.NorthEast: + Console.WriteLine("NORTHEAST"); + break; + case CardinalDirection.NorthWest: + Console.WriteLine("NORTHWEST"); + break; + case CardinalDirection.SouthEast: + Console.WriteLine("SOUTHEAST"); + break; + case CardinalDirection.SouthWest: + Console.WriteLine("SOUTHWEST"); + break; } Console.WriteLine(); - /* - 720 PRINT - 730 RETURN - */ + } + + private enum CardinalDirection + { + None, + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest } private class GamePoint { public int X {get;init;} public int Y {get;init;} + + public CardinalDirection GetDirectionTo(GamePoint target) + { + if(X == target.X) + { + if(Y > target.Y) + { + return CardinalDirection.South; + } + else if(Y < target.Y) + { + return CardinalDirection.North; + } + else + { + return CardinalDirection.None; + } + } + else if(X > target.X) + { + if(Y == target.Y) + { + return CardinalDirection.West; + } + else if(Y > target.Y) + { + return CardinalDirection.SouthWest; + } + else + { + return CardinalDirection.NorthWest; + } + } + else + { + if(Y == target.Y) + { + return CardinalDirection.East; + } + else if(Y > target.Y) + { + return CardinalDirection.SouthEast; + } + else{ + return CardinalDirection.NorthEast; + } + } + } } } } \ No newline at end of file From 59369f93ed327afc3762b7e42ad9bec455867a3c Mon Sep 17 00:00:00 2001 From: Topher Lamey Date: Sat, 27 Feb 2021 18:51:42 -0700 Subject: [PATCH 069/749] Fix up constants --- 02 Amazing/java/Amazing.java | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java index d6b61f29..6057e932 100644 --- a/02 Amazing/java/Amazing.java +++ b/02 Amazing/java/Amazing.java @@ -56,6 +56,11 @@ public class Amazing { int EXIT_DOWN = 1; int EXIT_RIGHT = 2; + int FIRST_COL = 0; + int LAST_COL = width - 1; + int FIRST_ROW = 0; + int LAST_ROW = length - 1; + int enterCol = random(0, width); int col = enterCol; int row = 0; @@ -69,33 +74,33 @@ public class Amazing { while (count != totalWalls) { ArrayList possibleDirs = new ArrayList<>(Arrays.asList(Direction.values())); - if (col == 0 || used[row][col - 1] != 0) { + if (col == FIRST_COL || 0 != used[row][col - 1]) { possibleDirs.remove(Direction.GO_LEFT); } - if (row == 0 || used[row - 1][col] != 0) { + if (row == FIRST_ROW || 0 != used[row - 1][col]) { possibleDirs.remove(Direction.GO_UP); } - if (col == width - 1 || used[row][col + 1] != 0) { + if (col == LAST_COL || 0 != used[row][col + 1]) { possibleDirs.remove(Direction.GO_RIGHT); } - if (row == length - 1 || used[row + 1][col] != 0) { + if (row == LAST_ROW || 0 != used[row + 1][col]) { possibleDirs.remove(Direction.GO_DOWN); } if (possibleDirs.size() != 0) { Direction direction = possibleDirs.get(random(0, possibleDirs.size())); if (direction == Direction.GO_LEFT) { - col = col - 1; + col--; walls[row][col] = EXIT_RIGHT; } else if (direction == Direction.GO_UP) { - row = row - 1; + row--; walls[row][col] = EXIT_DOWN; } else if (direction == Direction.GO_RIGHT) { walls[row][col] = walls[row][col] + EXIT_RIGHT; - col = col + 1; + col++; } else if (direction == Direction.GO_DOWN) { walls[row][col] = walls[row][col] + EXIT_DOWN; - row = row + 1; + row++; } used[row][col] = count; count++; From 74eaccabc1508a89f3338f67b0afdecf1f99c7ef Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 20:08:03 -0600 Subject: [PATCH 070/749] Isolate prompting from game Move the user input out of the game logic. --- 51 Hurkle/csharp/src/hurkle/HurkleGame.cs | 28 ++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs index ed030587..eff53f25 100644 --- a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs +++ b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs @@ -36,14 +36,8 @@ namespace hurkle */ for(var K=1;K<=guesses;K++) { - Console.WriteLine($"GUESS #{K}"); - var inputLine = Console.ReadLine(); - var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); - var guessPoint = new GamePoint{ - X = int.Parse(seperateStrings[0]), - Y = int.Parse(seperateStrings[1]) - }; - + var guessPoint = GetGuess(new GuessViewModel{CurrentGuessNumber = K}); + if(guessPoint.GetDirectionTo(hurklePoint) == CardinalDirection.None) { /* @@ -70,6 +64,24 @@ namespace hurkle Console.WriteLine($"THE HURKLE IS AT {hurklePoint.X},{hurklePoint.Y}"); } + private class GuessViewModel + { + public int CurrentGuessNumber {get;init;} + } + + private static GamePoint GetGuess(GuessViewModel model) + { + Console.WriteLine($"GUESS #{model.CurrentGuessNumber}"); + var inputLine = Console.ReadLine(); + var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); + var guessPoint = new GamePoint{ + X = int.Parse(seperateStrings[0]), + Y = int.Parse(seperateStrings[1]) + }; + + return guessPoint; + } + private static void PrintInfo(GamePoint guess, GamePoint target) { Console.Write("GO "); From 632d14e128fdba5606136336b9c23e38f71ceb75 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Sat, 27 Feb 2021 18:08:08 -0800 Subject: [PATCH 071/749] Ported LETTER to Python pretty straightforward port of the BASIC code to Python. Added a few functions for clarity. Removed CHR$(7) sounding of the bell, which is likely unsupported, and likely annoying. Also corrected a mis-scanned "Let's Plan Again" message in the .BAS file, to both make more sense and also agree with the 2nd edition printed book. --- 54 Letter/letter.bas | 2 +- 54 Letter/python/letter.py | 78 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 54 Letter/python/letter.py diff --git a/54 Letter/letter.bas b/54 Letter/letter.bas index 3064dbb6..ab3efe0c 100644 --- a/54 Letter/letter.bas +++ b/54 Letter/letter.bas @@ -21,6 +21,6 @@ 508 PRINT "GOOD JOB !!!!!" 510 FOR N=1 TO 15: PRINT CHR$(7);: NEXT N 515 PRINT -520 PRINT "LET'S PLAN AGAIN....." +520 PRINT "LET'S PLAY AGAIN....." 530 GOTO 310 999 END diff --git a/54 Letter/python/letter.py b/54 Letter/python/letter.py new file mode 100644 index 00000000..84526582 --- /dev/null +++ b/54 Letter/python/letter.py @@ -0,0 +1,78 @@ +""" +LETTER + +A letter guessing game. + +Ported by Dave LeCompte +""" + +import random + +# The original code printed character 7, the "BELL" character 15 times +# when the player won. Many modern systems do not support this, and in +# any case, it can quickly become annoying, so it is disabled here. + +BELLS_ON_SUCCESS = False + +def print_with_tab(space_count, msg): + if space_count > 0: + spaces = " " * space_count + else: + spaces = "" + + print(spaces + msg) + +def print_instructions(): + print("LETTER GUESSING GAME") + print() + print("I'LL THINK OF A LETTER OF THE ALPHABET, A TO Z.") + print("TRY TO GUESS MY LETTER AND I'LL GIVE YOU CLUES") + print("AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER.") + +def play_game(): + target_value = random.randint(ord('A'), ord('Z')) + num_guesses = 0 + print() + print("O.K., I HAVE A LETTER. START GUESSING.") + print() + while True: + print("WHAT IS YOUR GUESS?") + num_guesses += 1 + guess = ord(input()) + print() + if guess == target_value: + print() + print(f"YOU GOT IT IN {num_guesses} GUESSES!!") + if num_guesses > 5: + print("BUT IT SHOULDN'T TAKE MORE THAN 5 GUESSES!") + # goto 515 + print("GOOD JOB !!!!!") + + if BELLS_ON_SUCCESS: + bellStr = chr(7) * 15 + print(bellStr) + + print() + print("LET'S PLAY AGAIN.....") + return + elif guess > target_value: + print("TOO HIGH. TRY A LOWER LETTER.") + continue + else: + print("TOO LOW. TRY A HIGHER LETTER.") + continue + +def main(): + print_with_tab(33, "LETTER") + print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + print_instructions() + + while True: + play_game() + +if __name__ == "__main__": + main() From 4f4ae0b98152f8aa68a948c6c821670499e81a90 Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 20:44:35 -0600 Subject: [PATCH 072/749] Add ViewModels for game loop Move all UI interaction off of game loop variables. --- .../csharp/src/hurkle/CardinalDirection.cs | 15 ++ .../csharp/src/hurkle/FailedGuessViewModel.cs | 7 + 51 Hurkle/csharp/src/hurkle/GamePoint.cs | 56 +++++++ 51 Hurkle/csharp/src/hurkle/HurkleGame.cs | 154 +++++------------- 51 Hurkle/csharp/src/hurkle/LossViewModel.cs | 8 + .../csharp/src/hurkle/VictoryViewModel.cs | 7 + 6 files changed, 135 insertions(+), 112 deletions(-) create mode 100644 51 Hurkle/csharp/src/hurkle/CardinalDirection.cs create mode 100644 51 Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs create mode 100644 51 Hurkle/csharp/src/hurkle/GamePoint.cs create mode 100644 51 Hurkle/csharp/src/hurkle/LossViewModel.cs create mode 100644 51 Hurkle/csharp/src/hurkle/VictoryViewModel.cs diff --git a/51 Hurkle/csharp/src/hurkle/CardinalDirection.cs b/51 Hurkle/csharp/src/hurkle/CardinalDirection.cs new file mode 100644 index 00000000..969c9b2b --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/CardinalDirection.cs @@ -0,0 +1,15 @@ +namespace hurkle +{ + internal enum CardinalDirection + { + None, + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs b/51 Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs new file mode 100644 index 00000000..25042dde --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs @@ -0,0 +1,7 @@ +namespace hurkle +{ + internal class FailedGuessViewModel + { + public CardinalDirection Direction { get; init; } + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/GamePoint.cs b/51 Hurkle/csharp/src/hurkle/GamePoint.cs new file mode 100644 index 00000000..f715a41d --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/GamePoint.cs @@ -0,0 +1,56 @@ +namespace hurkle +{ + internal class GamePoint + { + public int X {get;init;} + public int Y {get;init;} + + public CardinalDirection GetDirectionTo(GamePoint target) + { + if(X == target.X) + { + if(Y > target.Y) + { + return CardinalDirection.South; + } + else if(Y < target.Y) + { + return CardinalDirection.North; + } + else + { + return CardinalDirection.None; + } + } + else if(X > target.X) + { + if(Y == target.Y) + { + return CardinalDirection.West; + } + else if(Y > target.Y) + { + return CardinalDirection.SouthWest; + } + else + { + return CardinalDirection.NorthWest; + } + } + else + { + if(Y == target.Y) + { + return CardinalDirection.East; + } + else if(Y > target.Y) + { + return CardinalDirection.SouthEast; + } + else{ + return CardinalDirection.NorthEast; + } + } + } + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs index eff53f25..8b3b13f3 100644 --- a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs +++ b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs @@ -2,7 +2,7 @@ using System; namespace hurkle { - public class HurkleGame + public partial class HurkleGame { private readonly Random _random = new Random(); private readonly int guesses; @@ -24,68 +24,36 @@ namespace hurkle Y = _random.Next(0, gridSize) }; - /* - 310 FOR K=1 TO N - 320 PRINT "GUESS #";K; - 330 INPUT X,Y - 340 IF ABS(X-A)+ABS(Y-B)=0 THEN 500 - 350 REM PRINT INFO - 360 GOSUB 610 - 370 PRINT - 380 NEXT K - */ for(var K=1;K<=guesses;K++) { var guessPoint = GetGuess(new GuessViewModel{CurrentGuessNumber = K}); - - if(guessPoint.GetDirectionTo(hurklePoint) == CardinalDirection.None) - { - /* - 500 REM - 510 PRINT - 520 PRINT "YOU FOUND HIM IN";K;GUESSES!" - 540 GOTO 440 - */ - Console.WriteLine(); - Console.WriteLine($"YOU FOUND HIM IN {K} GUESSES!"); - return; - } - PrintInfo(guessPoint,hurklePoint); + var direction = guessPoint.GetDirectionTo(hurklePoint); + switch(direction) + { + case CardinalDirection.None: + ShowVictory(new VictoryViewModel{CurrentGuessNumber = K}); + return; + default: + ShowDirection(new FailedGuessViewModel{Direction = direction}); + continue; + } } - /* - 410 PRINT - 420 PRINT "SORRY, THAT'S;N;"GUESSES." - 430 PRINT "THE HURKLE IS AT ";A;",";B - */ + ShowLoss(new LossViewModel{MaxGuesses = guesses, HurkleLocation = hurklePoint } ); + } + + private void ShowLoss(LossViewModel lossViewModel) + { Console.WriteLine(); - Console.WriteLine($"SORRY, THAT'S {guesses} GUESSES"); - Console.WriteLine($"THE HURKLE IS AT {hurklePoint.X},{hurklePoint.Y}"); + Console.WriteLine($"SORRY, THAT'S {lossViewModel.MaxGuesses} GUESSES"); + Console.WriteLine($"THE HURKLE IS AT {lossViewModel.HurkleLocation.X},{lossViewModel.HurkleLocation.Y}"); } - private class GuessViewModel - { - public int CurrentGuessNumber {get;init;} - } - - private static GamePoint GetGuess(GuessViewModel model) - { - Console.WriteLine($"GUESS #{model.CurrentGuessNumber}"); - var inputLine = Console.ReadLine(); - var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); - var guessPoint = new GamePoint{ - X = int.Parse(seperateStrings[0]), - Y = int.Parse(seperateStrings[1]) - }; - - return guessPoint; - } - - private static void PrintInfo(GamePoint guess, GamePoint target) + private void ShowDirection(FailedGuessViewModel failedGuessViewModel) { Console.Write("GO "); - switch(guess.GetDirectionTo(target)) + switch(failedGuessViewModel.Direction) { case CardinalDirection.East: Console.WriteLine("EAST"); @@ -116,71 +84,33 @@ namespace hurkle Console.WriteLine(); } - private enum CardinalDirection + private void ShowVictory(VictoryViewModel victoryViewModel) { - None, - North, - NorthEast, - East, - SouthEast, - South, - SouthWest, - West, - NorthWest + Console.WriteLine(); + Console.WriteLine($"YOU FOUND HIM IN {victoryViewModel.CurrentGuessNumber} GUESSES!"); } - private class GamePoint + private class GuessViewModel { - public int X {get;init;} - public int Y {get;init;} + public int CurrentGuessNumber {get;init;} + } - public CardinalDirection GetDirectionTo(GamePoint target) - { - if(X == target.X) - { - if(Y > target.Y) - { - return CardinalDirection.South; - } - else if(Y < target.Y) - { - return CardinalDirection.North; - } - else - { - return CardinalDirection.None; - } - } - else if(X > target.X) - { - if(Y == target.Y) - { - return CardinalDirection.West; - } - else if(Y > target.Y) - { - return CardinalDirection.SouthWest; - } - else - { - return CardinalDirection.NorthWest; - } - } - else - { - if(Y == target.Y) - { - return CardinalDirection.East; - } - else if(Y > target.Y) - { - return CardinalDirection.SouthEast; - } - else{ - return CardinalDirection.NorthEast; - } - } - } + private static GamePoint GetGuess(GuessViewModel model) + { + Console.WriteLine($"GUESS #{model.CurrentGuessNumber}"); + var inputLine = Console.ReadLine(); + var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); + var guessPoint = new GamePoint{ + X = int.Parse(seperateStrings[0]), + Y = int.Parse(seperateStrings[1]) + }; + + return guessPoint; + } + + private static void PrintInfo(GamePoint guess, GamePoint target) + { + } } } \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/LossViewModel.cs b/51 Hurkle/csharp/src/hurkle/LossViewModel.cs new file mode 100644 index 00000000..2329be87 --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/LossViewModel.cs @@ -0,0 +1,8 @@ +namespace hurkle +{ + internal class LossViewModel + { + public int MaxGuesses { get; init; } + public GamePoint HurkleLocation { get; init; } + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/VictoryViewModel.cs b/51 Hurkle/csharp/src/hurkle/VictoryViewModel.cs new file mode 100644 index 00000000..ce25311c --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/VictoryViewModel.cs @@ -0,0 +1,7 @@ +namespace hurkle +{ + internal class VictoryViewModel + { + public int CurrentGuessNumber {get; init;} + } +} \ No newline at end of file From 0645ab1e30b458fb3e6881a980b5680a267a90f6 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Sat, 27 Feb 2021 18:53:06 -0800 Subject: [PATCH 073/749] Port KINEMA to Python Pulled "g", the gravitational constant, out as a constant, rewrote the equations to be a little clearer, closer to how a high school student would recognize them from first semester Physics class. --- 52 Kinema/python/kinema.py | 82 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 52 Kinema/python/kinema.py diff --git a/52 Kinema/python/kinema.py b/52 Kinema/python/kinema.py new file mode 100644 index 00000000..55d20aa1 --- /dev/null +++ b/52 Kinema/python/kinema.py @@ -0,0 +1,82 @@ +""" +KINEMA + +A kinematics physics quiz. + +Ported by Dave LeCompte +""" + +import random + +# We approximate gravity from 9.8 meters/second squared to 10, which +# is only off by about 2%. 10 is also a lot easier for people to use +# for mental math. + +g = 10 + + +def print_with_tab(spaces_count, msg): + if spaces_count > 0: + spaces = " " * spaces_count + else: + spaces = "" + print(spaces + msg) + + +def do_quiz(): + print() + print() + num_questions_correct = 0 + + # pick random initial velocity + v0 = random.randint(5, 40) + print(f"A BALL IS THROWN UPWARDS AT {v0} METERS PER SECOND.") + print() + + answer = v0 ** 2 / (2 * g) + num_questions_correct += ask_player("HOW HIGH WILL IT GO (IN METERS)?", answer) + + answer = 2 * v0 / g + num_questions_correct += ask_player( + "HOW LONG UNTIL IT RETURNS (IN SECONDS)?", answer + ) + + t = 1 + random.randint(0, 2 * v0) // g + answer = v0 - g * t + num_questions_correct += ask_player( + f"WHAT WILL ITS VELOCITY BE AFTER {t} SECONDS?", answer + ) + + print() + print(f"{num_questions_correct} right out of 3.") + if num_questions_correct >= 2: + print(" NOT BAD.") + + +def ask_player(question, answer): + print(question) + player_answer = float(input()) + if abs((player_answer - answer) / answer) < 0.15: + print("CLOSE ENOUGH.") + score = 1 + else: + print("NOT EVEN CLOSE....") + score = 0 + print(f"CORRECT ANSWER IS {answer}") + print() + return score + + +def main(): + print_with_tab(33, "KINEMA") + print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + while True: + do_quiz() + + +if __name__ == "__main__": + main() From e73c7c2bbf5db6253a787fe63917803d4d60d0d4 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Sat, 27 Feb 2021 18:55:29 -0800 Subject: [PATCH 074/749] Kinema tweak Moved the accuracy window constant to the top of the file with a comment. --- 52 Kinema/python/kinema.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/52 Kinema/python/kinema.py b/52 Kinema/python/kinema.py index 55d20aa1..e5529d68 100644 --- a/52 Kinema/python/kinema.py +++ b/52 Kinema/python/kinema.py @@ -14,6 +14,11 @@ import random g = 10 +# We only expect the student to get within this percentage of the +# correct answer. This isn't rocket science. + +EXPECTED_ACCURACY_PERCENT = 15 + def print_with_tab(spaces_count, msg): if spaces_count > 0: @@ -56,7 +61,9 @@ def do_quiz(): def ask_player(question, answer): print(question) player_answer = float(input()) - if abs((player_answer - answer) / answer) < 0.15: + + accuracy_frac = EXPECTED_ACCURACY_PERCENT / 100.0 + if abs((player_answer - answer) / answer) < accuracy_frac: print("CLOSE ENOUGH.") score = 1 else: From ed339ccd3f08577803de19e3390f87b8ed3abfb1 Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 20:59:55 -0600 Subject: [PATCH 075/749] Introduce a view class Move all the console interaction into a view class making the game logic isolated from UI. --- .../csharp/src/hurkle/ConsoleHurkleView.cs | 67 +++++++++++++++ 51 Hurkle/csharp/src/hurkle/GuessViewModel.cs | 7 ++ 51 Hurkle/csharp/src/hurkle/HurkleGame.cs | 84 ++----------------- 51 Hurkle/csharp/src/hurkle/IHurkleView.cs | 10 +++ 51 Hurkle/csharp/src/hurkle/Program.cs | 3 +- 5 files changed, 94 insertions(+), 77 deletions(-) create mode 100644 51 Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs create mode 100644 51 Hurkle/csharp/src/hurkle/GuessViewModel.cs create mode 100644 51 Hurkle/csharp/src/hurkle/IHurkleView.cs diff --git a/51 Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs b/51 Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs new file mode 100644 index 00000000..40366ad2 --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs @@ -0,0 +1,67 @@ +using System; + +namespace hurkle +{ + internal class ConsoleHurkleView : IHurkleView + { + public GamePoint GetGuess(GuessViewModel guessViewModel) + { + Console.WriteLine($"GUESS #{guessViewModel.CurrentGuessNumber}"); + var inputLine = Console.ReadLine(); + var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); + var guessPoint = new GamePoint{ + X = int.Parse(seperateStrings[0]), + Y = int.Parse(seperateStrings[1]) + }; + + return guessPoint; + } + + public void ShowDirection(FailedGuessViewModel failedGuessViewModel) + { + Console.Write("GO "); + switch(failedGuessViewModel.Direction) + { + case CardinalDirection.East: + Console.WriteLine("EAST"); + break; + case CardinalDirection.North: + Console.WriteLine("NORTH"); + break; + case CardinalDirection.South: + Console.WriteLine("SOUTH"); + break; + case CardinalDirection.West: + Console.WriteLine("WEST"); + break; + case CardinalDirection.NorthEast: + Console.WriteLine("NORTHEAST"); + break; + case CardinalDirection.NorthWest: + Console.WriteLine("NORTHWEST"); + break; + case CardinalDirection.SouthEast: + Console.WriteLine("SOUTHEAST"); + break; + case CardinalDirection.SouthWest: + Console.WriteLine("SOUTHWEST"); + break; + } + + Console.WriteLine(); + } + + public void ShowLoss(LossViewModel lossViewModel) + { + Console.WriteLine(); + Console.WriteLine($"SORRY, THAT'S {lossViewModel.MaxGuesses} GUESSES"); + Console.WriteLine($"THE HURKLE IS AT {lossViewModel.HurkleLocation.X},{lossViewModel.HurkleLocation.Y}"); + } + + public void ShowVictory(VictoryViewModel victoryViewModel) + { + Console.WriteLine(); + Console.WriteLine($"YOU FOUND HIM IN {victoryViewModel.CurrentGuessNumber} GUESSES!"); + } + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/GuessViewModel.cs b/51 Hurkle/csharp/src/hurkle/GuessViewModel.cs new file mode 100644 index 00000000..b0c5227c --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/GuessViewModel.cs @@ -0,0 +1,7 @@ +namespace hurkle +{ + internal class GuessViewModel + { + public int CurrentGuessNumber {get;init;} + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs index 8b3b13f3..88620bbc 100644 --- a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs +++ b/51 Hurkle/csharp/src/hurkle/HurkleGame.cs @@ -2,14 +2,16 @@ using System; namespace hurkle { - public partial class HurkleGame + internal class HurkleGame { private readonly Random _random = new Random(); + private readonly IHurkleView _view; private readonly int guesses; private readonly int gridSize; - public HurkleGame(int guesses, int gridSize) + public HurkleGame(int guesses, int gridSize, IHurkleView view) { + _view = view; this.guesses = guesses; this.gridSize = gridSize; } @@ -26,91 +28,21 @@ namespace hurkle for(var K=1;K<=guesses;K++) { - var guessPoint = GetGuess(new GuessViewModel{CurrentGuessNumber = K}); + var guessPoint = _view.GetGuess(new GuessViewModel{CurrentGuessNumber = K}); var direction = guessPoint.GetDirectionTo(hurklePoint); switch(direction) { case CardinalDirection.None: - ShowVictory(new VictoryViewModel{CurrentGuessNumber = K}); + _view.ShowVictory(new VictoryViewModel{CurrentGuessNumber = K}); return; default: - ShowDirection(new FailedGuessViewModel{Direction = direction}); + _view.ShowDirection(new FailedGuessViewModel{Direction = direction}); continue; } } - ShowLoss(new LossViewModel{MaxGuesses = guesses, HurkleLocation = hurklePoint } ); - } - - private void ShowLoss(LossViewModel lossViewModel) - { - Console.WriteLine(); - Console.WriteLine($"SORRY, THAT'S {lossViewModel.MaxGuesses} GUESSES"); - Console.WriteLine($"THE HURKLE IS AT {lossViewModel.HurkleLocation.X},{lossViewModel.HurkleLocation.Y}"); - } - - private void ShowDirection(FailedGuessViewModel failedGuessViewModel) - { - Console.Write("GO "); - switch(failedGuessViewModel.Direction) - { - case CardinalDirection.East: - Console.WriteLine("EAST"); - break; - case CardinalDirection.North: - Console.WriteLine("NORTH"); - break; - case CardinalDirection.South: - Console.WriteLine("SOUTH"); - break; - case CardinalDirection.West: - Console.WriteLine("WEST"); - break; - case CardinalDirection.NorthEast: - Console.WriteLine("NORTHEAST"); - break; - case CardinalDirection.NorthWest: - Console.WriteLine("NORTHWEST"); - break; - case CardinalDirection.SouthEast: - Console.WriteLine("SOUTHEAST"); - break; - case CardinalDirection.SouthWest: - Console.WriteLine("SOUTHWEST"); - break; - } - - Console.WriteLine(); - } - - private void ShowVictory(VictoryViewModel victoryViewModel) - { - Console.WriteLine(); - Console.WriteLine($"YOU FOUND HIM IN {victoryViewModel.CurrentGuessNumber} GUESSES!"); - } - - private class GuessViewModel - { - public int CurrentGuessNumber {get;init;} - } - - private static GamePoint GetGuess(GuessViewModel model) - { - Console.WriteLine($"GUESS #{model.CurrentGuessNumber}"); - var inputLine = Console.ReadLine(); - var seperateStrings = inputLine.Split(',', 2, StringSplitOptions.TrimEntries); - var guessPoint = new GamePoint{ - X = int.Parse(seperateStrings[0]), - Y = int.Parse(seperateStrings[1]) - }; - - return guessPoint; - } - - private static void PrintInfo(GamePoint guess, GamePoint target) - { - + _view.ShowLoss(new LossViewModel{MaxGuesses = guesses, HurkleLocation = hurklePoint } ); } } } \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/IHurkleView.cs b/51 Hurkle/csharp/src/hurkle/IHurkleView.cs new file mode 100644 index 00000000..e5ce3a1a --- /dev/null +++ b/51 Hurkle/csharp/src/hurkle/IHurkleView.cs @@ -0,0 +1,10 @@ +namespace hurkle +{ + internal interface IHurkleView + { + GamePoint GetGuess(GuessViewModel guessViewModel); + void ShowVictory(VictoryViewModel victoryViewModel); + void ShowDirection(FailedGuessViewModel failedGuessViewModel); + void ShowLoss(LossViewModel lossViewModel); + } +} \ No newline at end of file diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51 Hurkle/csharp/src/hurkle/Program.cs index 4c4040b7..148308d1 100644 --- a/51 Hurkle/csharp/src/hurkle/Program.cs +++ b/51 Hurkle/csharp/src/hurkle/Program.cs @@ -40,7 +40,8 @@ namespace hurkle Console.WriteLine(@"DIRECTION TO GO TO LOOK FOR THE HURKLE."); Console.WriteLine(); - var hurkle = new HurkleGame(N,G); + var view = new ConsoleHurkleView(); + var hurkle = new HurkleGame(N,G, view); while(true) { hurkle.PlayGame(); From ce403d2d2635926bcbaad374b8ac5ae1d796a3a3 Mon Sep 17 00:00:00 2001 From: epvanhouten Date: Sat, 27 Feb 2021 21:04:32 -0600 Subject: [PATCH 076/749] Updating README.md --- 51 Hurkle/csharp/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/51 Hurkle/csharp/README.md b/51 Hurkle/csharp/README.md index 4daabb5c..6973d578 100644 --- a/51 Hurkle/csharp/README.md +++ b/51 Hurkle/csharp/README.md @@ -1,3 +1,8 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/) + +This is demonstrating seperating the user interface from the application logic through the +use of the View/ViewModel/Controller pattern. + +It also makes an effort to be relatively immutable. From f78a4457aa9c3b65a53f05c1513720bf0820c5b7 Mon Sep 17 00:00:00 2001 From: nanochess Date: Sat, 27 Feb 2021 21:48:52 -0600 Subject: [PATCH 077/749] Ported HANGMAN and HELLO to Javascript --- 44 Hangman/javascript/hangman.html | 9 + 44 Hangman/javascript/hangman.js | 266 +++++++++++++++++++++++++++++ 45 Hello/javascript/hello.html | 9 + 45 Hello/javascript/hello.js | 163 ++++++++++++++++++ 4 files changed, 447 insertions(+) create mode 100644 44 Hangman/javascript/hangman.html create mode 100644 44 Hangman/javascript/hangman.js create mode 100644 45 Hello/javascript/hello.html create mode 100644 45 Hello/javascript/hello.js diff --git a/44 Hangman/javascript/hangman.html b/44 Hangman/javascript/hangman.html new file mode 100644 index 00000000..7bf3d250 --- /dev/null +++ b/44 Hangman/javascript/hangman.html @@ -0,0 +1,9 @@ + + +HANGMAN + + +


+
+
+
diff --git a/44 Hangman/javascript/hangman.js b/44 Hangman/javascript/hangman.js
new file mode 100644
index 00000000..322fd94f
--- /dev/null
+++ b/44 Hangman/javascript/hangman.js	
@@ -0,0 +1,266 @@
+// HANGMAN
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+print(tab(32) + "HANGMAN\n");
+print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+print("\n");
+print("\n");
+print("\n");
+
+var pa = [];
+var la = [];
+var da = [];
+var na = [];
+var ua = [];
+
+var words = ["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"];
+
+// Main control section
+async function main()
+{
+    c = 1;
+    n = 50;
+    while (1) {
+        for (i = 1; i <= 20; i++)
+            da[i] = "-";
+        for (i = 1; i <= n; i++)
+            ua[i] = 0;
+        m = 0;
+        ns = "";
+        for (i = 1; i <= 12; i++) {
+            pa[i] = [];
+            for (j = 1; j <= 12; j++) {
+                pa[i][j] = " ";
+            }
+        }
+        for (i = 1; i <= 12; i++) {
+            pa[i][1] = "X";
+        }
+        for (i = 1; i <= 7; i++) {
+            pa[1][i] = "X";
+        }
+        pa[2][7] = "X";
+        if (c >= n) {
+            print("YOU DID ALL THE WORDS!!\n");
+            break;
+        }
+        do {
+            q = Math.floor(n * Math.random()) + 1;
+        } while (ua[q] == 1) ;
+        ua[q] = 1;
+        c++;
+        t1 = 0;
+        as = words[q - 1];
+        l = as.length;
+        for (i = 1; i <= as.length; i++)
+            la[i] = as[i - 1];
+        while (1) {
+            while (1) {
+                print("HERE ARE THE LETTERS YOU USED:\n");
+                print(ns + "\n");
+                print("\n");
+                for (i = 1; i <= l; i++) {
+                    print(da[i]);
+                }
+                print("\n");
+                print("\n");
+                print("WHAT IS YOUR GUESS");
+                str = await input();
+                if (ns.indexOf(str) != -1) {
+                    print("YOU GUESSED THAT LETTER BEFORE!\n");
+                } else {
+                    break;
+                }
+            }
+            ns += str;
+            t1++;
+            r = 0;
+            for (i = 1; i <= l; i++) {
+                if (la[i] == str) {
+                    da[i] = str;
+                    r++;
+                }
+            }
+            if (r == 0) {
+                m++;
+                print("\n");
+                print("\n");
+                print("SORRY, THAT LETTER ISN'T IN THE WORD.\n");
+                switch (m) {
+                    case 1:
+                        print("FIRST, WE DRAW A HEAD\n");
+                        break;
+                    case 2:
+                        print("NOW WE DRAW A BODY.\n");
+                        break;
+                    case 3:
+                        print("NEXT WE DRAW AN ARM.\n");
+                        break;
+                    case 4:
+                        print("THIS TIME IT'S THE OTHER ARM.\n");
+                        break;
+                    case 5:
+                        print("NOW, LET'S DRAW THE RIGHT LEG.\n");
+                        break;
+                    case 6:
+                        print("THIS TIME WE DRAW THE LEFT LEG.\n");
+                        break;
+                    case 7:
+                        print("NOW WE PUT UP A HAND.\n");
+                        break;
+                    case 8:
+                        print("NEXT THE OTHER HAND.\n");
+                        break;
+                    case 9:
+                        print("NOW WE DRAW ONE FOOT.\n");
+                        break;
+                    case 10:
+                        print("HERE'S THE OTHER FOOT -- YOU'RE HUNG!!\n");
+                        break;
+                }
+                switch (m) {
+                    case 1:
+                        pa[3][6] = "-";
+                        pa[3][7] = "-";
+                        pa[3][8] = "-";
+                        pa[4][5] = "(";
+                        pa[4][6] = ".";
+                        pa[4][8] = ".";
+                        pa[4][9] = ")";
+                        pa[5][6] = "-";
+                        pa[5][7] = "-";
+                        pa[5][8] = "-";
+                        break;
+                    case 2:
+                        for (i = 6; i <= 9; i++)
+                            pa[i][7] = "X";
+                        break;
+                    case 3:
+                        for (i = 4; i <= 7; i++)
+                            pa[i][i - 1] = "\\";
+                        break;
+                    case 4:
+                        pa[4][11] = "/";
+                        pa[5][10] = "/";
+                        pa[6][9] = "/";
+                        pa[7][8] = "/";
+                        break;
+                    case 5:
+                        pa[10][6] = "/";
+                        pa[11][5] = "/";
+                        break;
+                    case 6:
+                        pa[10][8] = "\\";
+                        pa[11][9] = "\\";
+                        break;
+                    case 7:
+                        pa[3][11] = "\\";
+                        break;
+                    case 8:
+                        pa[3][3] = "/";
+                        break;
+                    case 9:
+                        pa[12][10] = "\\";
+                        pa[12][11] = "-";
+                        break;
+                    case 10:
+                        pa[12][3] = "-";
+                        pa[12][4] = "/";
+                        break;
+                }
+                for (i = 1; i <= 12; i++) {
+                    str = "";
+                    for (j = 1; j <= 12; j++)
+                        str += pa[i][j];
+                    print(str + "\n");
+                }
+                print("\n");
+                print("\n");
+                if (m == 10) {
+                    print("SORRY, YOU LOSE.  THE WORD WAS " + as + "\n");
+                    print("YOU MISSED THAT ONE.  DO YOU ");
+                    break;
+                }
+            } else {
+                for (i = 1; i <= l; i++)
+                    if (da[i] == "-")
+                        break;
+                if (i > l) {
+                    print("YOU FOUND THE WORD!\n");
+                    break;
+                }
+                print("\n");
+                for (i = 1; i <= l; i++)
+                    print(da[i]);
+                print("\n");
+                print("\n");
+                print("WHAT IS YOUR GUESS FOR THE WORD");
+                bs = await input();
+                if (as == bs) {
+                    print("RIGHT!!  IT TOOK YOU " + t1 + " GUESSES!\n");
+                    break;
+                }
+                print("WRONG.  TRY ANOTHER LETTER.\n");
+                print("\n");
+            }
+        }
+        print("WANT ANOTHER WORD");
+        str = await input();
+        if (str != "YES")
+            break;
+    }
+    print("\n");
+    print("IT'S BEEN FUN!  BYE FOR NOW.\n");
+    // Lines 620 and 990 unused in original
+}
+
+main();
diff --git a/45 Hello/javascript/hello.html b/45 Hello/javascript/hello.html
new file mode 100644
index 00000000..ac6fe180
--- /dev/null
+++ b/45 Hello/javascript/hello.html	
@@ -0,0 +1,9 @@
+
+
+HELLO
+
+
+

+
+
+
diff --git a/45 Hello/javascript/hello.js b/45 Hello/javascript/hello.js
new file mode 100644
index 00000000..d79b15f8
--- /dev/null
+++ b/45 Hello/javascript/hello.js	
@@ -0,0 +1,163 @@
+// HELLO
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main control section
+async function main()
+{
+    print(tab(33) + "HELLO\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("HELLO.  MY NAME IS CREATIVE COMPUTER.\n");
+    print("\n");
+    print("\n");
+    print("WHAT'S YOUR NAME");
+    ns = await input();
+    print("\n");
+    print("HI THERE, " + ns + ", ARE YOU ENJOYING YOURSELF HERE");
+    while (1) {
+        bs = await input();
+        print("\n");
+        if (bs == "YES") {
+            print("I'M GLAD TO HEAR THAT, " + ns + ".\n");
+            print("\n");
+            break;
+        } else if (bs == "NO") {
+            print("OH, I'M SORRY TO HEAR THAT, " + ns + ". MAYBE WE CAN\n");
+            print("BRIGHTEN UP YOUR VISIT A BIT.\n");
+            break;
+        } else {
+            print("PLEASE ANSWER 'YES' OR 'NO'.  DO YOU LIKE IT HERE");
+        }
+    }
+    print("\n");
+    print("SAY, " + ns + ", I CAN SOLVED ALL KINDS OF PROBLEMS EXCEPT\n");
+    print("THOSE DEALING WITH GREECE.  WHAT KIND OF PROBLEMS DO\n");
+    print("YOU HAVE (ANSWER SEX, HEALTH, MONEY, OR JOB)");
+    while (1) {
+        cs = await input();
+        print("\n");
+        if (cs != "SEX" && cs != "HEALTH" && cs != "MONEY" && cs != "JOB") {
+            print("OH, " + ns + ", YOUR ANSWER OF " + cs + " IS GREEK TO ME.\n");
+        } else if (cs == "JOB") {
+            print("I CAN SYMPATHIZE WITH YOU " + ns + ".  I HAVE TO WORK\n");
+            print("VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES\n");
+            print("REALLY BEAT ON MY KEYBOARD.  MY ADVICE TO YOU, " + ns + ",\n");
+            print("IS TO OPEN A RETAIL COMPUTER STORE.  IT'S GREAT FUN.\n");
+        } else if (cs == "MONEY") {
+            print("SORRY, " + ns + ", I'M BROKE TOO.  WHY DON'T YOU SELL\n");
+            print("ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING\n");
+            print("SO YOU WON'T NEED SO MUCH MONEY?\n");
+        } else if (cs == "HEALTH") {
+            print("MY ADVICE TO YOU " + ns + " IS:\n");
+            print("     1.  TAKE TWO ASPRIN\n");
+            print("     2.  DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)\n");
+            print("     3.  GO TO BED (ALONE)\n");
+        } else {
+            print("IS YOUR PROBLEM TOO MUCH OR TOO LITTLE");
+            while (1) {
+                ds = await input();
+                print("\n");
+                if (ds == "TOO MUCH") {
+                    print("YOU CALL THAT A PROBLEM?!!  I SHOULD HAVE SUCH PROBLEMS!\n");
+                    print("IF IT BOTHERS YOU, " + ns + ", TAKE A COLD SHOWER.\n");
+                    break;
+                } else if (ds == "TOO LITTLE") {
+                    print("WHY ARE YOU HERE IN SUFFERN, " + ns + "?  YOU SHOULD BE\n");
+                    print("IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME\n");
+                    print("REAL ACTION.\n");
+                    break;
+                } else {
+                    print("DON'T GET ALL SHOOK, " + ns + ", JUST ANSWER THE QUESTION\n");
+                    print("WITH 'TOO MUCH' OR 'TOO LITTLE'.  WHICH IS IT");
+                }
+            }
+        }
+        print("\n");
+        print("ANY MORE PROBLEMS YOU WANT SOLVED, " + ns);
+        es = await input();
+        print("\n");
+        if (es == "YES") {
+            print("WHAT KIND (SEX, MONEY, HEALTH, JOB)");
+        } else if (es == "NO") {
+            print("THAT WILL BE $5.00 FOR THE ADVICE, " + ns + ".\n");
+            print("PLEASE LEAVE THE MONEY ON THE TERMINAL.\n");
+            print("\n");
+//            d = new Date().valueOf();
+//            while (new Date().valueOf() - d < 2000) ;
+            print("\n");
+            print("\n");
+            while (1) {
+                print("DID YOU LEAVE THE MONEY");
+                gs = await input();
+                print("\n");
+                if (gs == "YES") {
+                    print("HEY, " + ns + "??? YOU LEFT NO MONEY AT ALL!\n");
+                    print("YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING.\n");
+                    print("\n");
+                    print("WHAT A RIP OFF, " + ns + "!!!\n");
+                    print("\n");
+                    break;
+                } else if (gs == "NO") {
+                    print("THAT'S HONEST, " + ns + ", BUT HOW DO YOU EXPECT\n");
+                    print("ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENT\n");
+                    print("DON'T PAY THEIR BILLS?\n");
+                    break;
+                } else {
+                    print("YOUR ANSWER OF '" + gs + "' CONFUSES ME, " + ns + ".\n");
+                    print("PLEASE RESPOND WITH 'YES' OR 'NO'.\n");
+                }
+            }
+            break;
+        }
+    }
+    print("\n");
+    print("TAKE A WALK, " + ns + ".\n");
+    print("\n");
+    print("\n");
+    // Line 390 not used in original
+}
+
+main();

From 7ede33f2c91b59580f98c5edea5fb2c42405da24 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sat, 27 Feb 2021 20:26:58 -0800
Subject: [PATCH 078/749] Port HELLO to Python

broke the file into functions to be easier to understand. There's (deliberate?) dead code in the original BASIC code, which I preserved - I don't see any way to get to the "happy" ending.
---
 45 Hello/python/hello.py | 207 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 207 insertions(+)
 create mode 100644 45 Hello/python/hello.py

diff --git a/45 Hello/python/hello.py b/45 Hello/python/hello.py
new file mode 100644
index 00000000..35a37c00
--- /dev/null
+++ b/45 Hello/python/hello.py	
@@ -0,0 +1,207 @@
+"""
+HELLO
+
+A very simple "chat" bot.
+
+Warning, the advice given here is bad.
+
+Ported by Dave LeCompte
+"""
+
+import time
+
+
+def print_with_tab(space_count, msg):
+    if space_count > 0:
+        spaces = " " * space_count
+    else:
+        spaces = ""
+    print(spaces + msg)
+
+
+def get_yes_or_no():
+    msg = input()
+    if msg.upper() == "YES":
+        return True, True, msg
+    elif msg.upper() == "NO":
+        return True, False, msg
+    else:
+        return False, None, msg
+
+
+def ask_enjoy_question(user_name):
+    print(f"HI THERE, {user_name}, ARE YOU ENJOYING YOURSELF HERE?")
+
+    has_answer = False
+    while True:
+        valid, value, msg = get_yes_or_no()
+
+        if valid:
+            if value:
+                print(f"I'M GLAD TO HEAR THAT, {user_name}.")
+                print()
+            else:
+                print(f"OH, I'M SORRY TO HEAR THAT, {user_name}. MAYBE WE CAN")
+                print("BRIGHTEN UP YOUR VISIT A BIT.")
+            break
+        else:
+            print(f"{user_name}, I DON'T UNDERSTAND YOUR ANSWER OF '{msg}'.")
+            print("PLEASE ANSWER 'YES' OR 'NO'.  DO YOU LIKE IT HERE?")
+
+
+def prompt_for_problems(user_name):
+    print()
+    print(f"SAY, {user_name}, I CAN SOLVE ALL KINDS OF PROBLEMS EXCEPT")
+    print("THOSE DEALING WITH GREECE.  WHAT KIND OF PROBLEMS DO")
+    print("YOU HAVE? (ANSWER SEX, HEALTH, MONEY, OR JOB)")
+
+    problem_type = input().upper()
+    return problem_type
+
+
+def prompt_too_much_or_too_little():
+    answer = input().upper()
+    if answer == "TOO MUCH":
+        return True, True
+    elif answer == "TOO LITTLE":
+        return True, False
+    return False, None
+
+
+def solve_sex_problem(user_name):
+    print("IS YOUR PROBLEM TOO MUCH OR TOO LITTLE?")
+    while True:
+        valid, too_much = prompt_too_much_or_too_little()
+        if valid:
+            if too_much:
+                print(f"YOU CALL THAT A PROBLEM?!!  I SHOULD HAVE SUCH PROBLEMS!")
+                print(f"IF IT BOTHERS YOU, {user_name}, TAKE A COLD SHOWER.")
+            else:
+                print(f"WHY ARE YOU HERE IN SUFFERN, {user_name}?  YOU SHOULD BE")
+                print(f"IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME")
+                print(f"REAL ACTION.")
+            return
+        else:
+            print(f"DON'T GET ALL SHOOK, {user_name}, JUST ANSWER THE QUESTION")
+            print(f"WITH 'TOO MUCH' OR 'TOO LITTLE'.  WHICH IS IT?")
+
+
+def solve_money_problem(user_name):
+    print(f"SORRY, {user_name}, I'M BROKE TOO.  WHY DON'T YOU SELL")
+    print("ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING")
+    print("SO YOU WON'T NEED SO MUCH MONEY?")
+
+
+def solve_health_problem(user_name):
+    print(f"MY ADVICE TO YOU {user_name} IS:")
+    print("     1.  TAKE TWO ASPRIN")
+    print("     2.  DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)")
+    print("     3.  GO TO BED (ALONE)")
+
+
+def solve_job_problem(user_name):
+    print(f"I CAN SYMPATHIZE WITH YOU {user_name}.  I HAVE TO WORK")
+    print("VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES")
+    print(f"REALLY BEAT ON MY KEYBOARD.  MY ADVICE TO YOU, {user_name},")
+    print("IS TO OPEN A RETAIL COMPUTER STORE.  IT'S GREAT FUN.")
+
+
+def alert_unknown_problem_type(user_name, problem_type):
+    print(f"OH, {user_name}, YOUR ANSWER OF {problem_type} IS GREEK TO ME.")
+
+
+def ask_question_loop(user_name):
+    while True:
+        problem_type = prompt_for_problems(user_name)
+        if problem_type == "SEX":
+            solve_sex_problem(user_name)
+        elif problem_type == "HEALTH":
+            solve_health_problem(user_name)
+        elif problem_type == "MONEY":
+            solve_money_problem(user_name)
+        elif problem_type == "JOB":
+            solve_job_problem(user_name)
+        else:
+            alert_unknown_problem_type(user_name, problem_type)
+
+        while True:
+            print()
+            print(f"ANY MORE PROBLEMS YOU WANT SOLVED, {user_name}?")
+
+            valid, value, msg = get_yes_or_no()
+            if valid:
+                if value:
+                    print("WHAT KIND (SEX, MONEY, HEALTH, JOB)")
+                    break
+                else:
+                    return
+            print(f"JUST A SIMPLE 'YES' OR 'NO' PLEASE, {user_name}.")
+
+
+def ask_for_fee(user_name):
+    print()
+    print(f"THAT WILL BE $5.00 FOR THE ADVICE, {user_name}.")
+    print(f"PLEASE LEAVE THE MONEY ON THE TERMINAL.")
+    time.sleep(4)
+    print()
+    print()
+    print()
+    print("DID YOU LEAVE THE MONEY?")
+
+    while True:
+        valid, value, msg = get_yes_or_no()
+        if valid:
+            if value:
+                print(f"HEY, {user_name}, YOU LEFT NO MONEY AT ALL!")
+                print("YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING.")
+                print()
+                print(f"WHAT A RIP OFF, {user_name}!!!")
+                print()
+            else:
+                print(f"THAT'S HONEST, {user_name}, BUT HOW DO YOU EXPECT")
+                print("ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENTS")
+                print("DON'T PAY THEIR BILLS?")
+            return
+        else:
+            print(f"YOUR ANSWER OF '{msg}' CONFUSES ME, {user_name}.")
+            print("PLEASE RESPOND WITH 'YES' or 'NO'.")
+
+
+def unhappy_goodbye(user_name):
+    print()
+    print(f"TAKE A WALK, {user_name}.")
+    print()
+    print()
+
+
+def happy_goodbye(user_name):
+    print(f"NICE MEETING YOU, {user_name}, HAVE A NICE DAY.")
+
+
+def main():
+    print_with_tab(33, "HELLO")
+    print_with_tab(15, "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+    print("HELLO.  MY NAME IS CREATIVE COMPUTER.")
+    print()
+    print()
+    print("WHAT'S YOUR NAME?")
+    user_name = input()
+    print()
+
+    ask_enjoy_question(user_name)
+
+    ask_question_loop(user_name)
+
+    ask_for_fee(user_name)
+
+    if False:
+        happy_goodbye(user_name)
+    else:
+        unhappy_goodbye(user_name)
+
+
+if __name__ == "__main__":
+    main()

From 7c28a2216b8dc3efce6eb5fa2335a9925e9d0fe3 Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sat, 27 Feb 2021 22:07:45 -0700
Subject: [PATCH 079/749] Be more explicit with cell values

---
 02 Amazing/java/Amazing.java | 86 +++++++++++++++++++-----------------
 1 file changed, 46 insertions(+), 40 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index 6057e932..5cbe5af0 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -20,6 +20,13 @@ public class Amazing {
         GO_DOWN,
     }
 
+    final static int FIRST_COL = 0;
+    final static int FIRST_ROW = 0;
+
+    final static int EXIT_UNSET = 0;
+    final static int EXIT_DOWN = 1;
+    final static int EXIT_RIGHT = 2;
+
     public void play() {
         out.println(tab(28) + "AMAZING PROGRAM");
         out.println(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
@@ -37,29 +44,11 @@ public class Amazing {
         } while (width < 1 || length < 1);
 
 
-        Integer[][] used = new Integer[length][width];
-        for (int i=0; i < length; i++) {
-            used[i] = new Integer[width];
-            for (int j = 0; j < width; j++) {
-                used[i][j] = 0;
-            }
-        }
+        Integer[][] walls = buildGrid(width, length);
+        Integer[][] used = buildGrid(width, length);
 
-        Integer[][] walls = new Integer[length][width];
-        for (int i=0; i < length; i++) {
-            walls[i] = new Integer[width];
-            for (int j = 0; j < width; j++) {
-                walls[i][j] = 0;
-            }
-        }
-
-        int EXIT_DOWN = 1;
-        int EXIT_RIGHT = 2;
-
-        int FIRST_COL = 0;
-        int LAST_COL = width - 1;
-        int FIRST_ROW = 0;
-        int LAST_ROW = length - 1;
+        int lastCol = width - 1;
+        int lastRow = length - 1;
 
         int enterCol = random(0, width);
         int col = enterCol;
@@ -72,20 +61,7 @@ public class Amazing {
         count++;
 
         while (count != totalWalls) {
-            ArrayList possibleDirs = new ArrayList<>(Arrays.asList(Direction.values()));
-
-            if (col == FIRST_COL || 0 != used[row][col - 1]) {
-                possibleDirs.remove(Direction.GO_LEFT);
-            }
-            if (row == FIRST_ROW || 0 != used[row - 1][col]) {
-                possibleDirs.remove(Direction.GO_UP);
-            }
-            if (col == LAST_COL || 0 != used[row][col + 1]) {
-                possibleDirs.remove(Direction.GO_RIGHT);
-            }
-            if (row == LAST_ROW || 0 != used[row + 1][col]) {
-                possibleDirs.remove(Direction.GO_DOWN);
-            }
+            ArrayList possibleDirs = getPossibleDirs(used, lastCol, lastRow, col, row);
 
             if (possibleDirs.size() != 0) {
                 Direction direction = possibleDirs.get(random(0, possibleDirs.size()));
@@ -106,9 +82,9 @@ public class Amazing {
                 count++;
             } else {
                 do {
-                    if (col != width - 1) {
+                    if (col != lastCol) {
                         col++;
-                    } else if (row != length - 1) {
+                    } else if (row != lastRow) {
                         row++;
                         col = 0;
                     } else {
@@ -123,6 +99,7 @@ public class Amazing {
         row = length - 1;
         walls[row][col] = walls[row][col] + 1;
 
+        // top line
         for (int i=0; i < width; i++) {
             if (i == enterCol) {
                 out.print(".  ");
@@ -135,7 +112,7 @@ public class Amazing {
         for (int i=0; i < length; i++) {
             out.print("I");
             for (int j = 0; j < width; j++) {
-                if (walls[i][j] < 2) {
+                if (walls[i][j] == EXIT_UNSET || walls[i][j] == EXIT_DOWN) {
                     out.print("  I");
                 } else {
                     out.print("   ");
@@ -143,7 +120,7 @@ public class Amazing {
             }
             out.println();
             for (int j = 0; j < width; j++) {
-                if (walls[i][j] == 0 || walls[i][j] == 2) {
+                if (walls[i][j] == EXIT_UNSET || walls[i][j] == EXIT_RIGHT) {
                     out.print(":--");
                 } else {
                     out.print(":  ");
@@ -153,6 +130,35 @@ public class Amazing {
         }
     }
 
+    private Integer[][] buildGrid(int width, int length) {
+        Integer[][] grid = new Integer[length][width];
+        for (int i=0; i < length; i++) {
+            grid[i] = new Integer[width];
+            for (int j = 0; j < width; j++) {
+                grid[i][j] = EXIT_UNSET;
+            }
+        }
+        return grid;
+    }
+
+    private ArrayList getPossibleDirs(Integer[][] used, int lastCol, int lastRow, int col, int row) {
+        ArrayList possibleDirs = new ArrayList<>(Arrays.asList(Direction.values()));
+
+        if (col == FIRST_COL || 0 != used[row][col - 1]) {
+            possibleDirs.remove(Direction.GO_LEFT);
+        }
+        if (row == FIRST_ROW || 0 != used[row - 1][col]) {
+            possibleDirs.remove(Direction.GO_UP);
+        }
+        if (col == lastCol || 0 != used[row][col + 1]) {
+            possibleDirs.remove(Direction.GO_RIGHT);
+        }
+        if (row == lastRow || 0 != used[row + 1][col]) {
+            possibleDirs.remove(Direction.GO_DOWN);
+        }
+        return possibleDirs;
+    }
+
     private String displayTextAndGetInput(String text) {
         out.print(text);
         return kbScanner.next();

From 1dcc302ce74d5e74b21d96f904566020b22d3c15 Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sat, 27 Feb 2021 22:17:10 -0700
Subject: [PATCH 080/749] Use single grade rather than two arrays

---
 02 Amazing/java/Amazing.java | 78 ++++++++++++++++++++----------------
 1 file changed, 44 insertions(+), 34 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index 5cbe5af0..ae9e886c 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -44,11 +44,7 @@ public class Amazing {
         } while (width < 1 || length < 1);
 
 
-        Integer[][] walls = buildGrid(width, length);
-        Integer[][] used = buildGrid(width, length);
-
-        int lastCol = width - 1;
-        int lastRow = length - 1;
+        Grid grid = new Grid(length, width);
 
         int enterCol = random(0, width);
         int col = enterCol;
@@ -57,47 +53,47 @@ public class Amazing {
         int totalWalls = width * length + 1;
 
         // set up entrance
-        used[row][col] = count;
+        grid.cells[row][col].count = count;
         count++;
 
         while (count != totalWalls) {
-            ArrayList possibleDirs = getPossibleDirs(used, lastCol, lastRow, col, row);
+            ArrayList possibleDirs = getPossibleDirs(grid, col, row);
 
             if (possibleDirs.size() != 0) {
                 Direction direction = possibleDirs.get(random(0, possibleDirs.size()));
                 if (direction == Direction.GO_LEFT) {
                     col--;
-                    walls[row][col] = EXIT_RIGHT;
+                    grid.cells[row][col].exitType = EXIT_RIGHT;
                 } else if (direction == Direction.GO_UP) {
                     row--;
-                    walls[row][col] = EXIT_DOWN;
+                    grid.cells[row][col].exitType = EXIT_DOWN;
                 } else if (direction == Direction.GO_RIGHT) {
-                    walls[row][col] = walls[row][col] + EXIT_RIGHT;
+                    grid.cells[row][col].exitType = grid.cells[row][col].exitType + EXIT_RIGHT;
                     col++;
                 } else if (direction == Direction.GO_DOWN) {
-                    walls[row][col] = walls[row][col] + EXIT_DOWN;
+                    grid.cells[row][col].exitType = grid.cells[row][col].exitType + EXIT_DOWN;
                     row++;
                 }
-                used[row][col] = count;
+                grid.cells[row][col].count = count;
                 count++;
             } else {
                 do {
-                    if (col != lastCol) {
+                    if (col != grid.lastCol) {
                         col++;
-                    } else if (row != lastRow) {
+                    } else if (row != grid.lastRow) {
                         row++;
                         col = 0;
                     } else {
                         row = 0;
                         col = 0;
                     }
-                } while (used[row][col] == 0);
+                } while (grid.cells[row][col].count == 0);
             }
         }
 
         col = random(0, width - 1);
         row = length - 1;
-        walls[row][col] = walls[row][col] + 1;
+        grid.cells[row][col].exitType = grid.cells[row][col].exitType + 1;
 
         // top line
         for (int i=0; i < width; i++) {
@@ -112,7 +108,7 @@ public class Amazing {
         for (int i=0; i < length; i++) {
             out.print("I");
             for (int j = 0; j < width; j++) {
-                if (walls[i][j] == EXIT_UNSET || walls[i][j] == EXIT_DOWN) {
+                if (grid.cells[i][j].exitType == EXIT_UNSET || grid.cells[i][j].exitType == EXIT_DOWN) {
                     out.print("  I");
                 } else {
                     out.print("   ");
@@ -120,7 +116,7 @@ public class Amazing {
             }
             out.println();
             for (int j = 0; j < width; j++) {
-                if (walls[i][j] == EXIT_UNSET || walls[i][j] == EXIT_RIGHT) {
+                if (grid.cells[i][j].exitType == EXIT_UNSET || grid.cells[i][j].exitType == EXIT_RIGHT) {
                     out.print(":--");
                 } else {
                     out.print(":  ");
@@ -130,30 +126,19 @@ public class Amazing {
         }
     }
 
-    private Integer[][] buildGrid(int width, int length) {
-        Integer[][] grid = new Integer[length][width];
-        for (int i=0; i < length; i++) {
-            grid[i] = new Integer[width];
-            for (int j = 0; j < width; j++) {
-                grid[i][j] = EXIT_UNSET;
-            }
-        }
-        return grid;
-    }
-
-    private ArrayList getPossibleDirs(Integer[][] used, int lastCol, int lastRow, int col, int row) {
+    private ArrayList getPossibleDirs(Grid grid, int col, int row) {
         ArrayList possibleDirs = new ArrayList<>(Arrays.asList(Direction.values()));
 
-        if (col == FIRST_COL || 0 != used[row][col - 1]) {
+        if (col == FIRST_COL || 0 != grid.cells[row][col - 1].count) {
             possibleDirs.remove(Direction.GO_LEFT);
         }
-        if (row == FIRST_ROW || 0 != used[row - 1][col]) {
+        if (row == FIRST_ROW || 0 != grid.cells[row - 1][col].count) {
             possibleDirs.remove(Direction.GO_UP);
         }
-        if (col == lastCol || 0 != used[row][col + 1]) {
+        if (col == grid.lastCol || 0 != grid.cells[row][col + 1].count) {
             possibleDirs.remove(Direction.GO_RIGHT);
         }
-        if (row == lastRow || 0 != used[row + 1][col]) {
+        if (row == grid.lastRow || 0 != grid.cells[row + 1][col].count) {
             possibleDirs.remove(Direction.GO_DOWN);
         }
         return possibleDirs;
@@ -188,5 +173,30 @@ public class Amazing {
         Random random = new Random();
         return random.nextInt(max - min) + min;
     }
+
+    public class Cell {
+        int exitType = EXIT_UNSET;
+        int count = 0;
+    }
+
+    public class Grid {
+        Cell[][] cells;
+
+        int lastCol;
+        int lastRow;
+
+        public Grid(int length, int width) {
+            lastCol = width - 1;
+            lastRow = length - 1;
+
+            cells = new Cell[length][width];
+            for (int i=0; i < length; i++) {
+                cells[i] = new Cell[width];
+                for (int j = 0; j < width; j++) {
+                    cells[i][j] = new Cell();
+                }
+            }
+        }
+    }
 }
 

From d0c396b73d4fc3874a7be552fbb66353951aa38a Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sat, 27 Feb 2021 22:28:37 -0700
Subject: [PATCH 081/749] Use cell for possible directions

---
 02 Amazing/java/Amazing.java | 40 ++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index ae9e886c..cd7c9cdd 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -43,7 +43,6 @@ public class Amazing {
             }
         } while (width < 1 || length < 1);
 
-
         Grid grid = new Grid(length, width);
 
         int enterCol = random(0, width);
@@ -57,7 +56,7 @@ public class Amazing {
         count++;
 
         while (count != totalWalls) {
-            ArrayList possibleDirs = getPossibleDirs(grid, col, row);
+            ArrayList possibleDirs = getPossibleDirs(grid, new Cell(row, col));
 
             if (possibleDirs.size() != 0) {
                 Direction direction = possibleDirs.get(random(0, possibleDirs.size()));
@@ -126,19 +125,19 @@ public class Amazing {
         }
     }
 
-    private ArrayList getPossibleDirs(Grid grid, int col, int row) {
+    private ArrayList getPossibleDirs(Grid grid, Cell cell) {
         ArrayList possibleDirs = new ArrayList<>(Arrays.asList(Direction.values()));
 
-        if (col == FIRST_COL || 0 != grid.cells[row][col - 1].count) {
+        if (cell.col == FIRST_COL || grid.isPrevColSet(cell)) {
             possibleDirs.remove(Direction.GO_LEFT);
         }
-        if (row == FIRST_ROW || 0 != grid.cells[row - 1][col].count) {
+        if (cell.row == FIRST_ROW || grid.isPrevRowSet(cell)) {
             possibleDirs.remove(Direction.GO_UP);
         }
-        if (col == grid.lastCol || 0 != grid.cells[row][col + 1].count) {
+        if (cell.col == grid.lastCol || grid.isNextColSet(cell)) {
             possibleDirs.remove(Direction.GO_RIGHT);
         }
-        if (row == grid.lastRow || 0 != grid.cells[row + 1][col].count) {
+        if (cell.row == grid.lastRow || grid.isNextRowSet(cell)) {
             possibleDirs.remove(Direction.GO_DOWN);
         }
         return possibleDirs;
@@ -177,6 +176,14 @@ public class Amazing {
     public class Cell {
         int exitType = EXIT_UNSET;
         int count = 0;
+
+        int col;
+        int row;
+
+        public Cell(int row, int col) {
+            this.row = row;
+            this.col = col;
+        }
     }
 
     public class Grid {
@@ -193,10 +200,27 @@ public class Amazing {
             for (int i=0; i < length; i++) {
                 cells[i] = new Cell[width];
                 for (int j = 0; j < width; j++) {
-                    cells[i][j] = new Cell();
+                    cells[i][j] = new Cell(i, j);
                 }
             }
         }
+
+        public boolean isPrevColSet(Cell cell) {
+            return 0 != cells[cell.row][cell.col - 1].count;
+        }
+
+        public boolean isPrevRowSet(Cell cell) {
+            return 0 != cells[cell.row - 1][cell.col].count;
+        }
+
+        public boolean isNextColSet(Cell cell) {
+            return 0 != cells[cell.row][cell.col + 1].count;
+        }
+
+        public boolean isNextRowSet(Cell cell) {
+            return 0 != cells[cell.row + 1][cell.col].count;
+        }
+
     }
 }
 

From 37681a40b66fb54590a20c6718a1a8e52e44cc26 Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sat, 27 Feb 2021 22:33:03 -0700
Subject: [PATCH 082/749] Add setup to grid

---
 02 Amazing/java/Amazing.java | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index cd7c9cdd..9bb8b4ae 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -45,15 +45,13 @@ public class Amazing {
 
         Grid grid = new Grid(length, width);
 
-        int enterCol = random(0, width);
-        int col = enterCol;
+
         int row = 0;
-        int count = 1;
         int totalWalls = width * length + 1;
 
-        // set up entrance
-        grid.cells[row][col].count = count;
-        count++;
+        int enterCol = grid.setup();
+        int col = enterCol;
+        int count = 2;
 
         while (count != totalWalls) {
             ArrayList possibleDirs = getPossibleDirs(grid, new Cell(row, col));
@@ -192,19 +190,28 @@ public class Amazing {
         int lastCol;
         int lastRow;
 
-        public Grid(int length, int width) {
-            lastCol = width - 1;
-            lastRow = length - 1;
+        int width;
 
-            cells = new Cell[length][width];
+        public Grid(int length, int width) {
+            this.lastCol = width - 1;
+            this.lastRow = length - 1;
+            this.width = width;
+
+            this.cells = new Cell[length][width];
             for (int i=0; i < length; i++) {
-                cells[i] = new Cell[width];
+                this.cells[i] = new Cell[width];
                 for (int j = 0; j < width; j++) {
-                    cells[i][j] = new Cell(i, j);
+                    this.cells[i][j] = new Cell(i, j);
                 }
             }
         }
 
+        public int setup() {
+            int enterCol = random(0, this.width);
+            cells[0][enterCol].count = 1;
+            return enterCol;
+        }
+
         public boolean isPrevColSet(Cell cell) {
             return 0 != cells[cell.row][cell.col - 1].count;
         }

From d188128a7c1126cd3de52d3f8114621cab08511d Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sat, 27 Feb 2021 23:37:13 -0700
Subject: [PATCH 083/749] Clean up additions

---
 02 Amazing/java/Amazing.java | 49 ++++++++++++++++++++++++++++++------
 1 file changed, 41 insertions(+), 8 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index 9bb8b4ae..fd9edd54 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -44,15 +44,14 @@ public class Amazing {
         } while (width < 1 || length < 1);
 
         Grid grid = new Grid(length, width);
-
-
-        int row = 0;
-        int totalWalls = width * length + 1;
-
         int enterCol = grid.setup();
+
+        int totalWalls = width * length + 1;
         int col = enterCol;
+        int row = 0;
         int count = 2;
 
+        Cell cell = grid.cells[row][col];
         while (count != totalWalls) {
             ArrayList possibleDirs = getPossibleDirs(grid, new Cell(row, col));
 
@@ -90,7 +89,7 @@ public class Amazing {
 
         col = random(0, width - 1);
         row = length - 1;
-        grid.cells[row][col].exitType = grid.cells[row][col].exitType + 1;
+        grid.cells[row][col].exitType += 1;
 
         // top line
         for (int i=0; i < width; i++) {
@@ -171,7 +170,7 @@ public class Amazing {
         return random.nextInt(max - min) + min;
     }
 
-    public class Cell {
+    public static class Cell {
         int exitType = EXIT_UNSET;
         int count = 0;
 
@@ -182,9 +181,19 @@ public class Amazing {
             this.row = row;
             this.col = col;
         }
+
+        @Override
+        public String toString() {
+            return "Cell{" +
+                    "exitType=" + exitType +
+                    ", count=" + count +
+                    ", col=" + col +
+                    ", row=" + row +
+                    '}';
+        }
     }
 
-    public class Grid {
+    public static class Grid {
         Cell[][] cells;
 
         int lastCol;
@@ -228,6 +237,30 @@ public class Amazing {
             return 0 != cells[cell.row + 1][cell.col].count;
         }
 
+        public Cell getPrevCol(Cell cell) { return cells[cell.row][--cell.col]; }
+        public Cell getPrevRow(Cell cell) { return cells[--cell.row][cell.col]; }
+        public Cell getNextCol(Cell cell) { return cells[cell.row][++cell.col]; }
+        public Cell getNextRow(Cell cell) { return cells[++cell.row][cell.col]; }
+
+        public Cell get(int row, int col) { return cells[row][col]; }
+
+        public Cell getFirstUnset(Cell cell) {
+            int col = cell.col;
+            int row = cell.row;
+            Cell newCell;
+            do {
+                if (col != this.lastCol) {
+                    col++;
+                } else if (row != this.lastRow) {
+                    row++;
+                    col = 0;
+                } else {
+                    row = 0;
+                    col = 0;
+                }
+            } while ((newCell = cells[row][col]).count == 0);
+            return newCell;
+        }
     }
 }
 

From 5b2368fb9cf346d47bad02e77b040ebaecf5fc1d Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sat, 27 Feb 2021 23:45:58 -0700
Subject: [PATCH 084/749] More cell

---
 02 Amazing/java/Amazing.java | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index fd9edd54..de262ca8 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -51,27 +51,26 @@ public class Amazing {
         int row = 0;
         int count = 2;
 
-        Cell cell = grid.cells[row][col];
         while (count != totalWalls) {
-            ArrayList possibleDirs = getPossibleDirs(grid, new Cell(row, col));
+            Cell cell = grid.cells[row][col];
+            ArrayList possibleDirs = getPossibleDirs(grid, cell);
 
             if (possibleDirs.size() != 0) {
                 Direction direction = possibleDirs.get(random(0, possibleDirs.size()));
                 if (direction == Direction.GO_LEFT) {
-                    col--;
-                    grid.cells[row][col].exitType = EXIT_RIGHT;
+                    cell = grid.cells[row][--col];
+                    cell.exitType = EXIT_RIGHT;
                 } else if (direction == Direction.GO_UP) {
-                    row--;
-                    grid.cells[row][col].exitType = EXIT_DOWN;
+                    cell = grid.cells[--row][col];
+                    cell.exitType = EXIT_DOWN;
                 } else if (direction == Direction.GO_RIGHT) {
-                    grid.cells[row][col].exitType = grid.cells[row][col].exitType + EXIT_RIGHT;
-                    col++;
+                    cell.exitType = cell.exitType + EXIT_RIGHT;
+                    cell = grid.cells[row][++col];
                 } else if (direction == Direction.GO_DOWN) {
-                    grid.cells[row][col].exitType = grid.cells[row][col].exitType + EXIT_DOWN;
-                    row++;
+                    cell.exitType = cell.exitType + EXIT_DOWN;
+                    cell = grid.cells[++row][col];
                 }
-                grid.cells[row][col].count = count;
-                count++;
+                cell.count = count++;
             } else {
                 do {
                     if (col != grid.lastCol) {

From cd1329cee458010ac708e2383782f27138df8642 Mon Sep 17 00:00:00 2001
From: Chris Reuter 
Date: Sun, 28 Feb 2021 02:06:51 -0500
Subject: [PATCH 085/749] Ported Bunny to Ruby.

Actually, did it twice.  One uses the original data, the other is more
readable.
---
 19 Bunny/ruby/README.md         |   8 +++
 19 Bunny/ruby/bunny-faithful.rb | 101 ++++++++++++++++++++++++++
 19 Bunny/ruby/bunny-modern.rb   | 124 ++++++++++++++++++++++++++++++++
 3 files changed, 233 insertions(+)
 create mode 100644 19 Bunny/ruby/bunny-faithful.rb
 create mode 100644 19 Bunny/ruby/bunny-modern.rb

diff --git a/19 Bunny/ruby/README.md b/19 Bunny/ruby/README.md
index fb32811e..1b8e6e8f 100644
--- a/19 Bunny/ruby/README.md	
+++ b/19 Bunny/ruby/README.md	
@@ -1,3 +1,11 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
 Conversion to [Ruby](https://www.ruby-lang.org/en/)
+
+There are two versions of this program here:
+
+* `bunny-faithful.rb` tries to be faithful to the design of the original
+  BASIC program.
+* `bunny-modern.rb` takes more advantage of the features of modern
+  tools and languages.
+
diff --git a/19 Bunny/ruby/bunny-faithful.rb b/19 Bunny/ruby/bunny-faithful.rb
new file mode 100644
index 00000000..7f6681cb
--- /dev/null
+++ b/19 Bunny/ruby/bunny-faithful.rb	
@@ -0,0 +1,101 @@
+#!/bin/env ruby
+
+# Bunny - Print a large ASCII-pixel bunny icon made up of the letters
+# of the word BUNNY.
+
+# This is a recreation of bunny.bas in Ruby that attempts to remain
+# relatively faithful to the design of the original program.
+#
+# The BASIC version works by storing the image as a series of pairs of
+# numbers containing ranges of text columns that will need to be
+# filled in with non-blank characters.
+#
+# For example, the first few entries in the block of DATA statements are:
+#
+#       1,2,-1,0,2,45,50,-1 ...
+#
+#           * 1,2 means "write letters from columns 1 to 2
+#           * -1 starts a new line
+#           * 0,2 draws letters between columns 0 and 2
+#           * 45,50 draws letters between columns 45 and 50
+#           * -1 starts a new line
+# 
+# ...and so on.
+#
+# We keep the data statements as they are and redraw the image using
+# them.  (Well, we drop the last one because it's the end-of-data flag
+# and Ruby is perfectly effective at finding the end of the list.)
+#
+# One tricky bit: BASIC has a function called 'tab()' which sets the
+# output column to the given position and which the BASIC version uses
+# to pick the columns to write to.  Ruby doesn't have an equivalent
+# feature (well, not without a *lot* more complexity).  Fortunately,
+# the data always draws from left to right so we just keep track of
+# the last column written to and then add some spaces to advance to
+# where we need to be.
+# 
+
+
+# Do the thing.  (We put it in a function to keep from spewing global
+# variables all over the place.  It's not really necessary here but
+# it's good practice.)
+def main
+
+  # Print the heading.  Note the highly advanced lower-case letters.
+  puts ' '*33 + "Bunny"
+  puts ' '*15 + "Creative Computing  Morristown, New Jersey"
+
+  # Print blank lines.
+  print "\n\n\n"
+
+  # The positions to write; this is ripped from the BASIC program's
+  # DATA statements.
+  positions = [
+    1,2,-1,0,2,45,50,-1,0,5,43,52,-1,0,7,41,52,-1,    
+    1,9,37,50,-1,2,11,36,50,-1,3,13,34,49,-1,4,14,32,48,-1,
+    5,15,31,47,-1,6,16,30,45,-1,7,17,29,44,-1,8,19,28,43,-1,
+    9,20,27,41,-1,10,21,26,40,-1,11,22,25,38,-1,12,22,24,36,-1,
+    13,34,-1,14,33,-1,15,31,-1,17,29,-1,18,27,-1,
+    19,26,-1,16,28,-1,13,30,-1,11,31,-1,10,32,-1,
+    8,33,-1,7,34,-1,6,13,16,34,-1,5,12,16,35,-1,
+    4,12,16,35,-1,3,12,15,35,-1,2,35,-1,1,35,-1,
+    2,34,-1,3,34,-1,4,33,-1,6,33,-1,10,32,34,34,-1,
+    14,17,19,25,28,31,35,35,-1,15,19,23,30,36,36,-1,
+    14,18,21,21,24,30,37,37,-1,13,18,23,29,33,38,-1,
+    12,29,31,33,-1,11,13,17,17,19,19,22,22,24,31,-1,
+    10,11,17,18,22,22,24,24,29,29,-1,
+    22,23,26,29,-1,27,29,-1,28,29,-1,
+  ]
+
+  # The text we're writing.
+  text = "BUNNY"
+
+  # Draw the bunny.
+  last_pos = 0
+  while positions.size > 0
+    first = positions.shift
+
+    # If we've found -1, start a new line
+    if first == -1
+      puts
+      last_pos = 0
+      next
+    end      
+
+    # Advance to start of the range
+    print ' '*(first - last_pos)
+    last_pos = first
+
+    # Now, draw pixels:
+    second = positions.shift
+    for i in first .. second
+      print text[i % text.size] # choose the letter according to the column
+      last_pos += 1
+    end
+  end
+
+  # Print the final blank line
+  puts
+end
+
+main
diff --git a/19 Bunny/ruby/bunny-modern.rb b/19 Bunny/ruby/bunny-modern.rb
new file mode 100644
index 00000000..6bd778dd
--- /dev/null
+++ b/19 Bunny/ruby/bunny-modern.rb	
@@ -0,0 +1,124 @@
+#!/bin/env ruby
+
+# Bunny - Print a large ASCII-pixel bunny icon made up of the letters
+# of the word BUNNY.
+
+# This is a recreation of bunny.bas in Ruby that takes advantage of
+# the language's features to make the code easier to understand and
+# modify.
+#
+# Instead of storing the image as a set of ranges, we just store it as
+# ASCII art, then replace the pixes with the appropriate letters when
+# printing.  In addition to being simpler, this also lets you modify
+# the image much more easily.
+
+
+# We assume a screen width of 80.  (With modern consoles, doing this
+# accurately gets complex and it's really not worth the bother for
+# this little program so 80 columns it is.)
+ScreenWidth = 80
+
+
+# The bunny image.  Totally not the logo of a magazine that was edgy
+# in the 1970s.
+Bunny = <
Date: Sun, 28 Feb 2021 00:45:12 -0700
Subject: [PATCH 086/749] Code cleanup

---
 02 Amazing/java/Amazing.java | 121 +++++++++++++++++------------------
 1 file changed, 58 insertions(+), 63 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index de262ca8..2ff2169a 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -44,54 +44,48 @@ public class Amazing {
         } while (width < 1 || length < 1);
 
         Grid grid = new Grid(length, width);
-        int enterCol = grid.setup();
+        int enterCol = grid.setupEntrance();
 
         int totalWalls = width * length + 1;
-        int col = enterCol;
-        int row = 0;
         int count = 2;
+        Cell cell = grid.startingCell();
 
         while (count != totalWalls) {
-            Cell cell = grid.cells[row][col];
             ArrayList possibleDirs = getPossibleDirs(grid, cell);
 
             if (possibleDirs.size() != 0) {
-                Direction direction = possibleDirs.get(random(0, possibleDirs.size()));
-                if (direction == Direction.GO_LEFT) {
-                    cell = grid.cells[row][--col];
-                    cell.exitType = EXIT_RIGHT;
-                } else if (direction == Direction.GO_UP) {
-                    cell = grid.cells[--row][col];
-                    cell.exitType = EXIT_DOWN;
-                } else if (direction == Direction.GO_RIGHT) {
-                    cell.exitType = cell.exitType + EXIT_RIGHT;
-                    cell = grid.cells[row][++col];
-                } else if (direction == Direction.GO_DOWN) {
-                    cell.exitType = cell.exitType + EXIT_DOWN;
-                    cell = grid.cells[++row][col];
-                }
+                cell = setCellExit(grid, cell, possibleDirs);
                 cell.count = count++;
             } else {
-                do {
-                    if (col != grid.lastCol) {
-                        col++;
-                    } else if (row != grid.lastRow) {
-                        row++;
-                        col = 0;
-                    } else {
-                        row = 0;
-                        col = 0;
-                    }
-                } while (grid.cells[row][col].count == 0);
+                cell = grid.getFirstUnset(cell);
             }
         }
+        grid.setupExit();
 
-        col = random(0, width - 1);
-        row = length - 1;
-        grid.cells[row][col].exitType += 1;
+        writeMaze(width, grid, enterCol);
+    }
 
+    private Cell setCellExit(Grid grid, Cell cell, ArrayList possibleDirs) {
+        Direction direction = possibleDirs.get(random(0, possibleDirs.size()));
+        if (direction == Direction.GO_LEFT) {
+            cell = grid.getPrevCol(cell);
+            cell.exitType = EXIT_RIGHT;
+        } else if (direction == Direction.GO_UP) {
+            cell = grid.getPrevRow(cell);
+            cell.exitType = EXIT_DOWN;
+        } else if (direction == Direction.GO_RIGHT) {
+            cell.exitType = cell.exitType + EXIT_RIGHT;
+            cell = grid.getNextCol(cell);
+        } else if (direction == Direction.GO_DOWN) {
+            cell.exitType = cell.exitType + EXIT_DOWN;
+            cell = grid.getNextRow(cell);
+        }
+        return cell;
+    }
+
+    private void writeMaze(int width, Grid grid, int enterCol) {
         // top line
-        for (int i=0; i < width; i++) {
+        for (int i = 0; i < width; i++) {
             if (i == enterCol) {
                 out.print(".  ");
             } else {
@@ -100,18 +94,18 @@ public class Amazing {
         }
         out.println('.');
 
-        for (int i=0; i < length; i++) {
+        for (Cell[] rows : grid.cells) {
             out.print("I");
-            for (int j = 0; j < width; j++) {
-                if (grid.cells[i][j].exitType == EXIT_UNSET || grid.cells[i][j].exitType == EXIT_DOWN) {
+            for (Cell cell : rows) {
+                if (cell.exitType == EXIT_UNSET || cell.exitType == EXIT_DOWN) {
                     out.print("  I");
                 } else {
                     out.print("   ");
                 }
             }
             out.println();
-            for (int j = 0; j < width; j++) {
-                if (grid.cells[i][j].exitType == EXIT_UNSET || grid.cells[i][j].exitType == EXIT_RIGHT) {
+            for (Cell cell : rows) {
+                if (cell.exitType == EXIT_UNSET || cell.exitType == EXIT_RIGHT) {
                     out.print(":--");
                 } else {
                     out.print(":  ");
@@ -159,11 +153,6 @@ public class Amazing {
         return new String(spacesTemp);
     }
 
-    public static boolean random() {
-        Random random = new Random();
-        return random.nextBoolean();
-    }
-
     public static int random(int min, int max) {
         Random random = new Random();
         return random.nextInt(max - min) + min;
@@ -180,16 +169,6 @@ public class Amazing {
             this.row = row;
             this.col = col;
         }
-
-        @Override
-        public String toString() {
-            return "Cell{" +
-                    "exitType=" + exitType +
-                    ", count=" + count +
-                    ", col=" + col +
-                    ", row=" + row +
-                    '}';
-        }
     }
 
     public static class Grid {
@@ -199,6 +178,7 @@ public class Amazing {
         int lastRow;
 
         int width;
+        int enterCol;
 
         public Grid(int length, int width) {
             this.lastCol = width - 1;
@@ -214,10 +194,19 @@ public class Amazing {
             }
         }
 
-        public int setup() {
-            int enterCol = random(0, this.width);
-            cells[0][enterCol].count = 1;
-            return enterCol;
+        public int setupEntrance() {
+            this.enterCol = random(0, this.width);
+            cells[0][this.enterCol].count = 1;
+            return this.enterCol;
+        }
+
+        public void setupExit() {
+            int exit = random(0, width - 1);
+            cells[lastRow][exit].exitType += 1;
+        }
+
+        public Cell startingCell() {
+            return cells[0][enterCol];
         }
 
         public boolean isPrevColSet(Cell cell) {
@@ -236,12 +225,18 @@ public class Amazing {
             return 0 != cells[cell.row + 1][cell.col].count;
         }
 
-        public Cell getPrevCol(Cell cell) { return cells[cell.row][--cell.col]; }
-        public Cell getPrevRow(Cell cell) { return cells[--cell.row][cell.col]; }
-        public Cell getNextCol(Cell cell) { return cells[cell.row][++cell.col]; }
-        public Cell getNextRow(Cell cell) { return cells[++cell.row][cell.col]; }
-
-        public Cell get(int row, int col) { return cells[row][col]; }
+        public Cell getPrevCol(Cell cell) {
+            return cells[cell.row][cell.col - 1];
+        }
+        public Cell getPrevRow(Cell cell) {
+            return cells[cell.row - 1][cell.col];
+        }
+        public Cell getNextCol(Cell cell) {
+            return cells[cell.row][cell.col + 1];
+        }
+        public Cell getNextRow(Cell cell) {
+            return cells[cell.row + 1][cell.col];
+        }
 
         public Cell getFirstUnset(Cell cell) {
             int col = cell.col;

From 57a5bad47d9ed47bc58fabf0ce8340531d236d89 Mon Sep 17 00:00:00 2001
From: Topher Lamey 
Date: Sun, 28 Feb 2021 00:47:50 -0700
Subject: [PATCH 087/749] Reformatted

---
 02 Amazing/java/Amazing.java | 66 +++++++++++++++++++-----------------
 1 file changed, 34 insertions(+), 32 deletions(-)

diff --git a/02 Amazing/java/Amazing.java b/02 Amazing/java/Amazing.java
index 2ff2169a..5188f14f 100644
--- a/02 Amazing/java/Amazing.java	
+++ b/02 Amazing/java/Amazing.java	
@@ -5,27 +5,40 @@ import java.util.Scanner;
 import static java.lang.System.in;
 import static java.lang.System.out;
 
+/**
+ * Core algorithm copied from amazing.py
+ */
 public class Amazing {
 
+    final static int FIRST_COL = 0;
+    final static int FIRST_ROW = 0;
+    final static int EXIT_UNSET = 0;
+    final static int EXIT_DOWN = 1;
+    final static int EXIT_RIGHT = 2;
     private final Scanner kbScanner;
-
     public Amazing() {
         kbScanner = new Scanner(in);
     }
 
-    enum Direction {
-        GO_LEFT,
-        GO_UP,
-        GO_RIGHT,
-        GO_DOWN,
+    private static int getDelimitedValue(String text, int pos) {
+        String[] tokens = text.split(",");
+        try {
+            return Integer.parseInt(tokens[pos]);
+        } catch (Exception ex) {
+            return 0;
+        }
     }
 
-    final static int FIRST_COL = 0;
-    final static int FIRST_ROW = 0;
+    private static String tab(int spaces) {
+        char[] spacesTemp = new char[spaces];
+        Arrays.fill(spacesTemp, ' ');
+        return new String(spacesTemp);
+    }
 
-    final static int EXIT_UNSET = 0;
-    final static int EXIT_DOWN = 1;
-    final static int EXIT_RIGHT = 2;
+    public static int random(int min, int max) {
+        Random random = new Random();
+        return random.nextInt(max - min) + min;
+    }
 
     public void play() {
         out.println(tab(28) + "AMAZING PROGRAM");
@@ -138,24 +151,11 @@ public class Amazing {
         return kbScanner.next();
     }
 
-    private static int getDelimitedValue(String text, int pos) {
-        String[] tokens = text.split(",");
-        try {
-            return Integer.parseInt(tokens[pos]);
-        } catch (Exception ex) {
-            return 0;
-        }
-    }
-
-    private static String tab(int spaces) {
-        char[] spacesTemp = new char[spaces];
-        Arrays.fill(spacesTemp, ' ');
-        return new String(spacesTemp);
-    }
-
-    public static int random(int min, int max) {
-        Random random = new Random();
-        return random.nextInt(max - min) + min;
+    enum Direction {
+        GO_LEFT,
+        GO_UP,
+        GO_RIGHT,
+        GO_DOWN,
     }
 
     public static class Cell {
@@ -186,7 +186,7 @@ public class Amazing {
             this.width = width;
 
             this.cells = new Cell[length][width];
-            for (int i=0; i < length; i++) {
+            for (int i = 0; i < length; i++) {
                 this.cells[i] = new Cell[width];
                 for (int j = 0; j < width; j++) {
                     this.cells[i][j] = new Cell(i, j);
@@ -228,12 +228,15 @@ public class Amazing {
         public Cell getPrevCol(Cell cell) {
             return cells[cell.row][cell.col - 1];
         }
+
         public Cell getPrevRow(Cell cell) {
             return cells[cell.row - 1][cell.col];
         }
+
         public Cell getNextCol(Cell cell) {
             return cells[cell.row][cell.col + 1];
         }
+
         public Cell getNextRow(Cell cell) {
             return cells[cell.row + 1][cell.col];
         }
@@ -256,5 +259,4 @@ public class Amazing {
             return newCell;
         }
     }
-}
-
+}
\ No newline at end of file

From eb4da06220cf3a40aede29a8088d5a12f180db81 Mon Sep 17 00:00:00 2001
From: quamrana 
Date: Sun, 28 Feb 2021 16:14:47 +0000
Subject: [PATCH 088/749] Create bowling.py

First commit of bowling.py
---
 14 Bowling/python/bowling.py | 132 +++++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)
 create mode 100644 14 Bowling/python/bowling.py

diff --git a/14 Bowling/python/bowling.py b/14 Bowling/python/bowling.py
new file mode 100644
index 00000000..92a16440
--- /dev/null
+++ b/14 Bowling/python/bowling.py	
@@ -0,0 +1,132 @@
+import random
+
+
+def simulateRoll(pins):
+    for _ in range(20):
+        x = random.randint(0, 14)
+        if x < len(pins):
+            pins[x] = 1
+
+
+def calculate_score(rolls):
+    score = 0
+    frame = 1
+    b = 1
+    for index, pins in enumerate(rolls):
+        score += pins
+        if b == 1:
+            if pins == 10:  # strike
+                score += sum(rolls[index + 1:index + 3])
+                frame += 1
+            else:
+                b = 2
+        else:
+            if sum(rolls[index - 1:index + 1]) == 10:  # spare
+                score += rolls[index + 1]
+            b = 1
+            frame += 1
+        if frame > 10:
+            break
+
+    return score
+
+
+class Player:
+    def __init__(self, name):
+        self.name = name
+        self.rolls = []
+
+    def play_frame(self, frame):
+        extra = 0
+        prev_score = 0
+        pins = [0] * 10  # reset the pins
+        for ball in range(2):
+            simulateRoll(pins)
+            score = sum(pins)
+            self.show(pins)
+            pin_count = score - prev_score
+            self.rolls.append(pin_count)  # log the number of pins toppled this roll
+            print(f'{pin_count} for {self.name}')
+            if score - prev_score == 0:
+                print("GUTTER!!!")
+            if ball == 0:
+                if score == 10:
+                    print("STRIKE!!!")
+                    extra = 2
+                    break  # cannot roll more than once in a frame
+                else:
+                    print(f"next roll {self.name}")
+            else:
+                if score == 10:
+                    print("SPARE!")
+                    extra = 1
+
+            prev_score = score  # remember previous pins to distinguish ...
+        if frame == 9 and extra > 0:
+            print(f'Extra rolls for {self.name}')
+            pins = [0] * 10  # reset the pins
+            score = 0
+            for ball in range(extra):
+                if score == 10:
+                    pins = [0] * 10
+                simulateRoll(pins)
+                score = sum(pins)
+                self.rolls.append(score)
+
+    def __str__(self):
+        return f'{self.name}: {self.rolls}, total:{calculate_score(self.rolls)}'
+
+    def show(self, pins):
+        pins_iter = iter(pins)
+        print()
+        for row in range(4):
+            print(' ' * row, end='')
+            for _ in range(4 - row):
+                p = next(pins_iter)
+                print('O ' if p else '+ ', end='')
+            print()
+
+
+def centreText(text, width):
+    t = len(text)
+    return (' ' * ((width - t) // 2)) + text
+
+
+def main():
+    print(centreText('Bowl', 80))
+    print(centreText('CREATIVE COMPUTING MORRISTOWN, NEW JERSEY', 80))
+    print()
+    print('WELCOME TO THE ALLEY.')
+    print('BRING YOUR FRIENDS.')
+    print("OKAY LET'S FIRST GET ACQUAINTED.")
+
+    while True:
+        print()
+        if input('THE INSTRUCTIONS (Y/N)? ') in 'yY':
+            print('THE GAME OF BOWLING TAKES MIND AND SKILL. DURING THE GAME')
+            print('THE COMPUTER WILL KEEP SCORE. YOU MAY COMPETE WITH')
+            print('OTHER PLAYERS[UP TO FOUR]. YOU WILL BE PLAYING TEN FRAMES.')
+            print("ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE")
+            print('PIN IS STANDING. AFTER THE GAME THE COMPUTER WILL SHOW YOUR')
+            print('SCORES.')
+
+        total_players = int(input('FIRST OF ALL...HOW MANY ARE PLAYING? '))
+        player_names = []
+        print()
+        print('VERY GOOD...')
+        for index in range(total_players):
+            player_names.append(Player(input(f'Enter name for player {index + 1}: ')))
+
+        for frame in range(10):
+            for player in player_names:
+                player.play_frame(frame)
+
+        for player in player_names:
+            print(player)
+
+        if input('DO YOU WANT ANOTHER GAME? ') not in 'yY':
+            break
+
+
+if __name__ == '__main__':
+    main()

From 03be93b7e19a2ae1ad9107891e5141a9879d7ada Mon Sep 17 00:00:00 2001
From: quamrana 
Date: Sun, 28 Feb 2021 16:29:29 +0000
Subject: [PATCH 089/749] Update bowling.py

Added comments about the conversion. In particular noting the original had problems keeping score and never calculated the final score.
---
 14 Bowling/python/bowling.py | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/14 Bowling/python/bowling.py b/14 Bowling/python/bowling.py
index 92a16440..42eaeddb 100644
--- a/14 Bowling/python/bowling.py	
+++ b/14 Bowling/python/bowling.py	
@@ -130,3 +130,19 @@ def main():
 
 if __name__ == '__main__':
     main()
+
+
+############################################################################################
+#
+# This is a fairly straight conversion to python with some exceptions.
+# I have kept most of the upper case text that the program prints.
+# I have added the feature of giving names to players.
+# I have added a Player class to store player data in.
+# This last change works around the problems in the original storing data in a matrix.
+# The original had bugs in calculating indexes which meant that the program
+# would overwrite data in the matrix, so the results printed out contained errors.
+# The last change is to do with the strict rules which allow extra rolls if the player
+# scores a spare or strike in the last frame.
+# This program allows these extra rolls and also calculates the proper score.
+#
+############################################################################################

From 7a7b86d458dabf99f5cee873e0fd8443df97c166 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:32:34 +0000
Subject: [PATCH 090/749] First pass at 'bagels' port.

---
 05 Bagels/ruby/bagels.rb | 106 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)
 create mode 100644 05 Bagels/ruby/bagels.rb

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
new file mode 100644
index 00000000..48b3a59b
--- /dev/null
+++ b/05 Bagels/ruby/bagels.rb	
@@ -0,0 +1,106 @@
+# Bagels
+# Number guessing game.
+# Original source unknown but suspected to be
+# Lawrence Hall of Science, U.C. Berkely
+
+def print_instructions
+  puts
+  puts 'I am thinking of a three-digit number. Try to guess'
+  puts 'my number and i will give you clues as follows:'
+  puts '   PICO   - one digit correct but in the wrong position'
+  puts '   FERMI  - one digit correct and in the right position'
+  puts '   BAGELS - no digits correct'
+end
+
+def generate_number_array
+  target = 0
+  target = rand(100..999) while target.to_s.split('').uniq.size < 3
+  target.to_s.split('')
+end
+
+def puts_clue_for(guess_array, target_array)
+  clues = [].tap do |clue|
+    guess_array.each_with_index do |n, i|
+      if target_array[i] == n
+        clue << 'FERMI'
+      elsif target_array.include?(n)
+        clue << 'PICO'
+      end
+    end
+  end
+
+  # sort clues so that FERMIs come before PICOs, but
+  # you don't know which response responds to which number
+  puts clues.length > 0 ? clues.sort.join(' ') : 'BAGELS'
+end
+
+player_points = 0
+desire_to_play = true
+
+puts 'Bagels'.center(72)
+puts 'Creative Computing  Morristown, New Jersey'.center(72)
+
+5.times { puts }
+
+puts 'Would you like to the rules? [Y]es or [N]o.'
+instructions_request = gets.chomp.downcase
+
+print_instructions if %w[yes y].include?(instructions_request)
+
+while desire_to_play
+  target_number_array = generate_number_array
+
+  2.times { puts }
+  puts 'OK. I have a number in mind.'
+
+  guess_count = 0
+  guess_array = []
+
+  while (guess_array != target_number_array) && guess_count < 20
+    guess_count += 1
+
+    puts "Guess ##{guess_count}:"
+
+    guess = gets.chomp
+
+    if guess =~ /[^1-9]/
+      puts 'What?'
+      next
+    end
+
+    if guess.length != 3
+      puts 'Try guessing a three digit number'
+      next
+    end
+
+    guess_array = guess.split('')
+
+    if guess_array.uniq.size < 3
+      puts 'Oh, I forgot to tell you: the number I have in mind has no two digits the same.'
+      next
+    end
+
+    if guess_array != target_number_array
+      puts_clue_for(guess_array, target_number_array)
+      puts
+    end
+  end
+
+  if guess_array == target_number_array
+    player_points += 1
+
+    puts 'You got it!!!'
+    puts
+  else
+    puts 'Oh well.'
+    puts "That's twenty guesses. My number was #{target_number_array.join('')}."
+  end
+
+  puts
+  puts 'Would you like to play again? [Y]es or [N]o'
+  play_again_request = gets.chomp
+  desire_to_play = %w[yes y].include?(play_again_request)
+end
+
+puts "A #{player_points} point bagels buff!!"
+puts 'Hope you had fun. Bye.'

From ea73772a9e6f5e39e1230e43852a101f0e63f6e0 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:38:31 +0000
Subject: [PATCH 091/749] Target and guess should be number, not arrays.

---
 05 Bagels/ruby/bagels.rb | 38 +++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index 48b3a59b..07024559 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -12,13 +12,15 @@ def print_instructions
   puts '   BAGELS - no digits correct'
 end
 
-def generate_number_array
-  target = 0
+def generate_target
   target = rand(100..999) while target.to_s.split('').uniq.size < 3
-  target.to_s.split('')
+  target
 end
 
-def puts_clue_for(guess_array, target_array)
+def puts_clue_for(guess_number, target_number)
+  guess_array = guess_number.to_s.split("")
+  target_array = target_number.to_s.split("")
+
   clues = [].tap do |clue|
     guess_array.each_with_index do |n, i|
       if target_array[i] == n
@@ -48,45 +50,47 @@ instructions_request = gets.chomp.downcase
 print_instructions if %w[yes y].include?(instructions_request)
 
 while desire_to_play
-  target_number_array = generate_number_array
+  target = generate_target
 
   2.times { puts }
   puts 'OK. I have a number in mind.'
 
-  guess_count = 0
-  guess_array = []
+  puts target
 
-  while (guess_array != target_number_array) && guess_count < 20
+  guess_count = 0
+  guess = 0
+
+  while (guess != target) && guess_count < 20
     guess_count += 1
 
     puts "Guess ##{guess_count}:"
 
-    guess = gets.chomp
+    raw_guess = gets.chomp
 
-    if guess =~ /[^1-9]/
+    if raw_guess =~ /[^0-9]/
       puts 'What?'
       next
     end
 
-    if guess.length != 3
+    if raw_guess.length != 3
       puts 'Try guessing a three digit number'
       next
     end
 
-    guess_array = guess.split('')
-
-    if guess_array.uniq.size < 3
+    if raw_guess.split('').uniq.size < 3
       puts 'Oh, I forgot to tell you: the number I have in mind has no two digits the same.'
       next
     end
 
-    if guess_array != target_number_array
-      puts_clue_for(guess_array, target_number_array)
+    guess = raw_guess.to_i
+
+    if guess != target
+      puts_clue_for(guess, target)
       puts
     end
   end
 
-  if guess_array == target_number_array
+  if guess == target
     player_points += 1
 
     puts 'You got it!!!'

From 2fb3ca21cf82a2727eb860210ebd884a7764ff98 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:41:56 +0000
Subject: [PATCH 092/749] Letting Rubocop have its way.

---
 05 Bagels/ruby/bagels.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index 07024559..44cd31da 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -18,8 +18,8 @@ def generate_target
 end
 
 def puts_clue_for(guess_number, target_number)
-  guess_array = guess_number.to_s.split("")
-  target_array = target_number.to_s.split("")
+  guess_array = guess_number.to_s.split('')
+  target_array = target_number.to_s.split('')
 
   clues = [].tap do |clue|
     guess_array.each_with_index do |n, i|

From 08c05d464643bd056ed969711987e7d9d44498bf Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:42:28 +0000
Subject: [PATCH 093/749] Translator's notes.

---
 05 Bagels/ruby/README.md | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/05 Bagels/ruby/README.md b/05 Bagels/ruby/README.md
index fb32811e..8e47c0dd 100644
--- a/05 Bagels/ruby/README.md	
+++ b/05 Bagels/ruby/README.md	
@@ -1,3 +1,16 @@
+## BAGELS
+
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
-Conversion to [Ruby](https://www.ruby-lang.org/en/)
+Conversion to [Ruby](https://www.ruby-lang.org/en/) by [Tom Armitage](https://github.com/infovore)
+
+## Translator's notes:
+
+This is a highly imperative port. As such, it's very much, in the spirit of David Ahl's original version, and also highly un-Rubyish.
+
+A few decisions I made:
+
+* the main loop is a 'while' loop. Most games are a main loop that runs until it doesn't, and I felt that "while the player wished to keep playing, the game should run" was an appropriate structure.
+* lots of puts and gets; that feels appropriate to the Ahl implementation. No clever cli or curses libraries here.
+* the number in question, and the player's answer, are stored as numbers. They're only converted into arrays for the purpose of `puts_clue_for` - ie, when comparison is need. The original game stored them as arrays, which made sense, but given the computer says "I have a number in mind", I decided to store what was in its 'mind' as a number.
+* the `String#center` method from Ruby 2.5~ sure is handy.

From 412b10491d4580fe99ea24fe39d1b6f2033a1711 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:45:21 +0000
Subject: [PATCH 094/749] Remove golfy ternary.

---
 05 Bagels/ruby/bagels.rb | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index 44cd31da..e3c2d9f7 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -13,7 +13,10 @@ def print_instructions
 end
 
 def generate_target
-  target = rand(100..999) while target.to_s.split('').uniq.size < 3
+
+  # pick a three digit number with no repeating numbers.
+  # gien that, 102-987 is a reasonable starting point!
+  target = rand(102..987) while target.to_s.split('').uniq.size < 3
   target
 end
 
@@ -33,7 +36,11 @@ def puts_clue_for(guess_number, target_number)
 
   # sort clues so that FERMIs come before PICOs, but
   # you don't know which response responds to which number
-  puts clues.length > 0 ? clues.sort.join(' ') : 'BAGELS'
+  if clues.length > 0
+    puts clues.sort.join
+  else
+    puts 'BAGELS'
+  end
 end
 
 player_points = 0

From 7ddc519bb33928e92199384497b9d086ded0d0c9 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:45:50 +0000
Subject: [PATCH 095/749] Works better if you hide the number in mind.

---
 05 Bagels/ruby/bagels.rb | 2 --
 1 file changed, 2 deletions(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index e3c2d9f7..bbf2b3a2 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -62,8 +62,6 @@ while desire_to_play
   2.times { puts }
   puts 'OK. I have a number in mind.'
 
-  puts target
-
   guess_count = 0
   guess = 0
 

From 6d102c6c497f9afc26f01cd45d8df94ad66bb2e7 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:46:46 +0000
Subject: [PATCH 096/749] Typo.

---
 05 Bagels/ruby/bagels.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index bbf2b3a2..9dea2b78 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -1,7 +1,7 @@
 # Bagels
 # Number guessing game.
 # Original source unknown but suspected to be
-# Lawrence Hall of Science, U.C. Berkely
+# Lawrence Hall of Science, U.C. Berkeley
 
 def print_instructions
   puts

From a7e099671d077a4f49e0f3ec835560de10c0e759 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:47:01 +0000
Subject: [PATCH 097/749] Spacing.

---
 05 Bagels/ruby/bagels.rb | 1 -
 1 file changed, 1 deletion(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index 9dea2b78..00330ce1 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -13,7 +13,6 @@ def print_instructions
 end
 
 def generate_target
-
   # pick a three digit number with no repeating numbers.
   # gien that, 102-987 is a reasonable starting point!
   target = rand(102..987) while target.to_s.split('').uniq.size < 3

From 6039fb600b1ed827b6eda429d3f4c56ae2850765 Mon Sep 17 00:00:00 2001
From: Tom Armitage 
Date: Sun, 28 Feb 2021 18:48:33 +0000
Subject: [PATCH 098/749] Final tweaks.

---
 05 Bagels/ruby/bagels.rb | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb
index 00330ce1..3a4eb789 100644
--- a/05 Bagels/ruby/bagels.rb	
+++ b/05 Bagels/ruby/bagels.rb	
@@ -47,7 +47,6 @@ desire_to_play = true
 
 puts 'Bagels'.center(72)
 puts 'Creative Computing  Morristown, New Jersey'.center(72)
-
 5.times { puts }
 
 puts 'Would you like to the rules? [Y]es or [N]o.'
@@ -71,16 +70,19 @@ while desire_to_play
 
     raw_guess = gets.chomp
 
+    ## if the guess isn't numerical, sound confused
     if raw_guess =~ /[^0-9]/
       puts 'What?'
       next
     end
 
+    ## if the guess is more ore less than three digits, prompt player
     if raw_guess.length != 3
       puts 'Try guessing a three digit number'
       next
     end
 
+    ## if the guess contains duplicate numbers, give player a clue
     if raw_guess.split('').uniq.size < 3
       puts 'Oh, I forgot to tell you: the number I have in mind has no two digits the same.'
       next
@@ -106,6 +108,7 @@ while desire_to_play
 
   puts
   puts 'Would you like to play again? [Y]es or [N]o'
+
   play_again_request = gets.chomp
   desire_to_play = %w[yes y].include?(play_again_request)
 end

From 16be2e673e3d6c4557092491baa1626dc41c8ee2 Mon Sep 17 00:00:00 2001
From: Eric Fischer 
Date: Sun, 28 Feb 2021 11:25:08 -0800
Subject: [PATCH 099/749] Link to C port

---
 24 Chemist/README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/24 Chemist/README.md b/24 Chemist/README.md
index bdbe8ebf..afd39752 100644
--- a/24 Chemist/README.md	
+++ b/24 Chemist/README.md	
@@ -5,3 +5,5 @@ https://www.atariarchives.org/basicgames/showpage.php?page=42
 
 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)

From 03890e6ea016bbd52fda6ba553cefd5149367533 Mon Sep 17 00:00:00 2001
From: Christopher Oezbek 
Date: Sun, 28 Feb 2021 21:44:30 +0100
Subject: [PATCH 100/749] Added conversion of "01 Acey Ducey" to ruby

---
 01 Acey Ducey/ruby/README.md    |   2 +-
 01 Acey Ducey/ruby/aceyducey.rb | 139 ++++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 01 Acey Ducey/ruby/aceyducey.rb

diff --git a/01 Acey Ducey/ruby/README.md b/01 Acey Ducey/ruby/README.md
index fb32811e..b7a76a3e 100644
--- a/01 Acey Ducey/ruby/README.md	
+++ b/01 Acey Ducey/ruby/README.md	
@@ -1,3 +1,3 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
-Conversion to [Ruby](https://www.ruby-lang.org/en/)
+Conversion to [Ruby](https://www.ruby-lang.org/en/) by Christopher Özbek [coezbek@github](https://github.com/coezbek).
diff --git a/01 Acey Ducey/ruby/aceyducey.rb b/01 Acey Ducey/ruby/aceyducey.rb
new file mode 100644
index 00000000..b9648ef8
--- /dev/null
+++ b/01 Acey Ducey/ruby/aceyducey.rb	
@@ -0,0 +1,139 @@
+########################################################
+#
+# Acey Ducey
+#
+# From: BASIC Computer Games (1978)
+#       Edited by David Ahl
+#
+# "This is a simulation of the Acey Ducey card game.
+#  In the game, the dealer (the computer) deals two
+#  cards face up.  You have an option to bet or not to
+#  bet depending on whether or not you feel the next
+#  card dealt will have a value between the first two.
+#
+# "Your initial money is set to $100. The game keeps
+#  going on until you lose all your money or interrupt
+#  the program.
+#
+# "The original BASIC program author was Bill Palmby
+#  of Prairie View, Illinois."
+#
+# Ruby port by Christopher Oezbek, 2021
+#
+# This uses the following techniques:
+#
+#  - The programm largely consists of a GAME LOOP,
+#    which is used to represent one round.
+#  - The Kernel function rand(Range) is used to get an
+#    Integer in the (inclusive) Range of 2 to 14.
+#  - To ensure the user enters a proper Integer
+#    via the console, an inline 'rescue' statement is
+#    used.
+#  - To capture the long text in the introduction, a
+#    squiggly HEREDOC string declaration <<~ is used.
+#
+#
+########################################################
+
+puts <<~INSTRUCTIONS
+           🂡  ACEY DUCEY CARD GAME 🂱
+   CREATIVE COMPUTING - MORRISTOWN, NEW JERSEY
+
+  ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER
+  THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP
+  YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING
+  ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE
+  A VALUE BETWEEN THE FIRST TWO.
+  IF YOU DO NOT WANT TO BET IN A ROUND, ENTER 0
+INSTRUCTIONS
+
+# The player starts with 100$
+stake = 100
+
+while true # Game loop
+  puts
+  puts "YOU NOW HAVE #{stake} DOLLARS."
+  puts
+  puts "HERE ARE YOUR NEXT TWO CARDS:"
+
+  # Randomly draw two cards from 2 to 14 and make sure the first card is lower in value than the second
+  # Using array destructuring, this sorted array can be assigned to `first_card` and `second_card`
+  first_card, second_card = [rand(2..14), rand(2..14)].sort
+
+  # Helper method to convert a numeric card into a String for printing
+  def card_name(card)
+    case card
+    when 11
+      "JACK"
+    when 12
+      "QUEEN"
+    when 13
+      "KING"
+    when 14
+      "ACE"
+    else
+      card
+    end
+  end
+
+  puts card_name(first_card)
+  puts card_name(second_card)
+  puts
+  puts
+
+  # Loop until the user enters something sensible
+  while true
+    puts "WHAT IS YOUR BET? ENTER 0 IF YOU DON'T WANT TO BET (CTRL+C TO EXIT)"
+    your_bet = Integer(gets.chomp) rescue nil
+
+    if your_bet == nil || your_bet < 0
+      puts "PLEASE ENTER A POSITIVE NUMBER"
+      puts
+      next
+    end
+
+    if your_bet > stake
+      puts "SORRY, MY FRIEND, BUT YOU BET TOO MUCH."
+      puts "YOU HAVE ONLY #{stake} DOLLARS TO BET."
+      puts
+      next
+    end
+
+    break
+  end
+
+  if your_bet == 0
+    puts "CHICKEN!!"
+    next
+  end
+
+  puts "THANK YOU! YOUR BET IS #{your_bet} DOLLARS."
+  puts ""
+  puts "THE THIRD CARD IS:"
+  third_card = rand(2..14)
+  puts card_name(third_card)
+  puts
+
+  if first_card <= third_card && third_card <= second_card
+    puts "YOU WIN!!!"
+    stake += your_bet
+  else
+    puts "SORRY, YOU LOSE"
+    stake -= your_bet
+  end
+
+  if stake == 0
+    puts
+    puts "SORRY, FRIEND, BUT YOU BLEW YOUR WAD."
+    puts
+
+    puts "TRY AGAIN? (YES OR NO)"
+    if gets.chomp.downcase.start_with? 'y'
+      # Reset cash to 100
+      stake = 100
+    else
+      puts "O.K., HOPE YOU HAD FUN!"
+      exit
+    end
+  end
+end

From 8f34aeea186a0739088f6f6a38a4770ad92af4e9 Mon Sep 17 00:00:00 2001
From: Sankarsan Kampa <19631364+iamtraction@users.noreply.github.com>
Date: Mon, 1 Mar 2021 02:30:38 +0530
Subject: [PATCH 101/749] gunner: add python port

Signed-off-by: Sankarsan Kampa <19631364+iamtraction@users.noreply.github.com>
---
 42 Gunner/python/gunner.py | 85 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 42 Gunner/python/gunner.py

diff --git a/42 Gunner/python/gunner.py b/42 Gunner/python/gunner.py
new file mode 100644
index 00000000..e12c0e56
--- /dev/null
+++ b/42 Gunner/python/gunner.py	
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+#
+# Ported to Python by @iamtraction
+
+from math import sin
+from random import random
+
+
+def gunner():
+    R = int(40000 * random() + 20000)
+
+    print("\nMAXIMUM RANGE OF YOUR GUN IS", R, "YARDS.")
+
+    Z = 0
+    S1 = 0
+
+    while True:
+        T = int(R * (.1 + .8 * random()))
+        S = 0
+
+        print("\nDISTANCE TO THE TARGET IS", T, "YARDS.")
+
+        while True:
+            B = float(input("\n\nELEVATION? "))
+
+            if B > 89:
+                print("MAXIMUM ELEVATION IS 89 DEGREES.")
+                continue
+
+            if B < 1:
+                print("MINIMUM ELEVATION IS ONE DEGREE.")
+                continue
+
+            S += 1
+
+            if S < 6:
+                B2 = 2 * B / 57.3
+                I = R * sin(B2)
+                X = T - I
+                E = int(X)
+
+                if (abs(E) < 100):
+                    print("*** TARGET DESTROYED *** ", S, "ROUNDS OF AMMUNITION EXPENDED.")
+                    S1 += S
+                    if Z == 4:
+                        print("\n\nTOTAL ROUNDS EXPENDED WERE: ", S1)
+                        if S1 > 18:
+                            print("BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!")
+                            return
+                        else:
+                            print("NICE SHOOTING !!")
+                            return
+                    else:
+                        Z += 1
+                        print("\nTHE FORWARD OBSERVER HAS SIGHTED MORE ENEMY ACTIVITY...")
+                        break
+                else:
+                    if E > 100:
+                        print("SHORT OF TARGET BY", abs(E), "YARDS.")
+                    else:
+                        print("OVER TARGET BY", abs(E), "YARDS.")
+            else:
+                print("\nBOOM !!!!   YOU HAVE JUST BEEN DESTROYED BY THE ENEMY.\n\n\n")
+                print("BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!")
+                return
+
+
+if __name__ == "__main__":
+    print(" " * 33 + "GUNNER")
+    print(" " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+
+    print("\n\n\n")
+
+    print("YOU ARE THE OFFICER-IN-CHARGE, GIVING ORDERS TO A GUN")
+    print("CREW, TELLING THEM THE DEGREES OF ELEVATION YOU ESTIMATE")
+    print("WILL PLACE A PROJECTILE ON TARGET.  A HIT WITHIN 100 YARDS")
+    print("OF THE TARGET WILL DESTROY IT.")
+
+    while True:
+        gunner()
+
+        Y = input("TRY AGAIN (Y OR N)? ")
+        if (Y != "Y"):
+            print("\nOK.  RETURN TO BASE CAMP.")
+            break

From 4fa20e5694f4d8c6164f5b120f4a9ca980022d2b Mon Sep 17 00:00:00 2001
From: boltyk 
Date: Sun, 28 Feb 2021 13:31:29 -0800
Subject: [PATCH 102/749] Port Battle to C#

---
 09 Battle/csharp/Battle.csproj |   8 +
 09 Battle/csharp/Battle.sln    |  25 +++
 09 Battle/csharp/Game.cs       | 347 +++++++++++++++++++++++++++++++++
 09 Battle/csharp/Program.cs    |  12 ++
 4 files changed, 392 insertions(+)
 create mode 100644 09 Battle/csharp/Battle.csproj
 create mode 100644 09 Battle/csharp/Battle.sln
 create mode 100644 09 Battle/csharp/Game.cs
 create mode 100644 09 Battle/csharp/Program.cs

diff --git a/09 Battle/csharp/Battle.csproj b/09 Battle/csharp/Battle.csproj
new file mode 100644
index 00000000..c73e0d16
--- /dev/null
+++ b/09 Battle/csharp/Battle.csproj	
@@ -0,0 +1,8 @@
+
+
+  
+    Exe
+    netcoreapp3.1
+  
+
+
diff --git a/09 Battle/csharp/Battle.sln b/09 Battle/csharp/Battle.sln
new file mode 100644
index 00000000..241a299a
--- /dev/null
+++ b/09 Battle/csharp/Battle.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Battle", "Battle.csproj", "{154E5E43-053B-4FB1-88D0-ED7166464257}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{154E5E43-053B-4FB1-88D0-ED7166464257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{154E5E43-053B-4FB1-88D0-ED7166464257}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{154E5E43-053B-4FB1-88D0-ED7166464257}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{154E5E43-053B-4FB1-88D0-ED7166464257}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {5CC3AC8C-6CEC-4FD6-B5A0-B2376B37C42F}
+	EndGlobalSection
+EndGlobal
diff --git a/09 Battle/csharp/Game.cs b/09 Battle/csharp/Game.cs
new file mode 100644
index 00000000..c74a48ca
--- /dev/null
+++ b/09 Battle/csharp/Game.cs	
@@ -0,0 +1,347 @@
+using System;
+using System.Linq;
+
+namespace Battle
+{
+    public class Game
+    {
+        private int[,] field = new int[7, 7];
+
+        private Random random = new Random();
+
+        public void Run()
+        {
+            DisplayIntro();
+
+            while (true)
+            {
+                field = new int[7, 7];
+
+                foreach (var shipType in new []{ 1, 2, 3})
+                {
+                    foreach (var ship in new int[] { 1, 2 })
+                    {
+                        while (!SetShip(shipType, ship)) { }
+                    }
+                }
+
+                UserInteraction();
+            }
+        }
+
+        private bool SetShip(int shipType, int shipNum)
+        {
+            var shipSize = 4 - shipType;
+            int direction;
+            int[] A = new int[5];
+            int[] B = new int[5];
+            int row, col;
+
+            do
+            {
+                row = Rnd(6) + 1;
+                col = Rnd(6) + 1;
+                direction = Rnd(4) + 1;
+            } while (field[row, col] > 0);
+
+            var M = 0;
+
+            switch (direction)
+            {
+                case 1:
+                    B[1] = col;
+                    B[2] = 7;
+                    B[3] = 7;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        if (!(M > 1 || B[K] == 6 || field[row, B[K] + 1] > 0))
+                        {
+                            B[K + 1] = B[K] + 1;
+                            continue;
+                        }
+
+                        M = 2;
+                        var Z = 1;
+
+                        if (B[1] < B[2] && B[1] < B[3]) Z = B[1];
+                        if (B[2] < B[1] && B[2] < B[3]) Z = B[2];
+                        if (B[3] < B[1] && B[3] < B[2]) Z = B[3];
+
+                        if (Z == 1 || field[row, Z - 1] > 0) return false;
+
+                        B[K + 1] = Z - 1;
+                    }
+
+                    field[row, col] = 9 - 2 * shipType - shipNum;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        field[row, B[K + 1]] = field[row, col];
+                    }
+                    break;
+
+                case 2:
+                    A[1] = row;
+                    B[1] = col;
+                    A[2] = 0;
+                    A[3] = 0;
+                    B[2] = 0;
+                    B[3] = 0;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        if (!(M > 1
+                            || A[K] == 1 || B[K] == 1
+                            || field[A[K] - 1, B[K] - 1] > 0
+                            || (field[A[K] - 1, B[K]] > 0 && field[A[K] - 1, B[K]] == field[A[K], B[K] - 1])))
+                        {
+                            A[K + 1] = A[K] - 1;
+                            B[K + 1] = B[K] - 1;
+                            continue;
+                        }
+
+                        M = 2;
+                        var Z1 = 1;
+                        var Z2 = 1;
+
+                        if (A[1] > A[2] && A[1] > A[3]) Z1 = A[1];
+                        if (A[2] > A[1] && A[2] > A[3]) Z1 = A[2];
+                        if (A[3] > A[1] && A[3] > A[2]) Z1 = A[3];
+                        if (B[1] > B[2] && B[1] > B[3]) Z2 = B[1];
+                        if (B[2] > B[1] && B[2] > B[3]) Z2 = B[2];
+                        if (B[3] > B[1] && B[3] > B[2]) Z2 = B[3];
+
+                        if (Z1 == 6 || Z2 == 6
+                            || field[Z1 + 1, Z2 + 1] > 0
+                            || (field[Z1, Z2 + 1] > 0 && field[Z1, Z2 + 1] == field[Z1 + 1, Z2])) return false;
+
+                        A[K + 1] = Z1 + 1;
+                        B[K + 1] = Z2 + 1;
+                    }
+
+                    field[row, col] = 9 - 2 * shipType - shipNum;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        field[A[K + 1], B[K + 1]] = field[row, col];
+                    }
+                    break;
+
+                case 3:
+                    A[1] = row;
+                    A[2] = 7;
+                    A[3] = 7;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        if (!(M > 1 || A[K] == 6
+                            || field[A[K] + 1, col] > 0))
+                        {
+                            A[K + 1] = A[K] + 1;
+                            continue;
+                        }
+
+                        M = 2;
+                        var Z = 1;
+
+                        if (A[1] < A[2] && A[1] < A[3]) Z = A[1];
+                        if (A[2] < A[1] && A[2] < A[3]) Z = A[2];
+                        if (A[3] < A[1] && A[3] < A[2]) Z = A[3];
+
+                        if (Z == 1 || field[Z - 1, col] > 0) return false;
+
+                        A[K + 1] = Z - 1;
+                    }
+
+                    field[row, col] = 9 - 2 * shipType - shipNum;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        field[A[K + 1], col] = field[row, col];
+                    }
+                    break;
+
+                case 4:
+                default:
+                    A[1] = row;
+                    B[1] = col;
+                    A[2] = 7;
+                    A[3] = 7;
+                    B[2] = 0;
+                    B[3] = 0;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        if (!(M > 1 || A[K] == 6 || B[K] == 1
+                            || field[A[K] + 1, B[K] - 1] > 0
+                            || (field[A[K] + 1, B[K]] > 0 && field[A[K] + 1, B[K]] == field[A[K], B[K] - 1])))
+                        {
+                            A[K + 1] = A[K] + 1;
+                            B[K + 1] = B[K] - 1;
+                            continue;
+                        }
+
+                        M = 2;
+                        var Z1 = 1;
+                        var Z2 = 1;
+
+                        if (A[1] < A[2] && A[1] < A[3]) Z1 = A[1];
+                        if (A[2] < A[1] && A[2] < A[3]) Z1 = A[2];
+                        if (A[3] < A[1] && A[3] < A[2]) Z1 = A[3];
+                        if (B[1] > B[2] && B[1] > B[3]) Z2 = B[1];
+                        if (B[2] > B[1] && B[2] > B[3]) Z2 = B[2];
+                        if (B[3] > B[1] && B[3] > B[2]) Z2 = B[3];
+
+                        if (Z1 == 1 || Z2 == 6
+                            || field[Z1 - 1, Z2 + 1] > 0
+                            || (field[Z1, Z2 + 1] > 0 && field[Z1, Z2 + 1] == field[Z1 - 1, Z2])) return false;
+
+                        A[K + 1] = Z1 - 1;
+                        B[K + 1] = Z2 + 1;
+                    }
+
+                    field[row, col] = 9 - 2 * shipType - shipNum;
+
+                    for (var K = 1; K <= shipSize; K++)
+                    {
+                        field[A[K + 1], B[K + 1]] = field[row, col];
+                    }
+
+                    break;
+            }
+
+            return true;
+        }
+
+        public void DisplayIntro()
+        {
+            Console.ForegroundColor = ConsoleColor.Green;
+            Print(Tab(33) + "BATTLE");
+            Print(Tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+            //-- BATTLE WRITTEN BY RAY WESTERGARD  10 / 70
+            // COPYRIGHT 1971 BY THE REGENTS OF THE UNIV.OF CALIF.
+            // PRODUCED AT THE LAWRENCE HALL OF SCIENCE, BERKELEY
+        }
+
+        public void UserInteraction()
+        {
+            Print();
+            Print("THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION");
+            Print("HAS BEEN CAPTURED BUT NOT DECODED:");
+            Print();
+
+            for (var row = 1; row <= 6; row++)
+            {
+                for (var col = 1; col <= 6; col++)
+                {
+                    Write(field[col, row].ToString());
+                }
+
+                Print();
+            }
+
+            Print();
+            Print("DE-CODE IT AND USE IT IF YOU CAN");
+            Print("BUT KEEP THE DE-CODING METHOD A SECRET.");
+            Print();
+
+            var hit = new int[7, 7];
+            var lost = new int[4];
+            var shipHits = new[] { 0, 2, 2, 1, 1, 0, 0 };
+            var splashes = 0;
+            var hits = 0;
+
+            Print("START GAME");
+
+            do
+            {
+                var input = Console.ReadLine().Split(',').Select(x => int.TryParse(x, out var num) ? num : 0).ToArray();
+
+                if (!IsValid(input))
+                {
+                    Print("INVALID INPUT.  TRY AGAIN.");
+                    continue;
+                }
+
+                var col = input[0];
+                var row = 7 - input[1];
+                var shipNum = field[row, col];
+
+                if (shipNum == 0)
+                {
+                    splashes = splashes + 1;
+                    Print("SPLASH!  TRY AGAIN.");
+                    continue;
+                }
+
+                if (shipHits[shipNum] > 3)
+                {
+                    Print("THERE USED TO BE A SHIP AT THAT POINT, BUT YOU SUNK IT.");
+                    Print("SPLASH!  TRY AGAIN.");
+                    splashes = splashes + 1;
+                    continue;
+                }
+
+                if (hit[row, col] > 0)
+                {
+                    Print($"YOU ALREADY PUT A HOLE IN SHIP NUMBER {shipNum} AT THAT POINT.");
+                    Print("SPLASH!  TRY AGAIN.");
+                    splashes = splashes + 1;
+                    continue;
+                }
+
+                hits = hits + 1;
+                hit[row, col] = shipNum;
+
+                Print($"A DIRECT HIT ON SHIP NUMBER {shipNum}");
+                shipHits[shipNum] = shipHits[shipNum] + 1;
+
+                if (shipHits[shipNum] < 4)
+                {
+                    Print("TRY AGAIN.");
+                    continue;
+                }
+
+                var shipType = (shipNum - 1) / 2 + 1;
+                lost[shipType] = lost[shipType] + 1;
+    
+                Print("AND YOU SUNK IT.  HURRAH FOR THE GOOD GUYS.");
+                Print("SO FAR, THE BAD GUYS HAVE LOST");
+                Write($"{lost[1]} DESTROYER(S), {lost[2]} CRUISER(S), AND ");
+                Print($"{lost[3]} AIRCRAFT CARRIER(S).");
+                Print($"YOUR CURRENT SPLASH/HIT RATIO IS {splashes / hits}");
+
+                if ((lost[1] + lost[2] + lost[3]) < 6) continue;
+
+                Print();
+                Print("YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET");
+                Print($"WITH A FINAL SPLASH/HIT RATIO OF {splashes / hits}");
+
+                if ((splashes / hits) == 0)
+                {
+                    Print("CONGRATULATIONS -- A DIRECT HIT EVERY TIME.");
+                }
+
+                Print();
+                Print("****************************");
+                Print();
+
+                return;
+
+            } while (true);
+        }
+
+        public bool IsValid(int[] input) => input.Length == 2 && input.All(Valid);
+
+        public bool Valid(int value) => value > 0 && value < 7;
+
+        public void Print(string str = "") => Console.WriteLine(str);
+
+        public void Write(string value) => Console.Write(value);
+
+        public string Tab(int pos) => new String(' ', pos);
+
+        public int Rnd(int seed) => random.Next(seed);
+    }
+}
diff --git a/09 Battle/csharp/Program.cs b/09 Battle/csharp/Program.cs
new file mode 100644
index 00000000..526287de
--- /dev/null
+++ b/09 Battle/csharp/Program.cs	
@@ -0,0 +1,12 @@
+using System;
+
+namespace Battle
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            new Game().Run();
+        }
+    }
+}

From 48b823f42a9c25faf09d1f4116f10020ce524ffa Mon Sep 17 00:00:00 2001
From: Oliver Hensman-Crook 
Date: Sun, 28 Feb 2021 23:03:30 +0000
Subject: [PATCH 103/749] Added java version of mathdice game

---
 61 Math Dice/java/Die.java      | 73 +++++++++++++++++++++++++++++++++
 61 Math Dice/java/MathDice.java | 53 ++++++++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 61 Math Dice/java/Die.java
 create mode 100644 61 Math Dice/java/MathDice.java

diff --git a/61 Math Dice/java/Die.java b/61 Math Dice/java/Die.java
new file mode 100644
index 00000000..1a616213
--- /dev/null
+++ b/61 Math Dice/java/Die.java	
@@ -0,0 +1,73 @@
+import java.util.Random;
+
+public class Die {
+    private static final int DEFAULT_SIDES = 6;
+    private int faceValue;
+    private int sides;
+    private Random generator = new Random();
+
+    /**
+     * Construct a new Die with default sides
+     */
+    public Die() {
+        this.sides = DEFAULT_SIDES;
+        this.faceValue = 1 + generator.nextInt(sides);
+    }
+
+    /**
+     * Generate a new random number between 1 and sides to be stored in faceValue
+     */
+    private void throwDie() {
+        this.faceValue = 1 + generator.nextInt(sides);
+    }
+
+    
+    /** 
+     * @return the faceValue
+     */
+    public int getFaceValue() {
+        return faceValue;
+    }
+
+    
+    public void printDie() {
+        throwDie();
+        int x = this.getFaceValue();
+
+        System.out.println(" ----- ");
+
+        if(x==4||x==5||x==6) {
+            printTwo();
+        } else if(x==2||x==3) {
+            System.out.println("| *   |");
+        } else {
+            printZero();
+        }
+
+        if(x==1||x==3||x==5) {
+            System.out.println("|  *  |");
+        } else if(x==2||x==4) {
+            printZero();
+        } else {
+            printTwo();
+        }
+
+        if(x==4||x==5||x==6) {
+            printTwo();
+        } else if(x==2||x==3) {
+            System.out.println("|   * |");
+        } else {
+            printZero();
+        }
+
+        System.out.println(" ----- ");
+    }
+
+    private void printZero() {
+        System.out.println("|     |");
+    }
+
+    private void printTwo() {
+        System.out.println("| * * |");
+    }
+}
\ No newline at end of file
diff --git a/61 Math Dice/java/MathDice.java b/61 Math Dice/java/MathDice.java
new file mode 100644
index 00000000..bd2ecd70
--- /dev/null
+++ b/61 Math Dice/java/MathDice.java	
@@ -0,0 +1,53 @@
+import java.util.Scanner;
+
+public class MathDice {
+
+    public static void main(String[] args) {
+        Scanner in = new Scanner(System.in);
+        Die dieOne = new Die();
+        Die dieTwo = new Die();
+        int guess = 1;
+        int answer;
+
+        System.out.println("Math Dice");
+        System.out.println("https://github.com/coding-horror/basic-computer-games");
+        System.out.println();
+        System.out.print("This program generates images of two dice.\n"
+                + "When two dice and an equals sign followed by a question\n"
+                + "mark have been printed, type your answer, and hit the ENTER\n" + "key.\n"
+                + "To conclude the program, type 0.\n");
+
+        while (true) {
+            dieOne.printDie();
+            System.out.println("   +");
+            dieTwo.printDie();
+            System.out.println("   =");
+            int tries = 0;
+            answer = dieOne.getFaceValue() + dieTwo.getFaceValue();
+
+            while (guess!=answer && tries < 2) {
+                if(tries == 1)
+                    System.out.println("No, count the spots and give another answer.");
+                try{
+                    guess = in.nextInt();
+                } catch(Exception e) {
+                    System.out.println("Thats not a number!");
+                    in.nextLine();
+                }
+
+                if(guess == 0) 
+                    System.exit(0);
+                
+                tries++;
+            }
+
+            if(guess != answer){
+                System.out.println("No, the answer is " + answer + "!");
+            } else {
+                System.out.println("Correct");
+            }
+            System.out.println("The dice roll again....");
+        }
+    }
+
+}
\ No newline at end of file

From 22c791d8d12aa4186744d1c0b334aa5f08ada70f Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sun, 28 Feb 2021 15:12:47 -0800
Subject: [PATCH 104/749] Port AWARI to Python

I attempted to do a faithful port of the logic for the most part. In particular, there's a clever base-6 encoding of move history that allows games to be stored as integers in a "losing book" array, which allows the AI to become stronger over time. I did not change this logic, as I felt that the cleverness of this solution is worth observing. I endeavored to make every variable clearer, and use functions to help make program flow easier to understand.

I did make one small change to the logic, which I also documented clearly, having to do with evaluating very large moves. The code, as originally published, looks like a typo to me, but with BASIC, it's hard to be certain.

Also, I'm bad at this game; the computer beats me almost always.
---
 04 Awari/python/awari.py | 401 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 401 insertions(+)
 create mode 100644 04 Awari/python/awari.py

diff --git a/04 Awari/python/awari.py b/04 Awari/python/awari.py
new file mode 100644
index 00000000..de97ee97
--- /dev/null
+++ b/04 Awari/python/awari.py	
@@ -0,0 +1,401 @@
+"""
+AWARI
+
+An ancient African game (see also Kalah, Mancala).
+
+Ported by Dave LeCompte
+"""
+
+"""
+
+PORTING NOTES
+
+This game started out as 70 lines of BASIC, and I have ported it
+before. I find it somewhat amazing how efficient (densely packed) the
+original code is. Of course, the original code has fairly cryptic
+variable names (as was forced by BASIC's limitation on long (2+
+character) variable names). I have done my best here to interpret what
+each variable is doing in context, and rename them appropriately.
+
+I have endeavored to leave the logic of the code in place, as it's
+interesting to see a 2-ply game tree evaluation written in BASIC,
+along with what a reader in 2021 would call "machine learning".
+
+As each game is played, the move history is stored as base-6
+digits stored losing_book[game_number]. If the human player wins or
+draws, the computer increments game_number, effectively "recording"
+that loss to be referred to later. As the computer evaluates moves, it
+checks the potential game state against these losing game records, and
+if the potential move matches with the losing game (up to the current
+number of moves), that move is evaluated at a two point penalty.  
+
+Compare this, for example with MENACE, a mechanical device for
+"learning" tic-tac-toe:
+https://en.wikipedia.org/wiki/Matchbox_Educable_Noughts_and_Crosses_Engine
+
+The base-6 representation allows game history to be VERY efficiently
+represented. I considered whether to rewrite this representation to be
+easier to read, but I elected to TRY to document it, instead.
+
+Another place where I have made a difficult decision between accuracy
+and correctness is inside the "wrapping" code where it considers
+"while human_move_end > 13". The original BASIC code reads:
+
+830 IF L>13 THEN L=L-14:R=1:GOTO 830
+
+I suspect that the intention is not to assign 1 to R, but to increment
+R. I discuss this more in a porting note comment next to the
+translated code. If you wish to play a more accurate version of the
+game as written in the book, you can convert the increment back to an
+assignment.
+
+
+I continue to be impressed with this jewel of a game; as soon as I had
+the AI playing against me, it was beating me. I've been able to score
+a few wins against the computer, but even at its 2-ply lookahead, it
+beats me nearly always. I would like to become better at this game to
+explore the effectiveness of the "losing book" machine learning.
+
+
+EXERCISES FOR THE READER
+One could go many directions with this game:
+
+- change the initial number of stones in each pit
+
+- change the number of pits
+
+- only allow capturing if you end on your side of the board
+
+- don't allow capturing at all
+
+- don't drop a stone into the enemy "home"
+
+- go clockwise, instead
+
+- allow the player to choose to go clockwise or counterclockwise
+
+- instead of a maximum of two moves, allow each move that ends on the
+  "home" to be followed by a free move.
+
+- increase the AI lookahead
+
+- make the scoring heuristic a little more nuanced
+
+- store history to a file on disk (or in the cloud!) to allow the AI
+  to learn over more than a single session
+
+"""
+
+
+game_number = 0
+move_count = 0
+losing_book = []
+
+MAX_HISTORY = 9
+LOSING_BOOK_SIZE = 50
+
+
+def print_with_tab(space_count, msg):
+    if space_count > 0:
+        spaces = " " * space_count
+    else:
+        spaces = ""
+    print(spaces + msg)
+
+
+def draw_pit(line, board, pit_index):
+    val = board[pit_index]
+    line = line + " "
+    if val < 10:
+        line = line + " "
+    line = line + str(val) + " "
+    return line
+
+
+def draw_board(board):
+    print()
+
+    # Draw the top (computer) pits
+    line = "   "
+    for i in range(12, 6, -1):
+        line = draw_pit(line, board, i)
+    print(line)
+
+    # Draw the side (home) pits
+    line = draw_pit("", board, 13)
+    line += " " * 24
+    line = draw_pit(line, board, 6)
+    print(line)
+
+    # Draw the bottom (player) pits
+    line = "   "
+    for i in range(0, 6):
+        line = draw_pit(line, board, i)
+    print(line)
+    print()
+    print()
+
+
+def play_game(board):
+    # Place the beginning stones
+    for i in range(0, 13):
+        board[i] = 3
+
+    # Empty the home pits
+    board[6] = 0
+    board[13] = 0
+
+    global move_count
+    move_count = 0
+
+    # clear the history record for this game
+    losing_book[game_number] = 0
+
+    while True:
+        draw_board(board)
+
+        print("YOUR MOVE")
+        landing_spot, is_still_going, home = player_move(board)
+        if not is_still_going:
+            break
+        if landing_spot == home:
+            landing_spot, is_still_going, home = player_move_again(board)
+        if not is_still_going:
+            break
+
+        print("MY MOVE")
+        landing_spot, is_still_going, home, msg = computer_move("", board)
+
+        if not is_still_going:
+            print(msg)
+            break
+        if landing_spot == home:
+            landing_spot, is_still_going, home, msg = computer_move(msg + " , ", board)
+        if not is_still_going:
+            print(msg)
+            break
+        print(msg)
+
+    game_over(board)
+
+
+def computer_move(msg, board):
+    # This function does a two-ply lookahead evaluation; one computer
+    # move plus one human move.
+    #
+    # To do this, it makes a copy (temp_board) of the board, plays
+    # each possible computer move and then uses math to work out what
+    # the scoring heuristic is for each possible human move.
+    #
+    # Additionally, if it detects that a potential move puts it on a
+    # series of moves that it has recorded in its "losing book", it
+    # penalizes that move by two stones.
+
+    best_quality = -99
+
+    # Make a copy of the board, so that we can experiment. We'll put
+    # everything back, later.
+    temp_board = board[:]
+
+    # For each legal computer move 7-12
+    for computer_move in range(7, 13):
+        if board[computer_move] == 0:
+            continue
+        do_move(computer_move, 13, board)  # try the move (1 move lookahead)
+
+        best_player_move_quality = 0
+        # for all legal human moves 0-5 (responses to computer move computer_move)
+        for human_move_start in range(0, 6):
+            if board[human_move_start] == 0:
+                continue
+
+            human_move_end = board[human_move_start] + human_move_start
+            this_player_move_quality = 0
+
+            # If this move goes around the board, wrap backwards.
+            #
+            # PORTING NOTE: The careful reader will note that I am
+            # incrementing this_player_move_quality for each wrap,
+            # while the original code only set it equal to 1.
+            #
+            # I expect this was a typo or oversight, but I also
+            # recognize that you'd have to go around the board more
+            # than once for this to be a difference, and even so, it
+            # would be a very small difference; there are only 36
+            # stones in the game, and going around the board twice
+            # requires 24 stones.
+
+            while human_move_end > 13:
+                human_move_end = human_move_end - 14
+                this_player_move_quality += 1
+
+            if (
+                (board[human_move_end] == 0)
+                and (human_move_end != 6)
+                and (human_move_end != 13)
+            ):
+                # score the capture
+                this_player_move_quality += board[12 - human_move_end]
+
+            if this_player_move_quality > best_player_move_quality:
+                best_player_move_quality = this_player_move_quality
+
+        # This is a zero sum game, so the better the human player's
+        # move is, the worse it is for the computer player.
+        computer_move_quality = board[13] - board[6] - best_player_move_quality
+
+        if move_count < MAX_HISTORY:
+            move_digit = computer_move
+            if move_digit > 6:
+                move_digit = move_digit - 7
+
+            # Calculate the base-6 history representation of the game
+            # with this move. If that history is in our "losing book",
+            # penalize that move.
+            for prev_game_number in range(game_number):
+                if losing_book[game_number] * 6 + move_digit == int(
+                    losing_book[prev_game_number] / 6 ^ (7 - move_count) + 0.1
+                ):
+                    computer_move_quality -= 2
+
+        # Copy back from temporary board
+        for i in range(14):
+            board[i] = temp_board[i]
+
+        if computer_move_quality >= best_quality:
+            best_move = computer_move
+            best_quality = computer_move_quality
+
+    selected_move = best_move
+
+    move_str = chr(42 + selected_move)
+    if msg:
+        msg += ", " + move_str
+    else:
+        msg = move_str
+
+    move_number, is_still_going, home = execute_move(selected_move, 13, board)
+
+    return move_number, is_still_going, home, msg
+
+
+def game_over(board):
+    print()
+    print("GAME OVER")
+
+    pit_difference = board[6] - board[13]
+    if pit_difference < 0:
+        print(f"I WIN BY {-pit_difference} POINTS")
+
+    else:
+        global n
+        n = n + 1
+
+        if pit_difference == 0:
+            print("DRAWN GAME")
+        else:
+            print(f"YOU WIN BY {pit_difference} POINTS")
+
+
+def do_capture(m, home, board):
+    board[home] += board[12 - m] + 1
+    board[m] = 0
+    board[12 - m] = 0
+
+
+def do_move(m, home, board):
+    move_stones = board[m]
+    board[m] = 0
+
+    for stones in range(move_stones, 0, -1):
+        m = m + 1
+        if m > 13:
+            m = m - 14
+        board[m] += 1
+    if board[m] == 1:
+        # capture
+        if (m != 6) and (m != 13) and (board[12 - m] != 0):
+            do_capture(m, home, board)
+    return m
+
+
+def player_has_stones(board):
+    for i in range(6):
+        if board[i] > 0:
+            return True
+    return False
+
+
+def computer_has_stones(board):
+    for i in range(7, 13):
+        if board[i] > 0:
+            return True
+    return False
+
+
+def execute_move(move, home, board):
+    move_digit = move
+    last_location = do_move(move, home, board)
+
+    if move_digit > 6:
+        move_digit = move_digit - 7
+
+    global move_count
+    move_count += 1
+    if move_count < MAX_HISTORY:
+        # The computer keeps a chain of moves in losing_book by
+        # storing a sequence of moves as digits in a base-6 number.
+        #
+        # game_number represents the current game,
+        # losing_book[game_number] records the history of the ongoing
+        # game.  When the computer evaluates moves, it tries to avoid
+        # moves that will lead it into paths that have led to previous
+        # losses.
+        losing_book[game_number] = losing_book[game_number] * 6 + move_digit
+
+    if player_has_stones(board) and computer_has_stones(board):
+        is_still_going = True
+    else:
+        is_still_going = False
+    return last_location, is_still_going, home
+
+
+def player_move_again(board):
+    print("AGAIN")
+    return player_move(board)
+
+
+def player_move(board):
+    while True:
+        print("SELECT MOVE 1-6")
+        m = int(input()) - 1
+
+        if m > 5 or m < 0 or board[m] == 0:
+            print("ILLEGAL MOVE")
+            continue
+
+        break
+
+    ending_spot, is_still_going, home = execute_move(m, 6, board)
+
+    draw_board(board)
+
+    return ending_spot, is_still_going, home
+
+
+def main():
+    print_with_tab(34, "AWARI")
+    print_with_tab(15, "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+
+    board = [0] * 14  # clear the board representation
+    global losing_book
+    losing_book = [0] * LOSING_BOOK_SIZE  # clear the "machine learning" state
+
+    while True:
+        play_game(board)
+
+
+if __name__ == "__main__":
+    main()

From 82cb0ffff77423b221fbc8dd9e1dbeeabc510423 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sun, 28 Feb 2021 15:36:30 -0800
Subject: [PATCH 105/749] Port CHEMIST to Python

Very straightforward port. I noticed a mis-scanned text error in chemist.bas, which I changed to comply both with the original book and correct English spelling. :)
---
 24 Chemist/chemist.bas       |  2 +-
 24 Chemist/python/chemist.py | 89 ++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 24 Chemist/python/chemist.py

diff --git a/24 Chemist/chemist.bas b/24 Chemist/chemist.bas
index cbd8f1ce..8b673c27 100644
--- a/24 Chemist/chemist.bas	
+++ b/24 Chemist/chemist.bas	
@@ -1,7 +1,7 @@
 3 PRINT TAB(33);"CHEMIST"
 6 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
 8 PRINT:PRINT:PRINT
-10 PRINT "THE FICTITIOUS CHECMICAL KRYPTOCYANIC ACID CAN ONLY BE"
+10 PRINT "THE FICTITIOUS CHEMICAL KRYPTOCYANIC ACID CAN ONLY BE"
 20 PRINT "DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID."
 30 PRINT "IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE"
 40 PRINT "AND SOON EXPLODES.  GIVEN THE AMOUNT OF ACID, YOU MUST"
diff --git a/24 Chemist/python/chemist.py b/24 Chemist/python/chemist.py
new file mode 100644
index 00000000..73dfdc4e
--- /dev/null
+++ b/24 Chemist/python/chemist.py	
@@ -0,0 +1,89 @@
+"""
+CHEMIST
+
+A math game posing as a chemistry word problem.
+
+Ported by Dave LeCompte
+"""
+
+import random
+
+MAX_LIVES = 9
+
+
+def print_with_tab(space_count, msg):
+    if space_count > 0:
+        spaces = " " * space_count
+    else:
+        spaces = ""
+
+    print(spaces + msg)
+
+
+def play_scenario():
+    acid_amount = random.randint(1, 50)
+
+    water_amount = 7 * acid_amount / 3
+
+    print(f"{acid_amount} LITERS OF KRYPTOCYANIC ACID.  HOW MUCH WATER?")
+
+    response = float(input())
+
+    difference = abs(water_amount - response)
+
+    acceptable_difference = water_amount / 20
+
+    if difference > acceptable_difference:
+        show_failure()
+
+        return False
+    else:
+        show_success()
+
+        return True
+
+
+def show_failure():
+    print(" SIZZLE!  YOU HAVE JUST BEEN DESALINATED INTO A BLOB")
+    print(" OF QUIVERING PROTOPLASM!")
+
+
+def show_success():
+    print(" GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!")
+    print()
+
+
+def show_ending():
+    print(f" YOUR {MAX_LIVES} LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR")
+    print(" YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.")
+
+
+def main():
+    print_with_tab(33, "CHEMIST")
+    print_with_tab(15, "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+    print("THE FICTITIOUS CHEMICAL KRYPTOCYANIC ACID CAN ONLY BE")
+    print("DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID.")
+    print("IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE")
+    print("AND SOON EXPLODES.  GIVEN THE AMOUNT OF ACID, YOU MUST")
+    print("DECIDE WHO MUCH WATER TO ADD FOR DILUTION.  IF YOU MISS")
+    print("YOU FACE THE CONSEQUENCES.")
+
+    lives_used = 0
+
+    while True:
+        success = play_scenario()
+
+        if not success:
+            lives_used += 1
+
+            if lives_used == MAX_LIVES:
+                show_ending()
+                return
+
+
+if __name__ == "__main__":
+    main()

From 5cefe561ddba356ba9e91b9b97497995c49c6382 Mon Sep 17 00:00:00 2001
From: Marc Heiligers 
Date: Sun, 28 Feb 2021 16:47:50 -0700
Subject: [PATCH 106/749] BasicArrayTwoD, top row drawn, and trying to logic my
 way through the next row

---
 02 Amazing/ruby/amazing.rb | 276 +++++++++++++++++++++++++++++++++++++
 1 file changed, 276 insertions(+)
 create mode 100644 02 Amazing/ruby/amazing.rb

diff --git a/02 Amazing/ruby/amazing.rb b/02 Amazing/ruby/amazing.rb
new file mode 100644
index 00000000..7e7db0ce
--- /dev/null
+++ b/02 Amazing/ruby/amazing.rb	
@@ -0,0 +1,276 @@
+# frozen_string_literal: true
+
+# BASIC arrays are 1-based, unlike Ruby 0-based arrays
+class BasicArrayTwoD
+  def initialize(width, height)
+    @val = Array.new(height) { Array.new(width, 0) }
+  end
+
+  def [](x, y)
+    @val[y - 1][x - 1]
+  end
+
+  def []=(x, y, n)
+    @val[y - 1][x - 1] = n
+  end
+
+  def to_s
+    @val.map { |r| r.join(' ') }.join("\n")
+  end
+end
+
+# 10 PRINT TAB(28);"AMAZING PROGRAM"
+# 20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
+# 30 PRINT:PRINT:PRINT:PRINT
+puts ' ' * 28 + 'AMAZING PROGRAM'
+puts ' ' * 15 + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY'
+puts "\n" * 4
+
+# 100 INPUT "WHAT ARE YOUR WIDTH AND LENGTH";H,V
+# 102 IF H<>1 AND V<>1 THEN 110
+# 104 PRINT "MEANINGLESS DIMENSIONS.  TRY AGAIN.":GOTO 100
+def ask_dimensions
+  print 'WHAT ARE YOUR WIDTH AND LENGTH? '
+  h = gets.to_i
+  print '?? '
+  v = gets.to_i
+  [h, v]
+end
+
+h, v = ask_dimensions
+while h < 1 || v < 1
+  puts "MEANINGLESS DIMENSIONS.  TRY AGAIN."
+  h, v = ask_dimensions
+end
+
+# 110 DIM W(H,V),V(H,V)
+# BASIC programs can have the same variable names for different types,
+#   so the v array is not the same as the v int. Here we're using suffixes.
+w_arr = BasicArrayTwoD.new(h, v)
+v_arr = BasicArrayTwoD.new(h, v)
+
+# 120 PRINT
+# 130 PRINT
+# 140 PRINT
+# 150 PRINT
+puts "\n" * 4
+
+# 160 Q=0:Z=0:X=INT(RND(1)*H+1)
+q = 0
+z = 0
+
+def draw_top(x, h)
+  # 165 FOR I=1 TO H
+  # 170 IF I=X THEN 173
+  # 171 PRINT ".--";:GOTO 180
+  # 173 PRINT ".  ";
+  # 180 NEXT I
+  (1..h).each do |i|
+    if i == x
+      print i == 1 ? '┏  ' : '┳  '
+    else
+      print i == 1 ? '┏━━' : '┳━━'
+    end
+  end
+
+  # 190 PRINT "."
+  puts '┓'
+
+  x # return this because we need it
+end
+
+# x represents the location of the opening
+x = (rand * h).round + 1
+draw_top(x, h)
+
+# 195 C=1:W(X,1)=C:C=C+1
+c = 1
+w_arr[x, 1] = c # This marks the opening in the first row
+c += 1
+
+puts w_arr
+
+# 200 R=X:S=1:GOTO 260
+r = x
+s = 1
+# 260 IF R-1=0 THEN 530
+if r - 1 == 0
+  # 530 IF S-1=0 THEN 670
+  if s - 1 == 0
+    # 670 IF R=H THEN 740
+    if r == h
+      # 740 IF S<>V THEN 760
+      if s != v
+        # 760 IF W(R,S+1)<>0 THEN 780
+        if w_arr[r, s + 1] != 0
+          # 780 GOTO 1000
+          # Well, we'll just go directly to 1000
+          # 1000 GOTO 210
+          # Well, now. I just got here, now back to 210
+          # 210 IF R<>H THEN 240
+          if r != h
+            # 240 R=R+1
+            r += 1
+            # 250 IF W(R,S)=0 THEN 210
+            if w_arr[r, s] == 0
+              # GOTO 210 -- this is a loop
+            end
+            # 260 IF R-1=0 THEN 530
+            if r - 1 == 0
+              # 530 IF S-1=0 THEN 670
+              # 540 IF W(R,S-1)<>0 THEN 670
+              if s - 1 == 0 || w_arr[r, s - 1] != 0
+                # 670 IF R=H THEN 740
+                # 680 IF W(R+1,S)<>0 THEN 740
+                # 685 IF S<>V THEN 700
+                # 690 IF Z=1 THEN 730
+                # 695 Q=1:GOTO 710
+              end
+              # 545 IF R=H THEN 610
+              # 547 IF W(R+1,S)<>0 THEN 610
+              if r == h || w_arr[r + 1, s] != 0
+                # 610 IF S<>V THEN 630
+                # 620 IF Z=1 THEN 660
+                # 625 Q=1:GOTO 640
+              end
+              # 550 IF S<>V THEN 560
+              if s != v
+                # 560 IF W(R,S+1)<>0 THEN 590
+                # 570 X=INT(RND(1)*3+1)
+                # 580 ON X GOTO 820,860,910
+              end
+              # 552 IF Z=1 THEN 590
+              if z == 1
+                # 590 X=INT(RND(1)*2+1)
+                # 600 ON X GOTO 820,860
+              end
+              # 554 Q=1:GOTO 570
+              q = 1
+              # 570 X=INT(RND(1)*3+1)
+              # 580 ON X GOTO 820,860,910
+            end
+          end
+        end
+      end
+    end
+  end
+end
+
+# 210 IF R<>H THEN 240
+# 215 IF S<>V THEN 230
+# 220 R=1:S=1:GOTO 250
+# 230 R=1:S=S+1:GOTO 250
+# 240 R=R+1
+# 250 IF W(R,S)=0 THEN 210
+# 260 IF R-1=0 THEN 530
+# 265 IF W(R-1,S)<>0 THEN 530
+# 270 IF S-1=0 THEN 390
+# 280 IF W(R,S-1)<>0 THEN 390
+# 290 IF R=H THEN 330
+# 300 IF W(R+1,S)<>0 THEN 330
+# 310 X=INT(RND(1)*3+1)
+# 320 ON X GOTO 790,820,860
+# 330 IF S<>V THEN 340
+# 334 IF Z=1 THEN 370
+# 338 Q=1:GOTO 350
+# 340 IF W(R,S+1)<>0 THEN 370
+# 350 X=INT(RND(1)*3+1)
+# 360 ON X GOTO 790,820,910
+# 370 X=INT(RND(1)*2+1)
+# 380 ON X GOTO 790,820
+# 390 IF R=H THEN 470
+# 400 IF W(R+1,S)<>0 THEN 470
+# 405 IF S<>V THEN 420
+# 410 IF Z=1 THEN 450
+# 415 Q=1:GOTO 430
+# 420 IF W(R,S+1)<>0 THEN 450
+# 430 X=INT(RND(1)*3+1)
+# 440 ON X GOTO 790,860,910
+# 450 X=INT(RND(1)*2+1)
+# 460 ON X GOTO 790,860
+# 470 IF S<>V THEN 490
+# 480 IF Z=1 THEN 520
+# 485 Q=1:GOTO 500
+# 490 IF W(R,S+1)<>0 THEN 520
+# 500 X=INT(RND(1)*2+1)
+# 510 ON X GOTO 790,910
+# 520 GOTO 790
+# 530 IF S-1=0 THEN 670
+# 540 IF W(R,S-1)<>0 THEN 670
+# 545 IF R=H THEN 610
+# 547 IF W(R+1,S)<>0 THEN 610
+# 550 IF S<>V THEN 560
+# 552 IF Z=1 THEN 590
+# 554 Q=1:GOTO 570
+# 560 IF W(R,S+1)<>0 THEN 590
+# 570 X=INT(RND(1)*3+1)
+# 580 ON X GOTO 820,860,910
+# 590 X=INT(RND(1)*2+1)
+# 600 ON X GOTO 820,860
+# 610 IF S<>V THEN 630
+# 620 IF Z=1 THEN 660
+# 625 Q=1:GOTO 640
+# 630 IF W(R,S+1)<>0 THEN 660
+# 640 X=INT(RND(1)*2+1)
+# 650 ON X GOTO 820,910
+# 660 GOTO 820
+# 670 IF R=H THEN 740
+# 680 IF W(R+1,S)<>0 THEN 740
+# 685 IF S<>V THEN 700
+# 690 IF Z=1 THEN 730
+# 695 Q=1:GOTO 710
+# 700 IF W(R,S+1)<>0 THEN 730
+# 710 X=INT(RND(1)*2+1)
+# 720 ON X GOTO 860,910
+# 730 GOTO 860
+# 740 IF S<>V THEN 760
+# 750 IF Z=1 THEN 780
+# 755 Q=1:GOTO 770
+# 760 IF W(R,S+1)<>0 THEN 780
+# 770 GOTO 910
+# 780 GOTO 1000
+# 790 W(R-1,S)=C
+# 800 C=C+1:V(R-1,S)=2:R=R-1
+# 810 IF C=H*V+1 THEN 1010
+# 815 Q=0:GOTO 260
+# 820 W(R,S-1)=C
+# 830 C=C+1
+# 840 V(R,S-1)=1:S=S-1:IF C=H*V+1 THEN 1010
+# 850 Q=0:GOTO 260
+# 860 W(R+1,S)=C
+# 870 C=C+1:IF V(R,S)=0 THEN 880
+# 875 V(R,S)=3:GOTO 890
+# 880 V(R,S)=2
+# 890 R=R+1
+# 900 IF C=H*V+1 THEN 1010
+# 905 GOTO 530
+# 910 IF Q=1 THEN 960
+# 920 W(R,S+1)=C:C=C+1:IF V(R,S)=0 THEN 940
+# 930 V(R,S)=3:GOTO 950
+# 940 V(R,S)=1
+# 950 S=S+1:IF C=H*V+1 THEN 1010
+# 955 GOTO 260
+# 960 Z=1
+# 970 IF V(R,S)=0 THEN 980
+# 975 V(R,S)=3:Q=0:GOTO 1000
+# 980 V(R,S)=1:Q=0:R=1:S=1:GOTO 250
+# 1000 GOTO 210
+# 1010 FOR J=1 TO V
+# 1011 PRINT "I";
+# 1012 FOR I=1 TO H
+# 1013 IF V(I,J)<2 THEN 1030
+# 1020 PRINT "   ";
+# 1021 GOTO 1040
+# 1030 PRINT "  I";
+# 1040 NEXT I
+# 1041 PRINT
+# 1043 FOR I=1 TO H
+# 1045 IF V(I,J)=0 THEN 1060
+# 1050 IF V(I,J)=2 THEN 1060
+# 1051 PRINT ":  ";
+# 1052 GOTO 1070
+# 1060 PRINT ":--";
+# 1070 NEXT I
+# 1071 PRINT "."
+# 1072 NEXT J
+# 1073 END

From 3c43eb01aca8c4dd39cd1353fccf9d755140cd8e Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sun, 28 Feb 2021 15:55:01 -0800
Subject: [PATCH 107/749] Port NUMBER to Python

Simple port, changed some variable names.
---
 66 Number/python/number.py | 82 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 66 Number/python/number.py

diff --git a/66 Number/python/number.py b/66 Number/python/number.py
new file mode 100644
index 00000000..7746ff6a
--- /dev/null
+++ b/66 Number/python/number.py	
@@ -0,0 +1,82 @@
+"""
+NUMBER
+
+A number guessing (gambling) game.
+
+Ported by Dave LeCompte
+"""
+
+import random
+
+
+def print_with_tab(num_spaces, msg):
+    if num_spaces > 0:
+        spaces = " " * num_spaces
+    else:
+        spaces = ""
+
+    print(spaces + msg)
+
+
+def print_instructions():
+    print("YOU HAVE 100 POINTS.  BY GUESSING NUMBERS FROM 1 TO 5, YOU")
+    print("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO")
+    print("A RANDOM NUMBER SELECTED BY THE COMPUTER.")
+    print()
+    print("YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)")
+    print("YOUR POINT COUNT.  YOU WIN WHEN YOU GET 500 POINTS.")
+    print()
+
+
+def fnr():
+    return random.randint(1, 5)
+
+
+def main():
+    print_with_tab(33, "NUMBER")
+    print_with_tab(15, "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+    print_instructions()
+
+    points = 100
+
+    while points <= 500:
+        print("GUESS A NUMBER FROM 1 TO 5")
+        guess = int(input())
+
+        if (guess < 1) or (guess > 5):
+            continue
+
+        r = fnr()
+        s = fnr()
+        t = fnr()
+        u = fnr()
+        v = fnr()
+
+        if guess == r:
+            # lose 5
+            points -= 5
+        elif guess == s:
+            # gain 5
+            points += 5
+        elif guess == t:
+            # double!
+            points += points
+            print("YOU HIT THE JACKPOT!!!")
+        elif guess == u:
+            # gain 1
+            points += 1
+        elif guess == v:
+            # lose half
+            points = points - (points * 0.5)
+
+        print(f"YOU HAVE {points} POINTS.")
+        print()
+    print(f"!!!!YOU WIN!!!! WITH {points} POINTS.")
+
+
+if __name__ == "__main__":
+    main()

From 7841caa577232da7493944444d8e3192e3d16595 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sun, 28 Feb 2021 16:44:54 -0800
Subject: [PATCH 108/749] Port NICOMACHUS to Python

Straightforward port. Uses a modulo operator instead of repeated subtraction, because what am I, a farmer?
---
 64 Nicomachus/python/nicomachus.py | 78 ++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 64 Nicomachus/python/nicomachus.py

diff --git a/64 Nicomachus/python/nicomachus.py b/64 Nicomachus/python/nicomachus.py
new file mode 100644
index 00000000..33c5ab58
--- /dev/null
+++ b/64 Nicomachus/python/nicomachus.py	
@@ -0,0 +1,78 @@
+"""
+NICOMACHUS
+
+Math exercise/demonstration
+
+Ported by Dave LeCompte
+"""
+
+"""
+PORTING NOTE
+
+The title, as printed ingame, is "NICOMA", hinting at a time when
+filesystems weren't even 8.3, but could only support 6 character
+filenames.
+"""
+
+import time
+
+def print_with_tab(spaces_count, msg):
+    if spaces_count > 0:
+        spaces = " " * spaces_count
+    else:
+        spaces = ""
+    print(spaces + msg)
+
+def get_yes_or_no():
+    while True:
+        response = input().upper()
+        if response == "YES":
+            return True
+        elif response == "NO":
+            return False
+        print(f"EH?  I DON'T UNDERSTAND '{response}'  TRY 'YES' OR 'NO'.")
+
+
+def play_game():
+    print("PLEASE THINK OF A NUMBER BETWEEN 1 AND 100.")
+    print("YOUR NUMBER DIVIDED BY 3 HAS A REMAINDER OF")
+    a = int(input())
+    print("YOUR NUMBER DIVIDED BY 5 HAS A REMAINDER OF")
+    b = int(input())
+    print("YOUR NUMBER DIVIDED BY 7 HAS A REMAINDER OF")
+    c = int(input())
+    print()
+    print("LET ME THINK A MOMENT...")
+    print()
+
+    time.sleep(2.5)
+
+    d = (70 * a + 21 * b + 15 * c) % 105
+
+    print(f"YOUR NUMBER WAS {d}, RIGHT?")
+
+    response = get_yes_or_no()
+
+    if response:
+        print("HOW ABOUT THAT!!")
+    else:
+        print("I FEEL YOUR ARITHMETIC IS IN ERROR.")
+    print()
+    print("LET'S TRY ANOTHER")
+    
+
+def main():
+    print_with_tab(33, "NICOMA")
+    print_with_tab(15, "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+    
+    print("BOOMERANG PUZZLE FROM ARITHMETICA OF NICOMACHUS -- A.D. 90!")
+    print()
+    while True:
+        play_game()
+        
+
+if __name__ == "__main__":
+    main()

From 7c02b6647a8fdefc78a4804bf43f73c559595960 Mon Sep 17 00:00:00 2001
From: Anson VanDoren 
Date: Sun, 28 Feb 2021 17:41:47 -0800
Subject: [PATCH 109/749] adds Python implementation of 31 - Depth Charge

---
 31 Depth Charge/python/depth_charge.py | 120 +++++++++++++++++++++++++
 1 file changed, 120 insertions(+)
 create mode 100644 31 Depth Charge/python/depth_charge.py

diff --git a/31 Depth Charge/python/depth_charge.py b/31 Depth Charge/python/depth_charge.py
new file mode 100644
index 00000000..f367962e
--- /dev/null
+++ b/31 Depth Charge/python/depth_charge.py	
@@ -0,0 +1,120 @@
+# Original BASIC version as published in Basic Computer Games (1978)
+# https://www.atariarchives.org/basicgames/showpage.php?page=55
+#
+# Converted to Python by Anson VanDoren in 2021
+
+import math
+import random
+
+
+def show_welcome():
+    # Clear screen. chr(27) is `Esc`, and the control sequence is
+    # initiated by Ctrl+[
+    # `J` is "Erase in Display" and `2J` means clear the entire screen
+    print(chr(27) + "[2J")
+
+    # Show the intro text, centered
+    print("DEPTH CHARGE".center(45))
+    print("Creative Computing  Morristown, New Jersey\n\n".center(45))
+
+
+def get_num_charges():
+    print("Depth Charge game\n")
+    while True:
+        search_area = input("Dimensions of search area? ")
+
+        # Make sure the input is an integer
+        try:
+            search_area = int(search_area)
+            break
+        except ValueError:
+            print("Must enter an integer number. Please try again...")
+
+    num_charges = int(math.log2(search_area)) + 1
+    return search_area, num_charges
+
+
+def ask_for_new_game():
+    answer = input("Another game (Y or N): ")
+    if answer.lower().strip()[0] == 'y':
+        start_new_game()
+    else:
+        print("OK. Hope you enjoyed yourself")
+        exit()
+
+
+def show_shot_result(shot, location):
+    result = "Sonar reports shot was "
+    if shot[1] > location[1]:  # y-direction
+        result += "north"
+    elif shot[1] < location[1]:  # y-direction
+        result += "south"
+    if shot[0] > location[0]:  # x-direction
+        result += "east"
+    elif shot[0] < location[0]:  # x-direction
+        result += "west"
+    if shot[1] != location[1] or shot[0] != location[0]:
+        result += " and "
+
+    if shot[2] > location[2]:
+        result += "too low."
+    elif shot[2] < location [2]:
+        result += "too high."
+    else:
+        result += "depth OK."
+    print(result)
+    return
+
+
+def get_shot_input():
+    while True:
+        raw_guess = input("Enter coordinates: ")
+        try:
+            x, y, z = raw_guess.split()
+        except ValueError:
+            print("Please enter coordinates separated by spaces")
+            print(f"Example: 3 2 1")
+            continue
+        try:
+            x, y, z = [int(num) for num in [x, y, z]]
+            return x, y, z
+        except ValueError:
+            print("Please enter whole numbers only")
+
+
+def play_game(search_area, num_charges):
+    print("\nYou are the captain of the destroyer USS Computer.")
+    print("An enemy sub has been causing you trouble. Your")
+    print(f"mission is to destroy it. You have {num_charges} shots.")
+    print("Specify depth charge explosion point with a")
+    print("trio of numbers -- the first two are the")
+    print("surface coordinates; the third is the depth.")
+    print("\nGood luck!\n")
+
+    # Generate position for submarine
+    a, b, c = [random.randint(0, search_area) for _ in range(3)]
+
+    # Get inputs until win or lose
+    for i in range(num_charges):
+        print(f"\nTrial #{i+1}")
+        x, y, z = get_shot_input()
+
+        if (x, y, z) == (a, b, c):
+            print(f"\nB O O M ! ! You found it in {i+1} tries!\n")
+            ask_for_new_game()
+        else:
+            show_shot_result((x, y, z), (a, b, c))
+
+    # out of shots
+    print("\nYou have been torpedoed! Abandon ship!")
+    print(f"The submarine was at {a} {b} {c}")
+    ask_for_new_game()
+
+
+def start_new_game():
+    search_area, num_charges = get_num_charges()
+    play_game(search_area, num_charges)
+
+
+if __name__ == '__main__':
+    start_new_game()

From d902b3ba29963c99bed98a1cc710c5f80bd610be Mon Sep 17 00:00:00 2001
From: Jeff Lewis 
Date: Sun, 28 Feb 2021 19:00:55 -0700
Subject: [PATCH 110/749] Port Amazing to C# from Java version

---
 02 Amazing/csharp/Amazing.cs | 320 +++++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)
 create mode 100644 02 Amazing/csharp/Amazing.cs

diff --git a/02 Amazing/csharp/Amazing.cs b/02 Amazing/csharp/Amazing.cs
new file mode 100644
index 00000000..f62549d4
--- /dev/null
+++ b/02 Amazing/csharp/Amazing.cs	
@@ -0,0 +1,320 @@
+using System;
+using System.Collections.Generic;
+
+namespace Amazing
+{
+    class AmazingGame
+    {
+        private const int FIRST_COL = 0;
+        private const int FIRST_ROW = 0;
+        private const int EXIT_UNSET = 0;
+        private const int EXIT_DOWN = 1;
+        private const int EXIT_RIGHT = 2;
+
+        private static int GetDelimitedValue(String text, int pos)
+        {
+            String[] tokens = text.Split(",");
+
+            int val;
+            if (Int32.TryParse(tokens[pos], out val))
+            {
+                return val;
+            }
+            return 0;
+        }
+
+        private static String Tab(int spaces)
+        {
+            return new String(' ', spaces);
+        }
+
+        public static int Random(int min, int max)
+        {
+            Random random = new Random();
+            return random.Next(max - min) + min;
+        }
+
+        public void Play()
+        {
+            Console.WriteLine(Tab(28) + "AMAZING PROGRAM");
+            Console.WriteLine(Tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+            Console.WriteLine();
+
+            int width = 0;
+            int length = 0;
+
+            do
+            {
+                String range = DisplayTextAndGetInput("WHAT ARE YOUR WIDTH AND LENGTH");
+                if (range.IndexOf(",") > 0)
+                {
+                    width = GetDelimitedValue(range, 0);
+                    length = GetDelimitedValue(range, 1);
+                }
+            }
+            while (width < 1 || length < 1);
+
+            Grid grid = new Grid(length, width);
+            int enterCol = grid.SetupEntrance();
+
+            int totalWalls = width * length + 1;
+            int count = 2;
+            Cell cell = grid.StartingCell();
+
+            while (count != totalWalls)
+            {
+                List possibleDirs = GetPossibleDirs(grid, cell);
+
+                if (possibleDirs.Count != 0)
+                {
+                    cell = SetCellExit(grid, cell, possibleDirs);
+                    cell.Count = count++;
+                }
+                else
+                {
+                    cell = grid.GetFirstUnset(cell);
+                }
+            }
+            grid.SetupExit();
+
+            WriteMaze(width, grid, enterCol);
+        }
+
+        private Cell SetCellExit(Grid grid, Cell cell, List possibleDirs)
+        {
+            Direction direction = possibleDirs[Random(0, possibleDirs.Count)];
+            if (direction == Direction.GO_LEFT)
+            {
+                cell = grid.GetPrevCol(cell);
+                cell.ExitType = EXIT_RIGHT;
+            }
+            else if (direction == Direction.GO_UP)
+            {
+                cell = grid.GetPrevRow(cell);
+                cell.ExitType = EXIT_DOWN;
+            }
+            else if (direction == Direction.GO_RIGHT)
+            {
+                cell.ExitType = cell.ExitType + EXIT_RIGHT;
+                cell = grid.GetNextCol(cell);
+            }
+            else if (direction == Direction.GO_DOWN)
+            {
+                cell.ExitType = cell.ExitType + EXIT_DOWN;
+                cell = grid.GetNextRow(cell);
+            }
+            return cell;
+        }
+
+        private void WriteMaze(int width, Grid grid, int enterCol)
+        {
+            // top line
+            for (int i = 0; i < width; i++)
+            {
+                if (i == enterCol) Console.Write(".  ");
+                else Console.Write(".--");
+            }
+            Console.WriteLine(".");
+
+            for (int i = 0; i < grid.Length; i++)
+            {
+                Console.Write("I");
+                for (int j = 0; j < grid.Width; j++)
+                {
+                    if (grid.Cells[i,j].ExitType == EXIT_UNSET || grid.Cells[i, j].ExitType == EXIT_DOWN)
+                        Console.Write("  I");
+                    else Console.Write("   ");
+                }
+                Console.WriteLine();
+                for (int j = 0; j < grid.Width; j++)
+                {
+                    if (grid.Cells[i,j].ExitType == EXIT_UNSET || grid.Cells[i, j].ExitType == EXIT_RIGHT)
+                        Console.Write(":--");
+                    else Console.Write(":  ");
+                }
+                Console.WriteLine(".");
+            }
+        }
+
+        private List GetPossibleDirs(Grid grid, Cell cell)
+        {
+            var possibleDirs = new List();
+            foreach (var val in Enum.GetValues(typeof(Direction)))
+            {
+                possibleDirs.Add((Direction)val);
+            }
+
+            if (cell.Col == FIRST_COL || grid.IsPrevColSet(cell))
+            {
+                possibleDirs.Remove(Direction.GO_LEFT);
+            }
+            if (cell.Row == FIRST_ROW || grid.IsPrevRowSet(cell))
+            {
+                possibleDirs.Remove(Direction.GO_UP);
+            }
+            if (cell.Col == grid.LastCol || grid.IsNextColSet(cell))
+            {
+                possibleDirs.Remove(Direction.GO_RIGHT);
+            }
+            if (cell.Row == grid.LastRow || grid.IsNextRowSet(cell))
+            {
+                possibleDirs.Remove(Direction.GO_DOWN);
+            }
+            return possibleDirs;
+        }
+
+        private String DisplayTextAndGetInput(String text)
+        {
+            Console.Write(text);
+            return Console.ReadLine();
+        }
+
+
+        private enum Direction
+        {
+            GO_LEFT,
+            GO_UP,
+            GO_RIGHT,
+            GO_DOWN,
+        }
+
+        public class Cell
+        {
+            public int ExitType { get; set; }
+            public int Count { get; set; }
+
+            public int Col { get; set; }
+            public int Row { get; set; }
+
+            public Cell(int row, int col)
+            {
+                ExitType = EXIT_UNSET;
+                Row = row;
+                Col = col;
+            }
+        }
+
+
+        public class Grid
+        {
+            public Cell[,] Cells { get; private set; }
+
+            public int LastCol { get; set; }
+            public int LastRow { get; set; }
+
+            public int Width { get; private set; }
+            public int Length { get; private set; }
+
+            private int enterCol;
+
+            public Grid(int length, int width)
+            {
+                LastCol = width - 1;
+                LastRow = length - 1;
+                Width = width;
+                Length = length;
+
+                Cells = new Cell[length,width];
+                for (int i = 0; i < length; i++)
+                {
+                    for (int j = 0; j < width; j++)
+                    {
+                        this.Cells[i,j] = new Cell(i, j);
+                    }
+                }
+            }
+
+            public int SetupEntrance()
+            {
+                this.enterCol = Random(0, Width);
+                Cells[0, enterCol].Count = 1;
+                return this.enterCol;
+            }
+
+            public void SetupExit()
+            {
+                int exit = Random(0, Width - 1);
+                Cells[LastRow, exit].ExitType += 1;
+            }
+
+            public Cell StartingCell()
+            {
+                return Cells[0, enterCol];
+            }
+
+            public bool IsPrevColSet(Cell cell)
+            {
+                return 0 != Cells[cell.Row, cell.Col - 1].Count;
+            }
+
+            public bool IsPrevRowSet(Cell cell)
+            {
+                return 0 != Cells[cell.Row - 1, cell.Col].Count;
+            }
+
+            public bool IsNextColSet(Cell cell)
+            {
+                return 0 != Cells[cell.Row, cell.Col + 1].Count;
+            }
+
+            public bool IsNextRowSet(Cell cell)
+            {
+                return 0 != Cells[cell.Row + 1, cell.Col].Count;
+            }
+
+            public Cell GetPrevCol(Cell cell)
+            {
+                return Cells[cell.Row, cell.Col - 1];
+            }
+
+            public Cell GetPrevRow(Cell cell)
+            {
+                return Cells[cell.Row - 1, cell.Col];
+            }
+
+            public Cell GetNextCol(Cell cell)
+            {
+                return Cells[cell.Row, cell.Col + 1];
+            }
+
+            public Cell GetNextRow(Cell cell)
+            {
+                return Cells[cell.Row + 1, cell.Col];
+            }
+
+            public Cell GetFirstUnset(Cell cell)
+            {
+                int col = cell.Col;
+                int row = cell.Row;
+                Cell newCell;
+                do
+                {
+                    if (col != this.LastCol)
+                    {
+                        col++;
+                    }
+                    else if (row != this.LastRow)
+                    {
+                        row++;
+                        col = 0;
+                    }
+                    else
+                    {
+                        row = 0;
+                        col = 0;
+                    }
+                }
+                while ((newCell = Cells[row, col]).Count == 0);
+                return newCell;
+            }
+        }
+    }
+
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            new AmazingGame().Play();
+        }
+    }
+}

From de5b6a68d43a649904f2a90588845df608726c27 Mon Sep 17 00:00:00 2001
From: Jack Boyce 
Date: Sun, 28 Feb 2021 18:22:23 -0800
Subject: [PATCH 111/749] first pass--feature complete, needs testing and
 cleanup

---
 84 Super Star Trek/python/superstartrek.py | 913 +++++++++++++++++++++
 1 file changed, 913 insertions(+)
 create mode 100644 84 Super Star Trek/python/superstartrek.py

diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py
new file mode 100644
index 00000000..9e254519
--- /dev/null
+++ b/84 Super Star Trek/python/superstartrek.py	
@@ -0,0 +1,913 @@
+
+# ****        **** STAR TREK ****        ****
+# **** SIMULATION OF A MISSION OF THE STARSHIP ENTERPRISE,
+# **** AS SEEN ON THE STAR TREK TV SHOW.
+# **** ORIGIONAL PROGRAM BY MIKE MAYFIELD, MODIFIED VERSION
+# **** PUBLISHED IN DEC'S "101 BASIC GAMES", BY DAVE AHL.
+# **** MODIFICATIONS TO THE LATTER (PLUS DEBUGGING) BY BOB
+# **** LEEDOM - APRIL & DECEMBER 1974,
+# **** WITH A LITTLE HELP FROM HIS FRIENDS . . .
+#
+# Python translation by Jack Boyce - 2/2021
+# Output is identical to BASIC version except for minor cleanup
+
+
+import random
+from math import sqrt
+
+
+# -------------------------------------------------------------------------
+#  Utility functions
+# -------------------------------------------------------------------------
+
+
+def fnd(i):
+    return sqrt((k[i][0] - s1)**2 + (k[i][1] - s2)**2)
+
+
+def fnr():
+    return int(random.random() * 7.98 + 0.01)
+
+
+def quadrant_name(row, col, region_only=False):
+    region1 = ['ANTARES', 'RIGEL', 'PROCYON', 'VEGA', 'CANOPUS', 'ALTAIR',
+               'SAGITTARIUS', 'POLLUX']
+    region2 = ['SIRIUS', 'DENEB', 'CAPELLA', 'BETELGEUSE', 'ALDEBARAN',
+               'REGULUS', 'ARCTURUS', 'SPICA']
+    modifier = ['I', 'II', 'III', 'IV']
+
+    quadrant = region1[row] if col < 4 else region2[row]
+
+    if not region_only:
+        quadrant += ' ' + modifier[col % 4]
+
+    return quadrant
+
+
+def insert_marker(row, col, marker):
+    global qs
+
+    if len(marker) != 3:
+        print('ERROR')
+        quit()
+
+    pos = round(col) * 3 + round(row) * 24
+    qs = qs[0:pos] + marker + qs[(pos + 3):192]
+
+
+def compare_marker(row, col, test_marker):
+    global qs
+
+    pos = round(col) * 3 + round(row) * 24
+    return qs[pos:(pos + 3)] == test_marker
+
+
+def find_empty_place():
+    while True:
+        row = fnr()
+        col = fnr()
+        if compare_marker(row, col, '   '):
+            return row, col
+
+
+# -------------------------------------------------------------------------
+#  Functions for individual player commands
+# -------------------------------------------------------------------------
+
+
+def navigation():
+    global d, s, e, k, s1, s2, qs, t8, t9, t, w1, c, q1, q2
+
+    c1 = float(input("COURSE (1-9) "))
+    if c1 == 9:
+        c1 = 1
+    if c1 < 1 or c1 >= 9:
+        print("   LT. SULU REPORTS, 'INCORRECT COURSE DATA, SIR!'")
+        return
+    xs = '0.2' if d[0] < 0 else '8'
+    w1 = float(input(f"WARP FACTOR (0-{xs}) "))
+    if d[0] < 0 and w1 > 0.2:
+        print("WARP ENGINES ARE DAMAGED. MAXIMUM SPEED = WARP 0.2")
+        return
+    if w1 == 0:
+        return
+    if w1 < 0 or w1 > 8:
+        print(f"   CHIEF ENGINEER SCOTT REPORTS 'THE ENGINES WON'T TAKE WARP {w1}!'")
+        return
+
+    n = int(w1 * 8 + 0.5)
+    if e < n:
+        print("ENGINEERING REPORTS   'INSUFFICIENT ENERGY AVAILABLE")
+        print(f"                       FOR MANEUVERING AT WARP {w1}!'")
+        if s >= n - e and d[6] >= 0:
+            print(f"DEFLECTOR CONTROL ROOM ACKNOWLEDGES {s} UNITS OF ENERGY")
+            print("                         PRESENTLY DEPLOYED TO SHIELDS.")
+        return
+
+    # klingons move and fire
+    for i in range(3):
+        if k[i][2] != 0:
+            insert_marker(k[i][0], k[i][1], '   ')
+            k[i][0], k[i][1] = find_empty_place()
+            insert_marker(k[i][0], k[i][1], '+K+')
+
+    klingons_fire()
+
+    # print damage control report
+    d1 = 0
+    line = ''
+    d6 = 1 if w1 >= 1 else w1
+    for i in range(8):
+        if d[i] < 0:
+            d[i] += d6
+            if d[i] > -0.1 and d[i] < 0:
+                d[i] = -0.1
+            elif d[i] >= 0:
+                if d1 != 1:
+                    d1 = 1
+                    line = "DAMAGE CONTROL REPORT:"
+                line += '   ' + devices[i] + ' REPAIR COMPLETED\n'
+    if len(line) > 0:
+        print(line)
+    if random.random() <= 0.2:
+        r1 = fnr()
+        if random.random() < 0.6:
+            d[r1] -= random.random() * 5 + 1
+            print(f'DAMAGE CONTROL REPORT:   {devices[r1]} DAMAGED\n')
+        else:
+            d[r1] += random.random() * 3 + 1
+            print(f'DAMAGE CONTROL REPORT:   {devices[r1]} STATE OF REPAIR IMPROVED\n')
+
+    # begin moving starship
+    insert_marker(int(s1), int(s2), '   ')
+    ic1 = int(c1)
+    x1 = c[ic1 - 1][0] + (c[ic1][0] - c[ic1 - 1][0]) * (c1 - ic1)
+    x, y = s1, s2
+    x2 = c[ic1 - 1][1] + (c[ic1][1] - c[ic1 - 1][1]) * (c1 - ic1)
+    q4, q5 = q1, q2
+    for i in range(1, n + 1):
+        s1 += x1
+        s2 += x2
+
+        if s1 < 0 or s1 > 7 or s2 < 0 or s2 > 7:
+            # exceeded quadrant limits
+            x += 8 * q1 + n * x1
+            y += 8 * q2 + n * x2
+            q1 = int(x / 8)
+            q2 = int(y / 8)
+            s1 = int(x - q1 * 8)
+            s2 = int(y - q2 * 8)
+            if s1 < 0:
+                q1 -= 1
+                s1 = 7
+            if s2 < 0:
+                q2 -= 1
+                s2 = 7
+            x5 = 0
+            if q1 < 0:
+                x5 = 1
+                q1 = s1 = 0
+            if q1 > 7:
+                x5 = 1
+                q1 = s1 = 7
+            if q2 < 0:
+                x5 = 1
+                q2 = s2 = 0
+            if q2 > 7:
+                x5 = 1
+                q2 = s2 = 7
+            if x5 == 1:
+                print("LT. UHURA REPORTS MESSAGE FROM STARFLEET COMMAND:")
+                print("  'PERMISSION TO ATTEMPT CROSSING OF GALACTIC PERIMETER")
+                print("  IS HEREBY *DENIED*. SHUT DOWN YOUR ENGINES.'")
+                print("CHIEF ENGINEER SCOTT REPORTS  'WARP ENGINES SHUT DOWN")
+                print(f"  AT SECTOR {s1 + 1},{s2 + 1} OF QUADRANT {q1 + 1},{q2 + 1}.'")
+                if t > t0 + t9:
+                    end_game()
+            if 8 * q1 + q2 == 8 * q4 + q5:
+                break
+            t += 1
+            maneuver_energy(n)
+            new_quadrant()
+            return
+        else:
+            s8 = int(s1) * 24 + int(s2) * 3
+            if qs[s8:(s8 + 2)] != '  ':
+                s1 = int(s1 - x1)
+                s2 = int(s2 - x2)
+                print(
+                    "WARP ENGINES SHUT DOWN AT SECTOR "
+                    f"{s1 + 1},{s2 + 1} DUE TO BAD NAVAGATION"
+                )
+                break
+    else:
+        s1, s2 = int(s1), int(s2)
+
+    insert_marker(int(s1), int(s2), '<*>')
+    maneuver_energy(n)
+
+    t8 = 1
+    if w1 < 1:
+        t8 = 0.1 * int(10 * w1)
+    t += t8
+    if t > t0 + t9:
+        end_game()
+
+    short_range_scan()
+
+
+def maneuver_energy(n):
+    global e, s
+
+    e -= n + 10
+    if e > 0:
+        return
+
+    print("SHIELD CONTROL SUPPLIES ENERGY TO COMPLETE THE MANEUVER.")
+    s += e
+    e = 0
+    if s <= 0:
+        s = 0
+
+
+def short_range_scan():
+    global d0, e, p, s
+
+    d0 = 0
+    for i in (s1 - 1, s1, s1 + 1):
+        for j in (s2 - 1, s2, s2 + 1):
+            if 0 <= i <= 7 and 0 <= j <= 7:
+                if compare_marker(i, j, '>!<'):
+                    d0 = 1
+                    cs = 'DOCKED'
+                    e = e0
+                    p = p0
+                    print('SHIELDS DROPPED FOR DOCKING PURPOSES')
+                    s = 0
+                    break
+        else:
+            continue
+        break
+    else:
+        if k3 > 0:
+            cs = '*RED*'
+        elif e < e0 * 0.1:
+            cs = 'YELLOW'
+        else:
+            cs = 'GREEN'
+
+    if d[1] < 0:
+        print('\n*** SHORT RANGE SENSORS ARE OUT ***\n')
+        return
+
+    sep = '---------------------------------'
+    print(sep)
+    for i in range(8):
+        line = ''
+        for j in range(8):
+            pos = i * 24 + j * 3
+            line = line + ' ' + qs[pos:(pos + 3)]
+
+        if i == 0:
+            line += f'        STARDATE           {int(t * 10) * 0.1}'
+        elif i == 1:
+            line += f'        CONDITION          {cs}'
+        elif i == 2:
+            line += f'        QUADRANT           {q1 + 1},{q2 + 1}'
+        elif i == 3:
+            line += f'        SECTOR             {s1 + 1},{s2 + 1}'
+        elif i == 4:
+            line += f'        PHOTON TORPEDOES   {int(p)}'
+        elif i == 5:
+            line += f'        TOTAL ENERGY       {int(e + s)}'
+        elif i == 6:
+            line += f'        SHIELDS            {int(s)}'
+        else:
+            line += f'        KLINGONS REMAINING {k9}'
+
+        print(line)
+    print(sep)
+
+
+def long_range_scan():
+    global n, z
+
+    if d[2] < 0:
+        print('LONG RANGE SENSORS ARE INOPERABLE')
+        return
+
+    print(f'LONG RANGE SCAN FOR QUADRANT {q1 + 1},{q2 + 1}')
+    o1s = '-------------------'
+    print(o1s)
+    for i in (q1 - 1, q1, q1 + 1):
+        n[0] = -1
+        n[1] = -2
+        n[2] = -3
+
+        for j in (q2 - 1, q2, q2 + 1):
+            if 0 <= i <= 7 and 0 <= j <= 7:
+                n[j - q2 + 1] = g[i][j]
+                z[i][j] = g[i][j]
+
+        line = ': '
+        for l in range(3):
+            if n[l] < 0:
+                line += '*** : '
+            else:
+                line += str(n[l] + 1000).rjust(4, ' ')[-3:] + ' : '
+        print(line)
+        print(o1s)
+
+
+def phaser_control():
+    global d, e, k, k3, k9, qs, g, z, q1, q2
+
+    if d[3] < 0:
+        print("PHASERS INOPERATIVE")
+        return
+
+    if k3 <= 0:
+        print("SCIENCE OFFICER SPOCK REPORTS  'SENSORS SHOW NO ENEMY SHIPS")
+        print("                                IN THIS QUADRANT'")
+        return
+
+    if d[7] < 0:
+        print("COMPUTER FAILURE HAMPERS ACCURACY")
+
+    print(f"PHASERS LOCKED ON TARGET; ENERGY AVAILABLE = {e} UNITS")
+    x = 0
+    while True:
+        x = int(input("NUMBER OF UNITS TO FIRE "))
+        if x <= 0:
+            return
+        if e - x >= 0:
+            break
+        print(f"ENERGY AVAILABLE = {e} UNITS")
+
+    e -= x
+    if d[7] < 0:  # typo in original, was d[6]
+        x *= random.random()
+
+    h1 = int(x / k3)
+    for i in range(3):
+        if k[i][2] <= 0:
+            continue
+
+        h = int((h1 / fnd(i)) * (random.random() + 2))
+        if h <= 0.15 * k[i][2]:
+            print(f"SENSORS SHOW NO DAMAGE TO ENEMY AT {k[i][0] + 1},{k[i][1] + 1}")
+        else:
+            k[i][2] -= h
+            print(f"UNIT HIT ON KLINGON AT SECTOR {k[i][0] + 1},{k[i][1] + 1}")
+            if k[i][2] <= 0:
+                print("*** KLINGON DESTROYED ***")
+                k3 -= 1
+                k9 -= 1
+                insert_marker(k[i][0], k[i][1], '   ')
+                k[i][2] = 0
+                g[q1][q2] -= 100
+                z[q1][q2] = g[q1][q2]
+                if k9 <= 0:
+                    end_game(won=True)
+            else:
+                print(f"   (SENSORS SHOW {k[i][2]} UNITS REMAINING)")
+
+    klingons_fire()
+
+
+def photon_torpedoes():
+    global p, d, c, e, s1, s2, k3, k9, b3, b9, t, t0, t9, d0, g, z
+
+    if p <= 0:
+        print("ALL PHOTON TORPEDOES EXPENDED")
+        return
+    if d[4] < 0:
+        print("PHOTON TUBES ARE NOT OPERATIONAL")
+        return
+
+    c1 = float(input("PHOTON TORPEDO COURSE (1-9) "))
+    if c1 == 9:
+        c1 = 1
+    if c1 < 1 or c1 >= 9:
+        print("ENSIGN CHEKOV REPORTS, 'INCORRECT COURSE DATA, SIR!'")
+        return
+
+    ic1 = int(c1)
+    x1 = c[ic1 - 1][0] + (c[ic1][0] - c[ic1 - 1][0]) * (c1 - ic1)
+    e -= 2
+    p -= 1
+    x2 = c[ic1 - 1][1] + (c[ic1][1] - c[ic1 - 1][1]) * (c1 - ic1)
+    x, y = s1, s2
+    x3, y3 = x, y
+    print("TORPEDO TRACK:")
+    while True:
+        x += x1
+        y += x2
+        x3 = round(x)
+        y3 = round(y)
+        if x3 < 0 or x3 > 7 or y3 < 0 or y3 > 7:
+            print("TORPEDO MISSED")
+            klingons_fire()
+            return
+        print(f"               {x3 + 1},{y3 + 1}")
+        if not compare_marker(x3, y3, '   '):
+            break
+
+    if compare_marker(x3, y3, '+K+'):
+        print("*** KLINGON DESTROYED ***")
+        k3 -= 1
+        k9 -= 1
+        if k9 <= 0:
+            end_game(won=True)
+        for i in range(3):
+            if x3 == k[i][0] and y3 == k[i][1]:
+                k[i][2] = 0
+    elif compare_marker(x3, y3, ' * '):
+        print(f"STAR AT {x3 + 1},{y3 + 1} ABSORBED TORPEDO ENERGY.")
+        klingons_fire()
+        return
+    elif compare_marker(x3, y3, '>!<'):
+        print("*** STARBASE DESTROYED ***")
+        b3 -= 1
+        b9 -= 1
+        if b9 == 0 and k9 <= t - t0 - t9:
+            print("THAT DOES IT, CAPTAIN!! YOU ARE HEREBY RELIEVED OF COMMAND")
+            print("AND SENTENCED TO 99 STARDATES AT HARD LABOR ON CYGNUS 12!!")
+            end_game(quit=True)
+        else:
+            print("STARFLEET COMMAND REVIEWING YOUR RECORD TO CONSIDER")
+            print("COURT MARTIAL!")
+            d0 = 0
+
+    insert_marker(x3, y3, '   ')
+    g[q1][q2] = k3 * 100 + b3 * 10 + s3
+    z[q1][q2] = g[q1][q2]
+    klingons_fire()
+
+
+def klingons_fire():
+    global k3, s, k, d0, d
+
+    if k3 <= 0:
+        return
+    if d0 != 0:
+        print("STARBASE SHIELDS PROTECT THE ENTERPRISE")
+        return
+
+    for i in range(3):
+        if k[i][2] <= 0:
+            continue
+
+        h = int((k[i][2] / fnd(i)) * (random.random() + 2))
+        s -= h
+        k[i][2] /= (random.random() + 3)
+        print(f"{h} UNIT HIT ON ENTERPRISE FROM SECTOR {k[i][0] + 1},{k[i][1] + 1}")
+        if s <= 0:
+            end_game(enterprise_killed=True)
+        print(f"      ")
+        if h >= 20 and random.random() < 0.60 and h / s > 0.02:
+            r1 = fnr()
+            d[r1] -= h / s + 0.5 * random.random()
+            print(f"DAMAGE CONTROL REPORTS {devices[r1]} DAMAGED BY THE HIT'")
+
+
+def shield_control():
+    global e, s, d
+
+    if d[6] < 0:
+        print('SHIELD CONTROL INOPERABLE')
+        return
+
+    x = input(f'ENERGY AVAILABLE = {e + s} NUMBER OF UNITS TO SHIELDS ')
+    x = int(x)
+
+    if x < 0 or s == x:
+        print('')
+        return
+
+    if x > e + s:
+        print(
+            "SHIELD CONTROL REPORTS  'THIS IS NOT THE FEDERATION TREASURY.'\n"
+            ""
+        )
+        return
+
+    e += s - x
+    s = x
+    print('DEFLECTOR CONTROL ROOM REPORT:')
+    print(f"  'SHIELDS NOW AT {s} UNITS PER YOUR COMMAND.'")
+
+
+def damage_control():
+    global d, d0, d4, t
+
+    if d[5] < 0:
+        print('DAMAGE CONTROL REPORT NOT AVAILABLE')
+    else:
+        print('\nDEVICE             STATE OF REPAIR')
+        for r1 in range(8):
+            print(f"{devices[r1].ljust(25, ' ')}{int(d[r1] * 100) * 0.01}")
+        print()
+
+    if d0 == 0:
+        return
+
+    d3 = sum(0.1 for i in range(8) if d[i] < 0)
+    if d3 == 0:
+        return
+
+    d3 += d4
+    if d3 >= 1:
+        d3 = 0.9
+    print("\nTECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;")
+    print(f"ESTIMATED TIME TO REPAIR: {0.01 * int(100 * d3)} STARDATES")
+    astr = input("WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N) ").upper()
+    if astr != 'Y':
+        return
+
+    for i in range(8):
+        if d[i] < 0:
+            d[i] = 0
+    t += d3 + 0.1
+
+
+def computer():
+    global d, g5, z, k9, t0, t9, t, b9, s1, s2, b4, b5
+
+    if d[7] < 0:
+        print("COMPUTER DISABLED")
+        return
+
+    while True:
+        coms = input("COMPUTER ACTIVE AND AWAITING COMMAND ")
+        if len(coms) == 0:
+            com = 6
+        else:
+            com = int(coms)
+        if com < 0:
+            return
+
+        print()
+        h8 = 1
+
+        if com == 0 or com == 5:
+            if com == 5:
+                h8 = 0
+                g5 = 1
+                print("                        THE GALAXY")
+            else:
+                # hardcopy disabled:
+                # 7540 REM INPUT"DO YOU WANT A HARDCOPY? IS THE TTY ON (Y/N)";A$
+                # 7542 REM IFA$="Y"THENPOKE1229,2:POKE1237,3:NULL1
+
+                print("\n        ");
+                print(f"COMPUTER RECORD OF GALAXY FOR QUADRANT {q1 + 1},{q2 + 1}")
+                print()
+
+            print("       1     2     3     4     5     6     7     8")
+            sep = "     ----- ----- ----- ----- ----- ----- ----- -----"
+            print(sep)
+
+            for i in range(8):
+                line = str(i + 1) + '  '
+
+                if h8 == 0:
+                    g2s = quadrant_name(i, 0, True)
+                    line += (' ' * int(14 - 0.5 * len(g2s))) + g2s
+                    g2s = quadrant_name(i, 4, True)
+                    line += (' ' * int(41 - 0.5 * len(g2s) - len(line))) + g2s
+                else:
+                    for j in range(8):
+                        line += '   '
+                        if z[i][j] == 0:
+                            line += '***'
+                        else:
+                            line += str(z[i][j] + 1000)[-3:]
+
+                print(line)
+                print(sep)
+
+            return
+        elif com == 1:
+            print("   STATUS REPORT:")
+            print(f"KLINGON{'S' if k9 > 1 else ''} LEFT: {k9}")
+            print(f"MISSION MUST BE COMPLETED IN {0.1 * int((t0+t9-t) * 10)} STARDATES")
+
+            if b9 == 0:
+                print("YOUR STUPIDITY HAS LEFT YOU ON YOUR ON IN")
+                print("  THE GALAXY -- YOU HAVE NO STARBASES LEFT!")
+            else:
+                print(f"THE FEDERATION IS MAINTAINING {b9} STARBASE{'S' if b9 > 1 else ''} IN THE GALAXY")
+
+            damage_control()
+            return
+        elif com == 2:
+            if k3 <= 0:
+                print("SCIENCE OFFICER SPOCK REPORTS  'SENSORS SHOW NO ENEMY SHIPS")
+                print("                                IN THIS QUADRANT'")
+                return
+
+            print(f"FROM ENTERPRISE TO KLINGON BATTLE CRUSER{'S' if k3 > 1 else ''}")
+            h8 = 0
+            for i in range(3):
+                if k[i][2] > 0:
+                    print_direction(s1, s2, k[i][0], k[i][1])
+            return
+        elif com == 3:
+            if b3 == 0:
+                print("MR. SPOCK REPORTS, 'SENSORS SHOW NO STARBASES IN THIS QUADRANT.'")
+                return
+
+            print("FROM ENTERPRISE TO STARBASE:")
+            print_direction(s1, s2, b4, b5)
+            return
+        elif com == 4:
+            print("DIRECTION/DISTANCE CALCULATOR:")
+            print(f"YOU ARE AT QUADRANT {q1},{q2} SECTOR {s1},{s2}")
+            print("PLEASE ENTER")
+            while True:
+                ins = input("  INITIAL COORDINATES (X,Y)").split(',')
+                if len(ins) == 2:
+                    from1, from2 = int(ins[0]), int(ins[1])
+                    break
+            while True:
+                ins = input("  FINAL COORDINATES (X,Y)").split(',')
+                if len(ins) == 2:
+                    to1, to2 = int(ins[0]), int(ins[1])
+                    break
+            print_direction(from1, from2, to1, to2)
+            return
+        else:
+            print(
+                "FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:\n"
+                "   0 = CUMULATIVE GALACTIC RECORD\n"
+                "   1 = STATUS REPORT\n"
+                "   2 = PHOTON TORPEDO DATA\n"
+                "   3 = STARBASE NAV DATA\n"
+                "   4 = DIRECTION/DISTANCE CALCULATOR\n"
+                "   5 = GALAXY 'REGION NAME' MAP\n"
+            )
+
+
+def print_direction(from1, from2, to1, to2):
+    to2 -= from2
+    from2 = from1 - to1
+
+    def f1(c1, a, x):
+        if abs(a) >= abs(x):
+            print(f"DIRECTION = {c1 + (abs(x) / abs(a))}")
+        else:
+            print(f"DIRECTION = {c1 + (((abs(x) - abs(a)) + abs(x)) / abs(x))}")
+
+    def f2(c1, a, x):
+        if abs(a) <= abs(x):
+            print(f"DIRECTION = {c1 + (abs(a) / abs(x))}")
+        else:
+            print(f"DIRECTION = {c1 + (((abs(a) - abs(x)) + abs(a)) / abs(a))}")
+
+    if to2 < 0:
+        if from2 > 0:
+            f1(3, from2, to2)
+        elif to2 != 0:
+            f2(5, from2, to2)
+        else:
+            f1(7, from2, to2)
+    else:
+        if from2 < 0:
+            f1(7, from2, to2)
+        elif to2 > 0:
+            f2(1, from2, to2)
+        elif from2 == 0:
+            f2(5, from2, to2)
+        else:
+            f2(1, from2, to2)
+
+    print(f"DISTANCE = {sqrt(to2 ** 2 + from2 ** 2)}")
+
+
+# -------------------------------------------------------------------------
+#  Game transitions
+# -------------------------------------------------------------------------
+
+
+def startup():
+    global g, c, k, n, z, d, t, t0, t9, d0, e, e0, p, p0, s9
+    global s, b9, k7, k9, devices
+    global q1, q2, s1, s2
+
+    print(
+        "\n\n\n\n\n\n\n\n\n\n\n"
+        "                                    ,------*------,\n"
+        "                    ,-------------   '---  ------'\n"
+        "                     '-------- --'      / /\n"
+        "                         ,---' '-------/ /--,\n"
+        "                          '----------------'\n\n"
+        "                    THE USS ENTERPRISE --- NCC-1701\n"
+        "\n\n\n\n\n"
+    )
+
+    # set up global game variables
+    g = [[0] * 8 for _ in range(8)]
+    c = [[0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1],
+         [0, 1]]
+    k = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
+    n = [0, 0, 0]
+    z = [[0] * 8 for _ in range(8)]
+    d = [0] * 8
+    t = 100 * random.randint(20, 39)
+    t0 = t
+    t9 = random.randint(25, 34)
+    d0 = 0
+    e = 3000
+    e0 = e
+    p = 10
+    p0 = p
+    s9 = 200
+    s = 0
+    b9 = 2
+    k9 = 0
+    devices = ['WARP ENGINES', 'SHORT RANGE SENSORS', 'LONG RANGE SENSORS',
+               'PHASER CONTROL', 'PHOTON TUBES', 'DAMAGE CONTROL',
+               'SHIELD CONTROL', 'LIBRARY-COMPUTER']
+
+    # initialize Enterprise's position
+    q1 = fnr()
+    q2 = fnr()
+    s1 = fnr()
+    s2 = fnr()
+
+    # initialize contents of galaxy
+    for i in range(8):
+        for j in range(8):
+            k3 = 0
+            r1 = random.random()
+
+            if r1 > 0.98:
+                k3 = 3
+            elif r1 > 0.95:
+                k3 = 2
+            elif r1 > 0.80:
+                k3 = 1
+            k9 += k3
+
+            b3 = 0
+            if random.random() > 0.96:
+                b3 = 1
+                b9 += 1
+            g[i][j] = k3 * 100 + b3 * 10 + fnr() + 1
+
+    if k9 > t9:
+        t9 = k9 + 1
+    if b9 == 0:
+        if g[q1][q2] < 200:
+            g[q1][q2] += 120
+            k9 += 1
+        b9 = 1
+        g[q1][q2] += 10
+        q1 = fnr()
+        q2 = fnr()
+
+    k7 = k9
+    print(
+        "YOUR ORDERS ARE AS FOLLOWS:\n"
+        f"   DESTROY THE {k9} KLINGON WARSHIPS WHICH HAVE INVADED\n"
+        "   THE GALAXY BEFORE THEY CAN ATTACK FEDERATION HEADQUARTERS\n"
+        f"   ON STARDATE {t0+t9}. THIS GIVES YOU {t9} DAYS. THERE {'IS' if b9 == 1 else 'ARE'}\n"
+        f"   {b9} STARBASE{'' if b9 == 1 else 'S'} IN THE GALAXY FOR RESUPPLYING YOUR SHIP.\n"
+    )
+
+
+def new_quadrant():
+    global z4, z5, k3, b3, s3, g5, d4, qs, b4, b5
+
+    z4 = q1
+    z5 = q2
+    k3 = 0
+    b3 = 0
+    s3 = 0
+    g5 = 0
+    d4 = 0.5 * random.random()
+    z[q1][q2] = g[q1][q2]
+
+    if 0 <= q1 < 8 and 0 <= q2 < 8:
+        g2s = quadrant_name(z4, z5, False)
+        if t == t0:
+            print('\nYOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED')
+            print(f"IN THE GALACTIC QUADRANT, '{g2s}'.\n")
+        else:
+            print(f'\nNOW ENTERING {g2s} QUADRANT . . .\n')
+
+        k3 = int(g[q1][q2] * 0.01)
+        b3 = int(g[q1][q2] * 0.1) - 10 * k3
+        s3 = g[q1][q2] - 100 * k3 - 10 * b3
+        if k3 != 0:
+            print('COMBAT AREA      CONDITION RED')
+            if s <= 200:
+                print('   SHIELDS DANGEROUSLY LOW')
+
+        for i in range(3):
+            k[i][0] = k[i][1] = 0
+
+    for i in range(3):
+        k[i][2] = 0
+
+    qs = ' ' * 192
+
+    z1 = s1
+    z2 = s2
+    insert_marker(z1, z2, '<*>')
+    if k3 > 0:
+        for i in range(k3):
+            r1, r2 = find_empty_place()
+            insert_marker(r1, r2, '+K+')
+            k[i] = [r1, r2, s9 * (0.5 + random.random())]
+    if b3 > 0:
+        r1, r2 = find_empty_place()
+        insert_marker(r1, r2, '>!<')
+        b4, b5 = r1, r2
+    for i in range(s3):
+        r1, r2 = find_empty_place()
+        insert_marker(r1, r2, ' * ')
+
+    short_range_scan()
+
+
+def end_game(won=False, quit=False, enterprise_killed=False):
+    global k7, t, t0
+
+    if won:
+        print("CONGRULATION, CAPTAIN! THE LAST KLINGON BATTLE CRUISER")
+        print("MENACING THE FEDERATION HAS BEEN DESTROYED.\n")
+        print(f"YOUR EFFICIENCY RATING IS {1000 * (k7 / (t - t0))**2}")
+    else:
+        if not quit:
+            if enterprise_killed:
+                print('\nTHE ENTERPRISE HAS BEEN DESTROYED. THEN FEDERATION WILL BE CONQUERED')
+
+            print(f'IT IS STARDATE {t}')
+
+        print(f'THERE WERE {k9} KLINGON BATTLE CRUISERS LEFT AT')
+        print(f'THE END OF YOUR MISSION.\n\n')
+
+        if b9 == 0:
+            exit()
+
+    print('THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER')
+    print('FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,')
+    astr = input("LET HIM STEP FORWARD AND ENTER 'AYE' ")
+    if astr == 'AYE' or astr == 'aye':
+        return
+    exit()
+
+
+# -------------------------------------------------------------------------
+#  Game loop
+# -------------------------------------------------------------------------
+
+
+while True:
+    startup()
+    new_quadrant()
+
+    restart = False
+
+    while not restart:
+        if s + e <= 10 or (e <= 10 and d[6] != 0):
+            print("\n** FATAL ERROR **   YOU'VE JUST STRANDED YOUR SHIP IN SPACE")
+            print("YOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND SHIELD CONTROL")
+            print("IS PRESENTLY INCAPABLE OF CROSS-CIRCUITING TO ENGINE ROOM!!")
+
+        command = input('COMMAND ').upper()
+
+        if command == 'NAV':
+            navigation()
+        elif command == 'SRS':
+            short_range_scan()
+        elif command == 'LRS':
+            long_range_scan()
+        elif command == 'PHA':
+            phaser_control()
+        elif command == 'TOR':
+            photon_torpedoes()
+        elif command == 'SHE':
+            shield_control()
+        elif command == 'DAM':
+            damage_control()
+        elif command == 'COM':
+            computer()
+        elif command == 'XXX':
+            end_game(quit=True)  # only returns on restart
+            restart = True
+        else:
+            print(
+                'ENTER ONE OF THE FOLLOWING:\n'
+                '  NAV  (TO SET COURSE)\n'
+                '  SRS  (FOR SHORT RANGE SENSOR SCAN)\n'
+                '  LRS  (FOR LONG RANGE SENSOR SCAN)\n'
+                '  PHA  (TO FIRE PHASERS)\n'
+                '  TOR  (TO FIRE PHOTON TORPEDOES)\n'
+                '  SHE  (TO RAISE OR LOWER SHIELDS)\n'
+                '  DAM  (FOR DAMAGE CONTROL REPORTS)\n'
+                '  COM  (TO CALL ON LIBRARY-COMPUTER)\n'
+                '  XXX  (TO RESIGN YOUR COMMAND)\n'
+            )

From 2ee4e57d6777cbf454c5ebbf0ef2045da218ce54 Mon Sep 17 00:00:00 2001
From: Swofty 
Date: Mon, 1 Mar 2021 13:28:51 +1100
Subject: [PATCH 112/749] 63 Name ported to Java

Porting over name to Java, should be fully complete.
---
 63 Name/java/main.class | 55 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 63 Name/java/main.class

diff --git a/63 Name/java/main.class b/63 Name/java/main.class
new file mode 100644
index 00000000..db01b014
--- /dev/null
+++ b/63 Name/java/main.class	
@@ -0,0 +1,55 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+public class main {
+
+    public static void printempty() { System.out.println(" "); }
+
+    public static void print(String toprint) { System.out.println(toprint); }
+
+    public static void main(String[] args) {
+        print("                                          NAME");
+        print("                         CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        printempty();
+        printempty();
+        print("HELLO.");
+        print("MY NAME iS CREATIVE COMPUTER.");
+        print("WHATS YOUR NAME? (FIRST AND LAST)");
+
+        Scanner namesc = new Scanner(System.in);
+        String name = namesc.nextLine();
+
+        String namereversed = new StringBuilder(name).reverse().toString();
+
+        char namesorted[] = name.toCharArray();
+        Arrays.sort(namesorted);
+
+        printempty();
+        print("THANK YOU, " + namereversed);
+        printempty();
+        print("OOPS!  I GUESS I GOT IT BACKWARDS.  A SMART");
+        print("COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!");
+        printempty();
+        printempty();
+        print("BUT I JUST NOTICED YOUR LETTERS ARE OUT OF ORDER.");
+
+        print("LET'S PUT THEM IN ORDER LIKE THIS: " + new String(namesorted));
+        printempty();
+        printempty();
+
+        print("DON'T YOU LIKE THAT BETTER?");
+        printempty();
+
+        Scanner agreementsc = new Scanner(System.in);
+        String agreement = agreementsc.nextLine();
+
+        if (agreement.equalsIgnoreCase("yes")) {
+            print("I KNEW YOU'D AGREE!!");
+        } else {
+            print("I'M SORRY YOU DON'T LIKE IT THAT WAY.");
+            printempty();
+            print("I REALLY ENJOYED MEETING YOU, " + name);
+            print("HAVE A NICE DAY!");
+        }
+    }
+}

From 2ded55c46e274eb332036401cdb9871418ba6039 Mon Sep 17 00:00:00 2001
From: ibrahim albarghouthi 
Date: Mon, 1 Mar 2021 04:45:51 +0200
Subject: [PATCH 113/749] Converted 'Word' to ruby

---
 96 Word/ruby/word.rb | 66 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 96 Word/ruby/word.rb

diff --git a/96 Word/ruby/word.rb b/96 Word/ruby/word.rb
new file mode 100644
index 00000000..1f0eead5
--- /dev/null
+++ b/96 Word/ruby/word.rb	
@@ -0,0 +1,66 @@
+#!/usr/bin/env ruby
+# WORD
+#
+# Converted from BASIC to Ruby
+
+
+WORDS = ["DINKY", "SMOKE", "WATER", "GRASS", "TRAIN", "MIGHT",
+         "FIRST","CANDY", "CHAMP", "WOULD", "CLUMP", "DOPEY"]
+
+def game_loop
+  target_word = WORDS.sample.downcase
+  guess_count = 0
+  guess_progress = ["-"] * 5
+
+  puts "You are starting a new game..."
+  while true
+    guess_word = ""
+    while guess_word == ""
+      puts "Guess a five letter word. "
+      guess_word = gets.chomp
+      if guess_word == "?"
+        break
+      elsif !guess_word.match(/^[[:alpha:]]+$/) || guess_word.length != 5
+        guess_word = ""
+        puts "You must guess a five letter word. Start again."
+      end
+    end
+    guess_count += 1
+    if guess_word == "?"
+      puts "The secret word is #{target_word}"
+      break
+    else
+      common_letters = ""
+      matches = 0
+      5.times do |i|
+        5.times do |j|
+          if guess_word[i] == target_word[j]
+            matches += 1
+            common_letters = common_letters + guess_word[i]
+            guess_progress[j] = guess_word[i] if i == j
+          end
+        end
+      end
+      puts "There were #{matches} matches and the common letters were... #{common_letters}"
+      puts "From the exact letter matches, you know............ #{guess_progress.join}"
+      if guess_progress.join == guess_word
+        puts "You have guessed the word. It took #{guess_count} guesses!"
+        break
+      elsif matches < 2
+        puts "If you give up, type '?' for you next guess."
+      end
+    end
+  end
+end
+
+puts " " * 33 + "WORD"
+puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n"
+puts "I am thinking of a word -- you guess it. I will give you"
+puts "clues to help you get it. Good luck!!\n"
+
+keep_playing = true
+while keep_playing
+  game_loop
+  puts "\n Want to play again? "
+  keep_playing = gets.chomp.downcase.index("y") == 0
+end

From 1d4b0d24e3af29d3003d152deea2a5ea23cf5a78 Mon Sep 17 00:00:00 2001
From: Sankarsan Kampa <19631364+iamtraction@users.noreply.github.com>
Date: Mon, 1 Mar 2021 08:32:43 +0530
Subject: [PATCH 114/749] hurkle: add python port

Signed-off-by: Sankarsan Kampa <19631364+iamtraction@users.noreply.github.com>
---
 51 Hurkle/python/hurkle.py | 65 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 51 Hurkle/python/hurkle.py

diff --git a/51 Hurkle/python/hurkle.py b/51 Hurkle/python/hurkle.py
new file mode 100644
index 00000000..dfe40d8d
--- /dev/null
+++ b/51 Hurkle/python/hurkle.py	
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+#
+# Ported to Python by @iamtraction
+
+from random import random
+
+
+def direction(A, B, X, Y):
+    """Prints the direction hint for finding the hurkle."""
+
+    print("GO ", end="")
+    if Y < B:
+        print("NORTH", end="")
+    elif Y > B:
+        print("SOUTH", end="")
+
+    if X < A:
+        print("EAST", end="")
+    elif X > A:
+        print("WEST", end="")
+
+    print()
+
+
+if __name__ == "__main__":
+    print(" " * 33 + "HURKLE")
+    print(" " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+
+    print("\n\n\n")
+
+    N = 5
+    G = 10
+
+    print()
+    print("A HURKLE IS HIDING ON A", G, "BY", G, "GRID. HOMEBASE")
+    print("ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,")
+    print("AND ANY POINT ON THE GRID IS DESIGNATED BY A")
+    print("PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST")
+    print("NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER")
+    print("IS THE VERTICAL POSITION. YOU MUST TRY TO")
+    print("GUESS THE HURKLE'S GRIDPOINT. YOU GET", N, "TRIES.")
+    print("AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE")
+    print("DIRECTION TO GO TO LOOK FOR THE HURKLE.")
+    print()
+
+    while True:
+        A = int(G * random())
+        B = int(G * random())
+
+        for k in range(0, N):
+            print("\nGUESS #" + str(k))
+
+            # read coordinates in `X, Y` format, split the string
+            # at `,`, and then parse the coordinates to `int` and
+            # store them in `X` and `Y` respectively.
+            [ X, Y ] = [int(c) for c in input("X,Y? ").split(",")]
+
+            if abs(X - A) + abs(Y - B) == 0:
+                print("\nYOU FOUND HIM IN", k + 1, "GUESSES!")
+                break
+            else:
+                direction(A, B, X, Y)
+                continue
+
+        print("\n\nLET'S PLAY AGAIN, HURKLE IS HIDING.\n")

From fb8b8c75cb1ec4c01640bbff3a447fd347f27bb6 Mon Sep 17 00:00:00 2001
From: Daniel Piron 
Date: Sat, 20 Feb 2021 02:06:52 -0500
Subject: [PATCH 115/749] Python port of Tic-Tac-Toe 2 (first pass)

Needs work on Computer AI
---
 89 Tic-Tac-Toe/python/tictactoe2.py | 229 ++++++++++++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100755 89 Tic-Tac-Toe/python/tictactoe2.py

diff --git a/89 Tic-Tac-Toe/python/tictactoe2.py b/89 Tic-Tac-Toe/python/tictactoe2.py
new file mode 100755
index 00000000..95493657
--- /dev/null
+++ b/89 Tic-Tac-Toe/python/tictactoe2.py	
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+from enum import Enum
+
+
+class OccupiedBy(Enum):
+    COMPUTER=-1
+    EMPTY=0
+    PLAYER=1
+
+
+class Winner(Enum):
+    NONE=0
+    COMPUTER=1
+    PLAYER=2
+    DRAW=3
+
+
+class Space(Enum):
+    TOP_LEFT = 0
+    TOP_CENTER = 1
+    TOP_RIGHT = 2
+    MID_LEFT = 3
+    MID_CENTER = 4
+    MID_RIGHT = 5
+    BOT_LEFT = 6
+    BOT_CENTER = 7
+    BOT_RIGHT = 8
+
+
+def line_170(board, g, h, j, k):
+    if g == OccupiedBy.Player:
+        if board[Space.MID_CENTER] == g:
+            if board[Space.TOP_RIGHT] == g and board[Space.BOTTOM_LEFT] is OccupiedBy.EMPTY: # Line 171
+                return Space.BOTTOM_LEFT # Line 187
+            elif board[Space.BOTTOM_RIGHT] == g and board[Space.TOP_LEFT] is OccupiedBy.EMPTY: # Line 172
+                return Space.TOP_LEFT # Line 181
+            elif board[Space.BOTTOM_LEFT] == g and board[Space.TOP_RIGHT] is OccupiedBy.EMPTY: # Line 173
+                return Space.TOP_RIGHT # Line 183
+            elif board[Space.BOTTOM_RIGHT] is OccupiedBy.PLAYER and board[Space.TOP_RIGHT] is OccupiedBy.EMPTY: # Line 174
+                return Space.TOP_RIGHT # Line 189
+            elif g is OccupiedBy.COMPUTER:
+                g = OccupiedBy.PLAYER
+                h = OccupiedBy.COMPUTER
+                return line_118(board, g, h, j, k)
+
+
+def line_150(board, g, h, j, k):
+    if board[k] != g: # line 150
+        if (board[k] == h       # line 160
+            or board[k + 6] != g   # line 161
+            or board[k + 3] != g): # line 162
+            return -1 # Goto 170
+        else:
+            return k + 3  # Line 163
+    elif board[k + 6] != g: # line 152
+        if board[k + 6] != 0 or board[k + 3] != g: # line 165
+            return -1 # Goto 170
+    elif board[k + 3]: # line 156
+        return - 1
+
+    return k + 6
+
+
+def line_120(board, g, h, j, k):
+    if board[j] != g:
+        if board[j] == h or board[j+2] != g or board[j+1] != g:
+            if board[k] != g:
+                if board[k + 6] != g and (board[k + 6] != 0 or board[k+3] != g):
+                    # 450 IF G=1 THEN 465
+                    pass
+            elif board[j + 2] is not g: # Line 122
+                pass
+            elif board[j + 1] is not OccupiedBy.EMPTY:
+                pass
+
+
+def line_118(board, g, h):
+    for j in range(7):
+        for k in range (3):
+            return line_120(board, g, h, j, k)
+
+
+def think(board, g, h, moves):
+
+    if board[Space.MID_CENTER] is OccupiedBy.EMPTY:
+        return Space.MID_CENTER
+
+    if board[Space.MID_CENTER] is OccupiedBy.PLAYER:
+        if board[Space.TOP_CENTER] is OccupiedBy.PLAYER and board[Space.TOP_LEFT] is OccupiedBy.EMPTY \
+           or board[Space.MID_LEFT] is OccupiedBy.PLAYER and board[Space.TOP_LEFT] is OccupiedBy.EMPTY:
+             return Space.BOT_LEFT
+        elif board[Space.MID_RIGHT] is OccupiedBy.PLAYER and board[Space.BOT_RIGHT] is OccupiedBy.EMPTY \
+           or board[Space.BOT_CENTER] is OccupiedBy.PLAYER and board[Space.BOT_RIGHT] is OccupiedBy.EMPTY:
+             return Space.BOT_RIGHT
+
+    if g == OccupiedBy.PLAYER:
+        j = 3 * int((moves-1) / 3)
+        if move == j + 1:
+            k = 1
+        if move == j + 2:
+            k = 2
+        if move == j + 3:
+            k = 3
+        return subthink(g, h, j, k)
+
+
+def render_board(board, space_mapping):
+    vertical_divider = '!'
+    horizontal_divider = '---+---+---'
+    lines = []
+    lines.append(vertical_divider.join(space_mapping[space] for space in board[0:3]))
+    lines.append(horizontal_divider)
+    lines.append(vertical_divider.join(space_mapping[space] for space in board[3:6]))
+    lines.append(horizontal_divider)
+    lines.append(vertical_divider.join(space_mapping[space] for space in board[6:9]))
+    return '\n'.join(lines)
+
+
+def determine_winner(board, g):
+    # Check for matching horizontal lines
+    for i in range(Space.TOP_LEFT.value, Space.BOT_LEFT.value + 1, 3):      # Line 1095
+        if board[i] != board[i+1] or board[i] != board[i+2]:  # Lines 1100 and 1105
+            continue # First third of Line 1115 
+        elif board[i] == OccupiedBy.COMPUTER: # 
+            return Winner.COMPUTER
+        elif board[i] == OccupiedBy.PLAYER:
+            return Winner.PLAYER
+
+    # Check for matching vertical lines
+    for i in range(Space.TOP_LEFT.value, Space.TOP_LEFT.value + 1, 1):  # Second third of Line 1115
+        if board[i] != board[i+3] or board[i] != board[i+6]: # Last third of Line 1115
+            continue # First third of 1150
+        elif board[i] == OccupiedBy.COMPUTER: # Line 1135
+            return Winner.COMPUTER
+        elif board[i] == OccupiedBy.PLAYER:   # Line 1137
+            return Winner.PLAYER
+
+    # Check diagonals
+    if any(space is OccupiedBy.EMPTY for space in board):
+        if board[Space.MID_CENTER.value] != g:
+            return Winner.NONE
+        elif (board[Space.TOP_LEFT.value] == g and board[Space.BOT_RIGHT.value] == g) or \
+            (board[Space.BOT_LEFT.value] == g and board[Space.TOP_RIGHT.value] == g):
+            return Winner.COMPUTER if g is OccupiedBy.COMPUTER else Winner.PLAYER
+        else:
+            return Winner.NONE
+
+    return Winner.DRAW
+
+
+def computer_think(board):
+        empty_indices = [index for index, space in enumerate(board)
+                         if space is OccupiedBy.EMPTY]
+
+        return empty_indices[0]
+
+
+def prompt_player(board):
+    while True:
+        move = int(input("\nWHERE DO YOU MOVE? "))
+
+        if move == 0:
+            return 0
+
+        if move > 9 or board[move - 1] is not OccupiedBy.EMPTY:
+            print("THAT SQUARE IS OCCUPIED.\n\n")
+            continue
+
+        return move
+
+
+def play():
+    print(' '*30 + 'TIC-TAC-TOE')
+    print(' '*15 + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY')
+    print('\n\n')
+
+    print('THE BOARD IS NUMBERED:')
+    print(' 1  2  3')
+    print(' 4  5  6')
+    print(' 7  8  9')
+    print('\n\n')
+
+    # Default state
+    board = [OccupiedBy.EMPTY] * 9
+    current_player = OccupiedBy.PLAYER
+    space_mapping = {
+        OccupiedBy.EMPTY: '   ',
+        OccupiedBy.PLAYER: ' X ',
+        OccupiedBy.COMPUTER: ' O '
+    }
+
+    symbol = input("DO YOU WANT 'X' OR 'O'? ").upper()
+
+    # If the player doesn't choose X, then assume you want O
+    # and the computer goes first.
+    if symbol != "X":
+        space_mapping[OccupiedBy.PLAYER] = ' O '
+        space_mapping[OccupiedBy.COMPUTER] = ' X '
+        current_player = OccupiedBy.COMPUTER
+
+    while True:
+        if current_player is OccupiedBy.PLAYER:
+            move = prompt_player(board)
+            if move == 0:
+                print("THANKS FOR THE GAME.")
+                break
+            board[move - 1] = current_player
+            print(render_board(board, space_mapping))
+
+        elif current_player is OccupiedBy.COMPUTER:
+            print("\nTHE COMPUTER MOVES TO...")
+            board[computer_think(board)] = current_player
+
+        print(render_board(board, space_mapping))
+
+        winner = determine_winner(board, current_player)
+
+        if winner is not Winner.NONE:
+           print(winner)
+           break
+
+        if current_player is OccupiedBy.COMPUTER:
+            current_player = OccupiedBy.PLAYER
+        elif current_player is OccupiedBy.PLAYER:
+            current_player = OccupiedBy.COMPUTER
+
+
+if __name__ == '__main__':
+    play()

From edd76ea962df5ba171c6f7de446a523d8440f746 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sun, 28 Feb 2021 22:19:46 -0600
Subject: [PATCH 116/749] Ported BATTLE to Javascript

---
 09 Battle/javascript/battle.html |   9 +
 09 Battle/javascript/battle.js   | 316 +++++++++++++++++++++++++++++++
 2 files changed, 325 insertions(+)
 create mode 100644 09 Battle/javascript/battle.html
 create mode 100644 09 Battle/javascript/battle.js

diff --git a/09 Battle/javascript/battle.html b/09 Battle/javascript/battle.html
new file mode 100644
index 00000000..83cccf10
--- /dev/null
+++ b/09 Battle/javascript/battle.html	
@@ -0,0 +1,9 @@
+
+
+BATTLE
+
+
+

+
+
+
diff --git a/09 Battle/javascript/battle.js b/09 Battle/javascript/battle.js
new file mode 100644
index 00000000..3adcfaba
--- /dev/null
+++ b/09 Battle/javascript/battle.js	
@@ -0,0 +1,316 @@
+// BATTLE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var fa = [];
+var ha = [];
+var aa = [];
+var ba = [];
+var ca = [];
+var la = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "BATTLE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    // -- BATTLE WRITTEN BY RAY WESTERGARD  10/70
+    // COPYRIGHT 1971 BY THE REGENTS OF THE UNIV. OF CALIF.
+    // PRODUCED AT THE LAWRENCE HALL OF SCIENCE, BERKELEY
+    while (1) {
+        for (x = 1; x <= 6; x++) {
+            fa[x] = [];
+            ha[x] = [];
+            for (y = 1; y <= 6; y++) {
+                fa[x][y] = 0;
+                ha[x][y] = 0;
+            }
+        }
+        for (i = 1; i <= 3; i++) {
+            n = 4 - i;
+            for (j = 1; j <= 2; j++) {
+                while (1) {
+                    a = Math.floor(6 * Math.random() + 1);
+                    b = Math.floor(6 * Math.random() + 1);
+                    d = Math.floor(4 * Math.random() + 1);
+                    if (fa[a][b] > 0)
+                        continue;
+                    m = 0;
+                    switch (d) {
+                        case 1:
+                            ba[1] = b;
+                            ba[2] = 7;
+                            ba[3] = 7;
+                            for (k = 1; k <= n; k++) {
+                                if (m <= 1 && ba[k] != 6 && fa[a][ba[k] + 1] <= 0) {
+                                    ba[k + 1] = ba[k] + 1;
+                                } else {
+                                    m = 2;
+                                    if (ba[1] < ba[2] && ba[1] < ba[3])
+                                        z = ba[1];
+                                    if (ba[2] < ba[1] && ba[2] < ba[3])
+                                        z = ba[2];
+                                    if (ba[3] < ba[1] && ba[3] < ba[2])
+                                        z = ba[3];
+                                    if (z == 1)
+                                        break;
+                                    if (fa[a][z - 1] > 0)
+                                        break;
+                                    ba[k + 1] = z - 1;
+                                }
+                            }
+                            if (k <= n)
+                                continue;
+                            fa[a][b] = 9 - 2 * i - j;
+                            for (k = 1; k <= n; k++)
+                                fa[a][ba[k + 1]] = fa[a][b];
+                            break;
+                        case 2:
+                            aa[1] = a;
+                            ba[1] = b;
+                            aa[2] = 0;
+                            aa[3] = 0;
+                            ba[2] = 0;
+                            ba[3] = 0;
+                            for (k = 1; k <= n; k++) {
+                                if (m <= 1 && aa[k] != 1 && ba[k] != 1 && fa[aa[k] - 1][ba[k] - 1] <= 0 && (fa[aa[k] - 1][ba[k]] <= 0 || fa[aa[k] - 1][ba[k]] != fa[aa[k]][ba[k] - 1])) {
+                                    aa[k + 1] = aa[k] - 1;
+                                    ba[k + 1] = ba[k] - 1;
+                                } else {
+                                    m = 2;
+                                    if (aa[1] > aa[2] && aa[1] > aa[3])
+                                        z1 = aa[1];
+                                    if (aa[2] > aa[1] && aa[2] > aa[3])
+                                        z1 = aa[2];
+                                    if (aa[3] > aa[1] && aa[3] > aa[2])
+                                        z1 = aa[3];
+                                    if (ba[1] > ba[2] && ba[1] > ba[3])
+                                        z2 = ba[1];
+                                    if (ba[2] > ba[1] && ba[2] > ba[3])
+                                        z2 = ba[2];
+                                    if (ba[3] > ba[1] && ba[3] > ba[2])
+                                        z2 = ba[3];
+                                    if (z1 == 6 || z2 == 6)
+                                        break;
+                                    if (fa[z1 + 1][z2 + 1] > 0)
+                                        break;
+                                    if (fa[z1][z2 + 1] > 0 && fa[z1][z2 + 1] == fa[z1 + 1][z2])
+                                        break;
+                                    aa[k + 1] = z1 + 1;
+                                    ba[k + 1] = z2 + 1;
+                                }
+                            }
+                            if (k <= n)
+                                continue;
+                            fa[a][b] = 9 - 2 * i - j;
+                            for (k = 1; k <= n; k++)
+                                fa[aa[k + 1]][ba[k + 1]] = fa[a][b];
+                            break;
+                        case 3:
+                            aa[1] = a;
+                            aa[2] = 7;
+                            aa[3] = 7;
+                            for (k = 1; k <= n; k++) {
+                                if (m <= 1 && aa[k] != 6 && fa[aa[k] + 1][b] <= 0) {
+                                    aa[k + 1] = aa[k] + 1;
+                                } else {
+                                    m = 2;
+                                    if (aa[1] < aa[2] && aa[1] < aa[3])
+                                        z = aa[1];
+                                    if (aa[2] < aa[1] && aa[2] < aa[3])
+                                        z = aa[2];
+                                    if (aa[3] < aa[1] && aa[3] < aa[2])
+                                        z = aa[3];
+                                    if (z == 1)
+                                        break;
+                                    if (fa[z - 1][b] > 0)
+                                        break;
+                                    aa[k + 1] = z - 1;
+                                }
+                            }
+                            if (k <= n)
+                                continue;
+                            fa[a][b] = 9 - 2 * i - j;
+                            for (k = 1; k <= n; k++)
+                                fa[aa[k + 1]][b] = fa[a][b];
+                            break;
+                        case 4:
+                            aa[1] = a;
+                            ba[1] = b;
+                            aa[2] = 7;
+                            aa[3] = 7;
+                            ba[2] = 0;
+                            ba[3] = 0;
+                            for (k = 1; k <= n; k++) {
+                                if (m <= 1 && aa[k] != 6 && ba[k] != 1 && fa[aa[k] + 1][ba[k] - 1] <= 0 && (fa[aa[k] + 1][ba[k]] <= 0 || fa[aa[k] + 1][ba[k]] != fa[aa[k]][ba[k] - 1])) {
+                                    aa[k + 1] = aa[k] + 1;
+                                    ba[k + 1] = ba[k] - 1;
+                                } else {
+                                    m = 2;
+                                    if (aa[1] < aa[2] && aa[1] < aa[3])
+                                        z1 = aa[1];
+                                    if (aa[2] < aa[1] && aa[2] < aa[3])
+                                        z1 = aa[2];
+                                    if (aa[3] < aa[1] && aa[3] < aa[2])
+                                        z1 = aa[3];
+                                    if (ba[1] > ba[2] && ba[1] > ba[3])
+                                        z2 = ba[1];
+                                    if (ba[2] > ba[1] && ba[2] > ba[3])
+                                        z2 = ba[2];
+                                    if (ba[3] > ba[1] && ba[3] > ba[2])
+                                        z2 = ba[3];
+                                    if (z1 == 1 || z2 == 6)
+                                        break;
+                                    if (fa[z1 - 1][z2 + 1] > 0)
+                                        break;
+                                    if (fa[z1][z2 + 1] > 0 && fa[z1][z2 + 1] == fa[z1 - 1][z2])
+                                        break;
+                                    aa[k + 1] = z1 - 1;
+                                    ba[k + 1] = z2 + 1;
+                                }
+                            }
+                            if (k <= n)
+                                continue;
+                            fa[a][b] = 9 - 2 * i - j;
+                            for (k = 1; k <= n; k++)
+                                fa[aa[k + 1]][ba[k + 1]] = fa[a][b];
+                            break;
+                    }
+                    break;
+                }
+            }
+        }
+        print("\n");
+        print("THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION\n");
+        print("HAS BEEN CAPTURED BUT NOT DECODED:\n");
+        print("\n");
+        for (i = 1; i <= 6; i++) {
+            for (j = 1; j <= 6; j++) {
+                ha[i][j] = fa[j][i];
+            }
+        }
+        for (i = 1; i <= 6; i++) {
+            str = "";
+            for (j = 1; j <= 6; j++) {
+                str += " " + ha[i][j] + " ";
+            }
+            print(str + "\n");
+        }
+        print("\n");
+        print("DE-CODE IT AND USE IT IF YOU CAN\n");
+        print("BUT KEEP THE DE-CODING METHOD A SECRET.\n");
+        print("\n");
+        for (i = 1; i <= 6; i++) {
+            for (j = 1; j <= 6; j++) {
+                ha[i][j] = 0;
+            }
+        }
+        for (i = 1; i <= 3; i++)
+            la[i] = 0;
+        ca[1] = 2;
+        ca[2] = 2;
+        ca[3] = 1;
+        ca[4] = 1;
+        ca[5] = 0;
+        ca[6] = 0;
+        s = 0;
+        h = 0;
+        print("START GAME\n");
+        while (1) {
+            str = await input();
+            x = parseInt(str);
+            y = parseInt(str.substr(str.indexOf(",") + 1));
+            if (x < 1 || x > 6 || y < 1 || y > 6) {
+                print("INVALID INPUT.  TRY AGAIN.\n");
+                continue;
+            }
+            r = 7 - y;
+            c = x;
+            if (fa[r][c] <= 0) {
+                s++;
+                print("SPLASH!  TRY AGAIN.\n");
+                continue;
+            }
+            if (ca[fa[r][c]] >= 4) {
+                print("THERE USED TO BE A SHIP AT THAT POINT, BUT YOU SUNK IT.\n");
+                print("SPLASH!  TRY AGAIN.\n");
+                s++;
+                continue;
+            }
+            if (ha[r][c] > 0) {
+                print("YOU ALREADY PUT A HOLE IN SHIP NUMBER " + fa[r][c] + " AT THAT POINT.\n");
+                print("SPLASH!  TRY AGAIN.\n");
+                s++;
+                continue;
+            }
+            h++;
+            ha[r][c] = fa[r][c];
+            print("A DIRECT HIT ON SHIP NUMBER " + fa[r][c] + "\n");
+            ca[fa[r][c]]++;
+            if (ca[fa[r][c]] < 4) {
+                print("TRY AGAIN.\n");
+                continue;
+            }
+            la[Math.floor((fa[r][c] - 1) / 2) + 1]++;
+            print("AND YOU SUNK IT.  HURRAH FOR THE GOOD GUYS.\n");
+            print("SO FAR, THE BAD GUYS HAVE LOST\n");
+            print(" " + la[1] + " DESTROYER(S), " + la[2] + " CRUISER(S), AND");
+            print(" " + la[3] + " AIRCRAFT CARRIER(S).\n");
+            print("YOUR CURRENT SPLASH/HIT RATIO IS " + s / h + "\n");
+            if (la[1] + la[2] + la[3] < 6)
+                continue;
+            print("\n");
+            print("YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET\n");
+            print("WITH A FINAL SPLASH/HIT RATIO OF " + s / h + "\n");
+            if (s / h <= 0) {
+                print("CONGRATULATIONS -- A DIRECT HIT EVERY TIME.\n");
+            }
+            print("\n");
+            print("****************************\n");
+            print("\n");
+            break;
+        }
+    }
+}
+
+main();

From ee0aa306ee1690966e968456b72467c91e314dce Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Mon, 1 Mar 2021 14:58:47 +1030
Subject: [PATCH 117/749] Java version of Love game

---
 58 Love/java/src/Love.java | 171 +++++++++++++++++++++++++++++++++++++
 1 file changed, 171 insertions(+)
 create mode 100644 58 Love/java/src/Love.java

diff --git a/58 Love/java/src/Love.java b/58 Love/java/src/Love.java
new file mode 100644
index 00000000..ab06f303
--- /dev/null
+++ b/58 Love/java/src/Love.java	
@@ -0,0 +1,171 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Love
+ * 

+ * Based on the Basic game of Love here + * https://github.com/coding-horror/basic-computer-games/blob/main/58%20Love/love.bas + *

+ * 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 Love { + + // This is actually defined in the data, but made it a const for readability + public static final int ROW_LENGTH = 60; + + // Contains the data to draw the picture + private final ArrayList data; + + // Used for keyboard input + private final Scanner kbScanner; + + public Love() { + data = storeData(); + kbScanner = new Scanner(System.in); + } + + /** + * Show an intro, accept a message, then draw the picture. + */ + public void process() { + intro(); + + int rowLength = data.get(0); + + String message = displayTextAndGetInput("YOUR MESSAGE, PLEASE "); + + // ensure the string is at least 60 characters + while (message.length() < rowLength) { + message += message; + } + + // chop of any extra characters so its exactly ROW_LENGTH in length + if (message.length() > ROW_LENGTH) { + message = message.substring(0, ROW_LENGTH); + } + + // Print header + System.out.println(message); + + int pos = 1; // don't read row length which is value in first element position + + int runningLineTotal = 0; + StringBuilder lineText = new StringBuilder(); + boolean outputChars = true; + while (true) { + int charsOrSpacesLength = data.get(pos); + if (charsOrSpacesLength == ROW_LENGTH) { + // EOF, so exit + break; + } + if (outputChars) { + // add characters from message string for charsOrSpacesLength characters + for (int i = 0; i < charsOrSpacesLength; i++) { + lineText.append(message.charAt(i + runningLineTotal)); + // switch to spaces which will be in the next element of the arraylist + outputChars = false; + } + } else { + // add charsOrSpacesLength spaces to the string + lineText.append(addSpaces(charsOrSpacesLength)); + // Switch to chars to output on next loop + outputChars = true; + } + + // We need to know when to print the string out + runningLineTotal += charsOrSpacesLength; + + // Are we at end of line? If so print and reset for next line + if (runningLineTotal >= ROW_LENGTH) { + System.out.println(lineText); + lineText = new StringBuilder(); + runningLineTotal = 0; + outputChars = true; + } + + // Move to next arraylist element + pos++; + } + + // Print footer + System.out.println(message); + + } + + private void intro() { + System.out.println(addSpaces(33) + "LOVE"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("A TRIBUTE TO THE GREAT AMERICAN ARTIST, ROBERT INDIANA."); + System.out.println("HIS GREATEST WORK WILL BE REPRODUCED WITH A MESSAGE OF"); + System.out.println("YOUR CHOICE UP TO 60 CHARACTERS. IF YOU CAN'T THINK OF"); + System.out.println("A MESSAGE, SIMPLE TYPE THE WORD 'LOVE'"); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.nextLine(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Original Basic program had the data in DATA format. We're importing all the data into an array for ease of + * processing. + * Format of data is + * FIRST int of data is 60, which is the number of characters per line. + * LAST int of data is same as FIRST above. + * Then the data alternates between how many characters to print and how many spaces to print + * You need to keep a running total of the count of ints read and once this hits 60, its time to + * print and then reset count to zero. + * + * @return ArrayList of type Integer containing the data + */ + private ArrayList storeData() { + + ArrayList theData = new ArrayList<>(); + + theData.addAll(Arrays.asList(60, 1, 12, 26, 9, 12, 3, 8, 24, 17, 8, 4, 6, 23, 21, 6, 4, 6, 22, 12, 5, 6, 5)); + theData.addAll(Arrays.asList(4, 6, 21, 11, 8, 6, 4, 4, 6, 21, 10, 10, 5, 4, 4, 6, 21, 9, 11, 5, 4)); + theData.addAll(Arrays.asList(4, 6, 21, 8, 11, 6, 4, 4, 6, 21, 7, 11, 7, 4, 4, 6, 21, 6, 11, 8, 4)); + theData.addAll(Arrays.asList(4, 6, 19, 1, 1, 5, 11, 9, 4, 4, 6, 19, 1, 1, 5, 10, 10, 4, 4, 6, 18, 2, 1, 6, 8, 11, 4)); + theData.addAll(Arrays.asList(4, 6, 17, 3, 1, 7, 5, 13, 4, 4, 6, 15, 5, 2, 23, 5, 1, 29, 5, 17, 8)); + theData.addAll(Arrays.asList(1, 29, 9, 9, 12, 1, 13, 5, 40, 1, 1, 13, 5, 40, 1, 4, 6, 13, 3, 10, 6, 12, 5, 1)); + theData.addAll(Arrays.asList(5, 6, 11, 3, 11, 6, 14, 3, 1, 5, 6, 11, 3, 11, 6, 15, 2, 1)); + theData.addAll(Arrays.asList(6, 6, 9, 3, 12, 6, 16, 1, 1, 6, 6, 9, 3, 12, 6, 7, 1, 10)); + theData.addAll(Arrays.asList(7, 6, 7, 3, 13, 6, 6, 2, 10, 7, 6, 7, 3, 13, 14, 10, 8, 6, 5, 3, 14, 6, 6, 2, 10)); + theData.addAll(Arrays.asList(8, 6, 5, 3, 14, 6, 7, 1, 10, 9, 6, 3, 3, 15, 6, 16, 1, 1)); + theData.addAll(Arrays.asList(9, 6, 3, 3, 15, 6, 15, 2, 1, 10, 6, 1, 3, 16, 6, 14, 3, 1, 10, 10, 16, 6, 12, 5, 1)); + theData.addAll(Arrays.asList(11, 8, 13, 27, 1, 11, 8, 13, 27, 1, 60)); + System.out.println(theData.size()); + + return theData; + } + + public static void main(String[] args) { + + Love love = new Love(); + love.process(); + } +} \ No newline at end of file From af605a80c79216985ac0da7305aaaa4622525141 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Sun, 28 Feb 2021 20:46:23 -0800 Subject: [PATCH 118/749] Port POETRY to Python So much spaghetti in the source BASIC! I've tried to make things more modular, but it's still a complicated machine. There's room for somebody else to refactor this to be cleaner, if they feel like it. --- 70 Poetry/python/poetry.py | 160 +++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 70 Poetry/python/poetry.py diff --git a/70 Poetry/python/poetry.py b/70 Poetry/python/poetry.py new file mode 100644 index 00000000..9e9a1af1 --- /dev/null +++ b/70 Poetry/python/poetry.py @@ -0,0 +1,160 @@ +""" +POETRY + +A poetry generator + +Ported by Dave LeCompte +""" + +""" +PORTING EDITORIAL NOTE: + +The original code is a pretty convoluted mesh of GOTOs and global +state. This adaptation pulls things apart into phrases, but I have +left the variables as globals, which makes goes against decades of +wisdom that global state is bad. +""" + +PAGE_WIDTH = 64 + +import random + +# globals +u = 0 +i = 0 +j = 0 +k = 0 +phrase = 1 +line = "" + +def print_centered(msg): + spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) + print (spaces + msg) + +def process_phrase_1(): + global line + + line_1_options = ["MIDNIGHT DREARY", + "FIERY EYES", + "BIRD OR FIEND", + "THING OF EVIL", + "PROPHET"] + + line = line + line_1_options[i] + return line + +def process_phrase_2(): + global line + global u + + line_2_options = [ + ("BEGUILING ME", 2), + ("THRILLED ME", None), + ("STILL SITTING....", None), + ("NEVER FLITTING", 2), + ("BURNED", None)] + words, u_modifier = line_2_options[i] + line += words + if not (u_modifier is None): + u = u_modifier + +def process_phrase_3(): + global line + + phrases = [ + (False, "AND MY SOUL"), + (False, "DARKNESS THERE"), + (False, "SHALL BE LIFTED"), + (False, "QUOTH THE RAVEN"), + (True, "SIGN OF PARTING"), + ] + + only_if_u, words = phrases[i] + if (not only_if_u) or (u > 0): + line = line + words + +def process_phrase_4(): + global line + + phrases = [ + ("NOTHING MORE"), + ("YET AGAIN"), + ("SLOWLY CREEPING"), + ("...EVERMORE"), + ("NEVERMORE")] + + line += phrases[i] + +def maybe_comma(): + # line 210 + global u + global line + + if len(line) > 0 and line[-1] == ".": + # don't follow a period with a comma, ever + return + + if u != 0 and random.random() <= 0.19: + line += ", " + u = 2 + # line 212 + if random.random() <= 0.65: + line += " " + u += 1 + else: + # line 214 + print(line) + line = "" + u = 0 + + +def pick_phrase(): + global phrase + global line + global i, j, k + + i = random.randint(0, 4) + j += 1 + k += 1 + + if u <= 0 and (j % 2) != 0: + # random indentation is fun! + line += " " * 5 + phrase = j + 1 + + +def main(): + print_centered("POETRY") + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + global line, phrase, j, k, u + + phrase_processors = { + 1: process_phrase_1, + 2: process_phrase_2, + 3: process_phrase_3, + 4: process_phrase_4 + } + + while True: + if phrase >= 1 and phrase <= 4: + phrase_processors[phrase]() + maybe_comma() + elif phrase == 5: + j = 0 + print(line) + line = "" + if k > 20: + print() + u = 0 + k = 0 + else: + phrase = 2 + continue + pick_phrase() + +if __name__ == "__main__": + main() From 7979e2c8cc9ac7881db28d8b697e48d5f671571f Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Sun, 28 Feb 2021 21:33:52 -0800 Subject: [PATCH 119/749] Port ORBIT to Python Pretty straightforward port - a huge portion of the code is drawing ASCII art of Earth. I also took the liberty of deleting unnecessary work to get the argument to math.cos to lie between -180 and 180 degrees. Maybe that was important back in the day. --- 68 Orbit/python/orbit.py | 163 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 68 Orbit/python/orbit.py diff --git a/68 Orbit/python/orbit.py b/68 Orbit/python/orbit.py new file mode 100644 index 00000000..66fb6c56 --- /dev/null +++ b/68 Orbit/python/orbit.py @@ -0,0 +1,163 @@ +""" +ORBIT + +Orbital mechanics simulation + +Port by Dave LeCompte +""" + +import math +import random + +PAGE_WIDTH = 64 + + +def print_centered(msg): + spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) + print(spaces + msg) + + +def print_instructions(): + print( + """SOMEWHERE ABOVE YOUR PLANET IS A ROMULAN SHIP. + +THE SHIP IS IN A CONSTANT POLAR ORBIT. ITS +DISTANCE FROM THE CENTER OF YOUR PLANET IS FROM +10,000 TO 30,000 MILES AND AT ITS PRESENT VELOCITY CAN +CIRCLE YOUR PLANET ONCE EVERY 12 TO 36 HOURS. + +UNFORTUNATELY, THEY ARE USING A CLOAKING DEVICE SO +YOU ARE UNABLE TO SEE THEM, BUT WITH A SPECIAL +INSTRUMENT YOU CAN TELL HOW NEAR THEIR SHIP YOUR +PHOTON BOMB EXPLODED. YOU HAVE SEVEN HOURS UNTIL THEY +HAVE BUILT UP SUFFICIENT POWER IN ORDER TO ESCAPE +YOUR PLANET'S GRAVITY. + +YOUR PLANET HAS ENOUGH POWER TO FIRE ONE BOMB AN HOUR. + +AT THE BEGINNING OF EACH HOUR YOU WILL BE ASKED TO GIVE AN +ANGLE (BETWEEN 0 AND 360) AND A DISTANCE IN UNITS OF +100 MILES (BETWEEN 100 AND 300), AFTER WHICH YOUR BOMB'S +DISTANCE FROM THE ENEMY SHIP WILL BE GIVEN. + +AN EXPLOSION WITHIN 5,000 MILES OF THE ROMULAN SHIP +WILL DESTROY IT. + +BELOW IS A DIAGRAM TO HELP YOU VISUALIZE YOUR PLIGHT. + + + 90 + 0000000000000 + 0000000000000000000 + 000000 000000 + 00000 00000 + 00000 XXXXXXXXXXX 00000 + 00000 XXXXXXXXXXXXX 00000 + 0000 XXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXXXXXX 0000 +180<== 00000 XXXXXXXXXXXXXXXXXXX 00000 ==>0 + 0000 XXXXXXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXX 0000 + 00000 XXXXXXXXXXXXX 00000 + 00000 XXXXXXXXXXX 00000 + 00000 00000 + 000000 000000 + 0000000000000000000 + 0000000000000 + 270 + +X - YOUR PLANET +O - THE ORBIT OF THE ROMULAN SHIP + +ON THE ABOVE DIAGRAM, THE ROMULAN SHIP IS CIRCLING +COUNTERCLOCKWISE AROUND YOUR PLANET. DON'T FORGET THAT +WITHOUT SUFFICIENT POWER THE ROMULAN SHIP'S ALTITUDE +AND ORBITAL RATE WILL REMAIN CONSTANT. + +GOOD LUCK. THE FEDERATION IS COUNTING ON YOU. +""" + ) + + +def get_yes_or_no(): + while True: + response = input().upper() + if response == "YES": + return True + elif response == "NO": + return False + else: + print("PLEASE TYPE 'YES' OR 'NO'") + + +def game_over(is_success): + if is_success: + print("YOU HAVE SUCCESSFULLY COMPLETED YOUR MISSION.") + else: + print("YOU HAVE ALLOWED THE ROMULANS TO ESCAPE.") + print("ANOTHER ROMULAN SHIP HAS GONE INTO ORBIT.") + print("DO YOU WISH TO TRY TO DESTROY IT?") + + return get_yes_or_no() + + +def play_game(): + rom_angle = random.randint(0, 359) + rom_distance = random.randint(100, 300) + rom_angular_velocity = random.randint(10, 30) + hour = 0 + while hour < 7: + hour += 1 + print() + print() + print(f"THIS IS HOUR {hour}, AT WHAT ANGLE DO YOU WISH TO SEND") + print("YOUR PHOTON BOMB?") + + bomb_angle = float(input()) + print("HOW FAR OUT DO YOU WISH TO DETONATE IT?") + bomb_distance = float(input()) + print() + print() + + rom_angle = (rom_angle + rom_angular_velocity) % 360 + angular_difference = rom_angle - bomb_angle + c = math.sqrt( + rom_distance ** 2 + + bomb_distance ** 2 + - 2 + * rom_distance + * bomb_distance + * math.cos(math.radians(angular_difference)) + ) + + print(f"YOUR PHOTON BOMB EXPLODED {c:.4f}*10^2 MILES FROM THE") + print("ROMULAN SHIP.") + + if c <= 50: + # Destroyed the Romulan + return True + + # Ran out of time + return False + + +def main(): + print_centered("ORBIT") + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + print_instructions() + + while True: + success = play_game() + again = game_over(success) + if not again: + return + + +if __name__ == "__main__": + main() From e84711d8c308e5456eac24a1a7f91fcde46683a9 Mon Sep 17 00:00:00 2001 From: Jack Boyce Date: Mon, 1 Mar 2021 01:03:46 -0800 Subject: [PATCH 120/749] testing and cleanup --- 84 Super Star Trek/python/superstartrek.py | 361 +++++++++++---------- 1 file changed, 185 insertions(+), 176 deletions(-) diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py index 9e254519..3182405d 100644 --- a/84 Super Star Trek/python/superstartrek.py +++ b/84 Super Star Trek/python/superstartrek.py @@ -22,14 +22,19 @@ from math import sqrt def fnd(i): + # Find distance between Enterprise and i'th Klingon warship. + global k, s1, s2 + return sqrt((k[i][0] - s1)**2 + (k[i][1] - s2)**2) def fnr(): + # Generate a random number from 0 to 7 inclusive. return int(random.random() * 7.98 + 0.01) def quadrant_name(row, col, region_only=False): + # Return quadrant name visible on scans, etc. region1 = ['ANTARES', 'RIGEL', 'PROCYON', 'VEGA', 'CANOPUS', 'ALTAIR', 'SAGITTARIUS', 'POLLUX'] region2 = ['SIRIUS', 'DENEB', 'CAPELLA', 'BETELGEUSE', 'ALDEBARAN', @@ -45,6 +50,8 @@ def quadrant_name(row, col, region_only=False): def insert_marker(row, col, marker): + # Insert a marker into a given position in the quadrant string `qs`. The + # contents of a quadrant (Enterprise, stars, etc.) are stored in `qs`. global qs if len(marker) != 3: @@ -56,6 +63,8 @@ def insert_marker(row, col, marker): def compare_marker(row, col, test_marker): + # Check whether the position in the current quadrant is occupied with a + # given marker. global qs pos = round(col) * 3 + round(row) * 24 @@ -63,9 +72,9 @@ def compare_marker(row, col, test_marker): def find_empty_place(): + # Find an empty location in the current quadrant. while True: - row = fnr() - col = fnr() + row, col = fnr(), fnr() if compare_marker(row, col, ' '): return row, col @@ -76,23 +85,25 @@ def find_empty_place(): def navigation(): + # Take navigation input and move the Enterprise. global d, s, e, k, s1, s2, qs, t8, t9, t, w1, c, q1, q2 - c1 = float(input("COURSE (1-9) ")) + c1 = float(input("COURSE (1-9)? ")) if c1 == 9: c1 = 1 if c1 < 1 or c1 >= 9: print(" LT. SULU REPORTS, 'INCORRECT COURSE DATA, SIR!'") return xs = '0.2' if d[0] < 0 else '8' - w1 = float(input(f"WARP FACTOR (0-{xs}) ")) + w1 = float(input(f"WARP FACTOR (0-{xs})? ")) if d[0] < 0 and w1 > 0.2: print("WARP ENGINES ARE DAMAGED. MAXIMUM SPEED = WARP 0.2") return if w1 == 0: return if w1 < 0 or w1 > 8: - print(f" CHIEF ENGINEER SCOTT REPORTS 'THE ENGINES WON'T TAKE WARP {w1}!'") + print(" CHIEF ENGINEER SCOTT REPORTS 'THE ENGINES WON'T TAKE " + f"WARP {w1}!'") return n = int(w1 * 8 + 0.5) @@ -133,10 +144,11 @@ def navigation(): r1 = fnr() if random.random() < 0.6: d[r1] -= random.random() * 5 + 1 - print(f'DAMAGE CONTROL REPORT: {devices[r1]} DAMAGED\n') + print(f"DAMAGE CONTROL REPORT: {devices[r1]} DAMAGED\n") else: d[r1] += random.random() * 3 + 1 - print(f'DAMAGE CONTROL REPORT: {devices[r1]} STATE OF REPAIR IMPROVED\n') + print(f"DAMAGE CONTROL REPORT: {devices[r1]} STATE OF " + "REPAIR IMPROVED\n") # begin moving starship insert_marker(int(s1), int(s2), ' ') @@ -178,10 +190,12 @@ def navigation(): q2 = s2 = 7 if x5 == 1: print("LT. UHURA REPORTS MESSAGE FROM STARFLEET COMMAND:") - print(" 'PERMISSION TO ATTEMPT CROSSING OF GALACTIC PERIMETER") + print(" 'PERMISSION TO ATTEMPT CROSSING OF GALACTIC " + "PERIMETER") print(" IS HEREBY *DENIED*. SHUT DOWN YOUR ENGINES.'") print("CHIEF ENGINEER SCOTT REPORTS 'WARP ENGINES SHUT DOWN") - print(f" AT SECTOR {s1 + 1},{s2 + 1} OF QUADRANT {q1 + 1},{q2 + 1}.'") + print(f" AT SECTOR {s1 + 1} , {s2 + 1} OF QUADRANT " + f"{q1 + 1} , {q2 + 1}.'") if t > t0 + t9: end_game() if 8 * q1 + q2 == 8 * q4 + q5: @@ -195,10 +209,8 @@ def navigation(): if qs[s8:(s8 + 2)] != ' ': s1 = int(s1 - x1) s2 = int(s2 - x2) - print( - "WARP ENGINES SHUT DOWN AT SECTOR " - f"{s1 + 1},{s2 + 1} DUE TO BAD NAVAGATION" - ) + print("WARP ENGINES SHUT DOWN AT SECTOR " + f"{s1 + 1} , {s2 + 1} DUE TO BAD NAVAGATION") break else: s1, s2 = int(s1), int(s2) @@ -217,6 +229,7 @@ def navigation(): def maneuver_energy(n): + # Deduct the energy for navigation from energy/shields. global e, s e -= n + 10 @@ -231,7 +244,8 @@ def maneuver_energy(n): def short_range_scan(): - global d0, e, p, s + # Print a short range scan. + global d0, e, e0, p, p0, s d0 = 0 for i in (s1 - 1, s1, s1 + 1): @@ -242,7 +256,7 @@ def short_range_scan(): cs = 'DOCKED' e = e0 p = p0 - print('SHIELDS DROPPED FOR DOCKING PURPOSES') + print("SHIELDS DROPPED FOR DOCKING PURPOSES") s = 0 break else: @@ -257,7 +271,7 @@ def short_range_scan(): cs = 'GREEN' if d[1] < 0: - print('\n*** SHORT RANGE SENSORS ARE OUT ***\n') + print("\n*** SHORT RANGE SENSORS ARE OUT ***\n") return sep = '---------------------------------' @@ -269,13 +283,13 @@ def short_range_scan(): line = line + ' ' + qs[pos:(pos + 3)] if i == 0: - line += f' STARDATE {int(t * 10) * 0.1}' + line += f' STARDATE {round(int(t * 10) * 0.1, 1)}' elif i == 1: line += f' CONDITION {cs}' elif i == 2: - line += f' QUADRANT {q1 + 1},{q2 + 1}' + line += f' QUADRANT {q1 + 1} , {q2 + 1}' elif i == 3: - line += f' SECTOR {s1 + 1},{s2 + 1}' + line += f' SECTOR {s1 + 1} , {s2 + 1}' elif i == 4: line += f' PHOTON TORPEDOES {int(p)}' elif i == 5: @@ -290,19 +304,18 @@ def short_range_scan(): def long_range_scan(): + # Print a long range scan. global n, z if d[2] < 0: - print('LONG RANGE SENSORS ARE INOPERABLE') + print("LONG RANGE SENSORS ARE INOPERABLE") return - print(f'LONG RANGE SCAN FOR QUADRANT {q1 + 1},{q2 + 1}') + print(f"LONG RANGE SCAN FOR QUADRANT {q1 + 1} , {q2 + 1}") o1s = '-------------------' print(o1s) for i in (q1 - 1, q1, q1 + 1): - n[0] = -1 - n[1] = -2 - n[2] = -3 + n = [-1, -2, -3] for j in (q2 - 1, q2, q2 + 1): if 0 <= i <= 7 and 0 <= j <= 7: @@ -320,6 +333,7 @@ def long_range_scan(): def phaser_control(): + # Take phaser control input and fire phasers. global d, e, k, k3, k9, qs, g, z, q1, q2 if d[3] < 0: @@ -334,10 +348,10 @@ def phaser_control(): if d[7] < 0: print("COMPUTER FAILURE HAMPERS ACCURACY") - print(f"PHASERS LOCKED ON TARGET; ENERGY AVAILABLE = {e} UNITS") + print(f"PHASERS LOCKED ON TARGET; ENERGY AVAILABLE = {e} UNITS") x = 0 while True: - x = int(input("NUMBER OF UNITS TO FIRE ")) + x = int(input("NUMBER OF UNITS TO FIRE? ")) if x <= 0: return if e - x >= 0: @@ -355,10 +369,12 @@ def phaser_control(): h = int((h1 / fnd(i)) * (random.random() + 2)) if h <= 0.15 * k[i][2]: - print(f"SENSORS SHOW NO DAMAGE TO ENEMY AT {k[i][0] + 1},{k[i][1] + 1}") + print("SENSORS SHOW NO DAMAGE TO ENEMY AT " + f"{k[i][0] + 1} , {k[i][1] + 1}") else: k[i][2] -= h - print(f"UNIT HIT ON KLINGON AT SECTOR {k[i][0] + 1},{k[i][1] + 1}") + print(f" {h} UNIT HIT ON KLINGON AT SECTOR " + f"{k[i][0] + 1} , {k[i][1] + 1}") if k[i][2] <= 0: print("*** KLINGON DESTROYED ***") k3 -= 1 @@ -370,12 +386,13 @@ def phaser_control(): if k9 <= 0: end_game(won=True) else: - print(f" (SENSORS SHOW {k[i][2]} UNITS REMAINING)") + print(f" (SENSORS SHOW {round(k[i][2],6)} UNITS REMAINING)") klingons_fire() def photon_torpedoes(): + # Take photon torpedo input and process firing of torpedoes. global p, d, c, e, s1, s2, k3, k9, b3, b9, t, t0, t9, d0, g, z if p <= 0: @@ -385,7 +402,7 @@ def photon_torpedoes(): print("PHOTON TUBES ARE NOT OPERATIONAL") return - c1 = float(input("PHOTON TORPEDO COURSE (1-9) ")) + c1 = float(input("PHOTON TORPEDO COURSE (1-9)? ")) if c1 == 9: c1 = 1 if c1 < 1 or c1 >= 9: @@ -409,7 +426,7 @@ def photon_torpedoes(): print("TORPEDO MISSED") klingons_fire() return - print(f" {x3 + 1},{y3 + 1}") + print(f" {x3 + 1} , {y3 + 1}") if not compare_marker(x3, y3, ' '): break @@ -423,7 +440,7 @@ def photon_torpedoes(): if x3 == k[i][0] and y3 == k[i][1]: k[i][2] = 0 elif compare_marker(x3, y3, ' * '): - print(f"STAR AT {x3 + 1},{y3 + 1} ABSORBED TORPEDO ENERGY.") + print(f"STAR AT {x3 + 1} , {y3 + 1} ABSORBED TORPEDO ENERGY.") klingons_fire() return elif compare_marker(x3, y3, '>!<'): @@ -446,6 +463,7 @@ def photon_torpedoes(): def klingons_fire(): + # Process nearby Klingons firing on Enterprise. global k3, s, k, d0, d if k3 <= 0: @@ -461,44 +479,47 @@ def klingons_fire(): h = int((k[i][2] / fnd(i)) * (random.random() + 2)) s -= h k[i][2] /= (random.random() + 3) - print(f"{h} UNIT HIT ON ENTERPRISE FROM SECTOR {k[i][0] + 1},{k[i][1] + 1}") + print(f" {h} UNIT HIT ON ENTERPRISE FROM SECTOR " + f"{k[i][0] + 1} , {k[i][1] + 1}") if s <= 0: end_game(enterprise_killed=True) print(f" ") if h >= 20 and random.random() < 0.60 and h / s > 0.02: r1 = fnr() d[r1] -= h / s + 0.5 * random.random() - print(f"DAMAGE CONTROL REPORTS {devices[r1]} DAMAGED BY THE HIT'") + print(f"DAMAGE CONTROL REPORTS '{devices[r1]} DAMAGED " + "BY THE HIT'") def shield_control(): + # Raise or lower the shields. global e, s, d if d[6] < 0: - print('SHIELD CONTROL INOPERABLE') + print("SHIELD CONTROL INOPERABLE") return - x = input(f'ENERGY AVAILABLE = {e + s} NUMBER OF UNITS TO SHIELDS ') + x = input(f"ENERGY AVAILABLE = {e + s} NUMBER OF UNITS TO SHIELDS? ") x = int(x) if x < 0 or s == x: - print('') + print("") return if x > e + s: - print( - "SHIELD CONTROL REPORTS 'THIS IS NOT THE FEDERATION TREASURY.'\n" - "" - ) + print("SHIELD CONTROL REPORTS 'THIS IS NOT THE FEDERATION " + "TREASURY.'\n" + "") return e += s - x s = x - print('DEFLECTOR CONTROL ROOM REPORT:') + print("DEFLECTOR CONTROL ROOM REPORT:") print(f" 'SHIELDS NOW AT {s} UNITS PER YOUR COMMAND.'") def damage_control(): + # Print a damage control report. global d, d0, d4, t if d[5] < 0: @@ -506,7 +527,7 @@ def damage_control(): else: print('\nDEVICE STATE OF REPAIR') for r1 in range(8): - print(f"{devices[r1].ljust(25, ' ')}{int(d[r1] * 100) * 0.01}") + print(f"{devices[r1].ljust(26, ' ')}{int(d[r1] * 100) * 0.01:g}") print() if d0 == 0: @@ -521,7 +542,7 @@ def damage_control(): d3 = 0.9 print("\nTECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;") print(f"ESTIMATED TIME TO REPAIR: {0.01 * int(100 * d3)} STARDATES") - astr = input("WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N) ").upper() + astr = input("WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N)? ").upper() if astr != 'Y': return @@ -532,6 +553,7 @@ def damage_control(): def computer(): + # Perform the various functions of the library computer. global d, g5, z, k9, t0, t9, t, b9, s1, s2, b4, b5 if d[7] < 0: @@ -539,7 +561,7 @@ def computer(): return while True: - coms = input("COMPUTER ACTIVE AND AWAITING COMMAND ") + coms = input("COMPUTER ACTIVE AND AWAITING COMMAND? ") if len(coms) == 0: com = 6 else: @@ -548,34 +570,29 @@ def computer(): return print() - h8 = 1 if com == 0 or com == 5: if com == 5: - h8 = 0 + is_map = True g5 = 1 print(" THE GALAXY") else: - # hardcopy disabled: - # 7540 REM INPUT"DO YOU WANT A HARDCOPY? IS THE TTY ON (Y/N)";A$ - # 7542 REM IFA$="Y"THENPOKE1229,2:POKE1237,3:NULL1 - - print("\n "); - print(f"COMPUTER RECORD OF GALAXY FOR QUADRANT {q1 + 1},{q2 + 1}") - print() + is_map = False + print("\n COMPUTER RECORD OF GALAXY FOR " + f"QUADRANT {q1 + 1} , {q2 + 1}\n") print(" 1 2 3 4 5 6 7 8") sep = " ----- ----- ----- ----- ----- ----- ----- -----" print(sep) for i in range(8): - line = str(i + 1) + ' ' + line = ' ' + str(i + 1) + ' ' - if h8 == 0: + if is_map: g2s = quadrant_name(i, 0, True) - line += (' ' * int(14 - 0.5 * len(g2s))) + g2s + line += (' ' * int(12 - 0.5 * len(g2s))) + g2s g2s = quadrant_name(i, 4, True) - line += (' ' * int(41 - 0.5 * len(g2s) - len(line))) + g2s + line += (' ' * int(39 - 0.5 * len(g2s) - len(line))) + g2s else: for j in range(8): line += ' ' @@ -587,35 +604,41 @@ def computer(): print(line) print(sep) + print() return elif com == 1: print(" STATUS REPORT:") print(f"KLINGON{'S' if k9 > 1 else ''} LEFT: {k9}") - print(f"MISSION MUST BE COMPLETED IN {0.1 * int((t0+t9-t) * 10)} STARDATES") + print("MISSION MUST BE COMPLETED IN " + f"{round(0.1 * int((t0+t9-t) * 10), 1)} STARDATES") if b9 == 0: - print("YOUR STUPIDITY HAS LEFT YOU ON YOUR ON IN") + print("YOUR STUPIDITY HAS LEFT YOU ON YOUR OWN IN") print(" THE GALAXY -- YOU HAVE NO STARBASES LEFT!") else: - print(f"THE FEDERATION IS MAINTAINING {b9} STARBASE{'S' if b9 > 1 else ''} IN THE GALAXY") + print(f"THE FEDERATION IS MAINTAINING {b9} " + f"STARBASE{'S' if b9 > 1 else ''} IN THE GALAXY") damage_control() return elif com == 2: if k3 <= 0: - print("SCIENCE OFFICER SPOCK REPORTS 'SENSORS SHOW NO ENEMY SHIPS") - print(" IN THIS QUADRANT'") + print("SCIENCE OFFICER SPOCK REPORTS 'SENSORS SHOW NO ENEMY " + "SHIPS\n" + " IN THIS QUADRANT'") return - print(f"FROM ENTERPRISE TO KLINGON BATTLE CRUSER{'S' if k3 > 1 else ''}") - h8 = 0 + print("FROM ENTERPRISE TO KLINGON BATTLE " + f"CRUISER{'S' if k3 > 1 else ''}") + for i in range(3): if k[i][2] > 0: print_direction(s1, s2, k[i][0], k[i][1]) return elif com == 3: if b3 == 0: - print("MR. SPOCK REPORTS, 'SENSORS SHOW NO STARBASES IN THIS QUADRANT.'") + print("MR. SPOCK REPORTS, 'SENSORS SHOW NO STARBASES IN THIS " + "QUADRANT.'") return print("FROM ENTERPRISE TO STARBASE:") @@ -623,47 +646,49 @@ def computer(): return elif com == 4: print("DIRECTION/DISTANCE CALCULATOR:") - print(f"YOU ARE AT QUADRANT {q1},{q2} SECTOR {s1},{s2}") + print(f"YOU ARE AT QUADRANT {q1} , {q2} SECTOR {s1} , {s2}") print("PLEASE ENTER") while True: - ins = input(" INITIAL COORDINATES (X,Y)").split(',') + ins = input(" INITIAL COORDINATES (X,Y)? ").split(',') if len(ins) == 2: from1, from2 = int(ins[0]), int(ins[1]) break while True: - ins = input(" FINAL COORDINATES (X,Y)").split(',') + ins = input(" FINAL COORDINATES (X,Y)? ").split(',') if len(ins) == 2: to1, to2 = int(ins[0]), int(ins[1]) break print_direction(from1, from2, to1, to2) return else: - print( - "FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:\n" - " 0 = CUMULATIVE GALACTIC RECORD\n" - " 1 = STATUS REPORT\n" - " 2 = PHOTON TORPEDO DATA\n" - " 3 = STARBASE NAV DATA\n" - " 4 = DIRECTION/DISTANCE CALCULATOR\n" - " 5 = GALAXY 'REGION NAME' MAP\n" - ) + print("FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:\n" + " 0 = CUMULATIVE GALACTIC RECORD\n" + " 1 = STATUS REPORT\n" + " 2 = PHOTON TORPEDO DATA\n" + " 3 = STARBASE NAV DATA\n" + " 4 = DIRECTION/DISTANCE CALCULATOR\n" + " 5 = GALAXY 'REGION NAME' MAP\n") def print_direction(from1, from2, to1, to2): + # Print a direction and distance between two locations in the quadrant + # grid. to2 -= from2 from2 = from1 - to1 def f1(c1, a, x): if abs(a) >= abs(x): - print(f"DIRECTION = {c1 + (abs(x) / abs(a))}") + print(f"DIRECTION = {round(c1 + (abs(x)/abs(a)), 6)}") else: - print(f"DIRECTION = {c1 + (((abs(x) - abs(a)) + abs(x)) / abs(x))}") + print("DIRECTION = " + f"{round(c1 + (((abs(x)-abs(a))+abs(x))/abs(x)), 6)}") def f2(c1, a, x): if abs(a) <= abs(x): - print(f"DIRECTION = {c1 + (abs(a) / abs(x))}") + print(f"DIRECTION = {round(c1 + (abs(a)/abs(x)), 6)}") else: - print(f"DIRECTION = {c1 + (((abs(a) - abs(x)) + abs(a)) / abs(a))}") + print("DIRECTION = " + f"{round(c1 + (((abs(a)-abs(x))+abs(a))/abs(a)), 6)}") if to2 < 0: if from2 > 0: @@ -682,7 +707,7 @@ def print_direction(from1, from2, to1, to2): else: f2(1, from2, to2) - print(f"DISTANCE = {sqrt(to2 ** 2 + from2 ** 2)}") + print(f"DISTANCE = {round(sqrt(to2 ** 2 + from2 ** 2), 6)}") # ------------------------------------------------------------------------- @@ -691,50 +716,42 @@ def print_direction(from1, from2, to1, to2): def startup(): + # Initialize the game variables and map, and print startup messages. global g, c, k, n, z, d, t, t0, t9, d0, e, e0, p, p0, s9 - global s, b9, k7, k9, devices - global q1, q2, s1, s2 + global s, b9, k7, k9, devices, q1, q2, s1, s2 - print( - "\n\n\n\n\n\n\n\n\n\n\n" - " ,------*------,\n" - " ,------------- '--- ------'\n" - " '-------- --' / /\n" - " ,---' '-------/ /--,\n" - " '----------------'\n\n" - " THE USS ENTERPRISE --- NCC-1701\n" - "\n\n\n\n\n" - ) + print("\n\n\n\n\n\n\n\n\n\n\n" + " ,------*------,\n" + " ,------------- '--- ------'\n" + " '-------- --' / /\n" + " ,---' '-------/ /--,\n" + " '----------------'\n\n" + " THE USS ENTERPRISE --- NCC-1701\n" + "\n\n\n\n") # set up global game variables g = [[0] * 8 for _ in range(8)] - c = [[0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], - [0, 1]] + z = [[0] * 8 for _ in range(8)] k = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] n = [0, 0, 0] - z = [[0] * 8 for _ in range(8)] d = [0] * 8 - t = 100 * random.randint(20, 39) - t0 = t + t = t0 = 100 * random.randint(20, 39) t9 = random.randint(25, 34) d0 = 0 - e = 3000 - e0 = e - p = 10 - p0 = p - s9 = 200 + e = e0 = 3000 + p = p0 = 10 s = 0 - b9 = 2 - k9 = 0 + k9, b9, s9 = 0, 2, 200 + + c = [[0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1], + [1, 0], [1, 1], [0, 1]] devices = ['WARP ENGINES', 'SHORT RANGE SENSORS', 'LONG RANGE SENSORS', 'PHASER CONTROL', 'PHOTON TUBES', 'DAMAGE CONTROL', 'SHIELD CONTROL', 'LIBRARY-COMPUTER'] # initialize Enterprise's position - q1 = fnr() - q2 = fnr() - s1 = fnr() - s2 = fnr() + q1, q2 = fnr(), fnr() + s1, s2 = fnr(), fnr() # initialize contents of galaxy for i in range(8): @@ -758,64 +775,59 @@ def startup(): if k9 > t9: t9 = k9 + 1 + if b9 == 0: if g[q1][q2] < 200: g[q1][q2] += 120 k9 += 1 b9 = 1 g[q1][q2] += 10 - q1 = fnr() - q2 = fnr() + q1, q2 = fnr(), fnr() k7 = k9 - print( - "YOUR ORDERS ARE AS FOLLOWS:\n" - f" DESTROY THE {k9} KLINGON WARSHIPS WHICH HAVE INVADED\n" - " THE GALAXY BEFORE THEY CAN ATTACK FEDERATION HEADQUARTERS\n" - f" ON STARDATE {t0+t9}. THIS GIVES YOU {t9} DAYS. THERE {'IS' if b9 == 1 else 'ARE'}\n" - f" {b9} STARBASE{'' if b9 == 1 else 'S'} IN THE GALAXY FOR RESUPPLYING YOUR SHIP.\n" - ) + + print("YOUR ORDERS ARE AS FOLLOWS:\n" + f" DESTROY THE {k9} KLINGON WARSHIPS WHICH HAVE INVADED\n" + " THE GALAXY BEFORE THEY CAN ATTACK FEDERATION HEADQUARTERS\n" + f" ON STARDATE {t0+t9}. THIS GIVES YOU {t9} DAYS. THERE " + f"{'IS' if b9 == 1 else 'ARE'}\n" + f" {b9} STARBASE{'' if b9 == 1 else 'S'} IN THE GALAXY FOR " + "RESUPPLYING YOUR SHIP.\n") def new_quadrant(): - global z4, z5, k3, b3, s3, g5, d4, qs, b4, b5 + # Enter a new quadrant: populate map and print a short range scan. + global k3, b3, s3, g5, d4, b4, b5, z, g, q1, q2, t, t0, k, qs, s1, s2, s9 - z4 = q1 - z5 = q2 - k3 = 0 - b3 = 0 - s3 = 0 + k3 = b3 = s3 = 0 g5 = 0 d4 = 0.5 * random.random() z[q1][q2] = g[q1][q2] if 0 <= q1 < 8 and 0 <= q2 < 8: - g2s = quadrant_name(z4, z5, False) + g2s = quadrant_name(q1, q2, False) if t == t0: - print('\nYOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED') + print("\nYOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED") print(f"IN THE GALACTIC QUADRANT, '{g2s}'.\n") else: - print(f'\nNOW ENTERING {g2s} QUADRANT . . .\n') + print(f"\nNOW ENTERING {g2s} QUADRANT . . .\n") - k3 = int(g[q1][q2] * 0.01) - b3 = int(g[q1][q2] * 0.1) - 10 * k3 + k3 = g[q1][q2] // 100 + b3 = g[q1][q2] // 10 - 10 * k3 s3 = g[q1][q2] - 100 * k3 - 10 * b3 - if k3 != 0: - print('COMBAT AREA CONDITION RED') - if s <= 200: - print(' SHIELDS DANGEROUSLY LOW') - for i in range(3): - k[i][0] = k[i][1] = 0 + if k3 != 0: + print("COMBAT AREA CONDITION RED") + if s <= 200: + print(" SHIELDS DANGEROUSLY LOW") for i in range(3): - k[i][2] = 0 + k[i] = [0, 0, 0] qs = ' ' * 192 - z1 = s1 - z2 = s2 - insert_marker(z1, z2, '<*>') + # build quadrant string + insert_marker(s1, s2, '<*>') if k3 > 0: for i in range(k3): r1, r2 = find_empty_place() @@ -833,31 +845,31 @@ def new_quadrant(): def end_game(won=False, quit=False, enterprise_killed=False): - global k7, t, t0 + # Handle end-of-game situations. + global k7, t, t0, b9 if won: - print("CONGRULATION, CAPTAIN! THE LAST KLINGON BATTLE CRUISER") + print("CONGRATULATIONS, CAPTAIN! THE LAST KLINGON BATTLE CRUISER") print("MENACING THE FEDERATION HAS BEEN DESTROYED.\n") - print(f"YOUR EFFICIENCY RATING IS {1000 * (k7 / (t - t0))**2}") + print("YOUR EFFICIENCY RATING IS " + f"{round(1000 * (k7 / (t - t0))**2, 4)}\n\n") else: if not quit: if enterprise_killed: - print('\nTHE ENTERPRISE HAS BEEN DESTROYED. THEN FEDERATION WILL BE CONQUERED') + print("\nTHE ENTERPRISE HAS BEEN DESTROYED. THE FEDERATION " + "WILL BE CONQUERED.") + print(f"IT IS STARDATE {round(t, 1)}") - print(f'IT IS STARDATE {t}') - - print(f'THERE WERE {k9} KLINGON BATTLE CRUISERS LEFT AT') - print(f'THE END OF YOUR MISSION.\n\n') + print(f"THERE WERE {k9} KLINGON BATTLE CRUISERS LEFT AT") + print(f"THE END OF YOUR MISSION.\n\n") if b9 == 0: exit() - print('THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER') - print('FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,') - astr = input("LET HIM STEP FORWARD AND ENTER 'AYE' ") - if astr == 'AYE' or astr == 'aye': - return - exit() + print("THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER") + print("FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,") + if input("LET HIM STEP FORWARD AND ENTER 'AYE'? ").upper() != 'AYE': + exit() # ------------------------------------------------------------------------- @@ -869,15 +881,14 @@ while True: startup() new_quadrant() - restart = False - - while not restart: + while True: if s + e <= 10 or (e <= 10 and d[6] != 0): - print("\n** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP IN SPACE") - print("YOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND SHIELD CONTROL") - print("IS PRESENTLY INCAPABLE OF CROSS-CIRCUITING TO ENGINE ROOM!!") + print("\n** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP IN " + "SPACE\nYOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND " + "SHIELD CONTROL\nIS PRESENTLY INCAPABLE OF CROSS-CIRCUITING " + "TO ENGINE ROOM!!") - command = input('COMMAND ').upper() + command = input('COMMAND? ').upper() if command == 'NAV': navigation() @@ -896,18 +907,16 @@ while True: elif command == 'COM': computer() elif command == 'XXX': - end_game(quit=True) # only returns on restart - restart = True + end_game(quit=True) + break else: - print( - 'ENTER ONE OF THE FOLLOWING:\n' - ' NAV (TO SET COURSE)\n' - ' SRS (FOR SHORT RANGE SENSOR SCAN)\n' - ' LRS (FOR LONG RANGE SENSOR SCAN)\n' - ' PHA (TO FIRE PHASERS)\n' - ' TOR (TO FIRE PHOTON TORPEDOES)\n' - ' SHE (TO RAISE OR LOWER SHIELDS)\n' - ' DAM (FOR DAMAGE CONTROL REPORTS)\n' - ' COM (TO CALL ON LIBRARY-COMPUTER)\n' - ' XXX (TO RESIGN YOUR COMMAND)\n' - ) + print("ENTER ONE OF THE FOLLOWING:\n" + " NAV (TO SET COURSE)\n" + " SRS (FOR SHORT RANGE SENSOR SCAN)\n" + " LRS (FOR LONG RANGE SENSOR SCAN)\n" + " PHA (TO FIRE PHASERS)\n" + " TOR (TO FIRE PHOTON TORPEDOES)\n" + " SHE (TO RAISE OR LOWER SHIELDS)\n" + " DAM (FOR DAMAGE CONTROL REPORTS)\n" + " COM (TO CALL ON LIBRARY-COMPUTER)\n" + " XXX (TO RESIGN YOUR COMMAND)\n") From d8b7a3265566336ce97a01c9fdbfa6ab6d7e08de Mon Sep 17 00:00:00 2001 From: Jack Boyce Date: Mon, 1 Mar 2021 02:25:46 -0800 Subject: [PATCH 121/749] fix bug in starbase layout (bug in BASIC original) --- 84 Super Star Trek/python/superstartrek.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py index 3182405d..36e883fb 100644 --- a/84 Super Star Trek/python/superstartrek.py +++ b/84 Super Star Trek/python/superstartrek.py @@ -741,7 +741,8 @@ def startup(): e = e0 = 3000 p = p0 = 10 s = 0 - k9, b9, s9 = 0, 2, 200 + k9, b9 = 0, 0 + s9 = 200 c = [[0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], [0, 1]] @@ -777,9 +778,6 @@ def startup(): t9 = k9 + 1 if b9 == 0: - if g[q1][q2] < 200: - g[q1][q2] += 120 - k9 += 1 b9 = 1 g[q1][q2] += 10 q1, q2 = fnr(), fnr() From 9e0b0bbdfeadaeb57aeb72df9cfb3337accb1d9e Mon Sep 17 00:00:00 2001 From: Jack Boyce Date: Mon, 1 Mar 2021 03:06:29 -0800 Subject: [PATCH 122/749] cleanup --- 84 Super Star Trek/python/superstartrek.py | 42 ++++++++++------------ 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py index 36e883fb..dbb64014 100644 --- a/84 Super Star Trek/python/superstartrek.py +++ b/84 Super Star Trek/python/superstartrek.py @@ -30,7 +30,7 @@ def fnd(i): def fnr(): # Generate a random number from 0 to 7 inclusive. - return int(random.random() * 7.98 + 0.01) + return random.randint(0, 7) def quadrant_name(row, col, region_only=False): @@ -245,14 +245,14 @@ def maneuver_energy(n): def short_range_scan(): # Print a short range scan. - global d0, e, e0, p, p0, s + global docked, e, e0, p, p0, s - d0 = 0 + docked = False for i in (s1 - 1, s1, s1 + 1): for j in (s2 - 1, s2, s2 + 1): if 0 <= i <= 7 and 0 <= j <= 7: if compare_marker(i, j, '>!<'): - d0 = 1 + docked = True cs = 'DOCKED' e = e0 p = p0 @@ -393,7 +393,7 @@ def phaser_control(): def photon_torpedoes(): # Take photon torpedo input and process firing of torpedoes. - global p, d, c, e, s1, s2, k3, k9, b3, b9, t, t0, t9, d0, g, z + global p, d, c, e, s1, s2, k3, k9, b3, b9, t, t0, t9, docked, g, z if p <= 0: print("ALL PHOTON TORPEDOES EXPENDED") @@ -454,7 +454,7 @@ def photon_torpedoes(): else: print("STARFLEET COMMAND REVIEWING YOUR RECORD TO CONSIDER") print("COURT MARTIAL!") - d0 = 0 + docked = False insert_marker(x3, y3, ' ') g[q1][q2] = k3 * 100 + b3 * 10 + s3 @@ -464,11 +464,11 @@ def photon_torpedoes(): def klingons_fire(): # Process nearby Klingons firing on Enterprise. - global k3, s, k, d0, d + global k3, s, k, docked, d if k3 <= 0: return - if d0 != 0: + if docked: print("STARBASE SHIELDS PROTECT THE ENTERPRISE") return @@ -520,7 +520,7 @@ def shield_control(): def damage_control(): # Print a damage control report. - global d, d0, d4, t + global d, docked, d4, t if d[5] < 0: print('DAMAGE CONTROL REPORT NOT AVAILABLE') @@ -530,7 +530,7 @@ def damage_control(): print(f"{devices[r1].ljust(26, ' ')}{int(d[r1] * 100) * 0.01:g}") print() - if d0 == 0: + if not docked: return d3 = sum(0.1 for i in range(8) if d[i] < 0) @@ -541,9 +541,9 @@ def damage_control(): if d3 >= 1: d3 = 0.9 print("\nTECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;") - print(f"ESTIMATED TIME TO REPAIR: {0.01 * int(100 * d3)} STARDATES") - astr = input("WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N)? ").upper() - if astr != 'Y': + print("ESTIMATED TIME TO REPAIR: " + f"{round(0.01 * int(100 * d3), 2)} STARDATES") + if input("WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N)? ").upper() != 'Y': return for i in range(8): @@ -554,7 +554,7 @@ def damage_control(): def computer(): # Perform the various functions of the library computer. - global d, g5, z, k9, t0, t9, t, b9, s1, s2, b4, b5 + global d, z, k9, t0, t9, t, b9, s1, s2, b4, b5 if d[7] < 0: print("COMPUTER DISABLED") @@ -573,11 +573,8 @@ def computer(): if com == 0 or com == 5: if com == 5: - is_map = True - g5 = 1 print(" THE GALAXY") else: - is_map = False print("\n COMPUTER RECORD OF GALAXY FOR " f"QUADRANT {q1 + 1} , {q2 + 1}\n") @@ -588,7 +585,7 @@ def computer(): for i in range(8): line = ' ' + str(i + 1) + ' ' - if is_map: + if com == 5: g2s = quadrant_name(i, 0, True) line += (' ' * int(12 - 0.5 * len(g2s))) + g2s g2s = quadrant_name(i, 4, True) @@ -717,7 +714,7 @@ def print_direction(from1, from2, to1, to2): def startup(): # Initialize the game variables and map, and print startup messages. - global g, c, k, n, z, d, t, t0, t9, d0, e, e0, p, p0, s9 + global g, c, k, n, z, d, t, t0, t9, docked, e, e0, p, p0, s9 global s, b9, k7, k9, devices, q1, q2, s1, s2 print("\n\n\n\n\n\n\n\n\n\n\n" @@ -737,11 +734,11 @@ def startup(): d = [0] * 8 t = t0 = 100 * random.randint(20, 39) t9 = random.randint(25, 34) - d0 = 0 + docked = False e = e0 = 3000 p = p0 = 10 s = 0 - k9, b9 = 0, 0 + k9, b9 = 0, 0 # typo in original, was b9 = 2 s9 = 200 c = [[0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1], @@ -795,10 +792,9 @@ def startup(): def new_quadrant(): # Enter a new quadrant: populate map and print a short range scan. - global k3, b3, s3, g5, d4, b4, b5, z, g, q1, q2, t, t0, k, qs, s1, s2, s9 + global k3, b3, s3, d4, b4, b5, z, g, q1, q2, t, t0, k, qs, s1, s2, s9 k3 = b3 = s3 = 0 - g5 = 0 d4 = 0.5 * random.random() z[q1][q2] = g[q1][q2] From 8c397ea8f995128447dc8cce83c90ebdfcc22cd5 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 1 Mar 2021 22:53:22 +1100 Subject: [PATCH 123/749] Add Damage Control --- 84 Super Star Trek/csharp/Game.cs | 38 +++++++++++--- 84 Super Star Trek/csharp/Input.cs | 21 ++++++++ .../csharp/Objects/Enterprise.cs | 25 +++------- 84 Super Star Trek/csharp/Objects/Starbase.cs | 31 ++++++++++++ 84 Super Star Trek/csharp/Output.cs | 35 +++++++++++-- .../csharp/Resources/AcceptCommand.txt | 0 .../csharp/Resources/Congratulations.txt | 4 ++ .../csharp/Resources/Destroyed.txt | 1 + .../csharp/Resources/EndOfMission.txt | 3 ++ .../csharp/Resources/Instructions.txt | 1 + .../csharp/Resources/RepairEstimate.txt | 2 + .../csharp/Resources/RepairPrompt.txt | 1 + .../csharp/Resources/ReplayPrompt.txt | 2 + .../csharp/Resources/Stranded.txt | 3 ++ .../csharp/Resources/Strings.cs | 6 +++ 84 Super Star Trek/csharp/Space/Quadrant.cs | 3 +- .../csharp/Systems/DamageControl.cs | 49 +++++++++++++++++++ .../csharp/Systems/ShortRangeSensors.cs | 4 +- .../csharp/Systems/Subsystem.cs | 7 ++- 19 files changed, 200 insertions(+), 36 deletions(-) delete mode 100644 84 Super Star Trek/csharp/Resources/AcceptCommand.txt create mode 100644 84 Super Star Trek/csharp/Resources/Congratulations.txt create mode 100644 84 Super Star Trek/csharp/Resources/Destroyed.txt create mode 100644 84 Super Star Trek/csharp/Resources/EndOfMission.txt create mode 100644 84 Super Star Trek/csharp/Resources/RepairEstimate.txt create mode 100644 84 Super Star Trek/csharp/Resources/RepairPrompt.txt create mode 100644 84 Super Star Trek/csharp/Resources/Stranded.txt create mode 100644 84 Super Star Trek/csharp/Systems/DamageControl.cs diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index d97b8198..eb9fe03c 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -33,11 +33,7 @@ namespace SuperStarTrek { _output.Write(Strings.Title); - _output.Write("Do you need instructions (Y/N)? "); - var response = Console.ReadLine(); - _output.WriteLine(); - - if (!response.Equals("N", InvariantCultureIgnoreCase)) + if (_input.GetYesNo("Do you need instructions", Input.YesNoMode.FalseOnN)) { _output.Write(Strings.Instructions); @@ -68,7 +64,16 @@ namespace SuperStarTrek { var command = _input.GetCommand(); - gameOver = command == Command.XXX || _enterprise.Execute(command); + gameOver = command == Command.XXX || _enterprise.Execute(command) || CheckIfStranded(); + } + + if (_galaxy.KlingonCount > 0) + { + _output.Write(Strings.EndOfMission, _currentStardate, _galaxy.KlingonCount); + } + else + { + _output.Write(Strings.Congratulations, GetEfficiency()); } } @@ -86,12 +91,29 @@ namespace SuperStarTrek _initialKlingonCount = _galaxy.KlingonCount; _enterprise = new Enterprise(3000, random.GetCoordinate()); - _enterprise.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) - .Add(new ShieldControl(_enterprise, _output, _input)); + _enterprise + .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) + .Add(new ShieldControl(_enterprise, _output, _input)) + .Add(new DamageControl(_enterprise, _output)); return new Quadrant(_galaxy[_currentQuadrant], _enterprise); } public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye"); + + private bool CheckIfStranded() + { + if (_enterprise.TotalEnergy < 10 || + _enterprise.Energy < 10 && _enterprise.Shields.IsDamaged) + { + _output.Write(Strings.Stranded); + return true; + } + + return false; + } + + private double GetEfficiency() => + 1000 * Math.Pow(_initialKlingonCount / (_currentStardate - _initialStardate), 2); } } diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs index 98e5b297..3e2d7972 100644 --- a/84 Super Star Trek/csharp/Input.cs +++ b/84 Super Star Trek/csharp/Input.cs @@ -72,5 +72,26 @@ namespace SuperStarTrek _output.WriteLine(); } } + + public bool GetYesNo(string prompt, YesNoMode mode) + { + _output.Prompt($"{prompt} (Y/N)"); + var response = Console.ReadLine().ToUpperInvariant(); + + return (mode, response) switch + { + (YesNoMode.FalseOnN, "N") => false, + (YesNoMode.FalseOnN, _) => true, + (YesNoMode.TrueOnY, "Y") => true, + (YesNoMode.TrueOnY, _) => false, + _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, "Invalid value") + }; + } + + public enum YesNoMode + { + TrueOnY, + FalseOnN + } } } diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index 4f6055cc..e8447fca 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using SuperStarTrek.Resources; using SuperStarTrek.Space; @@ -13,7 +14,6 @@ namespace SuperStarTrek.Objects private readonly List _systems; private readonly Dictionary _commandExecutors; private Quadrant _quadrant; - private ShieldControl _shieldControl; public Enterprise(int maxEnergy, Coordinates sector) { @@ -27,11 +27,12 @@ namespace SuperStarTrek.Objects public Coordinates Quadrant => _quadrant.Coordinates; public Coordinates Sector { get; } public string Condition => GetCondition(); - public double Shields => _shieldControl.Energy; - public double Energy => TotalEnergy - Shields; + public ShieldControl Shields => (ShieldControl)_commandExecutors[Command.SHE]; + public double Energy => TotalEnergy - Shields.Energy; public double TotalEnergy { get; private set; } + public int DamagedSystemCount => _systems.Count(s => s.IsDamaged); + public IEnumerable Systems => _systems; public int TorpedoCount { get; } - public bool IsDocked { get; private set; } public Enterprise Add(Subsystem system) @@ -39,23 +40,9 @@ namespace SuperStarTrek.Objects _systems.Add(system); _commandExecutors[system.Command] = system; - if (system is ShieldControl shieldControl) { _shieldControl = shieldControl; } - return this; } - public string GetDamageReport() - { - var report = new StringBuilder(); - report.AppendLine().AppendLine().AppendLine("Device State of Repair"); - foreach (var system in _systems) - { - report.Append(system.Name.PadRight(25)).AppendLine(system.Condition.ToString(" 0.00;-0.00")); - } - report.AppendLine(); - return report.ToString(); - } - public void Enter(Quadrant quadrant, string entryTextFormat) { _quadrant = quadrant; @@ -66,7 +53,7 @@ namespace SuperStarTrek.Objects if (quadrant.HasKlingons) { _output.Write(Strings.CombatArea); - if (Shields <= 200) { _output.Write(Strings.LowShields); } + if (Shields.Energy <= 200) { _output.Write(Strings.LowShields); } } IsDocked = quadrant.EnterpriseIsNextToStarbase; diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs index 33110837..e11ca9f5 100644 --- a/84 Super Star Trek/csharp/Objects/Starbase.cs +++ b/84 Super Star Trek/csharp/Objects/Starbase.cs @@ -1,7 +1,38 @@ +using SuperStarTrek.Resources; + namespace SuperStarTrek.Objects { internal class Starbase { + private readonly Input _input; + private readonly Output _output; + private readonly double _repairDelay; + + public Starbase(Random random, Input input) + { + _repairDelay = random.GetDouble() * 0.5; + _input = input; + } + public override string ToString() => ">!<"; + + internal bool TryRepair(Enterprise enterprise, out double repairTime) + { + repairTime = enterprise.DamagedSystemCount * 0.1 + _repairDelay; + if (repairTime >= 1) { repairTime = 0.9; } + + _output.Write(Strings.RepairEstimate, repairTime); + if (_input.GetYesNo(Strings.RepairPrompt, Input.YesNoMode.TrueOnY)) + { + foreach (var system in enterprise.Systems) + { + system.Repair(); + } + return true; + } + + repairTime = 0; + return false; + } } } diff --git a/84 Super Star Trek/csharp/Output.cs b/84 Super Star Trek/csharp/Output.cs index 77e5e919..ed960eea 100644 --- a/84 Super Star Trek/csharp/Output.cs +++ b/84 Super Star Trek/csharp/Output.cs @@ -4,12 +4,37 @@ namespace SuperStarTrek { internal class Output { - public void Write(string text) => Console.Write(text); - public void Write(string format, params object[] args) => Console.Write(format, args); - public void WriteLine(string text = "") => Console.WriteLine(text); + public Output Write(string text) + { + Console.Write(text); + return this; + } - public void NextLine() => Console.WriteLine(); + public Output Write(string format, params object[] args) + { + Console.Write(format, args); + return this; + } + + public Output WriteLine(string text = "") + { + Console.WriteLine(text); + return this; + } + + + public Output NextLine() + { + Console.WriteLine(); + return this; + } + + + public Output Prompt(string text = "") + { + Console.Write($"{text}? "); + return this; + } - public void Prompt(string text = "") => Console.Write($"{text}? "); } } diff --git a/84 Super Star Trek/csharp/Resources/AcceptCommand.txt b/84 Super Star Trek/csharp/Resources/AcceptCommand.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/84 Super Star Trek/csharp/Resources/Congratulations.txt b/84 Super Star Trek/csharp/Resources/Congratulations.txt new file mode 100644 index 00000000..767f8653 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Congratulations.txt @@ -0,0 +1,4 @@ +Congratulations, Captain! The last Klingon battle cruiser +menacing the Federation has been destroyed. + +Your efficiency rating is {0}. diff --git a/84 Super Star Trek/csharp/Resources/Destroyed.txt b/84 Super Star Trek/csharp/Resources/Destroyed.txt new file mode 100644 index 00000000..881d7b49 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Destroyed.txt @@ -0,0 +1 @@ +The Enterprise has been destroyed. The Federation will be conquered. diff --git a/84 Super Star Trek/csharp/Resources/EndOfMission.txt b/84 Super Star Trek/csharp/Resources/EndOfMission.txt new file mode 100644 index 00000000..f6995e31 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/EndOfMission.txt @@ -0,0 +1,3 @@ +Is is stardate {0}. +There were {1} Klingon battle cruisers left at +the end of your mission. diff --git a/84 Super Star Trek/csharp/Resources/Instructions.txt b/84 Super Star Trek/csharp/Resources/Instructions.txt index fd74857e..34b4169c 100644 --- a/84 Super Star Trek/csharp/Resources/Instructions.txt +++ b/84 Super Star Trek/csharp/Resources/Instructions.txt @@ -1,3 +1,4 @@ + INSTRUCTIONS FOR 'SUPER STAR TREK' 1. When you see "Command ?" printed, enter one of the legal diff --git a/84 Super Star Trek/csharp/Resources/RepairEstimate.txt b/84 Super Star Trek/csharp/Resources/RepairEstimate.txt new file mode 100644 index 00000000..12e167a5 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/RepairEstimate.txt @@ -0,0 +1,2 @@ +Technicians standing by to effect repairs to your ship; +Estimated time to repair: {0} stardates. diff --git a/84 Super Star Trek/csharp/Resources/RepairPrompt.txt b/84 Super Star Trek/csharp/Resources/RepairPrompt.txt new file mode 100644 index 00000000..feffdb27 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/RepairPrompt.txt @@ -0,0 +1 @@ +Will you authorize the repair order (Y/N) \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt b/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt index 52aca0d1..3ca3a102 100644 --- a/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt +++ b/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt @@ -1,3 +1,5 @@ + + The Federation is in need of a new starship commander for a similar mission -- if there is a volunteer let him step forward and enter 'Aye' \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/Stranded.txt b/84 Super Star Trek/csharp/Resources/Stranded.txt new file mode 100644 index 00000000..07c37952 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Stranded.txt @@ -0,0 +1,3 @@ +** FATAL ERROR ** You've just stranded your ship in space +You have insufficient maneuvering energy, and shield control +is presently incapable of cross-circuiting to engine room!! diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index 930f1663..4592db31 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -7,14 +7,20 @@ namespace SuperStarTrek.Resources internal static class Strings { public static string CombatArea => GetResource(); + public static string Congratulations => GetResource(); + public static string Destroyed => GetResource(); + public static string EndOfMission => GetResource(); public static string Enterprise => GetResource(); public static string Instructions => GetResource(); public static string LowShields => GetResource(); public static string Orders => GetResource(); + public static string RepairEstimate => GetResource(); + public static string RepairPrompt => GetResource(); public static string ReplayPrompt => GetResource(); public static string ShieldsDropped => GetResource(); public static string ShortRangeSensorsOut => GetResource(); public static string StartText => GetResource(); + public static string Stranded => GetResource(); public static string Title => GetResource(); private static string GetResource([CallerMemberName] string name = "") diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index 2aa45b6d..f08fa18b 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -23,7 +23,7 @@ namespace SuperStarTrek.Space PositionObject(() => new Klingon(), _info.KlingonCount); if (_info.HasStarbase) { - _starbaseSector = PositionObject(() => new Starbase()); + _starbaseSector = PositionObject(() => new Starbase(_random, new Input(new Output()))); } PositionObject(() => new Star(), _info.StarCount); } @@ -31,6 +31,7 @@ namespace SuperStarTrek.Space public Coordinates Coordinates => _info.Coordinates; public bool HasKlingons => _info.KlingonCount > 0; public bool HasStarbase => _info.HasStarbase; + public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null; public bool EnterpriseIsNextToStarbase => _info.HasStarbase && Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 && diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84 Super Star Trek/csharp/Systems/DamageControl.cs new file mode 100644 index 00000000..5cfbda7e --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/DamageControl.cs @@ -0,0 +1,49 @@ +using SuperStarTrek.Objects; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems +{ + internal class DamageControl : Subsystem + { + private readonly Enterprise _enterprise; + private readonly Output _output; + + public DamageControl(Enterprise enterprise, Output output) + : base("Damage Control", Command.DAM) + { + _enterprise = enterprise; + _output = output; + } + + public override void ExecuteCommand(Quadrant quadrant) + { + if (IsDamaged) + { + _output.WriteLine("Damage Control report not available"); + } + else + { + WriteDamageReport(); + } + + if (_enterprise.DamagedSystemCount > 0 && _enterprise.IsDocked) + { + if (quadrant.Starbase.TryRepair(_enterprise, out var repairTime)) + { + WriteDamageReport(); + } + } + } + + public void WriteDamageReport() + { + _output.NextLine().NextLine().WriteLine("Device State of Repair"); + foreach (var system in _enterprise.Systems) + { + _output.Write(system.Name.PadRight(25)) + .WriteLine(((int)(system.Condition * 100) * 0.01).ToString(" 0.##;-0.##")); + } + _output.NextLine(); + } + } +} diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs index d22dda70..6632705c 100644 --- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs +++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs @@ -51,8 +51,8 @@ namespace SuperStarTrek.Systems yield return $"Quadrant {_enterprise.Quadrant}"; yield return $"Sector {_enterprise.Sector}"; yield return $"Photon torpedoes {_enterprise.TorpedoCount}"; - yield return $"Total energy {Math.Ceiling(_enterprise.Energy)}"; - yield return $"Shields {(int)_enterprise.Shields}"; + yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}"; + yield return $"Shields {(int)_enterprise.Shields.Energy}"; yield return $"Klingons remaining {_galaxy.KlingonCount}"; } } diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs index ae2ef7d6..9cb461ce 100644 --- a/84 Super Star Trek/csharp/Systems/Subsystem.cs +++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs @@ -12,9 +12,14 @@ namespace SuperStarTrek.Systems } public string Name { get; } - public double Condition { get; } + public double Condition { get; private set; } + public bool IsDamaged => Condition < 0; public Command Command { get; } public abstract void ExecuteCommand(Quadrant quadrant); + public void Repair() + { + if (Condition < 0) { Condition = 0; } + } } } From 43bf3788c4a74511538b31aa8a6b9560e25f7851 Mon Sep 17 00:00:00 2001 From: Brian Wignall Date: Mon, 1 Mar 2021 07:19:02 -0500 Subject: [PATCH 124/749] Array access changes --- 38 Fur Trader/csharp/GameState.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/38 Fur Trader/csharp/GameState.cs b/38 Fur Trader/csharp/GameState.cs index 4e174040..41c9d1ca 100644 --- a/38 Fur Trader/csharp/GameState.cs +++ b/38 Fur Trader/csharp/GameState.cs @@ -17,9 +17,9 @@ namespace FurTrader internal int[] Pelts { get; private set; } internal int MinkPelts { get { return this.Pelts[0]; } set { this.Pelts[0] = value; } } - internal int BeaverPelts { get { return this.Pelts[0]; } set { this.Pelts[0] = value; } } - internal int ErminePelts { get { return this.Pelts[0]; } set { this.Pelts[0] = value; } } - internal int FoxPelts { get { return this.Pelts[0]; } set { this.Pelts[0] = value; } } + internal int BeaverPelts { get { return this.Pelts[1]; } set { this.Pelts[1] = value; } } + internal int ErminePelts { get { return this.Pelts[2]; } set { this.Pelts[2] = value; } } + internal int FoxPelts { get { return this.Pelts[3]; } set { this.Pelts[3] = value; } } internal int SelectedFort { get; set; } From 880fac2e3f13eed89471514ad05145a909981c9b Mon Sep 17 00:00:00 2001 From: Jamie McCarthy Date: Mon, 1 Mar 2021 08:45:52 -0600 Subject: [PATCH 125/749] Start hurkle.rb with the original BASIC code --- 51 Hurkle/ruby/hurkle.rb | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 51 Hurkle/ruby/hurkle.rb diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb new file mode 100644 index 00000000..c758091c --- /dev/null +++ b/51 Hurkle/ruby/hurkle.rb @@ -0,0 +1,51 @@ +10 PRINT TAB(33);"HURKLE" +20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" +30 PRINT:PRINT:PRINT +110 N=5 +120 G=10 +210 PRINT +220 PRINT "A HURKLE IS HIDING ON A";G;"BY";G;"GRID. HOMEBASE" +230 PRINT "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER," +235 PRINT "AND ANY POINT ON THE GRID IS DESIGNATED BY A" +240 PRINT "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST" +245 PRINT "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER" +246 PRINT "IS THE VERTICAL POSITION. YOU MUST TRY TO" +250 PRINT "GUESS THE HURKLE'S GRIDPOINT. YOU GET";N;"TRIES." +260 PRINT "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE" +270 PRINT "DIRECTION TO GO TO LOOK FOR THE HURKLE." +280 PRINT +285 A=INT(G*RND(1)) +286 B=INT(G*RND(1)) +310 FOR K=1 TO N +320 PRINT "GUESS #";K; +330 INPUT X,Y +340 IF ABS(X-A)+ABS(Y-B)=0 THEN 500 +350 REM PRINT INFO +360 GOSUB 610 +370 PRINT +380 NEXT K +410 PRINT +420 PRINT "SORRY, THAT'S";N;"GUESSES." +430 PRINT "THE HURKLE IS AT ";A;",";B +440 PRINT +450 PRINT "LET'S PLAY AGAIN, HURKLE IS HIDING." +460 PRINT +470 GOTO 285 +500 REM +510 PRINT +520 PRINT "YOU FOUND HIM IN";K;"GUESSES!" +540 GOTO 440 +610 PRINT "GO "; +620 IF Y=B THEN 670 +630 IF Y Date: Mon, 1 Mar 2021 07:05:13 -0800 Subject: [PATCH 126/749] Port LITQUIZ to Python pulled questions and answers out into a question class to reduce repetition in the logic. --- 57 Literature Quiz/python/litquiz.py | 117 +++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 57 Literature Quiz/python/litquiz.py diff --git a/57 Literature Quiz/python/litquiz.py b/57 Literature Quiz/python/litquiz.py new file mode 100644 index 00000000..b5b9d1c5 --- /dev/null +++ b/57 Literature Quiz/python/litquiz.py @@ -0,0 +1,117 @@ +""" +LITQUIZ + +A children's literature quiz + +Ported by Dave LeCompte +""" + +PAGE_WIDTH = 64 + + +class Question: + def __init__( + self, question, answer_list, correct_number, incorrect_message, correct_message + ): + self.question = question + self.answer_list = answer_list + self.correct_number = correct_number + self.incorrect_message = incorrect_message + self.correct_message = correct_message + + def ask(self): + print(self.question) + + options = [f"{i+1}){self.answer_list[i]}" for i in range(len(self.answer_list))] + print(", ".join(options)) + + response = int(input()) + + if response == self.correct_number: + print(self.correct_message) + return True + else: + print(self.incorrect_message) + return False + + +questions = [ + Question( + "IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT?", + ["TIGGER", "CICERO", "FIGARO", "GUIPETTO"], + 3, + "SORRY...FIGARO WAS HIS NAME.", + "VERY GOOD! HERE'S ANOTHER.", + ), + Question( + "FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?", + ["MR. NIXON'S", "ELMER FUDD'S", "CLEM JUDD'S", "STROMBOLI'S"], + 2, + "TOO BAD...IT WAS ELMER FUDD'S GARDEN.", + "PRETTY GOOD!", + ), + Question( + "IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED?", + ["CICERO", "TRIXIA", "KING", "TOTO"], + 4, + "BACK TO THE BOOKS,...TOTO WAS HIS NAME.", + "YEA! YOU'RE A REAL LITERATURE GIANT.", + ), + Question( + "WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE?", + ["SLEEPING BEAUTY", "CINDERELLA", "SNOW WHITE", "WENDY"], + 3, + "OH, COME ON NOW...IT WAS SNOW WHITE.", + "GOOD MEMORY!", + ), +] + + +def print_centered(msg): + spaces = " " * ((64 - len(msg)) // 2) + + print(spaces + msg) + + +def print_instructions(): + print("TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE.") + print() + print("THIS IS A MULTIPLE-CHOICE QUIZ.") + print("TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK.") + print() + print("GOOD LUCK!") + print() + print() + + +def main(): + print_centered("LITERATURE QUIZ") + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + print_instructions() + + score = 0 + + for q in questions: + if q.ask(): + score += 1 + print() + print() + + if score == len(questions): + print("WOW! THAT'S SUPER! YOU REALLY KNOW YOUR NURSERY") + print("YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE") + print("LITERATURE (HA, HA, HA)") + elif score < len(questions) / 2: + print("UGH. THAT WAS DEFINITELY NOT TOO SWIFT. BACK TO") + print("NURSERY SCHOOL FOR YOU, MY FRIEND.") + else: + print("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME") + print("READING THE NURSERY GREATS.") + + +if __name__ == "__main__": + main() From 3a1f61737c3e449c06ecd3be83877246a678c81f Mon Sep 17 00:00:00 2001 From: nanochess Date: Mon, 1 Mar 2021 09:54:41 -0600 Subject: [PATCH 127/749] Ported BLACKJACK to Javascript --- 10 Blackjack/javascript/blackjack.html | 9 + 10 Blackjack/javascript/blackjack.js | 549 +++++++++++++++++++++++++ 2 files changed, 558 insertions(+) create mode 100644 10 Blackjack/javascript/blackjack.html create mode 100644 10 Blackjack/javascript/blackjack.js diff --git a/10 Blackjack/javascript/blackjack.html b/10 Blackjack/javascript/blackjack.html new file mode 100644 index 00000000..eb18ca9e --- /dev/null +++ b/10 Blackjack/javascript/blackjack.html @@ -0,0 +1,9 @@ + + +BLACKJACK + + +


+
+
+
diff --git a/10 Blackjack/javascript/blackjack.js b/10 Blackjack/javascript/blackjack.js
new file mode 100644
index 00000000..16f5a343
--- /dev/null
+++ b/10 Blackjack/javascript/blackjack.js	
@@ -0,0 +1,549 @@
+// BLACKJACK
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var da = [];
+
+var pa = [];
+var qa = [];
+var ca = [];
+var ta = [];
+var sa = [];
+var ba = [];
+var za = [];
+var ra = [];
+
+var ds = "N A  2  3  4  5  6  7N 8  9 10  J  Q  K";
+var is = "H,S,D,/,"
+
+var q;
+var aa;
+var ab;
+var ac;
+var h;
+var h1;
+
+function af(q) {
+    return q >= 22 ? q - 11 : q;
+}
+
+function reshuffle()
+{
+    print("RESHUFFLING\n");
+    for (; d >= 1; d--)
+        ca[--c] = da[d];
+    for (c1 = 52; c1 >= c; c1--) {
+        c2 = Math.floor(Math.random() * (c1 - c + 1)) + c;
+        c3 = ca[c2];
+        ca[c2] = ca[c1];
+        ca[c1] = c3;
+    }
+}
+
+// Subroutine to get a card.
+function get_card()
+{
+    if (c >= 51)
+        reshuffle();
+    return ca[c++];
+}
+
+// Card printing subroutine
+function card_print(x)
+{
+    print(ds.substr(3 * x - 3, 3) + "  ");
+}
+
+// Alternate card printing subroutine
+function alt_card_print(x)
+{
+    print(" " + ds.substr(3 * x - 2, 2) + "   ");
+}
+
+// Subroutine to add card 'which' to total 'q'
+function add_card(which)
+{
+    x1 = which;
+    if (x1 > 10)
+        x1 = 10;
+    q1 = q + x1;
+    if (q < 11) {
+        if (which <= 1) {
+            q += 11;
+            return;
+        }
+        if (q1 >= 11)
+            q = q1 + 11;
+        else
+            q = q1;
+        return;
+    }
+    if (q <= 21 && q1 > 21)
+        q = q1 + 1;
+    else
+        q = q1;
+    if (q >= 33)
+        q = -1;
+}
+
+// Subroutine to evaluate hand 'which'. Total is put into
+// qa[which]. Totals have the following meaning:
+//  2-10...hard 2-10
+// 11-21...soft 11-21
+// 22-32...hard 11-21
+//  33+....busted
+function evaluate_hand(which)
+{
+    q = 0;
+    for (q2 = 1; q2 <= ra[which]; q2++) {
+        add_card(pa[i][q2]);
+    }
+    qa[which] = q;
+}
+
+// Subroutine to add a card to row i
+function add_card_to_row(i, x) {
+    ra[i]++;
+    pa[i][ra[i]] = x;
+    q = qa[i];
+    add_card(x);
+    qa[i] = q;
+    if (q < 0) {
+        print("...BUSTED\n");
+        discard_row(i);
+    }
+}
+
+// Subroutine to discard row i
+function discard_row(i) {
+    while (ra[i]) {
+        d++;
+        da[d] = pa[i][ra[i]];
+        ra[i]--;
+    }
+}
+
+// Prints total of hand i
+function print_total(i) {
+    print("\n");
+    aa = qa[i];
+    total_aa();
+    print("TOTAL IS " + aa + "\n");
+}
+
+function total_aa()
+{
+    if (aa >= 22)
+        aa -= 11;
+}
+
+function total_ab()
+{
+    if (ab >= 22)
+        ab -= 11;
+}
+
+function total_ac()
+{
+    if (ac >= 22)
+        ac -= 11;
+}
+
+function process_input(str)
+{
+    str = str.substr(0, 1);
+    for (h = 1; h <= h1; h += 2) {
+        if (str == is.substr(h - 1, 1))
+            break;
+    }
+    if (h <= h1) {
+        h = (h + 1) / 2;
+        return 0;
+    }
+    print("TYPE " + is.substr(0, h1 - 1) + " OR " + is.substr(h1 - 1, 2) + " PLEASE");
+    return 1;
+}
+
+// Main program
+async function main()
+{
+    print(tab(31) + "BLACK JACK\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // --pa[i][j] IS THE JTH CARD IN HAND I, qa[i] IS TOTAL OF HAND I
+    // --C IS THE DECK BEING DEALT FROM, D IS THE DISCARD PILE,
+    // --ta[i] IS THE TOTAL FOR PLAYER I, sa[i] IS THE TOTAL THIS HAND FOR
+    // --PLAYER I, ba[i] IS TH BET FOR HAND I
+    // --ra[i] IS THE LENGTH OF pa[I,*]
+    
+    // --Program starts here
+    // --Initialize
+    for (i = 1; i <= 15; i++)
+        pa[i] = [];
+    for (i = 1; i <= 13; i++)
+        for (j = 4 * i - 3; j <= 4 * i; j++)
+            da[j] = i;
+    d = 52;
+    c = 53;
+    print("DO YOU WANT INSTRUCTIONS");
+    str = await input();
+    if (str.toUpperCase().substr(0, 1) != "N") {
+        print("THIS IS THE GAME OF 21. AS MANY AS 7 PLAYERS MAY PLAY THE\n");
+        print("GAME. ON EACH DEAL, BETS WILL BE ASKED FOR, AND THE\n");
+        print("PLAYERS' BETS SHOULD BE TYPED IN. THE CARDS WILL THEN BE\n");
+        print("DEALT, AND EACH PLAYER IN TURN PLAYS HIS HAND. THE\n");
+        print("FIRST RESPONSE SHOULD BE EITHER 'D', INDICATING THAT THE\n");
+        print("PLAYER IS DOUBLING DOWN, 'S', INDICATING THAT HE IS\n");
+        print("STANDING, 'H', INDICATING HE WANTS ANOTHER CARD, OR '/',\n");
+        print("INDICATING THAT HE WANTS TO SPLIT HIS CARDS. AFTER THE\n");
+        print("INITIAL RESPONSE, ALL FURTHER RESPONSES SHOULD BE 'S' OR\n");
+        print("'H', UNLESS THE CARDS WERE SPLIT, IN WHICH CASE DOUBLING\n");
+        print("DOWN IS AGAIN PERMITTED. IN ORDER TO COLLECT FOR\n");
+        print("BLACKJACK, THE INITIAL RESPONSE SHOULD BE 'S'.\n");
+    }
+    while (1) {
+        print("NUMBER OF PLAYERS");
+        n = parseInt(await input());
+        print("\n");
+        if (n < 1 || n > 7)
+            continue;
+        else
+            break;
+    }
+    for (i = 1; i <= 8; i++)
+        ta[i] = 0;
+    d1 = n + 1;
+    while (1) {
+        if (2 * d1 + c >= 52) {
+            reshuffle();
+        }
+        if (c == 2)
+            c--;
+        for (i = 1; i <= n; i++)
+            za[i] = 0;
+        for (i = 1; i <= 15; i++)
+            ba[i] = 0;
+        for (i = 1; i <= 15; i++)
+            qa[i] = 0;
+        for (i = 1; i <= 7; i++)
+            sa[i] = 0;
+        for (i = 1; i <= 15; i++)
+            ra[i] = 0;
+        print("BETS:\n");
+        for (i = 1; i <= n; i++) {
+            do {
+                print("#" + i + " ");
+                za[i] = parseFloat(await input());
+            } while (za[i] <= 0 || za[i] > 500) ;
+        }
+        for (i = 1; i <= n; i++)
+            ba[i] = za[i];
+        print("PLAYER");
+        for (i = 1; i <= n; i++) {
+            print(" " + i + "    ");
+        }
+        print("DEALER\n");
+        for (j = 1; j <= 2; j++) {
+            print(tab(5));
+            for (i = 1; i <= d1; i++) {
+                pa[i][j] = get_card();
+                if (j == 1 || i <= n)
+                    alt_card_print(pa[i][j]);
+            }
+            print("\n");
+        }
+        for (i = 1; i <= d1; i++)
+            ra[i] = 2;
+        // --Test for insurance
+        if (pa[d1][1] <= 1) {
+            print("ANY INSURANCE");
+            str = await input();
+            if (str.substr(0, 1) == "Y") {
+                print("INSURANCE BETS\n");
+                for (i = 1; i <= n; i++) {
+                    do {
+                        print("#" + i + " ");
+                        za[i] = parseFloat(await input());
+                    } while (za[i] < 0 || za[i] > ba[i] / 2) ;
+                }
+                for (i = 1; i <= n; i++)
+                    sa[i] = za[i] * ((pa[d1][2] >= 10 ? 3 : 0) - 1);
+            }
+        }
+        // --Test for dealer blackjack
+        l1 = 1;
+        l2 = 1;
+        if (pa[d1][1] == 1 && pa[d1][2] > 9) {
+            l1 = 0;
+            l2 = 0;
+        }
+        if (pa[d1][2] == 1 && pa[d1][1] > 9) {
+            l1 = 0;
+            l2 = 0;
+        }
+        if (l1 == 0 && l2 == 0) {
+            print("\n");
+            print("DEALER HAS A" + ds.substr(3 * pa[d1][2] - 3, 3) + " IN THE HOLE FOR BLACKJACK\n");
+            for (i = 1; i <= d1; i++)
+                evaluate_hand(i);
+        } else {
+            // --No dealer blackjack
+            if (pa[d1][1] <= 1 || pa[d1][1] >= 10) {
+                print("\n");
+                print("NO DEALER BLACKJACK.\n");
+            }
+            // --Now play the hands
+            for (i = 1; i <= n; i++) {
+                print("PLAYER " + i + " ");
+                h1 = 7;
+                do {
+                    str = await input();
+                } while (process_input(str)) ;
+                if (h == 1) {   // Player wants to be hit
+                    evaluate_hand(i);
+                    h1 = 3;
+                    x = get_card();
+                    print("RECEIVED A");
+                    card_print(x);
+                    add_card_to_row(i, x);
+                    if (q > 0)
+                        print_total(i);
+                } else if (h == 2) {    // Player wants to stand
+                    evaluate_hand(i);
+                    if (qa[i] == 21) {
+                        print("BLACKJACK\n");
+                        sa[i] = sa[i] + 1.5 * ba[i];
+                        ba[i] = 0;
+                        discard_row(i);
+                    } else {
+                        print_total(i);
+                    }
+                } else if (h == 3) {    // Player wants to double down
+                    evaluate_hand(i);
+                    h1 = 3;
+                    h = 1;
+                    while (1) {
+                        if (h == 1) {   // Hit
+                            x = get_card();
+                            print("RECEIVED A");
+                            card_print(x);
+                            add_card_to_row(i, x);
+                            if (q < 0)
+                                break;
+                            print("HIT");
+                        } else if (h == 2) {    // Stand
+                            print_total(i);
+                            break;
+                        }
+                        do {
+                            str = await input();
+                        } while (process_input(str)) ;
+                        h1 = 3;
+                    }
+                } else if (h == 4) {    // Player wants to split
+                    l1 = pa[i][1];
+                    if (l1 > 10)
+                        l1 = 10;
+                    l2 = pa[i][2];
+                    if (l2 > 10)
+                        l2 = 10;
+                    if (l1 != l2) {
+                        print("SPLITTING NOT ALLOWED.\n");
+                        i--;
+                        continue;
+                    }
+                    // --Play out split
+                    i1 = i + d1;
+                    ra[i1] = 2;
+                    pa[i1][1] = pa[i1][2];
+                    ba[i + d1] = ba[i];
+                    x = get_card();
+                    print("FIRST HAND RECEIVES A");
+                    card_print(x);
+                    pa[i][2] = x;
+                    evaluate_hand(i);
+                    print("\n");
+                    x = get_card();
+                    print("SECOND HAND RECEIVES A");
+                    i = i1;
+                    card_print(x);
+                    pa[i][2] = x;
+                    evaluate_hand(i);
+                    print("\n");
+                    i = i1 - d1;
+                    if (pa[i][1] != 1) {
+                        // --Now play the two hands
+                        do {
+                            
+                            print("HAND " + (i > d1 ? 2 : 1) + " ");
+                            h1 = 5;
+                            while (1) {
+                                do {
+                                    str = await input();
+                                } while (process_input(str)) ;
+                                h1 = 3;
+                                if (h == 1) {   // Hit
+                                    x = get_card();
+                                    print("RECEIVED A");
+                                    card_print(x);
+                                    add_card_to_row(i, x);
+                                    if (q < 0)
+                                        break;
+                                    print("HIT");
+                                } else if (h == 2) {    // Stand
+                                    print_total(i);
+                                    break;
+                                } else {    // Double
+                                    x = get_card();
+                                    ba[i] *= 2;
+                                    print("RECEIVED A");
+                                    card_print(x);
+                                    add_card_to_row(i, x);
+                                    if (q > 0)
+                                        print_total(i);
+                                    break;
+                                }
+                            }
+                            i += d1;
+                        } while (i == i1) ;
+                        i = i1 - d1;
+                    }
+                }
+            }
+            // --Test for playing dealer's hand
+            evaluate_hand(i);
+            for (i = 1; i <= n; i++) {
+                if (ra[i] > 0 || ra[i + d1] > 0)
+                    break;
+            }
+            if (i > n) {
+                print("DEALER HAD A");
+                x = pa[d1][2];
+                card_print(x);
+                print(" CONCEALED.\n");
+            } else {
+                print("DEALER HAS A" + ds.substr(3 * pa[d1][2] - 3, 3) + " CONCEALED ");
+                i = d1;
+                aa = qa[i];
+                total_aa();
+                print("FOR A TOTAL OF " + aa + "\n");
+                if (aa <= 16) {
+                    print("DRAWS");
+                    do {
+                        
+                        x = get_card();
+                        alt_card_print(x);
+                        add_card_to_row(i, x);
+                        aa = q;
+                        total_aa();
+                    } while (q > 0 && aa < 17) ;
+                    if (q < 0) {
+                        qa[i] = q + 0.5;
+                    } else {
+                        qa[i] = q;
+                    }
+                    if (q >= 0) {
+                        aa = q;
+                        total_aa();
+                        print("---TOTAL IS " + aa + "\n");
+                    }
+                }
+                print("\n");
+            }
+        }
+        // --TALLY THE RESULT
+        str = "LOSES PUSHES WINS "
+        print("\n");
+        for (i = 1; i <= n; i++) {
+            aa = qa[i]
+            total_aa();
+            ab = qa[i + d1];
+            total_ab();
+            ac = qa[d1];
+            total_ac();
+            signaaac = aa - ac;
+            if (signaaac) {
+                if (signaaac < 0)
+                    signaaac = -1;
+                else
+                    signaaac = 1;
+            }
+            signabac = ab - ac;
+            if (signabac) {
+                if (signabac < 0)
+                    signabac = -1;
+                else
+                    signabac = 1;
+            }
+            sa[i] = sa[i] + ba[i] * signaaac + ba[i + d1] * signabac;
+            ba[i + d1] = 0;
+            print("PLAYER " + i + " ");
+            signsai = sa[i];
+            if (signsai) {
+                if (signsai < 0)
+                    signsai = -1;
+                else
+                    signsai = 1;
+            }
+            print(str.substr(signsai * 6 + 6, 6) + " ");
+            if (sa[i] == 0)
+                print("      ");
+            else
+                print(" " + Math.abs(sa[i]) + " ");
+            ta[i] = ta[i] + sa[i];
+            print("TOTAL= " + ta[i] + "\n");
+            discard_row(i);
+            ta[d1] = ta[d1] - sa[i];
+            i += d1;
+            discard_row(i);
+            i -= d1;
+        }
+        print("DEALER'S TOTAL= " + ta[d1] + "\n");
+        print("\n");
+        discard_row(i);
+    }
+}
+
+main();

From d8d3c0773c1c8fde1e3d07b4b2a8843095277929 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Mon, 1 Mar 2021 08:01:15 -0800
Subject: [PATCH 128/749] Port PIZZA to Python

Refactored logic into functions. If you're the kind of person that likes to say "pizza pie", then you might also like saying "pizza.py".
---
 69 Pizza/python/pizza.py | 187 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 187 insertions(+)
 create mode 100644 69 Pizza/python/pizza.py

diff --git a/69 Pizza/python/pizza.py b/69 Pizza/python/pizza.py
new file mode 100644
index 00000000..e3804e75
--- /dev/null
+++ b/69 Pizza/python/pizza.py	
@@ -0,0 +1,187 @@
+"""
+PIZZA
+
+A pizza delivery simulation
+
+Ported by Dave LeCompte
+"""
+
+import random
+
+PAGE_WIDTH = 64
+
+customer_names = [chr(65 + x) for x in range(16)]
+street_names = [str(n) for n in range(1, 5)]
+
+
+def print_centered(msg):
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
+
+
+def print_header(title):
+    print_centered(title)
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+
+def print_ticks():
+    for t in range(4):
+        print("-")
+
+
+def print_ruler():
+    print(" -----1-----2-----3-----4-----")
+
+
+def print_street(i):
+    street_number = 3 - i
+
+    street_name = street_names[street_number]
+    line = street_name
+
+    space = " " * 5
+    for customer_index in range(4):
+        line += space
+        customer_name = customer_names[4 * street_number + customer_index]
+        line += customer_name
+    line += space
+    line += street_name
+    print(line)
+
+
+def print_map():
+    print("MAP OF THE CITY OF HYATTSVILLE")
+    print()
+    print_ruler()
+    for i in range(4):
+        print_ticks()
+        print_street(i)
+    print_ticks()
+    print_ruler()
+    print()
+
+
+def print_instructions():
+    print("PIZZA DELIVERY GAME")
+    print()
+    print("WHAT IS YOUR FIRST NAME?")
+    player_name = input()
+    print()
+    print(f"HI, {player_name}.  IN THIS GAME YOU ARE TO TAKE ORDERS")
+    print("FOR PIZZAS.  THEN YOU ARE TO TELL A DELIVERY BOY")
+    print("WHERE TO DELIVER THE ORDERED PIZZAS.")
+    print()
+    print()
+
+    print_map()
+
+    print("THE OUTPUT IS A MAP OF THE HOMES WHERE")
+    print("YOU ARE TO SEND PIZZAS.")
+    print()
+    print("YOUR JOB IS TO GIVE A TRUCK DRIVER")
+    print("THE LOCATION OR COORDINATES OF THE")
+    print("HOME ORDERING THE PIZZA.")
+    print()
+
+    return player_name
+
+
+def yes_no_prompt(msg):
+    while True:
+        print(msg)
+        response = input().upper()
+
+        if response == "YES":
+            return True
+        elif response == "NO":
+            return False
+        print("'YES' OR 'NO' PLEASE, NOW THEN,")
+
+
+def print_more_directions(player_name):
+    print()
+    print("SOMEBODY WILL ASK FOR A PIZZA TO BE")
+    print("DELIVERED.  THEN A DELIVERY BOY WILL")
+    print("ASK YOU FOR THE LOCATION.")
+    print("     EXAMPLE:")
+    print("THIS IS J.  PLEASE SEND A PIZZA.")
+    print(f"DRIVER TO {player_name}.  WHERE DOES J LIVE?")
+    print("YOUR ANSWER WOULD BE 2,3")
+    print()
+
+
+def calculate_customer_index(x, y):
+    return 4 * (y - 1) + x - 1
+
+
+def deliver_to(customer_index, customer_name, player_name):
+    print(f"  DRIVER TO {player_name}:  WHERE DOES {customer_name} LIVE?")
+
+    coords = input()
+    xc, yc = [int(c) for c in coords.split(",")]
+    delivery_index = calculate_customer_index(xc, yc)
+    if delivery_index == customer_index:
+        print(f"HELLO {player_name}.  THIS IS {customer_name}, THANKS FOR THE PIZZA.")
+        return True
+    else:
+        delivery_name = customer_names[delivery_index]
+        print(f"THIS IS {delivery_name}.  I DID NOT ORDER A PIZZA.")
+        print(f"I LIVE AT {xc},{yc}")
+        return False
+
+
+def play_game(num_turns, player_name):
+    for turn in range(num_turns):
+        x = random.randint(1, 4)
+        y = random.randint(1, 4)
+        customer_index = calculate_customer_index(x, y)
+        customer_name = customer_names[customer_index]
+
+        print()
+        print(
+            f"HELLO {player_name}'S PIZZA.  THIS IS {customer_name}.  PLEASE SEND A PIZZA."
+        )
+        while True:
+            success = deliver_to(customer_index, customer_name, player_name)
+            if success:
+                break
+
+
+def main():
+    print_header("PIZZA")
+
+    player_name = print_instructions()
+
+    more_directions = yes_no_prompt("DO YOU NEED MORE DIRECTIONS?")
+
+    if more_directions:
+        print_more_directions(player_name)
+
+        understand = yes_no_prompt("UNDERSTAND?")
+
+        if not understand:
+            print("THIS JOB IS DEFINITELY TOO DIFFICULT FOR YOU. THANKS ANYWAY")
+            return
+
+    print("GOOD.  YOU ARE NOW READY TO START TAKING ORDERS.")
+    print()
+    print("GOOD LUCK!!")
+    print()
+
+    while True:
+        num_turns = 5
+        play_game(num_turns, player_name)
+
+        print()
+        more = yes_no_prompt("DO YOU WANT TO DELIVER MORE PIZZAS?")
+        if not more:
+            print(f"O.K. {player_name}, SEE YOU LATER!")
+            print()
+            return
+
+
+if __name__ == "__main__":
+    main()

From b4254488bd4ccd1bac6951b4c1b85a0d44689c08 Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 08:54:05 -0600
Subject: [PATCH 129/749] Line-by-line-as-literally-as-possible conversion from
 BASIC to Ruby

Excluding the direction-finding logic.

Ruby lacks a GOTO or even a way to "break" out of two loops instead of
one, necessitating the use of variables and subroutines that the
original program lacked.
---
 51 Hurkle/ruby/hurkle.rb | 117 ++++++++++++++++++++++-----------------
 1 file changed, 66 insertions(+), 51 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index c758091c..8d1840c3 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -1,51 +1,66 @@
-10 PRINT TAB(33);"HURKLE"
-20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
-30 PRINT:PRINT:PRINT
-110 N=5
-120 G=10
-210 PRINT
-220 PRINT "A HURKLE IS HIDING ON A";G;"BY";G;"GRID. HOMEBASE"
-230 PRINT "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
-235 PRINT "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
-240 PRINT "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
-245 PRINT "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
-246 PRINT "IS THE VERTICAL POSITION. YOU MUST TRY TO"
-250 PRINT "GUESS THE HURKLE'S GRIDPOINT. YOU GET";N;"TRIES."
-260 PRINT "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
-270 PRINT "DIRECTION TO GO TO LOOK FOR THE HURKLE."
-280 PRINT
-285 A=INT(G*RND(1))
-286 B=INT(G*RND(1))
-310 FOR K=1 TO N
-320 PRINT "GUESS #";K;
-330 INPUT X,Y
-340 IF ABS(X-A)+ABS(Y-B)=0 THEN 500
-350 REM PRINT INFO
-360 GOSUB 610
-370 PRINT
-380 NEXT K
-410 PRINT
-420 PRINT "SORRY, THAT'S";N;"GUESSES."
-430 PRINT "THE HURKLE IS AT ";A;",";B
-440 PRINT
-450 PRINT "LET'S PLAY AGAIN, HURKLE IS HIDING."
-460 PRINT
-470 GOTO 285
-500 REM
-510 PRINT
-520 PRINT "YOU FOUND HIM IN";K;"GUESSES!"
-540 GOTO 440
-610 PRINT "GO ";
-620 IF Y=B THEN 670
-630 IF Y
Date: Mon, 1 Mar 2021 10:06:08 -0600
Subject: [PATCH 130/749] Add in the direction-finding logic

---
 51 Hurkle/ruby/hurkle.rb | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index 8d1840c3..e3ddd9d0 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -50,16 +50,20 @@ end
 
 def say_where_to_go(x, y)
   print "GO "
-  #620 IF Y=B THEN 670
-  #630 IF Y
Date: Mon, 1 Mar 2021 10:08:27 -0600
Subject: [PATCH 131/749] Tighten up direction-finding logic

---
 51 Hurkle/ruby/hurkle.rb | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index e3ddd9d0..b4929906 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -50,20 +50,8 @@ end
 
 def say_where_to_go(x, y)
   print "GO "
-  if not y == $b
-    if not y < $b
-      print "SOUTH"
-    else
-      print "NORTH"
-    end
-  end
-  if not x == $a
-    if not x < $a
-      print "WEST"
-    else
-      print "EAST"
-    end
-  end
+  print y < $b ? "NORTH" : "SOUTH" unless y == $b
+  print x < $a ? "EAST"  : "WEST" unless x == $a
   puts
 end
 

From cc24398bdbad731e4e72a56260df7b43918aa26a Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 10:09:39 -0600
Subject: [PATCH 132/749] Correct hurkle's gender

Hurkles can give birth parthenogenetically, but are nevertheless -- or
at least this one is -- nongendered. No male hurkles are known to exist
---
 51 Hurkle/ruby/hurkle.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index b4929906..e6a7c1c0 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -45,7 +45,7 @@ end
 
 def you_found_him(k)
   puts
-  puts "YOU FOUND HIM IN " + k.to_s + " GUESSES!"
+  puts "YOU FOUND IT IN " + k.to_s + " GUESSES!"
 end
 
 def say_where_to_go(x, y)

From b7e044c9c27219fc2d00b5f6c47687a381bfcf36 Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 10:15:12 -0600
Subject: [PATCH 133/749] print_introduction

---
 51 Hurkle/ruby/hurkle.rb | 36 ++++++++++++++++++++----------------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index e6a7c1c0..ee9634fb 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -1,21 +1,25 @@
-puts " " * 33 + "HURKLE"
-puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
-3.times { puts }
-$n = 5
-$g = 10
-puts
-puts "A HURKLE IS HIDING ON A " + $g.to_s + " BY " + $g.to_s + " GRID. HOMEBASE"
-puts "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
-puts "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
-puts "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
-puts "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
-puts "IS THE VERTICAL POSITION. YOU MUST TRY TO"
-puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + $n.to_s + " TRIES."
-puts "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
-puts "DIRECTION TO GO TO LOOK FOR THE HURKLE."
-puts
+def print_introduction
+  puts " " * 33 + "HURKLE"
+  puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
+  3.times { puts }
+  $n = 5
+  $g = 10
+  puts
+  puts "A HURKLE IS HIDING ON A " + $g.to_s + " BY " + $g.to_s + " GRID. HOMEBASE"
+  puts "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
+  puts "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
+  puts "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
+  puts "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
+  puts "IS THE VERTICAL POSITION. YOU MUST TRY TO"
+  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + $n.to_s + " TRIES."
+  puts "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
+  puts "DIRECTION TO GO TO LOOK FOR THE HURKLE."
+  puts
+end
 
 def main
+  print_introduction
+
   loop do
     $a = rand($g).floor
     $b = rand($g).floor

From f9387636a7a19c4b74115f90d48b20ae6dfb091c Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 10:17:47 -0600
Subject: [PATCH 134/749] Move more prints into functions

---
 51 Hurkle/ruby/hurkle.rb | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index ee9634fb..779c9f85 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -1,4 +1,4 @@
-def print_introduction
+def say_introduction
   puts " " * 33 + "HURKLE"
   puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
   3.times { puts }
@@ -18,7 +18,7 @@ def print_introduction
 end
 
 def main
-  print_introduction
+  say_introduction
 
   loop do
     $a = rand($g).floor
@@ -29,25 +29,19 @@ def main
       print "? "
       x, y = gets.chomp.split(",").map(&:to_i)
       if (x-$a).abs + (y-$b).abs == 0
-        you_found_him(k)
+        say_success(k)
         found = true
         break
       end
       say_where_to_go(x, y)
       puts
     end
-    if not found
-      puts
-      puts "SORRY, THAT'S " + $n.to_s + " GUESSES."
-      puts "THE HURKLE IS AT " + $a.to_s + "," + $b.to_s
-    end
-    puts
-    puts "LET'S PLAY AGAIN, HURKLE IS HIDING."
-    puts
+    say_failure if not found
+    say_play_again
   end
 end
 
-def you_found_him(k)
+def say_success(k)
   puts
   puts "YOU FOUND IT IN " + k.to_s + " GUESSES!"
 end
@@ -59,4 +53,16 @@ def say_where_to_go(x, y)
   puts
 end
 
+def say_failure
+  puts
+  puts "SORRY, THAT'S " + $n.to_s + " GUESSES."
+  puts "THE HURKLE IS AT " + $a.to_s + "," + $b.to_s
+end
+
+def say_play_again
+  puts
+  puts "LET'S PLAY AGAIN, HURKLE IS HIDING."
+  puts
+end
+
 main

From 9d41dd2c313525b0f3b550f0ee8e9cd562d131f3 Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 10:18:12 -0600
Subject: [PATCH 135/749] Move a function around

---
 51 Hurkle/ruby/hurkle.rb | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index 779c9f85..790f579d 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -1,22 +1,3 @@
-def say_introduction
-  puts " " * 33 + "HURKLE"
-  puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
-  3.times { puts }
-  $n = 5
-  $g = 10
-  puts
-  puts "A HURKLE IS HIDING ON A " + $g.to_s + " BY " + $g.to_s + " GRID. HOMEBASE"
-  puts "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
-  puts "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
-  puts "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
-  puts "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
-  puts "IS THE VERTICAL POSITION. YOU MUST TRY TO"
-  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + $n.to_s + " TRIES."
-  puts "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
-  puts "DIRECTION TO GO TO LOOK FOR THE HURKLE."
-  puts
-end
-
 def main
   say_introduction
 
@@ -41,6 +22,25 @@ def main
   end
 end
 
+def say_introduction
+  puts " " * 33 + "HURKLE"
+  puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
+  3.times { puts }
+  $n = 5
+  $g = 10
+  puts
+  puts "A HURKLE IS HIDING ON A " + $g.to_s + " BY " + $g.to_s + " GRID. HOMEBASE"
+  puts "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
+  puts "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
+  puts "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
+  puts "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
+  puts "IS THE VERTICAL POSITION. YOU MUST TRY TO"
+  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + $n.to_s + " TRIES."
+  puts "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
+  puts "DIRECTION TO GO TO LOOK FOR THE HURKLE."
+  puts
+end
+
 def say_success(k)
   puts
   puts "YOU FOUND IT IN " + k.to_s + " GUESSES!"

From 7ab5cfd140e57d227b795e7b988c5ab9be0fe0d6 Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 10:20:40 -0600
Subject: [PATCH 136/749] Ruby names constants with UPPER_CASE by convention

---
 51 Hurkle/ruby/hurkle.rb | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index 790f579d..24eabf40 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -1,11 +1,14 @@
+MAX_GUESSES = 5
+GRID_SIZE = 10
+
 def main
   say_introduction
 
   loop do
-    $a = rand($g).floor
-    $b = rand($g).floor
+    $a = rand(GRID_SIZE).floor
+    $b = rand(GRID_SIZE).floor
     found = false
-    (1..$n).each do |k|
+    (1..MAX_GUESSES).each do |k|
       print "GUESS # " + k.to_s + " "
       print "? "
       x, y = gets.chomp.split(",").map(&:to_i)
@@ -26,16 +29,14 @@ def say_introduction
   puts " " * 33 + "HURKLE"
   puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
   3.times { puts }
-  $n = 5
-  $g = 10
   puts
-  puts "A HURKLE IS HIDING ON A " + $g.to_s + " BY " + $g.to_s + " GRID. HOMEBASE"
+  puts "A HURKLE IS HIDING ON A " + GRID_SIZE.to_s + " BY " + GRID_SIZE.to_s + " GRID. HOMEBASE"
   puts "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
   puts "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
   puts "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
   puts "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
   puts "IS THE VERTICAL POSITION. YOU MUST TRY TO"
-  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + $n.to_s + " TRIES."
+  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + MAX_GUESSES.to_s + " TRIES."
   puts "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
   puts "DIRECTION TO GO TO LOOK FOR THE HURKLE."
   puts
@@ -55,7 +56,7 @@ end
 
 def say_failure
   puts
-  puts "SORRY, THAT'S " + $n.to_s + " GUESSES."
+  puts "SORRY, THAT'S " + MAX_GUESSES.to_s + " GUESSES."
   puts "THE HURKLE IS AT " + $a.to_s + "," + $b.to_s
 end
 

From 3d6267433adee03bc64da9dfe58db8ecff3ebf68 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Mon, 1 Mar 2021 09:08:03 -0800
Subject: [PATCH 137/749] WIP Begin Porting HEXAPAWN to Python

So far, have printed out instructions and parsed player moves. Submitting pull request to let folks know I'm working on this.
---
 46 Hexapawn/python/hexapawn.py | 320 +++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)
 create mode 100644 46 Hexapawn/python/hexapawn.py

diff --git a/46 Hexapawn/python/hexapawn.py b/46 Hexapawn/python/hexapawn.py
new file mode 100644
index 00000000..232bb782
--- /dev/null
+++ b/46 Hexapawn/python/hexapawn.py	
@@ -0,0 +1,320 @@
+"""
+HEXAPAWN
+
+A machine learning game, an interpretation of HEXAPAWN game as
+presented in Martin Gardner's "The Unexpected Hanging and Other
+Mathematical Diversions", Chapter Eight: A Matchbox Game-Learning
+Machine. 
+
+Original version for H-P timeshare system by R.A. Kaapke 5/5/76 
+Instructions by Jeff Dalton 
+Conversion to MITS BASIC by Steve North
+
+
+Port to Python by Dave LeCompte
+"""
+
+PAGE_WIDTH = 64
+
+def print_centered(msg):
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
+
+def print_header(title):
+    print_centered(title)
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+def print_instructions():
+    print("""
+THIS PROGRAM PLAYS THE GAME OF HEXAPAWN.
+HEXAPAWN IS PLAYED WITH CHESS PAWNS ON A 3 BY 3 BOARD.
+THE PAWNS ARE MOVED AS IN CHESS - ONE SPACE FORWARD TO
+AN EMPTY SPACE OR ONE SPACE FORWARD AND DIAGONALLY TO
+CAPTURE AN OPPOSING MAN.  ON THE BOARD, YOUR PAWNS
+ARE 'O', THE COMPUTER'S PAWNS ARE 'X', AND EMPTY 
+SQUARES ARE '.'.  TO ENTER A MOVE, TYPE THE NUMBER OF
+THE SQUARE YOU ARE MOVING FROM, FOLLOWED BY THE NUMBER
+OF THE SQUARE YOU WILL MOVE TO.  THE NUMBERS MUST BE
+SEPERATED BY A COMMA.
+
+THE COMPUTER STARTS A SERIES OF GAMES KNOWING ONLY WHEN
+THE GAME IS WON (A DRAW IS IMPOSSIBLE) AND HOW TO MOVE.
+IT HAS NO STRATEGY AT FIRST AND JUST MOVES RANDOMLY.
+HOWEVER, IT LEARNS FROM EACH GAME.  THUS, WINNING BECOMES
+MORE AND MORE DIFFICULT.  ALSO, TO HELP OFFSET YOUR
+INITIAL ADVANTAGE, YOU WILL NOT BE TOLD HOW TO WIN THE
+GAME BUT MUST LEARN THIS BY PLAYING.
+
+THE NUMBERING OF THE BOARD IS AS FOLLOWS:
+          123
+          456
+          789
+
+FOR EXAMPLE, TO MOVE YOUR RIGHTMOST PAWN FORWARD,
+YOU WOULD TYPE 9,6 IN RESPONSE TO THE QUESTION
+'YOUR MOVE ?'.  SINCE I'M A GOOD SPORT, YOU'LL ALWAYS
+GO FIRST.
+
+""")
+
+
+def prompt_yes_no(msg):
+    while True:
+        print(msg)
+        response = input().upper()
+        if response[0] == "Y":
+            return True
+        elif response[0] == "N":
+            return False
+
+def fnr(x):
+    score = {1: -3,
+             2: -2,
+             3: -1,
+             4: -6,
+             5: -5,
+             6: -4,
+             7: -9,
+             8: -8,
+             9: -7}
+    return score[x]
+
+def fnm(y):
+    return y % 10
+
+def get_b(x, y):
+    data = [[-1, -1, -1,  1,  0,  0,  0,  1,  1],
+            [-1, -1, -1,  0,  1,  0,  1,  0,  1],
+            [-1,  0, -1, -1,  1,  0,  0,  0,  1],
+            [ 0, -1, -1,  1, -1,  0,  0,  0,  1],
+            [-1,  0, -1,  1,  1,  0,  0,  1,  0],
+            [-1, -1,  0,  1,  0,  1,  0,  0,  1],
+            [ 0, -1, -1,  0, -1,  1,  1,  0,  0],
+            [ 0, -1, -1, -1,  1,  1,  1,  0,  0],
+            [-1,  0, -1, -1,  0,  1,  0,  1,  0],
+            [ 0, -1, -1,  0,  1,  0,  0,  0,  1],
+            [ 0, -1, -1,  0,  1,  0,  1,  0,  0],
+            [-1,  0, -1,  1,  0,  0,  0,  0,  1],
+            [ 0,  0, -1, -1, -1,  1,  0,  0,  0],
+            [-1,  0,  0,  1,  1,  1,  0,  0,  0],
+            [ 0, -1,  0, -1,  1,  1,  0,  0,  0],
+            [-1,  0,  0, -1, -1,  1,  0,  0,  0],
+            [ 0,  0, -1, -1,  1,  0,  0,  0,  0],
+            [ 0, -1,  0,  1, -1,  0,  0,  0,  0],
+            [-1,  0,  0, -1,  1,  0,  0,  0,  0]]
+
+    return data[x+1][y+1]
+
+def get_m(x, y):
+    data = [[24, 25,36,0],
+            [14,15,36,0],
+            [15,35,36,47],
+            [36,58,59,0],
+            [15,35,36,0],
+            [24,25,26,0],
+            [26,57,58,0],
+            [26,35,0,0],
+            [47,48,0,0],
+            [35,36,0,0],
+            [35,36,0,0],
+            [36,0,0,0],
+            [47,58,0,0],
+            [15,0,0,0],
+            [26,47,0,0],
+            [47,58,0,0],
+            [35,36,47,0],
+            [28,58,0,0],
+            [15,47,0,0]]
+
+    return data[x+1][y+1]
+
+def init_board():
+    return [-1] * 3 + [0] * 3 + [1] * 3
+
+def print_board(board):
+    pieces = "X.O"
+
+    space = " "*10
+    print()
+    for i in range(3):
+        line = ""
+        for j in range(3):
+            line += space
+            space_number = i * 3 + j
+            space_contents = board[space_number]
+            line += pieces[space_contents + 1]
+        print(line)
+    print()
+
+def get_coordinates():
+    while True:
+        try:
+            print ("YOUR MOVE?")
+            response = input()
+            m1, m2 = [int(c) for c in response.split(',')]
+            return m1, m2
+        except ValueError as ve:
+            print("ILLEGAL MOVE.")
+
+def print_illegal():
+    print("ILLEGAL MOVE.")
+
+def board_contents(board, space_number):
+    return board[space_number - 1]
+
+def set_board(board, space_number, new_value):
+    board[space_number - 1] = new_value
+
+def main():
+    print_header("HEXAPAWN")
+    if prompt_yes_no("INSTRUCTIONS (Y-N)?"):
+        print_instructions()
+
+    w = 0
+    l = 0
+
+    x = 0
+    y = 0
+
+    board = init_board()
+
+    print_board(board)
+
+    while True:
+        m1, m2 = get_coordinates()
+
+        if board_contents(board, m1) != 1:
+            # Start space doesn't contain player's piece
+            print_illegal()
+            continue
+        if board_contents(board, m2) == 1:
+            # Destination space contains player's piece (can't capture your own piece)
+            print_illegal()
+            continue
+        # line 160
+        is_capture = (m2-m1 != -3)
+        if is_capture and board_contents(board, m2) != -1:
+            # Destination does not contain computer piece
+            print_illegal()
+            continue
+        # line 170
+        if m2 > m1:
+            # can't move backwards
+            print_illegal()
+            continue
+        # line 180
+        if (not is_capture) and board_contents(board, m2) != 0:
+            # Destination is not open
+            print_illegal()
+            continue
+        # line 185
+        if m2-m1 < -4:
+            # too far
+            print_illegal()
+            continue
+        # line 186
+        if m1 == 7 and m2 == 3:
+            # can't jump corner to corner ?!
+            print_illegal()
+            continue
+
+        # otherwise, acceptable move
+        break
+        
+    set_board(board, m1, 0)
+    set_board(board, m2, 1)
+
+    # line 205
+    print_board(board)
+    
+
+if __name__ == "__main__":
+    main()
+
+"""
+210 IF S(1)=1 OR S(2)=1 OR S(3)=1 THEN 820
+220 FOR I=1 TO 9
+221 IF S(I)=-1 THEN 230
+222 NEXT I
+223 GOTO 820
+230 FOR I=1 TO 9
+240 IF S(I)<>-1 THEN 330
+250 IF S(I+3)=0 THEN 350
+260 IF FNR(I)=I THEN 320
+270 IF I>3 THEN 300
+280 IF S(5)=1 THEN 350
+290 GOTO 330
+300 IF S(8)=1 THEN 350
+310 GOTO 330
+320 IF S(I+2)=1 OR S(I+4)=1 THEN 350
+330 NEXT I
+340 GOTO 820
+350 FOR I=1 TO 19
+360 FOR J=1 TO 3
+370 FOR K=3 TO 1 STEP -1
+380 T((J-1)*3+K)=B(I,(J-1)*3+4-K)
+390 NEXT K
+400 NEXT J
+410 FOR J=1 TO 9
+420 IF S(J)<>B(I,J) THEN 460
+430 NEXT J
+440 R=0
+450 GOTO 540
+460 FOR J=1 TO 9
+470 IF S(J)<>T(J) THEN 510
+480 NEXT J
+490 R=1
+500 GOTO 540
+510 NEXT I
+511 REMEMBER THE TERMINATION OF THIS LOOP IS IMPOSSIBLE
+512 PRINT "ILLEGAL BOARD PATTERN."
+530 STOP
+540 X=I
+550 FOR I=1 TO 4
+560 IF M(X,I)<>0 THEN 600
+570 NEXT I
+580 PRINT "I RESIGN."
+590 GOTO 820
+600 Y=INT(RND(1)*4+1)
+601 IF M(X,Y)=0 THEN 600
+610 IF R<>0 THEN 630
+620 PRINT "I MOVE FROM ";STR$(INT(M(X,Y)/10));" TO ";STR$(FNM(M(X,Y)))
+622 S(INT(M(X,Y)/10))=0
+623 S(FNM(M(X,Y)))=-1
+624 GOTO 640
+630 PRINT "I MOVE FROM ";STR$(FNR(INT(M(X,Y)/10)));" TO ";
+631 PRINT STR$(FNR(FNM(M(X,Y))))
+632 S(FNR(INT(M(X,Y)/10)))=0
+633 S(FNR(FNM(M(X,Y))))=-1
+640 GOSUB 1000
+641 IF S(7)=-1 OR S(8)=-1 OR S(9)=-1 THEN 870
+650 FOR I=1 TO 9
+660 IF S(I)=1 THEN 690
+670 NEXT I
+680 GOTO 870
+690 FOR I=1 TO 9
+700 IF S(I)<>1 THEN 790
+710 IF S(I-3)=0 THEN 120
+720 IF FNR(I)=I THEN 780
+730 IF I<7 THEN 760
+740 IF S(5)=-1 THEN 120
+750 GOTO 790
+760 IF S(2)=-1 THEN 120
+770 GOTO 790
+780 IF S(I-2)=-1 OR S(I-4)=-1 THEN 120
+790 NEXT I
+800 PRINT "YOU CAN'T MOVE, SO ";
+810 GOTO 870
+820 PRINT "YOU WIN."
+830 M(X,Y)=0
+840 L=L+1
+850 PRINT "I HAVE WON";W;"AND YOU";L;"OUT OF";L+W;"GAMES."
+851 PRINT
+860 GOTO 100
+870 PRINT "I WIN."
+880 W=W+1
+890 GOTO 850
+"""

From 6980dfda94c5f871265fca300ed4684ac1417ebd Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 11:17:00 -0600
Subject: [PATCH 138/749] Add a Point class

---
 51 Hurkle/ruby/hurkle.rb | 46 ++++++++++++++++++++++++++++------------
 1 file changed, 33 insertions(+), 13 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index 24eabf40..7a4e451b 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -1,26 +1,49 @@
 MAX_GUESSES = 5
 GRID_SIZE = 10
 
+class Point < Object
+  attr_accessor :x
+  attr_accessor :y
+
+  def initialize(text="")
+    x, y = text.split(",").map(&:strip)
+    @x = (x || rand(GRID_SIZE).floor).to_i
+    @y = (y || rand(GRID_SIZE).floor).to_i
+  end
+
+  def to_s
+    "#{@x}, #{@y}"
+  end
+
+  def ==(other_point)
+    @x == other_point.x && @y == other_point.y
+  end
+
+  def direction_to(other_point)
+    (  @y < other_point.y ? "NORTH" : "SOUTH" unless @y == other_point.y ).to_s +
+      (@x < other_point.x ? "EAST"  : "WEST"  unless @x == other_point.x ).to_s
+  end
+end
+
 def main
   say_introduction
 
   loop do
-    $a = rand(GRID_SIZE).floor
-    $b = rand(GRID_SIZE).floor
+    hurkle_point = Point.new
     found = false
     (1..MAX_GUESSES).each do |k|
       print "GUESS # " + k.to_s + " "
       print "? "
-      x, y = gets.chomp.split(",").map(&:to_i)
-      if (x-$a).abs + (y-$b).abs == 0
+      guess_point = Point.new(gets.chomp)
+      if guess_point == hurkle_point
         say_success(k)
         found = true
         break
       end
-      say_where_to_go(x, y)
+      say_where_to_go(hurkle_point, guess_point)
       puts
     end
-    say_failure if not found
+    say_failure(hurkle_point) if not found
     say_play_again
   end
 end
@@ -47,17 +70,14 @@ def say_success(k)
   puts "YOU FOUND IT IN " + k.to_s + " GUESSES!"
 end
 
-def say_where_to_go(x, y)
-  print "GO "
-  print y < $b ? "NORTH" : "SOUTH" unless y == $b
-  print x < $a ? "EAST"  : "WEST" unless x == $a
-  puts
+def say_where_to_go(hurkle_point, guess_point)
+  puts "GO #{guess_point.direction_to(hurkle_point)}"
 end
 
-def say_failure
+def say_failure(hurkle_point)
   puts
   puts "SORRY, THAT'S " + MAX_GUESSES.to_s + " GUESSES."
-  puts "THE HURKLE IS AT " + $a.to_s + "," + $b.to_s
+  puts "THE HURKLE IS AT #{hurkle_point}"
 end
 
 def say_play_again

From 31d048e3f9a012ae6376ac66f10d6fe9b312e6bc Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 11:30:11 -0600
Subject: [PATCH 139/749] Modularize a bit, clean up strings a bit

---
 51 Hurkle/ruby/hurkle.rb | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index 7a4e451b..e8b30eee 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -31,21 +31,14 @@ def main
   loop do
     hurkle_point = Point.new
     found = false
-    (1..MAX_GUESSES).each do |k|
-      print "GUESS # " + k.to_s + " "
-      print "? "
-      guess_point = Point.new(gets.chomp)
-      if guess_point == hurkle_point
-        say_success(k)
-        found = true
-        break
-      end
-      say_where_to_go(hurkle_point, guess_point)
-      puts
+    (1..MAX_GUESSES).each do |guess_num|
+      found = guess(hurkle_point, guess_num)
+      break if found
     end
     say_failure(hurkle_point) if not found
     say_play_again
   end
+
 end
 
 def say_introduction
@@ -53,25 +46,37 @@ def say_introduction
   puts " " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
   3.times { puts }
   puts
-  puts "A HURKLE IS HIDING ON A " + GRID_SIZE.to_s + " BY " + GRID_SIZE.to_s + " GRID. HOMEBASE"
+  puts "A HURKLE IS HIDING ON A #{GRID_SIZE} BY #{GRID_SIZE} GRID. HOMEBASE"
   puts "ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,"
   puts "AND ANY POINT ON THE GRID IS DESIGNATED BY A"
   puts "PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST"
   puts "NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER"
   puts "IS THE VERTICAL POSITION. YOU MUST TRY TO"
-  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET " + MAX_GUESSES.to_s + " TRIES."
+  puts "GUESS THE HURKLE'S GRIDPOINT. YOU GET #{MAX_GUESSES} TRIES."
   puts "AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE"
   puts "DIRECTION TO GO TO LOOK FOR THE HURKLE."
   puts
 end
 
-def say_success(k)
+def guess(hurkle_point, guess_num)
+  print "GUESS # #{guess_num} ? "
+  guess_point = Point.new(gets.chomp)
+  if guess_point == hurkle_point
+    say_success(guess_num)
+    return true
+  end
+  say_where_to_go(hurkle_point, guess_point)
+  false
+end
+
+def say_success(guess_num)
   puts
-  puts "YOU FOUND IT IN " + k.to_s + " GUESSES!"
+  puts "YOU FOUND IT IN #{guess_num} GUESSES!"
 end
 
 def say_where_to_go(hurkle_point, guess_point)
   puts "GO #{guess_point.direction_to(hurkle_point)}"
+  puts
 end
 
 def say_failure(hurkle_point)

From bd8c2dac481a6a2d86a488daf35fb2c869214cde Mon Sep 17 00:00:00 2001
From: Jamie McCarthy 
Date: Mon, 1 Mar 2021 11:33:52 -0600
Subject: [PATCH 140/749] Simplify

---
 51 Hurkle/ruby/hurkle.rb | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/51 Hurkle/ruby/hurkle.rb b/51 Hurkle/ruby/hurkle.rb
index e8b30eee..39898805 100644
--- a/51 Hurkle/ruby/hurkle.rb	
+++ b/51 Hurkle/ruby/hurkle.rb	
@@ -63,10 +63,11 @@ def guess(hurkle_point, guess_num)
   guess_point = Point.new(gets.chomp)
   if guess_point == hurkle_point
     say_success(guess_num)
-    return true
+    true
+  else
+    say_where_to_go(hurkle_point, guess_point)
+    false
   end
-  say_where_to_go(hurkle_point, guess_point)
-  false
 end
 
 def say_success(guess_num)

From f693cb88bdb44a81584b9506c543dd9f34402daf Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 16:25:14 -0300
Subject: [PATCH 141/749] Added main code of animal game (not fully tested)

---
 03 Animal/python/animal.py | 94 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 03 Animal/python/animal.py

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
new file mode 100644
index 00000000..50d9b115
--- /dev/null
+++ b/03 Animal/python/animal.py	
@@ -0,0 +1,94 @@
+class Node:
+    """
+    Nodes of the binary tree of questions.
+    """
+
+    def __init__(self, text, yes_node, no_node, is_leaf):
+        self.text = text
+        self.yes_node = yes_node
+        self.no_node = no_node
+        # the nodes that are leafs have as text the animal's name
+        self.is_leaf = is_leaf
+
+    def update_node(self, new_question, answer_new_ques, new_animal):
+        # update the yes or no leaf with a question
+        old_animal = self.text
+        # we replace the animal with a new question
+        self.text = new_question
+
+        if answer_new_ques == 'y':
+            self.yes_node = Node(new_animal, None, None, True)
+            self.no_node = Node(old_animal, None, None, True)
+        else:
+            self.yes_node = Node(old_animal, None, None, True)
+            self.no_node = Node(new_animal, None, None, True)
+
+        self.is_leaf = False
+
+
+def parse_input(message):
+    # only accepts yes or no inputs
+    correct_input = False
+    while not correct_input:
+        try:
+            inp = input(message)
+            token = inp[0].lower()
+            if token == 'y' or token == 'n':
+                correct_input = True
+        except IndexError:
+            pass
+
+    return token
+
+
+def avoid_void_input(message):
+    answer = ''
+    while answer == '':
+        answer = input(message)
+    return answer
+
+
+# Initial tree
+yes_child = Node('Fish', None, None, True)
+no_child = Node('Bird', None, None, True)
+root = Node('Does it swim?', yes_child, no_child, False)
+
+# Main loop of game
+keep_playing = parse_input('Are you thinking of an animal?') == 'y'
+while keep_playing:
+    keep_asking = True
+    # Start traversing the tree by the root
+    actual_node = root
+
+    while keep_asking:
+
+        if not actual_node.is_leaf:
+            # we have to keep asking i.e. traversing nodes
+            answer = parse_input(actual_node.text)
+
+            if answer == 'y':
+                actual_node = actual_node.yes_node
+            else:
+                actual_node = actual_node.no_node
+        else:
+            # we have reached a possible answer
+            answer = parse_input('Is it a {}?'.format(actual_node.text))
+            if answer == 'n':
+                # add the animal to the tree
+                new_animal = avoid_void_input(
+                    'The animal you were thinking of was a ?')
+                new_question = avoid_void_input(
+                    'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
+                print("new_animal:" + new_animal)
+                answer_new_question = parse_input(
+                    'for a {} the answer would be:'.format(new_animal))
+
+                actual_node.update_node(
+                    new_question+'?', answer_new_question, new_animal)
+
+            else:
+                print("Why not try another animal?")
+
+            keep_asking = False
+
+    keep_playing = parse_input('Are you thinking of an animal?') == 'y'

From f2e9c3a346e424c05edc6c496f1e6391db31b1ea Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 16:53:09 -0300
Subject: [PATCH 142/749] Updated Node tree data structure

---
 03 Animal/python/animal.py | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index 50d9b115..6f9cdffe 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -3,27 +3,29 @@ class Node:
     Nodes of the binary tree of questions.
     """
 
-    def __init__(self, text, yes_node, no_node, is_leaf):
+    def __init__(self, text, yes_node, no_node):
+        # the nodes that are leafs have as text the animal's name, otherwise
+        # a yes/no question
         self.text = text
         self.yes_node = yes_node
         self.no_node = no_node
-        # the nodes that are leafs have as text the animal's name
-        self.is_leaf = is_leaf
 
     def update_node(self, new_question, answer_new_ques, new_animal):
-        # update the yes or no leaf with a question
+        # update the leaf with a question
         old_animal = self.text
         # we replace the animal with a new question
         self.text = new_question
 
         if answer_new_ques == 'y':
-            self.yes_node = Node(new_animal, None, None, True)
-            self.no_node = Node(old_animal, None, None, True)
+            self.yes_node = Node(new_animal, None, None)
+            self.no_node = Node(old_animal, None, None)
         else:
-            self.yes_node = Node(old_animal, None, None, True)
-            self.no_node = Node(new_animal, None, None, True)
+            self.yes_node = Node(old_animal, None, None)
+            self.no_node = Node(new_animal, None, None)
 
-        self.is_leaf = False
+    # the leafs have as children None
+    def is_leaf(self):
+        return self.yes_node == None and self.no_node == None
 
 
 def parse_input(message):
@@ -49,9 +51,9 @@ def avoid_void_input(message):
 
 
 # Initial tree
-yes_child = Node('Fish', None, None, True)
-no_child = Node('Bird', None, None, True)
-root = Node('Does it swim?', yes_child, no_child, False)
+yes_child = Node('Fish', None, None)
+no_child = Node('Bird', None, None)
+root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
 keep_playing = parse_input('Are you thinking of an animal?') == 'y'
@@ -62,7 +64,7 @@ while keep_playing:
 
     while keep_asking:
 
-        if not actual_node.is_leaf:
+        if not actual_node.is_leaf():
             # we have to keep asking i.e. traversing nodes
             answer = parse_input(actual_node.text)
 
@@ -74,12 +76,11 @@ while keep_playing:
             # we have reached a possible answer
             answer = parse_input('Is it a {}?'.format(actual_node.text))
             if answer == 'n':
-                # add the animal to the tree
+                # add the new animal to the tree
                 new_animal = avoid_void_input(
                     'The animal you were thinking of was a ?')
                 new_question = avoid_void_input(
                     'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
-                print("new_animal:" + new_animal)
                 answer_new_question = parse_input(
                     'for a {} the answer would be:'.format(new_animal))
 

From 814eb92bb14237443feec7b6de88f95bb66e69ba Mon Sep 17 00:00:00 2001
From: Jeff Lewis 
Date: Mon, 1 Mar 2021 13:37:39 -0700
Subject: [PATCH 143/749] Added csproj and sln

---
 02 Amazing/csharp/Amazing.csproj |  8 ++++++++
 02 Amazing/csharp/Amazing.sln    | 25 +++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 02 Amazing/csharp/Amazing.csproj
 create mode 100644 02 Amazing/csharp/Amazing.sln

diff --git a/02 Amazing/csharp/Amazing.csproj b/02 Amazing/csharp/Amazing.csproj
new file mode 100644
index 00000000..d453e9a0
--- /dev/null
+++ b/02 Amazing/csharp/Amazing.csproj	
@@ -0,0 +1,8 @@
+
+
+  
+    Exe
+    netcoreapp3.1
+  
+
+
diff --git a/02 Amazing/csharp/Amazing.sln b/02 Amazing/csharp/Amazing.sln
new file mode 100644
index 00000000..8dffa5d1
--- /dev/null
+++ b/02 Amazing/csharp/Amazing.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.808.10
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amazing", "Amazing.csproj", "{DD3483B4-F366-493C-8BFE-BAFBFE6F3016}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{DD3483B4-F366-493C-8BFE-BAFBFE6F3016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DD3483B4-F366-493C-8BFE-BAFBFE6F3016}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DD3483B4-F366-493C-8BFE-BAFBFE6F3016}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DD3483B4-F366-493C-8BFE-BAFBFE6F3016}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {F8762606-E467-47C1-A28F-BD5C4F7BFF5A}
+	EndGlobalSection
+EndGlobal

From ed6367352d1fc75dd4fc6009dc546a5a973c7cc7 Mon Sep 17 00:00:00 2001
From: Jeff Lewis 
Date: Mon, 1 Mar 2021 13:39:18 -0700
Subject: [PATCH 144/749] Fixed prompt msg

---
 02 Amazing/csharp/Amazing.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/02 Amazing/csharp/Amazing.cs b/02 Amazing/csharp/Amazing.cs
index f62549d4..995b58d6 100644
--- a/02 Amazing/csharp/Amazing.cs	
+++ b/02 Amazing/csharp/Amazing.cs	
@@ -165,7 +165,7 @@ namespace Amazing
 
         private String DisplayTextAndGetInput(String text)
         {
-            Console.Write(text);
+            Console.WriteLine(text);
             return Console.ReadLine();
         }
 

From e13f82bd2dc27be8c94bf0d64c24fff7916b4f2e Mon Sep 17 00:00:00 2001
From: Jack Boyce 
Date: Mon, 1 Mar 2021 13:20:04 -0800
Subject: [PATCH 145/749] fixed direction/distance calculator

---
 84 Super Star Trek/python/superstartrek.py | 47 ++++++++++++++++------
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py
index dbb64014..63a454c3 100644
--- a/84 Super Star Trek/python/superstartrek.py	
+++ b/84 Super Star Trek/python/superstartrek.py	
@@ -88,14 +88,23 @@ def navigation():
     # Take navigation input and move the Enterprise.
     global d, s, e, k, s1, s2, qs, t8, t9, t, w1, c, q1, q2
 
-    c1 = float(input("COURSE (1-9)? "))
+    while True:
+        c1s = input("COURSE (1-9)? ")
+        if len(c1s) > 0:
+            c1 = float(c1s)
+            break
     if c1 == 9:
         c1 = 1
     if c1 < 1 or c1 >= 9:
         print("   LT. SULU REPORTS, 'INCORRECT COURSE DATA, SIR!'")
         return
+
     xs = '0.2' if d[0] < 0 else '8'
-    w1 = float(input(f"WARP FACTOR (0-{xs})? "))
+    while True:
+        w1s = input(f"WARP FACTOR (0-{xs})? ")
+        if len(w1s) > 0:
+            w1 = float(w1s)
+            break
     if d[0] < 0 and w1 > 0.2:
         print("WARP ENGINES ARE DAMAGED. MAXIMUM SPEED = WARP 0.2")
         return
@@ -351,10 +360,14 @@ def phaser_control():
     print(f"PHASERS LOCKED ON TARGET;  ENERGY AVAILABLE = {e} UNITS")
     x = 0
     while True:
-        x = int(input("NUMBER OF UNITS TO FIRE? "))
+        while True:
+            xs = input("NUMBER OF UNITS TO FIRE? ")
+            if len(xs) > 0:
+                x = int(xs)
+                break
         if x <= 0:
             return
-        if e - x >= 0:
+        if e >= x:
             break
         print(f"ENERGY AVAILABLE = {e} UNITS")
 
@@ -402,7 +415,11 @@ def photon_torpedoes():
         print("PHOTON TUBES ARE NOT OPERATIONAL")
         return
 
-    c1 = float(input("PHOTON TORPEDO COURSE (1-9)? "))
+    while True:
+        c1s = input("PHOTON TORPEDO COURSE (1-9)? ")
+        if len(c1s) > 0:
+            c1 = float(c1s)
+            break
     if c1 == 9:
         c1 = 1
     if c1 < 1 or c1 >= 9:
@@ -499,8 +516,11 @@ def shield_control():
         print("SHIELD CONTROL INOPERABLE")
         return
 
-    x = input(f"ENERGY AVAILABLE = {e + s} NUMBER OF UNITS TO SHIELDS? ")
-    x = int(x)
+    while True:
+        xs = input(f"ENERGY AVAILABLE = {e + s} NUMBER OF UNITS TO SHIELDS? ")
+        if len(xs) > 0:
+            x = int(xs)
+            break
 
     if x < 0 or s == x:
         print("")
@@ -643,18 +663,21 @@ def computer():
             return
         elif com == 4:
             print("DIRECTION/DISTANCE CALCULATOR:")
-            print(f"YOU ARE AT QUADRANT {q1} , {q2} SECTOR {s1} , {s2}")
+            print(f"YOU ARE AT QUADRANT {q1+1} , {q2+1} SECTOR "
+                  f"{s1+1} , {s2+1}")
             print("PLEASE ENTER")
             while True:
                 ins = input("  INITIAL COORDINATES (X,Y)? ").split(',')
                 if len(ins) == 2:
-                    from1, from2 = int(ins[0]), int(ins[1])
-                    break
+                    from1, from2 = int(ins[0]) - 1, int(ins[1]) - 1
+                    if 0 <= from1 <= 7 and 0 <= from2 <= 7:
+                        break
             while True:
                 ins = input("  FINAL COORDINATES (X,Y)? ").split(',')
                 if len(ins) == 2:
-                    to1, to2 = int(ins[0]), int(ins[1])
-                    break
+                    to1, to2 = int(ins[0]) - 1, int(ins[1]) - 1
+                    if 0 <= to1 <= 7 and 0 <= to2 <= 7:
+                        break
             print_direction(from1, from2, to1, to2)
             return
         else:

From cad8dd6f669cccd43069044eb661e0b708d61996 Mon Sep 17 00:00:00 2001
From: marvin826 
Date: Mon, 1 Mar 2021 14:24:51 -0700
Subject: [PATCH 146/749] Jupyter workbook for working out basic Salvo Python
 concepts

---
 77 Salvo/python/salvo.ipynb | 219 ++++++++++++++++++++++++++++++++++++
 1 file changed, 219 insertions(+)
 create mode 100644 77 Salvo/python/salvo.ipynb

diff --git a/77 Salvo/python/salvo.ipynb b/77 Salvo/python/salvo.ipynb
new file mode 100644
index 00000000..9b2479db
--- /dev/null
+++ b/77 Salvo/python/salvo.ipynb	
@@ -0,0 +1,219 @@
+{
+ "metadata": {
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.7.3-final"
+  },
+  "orig_nbformat": 2,
+  "kernelspec": {
+   "name": "python3",
+   "display_name": "Python 3.7.3 64-bit ('python': venv)",
+   "metadata": {
+    "interpreter": {
+     "hash": "d99f099520c2505e9f745916a84fcd3ec6a6f02f993bb8e12b586a85fced6daa"
+    }
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import random"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "random.seed()\n",
+    "\n",
+    "BOARD_WIDTH = 10\n",
+    "BOARD_HEIGHT = 10\n",
+    "\n",
+    "def random_x_y():\n",
+    "    x = random.randrange(1,BOARD_WIDTH+1)\n",
+    "    y = random.randrange(1,BOARD_HEIGHT+1)\n",
+    "    return (x,y)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "5 2\n"
+     ]
+    }
+   ],
+   "source": [
+    "x,y = random_x_y()\n",
+    "print (x,y)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def random_direction(valid_directions):\n",
+    "    idx = random.ran range(len(valid_directions))\n",
+    "    return valid_directions[idx]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "1\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(random_direction([0,1,2]))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "SHIPS = [ (\"BATTLESHIP\", 5),\n",
+    "          (\"CRUISER\", 3),\n",
+    "          (\"DESTROYER\", 2),\n",
+    "          (\"DESTROYER\", 2) ]\n",
+    "\n",
+    "# given a coordinate (x,y) and a ship type,\n",
+    "# determine which directions from the coordinate \n",
+    "# a ship could be placed. Directions are numbered\n",
+    "# starting at 0 for up, 1 for up/right, 2 for right, \n",
+    "# etc., clockwise from zero (12 o'clock position)\n",
+    "# returns a vector of direction numbers where\n",
+    "# a ship can be placed, starting at one end of the\n",
+    "# ship to its length\n",
+    "def get_possible_directions(x,y,ship):\n",
+    "    ship_len = SHIPS[ship][1] - 1\n",
+    "    dirs = [False for x in range(8)]\n",
+    "    dirs[0] = (x - ship_len) >=1\n",
+    "    dirs[2] = (y + ship_len) <= BOARD_WIDTH\n",
+    "    dirs[1] = dirs[0] and dirs[2]\n",
+    "    dirs[4] = (x + ship_len) <= BOARD_HEIGHT\n",
+    "    dirs[3] = dirs[2] and dirs[4]\n",
+    "    dirs[6] = (y - ship_len) >= 1\n",
+    "    dirs[5] = dirs[4] and dirs[6]\n",
+    "    dirs[7] = dirs[6] and dirs[0]\n",
+    "\n",
+    "    return [x for x in range(len(dirs)) if dirs[x]]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "Boundary Conditions\n( 5, 5): [0, 1, 2, 3, 4, 5, 6, 7]\n( 1, 1): [2, 3, 4]\n( 1,10): [4, 5, 6]\n(10,10): [0, 6, 7]\n(10, 1): [0, 1, 2]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(\"Boundary Conditions\")\n",
+    "print(\"( 5, 5):\",get_possible_directions(5,5,0))\n",
+    "print(\"( 1, 1):\",get_possible_directions(1,1,0))\n",
+    "print(\"( 1,10):\",get_possible_directions(1,10,0))\n",
+    "print(\"(10,10):\",get_possible_directions(10,10,0))\n",
+    "print(\"(10, 1):\",get_possible_directions(10,1,0))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "VALID_MOVES = [[-1, 0],\n",
+    "               [-1, 1],\n",
+    "               [ 0, 1],\n",
+    "               [ 1, 1],\n",
+    "               [ 1, 0],\n",
+    "               [ 1,-1],\n",
+    "               [ 0,-1],\n",
+    "               [-1,-1]]\n",
+    "\n",
+    "\n",
+    "def generate_ship_coordinates(x_start,y_start,direction,ship):\n",
+    "    ship_len = SHIPS[ship][1] - 1\n",
+    "    d_x = VALID_MOVES[direction][0]\n",
+    "    d_y = VALID_MOVES[direction][1]\n",
+    "\n",
+    "    coords = [(x_start,y_start)]\n",
+    "    x_coord = x_start\n",
+    "    y_coord = y_start\n",
+    "    for i in range(ship_len):\n",
+    "        x_coord = x_coord + d_x\n",
+    "        y_coord = y_coord + d_y\n",
+    "        coords.append((x_coord,y_coord))\n",
+    "    return coords"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {},
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "('BATTLESHIP', 5) 5 7 6 [(5, 7), (5, 6), (5, 5), (5, 4), (5, 3)]\n('CRUISER', 3) 1 3 3 [(1, 3), (2, 4), (3, 5)]\n('DESTROYER', 2) 5 9 6 [(5, 9), (5, 8)]\n('DESTROYER', 2) 3 4 3 [(3, 4), (4, 5)]\n"
+     ]
+    }
+   ],
+   "source": [
+    "\n",
+    "for ship in range(len(SHIPS)):\n",
+    "    x,y = random_x_y()\n",
+    "    directions = get_possible_directions(x,y,ship)\n",
+    "    direction = random_direction(directions)\n",
+    "    coords = generate_ship_coordinates(x,y,direction,ship)\n",
+    "    print(SHIPS[ship],x,y,direction,coords)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ]
+}
\ No newline at end of file

From 7fe09d6d2345b3b14f66718ea7e006aeda691b4b Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 18:51:39 -0300
Subject: [PATCH 147/749] Added List command and updated parse to recognize
 that operation

---
 03 Animal/python/animal.py | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index 6f9cdffe..da62a367 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -28,12 +28,34 @@ class Node:
         return self.yes_node == None and self.no_node == None
 
 
-def parse_input(message):
+def list_known_animals(root_node):
+    # Traversing the tree by recursion until we reach the leafs
+    if root_node == None:
+        return
+
+    if root_node.is_leaf():
+        print(root_node.text, end=' '*11)
+        return
+
+    if root_node.yes_node:
+        list_known_animals(root_node.yes_node)
+
+    if root_node.no_node:
+        list_known_animals(root_node.no_node)
+
+
+def parse_input(message, check_list, root_node):
     # only accepts yes or no inputs
     correct_input = False
     while not correct_input:
         try:
             inp = input(message)
+
+            if check_list and inp.lower() == 'list':
+                print('Animals I already know are:')
+                list_known_animals(root_node)
+                print('\n')
+
             token = inp[0].lower()
             if token == 'y' or token == 'n':
                 correct_input = True
@@ -56,7 +78,7 @@ no_child = Node('Bird', None, None)
 root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
-keep_playing = parse_input('Are you thinking of an animal?') == 'y'
+keep_playing = parse_input('Are you thinking of an animal?', True, root) == 'y'
 while keep_playing:
     keep_asking = True
     # Start traversing the tree by the root
@@ -66,7 +88,7 @@ while keep_playing:
 
         if not actual_node.is_leaf():
             # we have to keep asking i.e. traversing nodes
-            answer = parse_input(actual_node.text)
+            answer = parse_input(actual_node.text, False, None)
 
             if answer == 'y':
                 actual_node = actual_node.yes_node
@@ -74,7 +96,8 @@ while keep_playing:
                 actual_node = actual_node.no_node
         else:
             # we have reached a possible answer
-            answer = parse_input('Is it a {}?'.format(actual_node.text))
+            answer = parse_input('Is it a {}?'.format(
+                actual_node.text), False, None)
             if answer == 'n':
                 # add the new animal to the tree
                 new_animal = avoid_void_input(
@@ -82,7 +105,7 @@ while keep_playing:
                 new_question = avoid_void_input(
                     'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
                 answer_new_question = parse_input(
-                    'for a {} the answer would be:'.format(new_animal))
+                    'for a {} the answer would be:'.format(new_animal), False, None)
 
                 actual_node.update_node(
                     new_question+'?', answer_new_question, new_animal)
@@ -92,4 +115,5 @@ while keep_playing:
 
             keep_asking = False
 
-    keep_playing = parse_input('Are you thinking of an animal?') == 'y'
+    keep_playing = parse_input(
+        'Are you thinking of an animal?', True, root) == 'y'

From 2ec485c2b342efbf44f5ee3d3b7c384cb9c18086 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 19:18:24 -0300
Subject: [PATCH 148/749] Added initial message

---
 03 Animal/python/animal.py | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index da62a367..99e55f45 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -45,7 +45,7 @@ def list_known_animals(root_node):
 
 
 def parse_input(message, check_list, root_node):
-    # only accepts yes or no inputs
+    # only accepts yes or no inputs and recognizes list operation
     correct_input = False
     while not correct_input:
         try:
@@ -72,13 +72,21 @@ def avoid_void_input(message):
     return answer
 
 
+def initial_message():
+    print(' '*32 + 'Animal')
+    print(' '*15 + 'Creative Computing Morristown, New Jersey\n')
+    print('Play ´Guess the Animal´')
+    print('Think of an animal and the computer will try to guess it.\n')
+
+
 # Initial tree
 yes_child = Node('Fish', None, None)
 no_child = Node('Bird', None, None)
 root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
-keep_playing = parse_input('Are you thinking of an animal?', True, root) == 'y'
+initial_message()
+keep_playing = parse_input('Are you thinking of an animal? ', True, root) == 'y'
 while keep_playing:
     keep_asking = True
     # Start traversing the tree by the root
@@ -96,16 +104,16 @@ while keep_playing:
                 actual_node = actual_node.no_node
         else:
             # we have reached a possible answer
-            answer = parse_input('Is it a {}?'.format(
+            answer = parse_input('Is it a {}? '.format(
                 actual_node.text), False, None)
             if answer == 'n':
                 # add the new animal to the tree
                 new_animal = avoid_void_input(
-                    'The animal you were thinking of was a ?')
+                    'The animal you were thinking of was a ? ')
                 new_question = avoid_void_input(
-                    'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
+                    'Please type in a question that would distinguish a {} from a {}: '.format(new_animal, actual_node.text))
                 answer_new_question = parse_input(
-                    'for a {} the answer would be:'.format(new_animal), False, None)
+                    'for a {} the answer would be: '.format(new_animal), False, None)
 
                 actual_node.update_node(
                     new_question+'?', answer_new_question, new_animal)
@@ -116,4 +124,4 @@ while keep_playing:
             keep_asking = False
 
     keep_playing = parse_input(
-        'Are you thinking of an animal?', True, root) == 'y'
+        'Are you thinking of an animal? ', True, root) == 'y'

From cb61baaee1d8cacfa522c227b72dd2886273d387 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 16:25:14 -0300
Subject: [PATCH 149/749] Added main code of animal game (not fully tested)

---
 03 Animal/python/animal.py | 94 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 03 Animal/python/animal.py

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
new file mode 100644
index 00000000..50d9b115
--- /dev/null
+++ b/03 Animal/python/animal.py	
@@ -0,0 +1,94 @@
+class Node:
+    """
+    Nodes of the binary tree of questions.
+    """
+
+    def __init__(self, text, yes_node, no_node, is_leaf):
+        self.text = text
+        self.yes_node = yes_node
+        self.no_node = no_node
+        # the nodes that are leafs have as text the animal's name
+        self.is_leaf = is_leaf
+
+    def update_node(self, new_question, answer_new_ques, new_animal):
+        # update the yes or no leaf with a question
+        old_animal = self.text
+        # we replace the animal with a new question
+        self.text = new_question
+
+        if answer_new_ques == 'y':
+            self.yes_node = Node(new_animal, None, None, True)
+            self.no_node = Node(old_animal, None, None, True)
+        else:
+            self.yes_node = Node(old_animal, None, None, True)
+            self.no_node = Node(new_animal, None, None, True)
+
+        self.is_leaf = False
+
+
+def parse_input(message):
+    # only accepts yes or no inputs
+    correct_input = False
+    while not correct_input:
+        try:
+            inp = input(message)
+            token = inp[0].lower()
+            if token == 'y' or token == 'n':
+                correct_input = True
+        except IndexError:
+            pass
+
+    return token
+
+
+def avoid_void_input(message):
+    answer = ''
+    while answer == '':
+        answer = input(message)
+    return answer
+
+
+# Initial tree
+yes_child = Node('Fish', None, None, True)
+no_child = Node('Bird', None, None, True)
+root = Node('Does it swim?', yes_child, no_child, False)
+
+# Main loop of game
+keep_playing = parse_input('Are you thinking of an animal?') == 'y'
+while keep_playing:
+    keep_asking = True
+    # Start traversing the tree by the root
+    actual_node = root
+
+    while keep_asking:
+
+        if not actual_node.is_leaf:
+            # we have to keep asking i.e. traversing nodes
+            answer = parse_input(actual_node.text)
+
+            if answer == 'y':
+                actual_node = actual_node.yes_node
+            else:
+                actual_node = actual_node.no_node
+        else:
+            # we have reached a possible answer
+            answer = parse_input('Is it a {}?'.format(actual_node.text))
+            if answer == 'n':
+                # add the animal to the tree
+                new_animal = avoid_void_input(
+                    'The animal you were thinking of was a ?')
+                new_question = avoid_void_input(
+                    'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
+                print("new_animal:" + new_animal)
+                answer_new_question = parse_input(
+                    'for a {} the answer would be:'.format(new_animal))
+
+                actual_node.update_node(
+                    new_question+'?', answer_new_question, new_animal)
+
+            else:
+                print("Why not try another animal?")
+
+            keep_asking = False
+
+    keep_playing = parse_input('Are you thinking of an animal?') == 'y'

From 42ff2c852575c9ebe3f72ed3b3689c807f2920d4 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 16:53:09 -0300
Subject: [PATCH 150/749] Updated Node tree data structure

---
 03 Animal/python/animal.py | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index 50d9b115..6f9cdffe 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -3,27 +3,29 @@ class Node:
     Nodes of the binary tree of questions.
     """
 
-    def __init__(self, text, yes_node, no_node, is_leaf):
+    def __init__(self, text, yes_node, no_node):
+        # the nodes that are leafs have as text the animal's name, otherwise
+        # a yes/no question
         self.text = text
         self.yes_node = yes_node
         self.no_node = no_node
-        # the nodes that are leafs have as text the animal's name
-        self.is_leaf = is_leaf
 
     def update_node(self, new_question, answer_new_ques, new_animal):
-        # update the yes or no leaf with a question
+        # update the leaf with a question
         old_animal = self.text
         # we replace the animal with a new question
         self.text = new_question
 
         if answer_new_ques == 'y':
-            self.yes_node = Node(new_animal, None, None, True)
-            self.no_node = Node(old_animal, None, None, True)
+            self.yes_node = Node(new_animal, None, None)
+            self.no_node = Node(old_animal, None, None)
         else:
-            self.yes_node = Node(old_animal, None, None, True)
-            self.no_node = Node(new_animal, None, None, True)
+            self.yes_node = Node(old_animal, None, None)
+            self.no_node = Node(new_animal, None, None)
 
-        self.is_leaf = False
+    # the leafs have as children None
+    def is_leaf(self):
+        return self.yes_node == None and self.no_node == None
 
 
 def parse_input(message):
@@ -49,9 +51,9 @@ def avoid_void_input(message):
 
 
 # Initial tree
-yes_child = Node('Fish', None, None, True)
-no_child = Node('Bird', None, None, True)
-root = Node('Does it swim?', yes_child, no_child, False)
+yes_child = Node('Fish', None, None)
+no_child = Node('Bird', None, None)
+root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
 keep_playing = parse_input('Are you thinking of an animal?') == 'y'
@@ -62,7 +64,7 @@ while keep_playing:
 
     while keep_asking:
 
-        if not actual_node.is_leaf:
+        if not actual_node.is_leaf():
             # we have to keep asking i.e. traversing nodes
             answer = parse_input(actual_node.text)
 
@@ -74,12 +76,11 @@ while keep_playing:
             # we have reached a possible answer
             answer = parse_input('Is it a {}?'.format(actual_node.text))
             if answer == 'n':
-                # add the animal to the tree
+                # add the new animal to the tree
                 new_animal = avoid_void_input(
                     'The animal you were thinking of was a ?')
                 new_question = avoid_void_input(
                     'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
-                print("new_animal:" + new_animal)
                 answer_new_question = parse_input(
                     'for a {} the answer would be:'.format(new_animal))
 

From bf7028276b24cc6ed570741c81534698ddf0dec4 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 18:51:39 -0300
Subject: [PATCH 151/749] Added List command and updated parse to recognize
 that operation

---
 03 Animal/python/animal.py | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index 6f9cdffe..da62a367 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -28,12 +28,34 @@ class Node:
         return self.yes_node == None and self.no_node == None
 
 
-def parse_input(message):
+def list_known_animals(root_node):
+    # Traversing the tree by recursion until we reach the leafs
+    if root_node == None:
+        return
+
+    if root_node.is_leaf():
+        print(root_node.text, end=' '*11)
+        return
+
+    if root_node.yes_node:
+        list_known_animals(root_node.yes_node)
+
+    if root_node.no_node:
+        list_known_animals(root_node.no_node)
+
+
+def parse_input(message, check_list, root_node):
     # only accepts yes or no inputs
     correct_input = False
     while not correct_input:
         try:
             inp = input(message)
+
+            if check_list and inp.lower() == 'list':
+                print('Animals I already know are:')
+                list_known_animals(root_node)
+                print('\n')
+
             token = inp[0].lower()
             if token == 'y' or token == 'n':
                 correct_input = True
@@ -56,7 +78,7 @@ no_child = Node('Bird', None, None)
 root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
-keep_playing = parse_input('Are you thinking of an animal?') == 'y'
+keep_playing = parse_input('Are you thinking of an animal?', True, root) == 'y'
 while keep_playing:
     keep_asking = True
     # Start traversing the tree by the root
@@ -66,7 +88,7 @@ while keep_playing:
 
         if not actual_node.is_leaf():
             # we have to keep asking i.e. traversing nodes
-            answer = parse_input(actual_node.text)
+            answer = parse_input(actual_node.text, False, None)
 
             if answer == 'y':
                 actual_node = actual_node.yes_node
@@ -74,7 +96,8 @@ while keep_playing:
                 actual_node = actual_node.no_node
         else:
             # we have reached a possible answer
-            answer = parse_input('Is it a {}?'.format(actual_node.text))
+            answer = parse_input('Is it a {}?'.format(
+                actual_node.text), False, None)
             if answer == 'n':
                 # add the new animal to the tree
                 new_animal = avoid_void_input(
@@ -82,7 +105,7 @@ while keep_playing:
                 new_question = avoid_void_input(
                     'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
                 answer_new_question = parse_input(
-                    'for a {} the answer would be:'.format(new_animal))
+                    'for a {} the answer would be:'.format(new_animal), False, None)
 
                 actual_node.update_node(
                     new_question+'?', answer_new_question, new_animal)
@@ -92,4 +115,5 @@ while keep_playing:
 
             keep_asking = False
 
-    keep_playing = parse_input('Are you thinking of an animal?') == 'y'
+    keep_playing = parse_input(
+        'Are you thinking of an animal?', True, root) == 'y'

From cb20c15585a5f39472168e1091291e9806e34e08 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 19:18:24 -0300
Subject: [PATCH 152/749] Added initial message

---
 03 Animal/python/animal.py | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index da62a367..99e55f45 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -45,7 +45,7 @@ def list_known_animals(root_node):
 
 
 def parse_input(message, check_list, root_node):
-    # only accepts yes or no inputs
+    # only accepts yes or no inputs and recognizes list operation
     correct_input = False
     while not correct_input:
         try:
@@ -72,13 +72,21 @@ def avoid_void_input(message):
     return answer
 
 
+def initial_message():
+    print(' '*32 + 'Animal')
+    print(' '*15 + 'Creative Computing Morristown, New Jersey\n')
+    print('Play ´Guess the Animal´')
+    print('Think of an animal and the computer will try to guess it.\n')
+
+
 # Initial tree
 yes_child = Node('Fish', None, None)
 no_child = Node('Bird', None, None)
 root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
-keep_playing = parse_input('Are you thinking of an animal?', True, root) == 'y'
+initial_message()
+keep_playing = parse_input('Are you thinking of an animal? ', True, root) == 'y'
 while keep_playing:
     keep_asking = True
     # Start traversing the tree by the root
@@ -96,16 +104,16 @@ while keep_playing:
                 actual_node = actual_node.no_node
         else:
             # we have reached a possible answer
-            answer = parse_input('Is it a {}?'.format(
+            answer = parse_input('Is it a {}? '.format(
                 actual_node.text), False, None)
             if answer == 'n':
                 # add the new animal to the tree
                 new_animal = avoid_void_input(
-                    'The animal you were thinking of was a ?')
+                    'The animal you were thinking of was a ? ')
                 new_question = avoid_void_input(
-                    'Please type in a question that would distinguish a {} from a {}:'.format(new_animal, actual_node.text))
+                    'Please type in a question that would distinguish a {} from a {}: '.format(new_animal, actual_node.text))
                 answer_new_question = parse_input(
-                    'for a {} the answer would be:'.format(new_animal), False, None)
+                    'for a {} the answer would be: '.format(new_animal), False, None)
 
                 actual_node.update_node(
                     new_question+'?', answer_new_question, new_animal)
@@ -116,4 +124,4 @@ while keep_playing:
             keep_asking = False
 
     keep_playing = parse_input(
-        'Are you thinking of an animal?', True, root) == 'y'
+        'Are you thinking of an animal? ', True, root) == 'y'

From 8727dfff29519e287246c2a6bef8d6c4477958aa Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 16:30:23 -0600
Subject: [PATCH 153/749] Ported HURKLE, KINEMA, LETTER, LITQUIZ, LOVE, and
 MATHDICE to Javascript

---
 51 Hurkle/javascript/hurkle.html           |   9 ++
 51 Hurkle/javascript/hurkle.js             | 102 ++++++++++++++++++
 52 Kinema/javascript/kinema.html           |   9 ++
 52 Kinema/javascript/kinema.js             |  95 ++++++++++++++++
 54 Letter/javascript/letter.html           |   9 ++
 54 Letter/javascript/letter.js             |  91 ++++++++++++++++
 57 Literature Quiz/javascript/litquiz.html |   9 ++
 57 Literature Quiz/javascript/litquiz.js   | 119 +++++++++++++++++++++
 58 Love/javascript/love.html               |   9 ++
 58 Love/javascript/love.js                 | 105 ++++++++++++++++++
 61 Math Dice/javascript/mathdice.html      |   9 ++
 61 Math Dice/javascript/mathdice.js        | 113 +++++++++++++++++++
 61 Math Dice/mathdice.bas                  |   2 +-
 13 files changed, 680 insertions(+), 1 deletion(-)
 create mode 100644 51 Hurkle/javascript/hurkle.html
 create mode 100644 51 Hurkle/javascript/hurkle.js
 create mode 100644 52 Kinema/javascript/kinema.html
 create mode 100644 52 Kinema/javascript/kinema.js
 create mode 100644 54 Letter/javascript/letter.html
 create mode 100644 54 Letter/javascript/letter.js
 create mode 100644 57 Literature Quiz/javascript/litquiz.html
 create mode 100644 57 Literature Quiz/javascript/litquiz.js
 create mode 100644 58 Love/javascript/love.html
 create mode 100644 58 Love/javascript/love.js
 create mode 100644 61 Math Dice/javascript/mathdice.html
 create mode 100644 61 Math Dice/javascript/mathdice.js

diff --git a/51 Hurkle/javascript/hurkle.html b/51 Hurkle/javascript/hurkle.html
new file mode 100644
index 00000000..8d2a5022
--- /dev/null
+++ b/51 Hurkle/javascript/hurkle.html	
@@ -0,0 +1,9 @@
+
+
+HURKLE
+
+
+

+
+
+
diff --git a/51 Hurkle/javascript/hurkle.js b/51 Hurkle/javascript/hurkle.js
new file mode 100644
index 00000000..1e3301e5
--- /dev/null
+++ b/51 Hurkle/javascript/hurkle.js	
@@ -0,0 +1,102 @@
+// BATNUM
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "HURKLE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    n = 5;
+    g = 10;
+    print("\n");
+    print("A HURKLE IS HIDING ON A " + g + " BY " + g + " GRID. HOMEBASE\n");
+    print("ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,\n");
+    print("AND ANY POINT ON THE GRID IS DESIGNATED BY A\n");
+    print("PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST\n");
+    print("NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER\n");
+    print("IS THE VERTICAL POSITION. YOU MUST TRY TO\n");
+    print("GUESS THE HURKLE'S GRIDPOINT. YOU GET " + n + " TRIES.\n");
+    print("AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE\n");
+    print("DIRECTION TO GO TO LOOK FOR THE HURKLE.\n");
+    print("\n");
+    while (1) {
+        a = Math.floor(g * Math.random());
+        b = Math.floor(g * Math.random());
+        for (k = 1; k <= n; k++) {
+            print("GUESS #" + k + " ");
+            str = await input();
+            x = parseInt(str);
+            y = parseInt(str.substr(str.indexOf(",") + 1));
+            if (x == a && y == b) {
+                print("\n");
+                print("YOU FOUND HIM IN " + k + " GUESSES!\n");
+                break;
+            }
+            print("GO ");
+            if (y < b) {
+                print("NORTH");
+            } else if (y > b) {
+                print("SOUTH");
+            }
+            if (x < a) {
+                print("EAST\n");
+            } else {
+                print("WEST\n");
+            }
+        }
+        if (k > n) {
+            print("\n");
+            print("SORRY, THAT'S " + n + " GUESSES.\n");
+            print("THE HURKLE IS AT " + a + "," + b + "\n");
+        }
+        print("\n");
+        print("LET'S PLAY AGAIN, HURKLE IS HIDING.\n");
+        print("\n");
+    }
+}
+
+main();
diff --git a/52 Kinema/javascript/kinema.html b/52 Kinema/javascript/kinema.html
new file mode 100644
index 00000000..0e41284e
--- /dev/null
+++ b/52 Kinema/javascript/kinema.html	
@@ -0,0 +1,9 @@
+
+
+KINEMA
+
+
+

+
+
+
diff --git a/52 Kinema/javascript/kinema.js b/52 Kinema/javascript/kinema.js
new file mode 100644
index 00000000..abd2bb1c
--- /dev/null
+++ b/52 Kinema/javascript/kinema.js	
@@ -0,0 +1,95 @@
+// KINEMA
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var q;
+
+function evaluate_answer(str, a)
+{
+    g = parseFloat(str);
+    if (Math.abs((g - a) / a) < 0.15) {
+        print("CLOSE ENOUGH.\n");
+        q++;
+    } else {
+        print("NOT EVEN CLOSE....\n");
+    }
+    print("CORRECT ANSWER IS " + a + "\n\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "KINEMA\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("\n");
+        print("\n");
+        q = 0;
+        v = 5 + Math.floor(35 * Math.random());
+        print("A BALL IS THROWN UPWARDS AT " + v + " METERS PER SECOND.\n");
+        print("\n");
+        a = 0.5 * Math.pow(v, 2);
+        print("HOW HIGH WILL IT GO (IN METERS)");
+        str = await input();
+        evaluate_answer(str, a);
+        a = v / 5;
+        print("HOW LONG UNTIL IT RETURNS (IN SECONDS)");
+        str = await input();
+        evaluate_answer(str, a);
+        t = 1 + Math.floor(2 * v * Math.random()) / 10;
+        a = v - 10 * t;
+        print("WHAT WILL ITS VELOCITY BE AFTER " + t + " SECONDS");
+        str = await input();
+        evaluate_answer(str, a);
+        print("\n");
+        print(q + " RIGHT OUT OF 3.");
+        if (q < 2)
+            continue;
+        print("  NOT BAD.\n");
+    }
+}
+
+main();
diff --git a/54 Letter/javascript/letter.html b/54 Letter/javascript/letter.html
new file mode 100644
index 00000000..744a5499
--- /dev/null
+++ b/54 Letter/javascript/letter.html	
@@ -0,0 +1,9 @@
+
+
+LETTER
+
+
+

+
+
+
diff --git a/54 Letter/javascript/letter.js b/54 Letter/javascript/letter.js
new file mode 100644
index 00000000..7aef3de9
--- /dev/null
+++ b/54 Letter/javascript/letter.js	
@@ -0,0 +1,91 @@
+// LETTER
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "LETTER\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("LETTER GUESSING GAME\n");
+    print("\n");
+    print("I'LL THINK OF A LETTER OF THE ALPHABET, A TO Z.\n");
+    print("TRY TO GUESS MY LETTER AND I'LL GIVE YOU CLUES\n");
+    print("AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER.\n");
+    while (1) {
+        l = 65 + Math.floor(26 * Math.random());
+        g = 0;
+        print("\n");
+        print("O.K., I HAVE A LETTER.  START GUESSING.\n");
+        while (1) {
+            
+            print("\n");
+            print("WHAT IS YOUR GUESS");
+            g++;
+            str = await input();
+            a = str.charCodeAt(0);
+            print("\n");
+            if (a == l)
+                break;
+            if (a < l) {
+                print("TOO LOW.  TRY A HIGHER LETTER.\n");
+            } else {
+                print("TOO HIGH.  TRY A LOWER LETTER.\n");
+            }
+        }
+        print("\n");
+        print("YOU GOT IT IN " + g + " GUESSES!!\n");
+        if (g > 5) {
+            print("BUT IT SHOULDN'T TAKE MORE THAN 5 GUESSES!\n");
+        } else {
+            print("GOOD JOB !!!!!\n");
+        }
+        print("\n");
+        print("LET'S PLAY AGAIN.....");
+    }
+}
+
+main();
diff --git a/57 Literature Quiz/javascript/litquiz.html b/57 Literature Quiz/javascript/litquiz.html
new file mode 100644
index 00000000..e4aae4c3
--- /dev/null
+++ b/57 Literature Quiz/javascript/litquiz.html	
@@ -0,0 +1,9 @@
+
+
+LITERATURE QUIZ
+
+
+

+
+
+
diff --git a/57 Literature Quiz/javascript/litquiz.js b/57 Literature Quiz/javascript/litquiz.js
new file mode 100644
index 00000000..f4d6a4f6
--- /dev/null
+++ b/57 Literature Quiz/javascript/litquiz.js	
@@ -0,0 +1,119 @@
+// LITQUIZ
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(25) + "LITERATURE QUIZ\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    r = 0;
+    print("TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE.\n");
+    print("\n");
+    print("THIS IS A MULTIPLE-CHOICE QUIZ.\n");
+    print("TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK.\n");
+    print("\n");
+    print("GOOD LUCK!\n");
+    print("\n");
+    print("\n");
+    print("IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT\n");
+    print("1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO\n");
+    a = parseInt(await input());
+    if (a == 3) {
+        print("VERY GOOD!  HERE'S ANOTHER.\n");
+        r++;
+    } else {
+        print("SORRY...FIGARO WAS HIS NAME.\n");
+    }
+    print("\n");
+    print("\n");
+    print("FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?\n");
+    print("1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S\n");
+    a = parseInt(await input());
+    if (a == 2) {
+        print("PRETTY GOOD!\n");
+        r++;
+    } else {
+        print("TOO BAD...IT WAS ELMER FUDD'S GARDEN.\n");
+    }
+    print("\n");
+    print("\n");
+    print("IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED\n");
+    print("1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO\n");
+    a = parseInt(await input());
+    if (a == 4) {
+        print("YEA!  YOU'RE A REAL LITERATURE GIANT.\n");
+        r++;
+    } else {
+        print("BACK TO THE BOOKS,...TOTO WAS HIS NAME.\n");
+    }
+    print("\n");
+    print("\n");
+    print("WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE\n");
+    print("1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY\n");
+    a = parseInt(await input());
+    if (a == 3) {
+        print("GOOD MEMORY!\n");
+        r++;
+    } else {
+        print("OH, COME ON NOW...IT WAS SNOW WHITE.\n");
+    }
+    print("\n");
+    print("\n");
+    if (r == 4) {
+        print("WOW!  THAT'S SUPER!  YOU REALLY KNOW YOUR NURSERY\n");
+        print("YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE\n");
+        print("LITERATURE (HA, HA, HA)\n");
+    } else if (r < 2) {
+        print("UGH.  THAT WAS DEFINITELY NOT TOO SWIFT.  BACK TO\n");
+        print("NURSERY SCHOOL FOR YOU, MY FRIEND.\n");
+    } else {
+        print("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME\n");
+        print("READING THE NURSERY GREATS.\n");
+    }
+}
+
+main();
diff --git a/58 Love/javascript/love.html b/58 Love/javascript/love.html
new file mode 100644
index 00000000..ede593e8
--- /dev/null
+++ b/58 Love/javascript/love.html	
@@ -0,0 +1,9 @@
+
+
+LOVE
+
+
+

+
+
+
diff --git a/58 Love/javascript/love.js b/58 Love/javascript/love.js
new file mode 100644
index 00000000..d67c6acb
--- /dev/null
+++ b/58 Love/javascript/love.js	
@@ -0,0 +1,105 @@
+// LOVE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var data = [60,1,12,26,9,12,3,8,24,17,8,4,6,23,21,6,4,6,22,12,5,6,5,
+            4,6,21,11,8,6,4,4,6,21,10,10,5,4,4,6,21,9,11,5,4,
+            4,6,21,8,11,6,4,4,6,21,7,11,7,4,4,6,21,6,11,8,4,
+            4,6,19,1,1,5,11,9,4,4,6,19,1,1,5,10,10,4,4,6,18,2,1,6,8,11,4,
+            4,6,17,3,1,7,5,13,4,4,6,15,5,2,23,5,1,29,5,17,8,
+            1,29,9,9,12,1,13,5,40,1,1,13,5,40,1,4,6,13,3,10,6,12,5,1,
+            5,6,11,3,11,6,14,3,1,5,6,11,3,11,6,15,2,1,
+            6,6,9,3,12,6,16,1,1,6,6,9,3,12,6,7,1,10,
+            7,6,7,3,13,6,6,2,10,7,6,7,3,13,14,10,8,6,5,3,14,6,6,2,10,
+            8,6,5,3,14,6,7,1,10,9,6,3,3,15,6,16,1,1,
+            9,6,3,3,15,6,15,2,1,10,6,1,3,16,6,14,3,1,10,10,16,6,12,5,1,
+            11,8,13,27,1,11,8,13,27,1,60];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "LOVE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("A TRIBUTE TO THE GREAT AMERICAN ARTIST, ROBERT INDIANA.\n");
+    print("HIS GREATEST WORK WILL BE REPRODUCED WITH A MESSAGE OF\n");
+    print("YOUR CHOICE UP TO 60 CHARACTERS.  IF YOU CAN'T THINK OF\n");
+    print("A MESSAGE, SIMPLE TYPE THE WORD 'LOVE'\n");
+    print("\n");
+    print("YOUR MESSAGE, PLEASE");
+    str = await input();
+    l = str.length;
+    ts = [];
+    for (i = 1; i <= 10; i++)
+        print("\n");
+    ts = "";
+    do {
+        ts += str;
+    } while (ts.length < 60) ;
+    pos = 0;
+    c = 0;
+    while (++c < 37) {
+        a1 = 1;
+        p = 1;
+        print("\n");
+        do {
+            a = data[pos++];
+            a1 += a;
+            if (p != 1) {
+                for (i = 1; i <= a; i++)
+                    print(" ");
+                p = 1;
+            } else {
+                for (i = a1 - a; i <= a1 - 1; i++)
+                    print(ts[i]);
+                p = 0;
+            }
+        } while (a1 <= 60) ;
+    }
+    for (i = 1; i <= 10; i++)
+        print("\n");
+}
+
+main();
diff --git a/61 Math Dice/javascript/mathdice.html b/61 Math Dice/javascript/mathdice.html
new file mode 100644
index 00000000..dfdf3f5f
--- /dev/null
+++ b/61 Math Dice/javascript/mathdice.html	
@@ -0,0 +1,9 @@
+
+
+MATH DICE
+
+
+

+
+
+
diff --git a/61 Math Dice/javascript/mathdice.js b/61 Math Dice/javascript/mathdice.js
new file mode 100644
index 00000000..f6ccda81
--- /dev/null
+++ b/61 Math Dice/javascript/mathdice.js	
@@ -0,0 +1,113 @@
+// MATH DICE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(31) + "MATH DICE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE.\n");
+    print("WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION\n");
+    print("MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY.\n"),
+    print("TO CONCLUDE THE LESSON, TYPE ZERO AS YOUR ANSWER.\n");
+    print("\n");
+    print("\n");
+    n = 0;
+    while (1) {
+        n++;
+        d = Math.floor(6 * Math.random() + 1);
+        print(" ----- \n");
+        if (d == 1)
+            print("I     I\n");
+        else if (d == 2 || d == 3)
+            print("I *   I\n");
+        else
+            print("I * * I\n");
+        if (d == 2 || d == 4)
+            print("I     I\n");
+        else if (d == 6)
+            print("I * * I\n");
+        else
+            print("I  *  I\n");
+        if (d == 1)
+            print("I     I\n");
+        else if (d == 2 || d == 3)
+            print("I   * I\n");
+        else
+            print("I * * I\n");
+        print(" ----- \n");
+        print("\n");
+        if (n != 2) {
+            print("   +\n");
+            print("\n");
+            a = d;
+            continue;
+        }
+        t = d + a;
+        print("      =");
+        t1 = parseInt(await input());
+        if (t1 == 0)
+            break;
+        if (t1 != t) {
+            print("NO, COUNT THE SPOTS AND GIVE ANOTHER ANSWER.\n");
+            print("      =");
+            t1 = parseInt(await input());
+            if (t1 != t) {
+                print("NO, THE ANSWER IS " + t + "\n");
+            }
+        }
+        if (t1 == t) {
+            print("RIGHT!\n");
+        }
+        print("\n");
+        print("THE DICE ROLL AGAIN...\n");
+        print("\n");
+        n = 0;
+    }
+}
+
+main();
diff --git a/61 Math Dice/mathdice.bas b/61 Math Dice/mathdice.bas
index d61b060d..a62a7d8c 100644
--- a/61 Math Dice/mathdice.bas	
+++ b/61 Math Dice/mathdice.bas	
@@ -1,7 +1,7 @@
 10 PRINT TAB(31);"MATH DICE"
 20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
 30 PRINT:PRINT:PRINT
-40 PRINT "THIS PROGRAM GENERATES SUCCESIVE PICTURES OF TWO DICE."
+40 PRINT "THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE."
 50 PRINT "WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION"
 60 PRINT "MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY."
 70 PRINT "TO CONCLUDE THE LESSON, TYPE CONTROL-C AS YOUR ANSWER."

From 47fd3b5ab2b13d693c796ef3e677a5d94e0c2106 Mon Sep 17 00:00:00 2001
From: APHawkes 
Date: Mon, 1 Mar 2021 16:59:52 -0600
Subject: [PATCH 154/749] Create Gunner.java

---
 42 Gunner/java/Gunner.java | 108 +++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)
 create mode 100644 42 Gunner/java/Gunner.java

diff --git a/42 Gunner/java/Gunner.java b/42 Gunner/java/Gunner.java
new file mode 100644
index 00000000..0f56abab
--- /dev/null
+++ b/42 Gunner/java/Gunner.java	
@@ -0,0 +1,108 @@
+import java.util.Random;
+import java.util.Scanner;
+
+public class Gunner {
+
+    public static final int MAX_ROUNDS = 6;
+    public static final int MAX_ENEMIES = 4;
+    public static final int ERROR_DISTANCE = 100;
+
+    private static Scanner scanner = new Scanner(System.in);
+    private static Random random = new Random();
+
+    public static void main(String[] args) {
+        println("                              GUNNER");
+        println("               CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        println();
+        println();
+        println();
+        println("YOU ARE THE OFFICER-IN-CHARGE, GIVING ORDERS TO A GUN");
+        println("CREW, TELLING THEM THE DEGREES OF ELEVATION YOU ESTIMATE");
+        println("WILL PLACE A PROJECTILE ON TARGET.  A HIT WITHIN " + ERROR_DISTANCE + " YARDS");
+        println("OF THE TARGET WILL DESTROY IT.");
+        println();
+        while (true) {
+            int maxRange = random.nextInt(40000) + 20000;
+            int enemyCount = 0;
+            int totalRounds = 0;
+            println("MAXIMUM RANGE OF YOUR GUN IS " + maxRange + " YARDS.\n");
+
+            while (true) {
+                int rounds = fightEnemy(maxRange);
+                totalRounds += rounds;
+
+                if (enemyCount == MAX_ENEMIES || rounds >= MAX_ROUNDS) {
+                    if (rounds < MAX_ROUNDS) {
+                        println("\n\n\nTOTAL ROUNDS EXPENDED WERE:" + totalRounds);
+                    }
+                    if (totalRounds > 18 || rounds >= MAX_ROUNDS) {
+                        println("BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!");
+                    } else {
+                        println("NICE SHOOTING !!");
+                    }
+                    println("\nTRY AGAIN (Y OR N)");
+                    String tryAgainResponse = scanner.nextLine();
+                    if ("Y".equals(tryAgainResponse) || "y".equals(tryAgainResponse)) {
+                        break;
+                    }
+                    println("\nOK.  RETURN TO BASE CAMP.");
+                    return;
+                }
+                enemyCount++;
+                println("\nTHE FORWARD OBSERVER HAS SIGHTED MORE ENEMY ACTIVITY...");
+            }
+        }
+    }
+
+    private static int fightEnemy(int maxRange) {
+        int rounds = 0;
+        long target = Math.round(maxRange * (random.nextDouble() * 0.8 + 0.1));
+        println("      DISTANCE TO THE TARGET IS " + target + " YARDS.");
+
+        while (true) {
+            println("\nELEVATION?");
+            double elevation = Double.parseDouble(scanner.nextLine());
+            if (elevation > 89.0) {
+                println("MAXIMUM ELEVATION IS 89 DEGREES.");
+                continue;
+            }
+            if (elevation < 1.0) {
+                println("MINIMUM ELEVATION IS ONE DEGREE.");
+                continue;
+            }
+            rounds++;
+            if (rounds >= MAX_ROUNDS) {
+                println("\nBOOM !!!!   YOU HAVE JUST BEEN DESTROYED ");
+                println("BY THE ENEMY.\n\n\n");
+                break;
+            }
+
+            long error = calculateError(maxRange, target, elevation);
+            if (Math.abs(error) < ERROR_DISTANCE) {
+                println("*** TARGET DESTROYED ***  " + rounds + " ROUNDS OF AMMUNITION EXPENDED.");
+                break;
+            } else if (error > ERROR_DISTANCE) {
+                println("SHORT OF TARGET BY " + Math.abs(error) + " YARDS.");
+            } else {
+                println("OVER TARGET BY " + Math.abs(error) + " YARDS.");
+            }
+
+        }
+        return rounds;
+    }
+
+    private static long calculateError(int maxRange, long target, double elevationInDegrees) {
+        double elevationInRadians = Math.PI * elevationInDegrees / 90.0; //convert degrees to radians
+        double impact = maxRange * Math.sin(elevationInRadians);
+        double error = target - impact;
+        return Math.round(error);
+    }
+
+    private static void println(String s) {
+        System.out.println(s);
+    }
+
+    private static void println() {
+        System.out.println();
+    }
+}

From 52c0db4cf270927596f18e448cdc5a3f15460735 Mon Sep 17 00:00:00 2001
From: Jack Boyce 
Date: Mon, 1 Mar 2021 15:01:11 -0800
Subject: [PATCH 155/749] cleanup and documentation

---
 84 Super Star Trek/python/superstartrek.py | 129 ++++++++++-----------
 1 file changed, 62 insertions(+), 67 deletions(-)

diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py
index 63a454c3..5133bacf 100644
--- a/84 Super Star Trek/python/superstartrek.py	
+++ b/84 Super Star Trek/python/superstartrek.py	
@@ -2,14 +2,15 @@
 # ****        **** STAR TREK ****        ****
 # **** SIMULATION OF A MISSION OF THE STARSHIP ENTERPRISE,
 # **** AS SEEN ON THE STAR TREK TV SHOW.
-# **** ORIGIONAL PROGRAM BY MIKE MAYFIELD, MODIFIED VERSION
+# **** ORIGINAL PROGRAM BY MIKE MAYFIELD, MODIFIED VERSION
 # **** PUBLISHED IN DEC'S "101 BASIC GAMES", BY DAVE AHL.
 # **** MODIFICATIONS TO THE LATTER (PLUS DEBUGGING) BY BOB
 # **** LEEDOM - APRIL & DECEMBER 1974,
 # **** WITH A LITTLE HELP FROM HIS FRIENDS . . .
 #
 # Python translation by Jack Boyce - 2/2021
-# Output is identical to BASIC version except for minor cleanup
+#   Output is identical to BASIC version except for a few
+#   fixes (as noted, search `bug`) and minor cleanup.
 
 
 import random
@@ -21,13 +22,6 @@ from math import sqrt
 # -------------------------------------------------------------------------
 
 
-def fnd(i):
-    # Find distance between Enterprise and i'th Klingon warship.
-    global k, s1, s2
-
-    return sqrt((k[i][0] - s1)**2 + (k[i][1] - s2)**2)
-
-
 def fnr():
     # Generate a random number from 0 to 7 inclusive.
     return random.randint(0, 7)
@@ -206,7 +200,8 @@ def navigation():
                 print(f"  AT SECTOR {s1 + 1} , {s2 + 1} OF QUADRANT "
                       f"{q1 + 1} , {q2 + 1}.'")
                 if t > t0 + t9:
-                    end_game()
+                    end_game(won=False, quit=False)
+                    return
             if 8 * q1 + q2 == 8 * q4 + q5:
                 break
             t += 1
@@ -232,7 +227,8 @@ def navigation():
         t8 = 0.1 * int(10 * w1)
     t += t8
     if t > t0 + t9:
-        end_game()
+        end_game(won=False, quit=False)
+        return
 
     short_range_scan()
 
@@ -254,7 +250,7 @@ def maneuver_energy(n):
 
 def short_range_scan():
     # Print a short range scan.
-    global docked, e, e0, p, p0, s
+    global docked, e, p, s
 
     docked = False
     for i in (s1 - 1, s1, s1 + 1):
@@ -314,7 +310,7 @@ def short_range_scan():
 
 def long_range_scan():
     # Print a long range scan.
-    global n, z
+    global z
 
     if d[2] < 0:
         print("LONG RANGE SENSORS ARE INOPERABLE")
@@ -343,7 +339,7 @@ def long_range_scan():
 
 def phaser_control():
     # Take phaser control input and fire phasers.
-    global d, e, k, k3, k9, qs, g, z, q1, q2
+    global e, k, g, z, k3, k9
 
     if d[3] < 0:
         print("PHASERS INOPERATIVE")
@@ -372,7 +368,7 @@ def phaser_control():
         print(f"ENERGY AVAILABLE = {e} UNITS")
 
     e -= x
-    if d[7] < 0:  # typo in original, was d[6]
+    if d[7] < 0:  # bug in original, was d[6]
         x *= random.random()
 
     h1 = int(x / k3)
@@ -397,7 +393,8 @@ def phaser_control():
                 g[q1][q2] -= 100
                 z[q1][q2] = g[q1][q2]
                 if k9 <= 0:
-                    end_game(won=True)
+                    end_game(won=True, quit=False)
+                    return
             else:
                 print(f"   (SENSORS SHOW {round(k[i][2],6)} UNITS REMAINING)")
 
@@ -406,7 +403,7 @@ def phaser_control():
 
 def photon_torpedoes():
     # Take photon torpedo input and process firing of torpedoes.
-    global p, d, c, e, s1, s2, k3, k9, b3, b9, t, t0, t9, docked, g, z
+    global e, p, k3, k9, k, b3, b9, docked, g, z
 
     if p <= 0:
         print("ALL PHOTON TORPEDOES EXPENDED")
@@ -452,7 +449,8 @@ def photon_torpedoes():
         k3 -= 1
         k9 -= 1
         if k9 <= 0:
-            end_game(won=True)
+            end_game(won=True, quit=False)
+            return
         for i in range(3):
             if x3 == k[i][0] and y3 == k[i][1]:
                 k[i][2] = 0
@@ -467,7 +465,8 @@ def photon_torpedoes():
         if b9 == 0 and k9 <= t - t0 - t9:
             print("THAT DOES IT, CAPTAIN!! YOU ARE HEREBY RELIEVED OF COMMAND")
             print("AND SENTENCED TO 99 STARDATES AT HARD LABOR ON CYGNUS 12!!")
-            end_game(quit=True)
+            end_game(won=False)
+            return
         else:
             print("STARFLEET COMMAND REVIEWING YOUR RECORD TO CONSIDER")
             print("COURT MARTIAL!")
@@ -479,9 +478,14 @@ def photon_torpedoes():
     klingons_fire()
 
 
+def fnd(i):
+    # Find distance between Enterprise and i'th Klingon warship.
+    return sqrt((k[i][0] - s1)**2 + (k[i][1] - s2)**2)
+
+
 def klingons_fire():
     # Process nearby Klingons firing on Enterprise.
-    global k3, s, k, docked, d
+    global s, k, d
 
     if k3 <= 0:
         return
@@ -499,7 +503,8 @@ def klingons_fire():
         print(f" {h} UNIT HIT ON ENTERPRISE FROM SECTOR "
               f"{k[i][0] + 1} , {k[i][1] + 1}")
         if s <= 0:
-            end_game(enterprise_killed=True)
+            end_game(won=False, quit=False, enterprise_killed=True)
+            return
         print(f"      ")
         if h >= 20 and random.random() < 0.60 and h / s > 0.02:
             r1 = fnr()
@@ -540,7 +545,7 @@ def shield_control():
 
 def damage_control():
     # Print a damage control report.
-    global d, docked, d4, t
+    global d, t
 
     if d[5] < 0:
         print('DAMAGE CONTROL REPORT NOT AVAILABLE')
@@ -737,8 +742,8 @@ def print_direction(from1, from2, to1, to2):
 
 def startup():
     # Initialize the game variables and map, and print startup messages.
-    global g, c, k, n, z, d, t, t0, t9, docked, e, e0, p, p0, s9
-    global s, b9, k7, k9, devices, q1, q2, s1, s2
+    global g, z, k, d, t, t0, t9, docked, e, e0, p, p0, s, k9, b9, s9, c
+    global devices, q1, q2, s1, s2, k7, restart
 
     print("\n\n\n\n\n\n\n\n\n\n\n"
           "                                    ,------*------,\n"
@@ -750,29 +755,30 @@ def startup():
           "\n\n\n\n")
 
     # set up global game variables
-    g = [[0] * 8 for _ in range(8)]
-    z = [[0] * 8 for _ in range(8)]
-    k = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
-    n = [0, 0, 0]
-    d = [0] * 8
-    t = t0 = 100 * random.randint(20, 39)
-    t9 = random.randint(25, 34)
-    docked = False
-    e = e0 = 3000
-    p = p0 = 10
-    s = 0
-    k9, b9 = 0, 0  # typo in original, was b9 = 2
-    s9 = 200
+    g = [[0] * 8 for _ in range(8)]         # galaxy map
+    z = [[0] * 8 for _ in range(8)]         # charted galaxy map
+    k = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]   # Klingons in current quadrant
+    d = [0] * 8                             # damage stats for devices
+    t = t0 = 100 * random.randint(20, 39)   # stardate (current, initial)
+    t9 = random.randint(25, 34)             # mission duration (stardates)
+    docked = False                          # docking flag
+    e = e0 = 3000                           # energy (current, initial)
+    p = p0 = 10                             # torpedoes (current, initial)
+    s = 0                                   # shields
+    k9, b9 = 0, 0                           # total Klingons, bases in galaxy
+    # ^ bug in original, was b9 = 2
+    s9 = 200                                # avg. Klingon shield strength
 
     c = [[0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1],
-         [1, 0], [1, 1], [0, 1]]
+         [1, 0], [1, 1], [0, 1]]            # vectors in cardinal directions
+
     devices = ['WARP ENGINES', 'SHORT RANGE SENSORS', 'LONG RANGE SENSORS',
                'PHASER CONTROL', 'PHOTON TUBES', 'DAMAGE CONTROL',
                'SHIELD CONTROL', 'LIBRARY-COMPUTER']
 
     # initialize Enterprise's position
-    q1, q2 = fnr(), fnr()
-    s1, s2 = fnr(), fnr()
+    q1, q2 = fnr(), fnr()                   # Enterprise's quadrant
+    s1, s2 = fnr(), fnr()                   # ...and sector
 
     # initialize contents of galaxy
     for i in range(8):
@@ -797,7 +803,7 @@ def startup():
     if k9 > t9:
         t9 = k9 + 1
 
-    if b9 == 0:
+    if b9 == 0:  # original has buggy extra code here
         b9 = 1
         g[q1][q2] += 10
         q1, q2 = fnr(), fnr()
@@ -815,7 +821,8 @@ def startup():
 
 def new_quadrant():
     # Enter a new quadrant: populate map and print a short range scan.
-    global k3, b3, s3, d4, b4, b5, z, g, q1, q2, t, t0, k, qs, s1, s2, s9
+    global g, z, k, t, t0, s9, q1, q2, s1, s2
+    global k3, b3, s3, d4, qs, b4, b5
 
     k3 = b3 = s3 = 0
     d4 = 0.5 * random.random()
@@ -851,9 +858,8 @@ def new_quadrant():
             insert_marker(r1, r2, '+K+')
             k[i] = [r1, r2, s9 * (0.5 + random.random())]
     if b3 > 0:
-        r1, r2 = find_empty_place()
-        insert_marker(r1, r2, '>!<')
-        b4, b5 = r1, r2
+        b4, b5 = find_empty_place()
+        insert_marker(b4, b5, '>!<')
     for i in range(s3):
         r1, r2 = find_empty_place()
         insert_marker(r1, r2, ' * ')
@@ -861,9 +867,9 @@ def new_quadrant():
     short_range_scan()
 
 
-def end_game(won=False, quit=False, enterprise_killed=False):
+def end_game(won=False, quit=True, enterprise_killed=False):
     # Handle end-of-game situations.
-    global k7, t, t0, b9
+    global t, t0, b9, k7, restart
 
     if won:
         print("CONGRATULATIONS, CAPTAIN! THE LAST KLINGON BATTLE CRUISER")
@@ -887,6 +893,7 @@ def end_game(won=False, quit=False, enterprise_killed=False):
     print("FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,")
     if input("LET HIM STEP FORWARD AND ENTER 'AYE'? ").upper() != 'AYE':
         exit()
+    restart = True
 
 
 # -------------------------------------------------------------------------
@@ -894,11 +901,16 @@ def end_game(won=False, quit=False, enterprise_killed=False):
 # -------------------------------------------------------------------------
 
 
+f = {'NAV': navigation, 'SRS': short_range_scan, 'LRS': long_range_scan,
+     'PHA': phaser_control, 'TOR': photon_torpedoes, 'SHE': shield_control,
+     'DAM': damage_control, 'COM': computer, 'XXX': end_game}
+
 while True:
     startup()
     new_quadrant()
+    restart = False
 
-    while True:
+    while not restart:
         if s + e <= 10 or (e <= 10 and d[6] != 0):
             print("\n** FATAL ERROR **   YOU'VE JUST STRANDED YOUR SHIP IN "
                   "SPACE\nYOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND "
@@ -907,25 +919,8 @@ while True:
 
         command = input('COMMAND? ').upper()
 
-        if command == 'NAV':
-            navigation()
-        elif command == 'SRS':
-            short_range_scan()
-        elif command == 'LRS':
-            long_range_scan()
-        elif command == 'PHA':
-            phaser_control()
-        elif command == 'TOR':
-            photon_torpedoes()
-        elif command == 'SHE':
-            shield_control()
-        elif command == 'DAM':
-            damage_control()
-        elif command == 'COM':
-            computer()
-        elif command == 'XXX':
-            end_game(quit=True)
-            break
+        if command in f:
+            f[command]()
         else:
             print("ENTER ONE OF THE FOLLOWING:\n"
                   "  NAV  (TO SET COURSE)\n"

From aa6b075165ca6c01aa3d9bfa6574a0ff5a7f5530 Mon Sep 17 00:00:00 2001
From: Alvaro Frias Garay 
Date: Mon, 1 Mar 2021 20:39:40 -0300
Subject: [PATCH 156/749] Added history comment and porting notes

---
 03 Animal/python/animal.py | 69 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 67 insertions(+), 2 deletions(-)

diff --git a/03 Animal/python/animal.py b/03 Animal/python/animal.py
index 99e55f45..65263917 100644
--- a/03 Animal/python/animal.py	
+++ b/03 Animal/python/animal.py	
@@ -1,6 +1,51 @@
+########################################################
+#
+# Animal
+#
+# From: Basic computer Games(1978)
+#
+#    Unlike other computer games in which the computer
+#   picks a number or letter and you must guess what it is,
+#   in this game you think of an animal and the computer asks
+#   you questions and tries to guess the name of your animal.
+#   If the computer guesses incorrectly, it will ask you for a
+#   question that differentiates the animal it guessed
+#   from the one you were thinking of. In this way the
+#   computer "learns" new animals. Questions to differentiate
+#   new animals should be input without a question mark.
+#    This version of the game does not have a SAVE feature.
+#   If your sistem allows, you may modify the program to
+#   save array A$, then reload the array  when you want
+#   to play the game again. This way you can save what the
+#   computer learns over a series of games.
+#    At any time if you reply 'LIST' to the question "ARE YOU
+#   THINKING OF AN ANIMAL", the computer will tell you all the
+#   animals it knows so far.
+#    The program starts originally by knowing only FISH and BIRD.
+#   As you build up a file of animals you should use broad,
+#   general questions first and then narrow down to more specific
+#   ones with later animals. For example, If an elephant was to be
+#   your first animal, the computer would ask for a question to distinguish
+#   an elephant from a bird. Naturally there are hundreds of possibilities,
+#   however, if you plan to build a large file of animals a good question
+#   would be "IS IT A MAMAL".
+#    This program can be easily modified to deal with categories of
+#   things other than animals by simply modifying the initial data
+#   in Line 530 and the dialogue references to animal in Lines 10,
+#   40, 50, 130, 230, 240 and 600. In an educational environment, this
+#   would be a valuable program to teach the distinguishing chacteristics
+#   of many classes of objects -- rock formations, geography, marine life,
+#   cell structures, etc.
+#    Originally developed by Arthur Luehrmann at Dartmouth College,
+#   Animal was subsequently shortened and modified by Nathan Teichholtz at
+#   DEC and Steve North at Creative Computing
+#
+########################################################
+
+
 class Node:
     """
-    Nodes of the binary tree of questions.
+    Node of the binary tree of questions.
     """
 
     def __init__(self, text, yes_node, no_node):
@@ -86,7 +131,8 @@ root = Node('Does it swim?', yes_child, no_child)
 
 # Main loop of game
 initial_message()
-keep_playing = parse_input('Are you thinking of an animal? ', True, root) == 'y'
+keep_playing = parse_input(
+    'Are you thinking of an animal? ', True, root) == 'y'
 while keep_playing:
     keep_asking = True
     # Start traversing the tree by the root
@@ -125,3 +171,22 @@ while keep_playing:
 
     keep_playing = parse_input(
         'Are you thinking of an animal? ', True, root) == 'y'
+
+
+########################################################
+# Porting Notes
+#
+#   The data structure used for storing questions and
+#   animals is a binary tree where each non-leaf node
+#   has a question, while the leafs store the animals.
+#
+#   As the original program, this program doesn't store
+#   old questions and animals. A good modification would
+#   be to add a database to store the tree.
+#    Also as the original program, this one can be easily
+#   modified to not only make guesses about animals, by
+#   modyfing the initial data of the tree, the questions
+#   that are asked to the user and the initial message
+#   function  (Lines 120 to 130, 135, 158, 160, 168, 173)
+
+########################################################

From b07bb30d8d6d83cfb1bab9c65ed40fa3ea366c5e Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 20:20:04 -0600
Subject: [PATCH 157/749] Ported MUGWUMP to Javascript

---
 62 Mugwump/javascript/mugwump.html |   9 +++
 62 Mugwump/javascript/mugwump.js   | 117 +++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 62 Mugwump/javascript/mugwump.html
 create mode 100644 62 Mugwump/javascript/mugwump.js

diff --git a/62 Mugwump/javascript/mugwump.html b/62 Mugwump/javascript/mugwump.html
new file mode 100644
index 00000000..1d590487
--- /dev/null
+++ b/62 Mugwump/javascript/mugwump.html	
@@ -0,0 +1,9 @@
+
+
+MUGWUMP
+
+
+

+
+
+
diff --git a/62 Mugwump/javascript/mugwump.js b/62 Mugwump/javascript/mugwump.js
new file mode 100644
index 00000000..6156064b
--- /dev/null
+++ b/62 Mugwump/javascript/mugwump.js	
@@ -0,0 +1,117 @@
+// MATH DICE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var p = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "MUGWUMP\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // Courtesy People's Computer Company
+    print("THE OBJECT OF THIS GAME IS TO FIND FOUR MUGWUMPS\n");
+    print("HIDDEN ON A 10 BY 10 GRID.  HOMEBASE IS POSITION 0,0.\n");
+    print("ANY GUESS YOU MAKE MUST BE TWO NUMBERS WITH EACH\n");
+    print("NUMBER BETWEEN 0 AND 9, INCLUSIVE.  FIRST NUMBER\n");
+    print("IS DISTANCE TO RIGHT OF HOMEBASE AND SECOND NUMBER\n");
+    print("IS DISTANCE ABOVE HOMEBASE.\n");
+    print("\n");
+    print("YOU GET 10 TRIES.  AFTER EACH TRY, I WILL TELL\n");
+    print("YOU HOW FAR YOU ARE FROM EACH MUGWUMP.\n");
+    print("\n");
+    while (1) {
+        for (i = 1; i <= 4; i++) {
+            p[i] = [];
+            for (j = 1; j <= 2; j++) {
+                p[i][j] = Math.floor(10 * Math.random());
+            }
+        }
+        t = 0;
+        do {
+            t++;
+            print("\n");
+            print("\n");
+            print("TURN NO. " + t + " -- WHAT IS YOUR GUESS");
+            str = await input();
+            m = parseInt(str);
+            n = parseInt(str.substr(str.indexOf(",") + 1));
+            for (i = 1; i <= 4; i++) {
+                if (p[i][1] == -1)
+                    continue;
+                if (p[i][1] == m && p[i][2] == n) {
+                    p[i][1] = -1;
+                    print("YOU HAVE FOUND MUGWUMP " + i + "\n");
+                } else {
+                    d = Math.sqrt(Math.pow(p[i][1] - m, 2) + Math.pow(p[i][2] - n, 2));
+                    print("YOU ARE " + Math.floor(d * 10) / 10 + " UNITS FROM MUGWUMP " + i + "\n");
+                }
+            }
+            for (j = 1; j <= 4; j++) {
+                if (p[j][1] != -1)
+                    break;
+            }
+            if (j > 4) {
+                print("\n");
+                print("YOU GOT THEM ALL IN " + t + " TURNS!\n");
+                break;
+            }
+        } while (t < 10) ;
+        if (t == 10) {
+            print("\n");
+            print("SORRY, THAT'S 10 TRIES.  HERE IS WHERE THEY'RE HIDING:\n");
+            for (i = 1; i <= 4; i++) {
+                if (p[i][1] != -1)
+                    print("MUGWUMP " + i + " IS AT (" + p[i][1] + "," + p[i][2] + ")\n");
+            }
+        }
+        print("\n");
+        print("THAT WAS FUN! LET'S PLAY AGAIN.......\n");
+        print("FOUR MORE MUGWUMPS ARE NOW IN HIDING.\n");
+    }
+}
+
+main();

From 61dcef249953aeacc04388753abf10af0904657c Mon Sep 17 00:00:00 2001
From: Swofty 
Date: Tue, 2 Mar 2021 13:36:06 +1100
Subject: [PATCH 158/749] Ported Number to Java

---
 66 Number/java/main.class | 69 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 66 Number/java/main.class

diff --git a/66 Number/java/main.class b/66 Number/java/main.class
new file mode 100644
index 00000000..c3df4ebf
--- /dev/null
+++ b/66 Number/java/main.class	
@@ -0,0 +1,69 @@
+
+import java.time.temporal.ValueRange;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.Scanner;
+
+public class Number {
+
+    public static int points = 0;
+
+    public static void printempty() { System.out.println(" "); }
+
+    public static void print(String toprint) { System.out.println(toprint); }
+
+    public static void main(String[] args) {
+        print("YOU HAVE 100 POINTS.  BY GUESSING NUMBERS FROM 1 TO 5, YOU");
+        print("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO");
+        print("A RANDOM NUMBER SELECTED BY THE COMPUTER.");
+        printempty();
+        print("YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)");
+        print("YOUR POINT COUNT.  YOU WIN WHEN YOU GET 500 POINTS.");
+        printempty();
+
+        try {
+            while (true) {
+                print("GUESS A NUMBER FROM 1 TO 5");
+
+
+                Scanner numbersc = new Scanner(System.in);
+                String numberstring = numbersc.nextLine();
+
+                int number = Integer.parseInt(numberstring);
+
+                if (!(number < 1| number > 5)) {
+
+                    Random rand = new Random();
+
+                    int randomNum = rand.nextInt((5 - 1) + 1) + 1;
+
+                    if (randomNum == number) {
+                        print("YOU HIT THE JACKPOT!!!");
+                        points = points * 2;
+                    } else if(ValueRange.of(randomNum, randomNum + 1).isValidIntValue(number)) {
+                        print("+5");
+                        points = points + 5;
+                    } else if(ValueRange.of(randomNum - 1, randomNum + 2).isValidIntValue(number)) {
+                        print("+1");
+                        points = points + 1;
+                    } else if(ValueRange.of(randomNum - 3, randomNum + 1).isValidIntValue(number)) {
+                        print("-1");
+                        points = points - 1;
+                    } else {
+                        print("-half");
+                        points = (int) (points * 0.5);
+                    }
+
+                    print("YOU HAVE " + points + " POINTS.");
+                }
+
+                if (points >= 500) {
+                    print("!!!!YOU WIN!!!! WITH " + points + " POINTS.");
+                    return;
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

From d4b22b8786064a5dfa5b0001cd1cae0d2dbb507c Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Tue, 2 Mar 2021 13:14:37 +1030
Subject: [PATCH 159/749] Pizza Java version bugfix

Previous commit had some missing output that was caused by a lazy search/replace (my bad).
---
 69 Pizza/java/src/Pizza.java | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/69 Pizza/java/src/Pizza.java b/69 Pizza/java/src/Pizza.java
index 55bf8ceb..c3986c81 100644
--- a/69 Pizza/java/src/Pizza.java	
+++ b/69 Pizza/java/src/Pizza.java	
@@ -125,7 +125,7 @@ public class Pizza {
                     currentHouseDelivery = (int) (Math.random()
                             * (houses.length) + 1) - 1; // Deduct 1 for 0-based array
 
-                    System.out.println("HELLO " + playerName + "'S PIZZA.  IS "
+                    System.out.println("HELLO " + playerName + "'S PIZZA.  THIS IS "
                             + houses[currentHouseDelivery] + ".");
                     System.out.println("  PLEASE SEND A PIZZA.");
                     gameState = GAME_STATE.DELIVER_PIZZA;
@@ -145,7 +145,7 @@ public class Pizza {
 
                     // Did the player select the right house to deliver?
                     if (calculatedPos == currentHouseDelivery) {
-                        System.out.println("HELLO " + playerName + ".  IS " + houses[currentHouseDelivery]
+                        System.out.println("HELLO " + playerName + ".  THIS IS " + houses[currentHouseDelivery]
                                 + ", THANKS FOR THE PIZZA.");
                         pizzaDeliveryCount++;
 
@@ -157,7 +157,7 @@ public class Pizza {
                             gameState = GAME_STATE.START_DELIVER;
                         }
                     } else {
-                        System.out.println("IS " + houses[calculatedPos] + ".  I DID NOT ORDER A PIZZA.");
+                        System.out.println("THIS IS " + houses[calculatedPos] + ".  I DID NOT ORDER A PIZZA.");
                         System.out.println("I LIVE AT " + x + "," + y);
                         // Don't change gameState so state is executed again
                     }
@@ -238,7 +238,7 @@ public class Pizza {
         System.out.println("DELIVERED.  THEN A DELIVERY BOY WILL");
         System.out.println("ASK YOU FOR THE LOCATION.");
         System.out.println("     EXAMPLE:");
-        System.out.println("IS J.  PLEASE SEND A PIZZA.");
+        System.out.println("THIS IS J.  PLEASE SEND A PIZZA.");
         System.out.println("DRIVER TO " + playerName + ".  WHERE DOES J LIVE?");
         System.out.println("YOUR ANSWER WOULD BE 2,3");
         System.out.println();

From f6f70f1fd9c6369e988dd22ca4e58efc895b38a8 Mon Sep 17 00:00:00 2001
From: vashli300 <78328791+vashli300@users.noreply.github.com>
Date: Tue, 2 Mar 2021 13:57:30 +1100
Subject: [PATCH 160/749] Added C Sharp port

---
 57 Literature Quiz/csharp/litquiz.cs | 155 +++++++++++++++++++++++++++
 1 file changed, 155 insertions(+)
 create mode 100644 57 Literature Quiz/csharp/litquiz.cs

diff --git a/57 Literature Quiz/csharp/litquiz.cs b/57 Literature Quiz/csharp/litquiz.cs
new file mode 100644
index 00000000..52d2d160
--- /dev/null
+++ b/57 Literature Quiz/csharp/litquiz.cs	
@@ -0,0 +1,155 @@
+using System;
+
+namespace litquiz
+{
+    class litquiz
+    {
+        public static int Score = 0;
+      
+
+        public static void Main(string[] args)
+        {
+
+            //Print the title and intro
+
+            Console.WriteLine("                         LITERATURE QUIZ");
+            Console.WriteLine("               CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE");
+            Console.WriteLine();
+            Console.WriteLine("THIS IS A MULTIPLE-CHOICE QUIZ");
+            Console.WriteLine("TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK.");
+            Console.WriteLine();
+            Console.WriteLine("GOOD LUCK!");
+            Console.WriteLine();
+            Console.WriteLine();
+            One();
+
+   
+
+        }
+
+        public static void One() {
+            Console.WriteLine("IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT");
+            Console.WriteLine("1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO");
+
+            string answerOne;
+            answerOne = Console.ReadLine();
+
+            if(answerOne == "4")
+            {
+                Console.WriteLine("VERY GOOD! HERE'S ANOTHER.");
+                Score = Score + 1;
+                Two();
+            }
+            else
+            {
+                Console.WriteLine("SORRY...FIGARO WAS HIS NAME.");
+                Two();
+            }
+            
+        }
+
+        public static void Two()
+        {
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?");
+            Console.WriteLine("1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S");
+
+            string answerTwo;
+            answerTwo = Console.ReadLine();
+
+            if(answerTwo == "2")
+            {
+                Console.WriteLine("PRETTY GOOD!");
+                Score = Score + 1;
+                Three();
+            }
+            else
+            {
+                Console.WriteLine("TOO BAD...IT WAS ELMER FUDD'S GARDEN.");
+                Three();
+            }
+        }
+
+        public static void Three()
+        {
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED");
+            Console.WriteLine("1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO");
+
+            string answerThree;
+            answerThree = Console.ReadLine();
+            
+            if(answerThree == "4")
+            {
+                Console.WriteLine("YEA!  YOU'RE A REAL LITERATURE GIANT.");
+                Score = Score + 1;
+                Four();
+            }
+            else
+            {
+                Console.WriteLine("BACK TO THE BOOKS,...TOTO WAS HIS NAME.");
+                Four();
+            }
+
+
+
+
+        }
+
+        public static void Four()
+        {
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE");
+            Console.WriteLine("1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY");
+
+            string answerFour;
+            answerFour = Console.ReadLine();
+
+            if(answerFour == "3")
+            {
+                Console.WriteLine("GOOD MEMORY!");
+                Score = Score + 1;
+                End();
+            }
+            else
+            {
+                Console.WriteLine("OH, COME ON NOW...IT WAS SNOW WHITE.");
+                End();
+            }
+
+        }
+
+        public static void End()
+        {
+            Console.WriteLine();
+            Console.WriteLine();
+            if(Score == 4)
+            {
+                Console.WriteLine("WOW!  THAT'S SUPER!  YOU REALLY KNOW YOUR NURSERY");
+                Console.WriteLine("YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE");
+                Console.WriteLine("LITERATURE (HA, HA, HA)");
+                return;
+            }
+            else if(Score == 3)
+            {
+                Console.WriteLine("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME");
+                Console.WriteLine("READING THE NURSERY GREATS.");
+                return;
+            }
+            else
+            {
+                Console.WriteLine("UGH.  THAT WAS DEFINITELY NOT TOO SWIFT.  BACK TO");
+                Console.WriteLine("NURSERY SCHOOL FOR YOU, MY FRIEND.");
+                return;
+            }
+        }
+
+	}
+}

From cc8c251b49414a0961aad3993fced1db7bd806f2 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 20:59:08 -0600
Subject: [PATCH 161/749] Ported NAME to Javascript

---
 62 Mugwump/javascript/mugwump.js |  2 +-
 63 Name/javascript/name.html     |  9 ++++
 63 Name/javascript/name.js       | 93 ++++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 63 Name/javascript/name.html
 create mode 100644 63 Name/javascript/name.js

diff --git a/62 Mugwump/javascript/mugwump.js b/62 Mugwump/javascript/mugwump.js
index 6156064b..06f0adb9 100644
--- a/62 Mugwump/javascript/mugwump.js	
+++ b/62 Mugwump/javascript/mugwump.js	
@@ -1,4 +1,4 @@
-// MATH DICE
+// MUGWUMP
 //
 // Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
 //
diff --git a/63 Name/javascript/name.html b/63 Name/javascript/name.html
new file mode 100644
index 00000000..bed003f4
--- /dev/null
+++ b/63 Name/javascript/name.html	
@@ -0,0 +1,9 @@
+
+
+NAME
+
+
+

+
+
+
diff --git a/63 Name/javascript/name.js b/63 Name/javascript/name.js
new file mode 100644
index 00000000..cfa33cf4
--- /dev/null
+++ b/63 Name/javascript/name.js	
@@ -0,0 +1,93 @@
+// NAME
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var str;
+var b;
+
+// Main program
+async function main()
+{
+    print(tab(34) + "NAME\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("HELLO.\n");
+    print("MY NAME IS CREATIVE COMPUTER.\n");
+    print("WHAT'S YOUR NAME (FIRST AND LAST)");
+    str = await input();
+    l = str.length;
+    print("\n");
+    print("THANK YOU, ");
+    for (i = l; i >= 1; i--)
+        print(str[i - 1]);
+    print(".\n");
+    print("OOPS!  I GUESS I GOT IT BACKWARDS.  A SMART\n");
+    print("COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!\n");
+    print("\n");
+    print("BUT I JUST NOTICED YOUR LETTERS ARE OUT OF ORDER.\n");
+    print("LET'S PUT THEM IN ORDER LIKE THIS: ");
+    b = [];
+    for (i = 1; i <= l; i++)
+        b[i - 1] = str.charCodeAt(i - 1);
+    b.sort();
+    for (i = 1; i <= l; i++)
+        print(String.fromCharCode(b[i - 1]));
+    print("\n");
+    print("\n");
+    print("DON'T YOU LIKE THAT BETTER");
+    ds = await input();
+    if (ds == "YES") {
+        print("\n");
+        print("I KNEW YOU'D AGREE!!\n");
+    } else {
+        print("\n");
+        print("I'M SORRY YOU DON'T LIKE IT THAT WAY.\n");
+    }
+    print("\n");
+    print("I REALLY ENJOYED MEETING YOU " + str + ".\n");
+    print("HAVE A NICE DAY!\n");
+}
+
+main();

From 35917f6e8c76c0e8d32b74b1e8d1cd8580ade109 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 21:07:19 -0600
Subject: [PATCH 162/749] Ported NICOMACHUS to Javascript

---
 64 Nicomachus/javascript/nicomachus.html |  9 +++
 64 Nicomachus/javascript/nicomachus.js   | 91 ++++++++++++++++++++++++
 2 files changed, 100 insertions(+)
 create mode 100644 64 Nicomachus/javascript/nicomachus.html
 create mode 100644 64 Nicomachus/javascript/nicomachus.js

diff --git a/64 Nicomachus/javascript/nicomachus.html b/64 Nicomachus/javascript/nicomachus.html
new file mode 100644
index 00000000..2fe069f8
--- /dev/null
+++ b/64 Nicomachus/javascript/nicomachus.html	
@@ -0,0 +1,9 @@
+
+
+NICOMACHUS
+
+
+

+
+
+
diff --git a/64 Nicomachus/javascript/nicomachus.js b/64 Nicomachus/javascript/nicomachus.js
new file mode 100644
index 00000000..7abe1d51
--- /dev/null
+++ b/64 Nicomachus/javascript/nicomachus.js	
@@ -0,0 +1,91 @@
+// NICOMACHUS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var str;
+var b;
+
+// Main program
+async function main()
+{
+    print(tab(33) + "NICOMA\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("BOOMERANG PUZZLE FROM ARITHMETICA OF NICOMACHUS -- A.D. 90!\n");
+    while (1) {
+        print("\n");
+        print("PLEASE THINK OF A NUMBER BETWEEN 1 AND 100.\n");
+        print("YOUR NUMBER DIVIDED BY 3 HAS A REMAINDER OF");
+        a = parseInt(await input());
+        print("YOUR NUMBER DIVIDED BY 5 HAS A REMAINDER OF");
+        b = parseInt(await input());
+        print("YOUR NUMBER DIVIDED BY 7 HAS A REMAINDER OF");
+        c = parseInt(await input());
+        print("\n");
+        print("LET ME THINK A MOMENT...\n");
+        print("\n");
+        d = 70 * a + 21 * b + 15 * c;
+        while (d > 105)
+            d -= 105;
+        print("YOUR NUMBER WAS " + d + ", RIGHT");
+        while (1) {
+            str = await input();
+            print("\n");
+            if (str == "YES") {
+                print("HOW ABOUT THAT!!\n");
+                break;
+            } else if (str == "NO") {
+                print("I FEEL YOUR ARITHMETIC IS IN ERROR.\n");
+                break;
+            } else {
+                print("EH?  I DON'T UNDERSTAND '" + str + "'  TRY 'YES' OR 'NO'.\n");
+            }
+        }
+        print("\n");
+        print("LET'S TRY ANOTHER.\n");
+    }
+}
+
+main();

From eb8faf970285c07fcd8aa8e5f8e4481fddcdf312 Mon Sep 17 00:00:00 2001
From: Nahid Mondol 
Date: Mon, 1 Mar 2021 22:39:44 -0500
Subject: [PATCH 163/749] War.java (not done yet)

---
 94 War/java/War.java | 120 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)
 create mode 100644 94 War/java/War.java

diff --git a/94 War/java/War.java b/94 War/java/War.java
new file mode 100644
index 00000000..622adb30
--- /dev/null
+++ b/94 War/java/War.java	
@@ -0,0 +1,120 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Scanner;
+
+/**
+ * Converted FROM BASIC to Java by Nahid Mondol
+ * 
+ * Based on Trevor Hobsons approach
+ */
+public class War {
+
+    private static final int CARD_DECK_SIZE = 52;
+    private static int totalPlayerScore = 0;
+    private static int totalComputerScore = 0;
+    private static boolean directionPhase;
+    static Scanner input = new Scanner(System.in);
+    static ArrayList cards = new ArrayList(
+            Arrays.asList("S-2", "H-2", "C-2", "D-2", "S-3", "H-3", "C-3", "D-3", "S-4", "H-4", "C-4", "D-4", "S-5",
+                    "H-5", "C-5", "D-5", "S-6", "H-6", "C-6", "D-6", "S-7", "H-7", "C-7", "D-7", "S-8", "H-8", "C-8",
+                    "D-8", "S-9", "H-9", "C-9", "D-9", "S-10", "H-10", "C-10", "D-10", "S-J", "H-J", "C-J", "D-J",
+                    "S-Q", "H-Q", "C-Q", "D-Q", "S-K", "H-K", "C-K", "D-K", "S-A", "H-A", "C-A", "D-A"));
+
+    public static void main(String[] args) {
+        System.out.println("\t         WAR");
+        System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+        System.out.println("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#");
+        System.out.print("AS S-7 FOR SPADE 7. DO YOU WANT DIRECTIONS? ");
+
+        while (!directionPhase) {
+            getDirections(input);
+        }
+        System.out.println();
+        playGame();
+    }
+
+    private static void getDirections(Scanner userInput) {
+        switch (userInput.nextLine().toLowerCase()) {
+            case "yes":
+                System.out.println("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD");
+                System.out.println("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO ");
+                System.out.println("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.");
+                directionPhase = true;
+                break;
+            case "no":
+                directionPhase = true;
+                break;
+            default:
+                System.out.print("YES OR NO, PLEASE.   ");
+        }
+    }
+
+    private static void playGame() {
+
+        Collections.shuffle(cards);
+
+        // Since the cards are already suffled, pull each card from the deck starting
+        // until it is empty or until the user quits.
+        for (int i = 1; i <= CARD_DECK_SIZE; i += 2) {
+            System.out.println("YOU: " + cards.get(i - 1) + "\t " + "COMPUTER: " + cards.get(i));
+            getWinner(cards.get(i - 1), cards.get(i));
+            // if(endGame) {
+            // break;
+            // }
+        }
+        System.out.println("WE HAVE RUN OUT OF CARDS. FINAL SCORE:  YOU: " + getPlayerScore() + " COMPUTER: "
+                + getComputerScore());
+        System.out.println("THANKS FOR PLAYING.  IT WAS FUN.");
+    }
+
+    private static void getWinner(String playerCard, String computerCard) {
+
+        String playerScore = (playerCard.length() == 3) ? Character.toString(playerCard.charAt(2))
+                : playerCard.substring(2, 4);
+        String computerScore = (computerCard.length() == 3) ? Character.toString(computerCard.charAt(2))
+                : computerCard.substring(2, 4);
+
+        if (Integer.parseInt(checkCourtCards(playerScore)) > Integer.parseInt(checkCourtCards(computerScore))) {
+            System.out.println("YOU WIN.   YOU HAVE " + playerWonRound() + "   COMPUTER HAS " + getComputerScore());
+        } else if (Integer.parseInt(checkCourtCards(playerScore)) < Integer.parseInt(checkCourtCards(computerScore))) {
+            System.out.println(
+                    "COMPUTER WINS!!!   YOU HAVE " + getPlayerScore() + "   COMPUTER HAS " + computerWonRound());
+        } else {
+            System.out.println("TIE.  NO SCORE CHANGE");
+        }
+
+        System.out.println("DO YOU WANT TO CONTINUE? ");
+    }
+
+    private static String checkCourtCards(String score) {
+        switch (score) {
+            case "J":
+                return "11";
+            case "Q":
+                return "12";
+            case "K":
+                return "13";
+            case "A":
+                return "14";
+            default:
+                return score;
+        }
+    }
+
+    private static int playerWonRound() {
+        return totalPlayerScore += 1;
+    }
+
+    private static int getPlayerScore() {
+        return totalPlayerScore;
+    }
+
+    private static int computerWonRound() {
+        return totalComputerScore += 1;
+    }
+
+    private static int getComputerScore() {
+        return totalComputerScore;
+    }
+}
\ No newline at end of file

From 42876f41c8e069b8d897a345a7946be3566f316f Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 21:48:52 -0600
Subject: [PATCH 164/749] Ported NIM to Javascript

---
 65 Nim/javascript/nim.html |   9 ++
 65 Nim/javascript/nim.js   | 270 +++++++++++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+)
 create mode 100644 65 Nim/javascript/nim.html
 create mode 100644 65 Nim/javascript/nim.js

diff --git a/65 Nim/javascript/nim.html b/65 Nim/javascript/nim.html
new file mode 100644
index 00000000..db914b25
--- /dev/null
+++ b/65 Nim/javascript/nim.html	
@@ -0,0 +1,9 @@
+
+
+NIM
+
+
+

+
+
+
diff --git a/65 Nim/javascript/nim.js b/65 Nim/javascript/nim.js
new file mode 100644
index 00000000..847c049a
--- /dev/null
+++ b/65 Nim/javascript/nim.js	
@@ -0,0 +1,270 @@
+// NIM
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a = [];
+var b = [];
+var d = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "NIM\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 1; i <= 100; i++) {
+        a[i] = 0;
+        b[i] = [];
+        for (j = 0; j <= 10; j++)
+            b[i][j] = 0;
+    }
+    d[0] = 0;
+    d[1] = 0;
+    d[2] = 0;
+    print("DO YOU WANT INSTRUCTIONS");
+    while (1) {
+        str = await input();
+        str = str.toUpperCase();
+        if (str == "YES" || str == "NO")
+            break;
+        print("PLEASE ANSWER YES OR NO\n");
+    }
+    if (str == "YES") {
+        print("THE GAME IS PLAYED WITH A NUMBER OF PILES OF OBJECTS.\n");
+        print("ANY NUMBER OF OBJECTS ARE REMOVED FROM ONE PILE BY YOU AND\n");
+        print("THE MACHINE ALTERNATELY.  ON YOUR TURN, YOU MAY TAKE\n");
+        print("ALL THE OBJECTS THAT REMAIN IN ANY PILE, BUT YOU MUST\n");
+        print("TAKE AT LEAST ONE OBJECT, AND YOU MAY TAKE OBJECTS FROM\n");
+        print("ONLY ONE PILE ON A SINGLE TURN.  YOU MUST SPECIFY WHETHER\n");
+        print("WINNING IS DEFINED AS TAKING OR NOT TAKING THE LAST OBJECT,\n");
+        print("THE NUMBER OF PILES IN THE GAME, AND HOW MANY OBJECTS ARE\n");
+        print("ORIGINALLY IN EACH PILE.  EACH PILE MAY CONTAIN A\n");
+        print("DIFFERENT NUMBER OF OBJECTS.\n");
+        print("THE MACHINE WILL SHOW ITS MOVE BY LISTING EACH PILE AND THE\n");
+        print("NUMBER OF OBJECTS REMAINING IN THE PILES AFTER  EACH OF ITS\n");
+        print("MOVES.\n");
+    }
+    while (1) {
+        print("\n");
+        while (1) {
+            print("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST");
+            w = parseInt(await input());
+            if (w == 1 || w == 2)
+                break;
+        }
+        while (1) {
+            print("ENTER NUMBER OF PILES");
+            n = parseInt(await input());
+            if (n >= 1 && n <= 100)
+                break;
+        }
+        print("ENTER PILE SIZES\n");
+        for (i = 1; i <= n; i++) {
+            while (1) {
+                print(i + " ");
+                a[i] = parseInt(await input());
+                if (a[i] >= 1 && a[i] <= 2000)
+                    break;
+            }
+        }
+        print("DO YOU WANT TO MOVE FIRST");
+        while (1) {
+            str = await input();
+            str = str.toUpperCase();
+            if (str == "YES" || str == "NO")
+                break;
+            print("PLEASE ANSWER YES OR NO.\n");
+        }
+        if (str == "YES")
+            player_first = true;
+        else
+            player_first = false;
+        while (1) {
+            if (!player_first) {
+                if (w != 1) {
+                    c = 0;
+                    for (i = 1; i <= n; i++) {
+                        if (a[i] == 0)
+                            continue;
+                        c++;
+                        if (c == 3)
+                            break;
+                        d[c] = i;
+                    }
+                    if (i > n) {
+                        if (c == 2) {
+                            if (a[d[1]] == 1 || a[d[2]] == 1) {
+                                print("MACHINE WINS\n");
+                                break;
+                            }
+                        } else {
+                            if (a[d[1]] > 1)
+                                print("MACHINE WINS\n");
+                            else
+                                print("MACHINE LOSES\n");
+                            break;
+                        }
+                        
+                    } else {
+                        c = 0;
+                        for (i = 1; i <= n; i++) {
+                            if (a[i] > 1)
+                                break;
+                            if (a[i] == 0)
+                                continue;
+                            c++;
+                        }
+                        if (i > n && c % 2) {
+                            print("MACHINE LOSES\n");
+                            break;
+                        }
+                    }
+                }
+                for (i = 1; i <= n; i++) {
+                    e = a[i];
+                    for (j = 0; j <= 10; j++) {
+                        f = e / 2;
+                        b[i][j] = 2 * (f - Math.floor(f));
+                        e = Math.floor(f);
+                    }
+                }
+                for (j = 10; j >= 0; j--) {
+                    c = 0;
+                    h = 0;
+                    for (i = 1; i <= n; i++) {
+                        if (b[i][j] == 0)
+                            continue;
+                        c++;
+                        if (a[i] <= h)
+                            continue;
+                        h = a[i];
+                        g = i;
+                    }
+                    if (c % 2)
+                        break;
+                }
+                if (j < 0) {
+                    do {
+                        e = Math.floor(n * Math.random() + 1);
+                    } while (a[e] == 0) ;
+                    f = Math.floor(a[e] * Math.random() + 1);
+                    a[e] -= f;
+                } else {
+                    a[g] = 0;
+                    for (j = 0; j <= 10; j++) {
+                        b[g][j] = 0;
+                        c = 0;
+                        for (i = 1; i <= n; i++) {
+                            if (b[i][j] == 0)
+                                continue;
+                            c++;
+                        }
+                        a[g] = a[g] + (c % 2) * Math.pow(2, j);
+                    }
+                    if (w != 1) {
+                        c = 0;
+                        for (i = 1; i <= n; i++) {
+                            if (a[i] > 1)
+                                break;
+                            if (a[i] == 0)
+                                continue;
+                            c++;
+                        }
+                        if (i > n && c % 2 == 0)
+                            a[g] = 1 - a[g];
+                    }
+                }
+                print("PILE  SIZE\n");
+                for (i = 1; i <= n; i++)
+                    print(" " + i + "  " + a[i] + "\n");
+                if (w != 2) {
+                    if (game_completed()) {
+                        print("MACHINE WINS");
+                        break;
+                    }
+                }
+            } else {
+                player_first = false;
+            }
+            while (1) {
+                print("YOUR MOVE - PILE , NUMBER TO BE REMOVED");
+                str = await input();
+                x = parseInt(str);
+                y = parseInt(str.substr(str.indexOf(",") + 1));
+                if (x < 1 || x > n)
+                    continue;
+                if (y < 1 || y > a[x])
+                    continue;
+                break;
+            }
+            a[x] -= y;
+            if (game_completed()) {
+                print("MACHINE LOSES");
+                break;
+            }
+        }
+        print("DO YOU WANT TO PLAY ANOTHER GAME");
+        while (1) {
+            str = await input();
+            str = str.toUpperCase();
+            if (str == "YES" || str == "NO")
+                break;
+            print("PLEASE ANSWER YES OR NO.\n");
+        }
+        if (str == "NO")
+            break;
+    }
+}
+
+function game_completed()
+{
+    for (var i = 1; i <= n; i++) {
+        if (a[i] != 0)
+            return false;
+    }
+    return true;
+}
+
+main();

From 9b949f009ab1c448b1cd1064b12730e8ae61114e Mon Sep 17 00:00:00 2001
From: vashli300 <78328791+vashli300@users.noreply.github.com>
Date: Tue, 2 Mar 2021 14:53:23 +1100
Subject: [PATCH 165/749] Update litquiz.cs

Make it more accurate to the original BASIC code
---
 57 Literature Quiz/csharp/litquiz.cs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/57 Literature Quiz/csharp/litquiz.cs b/57 Literature Quiz/csharp/litquiz.cs
index 52d2d160..0b9a7737 100644
--- a/57 Literature Quiz/csharp/litquiz.cs	
+++ b/57 Literature Quiz/csharp/litquiz.cs	
@@ -137,16 +137,16 @@ namespace litquiz
                 Console.WriteLine("LITERATURE (HA, HA, HA)");
                 return;
             }
-            else if(Score == 3)
+            else if(Score < 2)
             {
-                Console.WriteLine("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME");
-                Console.WriteLine("READING THE NURSERY GREATS.");
+                Console.WriteLine("UGH.  THAT WAS DEFINITELY NOT TOO SWIFT.  BACK TO");
+                Console.WriteLine("NURSERY SCHOOL FOR YOU, MY FRIEND.");
                 return;
             }
             else
             {
-                Console.WriteLine("UGH.  THAT WAS DEFINITELY NOT TOO SWIFT.  BACK TO");
-                Console.WriteLine("NURSERY SCHOOL FOR YOU, MY FRIEND.");
+                Console.WriteLine("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME");
+                Console.WriteLine("READING THE NURSERY GREATS.");
                 return;
             }
         }

From d9abcf29d5b492980bb501796c06a50fbef960e4 Mon Sep 17 00:00:00 2001
From: Nahid Mondol 
Date: Mon, 1 Mar 2021 22:59:03 -0500
Subject: [PATCH 166/749] port War to Java

---
 94 War/java/War.java | 42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/94 War/java/War.java b/94 War/java/War.java
index 622adb30..ebe7ffca 100644
--- a/94 War/java/War.java	
+++ b/94 War/java/War.java	
@@ -52,20 +52,34 @@ public class War {
 
     private static void playGame() {
 
+        boolean endedEarly = false;
+
+        // Shuffle the deck of cards
         Collections.shuffle(cards);
 
-        // Since the cards are already suffled, pull each card from the deck starting
-        // until it is empty or until the user quits.
+        // Since the cards are already suffled, pull each card from the deck
+        // until the deck is empty or until the user quits.
         for (int i = 1; i <= CARD_DECK_SIZE; i += 2) {
             System.out.println("YOU: " + cards.get(i - 1) + "\t " + "COMPUTER: " + cards.get(i));
             getWinner(cards.get(i - 1), cards.get(i));
-            // if(endGame) {
-            // break;
+            System.out.print("DO YOU WANT TO CONTINUE? ");
+            // while (isInvalidInput) {
+            if (isGameEnded()) {
+                endedEarly = true;
+                break;
+            }
             // }
         }
-        System.out.println("WE HAVE RUN OUT OF CARDS. FINAL SCORE:  YOU: " + getPlayerScore() + " COMPUTER: "
-                + getComputerScore());
-        System.out.println("THANKS FOR PLAYING.  IT WAS FUN.");
+
+        if (endedEarly) {
+            System.out.println("YOU HAVE ENDED THE GAME. FINAL SCORE:  YOU: " + getPlayerScore() + " COMPUTER: "
+                    + getComputerScore());
+            System.out.println("THANKS FOR PLAYING.  IT WAS FUN.");
+        } else {
+            System.out.println("WE HAVE RUN OUT OF CARDS. FINAL SCORE:  YOU: " + getPlayerScore() + " COMPUTER: "
+                    + getComputerScore());
+            System.out.println("THANKS FOR PLAYING.  IT WAS FUN.");
+        }
     }
 
     private static void getWinner(String playerCard, String computerCard) {
@@ -83,8 +97,6 @@ public class War {
         } else {
             System.out.println("TIE.  NO SCORE CHANGE");
         }
-
-        System.out.println("DO YOU WANT TO CONTINUE? ");
     }
 
     private static String checkCourtCards(String score) {
@@ -102,6 +114,18 @@ public class War {
         }
     }
 
+    private static boolean isGameEnded() {
+        switch (input.nextLine().toLowerCase()) {
+            case "yes":
+                return false;
+            case "no":
+                return true;
+            default:
+                System.out.print("YES OR NO, PLEASE.   ");
+                return false;
+        }
+    }
+
     private static int playerWonRound() {
         return totalPlayerScore += 1;
     }

From 479fc68057d2b9a19f9c7daeac0699cc88aee488 Mon Sep 17 00:00:00 2001
From: Nahid Mondol 
Date: Mon, 1 Mar 2021 23:00:23 -0500
Subject: [PATCH 167/749] corrected spelling mistake "contine" to "continue"

---
 94 War/python/war.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/94 War/python/war.py b/94 War/python/war.py
index ebd87036..f512a6fa 100755
--- a/94 War/python/war.py	
+++ b/94 War/python/war.py	
@@ -63,7 +63,7 @@ def main():
     if input("Do you want directions ").lower().startswith("y"):
         print("The computer gives you and it a 'card'. The higher card")
         print("(numerically) wins. The game ends when you choose not to")
-        print("contine or when you have finished the pack.")
+        print("continue or when you have finished the pack.")
 
     keep_playing = True
     while keep_playing:

From 7fb1849aa44335433be3c69eb4ca6f7ad6e06c93 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 22:00:27 -0600
Subject: [PATCH 168/749] Ported NUMBER to Javascript

---
 66 Number/javascript/number.html |  9 ++++
 66 Number/javascript/number.js   | 93 ++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)
 create mode 100644 66 Number/javascript/number.html
 create mode 100644 66 Number/javascript/number.js

diff --git a/66 Number/javascript/number.html b/66 Number/javascript/number.html
new file mode 100644
index 00000000..5e384186
--- /dev/null
+++ b/66 Number/javascript/number.html	
@@ -0,0 +1,9 @@
+
+
+NUMBER
+
+
+

+
+
+
diff --git a/66 Number/javascript/number.js b/66 Number/javascript/number.js
new file mode 100644
index 00000000..5bda2ae6
--- /dev/null
+++ b/66 Number/javascript/number.js	
@@ -0,0 +1,93 @@
+// NUMBER
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "NUMBER\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("YOU HAVE 100 POINTS.  BY GUESSING NUMBERS FROM 1 TO 5, YOU\n");
+    print("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO\n");
+    print("A RANDOM NUMBER SELECTED BY THE COMPUTER.\n");
+    print("\n");
+    print("YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)\n");
+    print("YOUR POINT COUNT.  YOU WIN WHEN YOU GET 500 POINTS.\n");
+    print("\n");
+    p = 0;
+    while (1) {
+        do {
+            print("GUESS A NUMBER FROM 1 TO 5");
+            g = parseInt(await input());
+        } while (g < 1 || g > 5) ;
+        r = Math.floor(5 * Math.random() + 1);
+        s = Math.floor(5 * Math.random() + 1);
+        t = Math.floor(5 * Math.random() + 1);
+        u = Math.floor(5 * Math.random() + 1);
+        v = Math.floor(5 * Math.random() + 1);
+        if (g == r) {
+            p -= 5;
+        } else if (g == s) {
+            p += 5;
+        } else if (g == t) {
+            p += p;
+            print("YOU HIT THE JACKPOT!!!\n");
+        } else if (g == u) {
+            p += 1;
+        } else if (g == v) {
+            p -= p * 0.5;
+        }
+        if (p <= 500) {
+            print("YOU HAVE " + p + " POINTS.\n");
+            print("\n");
+        } else {
+            print("!!!!YOU WIN!!!! WITH " + p + " POINTS.\n");
+            break;
+        }
+    }
+}
+
+main();

From fbfb41f5fa6d5932ac294ccd29d490543c537fd9 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 1 Mar 2021 22:16:39 -0600
Subject: [PATCH 169/749] Ported ONE CHECK to Javascript

---
 67 One Check/javascript/onecheck.html |   9 ++
 67 One Check/javascript/onecheck.js   | 151 ++++++++++++++++++++++++++
 2 files changed, 160 insertions(+)
 create mode 100644 67 One Check/javascript/onecheck.html
 create mode 100644 67 One Check/javascript/onecheck.js

diff --git a/67 One Check/javascript/onecheck.html b/67 One Check/javascript/onecheck.html
new file mode 100644
index 00000000..ffdb77e5
--- /dev/null
+++ b/67 One Check/javascript/onecheck.html	
@@ -0,0 +1,9 @@
+
+
+ONE CHECK
+
+
+

+
+
+
diff --git a/67 One Check/javascript/onecheck.js b/67 One Check/javascript/onecheck.js
new file mode 100644
index 00000000..a9633b46
--- /dev/null
+++ b/67 One Check/javascript/onecheck.js	
@@ -0,0 +1,151 @@
+// ONE CHECK
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a = [];
+
+// Main program
+async function main()
+{
+    print(tab(30) + "ONE CHECK\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 0; i <= 64; i++)
+        a[i] = 0;
+    print("SOLITAIRE CHECKER PUZZLE BY DAVID AHL\n");
+    print("\n");
+    print("48 CHECKERS ARE PLACED ON THE 2 OUTSIDE SPACES OF A\n");
+    print("STANDARD 64-SQUARE CHECKERBOARD.  THE OBJECT IS TO\n");
+    print("REMOVE AS MANY CHECKERS AS POSSIBLE BY DIAGONAL JUMPS\n");
+    print("(AS IN STANDARD CHECKERS).  USE THE NUMBERED BOARD TO\n");
+    print("INDICATE THE SQUARE YOU WISH TO JUMP FROM AND TO.  ON\n");
+    print("THE BOARD PRINTED OUT ON EACH TURN '1' INDICATES A\n");
+    print("CHECKER AND '0' AN EMPTY SQUARE.  WHEN YOU HAVE NO\n");
+    print("POSSIBLE JUMPS REMAINING, INPUT A '0' IN RESPONSE TO\n");
+    print("QUESTION 'JUMP FROM ?'\n");
+    print("\n");
+    print("HERE IS THE NUMERICAL BOARD:\n");
+    print("\n");
+    while (1) {
+        for (j = 1; j <= 57; j += 8) {
+            str = "";
+            for (i = 0; i <= 7; i++) {
+                while (str.length < 4 * i)
+                    str += " ";
+                str += " " + (j + i);
+            }
+            print(str + "\n");
+        }
+        print("\n");
+        print("AND HERE IS THE OPENING POSITION OF THE CHECKERS.\n");
+        print("\n");
+        for (j = 1; j <= 64; j++)
+            a[j] = 1;
+        for (j = 19; j <= 43; j += 8)
+            for (i = j; i <= j + 3; i++)
+                a[i] = 0;
+        m = 0;
+        while (1) {
+            // Print board
+            for (j = 1; j <= 57; j += 8) {
+                str = "";
+                for (i = j; i <= j + 7; i++) {
+                    str += " " + a[i] + " ";
+                }
+                print(str + "\n");
+            }
+            print("\n");
+            while (1) {
+                print("JUMP FROM");
+                f = parseInt(await input());
+                if (f == 0)
+                    break;
+                print("TO");
+                t = parseInt(await input());
+                print("\n");
+                // Check legality of move
+                f1 = Math.floor((f - 1) / 8);
+                f2 = f - 8 * f1;
+                t1 = Math.floor((t - 1) / 8);
+                t2 = t - 8 * t1;
+                if (f1 > 7 || t1 > 7 || f2 > 8 || t2 > 8 || Math.abs(f1 - t1) != 2 || Math.abs(f2 - t2) != 2 || a[(t + f) / 2] == 0 || a[f] == 0 || a[t] == 1) {
+                    print("ILLEGAL MOVE.  TRY AGAIN...\n");
+                    continue;
+                }
+                break;
+            }
+            if (f == 0)
+                break;
+            // Update board
+            a[t] = 1;
+            a[f] = 0;
+            a[(t + f) / 2] = 0;
+            m++;
+        }
+        // End game summary
+        s = 0;
+        for (i = 1; i <= 64; i++)
+            s += a[i];
+        print("\n");
+        print("YOU MADE " + m + " JUMPS AND HAD " + s + " PIECES\n");
+        print("REMAINING ON THE BOARD.\n");
+        print("\n");
+        while (1) {
+            print("TRY AGAIN");
+            str = await input();
+            if (str == "YES")
+                break;
+            if (str == "NO")
+                break;
+            print("PLEASE ANSWER 'YES' OR 'NO'.\n");
+        }
+        if (str == "NO")
+            break;
+    }
+    print("\n");
+    print("O.K.  HOPE YOU HAD FUN!!\n");
+}
+
+main();

From c6f63a0ccdcc113820543e0cbe0df8f98cd345f8 Mon Sep 17 00:00:00 2001
From: "Kyle T. Koala" <79724734+koalahedron@users.noreply.github.com>
Date: Mon, 1 Mar 2021 23:23:28 -0500
Subject: [PATCH 170/749] Update README.md for Acey Ducey.

---
 01 Acey Ducey/README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/01 Acey Ducey/README.md b/01 Acey Ducey/README.md
index ad0bdbad..071a80e3 100644
--- a/01 Acey Ducey/README.md	
+++ b/01 Acey Ducey/README.md	
@@ -5,3 +5,5 @@ https://www.atariarchives.org/basicgames/showpage.php?page=2
 
 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).

From 8782d714e8853827fa97890d55cc2aaca9a8349d Mon Sep 17 00:00:00 2001
From: Andrew Cooper 
Date: Tue, 2 Mar 2021 15:24:23 +1100
Subject: [PATCH 171/749] Add CommandResult

---
 .../csharp/{ => Commands}/Command.cs          |  2 +-
 .../{ => Commands}/CommandExtensions.cs       |  2 +-
 .../csharp/Commands/CommandResult.cs          | 23 +++++
 84 Super Star Trek/csharp/Game.cs             | 91 +++++++++----------
 84 Super Star Trek/csharp/Input.cs            |  2 +
 .../csharp/Objects/Enterprise.cs              | 24 ++---
 .../csharp/Systems/DamageControl.cs           |  6 +-
 .../csharp/Systems/ShieldControl.cs           | 26 ++++--
 .../csharp/Systems/ShortRangeSensors.cs       |  7 +-
 .../csharp/Systems/Subsystem.cs               |  3 +-
 10 files changed, 114 insertions(+), 72 deletions(-)
 rename 84 Super Star Trek/csharp/{ => Commands}/Command.cs (95%)
 rename 84 Super Star Trek/csharp/{ => Commands}/CommandExtensions.cs (91%)
 create mode 100644 84 Super Star Trek/csharp/Commands/CommandResult.cs

diff --git a/84 Super Star Trek/csharp/Command.cs b/84 Super Star Trek/csharp/Commands/Command.cs
similarity index 95%
rename from 84 Super Star Trek/csharp/Command.cs
rename to 84 Super Star Trek/csharp/Commands/Command.cs
index 33d9fd01..f0d569f8 100644
--- a/84 Super Star Trek/csharp/Command.cs	
+++ b/84 Super Star Trek/csharp/Commands/Command.cs	
@@ -1,6 +1,6 @@
 using System.ComponentModel;
 
-namespace SuperStarTrek
+namespace SuperStarTrek.Commands
 {
     internal enum Command
     {
diff --git a/84 Super Star Trek/csharp/CommandExtensions.cs b/84 Super Star Trek/csharp/Commands/CommandExtensions.cs
similarity index 91%
rename from 84 Super Star Trek/csharp/CommandExtensions.cs
rename to 84 Super Star Trek/csharp/Commands/CommandExtensions.cs
index 2b69ea31..f8f7e9da 100644
--- a/84 Super Star Trek/csharp/CommandExtensions.cs	
+++ b/84 Super Star Trek/csharp/Commands/CommandExtensions.cs	
@@ -1,7 +1,7 @@
 using System.Reflection;
 using System.ComponentModel;
 
-namespace SuperStarTrek
+namespace SuperStarTrek.Commands
 {
     internal static class CommandExtensions
     {
diff --git a/84 Super Star Trek/csharp/Commands/CommandResult.cs b/84 Super Star Trek/csharp/Commands/CommandResult.cs
new file mode 100644
index 00000000..d92fba09
--- /dev/null
+++ b/84 Super Star Trek/csharp/Commands/CommandResult.cs	
@@ -0,0 +1,23 @@
+namespace SuperStarTrek.Commands
+{
+    internal class CommandResult
+    {
+        public static readonly CommandResult Ok = new(false);
+        public static readonly CommandResult GameOver = new(true);
+
+        private CommandResult(bool isGameOver)
+        {
+            IsGameOver = isGameOver;
+        }
+
+        private CommandResult(double timeElapsed)
+        {
+            TimeElapsed = timeElapsed;
+        }
+
+        public bool IsGameOver { get; }
+        public double TimeElapsed { get; }
+
+        public static CommandResult Elapsed(double timeElapsed) => new(timeElapsed);
+    }
+}
diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs
index eb9fe03c..c9d9c778 100644
--- a/84 Super Star Trek/csharp/Game.cs	
+++ b/84 Super Star Trek/csharp/Game.cs	
@@ -43,9 +43,50 @@ namespace SuperStarTrek
 
         public void Play()
         {
-            var quadrant = Initialise();
+            Initialise();
             var gameOver = false;
 
+            while (!gameOver)
+            {
+                var command = _input.GetCommand();
+
+                var result = _enterprise.Execute(command);
+
+                gameOver = result.IsGameOver || CheckIfStranded();
+                _currentStardate += result.TimeElapsed;
+            }
+
+            if (_galaxy.KlingonCount > 0)
+            {
+                _output.Write(Strings.EndOfMission, _currentStardate, _galaxy.KlingonCount);
+            }
+            else
+            {
+                _output.Write(Strings.Congratulations, GetEfficiency());
+            }
+        }
+
+        private void Initialise()
+        {
+            var random = new Random();
+
+            _currentStardate = _initialStardate = random.GetInt(20, 40) * 100;
+            _finalStarDate = _initialStardate + random.GetInt(25, 35);
+
+            _currentQuadrant = random.GetCoordinate();
+            _currentSector = random.GetCoordinate();
+
+            _galaxy = new Galaxy();
+            _initialKlingonCount = _galaxy.KlingonCount;
+
+            _enterprise = new Enterprise(3000, random.GetCoordinate(), _output);
+            _enterprise
+                .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
+                .Add(new ShieldControl(_enterprise, _output, _input))
+                .Add(new DamageControl(_enterprise, _output));
+
+            var quadrant = new Quadrant(_galaxy[_currentQuadrant], _enterprise);
+
             _output.Write(Strings.Enterprise);
             _output.Write(
                 Strings.Orders,
@@ -59,58 +100,14 @@ namespace SuperStarTrek
             _input.WaitForAnyKeyButEnter("when ready to accept command");
 
             _enterprise.Enter(quadrant, Strings.StartText);
-
-            while (!gameOver)
-            {
-                var command = _input.GetCommand();
-
-                gameOver = command == Command.XXX || _enterprise.Execute(command) || CheckIfStranded();
-            }
-
-            if (_galaxy.KlingonCount > 0)
-            {
-                _output.Write(Strings.EndOfMission, _currentStardate, _galaxy.KlingonCount);
-            }
-            else
-            {
-                _output.Write(Strings.Congratulations, GetEfficiency());
-            }
-        }
-
-        private Quadrant Initialise()
-        {
-            var random = new Random();
-
-            _currentStardate = _initialStardate = random.GetInt(20, 40) * 100;
-            _finalStarDate = _initialStardate + random.GetInt(25, 35);
-
-            _currentQuadrant = random.GetCoordinate();
-            _currentSector = random.GetCoordinate();
-
-            _galaxy = new Galaxy();
-            _initialKlingonCount = _galaxy.KlingonCount;
-
-            _enterprise = new Enterprise(3000, random.GetCoordinate());
-            _enterprise
-                .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
-                .Add(new ShieldControl(_enterprise, _output, _input))
-                .Add(new DamageControl(_enterprise, _output));
-
-            return new Quadrant(_galaxy[_currentQuadrant], _enterprise);
         }
 
         public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye");
 
         private bool CheckIfStranded()
         {
-            if (_enterprise.TotalEnergy < 10 ||
-                _enterprise.Energy < 10 && _enterprise.Shields.IsDamaged)
-            {
-                _output.Write(Strings.Stranded);
-                return true;
-            }
-
-            return false;
+            if (_enterprise.IsStranded) { _output.Write(Strings.Stranded); }
+            return _enterprise.IsStranded;
         }
 
         private double GetEfficiency() =>
diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs
index 3e2d7972..d86b7baf 100644
--- a/84 Super Star Trek/csharp/Input.cs	
+++ b/84 Super Star Trek/csharp/Input.cs	
@@ -1,5 +1,7 @@
 using System;
 using System.Linq;
+using SuperStarTrek.Commands;
+
 using static System.StringComparison;
 
 namespace SuperStarTrek
diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs
index e8447fca..97e5e3cd 100644
--- a/84 Super Star Trek/csharp/Objects/Enterprise.cs	
+++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs	
@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using SuperStarTrek.Commands;
 using SuperStarTrek.Resources;
 using SuperStarTrek.Space;
 using SuperStarTrek.Systems;
@@ -11,29 +12,32 @@ namespace SuperStarTrek.Objects
     internal class Enterprise
     {
         private readonly int _maxEnergy;
+        private readonly Output _output;
         private readonly List _systems;
         private readonly Dictionary _commandExecutors;
         private Quadrant _quadrant;
 
-        public Enterprise(int maxEnergy, Coordinates sector)
+        public Enterprise(int maxEnergy, Coordinates sector, Output output)
         {
             Sector = sector;
             TotalEnergy = _maxEnergy = maxEnergy;
 
             _systems = new List();
             _commandExecutors = new Dictionary();
+            _output = output;
         }
 
         public Coordinates Quadrant => _quadrant.Coordinates;
         public Coordinates Sector { get; }
         public string Condition => GetCondition();
-        public ShieldControl Shields => (ShieldControl)_commandExecutors[Command.SHE];
-        public double Energy => TotalEnergy - Shields.Energy;
+        public ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE];
+        public double Energy => TotalEnergy - ShieldControl.ShieldEnergy;
         public double TotalEnergy { get; private set; }
         public int DamagedSystemCount => _systems.Count(s => s.IsDamaged);
         public IEnumerable Systems => _systems;
         public int TorpedoCount { get; }
-        public bool IsDocked { get; private set; }
+        public bool IsDocked => _quadrant.EnterpriseIsNextToStarbase;
+        public bool IsStranded => TotalEnergy < 10 || Energy < 10 && ShieldControl.IsDamaged;
 
         public Enterprise Add(Subsystem system)
         {
@@ -47,17 +51,14 @@ namespace SuperStarTrek.Objects
         {
             _quadrant = quadrant;
 
-            var _output = new Output();
             _output.Write(entryTextFormat, quadrant);
 
             if (quadrant.HasKlingons)
             {
                 _output.Write(Strings.CombatArea);
-                if (Shields.Energy <= 200) { _output.Write(Strings.LowShields); }
+                if (ShieldControl.ShieldEnergy <= 200) { _output.Write(Strings.LowShields); }
             }
 
-            IsDocked = quadrant.EnterpriseIsNextToStarbase;
-
             Execute(Command.SRS);
         }
 
@@ -69,10 +70,11 @@ namespace SuperStarTrek.Objects
                 _ => "Green"
             };
 
-        public bool Execute(Command command)
+        public CommandResult Execute(Command command)
         {
-            _commandExecutors[command].ExecuteCommand(_quadrant);
-            return false;
+            if (command == Command.XXX) { return CommandResult.GameOver; }
+
+            return _commandExecutors[command].ExecuteCommand(_quadrant);
         }
 
         internal bool Recognises(string command)
diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84 Super Star Trek/csharp/Systems/DamageControl.cs
index 5cfbda7e..b4587add 100644
--- a/84 Super Star Trek/csharp/Systems/DamageControl.cs	
+++ b/84 Super Star Trek/csharp/Systems/DamageControl.cs	
@@ -1,3 +1,4 @@
+using SuperStarTrek.Commands;
 using SuperStarTrek.Objects;
 using SuperStarTrek.Space;
 
@@ -15,7 +16,7 @@ namespace SuperStarTrek.Systems
             _output = output;
         }
 
-        public override void ExecuteCommand(Quadrant quadrant)
+        public override CommandResult ExecuteCommand(Quadrant quadrant)
         {
             if (IsDamaged)
             {
@@ -31,8 +32,11 @@ namespace SuperStarTrek.Systems
                 if (quadrant.Starbase.TryRepair(_enterprise, out var repairTime))
                 {
                     WriteDamageReport();
+                    return CommandResult.Elapsed(repairTime);
                 }
             }
+
+            return CommandResult.Ok;
         }
 
         public void WriteDamageReport()
diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs
index e7aca413..9c4a3c16 100644
--- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
+++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
@@ -1,3 +1,4 @@
+using SuperStarTrek.Commands;
 using SuperStarTrek.Objects;
 using SuperStarTrek.Space;
 
@@ -17,26 +18,35 @@ namespace SuperStarTrek.Systems
             _input = input;
         }
 
-        public double Energy { get; private set; }
+        public double ShieldEnergy { get; private set; }
 
-        public override void ExecuteCommand(Quadrant quadrant)
+        public override CommandResult ExecuteCommand(Quadrant quadrant)
         {
             if (Condition < 0)
             {
                 _output.WriteLine("Shield Control inoperable");
-                return;
+            }
+            else
+            {
+                UpdateShields();
             }
 
+            return CommandResult.Ok;
+        }
+
+        private void UpdateShields()
+        {
             _output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
             var requested = _input.GetNumber($"Number of units to shields");
 
             if (Validate(requested))
             {
-                Energy = requested;
-                return;
+                ShieldEnergy = requested;
+            }
+            else
+            {
+                _output.WriteLine("");
             }
-
-            _output.WriteLine("");
         }
 
         private bool Validate(double requested)
@@ -47,7 +57,7 @@ namespace SuperStarTrek.Systems
                 return false;
             }
 
-            return requested >= 0 && requested != Energy;
+            return requested >= 0 && requested != ShieldEnergy;
         }
     }
 }
diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs
index 6632705c..953ec66e 100644
--- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs	
+++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs	
@@ -2,6 +2,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using SuperStarTrek.Commands;
 using SuperStarTrek.Objects;
 using SuperStarTrek.Resources;
 using SuperStarTrek.Space;
@@ -24,7 +25,7 @@ namespace SuperStarTrek.Systems
             _output = output;
         }
 
-        public override void ExecuteCommand(Quadrant quadrant)
+        public override CommandResult ExecuteCommand(Quadrant quadrant)
         {
             if (_enterprise.IsDocked)
             {
@@ -42,6 +43,8 @@ namespace SuperStarTrek.Systems
                 .ToList()
                 .ForEach(l => _output.WriteLine(l));
             _output.WriteLine("---------------------------------");
+
+            return CommandResult.Ok;
         }
 
         public IEnumerable GetStatusLines()
@@ -52,7 +55,7 @@ namespace SuperStarTrek.Systems
             yield return $"Sector             {_enterprise.Sector}";
             yield return $"Photon torpedoes   {_enterprise.TorpedoCount}";
             yield return $"Total energy       {Math.Ceiling(_enterprise.TotalEnergy)}";
-            yield return $"Shields            {(int)_enterprise.Shields.Energy}";
+            yield return $"Shields            {(int)_enterprise.ShieldControl.ShieldEnergy}";
             yield return $"Klingons remaining {_galaxy.KlingonCount}";
         }
     }
diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs
index 9cb461ce..53398b41 100644
--- a/84 Super Star Trek/csharp/Systems/Subsystem.cs	
+++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs	
@@ -1,3 +1,4 @@
+using SuperStarTrek.Commands;
 using SuperStarTrek.Space;
 
 namespace SuperStarTrek.Systems
@@ -16,7 +17,7 @@ namespace SuperStarTrek.Systems
         public bool IsDamaged => Condition < 0;
         public Command Command { get; }
 
-        public abstract void ExecuteCommand(Quadrant quadrant);
+        public abstract CommandResult ExecuteCommand(Quadrant quadrant);
         public void Repair()
         {
             if (Condition < 0) { Condition = 0; }

From fb88b706fd1a318cd8faeec4289adb3dfd94f228 Mon Sep 17 00:00:00 2001
From: Andrew Cooper 
Date: Tue, 2 Mar 2021 16:06:45 +1100
Subject: [PATCH 172/749]  Fix command input for short input

---
 84 Super Star Trek/csharp/Input.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs
index d86b7baf..0fba2e4c 100644
--- a/84 Super Star Trek/csharp/Input.cs	
+++ b/84 Super Star Trek/csharp/Input.cs	
@@ -60,7 +60,7 @@ namespace SuperStarTrek
             {
                 var response = GetString("Command");
 
-                if (response != "" &&
+                if (response.Length >= 3 &&
                     Enum.TryParse(response.Substring(0, 3), ignoreCase: true, out Command parsedCommand))
                 {
                     return parsedCommand;

From 2e2c322baae2ebf27dcd184e67b00cc72e9b60b3 Mon Sep 17 00:00:00 2001
From: Jack Boyce 
Date: Mon, 1 Mar 2021 22:26:09 -0800
Subject: [PATCH 173/749] improve readability

---
 84 Super Star Trek/python/superstartrek.py | 113 ++++++++++-----------
 1 file changed, 51 insertions(+), 62 deletions(-)

diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py
index 5133bacf..db2963a1 100644
--- a/84 Super Star Trek/python/superstartrek.py	
+++ b/84 Super Star Trek/python/superstartrek.py	
@@ -23,7 +23,7 @@ from math import sqrt
 
 
 def fnr():
-    # Generate a random number from 0 to 7 inclusive.
+    # Generate a random integer from 0 to 7 inclusive.
     return random.randint(0, 7)
 
 
@@ -80,7 +80,7 @@ def find_empty_place():
 
 def navigation():
     # Take navigation input and move the Enterprise.
-    global d, s, e, k, s1, s2, qs, t8, t9, t, w1, c, q1, q2
+    global d, s, e, k, qs, t, q1, q2, s1, s2
 
     while True:
         c1s = input("COURSE (1-9)? ")
@@ -93,26 +93,25 @@ def navigation():
         print("   LT. SULU REPORTS, 'INCORRECT COURSE DATA, SIR!'")
         return
 
-    xs = '0.2' if d[0] < 0 else '8'
     while True:
-        w1s = input(f"WARP FACTOR (0-{xs})? ")
-        if len(w1s) > 0:
-            w1 = float(w1s)
+        warps = input(f"WARP FACTOR (0-{'0.2' if d[0] < 0 else '8'})? ")
+        if len(warps) > 0:
+            warp = float(warps)
             break
-    if d[0] < 0 and w1 > 0.2:
+    if d[0] < 0 and warp > 0.2:
         print("WARP ENGINES ARE DAMAGED. MAXIMUM SPEED = WARP 0.2")
         return
-    if w1 == 0:
+    if warp == 0:
         return
-    if w1 < 0 or w1 > 8:
+    if warp < 0 or warp > 8:
         print("   CHIEF ENGINEER SCOTT REPORTS 'THE ENGINES WON'T TAKE "
-              f"WARP {w1}!'")
+              f"WARP {warp}!'")
         return
 
-    n = int(w1 * 8 + 0.5)
+    n = round(warp * 8)
     if e < n:
         print("ENGINEERING REPORTS   'INSUFFICIENT ENERGY AVAILABLE")
-        print(f"                       FOR MANEUVERING AT WARP {w1}!'")
+        print(f"                       FOR MANEUVERING AT WARP {warp}!'")
         if s >= n - e and d[6] >= 0:
             print(f"DEFLECTOR CONTROL ROOM ACKNOWLEDGES {s} UNITS OF ENERGY")
             print("                         PRESENTLY DEPLOYED TO SHIELDS.")
@@ -127,18 +126,15 @@ def navigation():
 
     klingons_fire()
 
-    # print damage control report
-    d1 = 0
+    # repair damaged devices and print damage report
     line = ''
-    d6 = 1 if w1 >= 1 else w1
     for i in range(8):
         if d[i] < 0:
-            d[i] += d6
-            if d[i] > -0.1 and d[i] < 0:
+            d[i] += min(warp, 1)
+            if -0.1 < d[i] < 0:
                 d[i] = -0.1
             elif d[i] >= 0:
-                if d1 != 1:
-                    d1 = 1
+                if len(line) == 0:
                     line = "DAMAGE CONTROL REPORT:"
                 line += '   ' + devices[i] + ' REPAIR COMPLETED\n'
     if len(line) > 0:
@@ -157,41 +153,41 @@ def navigation():
     insert_marker(int(s1), int(s2), '   ')
     ic1 = int(c1)
     x1 = c[ic1 - 1][0] + (c[ic1][0] - c[ic1 - 1][0]) * (c1 - ic1)
-    x, y = s1, s2
     x2 = c[ic1 - 1][1] + (c[ic1][1] - c[ic1 - 1][1]) * (c1 - ic1)
-    q4, q5 = q1, q2
-    for i in range(1, n + 1):
+    q1_start, q2_start = q1, q2
+    x, y = s1, s2
+
+    for _ in range(n):
         s1 += x1
         s2 += x2
 
         if s1 < 0 or s1 > 7 or s2 < 0 or s2 > 7:
-            # exceeded quadrant limits
+            # exceeded quadrant limits; calculate final position
             x += 8 * q1 + n * x1
             y += 8 * q2 + n * x2
-            q1 = int(x / 8)
-            q2 = int(y / 8)
-            s1 = int(x - q1 * 8)
-            s2 = int(y - q2 * 8)
+            q1, q2 = int(x / 8), int(y / 8)
+            s1, s2 = int(x - q1 * 8), int(y - q2 * 8)
             if s1 < 0:
                 q1 -= 1
                 s1 = 7
             if s2 < 0:
                 q2 -= 1
                 s2 = 7
-            x5 = 0
+
+            hit_edge = False
             if q1 < 0:
-                x5 = 1
+                hit_edge = True
                 q1 = s1 = 0
             if q1 > 7:
-                x5 = 1
+                hit_edge = True
                 q1 = s1 = 7
             if q2 < 0:
-                x5 = 1
+                hit_edge = True
                 q2 = s2 = 0
             if q2 > 7:
-                x5 = 1
+                hit_edge = True
                 q2 = s2 = 7
-            if x5 == 1:
+            if hit_edge:
                 print("LT. UHURA REPORTS MESSAGE FROM STARFLEET COMMAND:")
                 print("  'PERMISSION TO ATTEMPT CROSSING OF GALACTIC "
                       "PERIMETER")
@@ -202,17 +198,17 @@ def navigation():
                 if t > t0 + t9:
                     end_game(won=False, quit=False)
                     return
-            if 8 * q1 + q2 == 8 * q4 + q5:
+
+            if q1 == q1_start and q2 == q2_start:
                 break
             t += 1
             maneuver_energy(n)
             new_quadrant()
             return
         else:
-            s8 = int(s1) * 24 + int(s2) * 3
-            if qs[s8:(s8 + 2)] != '  ':
-                s1 = int(s1 - x1)
-                s2 = int(s2 - x2)
+            pos = int(s1) * 24 + int(s2) * 3
+            if qs[pos:(pos + 2)] != '  ':
+                s1, s2 = int(s1 - x1), int(s2 - x2)
                 print("WARP ENGINES SHUT DOWN AT SECTOR "
                       f"{s1 + 1} , {s2 + 1} DUE TO BAD NAVAGATION")
                 break
@@ -222,10 +218,7 @@ def navigation():
     insert_marker(int(s1), int(s2), '<*>')
     maneuver_energy(n)
 
-    t8 = 1
-    if w1 < 1:
-        t8 = 0.1 * int(10 * w1)
-    t += t8
+    t += 0.1 * int(10 * warp) if warp < 1 else 1
     if t > t0 + t9:
         end_game(won=False, quit=False)
         return
@@ -742,8 +735,8 @@ def print_direction(from1, from2, to1, to2):
 
 def startup():
     # Initialize the game variables and map, and print startup messages.
-    global g, z, k, d, t, t0, t9, docked, e, e0, p, p0, s, k9, b9, s9, c
-    global devices, q1, q2, s1, s2, k7, restart
+    global g, z, d, t, t0, t9, docked, e, e0, p, p0, s, k9, b9, s9, c
+    global devices, q1, q2, s1, s2, k7
 
     print("\n\n\n\n\n\n\n\n\n\n\n"
           "                                    ,------*------,\n"
@@ -757,11 +750,10 @@ def startup():
     # set up global game variables
     g = [[0] * 8 for _ in range(8)]         # galaxy map
     z = [[0] * 8 for _ in range(8)]         # charted galaxy map
-    k = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]   # Klingons in current quadrant
     d = [0] * 8                             # damage stats for devices
     t = t0 = 100 * random.randint(20, 39)   # stardate (current, initial)
     t9 = random.randint(25, 34)             # mission duration (stardates)
-    docked = False                          # docking flag
+    docked = False                          # true when docked at starbase
     e = e0 = 3000                           # energy (current, initial)
     p = p0 = 10                             # torpedoes (current, initial)
     s = 0                                   # shields
@@ -821,20 +813,20 @@ def startup():
 
 def new_quadrant():
     # Enter a new quadrant: populate map and print a short range scan.
-    global g, z, k, t, t0, s9, q1, q2, s1, s2
-    global k3, b3, s3, d4, qs, b4, b5
+    global g, z, t, t0, s9, q1, q2, s1, s2
+    global k3, b3, s3, d4, k, qs, b4, b5
 
     k3 = b3 = s3 = 0
     d4 = 0.5 * random.random()
     z[q1][q2] = g[q1][q2]
 
-    if 0 <= q1 < 8 and 0 <= q2 < 8:
-        g2s = quadrant_name(q1, q2, False)
+    if 0 <= q1 <= 7 and 0 <= q2 <= 7:
+        quad = quadrant_name(q1, q2, False)
         if t == t0:
             print("\nYOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED")
-            print(f"IN THE GALACTIC QUADRANT, '{g2s}'.\n")
+            print(f"IN THE GALACTIC QUADRANT, '{quad}'.\n")
         else:
-            print(f"\nNOW ENTERING {g2s} QUADRANT . . .\n")
+            print(f"\nNOW ENTERING {quad} QUADRANT . . .\n")
 
         k3 = g[q1][q2] // 100
         b3 = g[q1][q2] // 10 - 10 * k3
@@ -845,18 +837,15 @@ def new_quadrant():
             if s <= 200:
                 print("   SHIELDS DANGEROUSLY LOW")
 
-    for i in range(3):
-        k[i] = [0, 0, 0]
-
-    qs = ' ' * 192
+    k = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]   # Klingons in current quadrant
+    qs = ' ' * 192                          # quadrant string
 
     # build quadrant string
     insert_marker(s1, s2, '<*>')
-    if k3 > 0:
-        for i in range(k3):
-            r1, r2 = find_empty_place()
-            insert_marker(r1, r2, '+K+')
-            k[i] = [r1, r2, s9 * (0.5 + random.random())]
+    for i in range(k3):
+        r1, r2 = find_empty_place()
+        insert_marker(r1, r2, '+K+')
+        k[i] = [r1, r2, s9 * (0.5 + random.random())]
     if b3 > 0:
         b4, b5 = find_empty_place()
         insert_marker(b4, b5, '>!<')
@@ -913,7 +902,7 @@ while True:
     while not restart:
         if s + e <= 10 or (e <= 10 and d[6] != 0):
             print("\n** FATAL ERROR **   YOU'VE JUST STRANDED YOUR SHIP IN "
-                  "SPACE\nYOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND "
+                  "SPACE.\nYOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND "
                   "SHIELD CONTROL\nIS PRESENTLY INCAPABLE OF CROSS-CIRCUITING "
                   "TO ENGINE ROOM!!")
 

From 28373b31c8e435209cc2883d40a58350fe7f7b16 Mon Sep 17 00:00:00 2001
From: NezumiRonin 
Date: Tue, 2 Mar 2021 00:44:36 -0600
Subject: [PATCH 174/749] Create name.pl

Made with Perl!
---
 63 Name/perl/name.pl | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 63 Name/perl/name.pl

diff --git a/63 Name/perl/name.pl b/63 Name/perl/name.pl
new file mode 100644
index 00000000..d25bcfe0
--- /dev/null
+++ b/63 Name/perl/name.pl	
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+use strict;
+
+print ' 'x34 . "NAME\n";
+print ' 'x15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+
+print "HELLO.\n"; print "MY NAME IS CREATIVE COMPUTER.\n";
+print "WHAT'S YOUR NAME (FIRST AND LAST): ";
+chomp (my $A = );
+
+my @B= split("", $A); #Convert string to array of characters.
+
+print "\n"; print "THANK YOU, ";
+print reverse @B;
+
+print ".\n"; print "OOPS! I GUESS I GOT IT BACKWARDS. A SMART\n";
+print "COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!\n\n";
+print "BUT I JUST NOTICED YOUR LETTERS ARE OUT OF ORDER.\n";
+print "LET'S PUT THEM IN ORDER LIKE THIS: ";
+print sort @B;
+
+print "\n\n";
+print "DON'T YOU LIKE THAT BETTER? ";
+chomp (my $D = );
+if (uc($D) eq "YES") {
+	print "\n"; print "I KNEW YOU'D AGREE!!\n";
+	} else {
+	print "\n"; print "I'M SORRY YOU DON'T LIKE IT THAT WAY.\n";
+	}
+print "\n"; print "I REALLY ENJOYED MEETING YOU $A.\n";
+print "HAVE A NICE DAY!\n";
+exit;
+
+

From 0583751d407439466883276b97994d6d1fd67e87 Mon Sep 17 00:00:00 2001
From: NezumiRonin 
Date: Tue, 2 Mar 2021 01:10:18 -0600
Subject: [PATCH 175/749] Create buzzword.pl

Made with Perl!
---
 20 Buzzword/perl/buzzword.pl | 39 ++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 20 Buzzword/perl/buzzword.pl

diff --git a/20 Buzzword/perl/buzzword.pl b/20 Buzzword/perl/buzzword.pl
new file mode 100644
index 00000000..75f09b3c
--- /dev/null
+++ b/20 Buzzword/perl/buzzword.pl	
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+use strict;
+
+print ' 'x26 . "BUZZWORD GENERATOR\n";
+print ' 'x15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+
+print "THIS PROGRAM PRINTS HIGHLY ACCEPTABLE PHRASES IN\n";
+print "'EDUCATOR-SPEAK' THAT YOU CAN WORK INTO REPORTS\n";
+print "AND SPEECHES. WHENEVER A QUESTION MARK IS PRINTED,\n";
+print "TYPE A 'Y' FOR ANOTHER PHRASE OR 'N' TO QUIT.\n";
+print "\n\n"; print "HERE'S THE FIRST PHRASE; ";
+
+my @A= ("",
+	"ABILITY","BASAL","BEHAVIORAL","CHILD-CENTERED",
+	"DIFFERENTIATED","DISCOVERY","FLEXIBLE","HETEROGENEOUS",
+	"HOMOGENEOUS","MANIPULATIVE","MODULAR","TAVISTOCK",
+	"INDIVIDUALIZED","LEARNING","EVALUATIVE","OBJECTIVE", 
+	"COGNITIVE","ENRICHMENT","SCHEDULING","HUMANISTIC",
+	"INTEGRATED","NON-GRADED","TRAINING","VERTICAL AGE",
+	"MOTIVATIONAL","CREATIVE","GROUPING","MODIFICATION",
+	"ACCOUNTABILITY","PROCESS","CORE CURRICULUM","ALGORITHM",
+	"PERFORMANCE","REINFORCEMENT","OPEN CLASSROOM","RESOURCE", 
+	"STRUCTURE","FACILITY","ENVIRONMENT" 
+	);
+
+my $Y;
+do {
+	print $A[int(13*rand(1)+1)]." ";
+	print $A[int(13*rand(1)+14)]." ";
+	print $A[int(13*rand(1)+27)]; print "\n";
+	print "? ";
+	chomp ($Y = );
+	} until ($Y ne "Y");
+
+print "COME BACK WHEN YOU NEED HELP WITH ANOTHER REPORT!\n";
+exit;
+
+

From 9bfb20a4bdd3d87396a3a8dd8afc81d2cccfcc18 Mon Sep 17 00:00:00 2001
From: NezumiRonin 
Date: Tue, 2 Mar 2021 02:17:40 -0600
Subject: [PATCH 176/749] Create letter.pl

Made with Perl!
---
 54 Letter/perl/letter.pl | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 54 Letter/perl/letter.pl

diff --git a/54 Letter/perl/letter.pl b/54 Letter/perl/letter.pl
new file mode 100644
index 00000000..54fb5fe0
--- /dev/null
+++ b/54 Letter/perl/letter.pl	
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+use strict;
+
+print ' 'x33 . "LETTER\n";
+print ' 'x15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+
+print "LETTER GUESSING GAME\n"; print "\n";
+print "I'LL THINK OF A LETTER OF THE ALPHABET, A TO Z.\n";
+print "TRY TO GUESS MY LETTER AND I'LL GIVE YOU CLUES\n";
+print "AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER.\n";
+
+my $A;
+while (1) {
+	my $L= 65+int(rand(1)*26);
+	my $G= 0;
+	print "\n"; print "O.K., I HAVE A LETTER. START GUESSING.\n";
+
+	do {
+		print "\n"; print "WHAT IS YOUR GUESS? ";
+		$G=$G+1;
+		chomp($A= );
+		$A= ord($A);
+		print "\n";
+		if ($A<$L) { print "TOO LOW. TRY A HIGHER LETTER.\n"; }
+		if ($A>$L) { print "TOO HIGH. TRY A LOWER LETTER.\n"; }
+		} until($A eq $L);
+
+	print "\n"; print "YOU GOT IT IN $G GUESSES!!\n";
+
+	if ($G<=5) {
+		print "GOOD JOB !!!!!\n";
+		for (my $N=1; $N<=15; $N++) { print chr(7); } #ASCII Bell.
+		} else {
+		print "BUT IT SHOULDN'T TAKE MORE THAN 5 GUESSES!\n";
+		}
+
+	print "\n";
+	print "LET'S PLAN AGAIN.....\n";
+	}
+
+exit;
+
+

From a9619742e25e0fc7a55a50624b09f2a60682634d Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Tue, 2 Mar 2021 19:22:20 +1030
Subject: [PATCH 177/749] Java port of Nicomachus game

---
 64 Nicomachus/java/src/Nicomachus.java | 185 +++++++++++++++++++++++++
 1 file changed, 185 insertions(+)
 create mode 100644 64 Nicomachus/java/src/Nicomachus.java

diff --git a/64 Nicomachus/java/src/Nicomachus.java b/64 Nicomachus/java/src/Nicomachus.java
new file mode 100644
index 00000000..53bbbedd
--- /dev/null
+++ b/64 Nicomachus/java/src/Nicomachus.java	
@@ -0,0 +1,185 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Nichomachus
+ * 

+ * Based on the Basic game of Nichomachus here + * https://github.com/coding-horror/basic-computer-games/blob/main/64%20Nicomachus/nicomachus.bas + *

+ * 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 Nicomachus { + + public static final long TWO_SECONDS = 2000; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + GET_INPUTS, + RESULTS, + PLAY_AGAIN + } + + int remainderNumberDividedBy3; + int remainderNumberDividedBy5; + int remainderNumberDividedBy7; + + // Current game state + private GAME_STATE gameState; + + public Nicomachus() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() throws Exception { + + do { + switch (gameState) { + + case START_GAME: + intro(); + gameState = GAME_STATE.GET_INPUTS; + break; + + case GET_INPUTS: + + System.out.println("PLEASE THINK OF A NUMBER BETWEEN 1 AND 100."); + remainderNumberDividedBy3 = displayTextAndGetNumber("YOUR NUMBER DIVIDED BY 3 HAS A REMAINDER OF? "); + remainderNumberDividedBy5 = displayTextAndGetNumber("YOUR NUMBER DIVIDED BY 5 HAS A REMAINDER OF? "); + remainderNumberDividedBy7 = displayTextAndGetNumber("YOUR NUMBER DIVIDED BY 7 HAS A REMAINDER OF? "); + + gameState = GAME_STATE.RESULTS; + + case RESULTS: + System.out.println("LET ME THINK A MOMENT..."); + // Simulate the basic programs for/next loop to delay things. + // Here we are sleeping for one second. + Thread.sleep(TWO_SECONDS); + + // Calculate the number the player was thinking of. + int answer = (70 * remainderNumberDividedBy3) + (21 * remainderNumberDividedBy5) + + (15 * remainderNumberDividedBy7); + + // Something similar was in the original basic program + // (to test if the answer was 105 and deducting 105 until it was <= 105 + while (answer > 105) { + answer -= 105; + } + + do { + String input = displayTextAndGetInput("YOUR NUMBER WAS " + answer + ", RIGHT? "); + if (yesEntered(input)) { + System.out.println("HOW ABOUT THAT!!"); + break; + } else if (noEntered(input)) { + System.out.println("I FEEL YOUR ARITHMETIC IS IN ERROR."); + break; + } else { + System.out.println("EH? I DON'T UNDERSTAND '" + input + "' TRY 'YES' OR 'NO'."); + } + } while (true); + + gameState = GAME_STATE.PLAY_AGAIN; + break; + + case PLAY_AGAIN: + System.out.println("LET'S TRY ANOTHER"); + gameState = GAME_STATE.GET_INPUTS; + break; + } + + // Original basic program looped until CTRL-C + } while (true); + } + + private void intro() { + System.out.println(addSpaces(33) + "NICOMA"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("BOOMERANG PUZZLE FROM ARITHMETICA OF NICOMACHUS -- A.D. 90!"); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.nextLine(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * Checks whether player entered N or NO to a question. + * + * @param text player string from kb + * @return true of N or NO was entered, otherwise false + */ + private boolean noEntered(String text) { + return stringIsAnyValue(text, "N", "NO"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + } + + public static void main(String[] args) throws Exception { + + Nicomachus nicomachus = new Nicomachus(); + nicomachus.play(); + } +} \ No newline at end of file From cc592ef0e3cf687ae4c1e0b78c25d7a258d958f8 Mon Sep 17 00:00:00 2001 From: Ueli Kunz Date: Tue, 2 Mar 2021 13:44:09 +0100 Subject: [PATCH 178/749] nodejs based literature quiz --- .../javascript/literature-quiz-node.mjs | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 57 Literature Quiz/javascript/literature-quiz-node.mjs diff --git a/57 Literature Quiz/javascript/literature-quiz-node.mjs b/57 Literature Quiz/javascript/literature-quiz-node.mjs new file mode 100644 index 00000000..fb6192b4 --- /dev/null +++ b/57 Literature Quiz/javascript/literature-quiz-node.mjs @@ -0,0 +1,82 @@ +import * as readline from 'readline' + +// start reusable code +async function input(prompt = "") { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }) + + return new Promise((resolve, _) => { + rl.setPrompt(prompt) + rl.prompt() + rl.on('line', answer => { + rl.close() + resolve(answer) + }) + }) +} + +function println(message = "", align = "left"){ + let padColCount = 0 + if(align === "center"){ + padColCount = Math.round(process.stdout.columns / 2 + message.length / 2) + } + console.log(message.padStart(padColCount, " ")) +} +// end reusable code + + +function equalIgnoreCase(correct, provided){ + return correct.toString().toLowerCase() === provided.toString().toLowerCase() +} + +async function evaluateQuestion(question, answerOptions, correctAnswer, correctMessage, wrongMessage){ + const answer = await input(question + "\n" + answerOptions + "\n") + const isCorrect = equalIgnoreCase(correctAnswer, answer) + println(isCorrect ? correctMessage : wrongMessage) + return isCorrect ? 1 : 0 +} + +async function main(){ + let score = 0 + println("LITERATURE QUIZ", "center") + println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", "center") + println();println();println() + + score += await evaluateQuestion("IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT?", + "1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO", 3, + "VERY GOOD! HERE'S ANOTHER.", "SORRY...FIGARO WAS HIS NAME.") + println() + + score += await evaluateQuestion("FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?", + "1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S", 2, + "PRETTY GOOD!", "TOO BAD...IT WAS ELMER FUDD'S GARDEN.") + println() + + score += await evaluateQuestion("IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED", + "1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO", 4, + "YEA! YOU'RE A REAL LITERATURE GIANT.", + "BACK TO THE BOOKS,...TOTO WAS HIS NAME.") + println() + + score += await evaluateQuestion("WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE", + "1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY", 3, + "GOOD MEMORY!", "OH, COME ON NOW...IT WAS SNOW WHITE.") + + println();println() + + if(score === 4) { + println("WOW! THAT'S SUPER! YOU REALLY KNOW YOUR NURSERY\n"+ + "YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE\n"+ + "LITERATURE (HA, HA, HA)") + } else if(score <= 2){ + println("UGH. THAT WAS DEFINITELY NOT TOO SWIFT. BACK TO\n" + + "NURSERY SCHOOL FOR YOU, MY FRIEND.") + } else { + println("NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME\n"+ + "READING THE NURSERY GREATS.") + } +} + +main() \ No newline at end of file From 28c4883349dcc06329d3edb141c06dc07346439e Mon Sep 17 00:00:00 2001 From: Ueli Kunz Date: Tue, 2 Mar 2021 13:48:24 +0100 Subject: [PATCH 179/749] comments --- 57 Literature Quiz/javascript/literature-quiz-node.mjs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/57 Literature Quiz/javascript/literature-quiz-node.mjs b/57 Literature Quiz/javascript/literature-quiz-node.mjs index fb6192b4..2c8795e4 100644 --- a/57 Literature Quiz/javascript/literature-quiz-node.mjs +++ b/57 Literature Quiz/javascript/literature-quiz-node.mjs @@ -9,9 +9,13 @@ async function input(prompt = "") { return new Promise((resolve, _) => { rl.setPrompt(prompt) + // show use the question rl.prompt() + // listen for user answer, + // callback is triggered as soon as user hits enter key rl.on('line', answer => { rl.close() + // resolve the promise, with the input the user entered resolve(answer) }) }) @@ -20,6 +24,8 @@ async function input(prompt = "") { function println(message = "", align = "left"){ let padColCount = 0 if(align === "center"){ + // calculate the amount of spaces required to center the message + // process.stdout.columns is the number of spaces per line in the terminal padColCount = Math.round(process.stdout.columns / 2 + message.length / 2) } console.log(message.padStart(padColCount, " ")) @@ -32,6 +38,8 @@ function equalIgnoreCase(correct, provided){ } async function evaluateQuestion(question, answerOptions, correctAnswer, correctMessage, wrongMessage){ + // ask the user to answer the given question + // this is a blocking wait const answer = await input(question + "\n" + answerOptions + "\n") const isCorrect = equalIgnoreCase(correctAnswer, answer) println(isCorrect ? correctMessage : wrongMessage) From e6a65e55cb9346972d6100b150599ddde3748595 Mon Sep 17 00:00:00 2001 From: Ueli Kunz Date: Tue, 2 Mar 2021 14:05:15 +0100 Subject: [PATCH 180/749] typo --- 57 Literature Quiz/javascript/literature-quiz-node.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/57 Literature Quiz/javascript/literature-quiz-node.mjs b/57 Literature Quiz/javascript/literature-quiz-node.mjs index 2c8795e4..0d38d540 100644 --- a/57 Literature Quiz/javascript/literature-quiz-node.mjs +++ b/57 Literature Quiz/javascript/literature-quiz-node.mjs @@ -9,7 +9,7 @@ async function input(prompt = "") { return new Promise((resolve, _) => { rl.setPrompt(prompt) - // show use the question + // show user the question rl.prompt() // listen for user answer, // callback is triggered as soon as user hits enter key From 3a9e19197dd69d5787134df0e5b553d9af36eab0 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Tue, 2 Mar 2021 09:05:13 -0800 Subject: [PATCH 181/749] update port HEXAPAWN to Python mostly working, did major refactoring for clarity and understanding what all of the pieces are doing. Still another round of refactoring to go to make it clearer what's going on, but I think almost all of the logic is correct. There's what looks like a bug where the human wins by advancing to the back row, and the computer incorrectly says that it has lost because it has no moves. I suspect this is a bug in my logic, but I'll have to trace through the BASIC to verify. The game is playable and somewhat fun in its current state. --- 46 Hexapawn/python/hexapawn.py | 464 ++++++++++++++++++++++++++------- 1 file changed, 368 insertions(+), 96 deletions(-) diff --git a/46 Hexapawn/python/hexapawn.py b/46 Hexapawn/python/hexapawn.py index 232bb782..50f2abc8 100644 --- a/46 Hexapawn/python/hexapawn.py +++ b/46 Hexapawn/python/hexapawn.py @@ -14,8 +14,17 @@ Conversion to MITS BASIC by Steve North Port to Python by Dave LeCompte """ +import collections +import random + PAGE_WIDTH = 64 +HUMAN_PIECE = 1 +EMPTY_SPACE = 0 +COMPUTER_PIECE = -1 + +ComputerMove = collections.namedtuple('ComputerMove', ['x', 'y', 'm1', 'm2']) + def print_centered(msg): spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) print(spaces + msg) @@ -70,21 +79,20 @@ def prompt_yes_no(msg): elif response[0] == "N": return False -def fnr(x): - score = {1: -3, - 2: -2, - 3: -1, - 4: -6, - 5: -5, - 6: -4, - 7: -9, - 8: -8, - 9: -7} +def reverse_board_position(x): + assert(x >= 1 and x < 10) + + score = {1: 3, + 2: 2, + 3: 1, + 4: 6, + 5: 5, + 6: 4, + 7: 9, + 8: 8, + 9: 7} return score[x] -def fnm(y): - return y % 10 - def get_b(x, y): data = [[-1, -1, -1, 1, 0, 0, 0, 1, 1], [-1, -1, -1, 0, 1, 0, 1, 0, 1], @@ -106,36 +114,49 @@ def get_b(x, y): [ 0, -1, 0, 1, -1, 0, 0, 0, 0], [-1, 0, 0, -1, 1, 0, 0, 0, 0]] - return data[x+1][y+1] + assert(x >= 1 and x < 20) + assert(y >= 1 and y < 10) + + return data[x-1][y-1] + +m_data = [[24, 25, 36, 0], + [14, 15, 36, 0], + [15, 35, 36, 47], + [36, 58, 59, 0], + [15, 35, 36, 0], + [24, 25, 26, 0], + [26, 57, 58, 0], + [26, 35, 0, 0], + [47, 48, 0, 0], + [35, 36, 0, 0], + [35, 36, 0, 0], + [36, 0, 0, 0], + [47, 58, 0, 0], + [15, 0, 0, 0], + [26, 47, 0, 0], + [47, 58, 0, 0], + [35, 36, 47, 0], + [28, 58, 0, 0], + [15, 47, 0, 0]] def get_m(x, y): - data = [[24, 25,36,0], - [14,15,36,0], - [15,35,36,47], - [36,58,59,0], - [15,35,36,0], - [24,25,26,0], - [26,57,58,0], - [26,35,0,0], - [47,48,0,0], - [35,36,0,0], - [35,36,0,0], - [36,0,0,0], - [47,58,0,0], - [15,0,0,0], - [26,47,0,0], - [47,58,0,0], - [35,36,47,0], - [28,58,0,0], - [15,47,0,0]] + assert(x >= 1 and x < 20) + assert(y >= 1 and y < 5) - return data[x+1][y+1] + return m_data[x-1][y-1] + +def set_m(x, y, value): + m_data[x-1][y-1] = value def init_board(): - return [-1] * 3 + [0] * 3 + [1] * 3 + return ([COMPUTER_PIECE] * 3 + + [EMPTY_SPACE] * 3 + + [HUMAN_PIECE] * 3) def print_board(board): - pieces = "X.O" + piece_dict = {COMPUTER_PIECE: 'X', + EMPTY_SPACE: '.', + HUMAN_PIECE: 'O'} space = " "*10 print() @@ -145,7 +166,7 @@ def print_board(board): line += space space_number = i * 3 + j space_contents = board[space_number] - line += pieces[space_contents + 1] + line += piece_dict[space_contents] print(line) print() @@ -157,7 +178,7 @@ def get_coordinates(): m1, m2 = [int(c) for c in response.split(',')] return m1, m2 except ValueError as ve: - print("ILLEGAL MOVE.") + print_illegal() def print_illegal(): print("ILLEGAL MOVE.") @@ -168,78 +189,329 @@ def board_contents(board, space_number): def set_board(board, space_number, new_value): board[space_number - 1] = new_value +def is_legal_move(board, m1, m2): + if board_contents(board, m1) != HUMAN_PIECE: + # Start space doesn't contain player's piece + return False + if board_contents(board, m2) == HUMAN_PIECE: + # Destination space contains player's piece (can't capture your own piece) + return False + # line 160 + is_capture = (m2-m1 != -3) + if is_capture and board_contents(board, m2) != COMPUTER_PIECE: + # Destination does not contain computer piece + return False + # line 170 + if m2 > m1: + # can't move backwards + return False + # line 180 + if (not is_capture) and board_contents(board, m2) != EMPTY_SPACE: + # Destination is not open + return False + # line 185 + if m2-m1 < -4: + # too far + return False + # line 186 + if m1 == 7 and m2 == 3: + # can't jump corner to corner (wrapping around the board) + return False + return True + +def player_piece_on_back_row(board): + for space in range(1,4): + if board_contents(board, space) == HUMAN_PIECE: + return True + return False + +def computer_piece_on_front_row(board): + for space in range(7, 10): + if board_contents(board, space) == COMPUTER_PIECE: + return True + return False + +def all_human_pieces_captured(board): + return len(list(get_human_spaces(board))) == 0 + +def all_computer_pieces_captured(board): + return len(list(get_computer_spaces(board))) == 0 + +def human_win(last_computer_move): + print("YOU WIN") + set_m(last_computer_move.x, last_computer_move.y, 0) + global l + l += 1 + +def computer_win(has_moves): + if has_moves: + msg = "YOU CAN'T MOVE, SO " + else: + msg = "" + msg += "I WIN" + print(msg) + global w + w += 1 + +def show_scores(): + print(f"I HAVE WON {w} AND YOU {l} OUT OF {w+l} GAMES.") + print() + +def human_has_move(board): + # line 690 + for i in get_human_spaces(board): + if board_contents(board, i-3) == EMPTY_SPACE: + # can move piece forward + return True + elif reverse_board_position(i) == i: + # line 780 + # can capture from center + if ((board_contents(board, i-2) == COMPUTER_PIECE) or + (board_contents(board, i-4) == COMPUTER_PIECE)): + return True + else: + continue + elif i < 7: + # Line 760 + assert((i == 4) or (i == 6)) + # can capture computer piece at 2 + if board_contents(board, 2) == COMPUTER_PIECE: + return True + else: + continue + elif board_contents(board, 5) == COMPUTER_PIECE: + assert((i == 7) or (i == 9)) + # can capture computer piece at 5 + return True + else: + continue + return False + + +def get_board_spaces(): + yield from range(1, 10) + +def get_board_spaces_with(board, val): + for i in get_board_spaces(): + if board_contents(board, i) == val: + yield i + +def get_human_spaces(board): + yield from get_board_spaces_with(board, HUMAN_PIECE) + +def get_empty_spaces(board): + yield from get_board_spaces_with(board, EMPTY_SPACE) + +def get_computer_spaces(board): + yield from get_board_spaces_with(board, COMPUTER_PIECE) + + +def has_computer_move(board): + for i in get_computer_spaces(board): + found_move = False + if board_contents(board, i+3) == EMPTY_SPACE: + # can move forward (down) + return True + + # line 260 + if reverse_board_position(i) == i: + # i is in the middle column + if ((board_contents(board, i + 2) == HUMAN_PIECE) or + (board_contents(board, i + 4) == HUMAN_PIECE)): + return True + else: + # line 270 + if i > 3: + # beyond the first row + if board_contents(board, 8) == HUMAN_PIECE: + # can capture on 8 + return True + else: + continue + else: + # line 280 + if board_contents(board, 5) == HUMAN_PIECE: + # can capture on 5 + return True + else: + continue + return False + +def get_flipped_table(b_line): # TODO remove table altogether + t = {} + # line 360 + for row in range(1, 4): + for column in range(1, 4): + # line 380 + flipped_column = 4 - column + + # fill out t to represent the data from b flipped left to right + space = (row-1) * 3 + column + flipped_space = (row - 1) * 3 + flipped_column + + t[space] = get_b(b_line, flipped_space) + return t + +def board_matches_b(b_line, board): + for s in get_board_spaces(): + if get_b(b_line, s) != board_contents(board, s): + return False + return True + +def board_matches_flipped_b(b_line, board): + flipped_table = get_flipped_table(b_line) + + for s in get_board_spaces(): + if flipped_table[s] != board_contents(board, s): + return False + return True + +def does_b_line_match(b_line, board): + if board_matches_b(b_line, board): + return True, False + elif board_matches_flipped_b(b_line, board): + return True, True + else: + return False, None + +def has_any_m_table(x): + for i in range(1,5): + if get_m(x, i) != 0: + return True + return False + +def pick_from_m_table(x): + valid_y_list = [y for y in range(1,5) if get_m(x, y) != 0] + assert(len(valid_y_list) > 0) + return random.choice(valid_y_list) + + +def get_move_for_b_line(b_line, reverse_board): + # line 540 + x = b_line + + if not has_any_m_table(x): + return None + + # line 600 + y = pick_from_m_table(x) + + # line 610 + mxy = get_m(x, y) + m1 = mxy // 10 + m2 = mxy % 10 + if reverse_board: + m1 = reverse_board_position(m1) + m2 = reverse_board_position(m2) + + return ComputerMove(x, y, m1, m2) + + +def find_b_line_that_matches_board(board): + for b_line in range(1,20): + matches, reverse_board = does_b_line_match(b_line, board) + if matches: + return b_line, reverse_board + + # THE TERMINATION OF THIS LOOP IS IMPOSSIBLE + print("ILLEGAL BOARD PATTERN.") + assert(False) + + +def pick_computer_move(board): + if not has_computer_move(board): + # Line 340 + return None + + # line 350 + b_line, reverse_board = find_b_line_that_matches_board(board) + + m = get_move_for_b_line(b_line, reverse_board) + + if m == None: + print("I RESIGN") + return None + + return m + + + + +def play_game(): + last_computer_move = None + + board = init_board() + + while True: + print_board(board) + + has_legal_move = False + while not has_legal_move: + m1, m2 = get_coordinates() + + if not is_legal_move(board, m1, m2): + print_illegal() + else: + # otherwise, acceptable move + has_legal_move = True + + set_board(board, m1, 0) + set_board(board, m2, 1) + + # line 205 + print_board(board) + + if (player_piece_on_back_row(board) or + all_computer_pieces_captured(board)): + human_win(last_computer_move) + return + + # line 230 + computer_move = pick_computer_move(board) + if computer_move is None: + human_win(last_computer_move) + return + + last_computer_move = computer_move + + m1, m2 = last_computer_move.m1, last_computer_move.m2 + + print(f"I MOVE FROM {m1} TO {m2}") + set_board(board, m1, 0) + set_board(board, m2, -1) + + # line 640 + print_board(board) + + if (computer_piece_on_front_row(board) or + all_human_pieces_captured(board)): + computer_win(True) + return + elif not human_has_move(board): + computer_win(False) + return + + + + + def main(): print_header("HEXAPAWN") if prompt_yes_no("INSTRUCTIONS (Y-N)?"): print_instructions() + global w, l w = 0 l = 0 - x = 0 - y = 0 - - board = init_board() - - print_board(board) - while True: - m1, m2 = get_coordinates() - - if board_contents(board, m1) != 1: - # Start space doesn't contain player's piece - print_illegal() - continue - if board_contents(board, m2) == 1: - # Destination space contains player's piece (can't capture your own piece) - print_illegal() - continue - # line 160 - is_capture = (m2-m1 != -3) - if is_capture and board_contents(board, m2) != -1: - # Destination does not contain computer piece - print_illegal() - continue - # line 170 - if m2 > m1: - # can't move backwards - print_illegal() - continue - # line 180 - if (not is_capture) and board_contents(board, m2) != 0: - # Destination is not open - print_illegal() - continue - # line 185 - if m2-m1 < -4: - # too far - print_illegal() - continue - # line 186 - if m1 == 7 and m2 == 3: - # can't jump corner to corner ?! - print_illegal() - continue - - # otherwise, acceptable move - break + play_game() + show_scores() - set_board(board, m1, 0) - set_board(board, m2, 1) - - # line 205 - print_board(board) - - if __name__ == "__main__": main() """ -210 IF S(1)=1 OR S(2)=1 OR S(3)=1 THEN 820 -220 FOR I=1 TO 9 -221 IF S(I)=-1 THEN 230 -222 NEXT I -223 GOTO 820 230 FOR I=1 TO 9 240 IF S(I)<>-1 THEN 330 250 IF S(I+3)=0 THEN 350 From 7c84cffa52f459aad8401908a0c2d62d1d1dc92a Mon Sep 17 00:00:00 2001 From: nanochess Date: Tue, 2 Mar 2021 12:56:23 -0600 Subject: [PATCH 182/749] Ported ORBIT to Javascript --- 68 Orbit/javascript/orbit.html | 9 ++ 68 Orbit/javascript/orbit.js | 155 +++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 68 Orbit/javascript/orbit.html create mode 100644 68 Orbit/javascript/orbit.js diff --git a/68 Orbit/javascript/orbit.html b/68 Orbit/javascript/orbit.html new file mode 100644 index 00000000..b5ea3982 --- /dev/null +++ b/68 Orbit/javascript/orbit.html @@ -0,0 +1,9 @@ + + +ORBIT + + +


+
+
+
diff --git a/68 Orbit/javascript/orbit.js b/68 Orbit/javascript/orbit.js
new file mode 100644
index 00000000..fc505bdf
--- /dev/null
+++ b/68 Orbit/javascript/orbit.js	
@@ -0,0 +1,155 @@
+// ORBIT
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var a = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "ORBIT\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("SOMEWHERE ABOVE YOUR PLANET IS A ROMULAN SHIP.\n");
+    print("\n");
+    print("THE SHIP IS IN A CONSTANT POLAR ORBIT.  ITS\n");
+    print("DISTANCE FROM THE CENTER OF YOUR PLANET IS FROM\n");
+    print("10,000 TO 30,000 MILES AND AT ITS PRESENT VELOCITY CAN\n");
+    print("CIRCLE YOUR PLANET ONCE EVERY 12 TO 36 HOURS.\n");
+    print("\n");
+    print("UNFORTUNATELY, THEY ARE USING A CLOAKING DEVICE SO\n");
+    print("YOU ARE UNABLE TO SEE THEM, BUT WITH A SPECIAL\n");
+    print("INSTRUMENT YOU CAN TELL HOW NEAR THEIR SHIP YOUR\n");
+    print("PHOTON BOMB EXPLODED.  YOU HAVE SEVEN HOURS UNTIL THEY\n");
+    print("HAVE BUILT UP SUFFICIENT POWER IN ORDER TO ESCAPE\n");
+    print("YOUR PLANET'S GRAVITY.\n");
+    print("\n");
+    print("YOUR PLANET HAS ENOUGH POWER TO FIRE ONE BOMB AN HOUR.\n");
+    print("\n");
+    print("AT THE BEGINNING OF EACH HOUR YOU WILL BE ASKED TO GIVE AN\n");
+    print("ANGLE (BETWEEN 0 AND 360) AND A DISTANCE IN UNITS OF\n");
+    print("100 MILES (BETWEEN 100 AND 300), AFTER WHICH YOUR BOMB'S\n");
+    print("DISTANCE FROM THE ENEMY SHIP WILL BE GIVEN.\n");
+    print("\n");
+    print("AN EXPLOSION WITHIN 5,000 MILES OF THE ROMULAN SHIP\n");
+    print("WILL DESTROY IT.\n");
+    print("\n");
+    print("BELOW IS A DIAGRAM TO HELP YOU VISUALIZE YOUR PLIGHT.\n");
+    print("\n");
+    print("\n");
+    print("                          90\n");
+    print("                    0000000000000\n");
+    print("                 0000000000000000000\n");
+    print("               000000           000000\n");
+    print("             00000                 00000\n");
+    print("            00000    XXXXXXXXXXX    00000\n");
+    print("           00000    XXXXXXXXXXXXX    00000\n");
+    print("          0000     XXXXXXXXXXXXXXX     0000\n");
+    print("         0000     XXXXXXXXXXXXXXXXX     0000\n");
+    print("        0000     XXXXXXXXXXXXXXXXXXX     0000\n");
+    print("180<== 00000     XXXXXXXXXXXXXXXXXXX     00000 ==>0\n");
+    print("        0000     XXXXXXXXXXXXXXXXXXX     0000\n");
+    print("         0000     XXXXXXXXXXXXXXXXX     0000\n");
+    print("          0000     XXXXXXXXXXXXXXX     0000\n");
+    print("           00000    XXXXXXXXXXXXX    00000\n");
+    print("            00000    XXXXXXXXXXX    00000\n");
+    print("             00000                 00000\n");
+    print("               000000           000000\n");
+    print("                 0000000000000000000\n");
+    print("                    0000000000000\n");
+    print("                         270\n");
+    print("\n");
+    print("X - YOUR PLANET\n");
+    print("O - THE ORBIT OF THE ROMULAN SHIP\n");
+    print("\n");
+    print("ON THE ABOVE DIAGRAM, THE ROMULAN SHIP IS CIRCLING\n");
+    print("COUNTERCLOCKWISE AROUND YOUR PLANET.  DON'T FORGET THAT\n");
+    print("WITHOUT SUFFICIENT POWER THE ROMULAN SHIP'S ALTITUDE\n");
+    print("AND ORBITAL RATE WILL REMAIN CONSTANT.\n");
+    print("\n");
+    print("GOOD LUCK.  THE FEDERATION IS COUNTING ON YOU.\n");
+    while (1) {
+        a = Math.floor(360 * Math.random());
+        d = Math.floor(200 * Math.random() + 200);
+        r = Math.floor(20 * Math.random() + 10);
+        h = 0;
+        while (h < 7) {
+            print("\n");
+            print("\n");
+            print("THIS IS HOUR " + (h + 1) + ", AT WHAT ANGLE DO YOU WISH TO SEND\n");
+            print("YOUR PHOTON BOMB");
+            a1 = parseFloat(await input());
+            print("HOW FAR OUT DO YOU WISH TO DETONATE IT");
+            d1 = parseFloat(await input());
+            print("\n");
+            print("\n");
+            a += r;
+            if (a >= 360)
+                a -= 360;
+            t = Math.abs(a - a1);
+            if (t >= 180)
+                t = 360 - t;
+            c = Math.sqrt(d * d + d1 * d1 - 2 * d * d1 * Math.cos(t * Math.PI / 180));
+            print("YOUR PHOTON BOMB EXPLODED " + c + "*10^2 MILES FROM THE\n");
+            print("ROMULAN SHIP.\n");
+            if (c <= 50)
+                break;
+            h++;
+        }
+        if (h == 7) {
+            print("YOU HAVE ALLOWED THE ROMULANS TO ESCAPE.\n");
+        } else {
+            print("YOU HAVE SUCCESSFULLY COMPLETED YOUR MISSION.\n");
+        }
+        print("ANOTHER ROMULAN SHIP HAS GONE INTO ORBIT.\n");
+        print("DO YOU WISH TO TRY TO DESTROY IT");
+        str = await input();
+        if (str != "YES")
+            break;
+    }
+    print("GOOD BYE.\n");
+}
+
+main();

From b37295be0aab93367e07f06a81e47e051306ea2e Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Tue, 2 Mar 2021 13:13:44 -0600
Subject: [PATCH 183/749] Ported PIZZA to Javascript

---
 69 Pizza/javascript/pizza.html |   9 ++
 69 Pizza/javascript/pizza.js   | 155 +++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+)
 create mode 100644 69 Pizza/javascript/pizza.html
 create mode 100644 69 Pizza/javascript/pizza.js

diff --git a/69 Pizza/javascript/pizza.html b/69 Pizza/javascript/pizza.html
new file mode 100644
index 00000000..30134499
--- /dev/null
+++ b/69 Pizza/javascript/pizza.html	
@@ -0,0 +1,9 @@
+
+
+PIZZA
+
+
+

+
+
+
diff --git a/69 Pizza/javascript/pizza.js b/69 Pizza/javascript/pizza.js
new file mode 100644
index 00000000..ba7fe578
--- /dev/null
+++ b/69 Pizza/javascript/pizza.js	
@@ -0,0 +1,155 @@
+// PIZZA
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var sa = [, "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"];
+var ma = [, "1","2","3","4"];
+var a = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "PIZZA\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("PIZZA DELIVERY GAME\n");
+    print("\n");
+    print("WHAT IS YOUR FIRST NAME");
+    ns = await input();
+    print("\n");
+    print("HI, " + ns + ". IN THIS GAME YOU ARE TO TAKE ORDERS\n");
+    print("FOR PIZZAS.  THEN YOU ARE TO TELL A DELIVERY BOY\n");
+    print("WHERE TO DELIVER THE ORDERED PIZZAS.\n");
+    print("\n");
+    print("\n");
+    print("MAP OF THE CITY OF HYATTSVILLE\n");
+    print("\n");
+    print(" -----1-----2-----3-----4-----\n");
+    k = 4;
+    for (i = 1; i <= 4; i++) {
+        print("-\n");
+        print("-\n");
+        print("-\n");
+        print("-\n");
+        print(ma[k]);
+        s1 = 16 - 4 * i + 1;
+        print("     " + sa[s1] + "     " + sa[s1 + 1] + "     " + sa[s1 + 2] + "     ");
+        print(sa[s1 + 3] + "     " + ma[k] + "\n");
+        k--;
+    }
+    print("-\n");
+    print("-\n");
+    print("-\n");
+    print("-\n");
+    print(" -----1-----2-----3-----4-----\n");
+    print("\n");
+    print("THE OUTPUT IS A MAP OF THE HOMES WHERE\n");
+    print("YOU ARE TO SEND PIZZAS.\n");
+    print("\n");
+    print("YOUR JOB IS TO GIVE A TRUCK DRIVER\n");
+    print("THE LOCATION OR COORDINATES OF THE\n");
+    print("HOME ORDERING THE PIZZA.\n");
+    print("\n");
+    while (1) {
+        print("DO YOU NEED MORE DIRECTIONS");
+        str = await input();
+        if (str == "YES" || str == "NO")
+            break;
+        print("'YES' OR 'NO' PLEASE, NOW THEN, ");
+    }
+    if (str == "YES") {
+        print("\n");
+        print("SOMEBODY WILL ASK FOR A PIZZA TO BE\n");
+        print("DELIVERED.  THEN A DELIVERY BOY WILL\n");
+        print("ASK YOU FOR THE LOCATION.\n");
+        print("     EXAMPLE:\n");
+        print("THIS IS J.  PLEASE SEND A PIZZA.\n");
+        print("DRIVER TO " + ns + ".  WHERE DOES J LIVE?\n");
+        print("YOUR ANSWER WOULD BE 2,3\n");
+        print("\n");
+        print("UNDERSTAND");
+        str = await input();
+        if (str != "YES") {
+            print("THIS JOB IS DEFINITELY TOO DIFFICULT FOR YOU. THANKS ANYWAY");
+            return;
+        }
+        print("GOOD.  YOU ARE NOW READY TO START TAKING ORDERS.\n");
+        print("\n");
+        print("GOOD LUCK!!\n");
+        print("\n");
+    }
+    while (1) {
+        for (i = 1; i <= 5; i++) {
+            s = Math.floor(Math.random() * 16 + 1);
+            print("\n");
+            print("HELLO " + ns + "'S PIZZA.  THIS IS " + sa[s] + ".\n");
+            print("  PLEASE SEND A PIZZA.\n");
+            while (1) {
+                print("  DRIVER TO " + ns + ":  WHERE DOES " + sa[s] + " LIVE");
+                str = await input();
+                a[1] = parseInt(str);
+                a[2] = parseInt(str.substr(str.indexOf(",") + 1));
+                t = a[1] + (a[2] - 1) * 4;
+                if (t != s) {
+                    print("THIS IS " + sa[t] + ". I DID NOT ORDER A PIZZA.\n");
+                    print("I LIVE AT " + a[1] + "," + a[2] + "\n");
+                } else {
+                    break;
+                }
+            }
+            print("HELLO " + ns + ".  THIS IS " + sa[s] + ", THANKS FOR THE PIZZA.\n");
+        }
+        print("\n");
+        print("DO YOU WANT TO DELIVER MORE PIZZAS");
+        str = await input();
+        if (str != "YES")
+            break;
+    }
+    print("\n");
+    print("O.K. " + ns + ", SEE YOU LATER!\n");
+    print("\n");
+}
+
+main();

From 4109132f34313cf07850dae8979fbd4bb3d15ee0 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Wed, 3 Mar 2021 08:17:17 +1030
Subject: [PATCH 184/749] Java port of Rock Paper Scissors

---
 .../java/src/RockScissors.java                | 212 ++++++++++++++++++
 1 file changed, 212 insertions(+)
 create mode 100644 74 Rock Scissors Paper/java/src/RockScissors.java

diff --git a/74 Rock Scissors Paper/java/src/RockScissors.java b/74 Rock Scissors Paper/java/src/RockScissors.java
new file mode 100644
index 00000000..952cd80e
--- /dev/null
+++ b/74 Rock Scissors Paper/java/src/RockScissors.java	
@@ -0,0 +1,212 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Rock Scissors Paper
+ * 

+ * Based on the Basic game of Rock Scissors here + * https://github.com/coding-horror/basic-computer-games/blob/main/74%20Rock%20Scissors%20Paper/rockscissors.bas + *

+ * 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 RockScissors { + + public static final int MAX_GAMES = 10; + + public static final int PAPER = 1; + public static final int SCISSORS = 2; + public static final int ROCK = 3; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + GET_NUMBER_GAMES, + START_ROUND, + PLAY_ROUND, + GAME_RESULT, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private enum WINNER { + COMPUTER, + PLAYER + } + + private WINNER gameWinner; + + int playerWins; + int computerWins; + int numberOfGames; + int currentGameCount; + int computersChoice; + + public RockScissors() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case START_GAME: + intro(); + currentGameCount = 0; + gameState = GAME_STATE.GET_NUMBER_GAMES; + + break; + + case GET_NUMBER_GAMES: + numberOfGames = displayTextAndGetNumber("HOW MANY GAMES? "); + if (numberOfGames <= MAX_GAMES) { + gameState = GAME_STATE.START_ROUND; + } else { + System.out.println("SORRY, BUT WE AREN'T ALLOWED TO PLAY THAT MANY."); + } + break; + + case START_ROUND: + currentGameCount++; + if (currentGameCount > numberOfGames) { + gameState = GAME_STATE.GAME_RESULT; + break; + } + System.out.println("GAME NUMBER: " + (currentGameCount)); + computersChoice = (int) (Math.random() * 3) + 1; + gameState = GAME_STATE.PLAY_ROUND; + + case PLAY_ROUND: + System.out.println("3=ROCK...2=SCISSORS...1=PAPER"); + int playersChoice = displayTextAndGetNumber("1...2...3...WHAT'S YOUR CHOICE? "); + if (playersChoice >= PAPER && playersChoice <= ROCK) { + switch (computersChoice) { + case PAPER: + System.out.println("...PAPER"); + break; + case SCISSORS: + System.out.println("...SCISSORS"); + break; + case ROCK: + System.out.println("...ROCK"); + break; + } + + if (playersChoice == computersChoice) { + System.out.println("TIE GAME. NO WINNER."); + } else { + switch (playersChoice) { + case PAPER: + if (computersChoice == SCISSORS) { + gameWinner = WINNER.COMPUTER; + } else if (computersChoice == ROCK) { + // Don't need to re-assign here, as its initialized to + // false I'd argue this aids readability. + gameWinner = WINNER.PLAYER; + } + break; + case SCISSORS: + if (computersChoice == ROCK) { + gameWinner = WINNER.COMPUTER; + } else if (computersChoice == PAPER) { + // Don't need to re-assign here, as its initialized to + // false I'd argue this aids readability. + gameWinner = WINNER.PLAYER; + } + break; + case ROCK: + if (computersChoice == PAPER) { + gameWinner = WINNER.COMPUTER; + } else if (computersChoice == SCISSORS) { + // Don't need to re-assign here, as its initialized to + // false I'd argue this aids readability. + gameWinner = WINNER.PLAYER; + } + break; + } + + if (gameWinner == WINNER.COMPUTER) { + System.out.println("WOW! I WIN!!!"); + computerWins++; + } else { + System.out.println("YOU WIN!!!"); + playerWins++; + } + } + gameState = GAME_STATE.START_ROUND; + } else { + System.out.println("INVALID."); + } + + break; + + case GAME_RESULT: + System.out.println(); + System.out.println("HERE IS THE FINAL GAME SCORE:"); + System.out.println("I HAVE WON " + computerWins + " GAME" + (computerWins != 1 ? "S." : ".")); + System.out.println("YOU HAVE WON " + playerWins + " GAME" + (playerWins != 1 ? "S." : ".")); + int tiedGames = numberOfGames - (computerWins + playerWins); + System.out.println("AND " + tiedGames + " GAME" + (tiedGames != 1 ? "S " : " ") + "ENDED IN A TIE."); + System.out.println(); + System.out.println("THANKS FOR PLAYING!!"); + gameState = GAME_STATE.GAME_OVER; + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(addSpaces(21) + "GAME OF ROCK, SCISSORS, PAPER"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.nextLine(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + public static void main(String[] args) { + + RockScissors rockScissors = new RockScissors(); + rockScissors.play(); + } +} \ No newline at end of file From 1e8e689e646a339ccaf8f3a1cb2e4e5174c5a1ca Mon Sep 17 00:00:00 2001 From: nanochess Date: Tue, 2 Mar 2021 16:15:13 -0600 Subject: [PATCH 185/749] Ported RUSSIAN ROULETTE to Javascript --- .../javascript/russianroulette.html | 9 ++ .../javascript/russianroulette.js | 93 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 76 Russian Roulette/javascript/russianroulette.html create mode 100644 76 Russian Roulette/javascript/russianroulette.js diff --git a/76 Russian Roulette/javascript/russianroulette.html b/76 Russian Roulette/javascript/russianroulette.html new file mode 100644 index 00000000..782fa23e --- /dev/null +++ b/76 Russian Roulette/javascript/russianroulette.html @@ -0,0 +1,9 @@ + + +RUSSIAN ROULETTE + + +


+
+
+
diff --git a/76 Russian Roulette/javascript/russianroulette.js b/76 Russian Roulette/javascript/russianroulette.js
new file mode 100644
index 00000000..d528cfff
--- /dev/null
+++ b/76 Russian Roulette/javascript/russianroulette.js	
@@ -0,0 +1,93 @@
+// RUSSIAN ROULETTE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(28) + "RUSSIAN ROULETTE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS IS A GAME OF >>>>>>>>>>RUSSIAN ROULETTE.\n");
+    restart = true;
+    while (1) {
+        if (restart) {
+            restart = false;
+            print("\n");
+            print("HERE IS A REVOLVER.\n");
+        }
+        print("TYPE '1' TO SPIN CHAMBER AND PULL TRIGGER.\n");
+        print("TYPE '2' TO GIVE UP.\n");
+        print("GO");
+        n = 0;
+        while (1) {
+            i = parseInt(await input());
+            if (i == 2) {
+                print("     CHICKEN!!!!!\n");
+                break;
+            }
+            n++;
+            if (Math.random() > 0.833333) {
+                print("     BANG!!!!!   YOU'RE DEAD!\n");
+                print("CONDOLENCES WILL BE SENT TO YOUR RELATIVES.\n");
+                break;
+            }
+            if (n > 10) {
+                print("YOU WIN!!!!!\n");
+                print("LET SOMEONE ELSE BLOW HIS BRAINS OUT.\n");
+                restart = true;
+                break;
+            }
+            print("- CLICK -\n");
+            print("\n");
+        }
+        print("\n");
+        print("\n");
+        print("\n");
+        print("...NEXT VICTIM...\n");
+    }
+}
+
+main();

From cbcfebfeb3059157d7331f446b1cff5b7cfdf0f6 Mon Sep 17 00:00:00 2001
From: Andrew Cooper 
Date: Wed, 3 Mar 2021 09:21:40 +1100
Subject: [PATCH 186/749] Add quadrant names

---
 .../csharp/Resources/RegionNames.txt          |  8 +++++++
 .../csharp/Resources/Strings.cs               |  1 +
 84 Super Star Trek/csharp/Space/Coordinate.cs |  2 ++
 84 Super Star Trek/csharp/Space/Galaxy.cs     | 23 +++++++++++++++++--
 4 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 84 Super Star Trek/csharp/Resources/RegionNames.txt

diff --git a/84 Super Star Trek/csharp/Resources/RegionNames.txt b/84 Super Star Trek/csharp/Resources/RegionNames.txt
new file mode 100644
index 00000000..e2f47d79
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/RegionNames.txt	
@@ -0,0 +1,8 @@
+Antares     Sirius
+Rigel       Deneb
+Procyon     Capella
+Vega        Betelgeuse
+Canopus     Aldebaran
+Altair      Regulus
+Sagittarius Arcturus
+Pollux      Spica
\ No newline at end of file
diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs
index 4592db31..210d22ba 100644
--- a/84 Super Star Trek/csharp/Resources/Strings.cs	
+++ b/84 Super Star Trek/csharp/Resources/Strings.cs	
@@ -14,6 +14,7 @@ namespace SuperStarTrek.Resources
         public static string Instructions => GetResource();
         public static string LowShields => GetResource();
         public static string Orders => GetResource();
+        public static string RegionNames => GetResource();
         public static string RepairEstimate => GetResource();
         public static string RepairPrompt => GetResource();
         public static string ReplayPrompt => GetResource();
diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinate.cs
index b3328c24..87fe6e89 100644
--- a/84 Super Star Trek/csharp/Space/Coordinate.cs	
+++ b/84 Super Star Trek/csharp/Space/Coordinate.cs	
@@ -14,6 +14,8 @@ namespace SuperStarTrek.Space
 
         public int X { get; }
         public int Y { get; }
+        public int RegionIndex => ((X - 1) << 1) + ((Y - 1) >> 2);
+        public int SubRegionIndex => (Y - 1) % 4;
 
         private int Validated(int value, string argumentName)
         {
diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs
index 171ecdea..88361645 100644
--- a/84 Super Star Trek/csharp/Space/Galaxy.cs	
+++ b/84 Super Star Trek/csharp/Space/Galaxy.cs	
@@ -1,17 +1,33 @@
 using System.Linq;
+using SuperStarTrek.Resources;
+
+using static System.StringSplitOptions;
 
 namespace SuperStarTrek.Space
 {
     internal class Galaxy
     {
+        private static readonly string[] _regionNames;
+        private static readonly string[] _subRegionIdentifiers;
         private readonly QuadrantInfo[][] _quadrants;
 
+        static Galaxy()
+        {
+            _regionNames = Strings.RegionNames.Split(new[] { ' ', '\n' }, RemoveEmptyEntries | TrimEntries);
+            _subRegionIdentifiers = new[] { "I", "II", "III", "IV" };
+        }
+
         public Galaxy()
         {
             var random = new Random();
 
-            _quadrants = Enumerable.Range(1, 8).Select(x =>
-                Enumerable.Range(1, 8).Select(y => QuadrantInfo.Create(new Coordinates(x, y), "")).ToArray())
+            _quadrants = Enumerable
+                .Range(1, 8)
+                .Select(x => Enumerable
+                    .Range(1, 8)
+                    .Select(y => new Coordinates(x, y))
+                    .Select(c => QuadrantInfo.Create(c, GetQuadrantName(c)))
+                    .ToArray())
                 .ToArray();
 
             if (StarbaseCount == 0)
@@ -30,5 +46,8 @@ namespace SuperStarTrek.Space
 
         public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount);
         public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
+
+        private static string GetQuadrantName(Coordinates coordinates) =>
+            $"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}";
     }
 }

From 1f013aa21595e77944c27c5ff6706200d21258ea Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Tue, 2 Mar 2021 16:45:12 -0600
Subject: [PATCH 187/749] Ported COMBAT to Javascript

---
 28 Combat/javascript/combat.html |   9 ++
 28 Combat/javascript/combat.js   | 203 +++++++++++++++++++++++++++++++
 2 files changed, 212 insertions(+)
 create mode 100644 28 Combat/javascript/combat.html
 create mode 100644 28 Combat/javascript/combat.js

diff --git a/28 Combat/javascript/combat.html b/28 Combat/javascript/combat.html
new file mode 100644
index 00000000..8a75f8f4
--- /dev/null
+++ b/28 Combat/javascript/combat.html	
@@ -0,0 +1,9 @@
+
+
+COMBAT
+
+
+

+
+
+
diff --git a/28 Combat/javascript/combat.js b/28 Combat/javascript/combat.js
new file mode 100644
index 00000000..be4d72a9
--- /dev/null
+++ b/28 Combat/javascript/combat.js	
@@ -0,0 +1,203 @@
+// CHOMP
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "COMBAT\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("I AM AT WAR WITH YOU.\n");
+    print("WE HAVE 72000 SOLDIERS APIECE.\n");
+    do {
+        print("\n");
+        print("DISTRIBUTE YOUR FORCES.\n");
+        print("\tME\t  YOU\n");
+        print("ARMY\t30000\t");
+        a = parseInt(await input());
+        print("NAVY\t20000\t");
+        b = parseInt(await input());
+        print("A. F.\t22000\t");
+        c = parseInt(await input());
+    } while (a + b + c > 72000) ;
+    d = 30000;
+    e = 20000;
+    f = 22000;
+    print("YOU ATTACK FIRST. TYPE (1) FOR ARMY; (2) FOR NAVY;\n");
+    print("AND (3) FOR AIR FORCE.\n");
+    y = parseInt(await input());
+    do {
+        print("HOW MANY MEN\n");
+        x = parseInt(await input());
+    } while ((y == 1 && x > a) || (y == 2 && x > b) || (y == 3 && x > c)) ;
+    switch (y) {
+        case 1:
+            if (x < a / 3.0) {
+                print("YOU LOST " + x + " MEN FROM YOUR ARMY.\n");
+                a -= x;
+                break;
+            }
+            if (x < 2 * a / 3) {
+                print("YOU LOST " + Math.floor(x / 3.0) + " MEN, BUT I LOST " + Math.floor(2 * d / 3.0) + "\n");
+                a = Math.floor(a - x / 3.0);
+                d = 0;
+                break;
+            }
+            print("YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO\n");
+            print("OF YOUR AIR FORCE BASES AND 3 ARMY BASES.\n");
+            a = Math.floor(a / 3.0);
+            c = Math.floor(c / 3.0);
+            e = Math.floor(2 * e / 3.0);
+            break;
+        case 2:
+            if (x < e / 3) {
+                print("YOUR ATTACK WAS STOPPED!\n");
+                b -= x;
+                break;
+            }
+            if (x < 2 * e / 3) {
+                print("YOU DESTROYED " + Math.floor(2 * e / 3.0) + " OF MY ARMY.\n");
+                e = Math.floor(e / 3.0);
+                break;
+            }
+            print("YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO\n");
+            print("OF YOUR AIR FORCE BASES AND 3 ARMY BASES.\n");
+            a = Math.floor(a / 3.0);
+            c = Math.floor(c / 3.0);
+            e = Math.floor(2 * e / 3.0);
+            break;
+        case 3:
+            if (x < c / 3.0) {
+                print("YOUR ATTACK WAS WIPED OUT.\n");
+                c -= x;
+                break;
+            }
+            if (x < 2 * c / 3) {
+                print("WE HAD A DOGFIGHT. YOU WON - AND FINISHED YOUR MISSION.\n");
+                d = Math.floor(2 * d / 3.0);
+                e = Math.floor(e / 3.0);
+                f = Math.floor(f / 3.0);
+                break;
+            }
+            print("YOU WIPED OUT ONE OF MY ARMY PATROLS, BUT I DESTROYED\n");
+            print("TWO NAVY BASES AND BOMBED THREE ARMY BASES.\n");
+            a = Math.floor(a / 4);
+            b = Math.floor(b / 3.0);
+            d = Math.floor(2 * d / 3.0);
+            break;
+    }
+    print("\n");
+    print("\tYOU\tME\n");
+    print("ARMY\t" + a + "\t" + d + "\n");
+    print("NAVY\t" + b + "\t" + e + "\n");
+    print("A. F.\t" + c + "\t" + f + "\n");
+    print("WHAT IS YOUR NEXT MOVE?\n");
+    print("ARMY=1  NAVY=2  AIR FORCE=3\n");
+    g = parseInt(await input());
+    do {
+        print("HOW MANY MEN\n");
+        t = parseInt(await input());
+    } while (t < 0 || (g == 1 && t > a) || (g == 2 && t > b) || (g == 3 && t > c)) ;
+    crashed = false;
+    switch (g) {
+        case 1:
+            if (t < d / 2) {
+                print("I WIPED OUT YOUR ATTACK!\n");
+                a -= t;
+            } else {
+                print("YOU DESTROYED MY ARMY!\n");
+                d = 0;
+            }
+            break;
+        case 2:
+            if (t < e / 2) {
+                print("I SUNK TWO OF YOUR BATTLESHIPS, AND MY AIR FORCE\n");
+                print("WIPED OUT YOUR UNGUARDED CAPITOL.\n");
+                a /= 4.0;
+                b /= 2.0;
+                break;
+            }
+            print("YOUR NAVY SHOT DOWN THREE OF MY XIII PLANES.\n");
+            print("AND SUNK THREE BATTLESHIPS.\n");
+            f = 2 * f / 3;
+            e /= 2;
+            break;
+        case 3:
+            if (t > f / 2) {
+                print("MY NAVY AND AIR FORCE IN A COMBINED ATTACK LEFT\n");
+                print("YOUR COUNTRY IN SHAMBLES.\n");
+                a /= 3.0;
+                b /= 3.0;
+                c /= 3.0;
+                break;
+            }
+            print("ONE OF YOUR PLANES CRASHED INTO MY HOUSE. I AM DEAD.\n");
+            print("MY COUNTRY FELL APART.\n");
+            crashed = true;
+            won = 1;
+            break;
+    }
+    if (!crashed) {
+        won = 0;
+        print("\n");
+        print("FROM THE RESULTS OF BOTH OF YOUR ATTACKS,\n");
+        if (a + b + c > 3.0 / 2.0 * (d + e + f))
+            won = 1;
+        if (a + b + c < 2.0 / 3.0 * (d + e + f))
+            won = 2;
+    }
+    if (won == 0) {
+        print("THE TREATY OF PARIS CONCLUDED THAT WE TAKE OUR\n");
+        print("RESPECTIVE COUNTRIES AND LIVE IN PEACE.\n");
+    } else if (won == 1) {
+        print("YOU WON, OH! SHUCKS!!!!\n");
+    } else if (won == 2) {
+        print("YOU LOST-I CONQUERED YOUR COUNTRY.  IT SERVES YOU\n");
+        print("RIGHT FOR PLAYING THIS STUPID GAME!!!\n");
+    }
+}
+
+main();

From 16291fdcea8a77354272ae89184c912ea1e83fac Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Wed, 3 Mar 2021 09:40:12 +1030
Subject: [PATCH 188/749] Java port of Russian Roulette

---
 .../java/src/RussianRoulette.java             | 143 ++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100644 76 Russian Roulette/java/src/RussianRoulette.java

diff --git a/76 Russian Roulette/java/src/RussianRoulette.java b/76 Russian Roulette/java/src/RussianRoulette.java
new file mode 100644
index 00000000..1bbf37bc
--- /dev/null
+++ b/76 Russian Roulette/java/src/RussianRoulette.java	
@@ -0,0 +1,143 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Russian Roulette Paper
+ * 

+ * Based on the Basic game of Russian Roulette here + * https://github.com/coding-horror/basic-computer-games/blob/main/76%20Russian%20Roulette/russianroulette.bas + *

+ * Based on the Basic game of Mugwump here + * https://github.com/coding-horror/basic-computer-games/blob/main/62%20Mugwump/mugwump.bas + *

+ * 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 Mugwump { + + public static final int NUMBER_OF_MUGWUMPS = 4; + + public static final int MAX_TURNS = 10; + + public static final int FOUND = -1; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + INIT, + GAME_START, + PLAY_TURN + } + + // Current game state + private GAME_STATE gameState; + + int[][] mugwumpLocations; + + int turn; + + public Mugwump() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.INIT; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case INIT: + intro(); + gameState = GAME_STATE.GAME_START; + + break; + + case GAME_START: + + turn = 0; + + // initialise all array elements with 0 + mugwumpLocations = new int[NUMBER_OF_MUGWUMPS][2]; + + // Place 4 mugwumps + for (int i = 0; i < NUMBER_OF_MUGWUMPS; i++) { + for (int j = 0; j < 2; j++) { + mugwumpLocations[i][j] = (int) (Math.random() * 10); + } + } + gameState = GAME_STATE.PLAY_TURN; + break; + + case PLAY_TURN: + turn++; + String locations = displayTextAndGetInput("TURN NO." + turn + " -- WHAT IS YOUR GUESS? "); + int distanceRightGuess = getDelimitedValue(locations, 0); + int distanceUpGuess = getDelimitedValue(locations, 1); + + int numberFound = 0; + for (int i = 0; i < NUMBER_OF_MUGWUMPS; i++) { + + if (mugwumpLocations[i][0] == FOUND) { + numberFound++; + } + + int right = mugwumpLocations[i][0]; + int up = mugwumpLocations[i][1]; + + if (right == distanceRightGuess && up == distanceUpGuess) { + if (right != FOUND) { + System.out.println("YOU HAVE FOUND MUGWUMP " + (i + 1)); + mugwumpLocations[i][0] = FOUND; + } + numberFound++; + } else { + // Not found so show distance + if (mugwumpLocations[i][0] != FOUND) { + double distance = Math.sqrt((Math.pow(right - distanceRightGuess, 2.0d)) + + (Math.pow(up - distanceUpGuess, 2.0d))); + + System.out.println("YOU ARE " + (int) ((distance * 10) / 10) + " UNITS FROM MUGWUMP"); + } + } + } + + if (numberFound == NUMBER_OF_MUGWUMPS) { + System.out.println("YOU GOT THEM ALL IN " + turn + " TURNS!"); + gameState = GAME_STATE.GAME_START; + } else if (turn >= MAX_TURNS) { + System.out.println("SORRY, THAT'S " + MAX_TURNS + " TRIES. HERE IS WHERE THEY'RE HIDING"); + for (int i = 0; i < NUMBER_OF_MUGWUMPS; i++) { + if (mugwumpLocations[i][0] != FOUND) { + System.out.println("MUGWUMP " + (i + 1) + " IS AT (" + + mugwumpLocations[i][0] + "," + mugwumpLocations[i][1] + ")"); + } + } + gameState = GAME_STATE.GAME_START; + } + + // Game ended? + if (gameState != GAME_STATE.PLAY_TURN) { + System.out.println("THAT WAS FUN! LET'S PLAY AGAIN......."); + System.out.println("FOUR MORE MUGWUMPS ARE NOW IN HIDING."); + } + } + // Infinite loop - based on original basic version + } while (true); + } + + private void intro() { + System.out.println(addSpaces(33) + "MUGWUMP"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THE OBJECT OF THIS GAME IS TO FIND FOUR MUGWUMPS"); + System.out.println("HIDDEN ON A 10 BY 10 GRID. HOMEBASE IS POSITION 0,0."); + System.out.println("ANY GUESS YOU MAKE MUST BE TWO NUMBERS WITH EACH"); + System.out.println("NUMBER BETWEEN 0 AND 9, INCLUSIVE. FIRST NUMBER"); + System.out.println("IS DISTANCE TO RIGHT OF HOMEBASE AND SECOND NUMBER"); + System.out.println("IS DISTANCE ABOVE HOMEBASE."); + System.out.println(); + System.out.println("YOU GET 10 TRIES. AFTER EACH TRY, I WILL TELL"); + System.out.println("YOU HOW FAR YOU ARE FROM EACH MUGWUMP."); + } + + /** + * Accepts a string delimited by comma's and returns the pos'th delimited + * value (starting at count 0). + * + * @param text - text with values separated by comma's + * @param pos - which position to return a value for + * @return the int representation of the value + */ + private int getDelimitedValue(String text, int pos) { + String[] tokens = text.split(","); + return Integer.parseInt(tokens[pos]); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.nextLine(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + public static void main(String[] args) { + + Mugwump mugwump = new Mugwump(); + mugwump.play(); + } +} \ No newline at end of file From ad5e2fc79ae8c9cf1c8dfe173d2d86b1bc4b17ad Mon Sep 17 00:00:00 2001 From: Jack Boyce Date: Tue, 2 Mar 2021 20:35:40 -0800 Subject: [PATCH 191/749] more cleanup and comments --- 84 Super Star Trek/python/superstartrek.py | 34 ++++++++++------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py index db2963a1..c5858798 100644 --- a/84 Super Star Trek/python/superstartrek.py +++ b/84 Super Star Trek/python/superstartrek.py @@ -50,7 +50,7 @@ def insert_marker(row, col, marker): if len(marker) != 3: print('ERROR') - quit() + exit() pos = round(col) * 3 + round(row) * 24 qs = qs[0:pos] + marker + qs[(pos + 3):192] @@ -231,14 +231,12 @@ def maneuver_energy(n): global e, s e -= n + 10 - if e > 0: - return - print("SHIELD CONTROL SUPPLIES ENERGY TO COMPLETE THE MANEUVER.") - s += e - e = 0 - if s <= 0: - s = 0 + if e <= 0: + print("SHIELD CONTROL SUPPLIES ENERGY TO COMPLETE THE MANEUVER.") + s += e + e = 0 + s = max(0, s) def short_range_scan(): @@ -252,8 +250,7 @@ def short_range_scan(): if compare_marker(i, j, '>!<'): docked = True cs = 'DOCKED' - e = e0 - p = p0 + e, p = e0, p0 print("SHIELDS DROPPED FOR DOCKING PURPOSES") s = 0 break @@ -310,8 +307,8 @@ def long_range_scan(): return print(f"LONG RANGE SCAN FOR QUADRANT {q1 + 1} , {q2 + 1}") - o1s = '-------------------' - print(o1s) + sep = '-------------------' + print(sep) for i in (q1 - 1, q1, q1 + 1): n = [-1, -2, -3] @@ -327,7 +324,7 @@ def long_range_scan(): else: line += str(n[l] + 1000).rjust(4, ' ')[-3:] + ' : ' print(line) - print(o1s) + print(sep) def phaser_control(): @@ -427,8 +424,7 @@ def photon_torpedoes(): while True: x += x1 y += x2 - x3 = round(x) - y3 = round(y) + x3, y3 = round(x), round(y) if x3 < 0 or x3 > 7 or y3 < 0 or y3 > 7: print("TORPEDO MISSED") klingons_fire() @@ -816,8 +812,8 @@ def new_quadrant(): global g, z, t, t0, s9, q1, q2, s1, s2 global k3, b3, s3, d4, k, qs, b4, b5 - k3 = b3 = s3 = 0 - d4 = 0.5 * random.random() + k3 = b3 = s3 = 0 # Klingons, bases, stars in quad. + d4 = 0.5 * random.random() # extra delay in repairs at base z[q1][q2] = g[q1][q2] if 0 <= q1 <= 7 and 0 <= q2 <= 7: @@ -847,7 +843,7 @@ def new_quadrant(): insert_marker(r1, r2, '+K+') k[i] = [r1, r2, s9 * (0.5 + random.random())] if b3 > 0: - b4, b5 = find_empty_place() + b4, b5 = find_empty_place() # position of starbase (sector) insert_marker(b4, b5, '>!<') for i in range(s3): r1, r2 = find_empty_place() @@ -886,7 +882,7 @@ def end_game(won=False, quit=True, enterprise_killed=False): # ------------------------------------------------------------------------- -# Game loop +# Entry point and main game loop # ------------------------------------------------------------------------- From 6a1794a4355e9ef3e4427672915265de06ad04cc Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Tue, 2 Mar 2021 22:07:08 -0800 Subject: [PATCH 192/749] complete port HEXAPAWN to Python refactoring for more pythonic idioms, moved parallel data arrays into a class, which helped structure board matching functionality and move list updating. Should be pretty readable now. --- 46 Hexapawn/python/hexapawn.py | 554 ++++++++++++++------------------- 1 file changed, 239 insertions(+), 315 deletions(-) diff --git a/46 Hexapawn/python/hexapawn.py b/46 Hexapawn/python/hexapawn.py index 50f2abc8..e89e3426 100644 --- a/46 Hexapawn/python/hexapawn.py +++ b/46 Hexapawn/python/hexapawn.py @@ -14,6 +14,38 @@ Conversion to MITS BASIC by Steve North Port to Python by Dave LeCompte """ +""" +PORTING NOTES: + +I printed out the BASIC code and hand-annotated what each little block +of code did, which feels amazingly retro. + +I encourage other porters that have a complex knot of GOTOs and +semi-nested subroutines to do hard-copy hacking, it might be a +different perspective that helps. + +A spoiler - the objective of the game is not documented, ostensibly to +give the human player a challenge. If a player (human or computer) +advances a pawn across the board to the far row, that player wins. If +a player has no legal moves (either by being blocked, or all their +pieces having been captured), that player loses. + +The original BASIC had 2 2-dimensional tables stored in DATA at the +end of the program. This encoded all 19 different board configurations +(Hexapawn is a small game), with reflections in one table, and then in +a parallel table, for each of the 19 rows, a list of legal moves was +encoded by turning them into 2-digit decimal numbers. As gameplay +continued, the AI would overwrite losing moves with 0 in the second +array. + +My port takes this "parallel array" structure and turns that +information into a small Python class, BoardLayout. BoardLayout stores +the board description and legal moves, but stores the moves as (row, +column) 2-tuples, which is easier to read. The logic for checking if a +BoardLayout matches the current board, as well as removing losing move +have been moved into methods of this class. +""" + import collections import random @@ -23,12 +55,19 @@ HUMAN_PIECE = 1 EMPTY_SPACE = 0 COMPUTER_PIECE = -1 -ComputerMove = collections.namedtuple('ComputerMove', ['x', 'y', 'm1', 'm2']) +ComputerMove = collections.namedtuple( + "ComputerMove", ["board_index", "move_index", "m1", "m2"] +) + +wins = 0 +losses = 0 + def print_centered(msg): spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) print(spaces + msg) + def print_header(title): print_centered(title) print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") @@ -36,8 +75,10 @@ def print_header(title): print() print() + def print_instructions(): - print(""" + print( + """ THIS PROGRAM PLAYS THE GAME OF HEXAPAWN. HEXAPAWN IS PLAYED WITH CHESS PAWNS ON A 3 BY 3 BOARD. THE PAWNS ARE MOVED AS IN CHESS - ONE SPACE FORWARD TO @@ -67,7 +108,8 @@ YOU WOULD TYPE 9,6 IN RESPONSE TO THE QUESTION 'YOUR MOVE ?'. SINCE I'M A GOOD SPORT, YOU'LL ALWAYS GO FIRST. -""") +""" + ) def prompt_yes_no(msg): @@ -79,208 +121,239 @@ def prompt_yes_no(msg): elif response[0] == "N": return False -def reverse_board_position(x): - assert(x >= 1 and x < 10) - - score = {1: 3, - 2: 2, - 3: 1, - 4: 6, - 5: 5, - 6: 4, - 7: 9, - 8: 8, - 9: 7} - return score[x] -def get_b(x, y): - data = [[-1, -1, -1, 1, 0, 0, 0, 1, 1], - [-1, -1, -1, 0, 1, 0, 1, 0, 1], - [-1, 0, -1, -1, 1, 0, 0, 0, 1], - [ 0, -1, -1, 1, -1, 0, 0, 0, 1], - [-1, 0, -1, 1, 1, 0, 0, 1, 0], - [-1, -1, 0, 1, 0, 1, 0, 0, 1], - [ 0, -1, -1, 0, -1, 1, 1, 0, 0], - [ 0, -1, -1, -1, 1, 1, 1, 0, 0], - [-1, 0, -1, -1, 0, 1, 0, 1, 0], - [ 0, -1, -1, 0, 1, 0, 0, 0, 1], - [ 0, -1, -1, 0, 1, 0, 1, 0, 0], - [-1, 0, -1, 1, 0, 0, 0, 0, 1], - [ 0, 0, -1, -1, -1, 1, 0, 0, 0], - [-1, 0, 0, 1, 1, 1, 0, 0, 0], - [ 0, -1, 0, -1, 1, 1, 0, 0, 0], - [-1, 0, 0, -1, -1, 1, 0, 0, 0], - [ 0, 0, -1, -1, 1, 0, 0, 0, 0], - [ 0, -1, 0, 1, -1, 0, 0, 0, 0], - [-1, 0, 0, -1, 1, 0, 0, 0, 0]] +def reverse_space_name(space_name): + # reverse a space name in the range 1-9 left to right + assert 1 <= space_name <= 9 - assert(x >= 1 and x < 20) - assert(y >= 1 and y < 10) + reflections = {1: 3, 2: 2, 3: 1, 4: 6, 5: 5, 6: 4, 7: 9, 8: 8, 9: 7} + return reflections[space_name] - return data[x-1][y-1] -m_data = [[24, 25, 36, 0], - [14, 15, 36, 0], - [15, 35, 36, 47], - [36, 58, 59, 0], - [15, 35, 36, 0], - [24, 25, 26, 0], - [26, 57, 58, 0], - [26, 35, 0, 0], - [47, 48, 0, 0], - [35, 36, 0, 0], - [35, 36, 0, 0], - [36, 0, 0, 0], - [47, 58, 0, 0], - [15, 0, 0, 0], - [26, 47, 0, 0], - [47, 58, 0, 0], - [35, 36, 47, 0], - [28, 58, 0, 0], - [15, 47, 0, 0]] +def is_space_in_center_column(space_name): + return reverse_space_name(space_name) == space_name -def get_m(x, y): - assert(x >= 1 and x < 20) - assert(y >= 1 and y < 5) - return m_data[x-1][y-1] +class BoardLayout: + def __init__(self, cells, move_list): + self.cells = cells + self.moves = move_list + + def _check_match_no_mirror(self, cell_list): + for space_index, board_contents in enumerate(self.cells): + if board_contents != cell_list[space_index]: + return False + return True + + def _check_match_with_mirror(self, cell_list): + for space_index, board_contents in enumerate(self.cells): + reversed_space_index = reverse_space_name(space_index + 1) - 1 + if board_contents != cell_list[reversed_space_index]: + return False + return True + + def check_match(self, cell_list): + if self._check_match_with_mirror(cell_list): + return True, True + elif self._check_match_no_mirror(cell_list): + return True, False + return False, None + + def get_random_move(self, reverse_board): + if not self.moves: + return None + move_index = random.randrange(len(self.moves)) + + m1, m2 = self.moves[move_index] + if reverse_board: + m1 = reverse_space_name(m1) + m2 = reverse_space_name(m2) + + return move_index, m1, m2 + + +boards = [ + BoardLayout([-1, -1, -1, 1, 0, 0, 0, 1, 1], [(2, 4), (2, 5), (3, 6)]), + BoardLayout([-1, -1, -1, 0, 1, 0, 1, 0, 1], [(1, 4), (1, 5), (3, 6)]), + BoardLayout([-1, 0, -1, -1, 1, 0, 0, 0, 1], [(1, 5), (3, 5), (3, 6), (4, 7)]), + BoardLayout([0, -1, -1, 1, -1, 0, 0, 0, 1], [(3, 6), (5, 8), (5, 9)]), + BoardLayout([-1, 0, -1, 1, 1, 0, 0, 1, 0], [(1, 5), (3, 5), (3, 6)]), + BoardLayout([-1, -1, 0, 1, 0, 1, 0, 0, 1], [(2, 4), (2, 5), (2, 6)]), + BoardLayout([0, -1, -1, 0, -1, 1, 1, 0, 0], [(2, 6), (5, 7), (5, 8)]), + BoardLayout([0, -1, -1, -1, 1, 1, 1, 0, 0], [(2, 6), (3, 5)]), + BoardLayout([-1, 0, -1, -1, 0, 1, 0, 1, 0], [(4, 7), (4, 8)]), + BoardLayout([0, -1, -1, 0, 1, 0, 0, 0, 1], [(3, 5), (3, 6)]), + BoardLayout([0, -1, -1, 0, 1, 0, 1, 0, 0], [(3, 5), (3, 6)]), + BoardLayout([-1, 0, -1, 1, 0, 0, 0, 0, 1], [(3, 6)]), + BoardLayout([0, 0, -1, -1, -1, 1, 0, 0, 0], [(4, 7), (5, 8)]), + BoardLayout([-1, 0, 0, 1, 1, 1, 0, 0, 0], [(1, 5)]), + BoardLayout([0, -1, 0, -1, 1, 1, 0, 0, 0], [(2, 6), (4, 7)]), + BoardLayout([-1, 0, 0, -1, -1, 1, 0, 0, 0], [(4, 7), (5, 8)]), + BoardLayout([0, 0, -1, -1, 1, 0, 0, 0, 0], [(3, 5), (3, 6), (4, 7)]), + BoardLayout([0, -1, 0, 1, -1, 0, 0, 0, 0], [(2, 8), (5, 8)]), + BoardLayout([-1, 0, 0, -1, 1, 0, 0, 0, 0], [(1, 5), (4, 7)]), +] + + +def get_move(board_index, move_index): + assert board_index >= 0 and board_index < len(boards) + board = boards[board_index] + + assert move_index >= 0 and move_index < len(board.moves) + + return board.moves[move_index] + + +def remove_move(board_index, move_index): + assert board_index >= 0 and board_index < len(boards) + board = boards[board_index] + + assert move_index >= 0 and move_index < len(board.moves) + + del board.moves[move_index] -def set_m(x, y, value): - m_data[x-1][y-1] = value def init_board(): - return ([COMPUTER_PIECE] * 3 + - [EMPTY_SPACE] * 3 + - [HUMAN_PIECE] * 3) + return [COMPUTER_PIECE] * 3 + [EMPTY_SPACE] * 3 + [HUMAN_PIECE] * 3 + def print_board(board): - piece_dict = {COMPUTER_PIECE: 'X', - EMPTY_SPACE: '.', - HUMAN_PIECE: 'O'} + piece_dict = {COMPUTER_PIECE: "X", EMPTY_SPACE: ".", HUMAN_PIECE: "O"} - space = " "*10 + space = " " * 10 print() - for i in range(3): + for row in range(3): line = "" - for j in range(3): + for column in range(3): line += space - space_number = i * 3 + j + space_number = row * 3 + column space_contents = board[space_number] line += piece_dict[space_contents] print(line) print() + def get_coordinates(): while True: try: - print ("YOUR MOVE?") + print("YOUR MOVE?") response = input() - m1, m2 = [int(c) for c in response.split(',')] + m1, m2 = [int(c) for c in response.split(",")] return m1, m2 except ValueError as ve: print_illegal() + def print_illegal(): print("ILLEGAL MOVE.") + def board_contents(board, space_number): return board[space_number - 1] + def set_board(board, space_number, new_value): board[space_number - 1] = new_value -def is_legal_move(board, m1, m2): + +def is_legal_human_move(board, m1, m2): if board_contents(board, m1) != HUMAN_PIECE: # Start space doesn't contain player's piece return False if board_contents(board, m2) == HUMAN_PIECE: # Destination space contains player's piece (can't capture your own piece) return False - # line 160 - is_capture = (m2-m1 != -3) + + is_capture = m2 - m1 != -3 if is_capture and board_contents(board, m2) != COMPUTER_PIECE: # Destination does not contain computer piece return False - # line 170 + if m2 > m1: # can't move backwards return False - # line 180 + if (not is_capture) and board_contents(board, m2) != EMPTY_SPACE: # Destination is not open return False - # line 185 - if m2-m1 < -4: + + if m2 - m1 < -4: # too far return False - # line 186 + if m1 == 7 and m2 == 3: # can't jump corner to corner (wrapping around the board) return False return True + def player_piece_on_back_row(board): - for space in range(1,4): + for space in range(1, 4): if board_contents(board, space) == HUMAN_PIECE: return True return False + def computer_piece_on_front_row(board): for space in range(7, 10): if board_contents(board, space) == COMPUTER_PIECE: return True return False + def all_human_pieces_captured(board): return len(list(get_human_spaces(board))) == 0 + def all_computer_pieces_captured(board): return len(list(get_computer_spaces(board))) == 0 + def human_win(last_computer_move): print("YOU WIN") - set_m(last_computer_move.x, last_computer_move.y, 0) - global l - l += 1 + remove_move(last_computer_move.board_index, last_computer_move.move_index) + global losses + losses += 1 + def computer_win(has_moves): - if has_moves: + if not has_moves: msg = "YOU CAN'T MOVE, SO " else: msg = "" msg += "I WIN" print(msg) - global w - w += 1 + global wins + wins += 1 + def show_scores(): - print(f"I HAVE WON {w} AND YOU {l} OUT OF {w+l} GAMES.") + print(f"I HAVE WON {wins} AND YOU {losses} OUT OF {wins + losses} GAMES.") print() + def human_has_move(board): - # line 690 for i in get_human_spaces(board): - if board_contents(board, i-3) == EMPTY_SPACE: + if board_contents(board, i - 3) == EMPTY_SPACE: # can move piece forward return True - elif reverse_board_position(i) == i: - # line 780 - # can capture from center - if ((board_contents(board, i-2) == COMPUTER_PIECE) or - (board_contents(board, i-4) == COMPUTER_PIECE)): + elif is_space_in_center_column(i): + if (board_contents(board, i - 2) == COMPUTER_PIECE) or ( + board_contents(board, i - 4) == COMPUTER_PIECE + ): + # can capture from center return True else: - continue + continue elif i < 7: - # Line 760 - assert((i == 4) or (i == 6)) - # can capture computer piece at 2 + assert (i == 4) or (i == 6) if board_contents(board, 2) == COMPUTER_PIECE: + # can capture computer piece at 2 return True else: continue elif board_contents(board, 5) == COMPUTER_PIECE: - assert((i == 7) or (i == 9)) + assert (i == 7) or (i == 9) # can capture computer piece at 5 return True else: @@ -289,38 +362,43 @@ def human_has_move(board): def get_board_spaces(): + """ generates the space names (1-9)""" yield from range(1, 10) + def get_board_spaces_with(board, val): + """ generates spaces containing pieces of type val""" for i in get_board_spaces(): if board_contents(board, i) == val: yield i + def get_human_spaces(board): yield from get_board_spaces_with(board, HUMAN_PIECE) + def get_empty_spaces(board): yield from get_board_spaces_with(board, EMPTY_SPACE) + def get_computer_spaces(board): yield from get_board_spaces_with(board, COMPUTER_PIECE) - + def has_computer_move(board): for i in get_computer_spaces(board): found_move = False - if board_contents(board, i+3) == EMPTY_SPACE: + if board_contents(board, i + 3) == EMPTY_SPACE: # can move forward (down) return True - # line 260 - if reverse_board_position(i) == i: + if is_space_in_center_column(i): # i is in the middle column - if ((board_contents(board, i + 2) == HUMAN_PIECE) or - (board_contents(board, i + 4) == HUMAN_PIECE)): + if (board_contents(board, i + 2) == HUMAN_PIECE) or ( + board_contents(board, i + 4) == HUMAN_PIECE + ): return True else: - # line 270 if i > 3: # beyond the first row if board_contents(board, 8) == HUMAN_PIECE: @@ -329,7 +407,6 @@ def has_computer_move(board): else: continue else: - # line 280 if board_contents(board, 5) == HUMAN_PIECE: # can capture on 5 return True @@ -337,104 +414,48 @@ def has_computer_move(board): continue return False -def get_flipped_table(b_line): # TODO remove table altogether - t = {} - # line 360 - for row in range(1, 4): - for column in range(1, 4): - # line 380 - flipped_column = 4 - column - - # fill out t to represent the data from b flipped left to right - space = (row-1) * 3 + column - flipped_space = (row - 1) * 3 + flipped_column - - t[space] = get_b(b_line, flipped_space) - return t -def board_matches_b(b_line, board): - for s in get_board_spaces(): - if get_b(b_line, s) != board_contents(board, s): - return False - return True +def find_board_index_that_matches_board(board): + for board_index, board_layout in enumerate(boards): + matches, is_reversed = board_layout.check_match(board) + if matches: + return board_index, is_reversed -def board_matches_flipped_b(b_line, board): - flipped_table = get_flipped_table(b_line) - - for s in get_board_spaces(): - if flipped_table[s] != board_contents(board, s): - return False - return True - -def does_b_line_match(b_line, board): - if board_matches_b(b_line, board): - return True, False - elif board_matches_flipped_b(b_line, board): - return True, True - else: - return False, None - -def has_any_m_table(x): - for i in range(1,5): - if get_m(x, i) != 0: - return True - return False - -def pick_from_m_table(x): - valid_y_list = [y for y in range(1,5) if get_m(x, y) != 0] - assert(len(valid_y_list) > 0) - return random.choice(valid_y_list) - - -def get_move_for_b_line(b_line, reverse_board): - # line 540 - x = b_line - - if not has_any_m_table(x): - return None - - # line 600 - y = pick_from_m_table(x) - - # line 610 - mxy = get_m(x, y) - m1 = mxy // 10 - m2 = mxy % 10 - if reverse_board: - m1 = reverse_board_position(m1) - m2 = reverse_board_position(m2) - - return ComputerMove(x, y, m1, m2) - - -def find_b_line_that_matches_board(board): - for b_line in range(1,20): - matches, reverse_board = does_b_line_match(b_line, board) - if matches: - return b_line, reverse_board - # THE TERMINATION OF THIS LOOP IS IMPOSSIBLE print("ILLEGAL BOARD PATTERN.") - assert(False) - - + assert False + + def pick_computer_move(board): if not has_computer_move(board): - # Line 340 return None - # line 350 - b_line, reverse_board = find_b_line_that_matches_board(board) + board_index, reverse_board = find_board_index_that_matches_board(board) - m = get_move_for_b_line(b_line, reverse_board) + m = boards[board_index].get_random_move(reverse_board) - if m == None: + if m is None: print("I RESIGN") return None - return m - - + move_index, m1, m2 = m + + return ComputerMove(board_index, move_index, m1, m2) + + +def get_human_move(board): + while True: + m1, m2 = get_coordinates() + + if not is_legal_human_move(board, m1, m2): + print_illegal() + else: + return m1, m2 + + +def apply_move(board, m1, m2, piece_value): + set_board(board, m1, EMPTY_SPACE) + set_board(board, m2, piece_value) def play_game(): @@ -444,149 +465,52 @@ def play_game(): while True: print_board(board) - - has_legal_move = False - while not has_legal_move: - m1, m2 = get_coordinates() - - if not is_legal_move(board, m1, m2): - print_illegal() - else: - # otherwise, acceptable move - has_legal_move = True - - set_board(board, m1, 0) - set_board(board, m2, 1) - - # line 205 + + m1, m2 = get_human_move(board) + + apply_move(board, m1, m2, HUMAN_PIECE) + print_board(board) - - if (player_piece_on_back_row(board) or - all_computer_pieces_captured(board)): + + if player_piece_on_back_row(board) or all_computer_pieces_captured(board): human_win(last_computer_move) return - - # line 230 + computer_move = pick_computer_move(board) if computer_move is None: human_win(last_computer_move) return last_computer_move = computer_move - + m1, m2 = last_computer_move.m1, last_computer_move.m2 - + print(f"I MOVE FROM {m1} TO {m2}") - set_board(board, m1, 0) - set_board(board, m2, -1) - - # line 640 + apply_move(board, m1, m2, COMPUTER_PIECE) + print_board(board) - - if (computer_piece_on_front_row(board) or - all_human_pieces_captured(board)): + + if computer_piece_on_front_row(board): computer_win(True) return - elif not human_has_move(board): + elif (not human_has_move(board)) or (all_human_pieces_captured(board)): computer_win(False) return - - - - + def main(): print_header("HEXAPAWN") if prompt_yes_no("INSTRUCTIONS (Y-N)?"): print_instructions() - global w, l - w = 0 - l = 0 + global wins, losses + wins = 0 + losses = 0 while True: play_game() show_scores() - + + if __name__ == "__main__": main() - -""" -230 FOR I=1 TO 9 -240 IF S(I)<>-1 THEN 330 -250 IF S(I+3)=0 THEN 350 -260 IF FNR(I)=I THEN 320 -270 IF I>3 THEN 300 -280 IF S(5)=1 THEN 350 -290 GOTO 330 -300 IF S(8)=1 THEN 350 -310 GOTO 330 -320 IF S(I+2)=1 OR S(I+4)=1 THEN 350 -330 NEXT I -340 GOTO 820 -350 FOR I=1 TO 19 -360 FOR J=1 TO 3 -370 FOR K=3 TO 1 STEP -1 -380 T((J-1)*3+K)=B(I,(J-1)*3+4-K) -390 NEXT K -400 NEXT J -410 FOR J=1 TO 9 -420 IF S(J)<>B(I,J) THEN 460 -430 NEXT J -440 R=0 -450 GOTO 540 -460 FOR J=1 TO 9 -470 IF S(J)<>T(J) THEN 510 -480 NEXT J -490 R=1 -500 GOTO 540 -510 NEXT I -511 REMEMBER THE TERMINATION OF THIS LOOP IS IMPOSSIBLE -512 PRINT "ILLEGAL BOARD PATTERN." -530 STOP -540 X=I -550 FOR I=1 TO 4 -560 IF M(X,I)<>0 THEN 600 -570 NEXT I -580 PRINT "I RESIGN." -590 GOTO 820 -600 Y=INT(RND(1)*4+1) -601 IF M(X,Y)=0 THEN 600 -610 IF R<>0 THEN 630 -620 PRINT "I MOVE FROM ";STR$(INT(M(X,Y)/10));" TO ";STR$(FNM(M(X,Y))) -622 S(INT(M(X,Y)/10))=0 -623 S(FNM(M(X,Y)))=-1 -624 GOTO 640 -630 PRINT "I MOVE FROM ";STR$(FNR(INT(M(X,Y)/10)));" TO "; -631 PRINT STR$(FNR(FNM(M(X,Y)))) -632 S(FNR(INT(M(X,Y)/10)))=0 -633 S(FNR(FNM(M(X,Y))))=-1 -640 GOSUB 1000 -641 IF S(7)=-1 OR S(8)=-1 OR S(9)=-1 THEN 870 -650 FOR I=1 TO 9 -660 IF S(I)=1 THEN 690 -670 NEXT I -680 GOTO 870 -690 FOR I=1 TO 9 -700 IF S(I)<>1 THEN 790 -710 IF S(I-3)=0 THEN 120 -720 IF FNR(I)=I THEN 780 -730 IF I<7 THEN 760 -740 IF S(5)=-1 THEN 120 -750 GOTO 790 -760 IF S(2)=-1 THEN 120 -770 GOTO 790 -780 IF S(I-2)=-1 OR S(I-4)=-1 THEN 120 -790 NEXT I -800 PRINT "YOU CAN'T MOVE, SO "; -810 GOTO 870 -820 PRINT "YOU WIN." -830 M(X,Y)=0 -840 L=L+1 -850 PRINT "I HAVE WON";W;"AND YOU";L;"OUT OF";L+W;"GAMES." -851 PRINT -860 GOTO 100 -870 PRINT "I WIN." -880 W=W+1 -890 GOTO 850 -""" From 01fc5fbd0d9d6f494cab194b79a71238e43c52e3 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:09:54 +1030 Subject: [PATCH 193/749] Java version of Bunny --- 19 Bunny/java/src/Bunny.java | 167 +++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 19 Bunny/java/src/Bunny.java diff --git a/19 Bunny/java/src/Bunny.java b/19 Bunny/java/src/Bunny.java new file mode 100644 index 00000000..726491ea --- /dev/null +++ b/19 Bunny/java/src/Bunny.java @@ -0,0 +1,167 @@ +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Bunny + *

+ * Based on the Basic program Bunny + * https://github.com/coding-horror/basic-computer-games/blob/main/19%20Bunny/bunny.bas + *

+ * 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 Bunny { + + // First 4 elements are the text BUNNY, so skip those + public static final int REAL_DATA_START_POS = 5; + + // Data for characters is not representative of three ASCII character, so we have + // to add 64 to it as per original program design. + public static final int CONVERT_TO_ASCII = 64; + + public static final int EOF = 4096; //End of file + public static final int EOL = -1; // End of line + + // Contains the data to draw the picture + private final ArrayList data; + + public Bunny() { + data = loadData(); + } + + /** + * Show an intro, accept a message, then draw the picture. + */ + public void process() { + + intro(); + + // First 5 characters of data spells out BUNNY, so add this to a string + StringBuilder bunnyBuilder = new StringBuilder(); + for (int i = 0; i < REAL_DATA_START_POS; i++) { + // Convert the data to the character representation for output + // Ascii A=65, B=66 - see loadData method + bunnyBuilder.append(Character.toChars(data.get(i) + CONVERT_TO_ASCII)); + } + + // We now have the string to be used in the output + String bunny = bunnyBuilder.toString(); + + int pos = REAL_DATA_START_POS; // Point to the start of the actual data + int previousPos = 0; + + // Loop until we reach a number indicating EOF + while (true) { + // This is where we want to start drawing + int first = data.get(pos); + if (first == EOF) { + break; + } + if (first == EOL) { + System.out.println(); + previousPos = 0; + // Move to the next element in the ArrayList + pos++; + continue; + } + + // Because we are not using screen positioning, we just add an appropriate + // numbers of spaces from where we want to be, and where we last outputted something + System.out.print(addSpaces(first - previousPos)); + + // We use this next time around the loop + previousPos = first; + + // Move to next element + pos++; + // This is where we want to stop drawing/ + int second = data.get(pos); + + // Now we loop through the number of characters to draw using + // the starting and ending point. + for (int i = first; i <= second; i++) { + // Cycle through the actual number of characters but use the + // remainder operator to ensure we only use characters from the + // bunny string + System.out.print(bunny.charAt(i % bunny.length())); + // Advance where we were at. + previousPos += 1; + } + // Point to next data element + pos++; + } + + System.out.println(); + + } + + private void intro() { + System.out.println(addSpaces(33) + "BUNNY"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Original Basic program had the data in DATA format. + * We're importing all the data into an array for ease of processing. + * Format of data is + * characters 0-4 is the letters that will be used in the output. 64 + the value represents the ASCII character + * ASCII code 65 = A, 66 = B, etc. so 2+64=66 (B), 21+64=85 (U) and so on. + * Then we next have pairs of numbers. + * Looking at the this data + * 1,2,-1,0,2,45,50,-1 + * That reads as + * 1,2 = draw characters - in this case BU + * -1 = go to a new line + * 0,2 = DRAW BUN + * 45,50 = DRAW BUNNYB starting at position 45 + * and so on. + * 4096 is EOF + * + * @return ArrayList of type Integer containing the data + */ + private ArrayList loadData() { + + ArrayList theData = new ArrayList<>(); + + // This is the data faithfully added from the original basic program. + // Notes: + // The first 5 ints are ASCII character (well 64 is added to make them ASCII chars we can output). + theData.addAll(Arrays.asList(2, 21, 14, 14, 25)); + theData.addAll(Arrays.asList(1, 2, -1, 0, 2, 45, 50, -1, 0, 5, 43, 52, -1, 0, 7, 41, 52, -1)); + theData.addAll(Arrays.asList(1, 9, 37, 50, -1, 2, 11, 36, 50, -1, 3, 13, 34, 49, -1, 4, 14, 32, 48, -1)); + theData.addAll(Arrays.asList(5, 15, 31, 47, -1, 6, 16, 30, 45, -1, 7, 17, 29, 44, -1, 8, 19, 28, 43, -1)); + theData.addAll(Arrays.asList(9, 20, 27, 41, -1, 10, 21, 26, 40, -1, 11, 22, 25, 38, -1, 12, 22, 24, 36, -1)); + theData.addAll(Arrays.asList(13, 34, -1, 14, 33, -1, 15, 31, -1, 17, 29, -1, 18, 27, -1)); + theData.addAll(Arrays.asList(19, 26, -1, 16, 28, -1, 13, 30, -1, 11, 31, -1, 10, 32, -1)); + theData.addAll(Arrays.asList(8, 33, -1, 7, 34, -1, 6, 13, 16, 34, -1, 5, 12, 16, 35, -1)); + theData.addAll(Arrays.asList(4, 12, 16, 35, -1, 3, 12, 15, 35, -1, 2, 35, -1, 1, 35, -1)); + theData.addAll(Arrays.asList(2, 34, -1, 3, 34, -1, 4, 33, -1, 6, 33, -1, 10, 32, 34, 34, -1)); + theData.addAll(Arrays.asList(14, 17, 19, 25, 28, 31, 35, 35, -1, 15, 19, 23, 30, 36, 36, -1)); + theData.addAll(Arrays.asList(14, 18, 21, 21, 24, 30, 37, 37, -1, 13, 18, 23, 29, 33, 38, -1)); + theData.addAll(Arrays.asList(12, 29, 31, 33, -1, 11, 13, 17, 17, 19, 19, 22, 22, 24, 31, -1)); + theData.addAll(Arrays.asList(10, 11, 17, 18, 22, 22, 24, 24, 29, 29, -1)); + theData.addAll(Arrays.asList(22, 23, 26, 29, -1, 27, 29, -1, 28, 29, -1, 4096)); + + return theData; + } + + public static void main(String[] args) { + + Bunny bunny = new Bunny(); + bunny.process(); + } +} \ No newline at end of file From d891aeca94a82bdb6849f7f57dcb56b1b1a9ec34 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:10:58 +1030 Subject: [PATCH 194/749] Removed debugging output from Java port of Love --- 58 Love/java/src/Love.java | 1 - 1 file changed, 1 deletion(-) diff --git a/58 Love/java/src/Love.java b/58 Love/java/src/Love.java index ab06f303..89c1c1de 100644 --- a/58 Love/java/src/Love.java +++ b/58 Love/java/src/Love.java @@ -158,7 +158,6 @@ public class Love { theData.addAll(Arrays.asList(8, 6, 5, 3, 14, 6, 7, 1, 10, 9, 6, 3, 3, 15, 6, 16, 1, 1)); theData.addAll(Arrays.asList(9, 6, 3, 3, 15, 6, 15, 2, 1, 10, 6, 1, 3, 16, 6, 14, 3, 1, 10, 10, 16, 6, 12, 5, 1)); theData.addAll(Arrays.asList(11, 8, 13, 27, 1, 11, 8, 13, 27, 1, 60)); - System.out.println(theData.size()); return theData; } From 8e66cbbcc2c393123a916b2ff82562f859f37ba7 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Tue, 2 Mar 2021 22:43:52 -0800 Subject: [PATCH 195/749] port CHANGE to Python straightforward change(CHANGE!), the biggest modification is that it's considered bad practice to use floating point numbers for dollars, so I converted the entire program to pennies. Exercise for the reader, how about using locale information to try to guess what currency system the user is using? Also, this clearly comes from a time before ATMs making $20 bills super common. --- 22 Change/python/change.py | 113 +++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 22 Change/python/change.py diff --git a/22 Change/python/change.py b/22 Change/python/change.py new file mode 100644 index 00000000..cb9e72e9 --- /dev/null +++ b/22 Change/python/change.py @@ -0,0 +1,113 @@ +""" +CHANGE + +Change calculator + +Port by Dave LeCompte +""" + +PAGE_WIDTH = 64 + + +def print_centered(msg): + spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) + print(spaces + msg) + + +def print_header(title): + print_centered(title) + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + +def print_introduction(): + print("I, YOUR FRIENDLY MICROCOMPUTER, WILL DETERMINE") + print("THE CORRECT CHANGE FOR ITEMS COSTING UP TO $100.") + print() + print() + + +def pennies_to_dollar_string(p): + d = p / 100 + ds = f"${d:0.2f}" + return ds + + +def compute_change(): + print("COST OF ITEM?") + cost = float(input()) + print("AMOUNT OF PAYMENT?") + payment = float(input()) + + change_in_pennies = round((payment - cost) * 100) + if change_in_pennies == 0: + print("CORRECT AMOUNT, THANK YOU.") + return + + if change_in_pennies < 0: + short = -change_in_pennies / 100 + + print(f"SORRY, YOU HAVE SHORT-CHANGED ME ${short:0.2f}") + print() + return + + print(f"YOUR CHANGE, {pennies_to_dollar_string(change_in_pennies)}") + + d = change_in_pennies // 1000 + if d > 0: + print(f"{d} TEN DOLLAR BILL(S)") + change_in_pennies -= d * 1000 + + e = change_in_pennies // 500 + if e > 0: + print(f"{e} FIVE DOLLAR BILL(S)") + change_in_pennies -= e * 500 + + f = change_in_pennies // 100 + if f > 0: + print(f"{f} ONE DOLLAR BILL(S)") + change_in_pennies -= f * 100 + + g = change_in_pennies // 50 + if g > 0: + print("ONE HALF DOLLAR") + change_in_pennies -= g * 50 + + h = change_in_pennies // 25 + if h > 0: + print(f"{h} QUARTER(S)") + change_in_pennies -= h * 25 + + i = change_in_pennies // 10 + if i > 0: + print(f"{i} DIME(S)") + change_in_pennies -= i * 10 + + j = change_in_pennies // 5 + if j > 0: + print(f"{j} NICKEL(S)") + change_in_pennies -= j * 5 + + if change_in_pennies > 0: + print(f"{change_in_pennies} PENNY(S)") + + +def print_thanks(): + print("THANK YOU, COME AGAIN.") + print() + print() + + +def main(): + print_header("CHANGE") + print_introduction() + + while True: + compute_change() + print_thanks() + + +if __name__ == "__main__": + main() From 69c728955fa4bb810279baebef47f576ba93882f Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:14:54 +1030 Subject: [PATCH 196/749] Correct comment in method for Java port of Bunny --- 19 Bunny/java/src/Bunny.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/19 Bunny/java/src/Bunny.java b/19 Bunny/java/src/Bunny.java index 726491ea..d2fd1699 100644 --- a/19 Bunny/java/src/Bunny.java +++ b/19 Bunny/java/src/Bunny.java @@ -31,7 +31,7 @@ public class Bunny { } /** - * Show an intro, accept a message, then draw the picture. + * Show an intro, then draw the picture. */ public void process() { From a1b257d5ae42ab95888955ccd732f23a811dd39e Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Wed, 3 Mar 2021 23:22:16 +1100 Subject: [PATCH 197/749] Add Long Range Sensors --- 84 Super Star Trek/csharp/Game.cs | 1 + 84 Super Star Trek/csharp/Random.cs | 2 +- 84 Super Star Trek/csharp/Space/Coordinate.cs | 10 ++--- 84 Super Star Trek/csharp/Space/Galaxy.cs | 17 +++++-- 84 Super Star Trek/csharp/Space/Quadrant.cs | 4 +- .../csharp/Space/QuadrantInfo.cs | 10 +++++ .../csharp/Systems/LongRangeSensors.cs | 44 +++++++++++++++++++ 7 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 84 Super Star Trek/csharp/Systems/LongRangeSensors.cs diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index c9d9c778..0547103b 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -82,6 +82,7 @@ namespace SuperStarTrek _enterprise = new Enterprise(3000, random.GetCoordinate(), _output); _enterprise .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) + .Add(new LongRangeSensors(_galaxy, _output)) .Add(new ShieldControl(_enterprise, _output, _input)) .Add(new DamageControl(_enterprise, _output)); diff --git a/84 Super Star Trek/csharp/Random.cs b/84 Super Star Trek/csharp/Random.cs index 9b7e1bff..460c1cef 100644 --- a/84 Super Star Trek/csharp/Random.cs +++ b/84 Super Star Trek/csharp/Random.cs @@ -6,7 +6,7 @@ namespace SuperStarTrek { private static readonly System.Random _random = new(); - public Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive(), Get1To8Inclusive()); + public Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive() - 1, Get1To8Inclusive() - 1); // Duplicates the algorithm used in the original code to get an integer value from 1 to 8, inclusive: // 475 DEF FNR(R)=INT(RND(R)*7.98+1.01) diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinate.cs index 87fe6e89..aa5b5285 100644 --- a/84 Super Star Trek/csharp/Space/Coordinate.cs +++ b/84 Super Star Trek/csharp/Space/Coordinate.cs @@ -14,16 +14,16 @@ namespace SuperStarTrek.Space public int X { get; } public int Y { get; } - public int RegionIndex => ((X - 1) << 1) + ((Y - 1) >> 2); - public int SubRegionIndex => (Y - 1) % 4; + public int RegionIndex => (X << 1) + (Y >> 2); + public int SubRegionIndex => Y % 4; private int Validated(int value, string argumentName) { - if (value >= 1 && value <= 8) { return value; } + if (value >= 0 && value <= 7) { return value; } - throw new ArgumentOutOfRangeException(argumentName, value, "Must be 1 to 8 inclusive"); + throw new ArgumentOutOfRangeException(argumentName, value, "Must be 0 to 7 inclusive"); } - public override string ToString() => $"{X} , {Y}"; + public override string ToString() => $"{X+1} , {Y+1}"; } } diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 88361645..0392b335 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -1,3 +1,5 @@ +using System.Collections; +using System.Collections.Generic; using System.Linq; using SuperStarTrek.Resources; @@ -22,9 +24,9 @@ namespace SuperStarTrek.Space var random = new Random(); _quadrants = Enumerable - .Range(1, 8) + .Range(0, 8) .Select(x => Enumerable - .Range(1, 8) + .Range(0, 8) .Select(y => new Coordinates(x, y)) .Select(c => QuadrantInfo.Create(c, GetQuadrantName(c))) .ToArray()) @@ -42,12 +44,21 @@ namespace SuperStarTrek.Space } } - public QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X - 1][coordinate.Y - 1]; + public QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X][coordinate.Y]; public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount); public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase); private static string GetQuadrantName(Coordinates coordinates) => $"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}"; + + public IEnumerable> GetNeighborhood(Quadrant quadrant) => + Enumerable.Range(-1, 3) + .Select(dx => dx + quadrant.Coordinates.X) + .Select(x => GetNeighborhoodRow(quadrant, x)); + private IEnumerable GetNeighborhoodRow(Quadrant quadrant, int x) => + Enumerable.Range(-1, 3) + .Select(dy => dy + quadrant.Coordinates.Y) + .Select(y => y < 0 || y > 7 || x < 0 || x > 7 ? null : _quadrants[x][y]); } } diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index f08fa18b..e483604f 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -66,13 +66,13 @@ namespace SuperStarTrek.Space } } - public IEnumerable GetDisplayLines() => Enumerable.Range(1, 8).Select(x => GetDisplayLine(x)); + public IEnumerable GetDisplayLines() => Enumerable.Range(0, 8).Select(x => GetDisplayLine(x)); private string GetDisplayLine(int x) => string.Join( " ", Enumerable - .Range(1, 8) + .Range(0, 8) .Select(y => new Coordinates(x, y)) .Select(c => _sectors.GetValueOrDefault(c)) .Select(o => o?.ToString() ?? " ")); diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs index ed9ed3fa..20f21ee2 100644 --- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs +++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs @@ -2,6 +2,8 @@ namespace SuperStarTrek.Space { internal class QuadrantInfo { + private bool _isKnown; + private QuadrantInfo(Coordinates coordinates, string name, int klingonCount, int starCount, bool hasStarbase) { Coordinates = coordinates; @@ -36,5 +38,13 @@ namespace SuperStarTrek.Space internal void AddKlingon() => KlingonCount += 1; internal void AddStarbase() => HasStarbase = true; + + public string Scan() + { + _isKnown = true; + return ToString(); + } + + public override string ToString() => _isKnown ? $"{KlingonCount}{(HasStarbase ? 1 : 0)}{StarCount}" : "***"; } } diff --git a/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs b/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs new file mode 100644 index 00000000..233af4a6 --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs @@ -0,0 +1,44 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using SuperStarTrek.Commands; +using SuperStarTrek.Objects; +using SuperStarTrek.Resources; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems +{ + internal class LongRangeSensors : Subsystem + { + private readonly Galaxy _galaxy; + private readonly Output _output; + + public LongRangeSensors(Galaxy galaxy, Output output) + : base("Long Range Sensors", Command.LRS) + { + _galaxy = galaxy; + _output = output; + } + + public override CommandResult ExecuteCommand(Quadrant quadrant) + { + if (Condition < 0) + { + _output.WriteLine("Long Range Sensors are inoperable"); + } + else + { + _output.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}"); + _output.WriteLine("-------------------"); + foreach (var quadrants in _galaxy.GetNeighborhood(quadrant)) + { + _output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :"); + _output.WriteLine("-------------------"); + } + } + + return CommandResult.Ok; + } + } +} From fb34c3ffd6e41ebe68ec39f1d08977b790aa875e Mon Sep 17 00:00:00 2001 From: Jonas Nockert Date: Wed, 3 Mar 2021 14:05:56 +0100 Subject: [PATCH 198/749] Python port of SPLAT --- 81 Splat/python/splat.py | 278 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 81 Splat/python/splat.py diff --git a/81 Splat/python/splat.py b/81 Splat/python/splat.py new file mode 100644 index 00000000..86c95f75 --- /dev/null +++ b/81 Splat/python/splat.py @@ -0,0 +1,278 @@ +""" +SPLAT + +Splat similates 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 may also select +the acceleration due to gravity or, again, let the computer do it +in which case you might wind up on any one of the eight planets (out to +Neptune), the moon, or the sun. + +The computer then tells you the height you're 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 the way down. The computer +also keeps track of all prior jumps and lets you know how you compared +with previous successful jumps. If you want to recall information from +previous runs, then you should store the array `successful_jumps` on +disk and read it before each run. + +John Yegge created this program while at the Oak Ridge Associated +Universities. + +Ported in 2021 by Jonas Nockert / @lemonad + +""" +from math import sqrt +from random import choice, random, uniform + + +def numeric_input(question, default=0): + """Ask user for a numeric value.""" + while True: + answer = input(f"{question} [{default}]: ").strip() or default + try: + return float(answer) + except ValueError: + pass + + +def yes_no_input(question, default="YES"): + """Ask user a yes/no question and returns True if yes, otherwise False.""" + answer = input(f"{question} (YES OR NO) [{default}]: ").strip() or default + while answer.lower() not in ["n", "no", "y", "yes"]: + answer = input(f"YES OR NO [{default}]: ").strip() or default + return answer.lower() in ["y", "yes"] + + +def jump(): + """Simulate a jump and returns the altitude where the chute opened. + + The idea is to open the chute as late as possible -- but not too late. + """ + v = 0 # Terminal velocity. + a = 0 # Acceleration. + initial_altitude = int(9001 * random() + 1000) + + if yes_no_input("SELECT YOUR OWN TERMINAL VELOCITY", default="NO"): + v1 = numeric_input("WHAT TERMINAL VELOCITY (MI/HR)", default=100) + else: + # Computer picks 0-1000 terminal velocity. + v1 = int(1000 * random()) + print(f"OK. TERMINAL VELOCITY = {v1} MI/HR") + + # Convert miles/h to feet/s. + v1 = v1 * (5280 / 3600) + # Actual terminal velocity is +/-5% of v1. + v = v1 * uniform(0.95, 1.05) + + if yes_no_input("WANT TO SELECT ACCELERATION DUE TO GRAVITY", default="NO"): + a2 = numeric_input("WHAT ACCELERATION (FT/SEC/SEC)", default=32.16) + else: + body, a2 = pick_random_celestial_body() + print(f"FINE. YOU'RE ON {body}. ACCELERATION={a2} FT/SEC/SEC.") + + # Actual acceleration is +/-5% of a2. + a = a2 * uniform(0.95, 1.05) + print( + "\n" + f" ALTITUDE = {initial_altitude} FT\n" + f" TERM. VELOCITY = {v1:.2f} FT/SEC +/-5%\n" + f" ACCELERATION = {a2:.2f} FT/SEC/SEC +/-5%\n" + "SET THE TIMER FOR YOUR FREEFALL." + ) + t_freefall = numeric_input("HOW MANY SECONDS", default=10) + print( + "HERE WE GO.\n\n" + "TIME (SEC)\tDIST TO FALL (FT)\n" + "==========\t=================" + ) + + terminal_velocity_reached = False + is_splat = False + for i in range(9): + # Divide time for freefall into 8 intervals. + t = i * (t_freefall / 8) + # From the first equation of motion, v = v_0 + a * delta_t, with + # initial velocity v_0 = 0, we can get the time when terminal velocity + # is reached: delta_t = v / a. + if t > v / a: + if not terminal_velocity_reached: + print(f"TERMINAL VELOCITY REACHED AT T PLUS {v / a:.2f} SECONDS.") + terminal_velocity_reached = True + # After having reached terminal velocity, the displacement is + # composed of two parts: + # 1. Displacement up to reaching terminal velocity: + # From the third equation of motion, v^2 = v_0^2 + 2 * a * d, + # with v_0 = 0, we can get the displacement using + # d1 = v^2 / (2 * a). + # 2. Displacement beyond having reached terminal velocity: + # here, the displacement is just a function of the terminal + # velocity and the time passed after having reached terminal + # velocity: d2 = v * (t - t_reached_term_vel) + d1 = (v ** 2) / (2 * a) + d2 = v * (t - (v / a)) + altitude = initial_altitude - (d1 + d2) + if altitude <= 0: + # Time taken for an object to fall to the ground given + # an initial altitude is composed of two parts after having + # reached terminal velocity: + # 1. time up to reaching terminal velocity: t1 = v / a + # 2. time beyond having reached terminal velocity: + # here, the altitude that remains after having reached + # terminal velocity can just be divided by the constant + # terminal velocity to get the time it takes to reach the + # ground: t2 = altitude_remaining / v + t1 = v / a + t2 = (initial_altitude - d1) / v + print_splat(t1 + t2) + is_splat = True + break + else: + # 1. Displacement before reaching terminal velocity: + # From the second equation of motion, + # d = v_0 * t + 0.5 * a * t^2, with v_0 = 0, we can get + # the displacement using d1 = a / 2 * t^2 + d1 = (a / 2) * (t ** 2) + altitude = initial_altitude - d1 + if altitude <= 0: + # Time taken for an object to fall to the ground given that + # it never reaches terminal velocity can be calculated by + # using the second equation of motion: + # d = v_0 * t + 0.5 * a * t^2, with v_0 = 0, which + # when solved for t becomes + # t1 = sqrt(2 * d / a). + t1 = sqrt(2 * initial_altitude / a) + print_splat(t1) + is_splat = True + break + print(f"{t:.2f}\t\t{altitude:.1f}") + + if not is_splat: + print("CHUTE OPEN") + return altitude + + +def pick_random_celestial_body(): + """Pick a random planet, the moon, or the sun with associated gravity.""" + body, gravity = choice( + [ + ("MERCURY", 12.2), + ("VENUS", 28.3), + ("EARTH", 32.16), + ("THE MOON", 5.15), + ("MARS", 12.5), + ("JUPITER", 85.2), + ("SATURN", 37.6), + ("URANUS", 33.8), + ("NEPTUNE", 39.6), + ("THE SUN", 896.0), + ] + ) + return body, gravity + + +def jump_stats(previous_jumps, chute_altitude): + """Compare altitude when chute opened with previous successful jumps. + + Return the number of previous jumps and the number of times + the current jump is better. + """ + n_previous_jumps = len(previous_jumps) + n_better = sum([1 for pj in previous_jumps if chute_altitude < pj]) + return n_previous_jumps, n_better + + +def print_splat(time_on_impact): + """Parachute opened too late!""" + print(f"{time_on_impact:.2f}\t\tSPLAT") + print( + choice( + [ + "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.", + ] + ) + ) + + +def print_results(n_previous_jumps, n_better): + """Compare current jump to previous successful jumps.""" + k = n_previous_jumps + k1 = n_better + n_jumps = k + 1 + if n_jumps <= 3: + order = ["1ST", "2ND", "3RD"] + nth = order[n_jumps - 1] + print(f"AMAZING!!! NOT BAD FOR YOUR {nth} SUCCESSFUL JUMP!!!") + elif k - k1 <= 0.1 * k: + print( + f"WOW! THAT'S SOME JUMPING. OF THE {k} SUCCESSFUL JUMPS\n" + f"BEFORE YOURS, ONLY {k - k1} OPENED THEIR CHUTES LOWER THAN\n" + "YOU DID." + ) + elif k - k1 <= 0.25 * k: + print( + f"PRETTY GOOD! {k} SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n" + f"{k - k1} OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n" + "OPENED." + ) + elif k - k1 <= 0.5 * k: + print( + f"NOT BAD. THERE HAVE BEEN {k} SUCCESSFUL JUMPS BEFORE YOURS.\n" + f"YOU WERE BEATEN OUT BY {k - k1} OF THEM." + ) + elif k - k1 <= 0.75 * k: + print( + f"CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY {k - k1} IN THE\n" + f"{k} SUCCESSFUL JUMPS BEFORE YOURS." + ) + elif k - k1 <= 0.9 * k: + print( + "HUMPH! DON'T YOU HAVE ANY SPORTING BLOOD? THERE WERE\n" + f"{k} SUCCESSFUL JUMPS BEFORE YOURS AND YOU CAME IN {k1} JUMPS\n" + "BETTER THAN THE WORST. SHAPE UP!!!" + ) + else: + print( + f"HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. {k} SUCCESSFUL\n" + f"JUMPS BEFORE YOURS AND YOU CAME IN NUMBER {k - k1}!" + " GET WITH IT!" + ) + + +# Main program. + +print( + "SPLAT\n" + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n\n" + "WELCOME TO 'SPLAT' -- THE GAME THAT SIMULATES A PARACHUTE\n" + "JUMP. TRY TO OPEN YOUR CHUTE AT THE LAST POSSIBLE\n" + "MOMENT WITHOUT GOING SPLAT.\n\n" +) + +successful_jumps = [] +while True: + chute_altitude = jump() + if chute_altitude > 0: + # We want the statistics on previous jumps (i.e. not including the + # current jump.) + n_previous_jumps, n_better = jump_stats(successful_jumps, chute_altitude) + successful_jumps.append(chute_altitude) + print_results(n_previous_jumps, n_better) + else: + # Splat! + print("I'LL GIVE YOU ANOTHER CHANCE.") + z = yes_no_input("DO YOU WANT TO PLAY AGAIN") + if not z: + z = yes_no_input("PLEASE") + if not z: + print("SSSSSSSSSS.") + break From bc3d0296c5d5a6702c877f676a843c23afe2e4ce Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Wed, 3 Mar 2021 13:08:24 -0300 Subject: [PATCH 199/749] Added python port of russianroulette --- 76 Russian Roulette/python/russianroulette.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 76 Russian Roulette/python/russianroulette.py diff --git a/76 Russian Roulette/python/russianroulette.py b/76 Russian Roulette/python/russianroulette.py new file mode 100644 index 00000000..a1391608 --- /dev/null +++ b/76 Russian Roulette/python/russianroulette.py @@ -0,0 +1,55 @@ +from random import random + +NUMBER_OF_ROUNDS = 9 + + +def initial_message(): + print(" " * 28 + "Russian Roulette") + print(" " * 15 + "Creative Computing Morristown, New Jersey\n\n\n") + print("This is a game of >>>>>>>>>>Russian Roulette.\n") + print("Here is a Revolver.") + + +def parse_input(): + correct_input = False + while not correct_input: + try: + i = int(input('?')) + correct_input = True + except ValueError: + print('Number expected...') + return i + + +initial_message() +while True: + dead = False + n = 0 + print("Type \'1\' to Spin chamber and pull trigger") + print("Type \'2\' to Give up") + print("Go") + while not dead: + i = parse_input() + + if i == 2: + break + + if random() > 0.8333333333333334: + dead = True + else: + print("- CLICK -\n") + n += 1 + + if n > NUMBER_OF_ROUNDS: + break + if dead: + print("BANG!!!!! You're Dead!") + print("Condolences will be sent to your relatives.\n\n\n") + print("...Next victim...") + else: + if n > NUMBER_OF_ROUNDS: + print("You win!!!!!") + print("Let someone else blow his brain out.") + else: + print(" Chicken!!!!!\n\n\n") + print("...Next victim....") From dfa0584fdd9f1dba0678e334a1f53ec4282845fb Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Wed, 3 Mar 2021 13:24:39 -0300 Subject: [PATCH 200/749] Added history comments and porting notes --- 76 Russian Roulette/python/russianroulette.py | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/76 Russian Roulette/python/russianroulette.py b/76 Russian Roulette/python/russianroulette.py index a1391608..508fd15a 100644 --- a/76 Russian Roulette/python/russianroulette.py +++ b/76 Russian Roulette/python/russianroulette.py @@ -1,3 +1,21 @@ +######################################################## +# +# Russian Roulette +# +# From Basic Computer Games (1978) +# +# In this game, you are given by the computer a +# revolver loaded with one bullet and five empty +# chambers. You spin the chamber and pull the trigger +# by inputting a "1", or, if you want to quit, input +# a "2". You win if you play ten times and are still +# alive. +# Tom Adametx wrote this program while a student at +# Curtis Jr. High School in Sudbury, Massachusetts. +# +######################################################## + + from random import random NUMBER_OF_ROUNDS = 9 @@ -14,7 +32,7 @@ def parse_input(): correct_input = False while not correct_input: try: - i = int(input('?')) + i = int(input('? ')) correct_input = True except ValueError: print('Number expected...') @@ -53,3 +71,22 @@ while True: else: print(" Chicken!!!!!\n\n\n") print("...Next victim....") + + +######################################################## +# Porting Notes +# +# Altough the description says that accepts "1" or "2", +# the original game accepts any number as input, and +# if it's different of "2" the program considers +# as if the user had passed "1". That feature was +# kept in this port. +# Also, in the original game you must "pull the trigger" +# 11 times instead of 10 in orden to win, +# given that N=0 at the beginning and the condition to +# win is "IF N > 10 THEN 80". That was fixed in this +# port, asking the user to pull the trigger only ten +# times, tough the number of round can be set changing +# the constant NUMBER_OF_ROUNDS. +# +######################################################## From 893da91b0c6901171f219c464d58a7858c815761 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Wed, 3 Mar 2021 13:26:19 -0300 Subject: [PATCH 201/749] infimous change to print so it can look exactly like the original --- 76 Russian Roulette/python/russianroulette.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/76 Russian Roulette/python/russianroulette.py b/76 Russian Roulette/python/russianroulette.py index 508fd15a..bac04dc6 100644 --- a/76 Russian Roulette/python/russianroulette.py +++ b/76 Russian Roulette/python/russianroulette.py @@ -67,7 +67,7 @@ while True: else: if n > NUMBER_OF_ROUNDS: print("You win!!!!!") - print("Let someone else blow his brain out.") + print("Let someone else blow his brain out.\n") else: print(" Chicken!!!!!\n\n\n") print("...Next victim....") From 7e31c244d7d9ddd8e59bf49d8bb0e59ef02dadeb Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Wed, 3 Mar 2021 08:56:30 -0800 Subject: [PATCH 202/749] work in progress porting CHECKERS to python did a first pass, porting the logic, refactoring into functions. Found a few bugs in the original code: - when a computer promoted to a king, the original piece would not be removed from the board - humans could move normal pieces like kings I've noticed at least one bug where the computer does not promote to a king when reaching row 0 --- 23 Checkers/python/checkers.py | 358 +++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 23 Checkers/python/checkers.py diff --git a/23 Checkers/python/checkers.py b/23 Checkers/python/checkers.py new file mode 100644 index 00000000..3a1d1236 --- /dev/null +++ b/23 Checkers/python/checkers.py @@ -0,0 +1,358 @@ +""" +CHECKERS + +How about a nice game of checkers? + +Ported by Dave LeCompte +""" + + +PAGE_WIDTH = 64 + +HUMAN_PLAYER = 1 +COMPUTER_PLAYER = -1 +HUMAN_PIECE = 1 +HUMAN_KING = 2 +COMPUTER_PIECE = -1 +COMPUTER_KING = -2 +EMPTY_SPACE = 0 + +INVALID_MOVE = -99 + + +def print_centered(msg): + spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) + print(spaces + msg) + + +def print_header(title): + print_centered(title) + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + +class Board: + def __init__(self): + self.spaces = [[0 for y in range(8)] for x in range(8)] + for x in range(8): + if (x % 2) == 0: + self.spaces[x][6] = COMPUTER_PIECE + self.spaces[x][2] = HUMAN_PIECE + self.spaces[x][0] = HUMAN_PIECE + else: + self.spaces[x][7] = COMPUTER_PIECE + self.spaces[x][5] = COMPUTER_PIECE + self.spaces[x][1] = HUMAN_PIECE + + def __str__(self): + pieces = { + EMPTY_SPACE: ".", + HUMAN_PIECE: "O", + HUMAN_KING: "O*", + COMPUTER_PIECE: "X", + COMPUTER_KING: "X*", + } + + s = "\n\n\n" + for y in range(7, -1, -1): + for x in range(0, 8): + piece_str = pieces[self.spaces[x][y]] + piece_str += " " * (5 - len(piece_str)) + s += piece_str + s += "\n" + s += "\n\n" + + return s + + +def print_instructions(): + print("THIS IS THE GAME OF CHECKERS. THE COMPUTER IS X,") + print("AND YOU ARE O. THE COMPUTER WILL MOVE FIRST.") + print("SQUARES ARE REFERRED TO BY A COORDINATE SYSTEM.") + print("(0,0) IS THE LOWER LEFT CORNER") + print("(0,7) IS THE UPPER LEFT CORNER") + print("(7,0) IS THE LOWER RIGHT CORNER") + print("(7,7) IS THE UPPER RIGHT CORNER") + print("THE COMPUTER WILL TYPE '+TO' WHEN YOU HAVE ANOTHER") + print("JUMP. TYPE TWO NEGATIVE NUMBERS IF YOU CANNOT JUMP.") + print() + print() + print() + + +def get_spaces(): + for x in range(0, 8): + for y in range(0, 8): + yield x, y + + +def get_spaces_with_computer_pieces(board): + for x, y in get_spaces(): + contents = board.spaces[x][y] + if contents < 0: + yield x, y + + +def get_spaces_with_human_pieces(board): + for x, y in get_spaces(): + contents = board.spaces[x][y] + if contents > 0: + yield x, y + + +def pick_computer_move(board): + r = [INVALID_MOVE] * 5 + for x, y in get_spaces_with_computer_pieces(board): + contents = board.spaces[x][y] + if contents == COMPUTER_PIECE: + for dx in (-1, 1): + dy = -1 + sub_650(board, x, y, dx, dy, r) + else: + for dx in (-1, 1): + for dy in (-1, 1): + sub_650(board, x, y, dx, dy, r) + + if r[0] != INVALID_MOVE: + dx = r[3] - r[1] + dy = r[4] - r[2] + if abs(dx) != abs(dy): + print(r) + assert abs(dx) == abs(dy) + return r + + +def sub_650(board, x, y, dx, dy, r): + new_x = x + dx + new_y = y + dy + if not ((0 <= new_x <= 7) and (0 <= new_y <= 7)): + return + + contents = board.spaces[new_x][new_y] + if contents == 0: + sub_910(board, x, y, new_x, new_y, r) + return + if contents < 0: + return + + # check landing space + landing_x = new_x + dx + landing_y = new_y + dy + + # line 790 + if not ((0 <= landing_x <= 7) and (0 <= landing_y <= 7)): + return + if board.spaces[landing_x][landing_y] == 0: + sub_910(board, x, y, landing_x, landing_y, r) + + +def sub_910(board, start_x, start_y, dest_x, dest_y, r): + q = 0 + if dest_y == 0 and board.spaces[start_x][start_y] == COMPUTER_PIECE: + q += 2 + if abs(start_y - dest_y) == 2: + q += 5 + if start_y == 7: + q -= 2 + if dest_x in (0, 7): + q += 1 + for c in (-1, 1): + if (0 <= dest_x + c <= 7) and (1 <= dest_y): + # line 1035 + if board.spaces[dest_x + c][dest_y - 1] < 0: + q += 1 + # line 1040 + elif (0 <= dest_x - c <= 7) and (dest_y + 1 <= 7): + # line 1045 + if ( + (board.spaces[dest_x + c][dest_y - 1] > 0) + and (board.spaces[dest_x - c][dest_y + 1] == EMPTY_SPACE) + or ((dest_x - c == start_x) and (dest_y + 1 == start_y)) + ): + q -= 2 + # line 1080 + + if q > r[0]: + r[0] = q + r[1] = start_x + r[2] = start_y + r[3] = dest_x + r[4] = dest_y + + +def remove_r_pieces(board, r): + remove_pieces(board, r[1], r[2], r[3], r[4]) + + +def remove_pieces(board, start_x, start_y, dest_x, dest_y): + board.spaces[dest_x][dest_y] = board.spaces[start_x][start_y] + board.spaces[start_x][start_y] = EMPTY_SPACE + + if abs(dest_x - start_x) == 2: + mid_x = (start_x + dest_x) // 2 + mid_y = (start_y + dest_y) // 2 + board.spaces[mid_x][mid_y] = EMPTY_SPACE + + +def play_computer_move(board, r): + print(f"FROM {r[1]} {r[2]} TO {r[3]} {r[4]}") + + while True: + if r[4] == 0: + # KING ME + board.spaces[r[3]][r[4]] = COMPUTER_KING + remove_r_pieces(board, r) + return + else: + # line 1250 + board.spaces[r[3]][r[4]] = board.spaces[r[1]][r[2]] + remove_r_pieces(board, r) + + if abs(r[1] - r[3]) != 2: + return + + # line 1340 + x = r[3] + y = r[4] + r[0] = INVALID_MOVE + if board.spaces[x][y] == COMPUTER_PIECE: + for a in (-2, 2): + try_extend(board, r, x, y, a, -2) + else: + assert board.spaces[x][y] == COMPUTER_KING + for a in (-2, 2): + for b in (-2, 2): + try_extend(board, r, x, y, a, b) + if r[0] != INVALID_MOVE: + print(f"TO {r[3]} {r[4]}") + else: + return + + +def try_extend(board, r, x, y, a, b): + # line 1370 + nx = x + a + ny = y + b + if not ((0 <= nx <= 7) and (0 <= ny <= 7)): + return + if (board.spaces[nx][ny] == EMPTY_SPACE) and ( + board.spaces[nx + a // 2][ny + b // 2] > 0 + ): + sub_910(board, x, y, nx, ny, r) + + +def get_human_move(board): + is_king = False + + while True: + print("FROM?") + from_response = input() + x, y = [int(c) for c in from_response.split(",")] + + if board.spaces[x][y] > 0: + break + + is_king = board.spaces[x][y] == HUMAN_KING + + while True: + print("TO?") + to_response = input() + a, b = [int(c) for c in to_response.split(",")] + + if (not is_king) and (b < y): + # CHEATER! Trying to move non-king backwards + continue + if ( + (board.spaces[a][b] == 0) + and (abs(a - x) <= 2) + and (abs(a - x) == abs(b - y)) + ): + break + return x, y, a, b + + +def get_human_extension(board, sx, sy): + is_king = board.spaces[sx][sy] == HUMAN_KING + + while True: + print("+TO?") + to_response = input() + a1, b1 = [int(c) for c in to_response.split(",")] + if a1 < 0: + return False, None + if (not is_king) and (b1 < sy): + # CHEATER! Trying to move non-king backwards + continue + if ( + (board.spaces[a1][b1] == EMPTY_SPACE) + and (abs(a1 - sx) == 2) + and (abs(b1 - sy) == 2) + ): + return True, (sx, sy, a1, b1) + + +def play_human_move(board, start_x, start_y, dest_x, dest_y): + remove_pieces(board, start_x, start_y, dest_x, dest_y) + + if dest_y == 7: + # KING ME + board.spaces[dest_x][dest_y] = HUMAN_KING + + +def print_human_won(): + print() + print("YOU WIN.") + + +def print_computer_won(): + print() + print("I WIN.") + + +def check_pieces(board): + if len(list(get_spaces_with_computer_pieces(board))) == 0: + print_human_won() + return False + if len(list(get_spaces_with_computer_pieces(board))) == 0: + print_computer_won() + return False + return True + + +def play_game(): + board = Board() + + while True: + r = pick_computer_move(board) + if r[0] == INVALID_MOVE: + print_human_won() + return + play_computer_move(board, r) + + print(board) + + if not check_pieces(board): + return + + sx, sy, dx, dy = get_human_move(board) + play_human_move(board, sx, sy, dx, dy) + if abs(dx - sx) == 2: + while True: + extend, move = get_human_extension(board, dx, dy) + if not extend: + break + sx, sy, dx, dy = move + play_human_move(board, sx, sy, dx, dy) + + +def main(): + print_header("CHECKERS") + print_instructions() + + play_game() + + +if __name__ == "__main__": + main() From 221fa7fe095b3ac3aaf05d4afe303ac8983f382f Mon Sep 17 00:00:00 2001 From: Oliver Hensman-Crook Date: Wed, 3 Mar 2021 17:18:28 +0000 Subject: [PATCH 203/749] Tic-Tac-Toe java port --- 89 Tic-Tac-Toe/java/gitignore | 3 + 89 Tic-Tac-Toe/java/src/Board.java | 88 +++++++++++++++ 89 Tic-Tac-Toe/java/src/TicTacToe2.java | 135 ++++++++++++++++++++++++ 89 Tic-Tac-Toe/java/src/make.sh | 2 + 89 Tic-Tac-Toe/java/src/run.sh | 3 + 5 files changed, 231 insertions(+) create mode 100644 89 Tic-Tac-Toe/java/gitignore create mode 100644 89 Tic-Tac-Toe/java/src/Board.java create mode 100644 89 Tic-Tac-Toe/java/src/TicTacToe2.java create mode 100755 89 Tic-Tac-Toe/java/src/make.sh create mode 100755 89 Tic-Tac-Toe/java/src/run.sh diff --git a/89 Tic-Tac-Toe/java/gitignore b/89 Tic-Tac-Toe/java/gitignore new file mode 100644 index 00000000..0909e4b5 --- /dev/null +++ b/89 Tic-Tac-Toe/java/gitignore @@ -0,0 +1,3 @@ +bin +src/make.sh +src/run.sh \ No newline at end of file diff --git a/89 Tic-Tac-Toe/java/src/Board.java b/89 Tic-Tac-Toe/java/src/Board.java new file mode 100644 index 00000000..091f7bb2 --- /dev/null +++ b/89 Tic-Tac-Toe/java/src/Board.java @@ -0,0 +1,88 @@ +/** + * @author Ollie Hensman-Crook + */ +public class Board { + private char arr[]; + + public Board() { + this.arr = new char[9]; + for (int x = 1; x <= 9; x++) { + this.arr[x - 1] = ' '; + } + } + + + /** + * Place 'X' or 'O' on the board position passed + * @param position + * @param player + */ + public void setArr(int position, char player) { + if (player == 'X') { + this.arr[position-1] = 'X'; + } else { + this.arr[position -1] = 'O'; + } + } + + public void printBoard() { + System.out.format("%-3c ! %-3c ! %-3c\n----+----+----\n%-3c ! %-3c ! %-3c\n----+----+----\n%-3c ! %-3c ! %-3c\n", + this.arr[0], this.arr[1], this.arr[2], this.arr[3], this.arr[4], this.arr[5], this.arr[6], this.arr[7], this.arr[8] + ); + } + + + /** + * @param x + * @return the value of the char at a given position + */ + public char getBoardValue(int x) { + return arr[x-1]; + } + + + /** + * Go through the board and check for win (horizontal, diagonal, vertical) + * @param player + * @return whether a win has occured + */ + public boolean checkWin(char player) { + if(this.arr[0] == player && this.arr[1] == player && this.arr[2] == player) + return true; + + + if(this.arr[3] == player && this.arr[4] == player && this.arr[5] == player) + return true; + + + if(this.arr[6] == player && this.arr[7] == player && this.arr[8] == player) + return true; + + if(this.arr[0] == player && this.arr[4] == player && this.arr[8] == player) + return true; + + if(this.arr[2] == player && this.arr[4] == player && this.arr[6] == player) + return true; + + if(this.arr[0] == player && this.arr[3] == player && this.arr[6] == player) + return true; + + if(this.arr[1] == player && this.arr[4] == player && this.arr[7] == player) + return true; + + if(this.arr[2] == player && this.arr[5] == player && this.arr[8] == player) + return true; + + return false; + } + + /** + * Reset the board + */ + public void clear() { + for (int x = 1; x <= 9; x++) { + this.arr[x - 1] = ' '; + } + } + +} \ No newline at end of file diff --git a/89 Tic-Tac-Toe/java/src/TicTacToe2.java b/89 Tic-Tac-Toe/java/src/TicTacToe2.java new file mode 100644 index 00000000..5fe69cfd --- /dev/null +++ b/89 Tic-Tac-Toe/java/src/TicTacToe2.java @@ -0,0 +1,135 @@ +import java.util.Scanner; +import java.util.Random; + +/** + * @author Ollie Hensman-Crook + */ +public class TicTacToe2 { + public static void main(String[] args) { + Board gameBoard = new Board(); + Random compChoice = new Random(); + char yourChar; + char compChar; + Scanner in = new Scanner(System.in); + + System.out.println(" TIC-TAC-TOE"); + System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\nTHE BOARD IS NUMBERED: "); + System.out.println(" 1 2 3\n 4 5 6\n 7 8 9\n"); + + while (true) { + // ask if the player wants to be X or O and if their input is valid set their + // play piece as such + System.out.println("DO YOU WANT 'X' OR 'O'"); + while (true) { + try { + char input; + input = in.next().charAt(0); + + if (input == 'X' || input == 'x') { + yourChar = 'X'; + compChar = 'O'; + break; + } else if (input == 'O' || input == 'o') { + yourChar = 'O'; + compChar = 'X'; + } else { + System.out.println("THATS NOT 'X' OR 'O', TRY AGAIN"); + in.nextLine(); + } + + } catch (Exception e) { + System.out.println("THATS NOT 'X' OR 'O', TRY AGAIN"); + in.nextLine(); + } + } + + while (true) { + System.out.println("WHERE DO YOU MOVE"); + + // check the user can move where they want to and if so move them there + while (true) { + int input; + try { + input = in.nextInt(); + if (gameBoard.getBoardValue(input) == ' ') { + gameBoard.setArr(input, yourChar); + break; + } else { + System.out.println("INVALID INPUT, TRY AGAIN"); + //in.nextLine(); + } + in.nextLine(); + } catch (Exception e) { + System.out.println("INVALID INPUT, TRY AGAIN"); + in.nextLine(); + } + } + + gameBoard.printBoard(); + System.out.println("THE COMPUTER MOVES TO"); + + while (true) { + int position = 1 + compChoice.nextInt(9); + if (gameBoard.getBoardValue(position) == ' ') { + gameBoard.setArr(position, compChar); + break; + } + } + + gameBoard.printBoard(); + + // if there is a win print if player won or the computer won and ask if they + // want to play again + if (gameBoard.checkWin(yourChar)) { + System.out.println("YOU WIN, PLAY AGAIN? (Y/N)"); + gameBoard.clear(); + while (true) { + try { + char input; + input = in.next().charAt(0); + + if (input == 'Y' || input == 'y') { + break; + } else if (input == 'N' || input == 'n') { + System.exit(0); + } else { + System.out.println("THATS NOT 'Y' OR 'N', TRY AGAIN"); + in.nextLine(); + } + + } catch (Exception e) { + System.out.println("THATS NOT 'Y' OR 'N', TRY AGAIN"); + in.nextLine(); + } + } + break; + } else if (gameBoard.checkWin(compChar)) { + System.out.println("YOU LOSE, PLAY AGAIN? (Y/N)"); + gameBoard.clear(); + while (true) { + try { + char input; + input = in.next().charAt(0); + + if (input == 'Y' || input == 'y') { + break; + } else if (input == 'N' || input == 'n') { + System.exit(0); + } else { + System.out.println("THATS NOT 'Y' OR 'N', TRY AGAIN"); + in.nextLine(); + } + + } catch (Exception e) { + System.out.println("THATS NOT 'Y' OR 'N', TRY AGAIN"); + in.nextLine(); + } + } + break; + } + + } + } + } +} diff --git a/89 Tic-Tac-Toe/java/src/make.sh b/89 Tic-Tac-Toe/java/src/make.sh new file mode 100755 index 00000000..9492cfea --- /dev/null +++ b/89 Tic-Tac-Toe/java/src/make.sh @@ -0,0 +1,2 @@ +javac -d ../bin *.java + diff --git a/89 Tic-Tac-Toe/java/src/run.sh b/89 Tic-Tac-Toe/java/src/run.sh new file mode 100755 index 00000000..84c9d803 --- /dev/null +++ b/89 Tic-Tac-Toe/java/src/run.sh @@ -0,0 +1,3 @@ +cd ../bin +java TicTacToe2 +cd ../src From 35845b0962312a2c1ce2ded7894681dfbe1df2dd Mon Sep 17 00:00:00 2001 From: Oliver Hensman-Crook Date: Wed, 3 Mar 2021 17:20:46 +0000 Subject: [PATCH 204/749] Tic-Tac-Toe java port --- 89 Tic-Tac-Toe/java/.gitignore | 2 ++ 89 Tic-Tac-Toe/java/gitignore | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 89 Tic-Tac-Toe/java/.gitignore delete mode 100644 89 Tic-Tac-Toe/java/gitignore diff --git a/89 Tic-Tac-Toe/java/.gitignore b/89 Tic-Tac-Toe/java/.gitignore new file mode 100644 index 00000000..6e532130 --- /dev/null +++ b/89 Tic-Tac-Toe/java/.gitignore @@ -0,0 +1,2 @@ +src/make.sh +src/run.sh diff --git a/89 Tic-Tac-Toe/java/gitignore b/89 Tic-Tac-Toe/java/gitignore deleted file mode 100644 index 0909e4b5..00000000 --- a/89 Tic-Tac-Toe/java/gitignore +++ /dev/null @@ -1,3 +0,0 @@ -bin -src/make.sh -src/run.sh \ No newline at end of file From c6e6192f2b2cea7ee93fc90658eea8de32f6396e Mon Sep 17 00:00:00 2001 From: olliehcrook <53153427+olliehcrook@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:28:23 +0000 Subject: [PATCH 205/749] Delete make.sh --- 89 Tic-Tac-Toe/java/src/make.sh | 2 -- 1 file changed, 2 deletions(-) delete mode 100755 89 Tic-Tac-Toe/java/src/make.sh diff --git a/89 Tic-Tac-Toe/java/src/make.sh b/89 Tic-Tac-Toe/java/src/make.sh deleted file mode 100755 index 9492cfea..00000000 --- a/89 Tic-Tac-Toe/java/src/make.sh +++ /dev/null @@ -1,2 +0,0 @@ -javac -d ../bin *.java - From 3ff7a1c486de7c880e7a79a25e2edc4025834f3e Mon Sep 17 00:00:00 2001 From: olliehcrook <53153427+olliehcrook@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:28:33 +0000 Subject: [PATCH 206/749] Delete run.sh --- 89 Tic-Tac-Toe/java/src/run.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100755 89 Tic-Tac-Toe/java/src/run.sh diff --git a/89 Tic-Tac-Toe/java/src/run.sh b/89 Tic-Tac-Toe/java/src/run.sh deleted file mode 100755 index 84c9d803..00000000 --- a/89 Tic-Tac-Toe/java/src/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -cd ../bin -java TicTacToe2 -cd ../src From f5d949502b01e6fedd5987a6d72ee69be932ca2c Mon Sep 17 00:00:00 2001 From: olliehcrook <53153427+olliehcrook@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:29:03 +0000 Subject: [PATCH 207/749] Delete .gitignore --- 89 Tic-Tac-Toe/java/.gitignore | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 89 Tic-Tac-Toe/java/.gitignore diff --git a/89 Tic-Tac-Toe/java/.gitignore b/89 Tic-Tac-Toe/java/.gitignore deleted file mode 100644 index 6e532130..00000000 --- a/89 Tic-Tac-Toe/java/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -src/make.sh -src/run.sh From c1bb37472670b707d6aa9ed38aa4add17f4a5916 Mon Sep 17 00:00:00 2001 From: olliehcrook <53153427+olliehcrook@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:37:23 +0000 Subject: [PATCH 208/749] Update TicTacToe2.java --- 89 Tic-Tac-Toe/java/src/TicTacToe2.java | 1 - 1 file changed, 1 deletion(-) diff --git a/89 Tic-Tac-Toe/java/src/TicTacToe2.java b/89 Tic-Tac-Toe/java/src/TicTacToe2.java index 5fe69cfd..c186ea1d 100644 --- a/89 Tic-Tac-Toe/java/src/TicTacToe2.java +++ b/89 Tic-Tac-Toe/java/src/TicTacToe2.java @@ -57,7 +57,6 @@ public class TicTacToe2 { break; } else { System.out.println("INVALID INPUT, TRY AGAIN"); - //in.nextLine(); } in.nextLine(); } catch (Exception e) { From cad9b8f816f840237a49e86e9b0cb89b59246ede Mon Sep 17 00:00:00 2001 From: olliehcrook <53153427+olliehcrook@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:51:36 +0000 Subject: [PATCH 209/749] Debug tictactoe2.py Fixed board being rendered twice bug when current_player = OccupiedBy.PLAYER. TL;DR unnecessary print statement --- 89 Tic-Tac-Toe/python/tictactoe2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/89 Tic-Tac-Toe/python/tictactoe2.py b/89 Tic-Tac-Toe/python/tictactoe2.py index 95493657..63a68d0f 100755 --- a/89 Tic-Tac-Toe/python/tictactoe2.py +++ b/89 Tic-Tac-Toe/python/tictactoe2.py @@ -205,7 +205,6 @@ def play(): print("THANKS FOR THE GAME.") break board[move - 1] = current_player - print(render_board(board, space_mapping)) elif current_player is OccupiedBy.COMPUTER: print("\nTHE COMPUTER MOVES TO...") From 990658b8e6945107d77bd2b04dbefa95b6357e5d Mon Sep 17 00:00:00 2001 From: nanochess Date: Wed, 3 Mar 2021 15:24:21 -0600 Subject: [PATCH 210/749] Ported CRAPS to Javascript --- 28 Combat/javascript/combat.js | 2 +- 29 Craps/javascript/craps.html | 9 +++ 29 Craps/javascript/craps.js | 128 +++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 29 Craps/javascript/craps.html create mode 100644 29 Craps/javascript/craps.js diff --git a/28 Combat/javascript/combat.js b/28 Combat/javascript/combat.js index be4d72a9..a2e43c71 100644 --- a/28 Combat/javascript/combat.js +++ b/28 Combat/javascript/combat.js @@ -1,4 +1,4 @@ -// CHOMP +// COMBAT // // Converted from BASIC to Javascript by Oscar Toledo G. (nanochess) // diff --git a/29 Craps/javascript/craps.html b/29 Craps/javascript/craps.html new file mode 100644 index 00000000..50b2ca9b --- /dev/null +++ b/29 Craps/javascript/craps.html @@ -0,0 +1,9 @@ + + +CRAPS + + +


+
+
+
diff --git a/29 Craps/javascript/craps.js b/29 Craps/javascript/craps.js
new file mode 100644
index 00000000..93351011
--- /dev/null
+++ b/29 Craps/javascript/craps.js	
@@ -0,0 +1,128 @@
+// CRAPS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "CRAPS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    r = 0;
+    print("2,3,12 ARE LOSERS: 4,5,6,8,9,10 ARE POINTS: 7,11 ARE NATURAL WINNERS.\n");
+    t = 1;
+    print("PICK A NUMBER AND INPUT TO ROLL DICE");
+    z = parseInt(await input());
+    do {
+        x = Math.random();
+        t++;
+    } while (t <= z) ;
+    while (1) {
+        print("INPUT THE AMOUNT OF YOUR WAGER.");
+        f = parseInt(await input());
+        print("I WILL NOW THROW THE DICE\n");
+        do {
+            e = Math.floor(7 * Math.random());
+            s = Math.floor(7 * Math.random());
+            x = e + s;
+        } while (x == 0 || x == 1) ;
+        if (x == 7 || x == 11) {
+            print(x + " - NATURAL....A WINNER!!!!\n");
+            print(x + " PAYS EVEN MONEY, YOU WIN " + f + " DOLLARS\n");
+            r += f;
+        } else if (x == 2) {
+            print(x + " - SNAKE EYES....YOU LOSE.\n");
+            print("YOU LOSE " + f + " DOLLARS.\n");
+            r -= f;
+        } else if (x == 3 || x == 12) { // Original duplicates comparison in line 70
+            print(x + " - CRAPS....YOU LOSE.\n");
+            print("YOU LOSE " + f + " DOLLARS.\n");
+            r -= f;
+        } else {
+            print(x + " IS THE POINT. I WILL ROLL AGAIN\n");
+            while (1) {
+                do {
+                    h = Math.floor(7 * Math.random());
+                    q = Math.floor(7 * Math.random());
+                    o = h + q;
+                } while (o == 0 || o == 1) ;
+                if (o == 7) {
+                    print(o + " - CRAPS, YOU LOSE.\n");
+                    print("YOU LOSE $" + f + "\n");
+                    r -= f;
+                    break;
+                }
+                if (o == x) {
+                    print(x + " - A WINNER.........CONGRATS!!!!!!!!\n");
+                    print(x + " AT 2 TO 1 ODDS PAYS YOU...LET ME SEE..." + 2 * f + " DOLLARS\n");
+                    r += f * 2;
+                    break;
+                }
+                print(o + " - NO POINT. I WILL ROLL AGAIN\n");
+            }
+        }
+        print(" IF YOU WANT TO PLAY AGAIN PRINT 5 IF NOT PRINT 2");
+        m = parseInt(await input());
+        if (r < 0) {
+            print("YOU ARE NOW UNDER $" + -r + "\n");
+        } else if (r > 0) {
+            print("YOU ARE NOW AHEAD $" + r + "\n");
+        } else {
+            print("YOU ARE NOW EVEN AT 0\n");
+        }
+        if (m != 5)
+            break;
+    }
+    if (r < 0) {
+        print("TOO BAD, YOU ARE IN THE HOLE. COME AGAIN.\n");
+    } else if (r > 0) {
+        print("CONGRATULATIONS---YOU CAME OUT A WINNER. COME AGAIN!\n");
+    } else {
+        print("CONGRATULATIONS---YOU CAME OUT EVEN, NOT BAD FOR AN AMATEUR\n");
+    }
+    
+}
+
+main();

From 7a20c874bc9b44f8b8821fbbdea1bb4c0dd40ac0 Mon Sep 17 00:00:00 2001
From: Nahid Mondol 
Date: Wed, 3 Mar 2021 16:44:14 -0500
Subject: [PATCH 211/749] Updated War.java

---
 94 War/java/War.java | 222 +++++++++++++++++++++++++++----------------
 1 file changed, 138 insertions(+), 84 deletions(-)

diff --git a/94 War/java/War.java b/94 War/java/War.java
index ebe7ffca..cd66fcc1 100644
--- a/94 War/java/War.java	
+++ b/94 War/java/War.java	
@@ -11,66 +11,152 @@ import java.util.Scanner;
 public class War {
 
     private static final int CARD_DECK_SIZE = 52;
-    private static int totalPlayerScore = 0;
-    private static int totalComputerScore = 0;
-    private static boolean directionPhase;
-    static Scanner input = new Scanner(System.in);
-    static ArrayList cards = new ArrayList(
+    private static int playerTotalScore = 0;
+    private static int computerTotalScore = 0;
+    private static boolean invalidInput;
+    private static Scanner userInput = new Scanner(System.in);
+
+    // Simple approach for storing a deck of cards
+    // Suit-Value, ex: 2 of Spades = S-2, King of Diamonds = D-K, etc...
+    private static ArrayList deckOfCards = new ArrayList(
             Arrays.asList("S-2", "H-2", "C-2", "D-2", "S-3", "H-3", "C-3", "D-3", "S-4", "H-4", "C-4", "D-4", "S-5",
                     "H-5", "C-5", "D-5", "S-6", "H-6", "C-6", "D-6", "S-7", "H-7", "C-7", "D-7", "S-8", "H-8", "C-8",
                     "D-8", "S-9", "H-9", "C-9", "D-9", "S-10", "H-10", "C-10", "D-10", "S-J", "H-J", "C-J", "D-J",
                     "S-Q", "H-Q", "C-Q", "D-Q", "S-K", "H-K", "C-K", "D-K", "S-A", "H-A", "C-A", "D-A"));
 
     public static void main(String[] args) {
+        introMessage();
+        showDirectionsBasedOnInput();
+        playGame();
+    }
+
+    private static void introMessage() {
         System.out.println("\t         WAR");
         System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
         System.out.println("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#");
         System.out.print("AS S-7 FOR SPADE 7. DO YOU WANT DIRECTIONS? ");
-
-        while (!directionPhase) {
-            getDirections(input);
-        }
-        System.out.println();
-        playGame();
     }
 
-    private static void getDirections(Scanner userInput) {
-        switch (userInput.nextLine().toLowerCase()) {
-            case "yes":
-                System.out.println("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD");
-                System.out.println("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO ");
-                System.out.println("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.");
-                directionPhase = true;
-                break;
-            case "no":
-                directionPhase = true;
-                break;
-            default:
-                System.out.print("YES OR NO, PLEASE.   ");
+    private static void showDirectionsBasedOnInput() {
+        // Stay in loop until player chooses an option.
+        invalidInput = true;
+        while (invalidInput) {
+            switch (userInput.nextLine().toLowerCase()) {
+                case "yes":
+                    System.out.println("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD");
+                    System.out.println("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO ");
+                    System.out.println("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n");
+                    invalidInput = false;
+                    break;
+                case "no":
+                    System.out.println();
+                    invalidInput = false;
+                    break;
+                default:
+                    System.out.print("YES OR NO, PLEASE.   ");
+            }
         }
     }
 
     private static void playGame() {
 
-        boolean endedEarly = false;
+        // Checks to see if the player ends the game early.
+        // Ending early will cause a different output to appear.
+        boolean gameEndedEarly = false;
 
         // Shuffle the deck of cards
-        Collections.shuffle(cards);
+        Collections.shuffle(deckOfCards);
 
-        // Since the cards are already suffled, pull each card from the deck
-        // until the deck is empty or until the user quits.
+        // Since the deck is already suffled, pull each card until the deck is empty or
+        // until the user quits.
+        outerloop:
         for (int i = 1; i <= CARD_DECK_SIZE; i += 2) {
-            System.out.println("YOU: " + cards.get(i - 1) + "\t " + "COMPUTER: " + cards.get(i));
-            getWinner(cards.get(i - 1), cards.get(i));
-            System.out.print("DO YOU WANT TO CONTINUE? ");
-            // while (isInvalidInput) {
-            if (isGameEnded()) {
-                endedEarly = true;
-                break;
+            System.out.println("YOU: " + deckOfCards.get(i - 1) + "\t " + "COMPUTER: " + deckOfCards.get(i));
+            getWinner(deckOfCards.get(i - 1), deckOfCards.get(i));
+
+            invalidInput = true;
+            while (invalidInput) {
+                if (endedEarly()) {
+                    // Player ended game early. 
+                    // Break out of game loop and show end game output.
+                    gameEndedEarly = true;
+                    break outerloop;
+                }
             }
-            // }
         }
 
+        endGameOutput(gameEndedEarly);
+    }
+
+    /**
+     * Outputs the winner of the current round.
+     * 
+     * @param playerCard   Players card.
+     * @param computerCard Computers card.
+     */
+    private static void getWinner(String playerCard, String computerCard) {
+
+        // Return the number value of the card pulled.
+        String playerCardScore = (playerCard.length() == 3) ? Character.toString(playerCard.charAt(2))
+                : playerCard.substring(2, 4);
+        String computerCardScore = (computerCard.length() == 3) ? Character.toString(computerCard.charAt(2))
+                : computerCard.substring(2, 4);
+
+        if (checkCourtCards(playerCardScore) > checkCourtCards(computerCardScore)) {
+            System.out.println("YOU WIN.   YOU HAVE " + playerWonRound() + "   COMPUTER HAS " + getComputerScore());
+        } else if (checkCourtCards(playerCardScore) < checkCourtCards(computerCardScore)) {
+            System.out.println(
+                    "COMPUTER WINS!!!   YOU HAVE " + getPlayerScore() + "   COMPUTER HAS " + computerWonRound());
+        } else {
+            System.out.println("TIE.  NO SCORE CHANGE");
+        }
+
+        System.out.print("DO YOU WANT TO CONTINUE? ");
+    }
+
+    /**
+     * @param cardScore Score of the card being pulled.
+     * @return an integer value of the current card's score.
+     */
+    private static int checkCourtCards(String cardScore) {
+        switch (cardScore) {
+            case "J":
+                return Integer.parseInt("11");
+            case "Q":
+                return Integer.parseInt("12");
+            case "K":
+                return Integer.parseInt("13");
+            case "A":
+                return Integer.parseInt("14");
+            default:
+                return Integer.parseInt(cardScore);
+        }
+    }
+
+    /**
+     * @return true if the player ended the game early. false otherwise.
+     */
+    private static boolean endedEarly() {
+        switch (userInput.nextLine().toLowerCase()) {
+            case "yes":
+                invalidInput = false;
+                return false;
+            case "no":
+                invalidInput = false;
+                return true;
+            default:
+                invalidInput = true;
+                System.out.print("YES OR NO, PLEASE.   ");
+                return false;
+        }
+    }
+
+    /**
+     * Show output based on if the game was ended early or not.
+     * 
+     * @param endedEarly true if the game was ended early, false otherwise.
+     */
+    private static void endGameOutput(boolean endedEarly) {
         if (endedEarly) {
             System.out.println("YOU HAVE ENDED THE GAME. FINAL SCORE:  YOU: " + getPlayerScore() + " COMPUTER: "
                     + getComputerScore());
@@ -82,63 +168,31 @@ public class War {
         }
     }
 
-    private static void getWinner(String playerCard, String computerCard) {
-
-        String playerScore = (playerCard.length() == 3) ? Character.toString(playerCard.charAt(2))
-                : playerCard.substring(2, 4);
-        String computerScore = (computerCard.length() == 3) ? Character.toString(computerCard.charAt(2))
-                : computerCard.substring(2, 4);
-
-        if (Integer.parseInt(checkCourtCards(playerScore)) > Integer.parseInt(checkCourtCards(computerScore))) {
-            System.out.println("YOU WIN.   YOU HAVE " + playerWonRound() + "   COMPUTER HAS " + getComputerScore());
-        } else if (Integer.parseInt(checkCourtCards(playerScore)) < Integer.parseInt(checkCourtCards(computerScore))) {
-            System.out.println(
-                    "COMPUTER WINS!!!   YOU HAVE " + getPlayerScore() + "   COMPUTER HAS " + computerWonRound());
-        } else {
-            System.out.println("TIE.  NO SCORE CHANGE");
-        }
-    }
-
-    private static String checkCourtCards(String score) {
-        switch (score) {
-            case "J":
-                return "11";
-            case "Q":
-                return "12";
-            case "K":
-                return "13";
-            case "A":
-                return "14";
-            default:
-                return score;
-        }
-    }
-
-    private static boolean isGameEnded() {
-        switch (input.nextLine().toLowerCase()) {
-            case "yes":
-                return false;
-            case "no":
-                return true;
-            default:
-                System.out.print("YES OR NO, PLEASE.   ");
-                return false;
-        }
-    }
-
+    /**
+     * Increment the player's total score if they have won the round.
+     */
     private static int playerWonRound() {
-        return totalPlayerScore += 1;
+        return playerTotalScore += 1;
     }
 
+    /**
+     * Get the player's total score.
+     */
     private static int getPlayerScore() {
-        return totalPlayerScore;
+        return playerTotalScore;
     }
 
+    /**
+     * Increment the computer's total score if they have won the round.
+     */
     private static int computerWonRound() {
-        return totalComputerScore += 1;
+        return computerTotalScore += 1;
     }
 
+    /**
+     * Get the computer's total score.
+     */
     private static int getComputerScore() {
-        return totalComputerScore;
+        return computerTotalScore;
     }
 }
\ No newline at end of file

From 9bfcfed56963efffe78210afecd531060d812223 Mon Sep 17 00:00:00 2001
From: Daniel Piron 
Date: Wed, 3 Mar 2021 16:22:09 -0500
Subject: [PATCH 212/749] Center and left hand vertical wins correctly detected

---
 89 Tic-Tac-Toe/python/tictactoe2.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/89 Tic-Tac-Toe/python/tictactoe2.py b/89 Tic-Tac-Toe/python/tictactoe2.py
index 63a68d0f..181e86eb 100755
--- a/89 Tic-Tac-Toe/python/tictactoe2.py	
+++ b/89 Tic-Tac-Toe/python/tictactoe2.py	
@@ -127,7 +127,7 @@ def determine_winner(board, g):
             return Winner.PLAYER
 
     # Check for matching vertical lines
-    for i in range(Space.TOP_LEFT.value, Space.TOP_LEFT.value + 1, 1):  # Second third of Line 1115
+    for i in range(Space.TOP_LEFT.value, Space.TOP_RIGHT.value + 1, 1):  # Second third of Line 1115
         if board[i] != board[i+3] or board[i] != board[i+6]: # Last third of Line 1115
             continue # First third of 1150
         elif board[i] == OccupiedBy.COMPUTER: # Line 1135

From 33a93d58298c3568592c9cd46e4230c593dc90d1 Mon Sep 17 00:00:00 2001
From: Nahid Mondol 
Date: Wed, 3 Mar 2021 16:49:29 -0500
Subject: [PATCH 213/749] Updated War.java

---
 94 War/java/War.java | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/94 War/java/War.java b/94 War/java/War.java
index cd66fcc1..b09a4616 100644
--- a/94 War/java/War.java	
+++ b/94 War/java/War.java	
@@ -4,9 +4,9 @@ import java.util.Collections;
 import java.util.Scanner;
 
 /**
- * Converted FROM BASIC to Java by Nahid Mondol
+ * Converted FROM BASIC to Java by Nahid Mondol.
  * 
- * Based on Trevor Hobsons approach
+ * Based on Trevor Hobsons approach.
  */
 public class War {
 
@@ -16,7 +16,7 @@ public class War {
     private static boolean invalidInput;
     private static Scanner userInput = new Scanner(System.in);
 
-    // Simple approach for storing a deck of cards
+    // Simple approach for storing a deck of cards.
     // Suit-Value, ex: 2 of Spades = S-2, King of Diamonds = D-K, etc...
     private static ArrayList deckOfCards = new ArrayList(
             Arrays.asList("S-2", "H-2", "C-2", "D-2", "S-3", "H-3", "C-3", "D-3", "S-4", "H-4", "C-4", "D-4", "S-5",
@@ -64,7 +64,7 @@ public class War {
         // Ending early will cause a different output to appear.
         boolean gameEndedEarly = false;
 
-        // Shuffle the deck of cards
+        // Shuffle the deck of cards.
         Collections.shuffle(deckOfCards);
 
         // Since the deck is already suffled, pull each card until the deck is empty or

From 2899078cd5de3f6a8b8abad8977efe0631c1922d Mon Sep 17 00:00:00 2001
From: Jonas Nockert 
Date: Wed, 3 Mar 2021 23:19:00 +0100
Subject: [PATCH 214/749] Refactored user input into functions

---
 81 Splat/python/splat.py | 58 +++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 16 deletions(-)

diff --git a/81 Splat/python/splat.py b/81 Splat/python/splat.py
index 86c95f75..b8803b4f 100644
--- a/81 Splat/python/splat.py	
+++ b/81 Splat/python/splat.py	
@@ -44,6 +44,44 @@ def yes_no_input(question, default="YES"):
     return answer.lower() in ["y", "yes"]
 
 
+def get_terminal_velocity():
+    """Terminal velocity by user or picked by computer."""
+    if yes_no_input("SELECT YOUR OWN TERMINAL VELOCITY", default="NO"):
+        v1 = numeric_input("WHAT TERMINAL VELOCITY (MI/HR)", default=100)
+    else:
+        # Computer picks 0-1000 terminal velocity.
+        v1 = int(1000 * random())
+        print(f"OK.  TERMINAL VELOCITY = {v1} MI/HR")
+
+    # Convert miles/h to feet/s.
+    return v1 * (5280 / 3600)
+
+
+def get_acceleration():
+    """Acceleration due to gravity by user or picked by computer."""
+    if yes_no_input("WANT TO SELECT ACCELERATION DUE TO GRAVITY", default="NO"):
+        a2 = numeric_input("WHAT ACCELERATION (FT/SEC/SEC)", default=32.16)
+    else:
+        body, a2 = pick_random_celestial_body()
+        print(f"FINE. YOU'RE ON {body}. ACCELERATION={a2} FT/SEC/SEC.")
+    return a2
+
+
+def get_freefall_time():
+    """User-guessed freefall time.
+
+    The idea of the game is to pick a freefall time, given initial
+    altitude, terminal velocity and acceleration, so the parachute
+    as close to the ground as possible without going splat.
+    """
+    t_freefall = 0
+    # A zero or negative freefall time is not handled by the motion
+    # equations during the jump.
+    while t_freefall <= 0:
+        t_freefall = numeric_input("HOW MANY SECONDS", default=10)
+    return t_freefall
+
+
 def jump():
     """Simulate a jump and returns the altitude where the chute opened.
 
@@ -53,26 +91,14 @@ def jump():
     a = 0  # Acceleration.
     initial_altitude = int(9001 * random() + 1000)
 
-    if yes_no_input("SELECT YOUR OWN TERMINAL VELOCITY", default="NO"):
-        v1 = numeric_input("WHAT TERMINAL VELOCITY (MI/HR)", default=100)
-    else:
-        # Computer picks 0-1000 terminal velocity.
-        v1 = int(1000 * random())
-        print(f"OK.  TERMINAL VELOCITY = {v1} MI/HR")
-
-    # Convert miles/h to feet/s.
-    v1 = v1 * (5280 / 3600)
+    v1 = get_terminal_velocity()
     # Actual terminal velocity is +/-5% of v1.
     v = v1 * uniform(0.95, 1.05)
 
-    if yes_no_input("WANT TO SELECT ACCELERATION DUE TO GRAVITY", default="NO"):
-        a2 = numeric_input("WHAT ACCELERATION (FT/SEC/SEC)", default=32.16)
-    else:
-        body, a2 = pick_random_celestial_body()
-        print(f"FINE. YOU'RE ON {body}. ACCELERATION={a2} FT/SEC/SEC.")
-
+    a2 = get_acceleration()
     # Actual acceleration is +/-5% of a2.
     a = a2 * uniform(0.95, 1.05)
+
     print(
         "\n"
         f"    ALTITUDE         = {initial_altitude} FT\n"
@@ -80,7 +106,7 @@ def jump():
         f"    ACCELERATION     = {a2:.2f} FT/SEC/SEC +/-5%\n"
         "SET THE TIMER FOR YOUR FREEFALL."
     )
-    t_freefall = numeric_input("HOW MANY SECONDS", default=10)
+    t_freefall = get_freefall_time()
     print(
         "HERE WE GO.\n\n"
         "TIME (SEC)\tDIST TO FALL (FT)\n"

From a814c9980d7eba5f6335703dbc246a050591a5c0 Mon Sep 17 00:00:00 2001
From: Jonas Nockert 
Date: Wed, 3 Mar 2021 23:27:26 +0100
Subject: [PATCH 215/749] Refactored header with centering

---
 81 Splat/python/splat.py | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/81 Splat/python/splat.py b/81 Splat/python/splat.py
index b8803b4f..6e08083b 100644
--- a/81 Splat/python/splat.py	
+++ b/81 Splat/python/splat.py	
@@ -25,6 +25,8 @@ Ported in 2021 by Jonas Nockert / @lemonad
 from math import sqrt
 from random import choice, random, uniform
 
+PAGE_WIDTH = 72
+
 
 def numeric_input(question, default=0):
     """Ask user for a numeric value."""
@@ -274,15 +276,28 @@ def print_results(n_previous_jumps, n_better):
         )
 
 
-# Main program.
+def print_centered(msg):
+    """Print centered text."""
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
 
-print(
-    "SPLAT\n"
-    "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n\n\n"
-    "WELCOME TO 'SPLAT' -- THE GAME THAT SIMULATES A PARACHUTE\n"
-    "JUMP.  TRY TO OPEN YOUR CHUTE AT THE LAST POSSIBLE\n"
-    "MOMENT WITHOUT GOING SPLAT.\n\n"
-)
+
+def print_header():
+    print_centered("SPLAT")
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print(
+        "\n\n\n"
+        "WELCOME TO 'SPLAT' -- THE GAME THAT SIMULATES A PARACHUTE\n"
+        "JUMP.  TRY TO OPEN YOUR CHUTE AT THE LAST POSSIBLE\n"
+        "MOMENT WITHOUT GOING SPLAT.\n\n"
+    )
+
+
+#
+# Main program.
+#
+
+print_header()
 
 successful_jumps = []
 while True:

From ea93a0779441ceaa5fc7ae9445f7a1fde7525e29 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Wed, 3 Mar 2021 17:11:09 -0600
Subject: [PATCH 216/749] Ported CUBE to Javascript

---
 30 Cube/cube.bas             |   4 +-
 30 Cube/javascript/cube.html |   9 ++
 30 Cube/javascript/cube.js   | 207 +++++++++++++++++++++++++++++++++++
 3 files changed, 218 insertions(+), 2 deletions(-)
 create mode 100644 30 Cube/javascript/cube.html
 create mode 100644 30 Cube/javascript/cube.js

diff --git a/30 Cube/cube.bas b/30 Cube/cube.bas
index e661ab66..1e4462f6 100644
--- a/30 Cube/cube.bas	
+++ b/30 Cube/cube.bas	
@@ -76,7 +76,7 @@
 820 LET O=3
 830 PRINT "WANT TO MAKE A WAGER?"
 840 INPUT Z
-850 IF Z=0 THEN 920
+850 IF Z=0 THEN 880
 860 PRINT "HOW MUCH ";
 870 INPUT Z1
 876 IF A1
+
+CUBE
+
+
+

+
+
+
diff --git a/30 Cube/javascript/cube.js b/30 Cube/javascript/cube.js
new file mode 100644
index 00000000..edbaaedc
--- /dev/null
+++ b/30 Cube/javascript/cube.js	
@@ -0,0 +1,207 @@
+// CUBE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "CUBE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("DO YOU WANT TO SEE THE INSTRUCTIONS? (YES--1,NO--0)");
+    b7 = parseInt(await input());
+    if (b7 != 0) {
+        print("THIS IS A GAME IN WHICH YOU WILL BE PLAYING AGAINST THE\n");
+        print("RANDOM DECISION OF THE COMPUTER. THE FIELD OF PLAY IS A\n");
+        print("CUBE OF SIDE 3. ANY OF THE 27 LOCATIONS CAN BE DESIGNATED\n");
+        print("BY INPUTING THREE NUMBERS SUCH AS 2,3,1. AT THE START,\n");
+        print("YOU ARE AUTOMATICALLY AT LOCATION 1,1,1. THE OBJECT OF\n");
+        print("THE GAME IS TO GET TO LOCATION 3,3,3. ONE MINOR DETAIL:\n");
+        print("THE COMPUTER WILL PICK, AT RANDOM, 5 LOCATIONS AT WHICH\n");
+        print("IT WILL PLANT LAND MINES. IF YOU HIT ONE OF THESE LOCATIONS\n");
+        print("YOU LOSE. ONE OTHER DETAIL: YOU MAY MOVE ONLY ONE SPACE \n");
+        print("IN ONE DIRECTION EACH MOVE. FOR  EXAMPLE: FROM 1,1,2 YOU\n");
+        print("MAY MOVE TO 2,1,2 OR 1,1,3. YOU MAY NOT CHANGE\n");
+        print("TWO OF THE NUMBERS ON THE SAME MOVE. IF YOU MAKE AN ILLEGAL\n");
+        print("MOVE, YOU LOSE AND THE COMPUTER TAKES THE MONEY YOU MAY\n");
+        print("HAVE BET ON THAT ROUND.\n");
+        print("\n");
+        print("\n");
+        print("ALL YES OR NO QUESTIONS WILL BE ANSWERED BY A 1 FOR YES\n");
+        print("OR A 0 (ZERO) FOR NO.\n");
+        print("\n");
+        print("WHEN STATING THE AMOUNT OF A WAGER, PRINT ONLY THE NUMBER\n");
+        print("OF DOLLARS (EXAMPLE: 250)  YOU ARE AUTOMATICALLY STARTED WITH\n");
+        print("500 DOLLARS IN YOUR ACCOUNT.\n");
+        print("\n");
+        print("GOOD LUCK!\n");
+    }
+    a1 = 500;
+    while (1) {
+        a = Math.floor(3 * Math.random());
+        if (a == 0)
+            a = 3;
+        b = Math.floor(3 * Math.random());
+        if (b == 0)
+            b = 2;
+        c = Math.floor(3 * Math.random());
+        if (c == 0)
+            c = 3;
+        d = Math.floor(3 * Math.random());
+        if (d == 0)
+            d = 1;
+        e = Math.floor(3 * Math.random());
+        if (e == 0)
+            e = 3;
+        f = Math.floor(3 * Math.random());
+        if (f == 0)
+            f = 3;
+        g = Math.floor(3 * Math.random());
+        if (g == 0)
+            g = 3;
+        h = Math.floor(3 * Math.random());
+        if (h == 0)
+            h = 3;
+        i = Math.floor(3 * Math.random());
+        if (i == 0)
+            i = 2;
+        j = Math.floor(3 * Math.random());
+        if (j == 0)
+            j = 3;
+        k = Math.floor(3 * Math.random());
+        if (k == 0)
+            k = 2;
+        l = Math.floor(3 * Math.random());
+        if (l == 0)
+            l = 3;
+        m = Math.floor(3 * Math.random());
+        if (m == 0)
+            m = 3;
+        n = Math.floor(3 * Math.random());
+        if (n == 0)
+            n = 1;
+        o = Math.floor(3 * Math.random());
+        if (o == 0)
+            o = 3;
+        print("WANT TO MAKE A WAGER?");
+        z = parseInt(await input());
+        if (z != 0) {
+            print("HOW MUCH ");
+            while (1) {
+                z1 = parseInt(await input());
+                if (a1 < z1) {
+                    print("TRIED TO FOOL ME; BET AGAIN");
+                } else {
+                    break;
+                }
+            }
+        }
+        w = 1;
+        x = 1;
+        y = 1;
+        print("\n");
+        print("IT'S YOUR MOVE:  ");
+        while (1) {
+            str = await input();
+            p = parseInt(str);
+            q = parseInt(str.substr(str.indexOf(",") + 1));
+            r = parseInt(str.substr(str.lastIndexOf(",") + 1));
+            if (p > w + 1 || q > x + 1 || r > y + 1 || (p == w + 1 && (q >= x + 1 || r >= y + 1)) || (q == x + 1 && r >= y + 1)) {
+                print("\n");
+                print("ILLEGAL MOVE, YOU LOSE.\n");
+                break;
+            }
+            w = p;
+            x = q;
+            y = r;
+            if (p == 3 && q == 3 && r == 3) {
+                won = true;
+                break;
+            }
+            if (p == a && q == b && r == c
+             || p == d && q == e && r == f
+             || p == g && q == h && r == i
+             || p == j && q == k && r == l
+             || p == m && q == n && r == o) {
+                print("******BANG******");
+                print("YOU LOSE!");
+                print("\n");
+                print("\n");
+                won = false;
+                break;
+            }
+            print("NEXT MOVE: ");
+        }
+        if (won) {
+            print("CONGRATULATIONS!\n");
+            if (z != 0) {
+                z2 = a1 + z1;
+                print("YOU NOW HAVE " + z2 + " DOLLARS.\n");
+                a1 = z2;
+            }
+        } else {
+            if (z != 0) {
+                print("\n");
+                z2 = a1 - z1;
+                if (z2 <= 0) {
+                    print("YOU BUST.\n");
+                    break;
+                } else {
+                    print(" YOU NOW HAVE " + z2 + " DOLLARS.\n");
+                    a1 = z2;
+                }
+            }
+        }
+        print("DO YOU WANT TO TRY AGAIN ");
+        s = parseInt(await input());
+        if (s != 1)
+            break;
+    }
+    print("TOUGH LUCK!\n");
+    print("\n");
+    print("GOODBYE.\n");
+}
+
+main();

From dbfcc3dfc208d1f279cfd99557e611a678e959c8 Mon Sep 17 00:00:00 2001
From: Haydn Kane 
Date: Thu, 4 Mar 2021 00:35:47 +0000
Subject: [PATCH 217/749] C# port of Name

---
 63 Name/csharp/Name.csproj         |  8 ++++++
 63 Name/csharp/Name.sln            | 25 +++++++++++++++++
 63 Name/csharp/Program.cs          | 44 ++++++++++++++++++++++++++++++
 63 Name/csharp/StringExtensions.cs | 41 ++++++++++++++++++++++++++++
 4 files changed, 118 insertions(+)
 create mode 100644 63 Name/csharp/Name.csproj
 create mode 100644 63 Name/csharp/Name.sln
 create mode 100644 63 Name/csharp/Program.cs
 create mode 100644 63 Name/csharp/StringExtensions.cs

diff --git a/63 Name/csharp/Name.csproj b/63 Name/csharp/Name.csproj
new file mode 100644
index 00000000..c73e0d16
--- /dev/null
+++ b/63 Name/csharp/Name.csproj	
@@ -0,0 +1,8 @@
+
+
+  
+    Exe
+    netcoreapp3.1
+  
+
+
diff --git a/63 Name/csharp/Name.sln b/63 Name/csharp/Name.sln
new file mode 100644
index 00000000..931d9288
--- /dev/null
+++ b/63 Name/csharp/Name.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Name", "Name.csproj", "{B63B5D5C-C5E0-4EFE-9EF4-292915DCC22D}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B63B5D5C-C5E0-4EFE-9EF4-292915DCC22D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B63B5D5C-C5E0-4EFE-9EF4-292915DCC22D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B63B5D5C-C5E0-4EFE-9EF4-292915DCC22D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B63B5D5C-C5E0-4EFE-9EF4-292915DCC22D}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {FCD5BEAE-D35E-49A7-B8F3-B8B3F4A8C624}
+	EndGlobalSection
+EndGlobal
diff --git a/63 Name/csharp/Program.cs b/63 Name/csharp/Program.cs
new file mode 100644
index 00000000..a9c817f3
--- /dev/null
+++ b/63 Name/csharp/Program.cs	
@@ -0,0 +1,44 @@
+using System;
+
+namespace Name
+{
+    public class Program
+    {
+        static void Main(string[] args)
+        {
+            Console.WriteLine("NAME".CentreAlign());
+            Console.WriteLine("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY".CentreAlign());
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("HELLO.");
+            Console.WriteLine("MY NAME IS CREATIVE COMPUTER.");
+            Console.Write("WHAT'S YOUR NAME (FIRST AND LAST? ");
+            var name = Console.ReadLine();
+            Console.WriteLine();
+            Console.WriteLine($"THANK YOU, {name.Reverse()}.");
+            Console.WriteLine("OOPS!  I GUESS I GOT IT BACKWARDS.  A SMART");
+            Console.WriteLine("COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!");
+            Console.WriteLine();
+            Console.WriteLine("BUT I JUST NOTICED YOUR LETTERS ARE OUT OF ORDER.");
+            Console.WriteLine($"LET'S PUT THEM IN ORDER LIKE THIS: {name.Sort()}");
+            Console.WriteLine();
+            Console.Write("DON'T YOU LIKE THAT BETTER? ");
+            var like = Console.ReadLine();
+            Console.WriteLine();
+
+            if (like.ToUpperInvariant() == "YES")
+            {
+                Console.WriteLine("I KNEW YOU'D AGREE!!");
+            }
+            else
+            {
+                Console.WriteLine("I'M SORRY YOU DON'T LIKE IT THAT WAY.");
+            }
+
+            Console.WriteLine();
+            Console.WriteLine($"I REALLY ENJOYED MEETING YOU {name}.");
+            Console.WriteLine("HAVE A NICE DAY!");
+        }
+    }
+}
diff --git a/63 Name/csharp/StringExtensions.cs b/63 Name/csharp/StringExtensions.cs
new file mode 100644
index 00000000..8003fa38
--- /dev/null
+++ b/63 Name/csharp/StringExtensions.cs	
@@ -0,0 +1,41 @@
+using System;
+
+namespace Name
+{
+    public static class StringExtensions
+    {
+        private const int ConsoleWidth = 120; // default console width
+
+        public static string CentreAlign(this string value)
+        {
+            int spaces = ConsoleWidth - value.Length;
+            int leftPadding = spaces / 2 + value.Length;
+
+            return value.PadLeft(leftPadding).PadRight(ConsoleWidth);
+        }
+
+        public static string Reverse(this string value)
+        {
+            if (value is null)
+            {
+                return null;
+            }
+
+            char[] characterArray = value.ToCharArray();
+            Array.Reverse(characterArray);
+            return new String(characterArray);
+        }
+
+        public static string Sort(this string value)
+        {
+            if (value is null)
+            {
+                return null;
+            }
+
+            char[] characters = value.ToCharArray();
+            Array.Sort(characters);
+            return new string(characters);
+        }
+    }
+}

From 04f5f8d71e9e8eb42fac58a9af5d66be3c50ad47 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Wed, 3 Mar 2021 19:11:42 -0600
Subject: [PATCH 218/749] Ported CIVIL WAR to Javascript

---
 27 Civil War/civilwar.bas             |   4 +-
 27 Civil War/javascript/civilwar.html |   9 +
 27 Civil War/javascript/civilwar.js   | 528 ++++++++++++++++++++++++++
 3 files changed, 539 insertions(+), 2 deletions(-)
 create mode 100644 27 Civil War/javascript/civilwar.html
 create mode 100644 27 Civil War/javascript/civilwar.js

diff --git a/27 Civil War/civilwar.bas b/27 Civil War/civilwar.bas
index 5720d767..2311711e 100644
--- a/27 Civil War/civilwar.bas	
+++ b/27 Civil War/civilwar.bas	
@@ -284,7 +284,7 @@
 2940  PRINT "THE UNION HAS WON THE WAR"
 2950  PRINT
 2960  IF R1=0 THEN 3100
-2970  PRINT "FOR THE "W+L+W0" BATTLES FOUGHT (EXCUDING RERUNS)"
+2970  PRINT "FOR THE "W+L+W0" BATTLES FOUGHT (EXCLUDING RERUNS)"
 2980  PRINT " "," "," ";
 2990  PRINT "CONFEDERACY"," UNION"
 3000  PRINT "HISTORICAL LOSSES",INT(P1+.5),INT(P2+.5)
@@ -295,7 +295,7 @@
 3050  PRINT
 3060  PRINT "UNION INTELLIGENCE SUGGESTS THAT THE SOUTH USED "
 3070  PRINT "STRATEGIES 1, 2, 3, 4 IN THE FOLLOWING PERCENTAGES"
-3080  PRINT S(1);S2(2);S(3);S(4)
+3080  PRINT S(1);S(2);S(3);S(4)
 3090  REM---------------------------------
 3100  STOP
 3110  REM - UNION STRATEGY IS COMPUTER CHOSEN
diff --git a/27 Civil War/javascript/civilwar.html b/27 Civil War/javascript/civilwar.html
new file mode 100644
index 00000000..dcff69ff
--- /dev/null
+++ b/27 Civil War/javascript/civilwar.html	
@@ -0,0 +1,9 @@
+
+
+CIVIL WAR
+
+
+

+
+
+
diff --git a/27 Civil War/javascript/civilwar.js b/27 Civil War/javascript/civilwar.js
new file mode 100644
index 00000000..489e2955
--- /dev/null
+++ b/27 Civil War/javascript/civilwar.js	
@@ -0,0 +1,528 @@
+// CIVIL WAR
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Historical data...can add more (strat., etc) by inserting
+// data statements after appro. info, and adjusting read
+//                      0 - C$     1-M1  2-M2  3-C1 4-C2 5-D
+var historical_data = [,
+                       ["BULL RUN",18000,18500,1967,2708,1],
+                       ["SHILOH",40000.,44894.,10699,13047,3],
+                       ["SEVEN DAYS",95000.,115000.,20614,15849,3],
+                       ["SECOND BULL RUN",54000.,63000.,10000,14000,2],
+                       ["ANTIETAM",40000.,50000.,10000,12000,3],
+                       ["FREDERICKSBURG",75000.,120000.,5377,12653,1],
+                       ["MURFREESBORO",38000.,45000.,11000,12000,1],
+                       ["CHANCELLORSVILLE",32000,90000.,13000,17197,2],
+                       ["VICKSBURG",50000.,70000.,12000,19000,1],
+                       ["GETTYSBURG",72500.,85000.,20000,23000,3],
+                       ["CHICKAMAUGA",66000.,60000.,18000,16000,2],
+                       ["CHATTANOOGA",37000.,60000.,36700.,5800,2],
+                       ["SPOTSYLVANIA",62000.,110000.,17723,18000,2],
+                       ["ATLANTA",65000.,100000.,8500,3700,1]];
+var sa = [];
+var da = [];
+var fa = [];
+var ha = [];
+var ba = [];
+var oa = [];
+
+// Main program
+async function main()
+{
+    print(tab(26) + "CIVIL WAR\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // Original game design: Cram, Goodie, Hibbard Lexington H.S.
+    // Modifications: G. Paul, R. Hess (Ties), 1973
+    // Union info on likely confederate strategy
+    sa[1] = 25;
+    sa[2] = 25;
+    sa[3] = 25;
+    sa[4] = 25;
+    d = Math.random();
+    print("\n");
+    print("DO YOU WANT INSTRUCTIONS");
+    while (1) {
+        str = await input();
+        if (str == "YES" || str == "NO")
+            break;
+        print("YES OR NO -- \n");
+    }
+    if (str == "YES") {
+        print("\n");
+        print("\n");
+        print("\n");
+        print("\n");
+        print("THIS IS A CIVIL WAR SIMULATION.\n");
+        print("TO PLAY TYPE A RESPONSE WHEN THE COMPUTER ASKS.\n");
+        print("REMEMBER THAT ALL FACTORS ARE INTERRELATED AND THAT YOUR\n");
+        print("RESPONSES COULD CHANGE HISTORY. FACTS AND FIGURES USED ARE\n");
+        print("BASED ON THE ACTUAL OCCURRENCE. MOST BATTLES TEND TO RESULT\n");
+        print("AS THEY DID IN THE CIVIL WAR, BUT IT ALL DEPENDS ON YOU!!\n");
+        print("\n");
+        print("THE OBJECT OF THE GAME IS TO WIN AS MANY BATTLES AS ");
+        print("POSSIBLE.\n");
+        print("\n");
+        print("YOUR CHOICES FOR DEFENSIVE STRATEGY ARE:\n");
+        print("        (1) ARTILLERY ATTACK\n");
+        print("        (2) FORTIFICATION AGAINST FRONTAL ATTACK\n");
+        print("        (3) FORTIFICATION AGAINST FLANKING MANEUVERS\n");
+        print("        (4) FALLING BACK\n");
+        print(" YOUR CHOICES FOR OFFENSIVE STRATEGY ARE:\n");
+        print("        (1) ARTILLERY ATTACK\n");
+        print("        (2) FRONTAL ATTACK\n");
+        print("        (3) FLANKING MANEUVERS\n");
+        print("        (4) ENCIRCLEMENT\n");
+        print("YOU MAY SURRENDER BY TYPING A '5' FOR YOUR STRATEGY.\n");
+    }
+    print("\n");
+    print("\n");
+    print("\n");
+    print("ARE THERE TWO GENERALS PRESENT ");
+    while (1) {
+        print("(ANSWER YES OR NO)");
+        bs = await input();
+        if (bs == "YES") {
+            d = 2;
+            break;
+        } else if (bs == "NO") {
+            print("\n");
+            print("YOU ARE THE CONFEDERACY.   GOOD LUCK!\n");
+            print("\n");
+            d = 1;
+            break;
+        }
+    }
+    print("SELECT A BATTLE BY TYPING A NUMBER FROM 1 TO 14 ON\n");
+    print("REQUEST.  TYPE ANY OTHER NUMBER TO END THE SIMULATION.\n");
+    print("BUT '0' BRINGS BACK EXACT PREVIOUS BATTLE SITUATION\n");
+    print("ALLOWING YOU TO REPLAY IT\n");
+    print("\n");
+    print("NOTE: A NEGATIVE FOOD$ ENTRY CAUSES THE PROGRAM TO \n");
+    print("USE THE ENTRIES FROM THE PREVIOUS BATTLE\n");
+    print("\n");
+    print("AFTER REQUESTING A BATTLE, DO YOU WISH ");
+    print("BATTLE DESCRIPTIONS ");
+    while (1) {
+        print("(ANSWER YES OR NO)");
+        xs = await input();
+        if (xs == "YES" || xs == "NO")
+            break;
+    }
+    l = 0;
+    w = 0;
+    r1 = 0;
+    q1 = 0;
+    m3 = 0;
+    m4 = 0;
+    p1 = 0;
+    p2 = 0;
+    t1 = 0;
+    t2 = 0;
+    for (i = 1; i <= 2; i++) {
+        da[i] = 0;
+        fa[i] = 0;
+        ha[i] = 0;
+        ba[i] = 0;
+        oa[i] = 0;
+    }
+    r2 = 0;
+    q2 = 0;
+    c6 = 0;
+    f = 0;
+    w0 = 0;
+    y = 0;
+    y2 = 0;
+    u = 0;
+    u2 = 0;
+    while (1) {
+        print("\n");
+        print("\n");
+        print("\n");
+        print("WHICH BATTLE DO YOU WISH TO SIMULATE");
+        a = parseInt(await input());
+        if (a < 1 || a > 14)
+            break;
+        if (a != 0 || r == 0) {
+            cs = historical_data[a][0];
+            m1 = historical_data[a][1];
+            m2 = historical_data[a][2];
+            c1 = historical_data[a][3];
+            c2 = historical_data[a][4];
+            m = historical_data[a][5];
+            u = 0;
+            // Inflation calc
+            i1 = 10 + (l - w) * 2;
+            i2 = 10 + (w - l) * 2;
+            // Money available
+            da[1] = 100 * Math.floor((m1 * (100 - i1) / 2000) * (1 + (r1 - q1) / (r1 + 1)) + 0.5);
+            da[2] = 100 * Math.floor(m2 * (100 - i2) / 2000 + 0.5);
+            if (bs == "YES") {
+                da[2] = 100 * Math.floor((m2 * (100 - i2) / 2000) * (1 + (r2 - q2) / (r2 + 1)) + 0.5);
+            }
+            // Men available
+            m5 = Math.floor(m1 * (1 + (p1 - t1) / (m3 + 1)));
+            m6 = Math.floor(m2 * (1 + (p2 - t2) / (m4 + 1)));
+            f1 = 5 * m1 / 6;
+            print("\n");
+            print("\n");
+            print("\n");
+            print("\n");
+            print("\n");
+            print("THIS IS THE BATTLE OF " + cs + "\n");
+            if (xs != "NO") {
+                switch (a) {
+                    case 1:
+                        print("JULY 21, 1861.  GEN. BEAUREGARD, COMMANDING THE SOUTH, MET\n");
+                        print("UNION FORCES WITH GEN. MCDOWELL IN A PREMATURE BATTLE AT\n");
+                        print("BULL RUN. GEN. JACKSON HELPED PUSH BACK THE UNION ATTACK.\n");
+                        break;
+                    case 2:
+                        print("APRIL 6-7, 1862.  THE CONFEDERATE SURPRISE ATTACK AT\n");
+                        print("SHILOH FAILED DUE TO POOR ORGANIZATION.\n");
+                        break;
+                    case 3:
+                        print("JUNE 25-JULY 1, 1862.  GENERAL LEE (CSA) UPHELD THE\n");
+                        print("OFFENSIVE THROUGHOUT THE BATTLE AND FORCED GEN. MCCLELLAN\n");
+                        print("AND THE UNION FORCES AWAY FROM RICHMOND.\n");
+                        break;
+                    case 4:
+                        print("AUG 29-30, 1862.  THE COMBINED CONFEDERATE FORCES UNDER LEE\n");
+                        print("AND JACKSON DROVE THE UNION FORCES BACK INTO WASHINGTON.\n");
+                        break;
+                    case 5:
+                        print("SEPT 17, 1862.  THE SOUTH FAILED TO INCORPORATE MARYLAND\n");
+                        print("INTO THE CONFEDERACY.\n");
+                        break;
+                    case 6:
+                        print("DEC 13, 1862.  THE CONFEDERACY UNDER LEE SUCCESSFULLY\n");
+                        print("REPULSED AN ATTACK BY THE UNION UNDER GEN. BURNSIDE.\n");
+                        break;
+                    case 7:
+                        print("DEC 31, 1862.  THE SOUTH UNDER GEN. BRAGG WON A CLOSE BATTLE.\n");
+                        break;
+                    case 8:
+                        print("MAY 1-6, 1863.  THE SOUTH HAD A COSTLY VICTORY AND LOST\n");
+                        print("ONE OF THEIR OUTSTANDING GENERALS, 'STONEWALL' JACKSON.\n");
+                        break;
+                    case 9:
+                        print("JULY 4, 1863.  VICKSBURG WAS A COSTLY DEFEAT FOR THE SOUTH\n");
+                        print("BECAUSE IT GAVE THE UNION ACCESS TO THE MISSISSIPPI.\n");
+                        break;
+                    case 10:
+                        print("JULY 1-3, 1863.  A SOUTHERN MISTAKE BY GEN. LEE AT GETTYSBURG\n");
+                        print("COST THEM ONE OF THE MOST CRUCIAL BATTLES OF THE WAR.\n");
+                        break;
+                    case 11:
+                        print("SEPT. 15, 1863. CONFUSION IN A FOREST NEAR CHICKAMAUGA LED\n");
+                        print("TO A COSTLY SOUTHERN VICTORY.\n");
+                        break;
+                    case 12:
+                        print("NOV. 25, 1863. AFTER THE SOUTH HAD SIEGED GEN. ROSENCRANS'\n");
+                        print("ARMY FOR THREE MONTHS, GEN. GRANT BROKE THE SIEGE.\n");
+                        break;
+                    case 13:
+                        print("MAY 5, 1864.  GRANT'S PLAN TO KEEP LEE ISOLATED BEGAN TO\n");
+                        print("FAIL HERE, AND CONTINUED AT COLD HARBOR AND PETERSBURG.\n");
+                        break;
+                    case 14:
+                        print("AUGUST, 1864.  SHERMAN AND THREE VETERAN ARMIES CONVERGED\n");
+                        print("ON ATLANTA AND DEALT THE DEATH BLOW TO THE CONFEDERACY.\n");
+                        break;
+                }
+            }
+        } else {
+            print(cs + " INSTANT REPLAY\n");
+        }
+        print("\n");
+        print(" \tCONFEDERACY\t UNION\n"),
+        print("MEN\t  " + m5 + "\t\t " + m6 + "\n");
+        print("MONEY\t $" + da[1] + "\t\t$" + da[2] + "\n");
+        print("INFLATION\t " + (i1 + 15) + "%\t " + i2 + "%\n");
+        print("\n");
+        // ONLY IN PRINTOUT IS CONFED INFLATION = I1 + 15%
+        // IF TWO GENERALS, INPUT CONFED, FIRST
+        for (i = 1; i <= d; i++) {
+            if (bs == "YES" && i == 1)
+                print("CONFEDERATE GENERAL---");
+            print("HOW MUCH DO YOU WISH TO SPEND FOR\n");
+            while (1) {
+                print(" - FOOD......");
+                f = parseInt(await input());
+                if (f < 0) {
+                    if (r1 == 0) {
+                        print("NO PREVIOUS ENTRIES\n");
+                        continue;
+                    }
+                    print("ASSUME YOU WANT TO KEEP SAME ALLOCATIONS\n");
+                    print("\n");
+                    break;
+                }
+                fa[i] = f;
+                while (1) {
+                    print(" - SALARIES..");
+                    ha[i] = parseInt(await input());
+                    if (ha[i] >= 0)
+                        break;
+                    print("NEGATIVE VALUES NOT ALLOWED.\n");
+                }
+                while (1) {
+                    print(" - AMMUNITION");
+                    ba[i] = parseInt(await input());
+                    if (ba[i] >= 0)
+                        break;
+                    print("NEGATIVE VALUES NOT ALLOWED.\n");
+                }
+                print("\n");
+                if (fa[i] + ha[i] + ba[i] > da[i]) {
+                    print("THINK AGAIN! YOU HAVE ONLY $" + da[i] + "\n");
+                } else {
+                    break;
+                }
+            }
+            if (bs != "YES" || i == 2)
+                break;
+            print("UNION GENERAL---");
+        }
+        for (z = 1; z <= d; z++) {
+            if (bs == "YES") {
+                if (z == 1)
+                    print("CONFEDERATE ");
+                else
+                    print("      UNION ");
+            }
+            // Find morale
+            o = ((2 * Math.pow(fa[z], 2) + Math.pow(ha[z], 2)) / Math.pow(f1, 2) + 1);
+            if (o >= 10) {
+                print("MORALE IS HIGH\n");
+            } else if (o >= 5) {
+                print("MORALE IS FAIR\n");
+            } else {
+                print("MORALE IS POOR\n");
+            }
+            if (bs != "YES")
+                break;
+            oa[z] = o;
+        }
+        o2 = oa[2];
+        o = oa[1];
+        print("CONFEDERATE GENERAL---");
+        // Actual off/def battle situation
+        if (m == 3) {
+            print("YOU ARE ON THE OFFENSIVE\n");
+        } else if (m == 1) {
+            print("YOU ARE ON THE DEFENSIVE\n");
+        } else {
+            print("BOTH SIDES ARE ON THE OFFENSIVE \n");
+        }
+        print("\n");
+        // Choose strategies
+        if (bs != "YES") {
+            print("YOUR STRATEGY ");
+            while (1) {
+                y = parseInt(await input());
+                if (Math.abs(y - 3) < 3)
+                    break;
+                print("STRATEGY " + y + " NOT ALLOWED.\n");
+            }
+            if (y == 5) {
+                print("THE CONFEDERACY HAS SURRENDERED.\n");
+                break;
+            }
+            // Union strategy is computer choesn
+            print("UNION STRATEGY IS ");
+            if (a == 0) {
+                while (1) {
+                    y2 = parseInt(await input());
+                    if (y2 > 0 && y2 < 5)
+                        break;
+                    print("ENTER 1, 2, 3, OR 4 (USUALLY PREVIOUS UNION STRATEGY)\n");
+                }
+            } else {
+                s0 = 0;
+                r = Math.random() * 100;
+                for (i = 1; i <= 4; i++) {
+                    s0 += sa[i];
+                    // If actual strategy info is in program data statements
+                    // then r-100 is extra weight given to that strategy.
+                    if (r < s0)
+                        break;
+                }
+                y2 = i;
+                print(y2 + "\n");
+            }
+        } else {
+            for (i = 1; i <= 2; i++) {
+                if (i == 1)
+                    print("CONFEDERATE STRATEGY ");
+                while (1) {
+                    y = parseInt(await input());
+                    if (Math.abs(y - 3) < 3)
+                        break;
+                    print("STRATEGY " + y + " NOT ALLOWED.\n");
+                }
+                if (i == 2) {
+                    y2 = y;
+                    y = y1;
+                    if (y2 != 5)
+                        break;
+                } else {
+                    y1 = y;
+                }
+                print("UNION STRATEGY ");
+            }
+            // Simulated losses - North
+            c6 = (2 * c2 / 5) * (1 + 1 / (2 * (Math.abs(y2 - y) + 1)));
+            c6 = c6 * (1.28 + (5 * m2 / 6) / (b[2] + 1));
+            c6 = Math.floor(c6 * (1 + 1 / o2) + 0.5);
+            // If loss > men present, rescale losses
+            e2 = 100 / o2;
+            if (Math.floor(c6 + e2) >= m6) {
+                c6 = Math.floor(13 * m6 / 20);
+                e2 = 7 * c6 / 13;
+                u2 = 1;
+            }
+        }
+        // Calculate simulated losses
+        print("\n");
+        print("\n");
+        print("\n");
+        print("\t\tCONFEDERACY\tUNION\n");
+        c5 = (2 * c1 / 5) * (1 + 1 / (2 * (Math.abs(y2 - y) + 1)));
+        c5 = Math.floor(c5 * (1 + 1 / o) * (1.28 + f1 / (ba[1] + 1)) + 0.5);
+        e = 100 / o;
+        if (c5 + 100 / o >= m1 * (1 + (p1 - t1) / (m3 + 1))) {
+            c5 = Math.floor(13 * m1 / 20 * (1 + (p1 - t1) / (m3 + 1)));
+            e = 7 * c5 / 13;
+            u = 1;
+        }
+        if (d == 1) {
+            c6 = Math.floor(17 * c2 * c1 / (c5 * 20));
+            e2 = 5 * o;
+        }
+        print("CASUALTIES\t" + c5 + "\t\t" + c6 + "\n");
+        print("DESERTIONS\t" + Math.floor(e) + "\t\t" + Math.floor(e2) + "\n");
+        print("\n");
+        if (bs == "YES") {
+            print("COMPARED TO THE ACTUAL CASUALTIES AT " + cs + "\n");
+            print("CONFEDERATE: " + Math.floor(100 * (c5 / c1) + 0.5) + "% OF THE ORIGINAL\n");
+            print("UNION:       " + Math.floor(100 * (c6 / c2) + 0.5) + "% OF THE ORIGINAL\n");
+        }
+        print("\n");
+        // 1 Who one
+        if (u == 1 && u2 == 1 || (u != 1 && u2 != 1 && c5 + e == c6 + e2)) {
+            print("BATTLE OUTCOME UNRESOLVED\n");
+            w0++;
+        } else if (u == 1 || (u != 1 && u2 != 1 && c5 + e > c6 + e2)) {
+            print("THE UNION WINS " + cs + "\n");
+            if (a != 0)
+                l++;
+        } else  {
+            print("THE CONFEDERACY WINS " + cs + "\n");
+            if (a != 0)
+                w++;
+        }
+        // Lines 2530 to 2590 from original are unreachable.
+        if (a != 0) {
+            t1 += c5 + e;
+            t2 += c6 + e2;
+            p1 += c1;
+            p2 += c2;
+            q1 += fa[1] + ha[1] + ba[1];
+            q2 += fa[2] + ha[2] + ba[2];
+            r1 += m1 * (100 - i1) / 20;
+            r2 += m2 * (100 - i2) / 20;
+            m3 += m1;
+            m4 += m2;
+            // Learn present strategy, start forgetting old ones
+            // present startegy of south gains 3*s, others lose s
+            // probability points, unless a strategy falls below 5%.
+            s = 3;
+            s0 = 0;
+            for (i = 1; i <= 4; i++) {
+                if (s[i] <= 5)
+                    continue;
+                s[i] -= 5;
+                s0 += s;
+            }
+            s[y] += s0;
+        }
+        u = 0;
+        u2 = 0;
+        print("---------------");
+        continue;
+    }
+    print("\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THE CONFEDERACY HAS WON " + w + " BATTLES AND LOST " + l + "\n");
+    if (y == 5 || (y2 != 5 && w <= l)) {
+        print("THE UNION HAS WON THE WAR\n");
+    } else {
+        print("THE CONFEDERACY HAS WON THE WAR\n");
+    }
+    print("\n");
+    if (r1) {
+        print("FOR THE " + (w + l + w0) + " BATTLES FOUGHT (EXCLUDING RERUNS)\n");
+        print(" \t \t ");
+        print("CONFEDERACY\t UNION\n");
+        print("HISTORICAL LOSSES\t" + Math.floor(p1 + 0.5) + "\t" + Math.floor(p2 + 0.5) + "\n");
+        print("SIMULATED LOSSES\t" + Math.floor(t1 + 0.5) + "\t" + Math.floor(t2 + 0.5) + "\n");
+        print("\n");
+        print("    % OF ORIGINAL\t" + Math.floor(100 * (t1 / p1) + 0.5) + "\t" + Math.floor(100 * (t2 / p2) + 0.5) + "\n");
+        if (bs != "YES") {
+            print("\n");
+            print("UNION INTELLIGENCE SUGGEST THAT THE SOUTH USED \n");
+            print("STRATEGIES 1, 2, 3, 4 IN THE FOLLOWING PERCENTAGES\n");
+            print(sa[1] + " " + sa[2] + " " + sa[3] + " " + sa[4] + "\n");
+        }
+    }
+}
+
+main();

From e5d1b730ccd258da61b8120d2d4662ed79bf15f6 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Wed, 3 Mar 2021 19:14:42 -0600
Subject: [PATCH 219/749] Corrected bug in CIVIL WAR Javascript

---
 27 Civil War/javascript/civilwar.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/27 Civil War/javascript/civilwar.js b/27 Civil War/javascript/civilwar.js
index 489e2955..c1630621 100644
--- a/27 Civil War/javascript/civilwar.js	
+++ b/27 Civil War/javascript/civilwar.js	
@@ -416,7 +416,7 @@ async function main()
             }
             // Simulated losses - North
             c6 = (2 * c2 / 5) * (1 + 1 / (2 * (Math.abs(y2 - y) + 1)));
-            c6 = c6 * (1.28 + (5 * m2 / 6) / (b[2] + 1));
+            c6 = c6 * (1.28 + (5 * m2 / 6) / (ba[2] + 1));
             c6 = Math.floor(c6 * (1 + 1 / o2) + 0.5);
             // If loss > men present, rescale losses
             e2 = 100 / o2;
@@ -483,12 +483,12 @@ async function main()
             s = 3;
             s0 = 0;
             for (i = 1; i <= 4; i++) {
-                if (s[i] <= 5)
+                if (sa[i] <= 5)
                     continue;
-                s[i] -= 5;
+                sa[i] -= 5;
                 s0 += s;
             }
-            s[y] += s0;
+            sa[y] += s0;
         }
         u = 0;
         u2 = 0;

From e58d7d6d2aef1a152f7674a7156f2c6425e5cac4 Mon Sep 17 00:00:00 2001
From: Todd Kaiser 
Date: Wed, 3 Mar 2021 20:33:26 -0700
Subject: [PATCH 220/749] Added logic to generate valid board, refactored
 generation logic and cleaned up overall structure

---
 77 Salvo/python/salvo.ipynb | 322 +++++++++++++++++++-----------------
 1 file changed, 169 insertions(+), 153 deletions(-)

diff --git a/77 Salvo/python/salvo.ipynb b/77 Salvo/python/salvo.ipynb
index d1681dfb..0c8287af 100644
--- a/77 Salvo/python/salvo.ipynb	
+++ b/77 Salvo/python/salvo.ipynb	
@@ -24,7 +24,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 225,
+   "execution_count": 715,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,15 +33,45 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 226,
+   "execution_count": 716,
    "metadata": {},
    "outputs": [],
    "source": [
-    "random.seed()\n",
-    "\n",
     "BOARD_WIDTH = 10\n",
     "BOARD_HEIGHT = 10\n",
     "\n",
+    "SHIPS = [ (\"BATTLESHIP\", 5),\n",
+    "          (\"CRUISER\", 3),\n",
+    "          (\"DESTROYER
\", 2),\n", + " (\"DESTROYER\", 2) ]\n", + " \n", + "VALID_MOVES = [[-1, 0],\n", + " [-1, 1],\n", + " [ 0, 1],\n", + " [ 1, 1],\n", + " [ 1, 0],\n", + " [ 1,-1],\n", + " [ 0,-1],\n", + " [-1,-1]]" + ] + }, + { + "cell_type": "code", + "execution_count": 717, + "metadata": {}, + "outputs": [], + "source": [ + "# random number functions\n", + "#\n", + "# seed the random number generator\n", + "random.seed()\n", + "\n", + "# random_x_y\n", + "#\n", + "# generate a valid x,y coordinate on the board\n", + "# returns: x,y\n", + "# x: integer between 1 and BOARD_HEIGHT\n", + "# y: integer between 1 and BOARD WIDTH\n", "def random_x_y():\n", " x = random.randrange(1,BOARD_WIDTH+1)\n", " y = random.randrange(1,BOARD_HEIGHT+1)\n", @@ -50,14 +80,14 @@ }, { "cell_type": "code", - "execution_count": 227, + "execution_count": 718, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "7 2\n" + "8 4\n" ] } ], @@ -68,183 +98,109 @@ }, { "cell_type": "code", - "execution_count": 228, + "execution_count": 719, "metadata": {}, "outputs": [], "source": [ - "def random_direction(valid_directions):\n", - " idx = random.randrange(len(valid_directions))\n", - " return valid_directions[idx]" - ] - }, - { - "cell_type": "code", - "execution_count": 229, - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "0\n" - ] - } - ], - "source": [ - "print(random_direction([0,1,2]))" - ] - }, - { - "cell_type": "code", - "execution_count": 230, - "metadata": {}, - "outputs": [], - "source": [ - "SHIPS = [ (\"BATTLESHIP\", 5),\n", - " (\"CRUISER\", 3),\n", - " (\"DESTROYER\", 2),\n", - " (\"DESTROYER\", 2) ]\n", + "# TODO: add an optional starting coordinate for testing\n", + "# purposes\n", + "def generate_ship_coordinates(ship):\n", + " \n", + " # randomly generate starting x,y coordinates\n", + " start_x, start_y = random_x_y()\n", "\n", - "# given a coordinate (x,y) and a ship type,\n", - "# determine which directions from the coordinate \n", - "# a ship could be placed. Directions are numbered\n", - "# starting at 0 for up, 1 for up/right, 2 for right, \n", - "# etc., clockwise from zero (12 o'clock position)\n", - "# returns a vector of direction numbers where\n", - "# a ship can be placed, starting at one end of the\n", - "# ship to its length\n", - "def get_possible_directions(x,y,ship):\n", + " # using starting coordinates and the ship type,\n", + " # generate a vector of possible directions the ship \n", + " # could be placed. directions are numbered 0-7 along\n", + " # points of the compass (N, NE, E, SE, S, SW, W, NW)\n", + " # clockwise. a vector of valid directions where the\n", + " # ship does not go off the board is determined\n", " ship_len = SHIPS[ship][1] - 1\n", " dirs = [False for x in range(8)]\n", - " dirs[0] = (x - ship_len) >=1\n", - " dirs[2] = (y + ship_len) <= BOARD_WIDTH\n", + " dirs[0] = (start_x - ship_len) >=1\n", + " dirs[2] = (start_y + ship_len) <= BOARD_WIDTH\n", " dirs[1] = dirs[0] and dirs[2]\n", - " dirs[4] = (x + ship_len) <= BOARD_HEIGHT\n", + " dirs[4] = (start_x + ship_len) <= BOARD_HEIGHT\n", " dirs[3] = dirs[2] and dirs[4]\n", - " dirs[6] = (y - ship_len) >= 1\n", + " dirs[6] = (start_y - ship_len) >= 1\n", " dirs[5] = dirs[4] and dirs[6]\n", " dirs[7] = dirs[6] and dirs[0]\n", + " directions = [p for p in range(len(dirs)) if dirs[p]]\n", "\n", - " return [x for x in range(len(dirs)) if dirs[x]]" - ] - }, - { - "cell_type": "code", - "execution_count": 231, - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Boundary Conditions\n( 5, 5): [0, 1, 2, 3, 4, 5, 6, 7]\n( 1, 1): [2, 3, 4]\n( 1,10): [4, 5, 6]\n(10,10): [0, 6, 7]\n(10, 1): [0, 1, 2]\n" - ] - } - ], - "source": [ - "print(\"Boundary Conditions\")\n", - "print(\"( 5, 5):\",get_possible_directions(5,5,0))\n", - "print(\"( 1, 1):\",get_possible_directions(1,1,0))\n", - "print(\"( 1,10):\",get_possible_directions(1,10,0))\n", - "print(\"(10,10):\",get_possible_directions(10,10,0))\n", - "print(\"(10, 1):\",get_possible_directions(10,1,0))" - ] - }, - { - "cell_type": "code", - "execution_count": 232, - "metadata": {}, - "outputs": [], - "source": [ - "VALID_MOVES = [[-1, 0],\n", - " [-1, 1],\n", - " [ 0, 1],\n", - " [ 1, 1],\n", - " [ 1, 0],\n", - " [ 1,-1],\n", - " [ 0,-1],\n", - " [-1,-1]]\n", + " # using the vector of valid directions, pick a\n", + " # random direction to place the ship\n", + " dir_idx = random.randrange(len(directions))\n", + " direction = directions[dir_idx]\n", "\n", - "\n", - "def generate_ship_coordinates(x_start,y_start,direction,ship):\n", + " # using the starting x,y, direction and ship\n", + " # type, return the coordinates of each point \n", + " # of the ship. VALID_MOVES is a staic array\n", + " # of coordinate offsets to walk from starting\n", + " # coordinate to the end coordinate in the \n", + " # chosen direction\n", " ship_len = SHIPS[ship][1] - 1\n", " d_x = VALID_MOVES[direction][0]\n", " d_y = VALID_MOVES[direction][1]\n", "\n", - " coords = [(x_start,y_start)]\n", - " x_coord = x_start\n", - " y_coord = y_start\n", + " coords = [(start_x,start_y)]\n", + " x_coord = start_x\n", + " y_coord = start_y\n", " for i in range(ship_len):\n", " x_coord = x_coord + d_x\n", " y_coord = y_coord + d_y\n", " coords.append((x_coord,y_coord))\n", - " return coords" + " return coords\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 233, + "execution_count": 720, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "('BATTLESHIP', 5) 2 2 4 [(2, 2), (3, 2), (4, 2), (5, 2), (6, 2)]\n", - "('CRUISER', 3) 6 7 3 [(6, 7), (7, 8), (8, 9)]\n", - "('DESTROYER', 2) 1 1 3 [(1, 1), (2, 2)]\n", - "('DESTROYER', 2) 8 3 6 [(8, 3), (8, 2)]\n" + "BATTLESHIP 5 [(9, 2), (8, 3), (7, 4), (6, 5), (5, 6)]\nCRUISER 3 [(3, 8), (2, 9), (1, 10)]\nDESTROYER 2 [(3, 5), (3, 6)]\nDESTROYER 2 [(6, 5), (7, 4)]\n" ] } ], "source": [ "\n", "for ship in range(len(SHIPS)):\n", - " x,y = random_x_y()\n", - " directions = get_possible_directions(x,y,ship)\n", - " direction = random_direction(directions)\n", - " coords = generate_ship_coordinates(x,y,direction,ship)\n", - " print(SHIPS[ship],x,y,direction,coords)" + " coords = generate_ship_coordinates(ship)\n", + " print(f'{SHIPS[ship][0]:15}',f'{SHIPS[ship][1]:2}',coords)" ] }, { "cell_type": "code", - "execution_count": 234, + "execution_count": 721, "metadata": {}, "outputs": [], "source": [ - "computer_board = [ [ -1 for y in range(BOARD_WIDTH)] \n", - " for x in range(BOARD_HEIGHT)]\n", - "player_board = [ [ -1 for y in range(BOARD_WIDTH)] \n", - " for x in range(BOARD_HEIGHT)]" + "def create_blank_board():\n", + " return [ [ None for y in range(BOARD_WIDTH)] \n", + " for x in range(BOARD_HEIGHT)]" ] }, { "cell_type": "code", - "execution_count": 235, + "execution_count": 722, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - " 1 2 3 4 5 6 7 8 9 10\n", - " 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 3 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 5 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 6 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 7 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - "10 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n" + " 1 2 3 4 5 6 7 8 9 10\n 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n 9 \n10 \n" ] } ], "source": [ "def print_board(board):\n", "\n", + " # print board header (column numbers)\n", " print(' ',end='')\n", " for z in range(BOARD_WIDTH):\n", " print(f'{z+1:3}',end='')\n", @@ -253,62 +209,122 @@ " for x in range(len(board)):\n", " print(f'{x+1:2}',end='')\n", " for y in range(len(board[x])):\n", - " print(f\"{board[x][y]:3}\",end='')\n", + " if(board[x][y] is None):\n", + " print(f\"{' ':3}\",end='')\n", + " else:\n", + " print(f\"{board[x][y]:3}\",end='')\n", " print('')\n", "\n", + "computer_board = create_blank_board()\n", "print_board(computer_board)" ] }, { "cell_type": "code", - "execution_count": 236, + "execution_count": 723, "metadata": {}, "outputs": [], "source": [ "def place_ship(board,coords,ship):\n", " for coord in coords:\n", - " print(\"--->\",coord)\n", - " board[coord[0]-1][coord[1]-1] = 0" + " board[coord[0]-1][coord[1]-1] = ship" ] }, { "cell_type": "code", - "execution_count": 237, + "execution_count": 724, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "[(7, 5), (6, 4), (5, 3), (4, 2), (3, 1)]\n", - "---> (7, 5)\n", - "---> (6, 4)\n", - "---> (5, 3)\n", - "---> (4, 2)\n", - "---> (3, 1)\n", + "DESTROYER 2 [(1, 7), (2, 6), (3, 5), (4, 4), (5, 3)]\n", " 1 2 3 4 5 6 7 8 9 10\n", - " 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 3 0 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 4 -1 0 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 5 -1 -1 0 -1 -1 -1 -1 -1 -1 -1\n", - " 6 -1 -1 -1 0 -1 -1 -1 -1 -1 -1\n", - " 7 -1 -1 -1 -1 0 -1 -1 -1 -1 -1\n", - " 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - " 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", - "10 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n" + " 1 0 \n", + " 2 0 \n", + " 3 0 \n", + " 4 0 \n", + " 5 0 \n", + " 6 \n", + " 7 \n", + " 8 \n", + " 9 \n", + "10 \n" ] } ], "source": [ - "x,y = random_x_y()\n", - "ship = 0\n", - "directions = get_possible_directions(x,y,ship)\n", - "direction = random_direction(directions)\n", - "coords = generate_ship_coordinates(x,y,direction,ship)\n", - "print(coords)\n", - "place_ship(computer_board,coords,0)\n", - "print_board(computer_board)" + "# test place_ship\n", + "board = create_blank_board()\n", + "coords = generate_ship_coordinates(0)\n", + "print(f'{SHIPS[ship][0]:15}',f'{SHIPS[ship][1]:2}',coords)\n", + "place_ship(board,coords,0)\n", + "print_board(board)" + ] + }, + { + "cell_type": "code", + "execution_count": 725, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + " 1 2 3 4 5 6 7 8 9 10\n 1 1 0 \n 2 1 0 \n 3 1 0 \n 4 0 \n 5 2 0 \n 6 2 \n 7 3 3 \n 8 \n 9 \n10 \n" + ] + } + ], + "source": [ + "# NOTE: A little quirk that exists here and in the orginal\n", + "# game: Ships are allowed to cross each other!\n", + "# For example: 2 destroyers, length 2, one at\n", + "# [(1,1),(2,2)] and other at [(2,1),(1,2)]\n", + "\n", + "def generate_board():\n", + " board = create_blank_board()\n", + "\n", + " for ship in range(len(SHIPS)):\n", + " placed = False\n", + " coords = []\n", + " while not placed:\n", + " coords = generate_ship_coordinates(ship)\n", + " clear = True\n", + " for coord in coords:\n", + " if board[coord[0]-1][coord[1]-1] is not None:\n", + " clear = False\n", + " break\n", + " if clear:\n", + " placed = True\n", + " place_ship(board,coords,ship)\n", + " return board\n", + "\n", + "print_board(generate_board())" + ] + }, + { + "cell_type": "code", + "execution_count": 726, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[(4, 4), (2, 8), (10, 6), (2, 4), (10, 7)]\n" + ] + } + ], + "source": [ + "def generate_shots(number):\n", + " shots = []\n", + " for i in range(number):\n", + " shots.append(random_x_y())\n", + " return shots\n", + "\n", + "shots = generate_shots(5)\n", + "print(shots)" ] }, { From c23d7e6c1b01b60af634fb58db3c0d2ab32f52bd Mon Sep 17 00:00:00 2001 From: nanochess Date: Wed, 3 Mar 2021 21:37:14 -0600 Subject: [PATCH 221/749] Ported DIGITS to Javascript --- 34 Digits/javascript/digits.html | 9 ++ 34 Digits/javascript/digits.js | 175 +++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 34 Digits/javascript/digits.html create mode 100644 34 Digits/javascript/digits.js diff --git a/34 Digits/javascript/digits.html b/34 Digits/javascript/digits.html new file mode 100644 index 00000000..c6db808f --- /dev/null +++ b/34 Digits/javascript/digits.html @@ -0,0 +1,9 @@ + + +DIGITS + + +

+
+
+
diff --git a/34 Digits/javascript/digits.js b/34 Digits/javascript/digits.js
new file mode 100644
index 00000000..8f2be6de
--- /dev/null
+++ b/34 Digits/javascript/digits.js	
@@ -0,0 +1,175 @@
+// DIGITS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "DIGITS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS IS A GAME OF GUESSING.\n");
+    print("FOR INSTRUCTIONS, TYPE '1', ELSE TYPE '0'");
+    e = parseInt(await input());
+    if (e != 0) {
+        print("\n");
+        print("PLEASE TAKE A PIECE OF PAPER AND WRITE DOWN\n");
+        print("THE DIGITS '0', '1', OR '2' THIRTY TIMES AT RANDOM.\n");
+        print("ARRANGE THEM IN THREE LINES OF TEN DIGITS EACH.\n");
+        print("I WILL ASK FOR THEN TEN AT A TIME.\n");
+        print("I WILL ALWAYS GUESS THEM FIRST AND THEN LOOK AT YOUR\n");
+        print("NEXT NUMBER TO SEE IF I WAS RIGHT. BY PURE LUCK,\n");
+        print("I OUGHT TO BE RIGHT TEN TIMES. BUT I HOPE TO DO BETTER\n");
+        print("THAN THAT *****\n");
+        print("\n");
+        print("\n");
+    }
+    a = 0;
+    b = 1;
+    c = 3;
+    m = [];
+    k = [];
+    l = [];
+    n = [];
+    while (1) {
+        for (i = 0; i <= 26; i++) {
+            m[i] = [];
+            for (j = 0; j <= 2; j++) {
+                m[i][j] = 1;
+            }
+        }
+        for (i = 0; i <= 2; i++) {
+            k[i] = [];
+            for (j = 0; j <= 2; j++) {
+                k[i][j] = 9;
+            }
+        }
+        for (i = 0; i <= 8; i++) {
+            l[i] = [];
+            for (j = 0; j <= 2; j++) {
+                l[i][j] = 3;
+            }
+        }
+        l[0][0] = 2;
+        l[4][1] = 2;
+        l[8][2] = 2;
+        z = 26;
+        z1 = 8;
+        z2 = 2;
+        x = 0;
+        for (t = 1; t <= 3; t++) {
+            while (1) {
+                print("\n");
+                print("TEN NUMBERS, PLEASE");
+                str = await input();
+                for (i = 1; i <= 10; i++) {
+                    n[i] = parseInt(str);
+                    j = str.indexOf(",");
+                    if (j >= 0) {
+                        str = str.substr(j + 1);
+                    }
+                    if (n[i] < 0 || n[i] > 2)
+                        break;
+                }
+                if (i <= 10) {
+                    print("ONLY USE THE DIGITS '0', '1', OR '2'.\n");
+                    print("LET'S TRY AGAIN.\n");
+                } else {
+                    break;
+                }
+            }
+            print("\n");
+            print("MY GUESS\tYOUR NO.\tRESULT\tNO. RIGHT\n");
+            print("\n");
+            for (u = 1; u <= 10; u++) {
+                n2 = n[u];
+                s = 0;
+                for (j = 0; j <= 2; j++) {
+                    s1 = a * k[z2][j] + b * l[z1][j] + c * m[z][j];
+                    if (s > s1)
+                        continue;
+                    if (s < s1 || Math.random() >= 0.5) {
+                        s = s1;
+                        g = j;
+                    }
+                }
+                print("  " + g + "\t\t   " + n[u] + "\t\t");
+                if (g == n[u]) {
+                    x++;
+                    print(" RIGHT\t " + x + "\n");
+                    m[z][n2]++;
+                    l[z1][n2]++;
+                    k[z2][n2]++;
+                    z = z % 9;
+                    z = 3 * z + n[u];
+                } else {
+                    print(" WRONG\t " + x + "\n");
+                }
+                z1 = z % 9;
+                z2 = n[u];
+            }
+        }
+        print("\n");
+        if (x > 10) {
+            print("I GUESSED MORE THAN 1/3 OF YOUR NUMBERS.\n");
+            print("I WIN.\n");
+        } else if (x == 10) {
+            print("I GUESSED EXACTLY 1/3 OF YOUR NUMBERS.\n");
+            print("IT'S A TIE GAME.\n");
+        } else {
+            print("I GUESSED LESS THAN 1/3 OF YOUR NUMBERS.\n");
+            print("YOU BEAT ME.  CONGRATULATIONS *****\n");
+        }
+        print("\n");
+        print("DO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO)");
+        x = parseInt(await input());
+        if (x != 1)
+            break;
+    }
+    print("\n");
+    print("THANKS FOR THE GAME.\n");
+}
+
+main();

From 8e8fbf345d5244ac3d61751741ce3d17b08e7484 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Wed, 3 Mar 2021 22:09:54 -0600
Subject: [PATCH 222/749] Ported FLIPFLOP to Javascript

---
 36 Flip Flop/javascript/flipflop.html |   9 ++
 36 Flip Flop/javascript/flipflop.js   | 144 ++++++++++++++++++++++++++
 2 files changed, 153 insertions(+)
 create mode 100644 36 Flip Flop/javascript/flipflop.html
 create mode 100644 36 Flip Flop/javascript/flipflop.js

diff --git a/36 Flip Flop/javascript/flipflop.html b/36 Flip Flop/javascript/flipflop.html
new file mode 100644
index 00000000..2de8e198
--- /dev/null
+++ b/36 Flip Flop/javascript/flipflop.html	
@@ -0,0 +1,9 @@
+
+
+FLIPFLOP
+
+
+

+
+
+
diff --git a/36 Flip Flop/javascript/flipflop.js b/36 Flip Flop/javascript/flipflop.js
new file mode 100644
index 00000000..fad83d64
--- /dev/null
+++ b/36 Flip Flop/javascript/flipflop.js	
@@ -0,0 +1,144 @@
+// FLIPFLOP
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var as = [];
+
+// Main program
+async function main()
+{
+    print(tab(32) + "FLIPFLOP\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    // *** Created by Michael Cass
+    print("THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:\n");
+    print("\n");
+    print("X X X X X X X X X X\n");
+    print("\n");
+    print("TO THIS:\n");
+    print("\n");
+    print("O O O O O O O O O O\n");
+    print("\n");
+    print("BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE\n");
+    print("LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON\n");
+    print("OTHERS, TWO WILL CHANGE.  TO RESET LINE TO ALL X'S, TYPE 0\n");
+    print("(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE \n");
+    print("11 (ELEVEN).\n");
+    print("\n");
+    while (1) {
+        start = 1;
+        do {
+            z = 1;
+            if (start == 1) {
+                m = 0;
+                q = Math.random();
+                print("HERE IS THE STARTING LINE OF X'S.\n");
+                print("\n");
+                c = 0;
+                start = 2;
+            }
+            if (start == 2) {
+                print("1 2 3 4 5 6 7 8 9 10\n");
+                print("X X X X X X X X X X\n");
+                print("\n");
+                for (x = 1; x <= 10; x++)
+                    as[x] = "X";
+                start = 0;
+            }
+            print("INPUT THE NUMBER");
+            while (1) {
+                n = parseInt(await input());
+                if (n >= 0 && n <= 11)
+                    break;
+                print("ILLEGAL ENTRY--TRY AGAIN.\n");
+            }
+            if (n == 11) {
+                start = 1;
+                continue;
+            }
+            if (n == 0) {
+                start = 2;
+                continue;
+            }
+            if (m != n) {
+                m = n;
+                as[n] = (as[n] == "O" ? "X" : "O");
+                do {
+                    r = Math.tan(q + n / q - n) - Math.sin(q / n) + 336 * Math.sin(8 * n);
+                    n = r - Math.floor(r);
+                    n = Math.floor(10 * n);
+                    as[n] = (as[n] == "O" ? "X" : "O");
+                } while (m == n) ;
+            } else {
+                as[n] = (as[n] == "O" ? "X" : "O");
+                do {
+                    r = 0.592 * (1 / Math.tan(q / n + q)) / Math.sin(n * 2 + q) - Math.cos(n);
+                    n = r - Math.floor(r);
+                    n = Math.floor(10 * n);
+                    as[n] = (as[n] == "O" ? "X" : "O");
+                } while (m == n) ;
+            }
+            print("1 2 3 4 5 6 7 8 9 10\n");
+            for (z = 1; z <= 10; z++)
+                print(as[z] + " ");
+            c++;
+            print("\n");
+            for (z = 1; z <= 10; z++) {
+                if (as[z] != "O")
+                    break;
+            }
+        } while (z <= 10) ;
+        if (c <= 12) {
+            print("VERY GOOD.  YOU GUESSED IT IN ONLY " + c + " GUESSES.\n");
+        } else {
+            print("TRY HARDER NEXT TIME.  IT TOOK YOU " + c + " GUESSES.\n");
+        }
+        print("DO YOU WANT TO TRY ANOTHER PUZZLE");
+        str = await input();
+        if (str.substr(0, 1) == "N")
+            break;
+    }
+    print("\n");
+}
+
+main();

From 8c3b20b129e1c22d4bc2fb8d5e3a522577cbb6b6 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Thu, 4 Mar 2021 15:17:20 +1030
Subject: [PATCH 223/749] Java port of Hammurabi - WIP

---
 43 Hammurabi/java/src/Hammurabi.java     | 304 +++++++++++++++++++++++
 43 Hammurabi/java/src/HammurabiGame.java |   7 +
 2 files changed, 311 insertions(+)
 create mode 100644 43 Hammurabi/java/src/Hammurabi.java
 create mode 100644 43 Hammurabi/java/src/HammurabiGame.java

diff --git a/43 Hammurabi/java/src/Hammurabi.java b/43 Hammurabi/java/src/Hammurabi.java
new file mode 100644
index 00000000..b8589062
--- /dev/null
+++ b/43 Hammurabi/java/src/Hammurabi.java	
@@ -0,0 +1,304 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Hammurabi
+ * 

+ * Based on the Basic game of Hammurabi here + * https://github.com/coding-horror/basic-computer-games/blob/main/43%20Hammurabi/hammurabi.bas + *

+ * 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 Hammurabi { + + private int year; + private int population; + private int acres; + private int bushels; + private int harvest; + private int landTradingAt; + private int cameToCity; + private int died; + private int q; + private int ratsAte; + private double peopleFed; + private double totalPlanted; + private double percentageStarved; + private int acresToPlant; + private int bushelsToFeedPeople; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + STARTUP, + INIT, + YEAR_CYCLE, + BUY_ACRES, + SELL_ACRES, + FEED_PEOPLE, + PLANT_SEED, + CALCULATE_HARVEST, + CALCULATE_BABIES, + RESULTS, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + public Hammurabi() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.STARTUP; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case STARTUP: + intro(); + gameState = GAME_STATE.INIT; + break; + + case INIT: + + // These are hard coded startup figures from the basic program + year = 0; + population = 95; + bushels = 2800; + harvest = 3000; + landTradingAt = 3; + acres = harvest / landTradingAt; + cameToCity = 5; + died = 0; + q = 1; + ratsAte = harvest - bushels; + peopleFed = 0; + totalPlanted = 0; + percentageStarved = 0; + acresToPlant = 0; + bushelsToFeedPeople = 0; + + gameState = GAME_STATE.YEAR_CYCLE; + break; + + case YEAR_CYCLE: + System.out.println(); + year += 1; + System.out.println("HAMURABI: I BEG TO REPORT TO YOU,"); + System.out.println("IN YEAR " + year + "," + died + " PEOPLE STARVED," + cameToCity + " CAME TO THE CITY,"); + population += cameToCity; + if (q == 0) { + population /= 2; + System.out.println("A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED."); + } + System.out.println("POPULATION IS NOW " + population); + System.out.println("THE CITY NOW OWNS " + acres + " ACRES."); + System.out.println("YOU HARVESTED " + landTradingAt + " BUSHELS PER ACRE."); + System.out.println("THE RATS ATE " + ratsAte + " BUSHELS."); + System.out.println("YOU NOW HAVE " + bushels + " BUSHELS IN STORE."); + System.out.println(); + + peopleFed = (int) (Math.random() * 10); + landTradingAt = (int) peopleFed + 17; + System.out.println("LAND IS TRADING AT " + landTradingAt + " BUSHELS PER ACRE."); + + gameState = GAME_STATE.BUY_ACRES; + break; + + case BUY_ACRES: + int acresToBuy = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO BUY? "); + if (acresToBuy < 0) { + gameState = GAME_STATE.GAME_OVER; + } + + if(acresToBuy >0) { + if ((landTradingAt * acresToBuy) > bushels) { + System.out.println("HAMURABI: THINK AGAIN. YOU HAVE ONLY"); + System.out.println(bushels + " BUSHELS OF GRAIN. NOW THEN,"); + } else { + if (q == 0) { + gameState = GAME_STATE.SELL_ACRES; + } else { + acres += acresToBuy; + bushels -= (landTradingAt * acresToBuy); + peopleFed = 0; + gameState = GAME_STATE.FEED_PEOPLE; + } + } + } else { + // 0 entered as buy so try to sell + gameState = GAME_STATE.SELL_ACRES; + } + break; + + case SELL_ACRES: + int acresToSell = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO SELL? "); + if (acresToSell < 0) { + gameState = GAME_STATE.GAME_OVER; + } + if (acresToSell < acres) { + acres -= acresToSell; + bushels += (landTradingAt * acresToSell); + gameState = GAME_STATE.FEED_PEOPLE; + } else { + System.out.println("HAMURABI: THINK AGAIN. YOU OWN ONLY " + acres + " ACRES. NOW THEN,"); + } + break; + + case FEED_PEOPLE: + + bushelsToFeedPeople = displayTextAndGetNumber("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE ? "); + if (bushelsToFeedPeople < 0) { + gameState = GAME_STATE.GAME_OVER; + } + + if (bushelsToFeedPeople <= bushels) { + bushels -= bushelsToFeedPeople; + peopleFed = 1; + gameState = GAME_STATE.PLANT_SEED; + } else { + System.out.println("HAMURABI: THINK AGAIN. YOU HAVE ONLY"); + System.out.println(bushels + " BUSHELS OF GRAIN. NOW THEN,"); + } + break; + + case PLANT_SEED: + + acresToPlant = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED ? "); + if (acresToPlant < 0) { + gameState = GAME_STATE.GAME_OVER; + } + + if (acresToPlant <= acres) { + if(acresToPlant/2 <= bushels) { + if(acresToPlant < 10*population) { + bushels -= acresToPlant/2; + peopleFed = (int) (Math.random()*5)+1; + landTradingAt = (int) peopleFed; + harvest = acresToPlant * landTradingAt; + ratsAte = 0; + gameState = GAME_STATE.CALCULATE_HARVEST; + } else { + System.out.println("BUT YOU HAVE ONLY " + population + " PEOPLE TO TEND THE FIELDS! NOW THEN,"); + } + } else { + System.out.println("HAMURABI: THINK AGAIN. YOU HAVE ONLY"); + System.out.println("BUSHELS OF GRAIN. NOW THEN,"); + } + } else { + System.out.println("HAMURABI: THINK AGAIN. YOU OWN ONLY " + acres + " ACRES. NOW THEN,"); + } + break; + + case CALCULATE_HARVEST: + + if( (int) (peopleFed/2) == peopleFed/2) { + // Rats are running wild + ratsAte = (int) (bushels / peopleFed); + } + bushels = bushels - ratsAte; + bushels += harvest; + gameState = GAME_STATE.CALCULATE_BABIES; + break; + + case CALCULATE_BABIES: + + cameToCity = (int) (peopleFed*(20*acres+bushels)/population/100+1); + peopleFed = (int) (bushelsToFeedPeople/20); + q = (int) ((10*(Math.random()*2)-.3)); + if(population .45*population) { + System.out.println(); + System.out.println("YOU STARVED " + (int) starved + " PEOPLE IN ONE YEAR!!!"); + System.out.println("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY"); + System.out.println("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE"); + System.out.println("ALSO BEEN DECLARED NATIONAL FINK!!!!"); + gameState = GAME_STATE.GAME_OVER; + } else { + percentageStarved = ((year-1)*percentageStarved+(double) (acresToPlant*100/population))/year; + population = (int) peopleFed; + totalPlanted += acresToPlant; + gameState = GAME_STATE.YEAR_CYCLE; + } + + break; + + + + + + + + } + + } while (gameState != GAME_STATE.GAME_OVER); + } + + private void intro() { + System.out.println(simulateTabs(33) + "KINEMA"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + } + + private boolean calculate(double playerAnswer, double correctAnswer) { + + boolean gotItRight = false; + + if (Math.abs((playerAnswer - correctAnswer) / correctAnswer) < 0.15) { + System.out.println("CLOSE ENOUGH"); + gotItRight = true; + } else { + System.out.println("NOT EVEN CLOSE"); + } + System.out.println("CORRECT ANSWER IS " + correctAnswer); + System.out.println(); + + return gotItRight; + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + +} diff --git a/43 Hammurabi/java/src/HammurabiGame.java b/43 Hammurabi/java/src/HammurabiGame.java new file mode 100644 index 00000000..1cc78a67 --- /dev/null +++ b/43 Hammurabi/java/src/HammurabiGame.java @@ -0,0 +1,7 @@ +public class HammurabiGame { + public static void main(String[] args) { + + Hammurabi hammurabi = new Hammurabi(); + hammurabi.play(); + } +} From b2d4607713c6cb90e976edb6a0a9c037c63ebc4e Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Thu, 4 Mar 2021 15:21:24 +1030 Subject: [PATCH 224/749] Port of Hamurabi to Java (WIP) --- 43 Hammurabi/java/src/HammurabiGame.java | 7 ------- .../java/src/{Hammurabi.java => Hamurabi.java} | 13 ++++++++----- 43 Hammurabi/java/src/HamurabiGame.java | 7 +++++++ 3 files changed, 15 insertions(+), 12 deletions(-) delete mode 100644 43 Hammurabi/java/src/HammurabiGame.java rename 43 Hammurabi/java/src/{Hammurabi.java => Hamurabi.java} (97%) create mode 100644 43 Hammurabi/java/src/HamurabiGame.java diff --git a/43 Hammurabi/java/src/HammurabiGame.java b/43 Hammurabi/java/src/HammurabiGame.java deleted file mode 100644 index 1cc78a67..00000000 --- a/43 Hammurabi/java/src/HammurabiGame.java +++ /dev/null @@ -1,7 +0,0 @@ -public class HammurabiGame { - public static void main(String[] args) { - - Hammurabi hammurabi = new Hammurabi(); - hammurabi.play(); - } -} diff --git a/43 Hammurabi/java/src/Hammurabi.java b/43 Hammurabi/java/src/Hamurabi.java similarity index 97% rename from 43 Hammurabi/java/src/Hammurabi.java rename to 43 Hammurabi/java/src/Hamurabi.java index b8589062..d157c489 100644 --- a/43 Hammurabi/java/src/Hammurabi.java +++ b/43 Hammurabi/java/src/Hamurabi.java @@ -2,15 +2,15 @@ import java.util.Arrays; import java.util.Scanner; /** - * Game of Hammurabi + * Game of Hamurabi *

- * Based on the Basic game of Hammurabi here + * Based on the Basic game of Hamurabi here * https://github.com/coding-horror/basic-computer-games/blob/main/43%20Hammurabi/hammurabi.bas *

* 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 Hammurabi { +public class Hamurabi { private int year; private int population; @@ -48,7 +48,7 @@ public class Hammurabi { // Current game state private GAME_STATE gameState; - public Hammurabi() { + public Hamurabi() { kbScanner = new Scanner(System.in); gameState = GAME_STATE.STARTUP; } @@ -246,9 +246,12 @@ public class Hammurabi { } private void intro() { - System.out.println(simulateTabs(33) + "KINEMA"); + System.out.println(simulateTabs(32) + "HAMURABI"); System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); System.out.println(); + System.out.println("TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA"); + System.out.println("FOR A TEN-YEAR TERM OF OFFICE."); + System.out.println(); } private boolean calculate(double playerAnswer, double correctAnswer) { diff --git a/43 Hammurabi/java/src/HamurabiGame.java b/43 Hammurabi/java/src/HamurabiGame.java new file mode 100644 index 00000000..82631e1b --- /dev/null +++ b/43 Hammurabi/java/src/HamurabiGame.java @@ -0,0 +1,7 @@ +public class HamurabiGame { + public static void main(String[] args) { + + Hamurabi hamurabi = new Hamurabi(); + hamurabi.play(); + } +} From 2f1a3e8555441e5ab61cdde780cb6766f2f61abc Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Wed, 3 Mar 2021 22:37:43 -0800 Subject: [PATCH 225/749] update port CHECKERS to python Moved a lot of methods into the board class, documented the logic for the board evaluation heuristics. Documented some known issues with the original BASIC source code. I've noticed that the computer has resigned to me when it has legal, if bad, moves. A bug in my code? A bug in the BASIC code? Still need to investigate further. --- 23 Checkers/README.md | 8 + 23 Checkers/python/checkers.py | 518 ++++++++++++++++++--------------- 2 files changed, 286 insertions(+), 240 deletions(-) diff --git a/23 Checkers/README.md b/23 Checkers/README.md index 178b7957..05681815 100644 --- a/23 Checkers/README.md +++ b/23 Checkers/README.md @@ -5,3 +5,11 @@ https://www.atariarchives.org/basicgames/showpage.php?page=40 Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html + + +## Known Issues In the Original BASIC Code + - If the computer moves a checker to the bottom row, it promotes, but + leaves the original checker in place. (See line 1240) + - Human players may move non-kings as if they were kings. (See lines 1590 to 1810) + - Curious writing to "I" variable without ever reading it. (See lines 1700 and 1806) + \ No newline at end of file diff --git a/23 Checkers/python/checkers.py b/23 Checkers/python/checkers.py index 3a1d1236..adec5a64 100644 --- a/23 Checkers/python/checkers.py +++ b/23 Checkers/python/checkers.py @@ -6,6 +6,7 @@ How about a nice game of checkers? Ported by Dave LeCompte """ +import collections PAGE_WIDTH = 64 @@ -17,7 +18,12 @@ COMPUTER_PIECE = -1 COMPUTER_KING = -2 EMPTY_SPACE = 0 -INVALID_MOVE = -99 +TOP_ROW = 7 +BOTTOM_ROW = 0 + +MoveRecord = collections.namedtuple( + "MoveRecord", ["quality", "start_x", "start_y", "dest_x", "dest_y"] +) def print_centered(msg): @@ -33,6 +39,28 @@ def print_header(title): print() +def get_coordinates(prompt): + err_msg = "ENTER COORDINATES in X,Y FORMAT" + while True: + print(prompt) + response = input() + if "," not in response: + print(err_msg) + continue + + try: + x, y = [int(c) for c in response.split(",")] + except ValueError as ve: + print(err_msg) + continue + + return x, y + + +def is_legal_board_coordinate(x, y): + return (0 <= x <= 7) and (0 <= y <= 7) + + class Board: def __init__(self): self.spaces = [[0 for y in range(8)] for x in range(8)] @@ -66,6 +94,245 @@ class Board: return s + def get_spaces(self): + for x in range(0, 8): + for y in range(0, 8): + yield x, y + + def get_spaces_with_computer_pieces(self): + for x, y in self.get_spaces(): + contents = self.spaces[x][y] + if contents < 0: + yield x, y + + def get_spaces_with_human_pieces(self): + for x, y in self.get_spaces(): + contents = self.spaces[x][y] + if contents > 0: + yield x, y + + def get_legal_deltas_for_space(self, x, y): + contents = self.spaces[x][y] + if contents == COMPUTER_PIECE: + for delta_x in (-1, 1): + yield (delta_x, -1) + else: + for delta_x in (-1, 1): + for delta_y in (-1, 1): + yield (delta_x, delta_y) + + def pick_computer_move(self): + move_record = None + + for start_x, start_y in self.get_spaces_with_computer_pieces(): + for delta_x, delta_y in self.get_legal_deltas_for_space(start_x, start_y): + new_move_record = self.check_move(start_x, start_y, delta_x, delta_y) + + if new_move_record is None: + continue + + if (move_record is None) or (new_move_record.quality > move_record.quality): + move_record = new_move_record + + return move_record + + def check_move(self, start_x, start_y, delta_x, delta_y): + new_x = start_x + delta_x + new_y = start_y + delta_y + if not is_legal_board_coordinate(new_x, new_y): + return None + + contents = self.spaces[new_x][new_y] + if contents == EMPTY_SPACE: + return self.evaluate_move(start_x, start_y, new_x, new_y) + if contents < 0: + return None + + # check jump landing space, which is an additional dx, dy from new_x, newy + landing_x = new_x + delta_x + landing_y = new_y + delta_y + + if not is_legal_board_coordinate(landing_x, landing_y): + return None + if self.spaces[landing_x][landing_y] == EMPTY_SPACE: + return self.evaluate_move(start_x, start_y, landing_x, landing_y) + + def evaluate_move(self, start_x, start_y, dest_x, dest_y): + quality = 0 + if dest_y == 0 and self.spaces[start_x][start_y] == COMPUTER_PIECE: + # promoting is good + quality += 2 + if abs(dest_y - start_y) == 2: + # jumps are good + quality += 5 + if start_y == 7: + # prefer to defend back row + quality -= 2 + if dest_x in (0, 7): + # moving to edge column + quality += 1 + for delta_x in (-1, 1): + if not is_legal_board_coordinate(dest_x + delta_x, dest_y - 1): + continue + + if self.spaces[dest_x + delta_x][dest_y - 1] < 0: + # moving into "shadow" of another computer piece + quality += 1 + + if not is_legal_board_coordinate(dest_x - delta_x, dest_y + 1): + continue + + if ( + (self.spaces[dest_x + delta_x][dest_y - 1] > 0) + and (self.spaces[dest_x - delta_x][dest_y + 1] == EMPTY_SPACE) + or ((dest_x - delta_x == start_x) and (dest_y + 1 == start_y)) + ): + # we are moving up to a human checker that could jump us + quality -= 2 + return MoveRecord(quality, start_x, start_y, dest_x, dest_y) + + def remove_r_pieces(self, move_record): + self.remove_pieces( + move_record.start_x, + move_record.start_y, + move_record.dest_x, + move_record.dest_y, + ) + + def remove_pieces(self, start_x, start_y, dest_x, dest_y): + self.spaces[dest_x][dest_y] = self.spaces[start_x][start_y] + self.spaces[start_x][start_y] = EMPTY_SPACE + + if abs(dest_x - start_x) == 2: + mid_x = (start_x + dest_x) // 2 + mid_y = (start_y + dest_y) // 2 + self.spaces[mid_x][mid_y] = EMPTY_SPACE + + def play_computer_move(self, move_record): + print( + f"FROM {move_record.start_x} {move_record.start_y} TO {move_record.dest_x} {move_record.dest_y}" + ) + + while True: + if move_record.dest_y == BOTTOM_ROW: + # KING ME + self.remove_r_pieces(move_record) + self.spaces[move_record.dest_x][move_record.dest_y] = COMPUTER_KING + return + else: + self.spaces[move_record.dest_x][move_record.dest_y] = self.spaces[ + move_record.start_x + ][move_record.start_y] + self.remove_r_pieces(move_record) + + if abs(move_record.dest_x - move_record.start_x) != 2: + return + + landing_x = move_record.dest_x + landing_y = move_record.dest_y + + best_move = None + if self.spaces[landing_x][landing_y] == COMPUTER_PIECE: + for delta_x in (-2, 2): + test_record = self.try_extend(landing_x, landing_y, delta_x, -2) + if not (move_record is None): + if (best_move is None) or ( + move_record.quality > best_move.quality + ): + best_move = test_record + else: + assert self.spaces[landing_x][landing_y] == COMPUTER_KING + for delta_x in (-2, 2): + for delta_y in (-2, 2): + test_record = self.try_extend( + landing_x, landing_y, delta_x, delta_y + ) + if not (move_record is None): + if (best_move is None) or ( + move_record.quality > best_move.quality + ): + best_move = test_record + + if best_move is None: + return + else: + print(f"TO {best_move.dest_x} {best_move.dest_y}") + move_record = best_move + + def try_extend(self, start_x, start_y, delta_x, delta_y): + new_x = start_x + delta_x + new_y = start_y + delta_y + + if not is_legal_board_coordinate(new_x, new_y): + return None + + jumped_x = start_x + delta_x // 2 + jumped_y = start_y + delta_y // 2 + + if (self.spaces[new_x][new_y] == EMPTY_SPACE) and ( + self.spaces[jumped_x][jumped_y] > 0 + ): + return self.evaluate_move(start_x, start_y, new_x, new_y) + + def get_human_move(self): + is_king = False + + while True: + start_x, start_y = get_coordinates("FROM?") + + if self.spaces[start_x][start_y] > 0: + break + + is_king = self.spaces[start_x][start_y] == HUMAN_KING + + while True: + dest_x, dest_y = get_coordinates("TO?") + + if (not is_king) and (dest_y < start_y): + # CHEATER! Trying to move non-king backwards + continue + if ( + (self.spaces[dest_x][dest_y] == 0) + and (abs(dest_x - start_x) <= 2) + and (abs(dest_x - start_x) == abs(dest_y - start_y)) + ): + break + return start_x, start_y, dest_x, dest_y + + def get_human_extension(self, start_x, start_y): + is_king = self.spaces[start_x][start_y] == HUMAN_KING + + while True: + dest_x, dest_y = get_coordinates("+TO?") + + if dest_x < 0: + return False, None + if (not is_king) and (dest_y < start_y): + # CHEATER! Trying to move non-king backwards + continue + if ( + (self.spaces[dest_x][dest_y] == EMPTY_SPACE) + and (abs(dest_x - start_x) == 2) + and (abs(dest_y - start_y) == 2) + ): + return True, (start_x, start_y, dest_x, dest_y) + + def play_human_move(self, start_x, start_y, dest_x, dest_y): + self.remove_pieces(start_x, start_y, dest_x, dest_y) + + if dest_y == TOP_ROW: + # KING ME + self.spaces[dest_x][dest_y] = HUMAN_KING + + def check_pieces(self): + if len(list(self.get_spaces_with_computer_pieces())) == 0: + print_human_won() + return False + if len(list(self.get_spaces_with_computer_pieces())) == 0: + print_computer_won() + return False + return True + def print_instructions(): print("THIS IS THE GAME OF CHECKERS. THE COMPUTER IS X,") @@ -82,225 +349,6 @@ def print_instructions(): print() -def get_spaces(): - for x in range(0, 8): - for y in range(0, 8): - yield x, y - - -def get_spaces_with_computer_pieces(board): - for x, y in get_spaces(): - contents = board.spaces[x][y] - if contents < 0: - yield x, y - - -def get_spaces_with_human_pieces(board): - for x, y in get_spaces(): - contents = board.spaces[x][y] - if contents > 0: - yield x, y - - -def pick_computer_move(board): - r = [INVALID_MOVE] * 5 - for x, y in get_spaces_with_computer_pieces(board): - contents = board.spaces[x][y] - if contents == COMPUTER_PIECE: - for dx in (-1, 1): - dy = -1 - sub_650(board, x, y, dx, dy, r) - else: - for dx in (-1, 1): - for dy in (-1, 1): - sub_650(board, x, y, dx, dy, r) - - if r[0] != INVALID_MOVE: - dx = r[3] - r[1] - dy = r[4] - r[2] - if abs(dx) != abs(dy): - print(r) - assert abs(dx) == abs(dy) - return r - - -def sub_650(board, x, y, dx, dy, r): - new_x = x + dx - new_y = y + dy - if not ((0 <= new_x <= 7) and (0 <= new_y <= 7)): - return - - contents = board.spaces[new_x][new_y] - if contents == 0: - sub_910(board, x, y, new_x, new_y, r) - return - if contents < 0: - return - - # check landing space - landing_x = new_x + dx - landing_y = new_y + dy - - # line 790 - if not ((0 <= landing_x <= 7) and (0 <= landing_y <= 7)): - return - if board.spaces[landing_x][landing_y] == 0: - sub_910(board, x, y, landing_x, landing_y, r) - - -def sub_910(board, start_x, start_y, dest_x, dest_y, r): - q = 0 - if dest_y == 0 and board.spaces[start_x][start_y] == COMPUTER_PIECE: - q += 2 - if abs(start_y - dest_y) == 2: - q += 5 - if start_y == 7: - q -= 2 - if dest_x in (0, 7): - q += 1 - for c in (-1, 1): - if (0 <= dest_x + c <= 7) and (1 <= dest_y): - # line 1035 - if board.spaces[dest_x + c][dest_y - 1] < 0: - q += 1 - # line 1040 - elif (0 <= dest_x - c <= 7) and (dest_y + 1 <= 7): - # line 1045 - if ( - (board.spaces[dest_x + c][dest_y - 1] > 0) - and (board.spaces[dest_x - c][dest_y + 1] == EMPTY_SPACE) - or ((dest_x - c == start_x) and (dest_y + 1 == start_y)) - ): - q -= 2 - # line 1080 - - if q > r[0]: - r[0] = q - r[1] = start_x - r[2] = start_y - r[3] = dest_x - r[4] = dest_y - - -def remove_r_pieces(board, r): - remove_pieces(board, r[1], r[2], r[3], r[4]) - - -def remove_pieces(board, start_x, start_y, dest_x, dest_y): - board.spaces[dest_x][dest_y] = board.spaces[start_x][start_y] - board.spaces[start_x][start_y] = EMPTY_SPACE - - if abs(dest_x - start_x) == 2: - mid_x = (start_x + dest_x) // 2 - mid_y = (start_y + dest_y) // 2 - board.spaces[mid_x][mid_y] = EMPTY_SPACE - - -def play_computer_move(board, r): - print(f"FROM {r[1]} {r[2]} TO {r[3]} {r[4]}") - - while True: - if r[4] == 0: - # KING ME - board.spaces[r[3]][r[4]] = COMPUTER_KING - remove_r_pieces(board, r) - return - else: - # line 1250 - board.spaces[r[3]][r[4]] = board.spaces[r[1]][r[2]] - remove_r_pieces(board, r) - - if abs(r[1] - r[3]) != 2: - return - - # line 1340 - x = r[3] - y = r[4] - r[0] = INVALID_MOVE - if board.spaces[x][y] == COMPUTER_PIECE: - for a in (-2, 2): - try_extend(board, r, x, y, a, -2) - else: - assert board.spaces[x][y] == COMPUTER_KING - for a in (-2, 2): - for b in (-2, 2): - try_extend(board, r, x, y, a, b) - if r[0] != INVALID_MOVE: - print(f"TO {r[3]} {r[4]}") - else: - return - - -def try_extend(board, r, x, y, a, b): - # line 1370 - nx = x + a - ny = y + b - if not ((0 <= nx <= 7) and (0 <= ny <= 7)): - return - if (board.spaces[nx][ny] == EMPTY_SPACE) and ( - board.spaces[nx + a // 2][ny + b // 2] > 0 - ): - sub_910(board, x, y, nx, ny, r) - - -def get_human_move(board): - is_king = False - - while True: - print("FROM?") - from_response = input() - x, y = [int(c) for c in from_response.split(",")] - - if board.spaces[x][y] > 0: - break - - is_king = board.spaces[x][y] == HUMAN_KING - - while True: - print("TO?") - to_response = input() - a, b = [int(c) for c in to_response.split(",")] - - if (not is_king) and (b < y): - # CHEATER! Trying to move non-king backwards - continue - if ( - (board.spaces[a][b] == 0) - and (abs(a - x) <= 2) - and (abs(a - x) == abs(b - y)) - ): - break - return x, y, a, b - - -def get_human_extension(board, sx, sy): - is_king = board.spaces[sx][sy] == HUMAN_KING - - while True: - print("+TO?") - to_response = input() - a1, b1 = [int(c) for c in to_response.split(",")] - if a1 < 0: - return False, None - if (not is_king) and (b1 < sy): - # CHEATER! Trying to move non-king backwards - continue - if ( - (board.spaces[a1][b1] == EMPTY_SPACE) - and (abs(a1 - sx) == 2) - and (abs(b1 - sy) == 2) - ): - return True, (sx, sy, a1, b1) - - -def play_human_move(board, start_x, start_y, dest_x, dest_y): - remove_pieces(board, start_x, start_y, dest_x, dest_y) - - if dest_y == 7: - # KING ME - board.spaces[dest_x][dest_y] = HUMAN_KING - - def print_human_won(): print() print("YOU WIN.") @@ -311,40 +359,30 @@ def print_computer_won(): print("I WIN.") -def check_pieces(board): - if len(list(get_spaces_with_computer_pieces(board))) == 0: - print_human_won() - return False - if len(list(get_spaces_with_computer_pieces(board))) == 0: - print_computer_won() - return False - return True - - def play_game(): board = Board() while True: - r = pick_computer_move(board) - if r[0] == INVALID_MOVE: + move_record = board.pick_computer_move() + if move_record is None: print_human_won() return - play_computer_move(board, r) + board.play_computer_move(move_record) print(board) - if not check_pieces(board): + if not board.check_pieces(): return - sx, sy, dx, dy = get_human_move(board) - play_human_move(board, sx, sy, dx, dy) - if abs(dx - sx) == 2: + start_x, start_y, dest_x, dest_y = board.get_human_move() + board.play_human_move(start_x, start_y, dest_x, dest_y) + if abs(dest_x - start_x) == 2: while True: - extend, move = get_human_extension(board, dx, dy) + extend, move = board.get_human_extension(dest_x, dest_y) if not extend: break - sx, sy, dx, dy = move - play_human_move(board, sx, sy, dx, dy) + start_x, start_y, dest_x, dest_y = move + board.play_human_move(start_x, start_y, dest_x, dest_y) def main(): From a62fbc49ad05a0f0ae784196cc80336b5de2e0f0 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Wed, 3 Mar 2021 22:49:52 -0800 Subject: [PATCH 226/749] update CHECKERS for python found an indentation error, played game to completion. --- 23 Checkers/python/checkers.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/23 Checkers/python/checkers.py b/23 Checkers/python/checkers.py index adec5a64..fc1008ae 100644 --- a/23 Checkers/python/checkers.py +++ b/23 Checkers/python/checkers.py @@ -128,11 +128,13 @@ class Board: for delta_x, delta_y in self.get_legal_deltas_for_space(start_x, start_y): new_move_record = self.check_move(start_x, start_y, delta_x, delta_y) - if new_move_record is None: - continue + if new_move_record is None: + continue - if (move_record is None) or (new_move_record.quality > move_record.quality): - move_record = new_move_record + if (move_record is None) or ( + new_move_record.quality > move_record.quality + ): + move_record = new_move_record return move_record From 2572b512a69842a490d5ba3039c20daf423b8115 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Thu, 4 Mar 2021 09:41:04 -0800 Subject: [PATCH 227/749] port SYNONYM to Python maintained the effect of the original logic without all the crazy array manipulations. --- 85 Synonym/README.md | 10 ++++ 85 Synonym/python/synonym.py | 100 +++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 85 Synonym/python/synonym.py diff --git a/85 Synonym/README.md b/85 Synonym/README.md index 4f723858..b9a5b79f 100644 --- a/85 Synonym/README.md +++ b/85 Synonym/README.md @@ -5,3 +5,13 @@ https://www.atariarchives.org/basicgames/showpage.php?page=164 Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html + + +## Known Issues + + - Each time the player asks for HELP, one of the synonyms is shown + and discarded. There is no protection against the player using up + all of the help. + + - The player can ask for HELP and then submit that answer. Is it + meant to be a clue, or just giving a correct answer to the player? \ No newline at end of file diff --git a/85 Synonym/python/synonym.py b/85 Synonym/python/synonym.py new file mode 100644 index 00000000..02ac24e6 --- /dev/null +++ b/85 Synonym/python/synonym.py @@ -0,0 +1,100 @@ +""" +SYNONYM + +Vocabulary quiz + +Ported by Dave LeCompte +""" + +import random + + +PAGE_WIDTH = 64 + + +def print_centered(msg): + spaces = " " * ((PAGE_WIDTH - len(msg)) // 2) + print(spaces + msg) + + +def print_header(title): + print_centered(title) + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + +def print_instructions(): + print("A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH") + print("LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME MEANING.") + print("I CHOOSE A WORD -- YOU TYPE A SYNONYM.") + print("IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP'") + print("AND I WILL TELL YOU A SYNONYM.") + print() + + +right_words = ["RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"] + +synonym_words = [ + ["FIRST", "START", "BEGINNING", "ONSET", "INITIAL"], + ["SIMILAR", "ALIKE", "SAME", "LIKE", "RESEMBLING"], + ["MODEL", "PATTERN", "PROTOTYPE", "STANDARD", "CRITERION"], + ["SMALL", "INSIGNIFICANT", "LITTLE", "TINY", "MINUTE"], + ["STOP", "HALT", "STAY", "ARREST", "CHECK", "STANDSTILL"], + ["HOUSE", "DWELLING", "RESIDENCE", "DOMICILE", "LODGING", "HABITATION"], + ["PIT", "HOLE", "HOLLOW", "WELL", "GULF", "CHASM", "ABYSS"], + ["PUSH", "SHOVE", "THRUST", "PROD", "POKE", "BUTT", "PRESS"], + ["RED", "ROUGE", "SCARLET", "CRIMSON", "FLAME", "RUBY"], + ["PAIN", "SUFFERING", "HURT", "MISERY", "DISTRESS", "ACHE", "DISCOMFORT"], +] + + +def print_right(): + print(random.choice(right_words)) + + +def ask_question(question_number): + words = synonym_words[question_number] + clues = words[:] + base_word = clues.pop(0) + + while True: + question = f" WHAT IS A SYNONYM OF {base_word}? " + response = input(question).upper() + + if response == "HELP": + clue = random.choice(clues) + print(f"**** A SYNONYM OF {base_word} IS {clue}.") + print() + + # remove the clue from available clues + clues.remove(clue) + continue + + if (response != base_word) and (response in words): + print_right() + return + + +def finish(): + print() + print("SYNONYM DRILL COMPLETED.") + + +def main(): + print_header("SYNONYM") + print_instructions() + + num_questions = len(synonym_words) + word_indices = list(range(num_questions)) + random.shuffle(word_indices) + + for word_number in word_indices: + ask_question(word_number) + + finish() + + +if __name__ == "__main__": + main() From d7348f5dfa3aac7c54e2476e36d784feeaf66c2a Mon Sep 17 00:00:00 2001 From: Qursch Date: Thu, 4 Mar 2021 15:26:28 -0500 Subject: [PATCH 228/749] Initial commit --- 82 Stars/javascript/stars.html | 9 ++++ 82 Stars/javascript/stars.js | 96 ++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 82 Stars/javascript/stars.html create mode 100644 82 Stars/javascript/stars.js diff --git a/82 Stars/javascript/stars.html b/82 Stars/javascript/stars.html new file mode 100644 index 00000000..c63aeb0d --- /dev/null +++ b/82 Stars/javascript/stars.html @@ -0,0 +1,9 @@ + + +STARS + + +


+
+
+
diff --git a/82 Stars/javascript/stars.js b/82 Stars/javascript/stars.js
new file mode 100644
index 00000000..d558e86f
--- /dev/null
+++ b/82 Stars/javascript/stars.js	
@@ -0,0 +1,96 @@
+// STARS
+//
+// Converted from BASIC to Javascript by Qursch
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var guesses = 7;
+var limit = 100;
+
+// Main program
+async function main()
+{
+    print(tab(33) + "STARS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n\n\n");
+
+    print("DO YOU WANT INSTRUCTIONS? (Y/N)");
+    var instructions = await input();
+    if(instructions.toLowerCase()[0] == "y") {
+        print(`I AM THINKING OF A WHOLE NUMBER FROM 1 TO ${limit}\n`);
+        print("TRY TO GUESS MY NUMBER.  AFTER YOU GUESS, I\n");
+        print("WILL TYPE ONE OR MORE STARS (*).  THE MORE\n");
+        print("STARS I TYPE, THE CLOSER YOU ARE TO MY NUMBER.\n");
+        print("ONE STAR (*) MEANS FAR AWAY, SEVEN STARS (*******)\n");
+        print(`MEANS REALLY CLOSE!  YOU GET ${guesses} GUESSES.\n\n\n`);
+    }
+    while (true) {
+        var randomNum = Math.floor(Math.random() * 150) + 1;
+        console.log(randomNum);
+
+        print("OK, I AM THINKING OF A NUMBER, START GUESSING.\n\n");
+
+        var loss = true;
+
+        for(var guessNum=1; guessNum <= guesses; guessNum++) {
+            print("YOUR GUESS");
+
+            var guess = parseInt(await input());
+
+            if(guess == randomNum) {
+                loss = false;
+                print("*".repeat(79) + "!!!\n");
+                print(`YOU GOT IT IN ${guessNum} GUESSES!!! LET'S PLAY AGAIN...\n\n`);
+                break;
+            }
+
+            var dist = Math.abs(guess - randomNum);
+              
+            //IMPLEMENT CHECK HERE
+        }
+
+        if(loss) {
+            print(`SORRY, THAT'S ${guesses} GUESSES. THE NUMBER WAS ${randomNum}\n\n`);
+        }
+    }
+}
+
+main();

From 60938ebc783c16d791265e79a74354e441a1f409 Mon Sep 17 00:00:00 2001
From: Charles Gersh 
Date: Thu, 4 Mar 2021 17:03:20 -0500
Subject: [PATCH 229/749] Finished Stars

---
 82 Stars/javascript/stars.js | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/82 Stars/javascript/stars.js b/82 Stars/javascript/stars.js
index d558e86f..5ffdd761 100644
--- a/82 Stars/javascript/stars.js	
+++ b/82 Stars/javascript/stars.js	
@@ -52,6 +52,7 @@ async function main()
     print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
     print("\n\n\n");
 
+    // Instructions
     print("DO YOU WANT INSTRUCTIONS? (Y/N)");
     var instructions = await input();
     if(instructions.toLowerCase()[0] == "y") {
@@ -62,35 +63,46 @@ async function main()
         print("ONE STAR (*) MEANS FAR AWAY, SEVEN STARS (*******)\n");
         print(`MEANS REALLY CLOSE!  YOU GET ${guesses} GUESSES.\n\n\n`);
     }
+
+    // Game loop
     while (true) {
-        var randomNum = Math.floor(Math.random() * 150) + 1;
-        console.log(randomNum);
-
-        print("OK, I AM THINKING OF A NUMBER, START GUESSING.\n\n");
 
+        var randomNum = Math.floor(Math.random() * limit) + 1;
         var loss = true;
 
+        print("\nOK, I AM THINKING OF A NUMBER, START GUESSING.\n\n");
+        
         for(var guessNum=1; guessNum <= guesses; guessNum++) {
-            print("YOUR GUESS");
 
+            // Input guess
+            print("YOUR GUESS");
             var guess = parseInt(await input());
 
+            // Check if guess is correct
             if(guess == randomNum) {
                 loss = false;
-                print("*".repeat(79) + "!!!\n");
-                print(`YOU GOT IT IN ${guessNum} GUESSES!!! LET'S PLAY AGAIN...\n\n`);
+                print("\n\n" + "*".repeat(50) + "!!!\n");
+                print(`YOU GOT IT IN ${guessNum} GUESSES!!! LET'S PLAY AGAIN...\n`);
                 break;
             }
 
+            // Output distance in stars
             var dist = Math.abs(guess - randomNum);
-              
-            //IMPLEMENT CHECK HERE
+            if(isNaN(dist)) print("*");
+            else if(dist >= 64) print("*");
+            else if(dist >= 32) print("**");
+            else if(dist >= 16) print("***");
+            else if(dist >= 8) print("****");
+            else if(dist >= 4) print("*****");
+            else if(dist >= 2) print("******");
+            else print("*******")
+            print("\n\n")
         }
 
         if(loss) {
-            print(`SORRY, THAT'S ${guesses} GUESSES. THE NUMBER WAS ${randomNum}\n\n`);
+            print(`SORRY, THAT'S ${guesses} GUESSES. THE NUMBER WAS ${randomNum}\n`);
         }
     }
 }
 
-main();
+main();
\ No newline at end of file

From 5a624c5dc2c1fcc4680fba1ab77b79dcac4871fe Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Thu, 4 Mar 2021 20:37:48 -0600
Subject: [PATCH 230/749] Ported FUR TRADER to Javascript

---
 38 Fur Trader/javascript/furtrader.html |   9 +
 38 Fur Trader/javascript/furtrader.js   | 227 ++++++++++++++++++++++++
 2 files changed, 236 insertions(+)
 create mode 100644 38 Fur Trader/javascript/furtrader.html
 create mode 100644 38 Fur Trader/javascript/furtrader.js

diff --git a/38 Fur Trader/javascript/furtrader.html b/38 Fur Trader/javascript/furtrader.html
new file mode 100644
index 00000000..c7695a09
--- /dev/null
+++ b/38 Fur Trader/javascript/furtrader.html	
@@ -0,0 +1,9 @@
+
+
+FUR TRADER
+
+
+

+
+
+
diff --git a/38 Fur Trader/javascript/furtrader.js b/38 Fur Trader/javascript/furtrader.js
new file mode 100644
index 00000000..c27ab049
--- /dev/null
+++ b/38 Fur Trader/javascript/furtrader.js	
@@ -0,0 +1,227 @@
+// FUR TRADER
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var f = [];
+var bs = [, "MINK", "BEAVER", "ERMINE", "FOX"];
+
+function reset_stats()
+{
+    for (var j = 1; j <= 4; j++)
+        f[j] = 0;
+}
+
+// Main program
+async function main()
+{
+    print(tab(31) + "FUR TRADER\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    first_time = true;
+    while (1) {
+        if (first_time) {
+            print("YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN \n");
+            print("1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET\n");
+            print("SUPPLIES FOR THE NEXT YEAR.  YOU HAVE A CHOICE OF THREE\n");
+            print("FORTS AT WHICH YOU MAY TRADE.  THE COST OF SUPPLIES\n");
+            print("AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND\n");
+            print("ON THE FORT THAT YOU CHOOSE.\n");
+            i = 600;
+            print("DO YOU WISH TO TRADE FURS?\n");
+            first_time = false;
+        }
+        print("ANSWER YES OR NO\t");
+        str = await input();
+        if (str == "NO")
+            break;
+        print("\n");
+        print("YOU HAVE $" + i + " SAVINGS.\n");
+        print("AND 190 FURS TO BEGIN THE EXPEDITION.\n");
+        e1 = Math.floor((0.15 * Math.random() + 0.95) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+        b1 = Math.floor((0.25 * Math.random() + 1.00) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+        print("\n");
+        print("YOUR 190 FURS ARE DISTRIBUTED AMONG THE FOLLOWING\n");
+        print("KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX.\n");
+        reset_stats();
+        for (j = 1; j <= 4; j++) {
+            print("\n");
+            print("HOW MANY " + bs[j] + " PELTS DO YOU HAVE\n");
+            f[j] = parseInt(await input());
+            f[0] = f[1] + f[2] + f[3] + f[4];
+            if (f[0] == 190)
+                break;
+            if (f[0] > 190) {
+                print("\n");
+                print("YOU MAY NOT HAVE THAT MANY FURS.\n");
+                print("DO NOT TRY TO CHEAT.  I CAN ADD.\n");
+                print("YOU MUST START AGAIN.\n");
+                break;
+            }
+        }
+        if (f[0] > 190) {
+            first_time = true;
+            continue;
+        }
+        print("YOU MAY TRADE YOUR FURS AT FORT 1, FORT 2,\n");
+        print("OR FORT 3.  FORT 1 IS FORT HOCHELAGA (MONTREAL)\n");
+        print("AND IS UNDER THE PROTECTION OF THE FRENCH ARMY.\n");
+        print("FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE\n");
+        print("PROTECTION OF THE FRENCH ARMY.  HOWEVER, YOU MUST\n");
+        print("MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS.\n");
+        print("FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL.\n");
+        print("YOU MUST CROSS THROUGH IROQUOIS LAND.\n");
+        do {
+            print("ANSWER 1, 2, OR 3.\n");
+            b = parseInt(await input());
+            if (b == 1) {
+                print("YOU HAVE CHOSEN THE EASIEST ROUTE.  HOWEVER, THE FORT\n");
+                print("IS FAR FROM ANY SEAPORT.  THE VALUE\n");
+                print("YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST\n");
+                print("OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK.\n");
+            } else if (b == 2) {
+                print("YOU HAVE CHOSEN A HARD ROUTE.  IT IS, IN COMPARSION,\n");
+                print("HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN\n");
+                print("THE ROUTE TO NEW YORK.  YOU WILL RECEIVE AN AVERAGE VALUE\n");
+                print("FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE.\n");
+            } else {
+                print("YOU HAVE CHOSEN THE MOST DIFFICULT ROUTE.  AT\n");
+                print("FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE\n");
+                print("FOR YOUR FURS.  THE COST OF YOUR SUPPLIES\n");
+                print("WILL BE LOWER THAN AT ALL THE OTHER FORTS.\n");
+            }
+            if (b >= 1 && b <= 3) {
+                print("DO YOU WANT TO TRADE AT ANOTHER FORT?\n");
+                print("ANSWER YES OR NO\t");
+                str = await input();
+                if (str == "YES") {
+                    b = 0;
+                }
+            }
+        } while (b < 1 || b > 3) ;
+        show_beaver = true;
+        show_all = true;
+        if (b == 1) {
+            i -= 160;
+            print("\n");
+            m1 = Math.floor((0.2 * Math.random() + 0.7) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            e1 = Math.floor((0.2 * Math.random() + 0.65) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            b1 = Math.floor((0.2 * Math.random() + 0.75) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            d1 = Math.floor((0.2 * Math.random() + 0.8) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            print("SUPPLIES AT FORT HOCHELAGA COST $150.00.\n");
+            print("YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00.\n");
+        } else if (b == 2) {
+            i -= 140;
+            print("\n");
+            m1 = Math.floor((0.3 * Math.random() + 0.85) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            e1 = Math.floor((0.15 * Math.random() + 0.8) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            b1 = Math.floor((0.2 * Math.random() + 0.9) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            p = Math.floor(10 * Math.random()) + 1;
+            if (p <= 2) {
+                f[2] = 0;
+                print("YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS\n");
+                print("THE PORTAGE.  YOU HAD TO LEAVE THE PELTS, BUT FOUND\n");
+                print("THEM STOLEN WHEN YOU RETURNED.\n");
+                show_beaver = false;
+            } else if (p <= 6) {
+                print("YOU ARRIVED SAFELY AT FORT STADACONA.\n");
+            } else if (p <= 8) {
+                reset_stats();
+                print("YOUR CANOE UPSET IN THE LACHINE RAPIDS.  YOU\n");
+                print("LOST ALL YOUR FURS.\n");
+                show_all = false;
+            } else if (p <= 10) {
+                f[4] = 0;
+                print("YOUR FOX PELTS WERE NOT CURED PROPERLY.\n");
+                print("NO ONE WILL BUY THEM.\n");
+            }
+            print("SUPPLIES AT FORT STADACONA COST $125.00.\n");
+            print("YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00.\n");
+            
+            d1 = Math.floor((0.2 * Math.random() + 0.8) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+        } else if (b == 3) {
+            i -= 105;
+            print("\n");
+            m1 = Math.floor((0.15 * Math.random() + 1.05) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            d1 = Math.floor((0.25 * Math.random() + 1.1) * Math.pow(10, 2) + 0.5) / Math.pow(10, 2);
+            p = Math.floor(10 * Math.random()) + 1;
+            if (p <= 2) {
+                print("YOU WERE ATTACKED BY A PARTY OF IROQUOIS.\n");
+                print("ALL PEOPLE IN YOUR TRADING GROUP WERE\n");
+                print("KILLED.  THIS ENDS THE GAME.\n");
+                break;
+            } else if (p <= 6) {
+                print("YOU WERE LUCKY.  YOU ARRIVED SAFELY\n");
+                print("AT FORT NEW YORK.\n");
+            } else if (p <= 8) {
+                reset_stats();
+                print("YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY.\n");
+                print("HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND.\n");
+                show_all = false;
+            } else if (p <= 10) {
+                b1 /= 2;
+                m1 /= 2;
+                print("YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP.\n");
+                print("YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS.\n");
+            }
+            print("SUPPLIES AT NEW YORK COST $80.00.\n");
+            print("YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00.\n");
+        }
+        print("\n");
+        if (show_all) {
+            if (show_beaver)
+                print("YOUR BEAVER SOLD FOR $" + b1 * f[2] + " ");
+            print("YOUR FOX SOLD FOR $" + d1 * f[4] + "\n");
+            print("YOUR ERMINE SOLD FOR $" + e1 * f[3] + " ");
+            print("YOUR MINK SOLD FOR $" + m1 * f[1] + "\n");
+        }
+        i += m1 * f[1] + b1 * f[2] + e1 * f[3] + d1 * f[4];
+        print("\n");
+        print("YOU NOW HAVE $" + i + " INCLUDING YOUR PREVIOUS SAVINGS\n");
+        print("\n");
+        print("DO YOU WANT TO TRADE FURS NEXT YEAR?\n");
+    }
+}
+
+main();

From 3d8024c7ce5d6136e6dbbea80afde0487531178d Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Thu, 4 Mar 2021 20:58:52 -0600
Subject: [PATCH 231/749] Ported GOMOKO to Javascript

---
 40 Gomoko/javascript/gomoko.html |   9 ++
 40 Gomoko/javascript/gomoko.js   | 174 +++++++++++++++++++++++++++++++
 2 files changed, 183 insertions(+)
 create mode 100644 40 Gomoko/javascript/gomoko.html
 create mode 100644 40 Gomoko/javascript/gomoko.js

diff --git a/40 Gomoko/javascript/gomoko.html b/40 Gomoko/javascript/gomoko.html
new file mode 100644
index 00000000..adbfd691
--- /dev/null
+++ b/40 Gomoko/javascript/gomoko.html	
@@ -0,0 +1,9 @@
+
+
+GOMOKO
+
+
+

+
+
+
diff --git a/40 Gomoko/javascript/gomoko.js b/40 Gomoko/javascript/gomoko.js
new file mode 100644
index 00000000..662feabb
--- /dev/null
+++ b/40 Gomoko/javascript/gomoko.js	
@@ -0,0 +1,174 @@
+// GOMOKO
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+function reset_stats()
+{
+    for (var j = 1; j <= 4; j++)
+        f[j] = 0;
+}
+
+var a = [];
+var x;
+var y;
+var n;
+
+// *** PRINT THE BOARD ***
+function print_board()
+{
+    for (i = 1; i <= n; i++) {
+        for (j = 1; j <= n; j++) {
+            print(" " + a[i][j] + " ");
+        }
+        print("\n");
+    }
+    print("\n");
+}
+
+// Is valid the movement
+function is_valid()
+{
+    if (x < 1 || x > n || y < 1 || y > n)
+        return false;
+    return true;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "GOMOKO\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 0; i <= 19; i++) {
+        a[i] = [];
+        for (j = 0; j <= 19; j++)
+            a[i][j] = 0;
+    }
+    print("WELCOME TO THE ORIENTAL GAME OF GOMOKO.\n");
+    print("\n");
+    print("THE GAME IS PLAYED ON AN N BY N GRID OF A SIZE\n");
+    print("THAT YOU SPECIFY.  DURING YOUR PLAY, YOU MAY COVER ONE GRID\n");
+    print("INTERSECTION WITH A MARKER. THE OBJECT OF THE GAME IS TO GET\n");
+    print("5 ADJACENT MARKERS IN A ROW -- HORIZONTALLY, VERTICALLY, OR\n");
+    print("DIAGONALLY.  ON THE BOARD DIAGRAM, YOUR MOVES ARE MARKED\n");
+    print("WITH A '1' AND THE COMPUTER MOVES WITH A '2'.\n");
+    print("\n");
+    print("THE COMPUTER DOES NOT KEEP TRACK OF WHO HAS WON.\n");
+    print("TO END THE GAME, TYPE -1,-1 FOR YOUR MOVE.\n");
+    print("\n");
+    while (1) {
+        print("WHAT IS YOUR BOARD SIZE (MIN 7/ MAX 19)");
+        while (1) {
+            n = parseInt(await input());
+            if (n >= 7 && n<= 19)
+                break;
+            print("I SAID, THE MINIMUM IS 7, THE MAXIMUM IS 19.\n");
+        }
+        for (i = 1; i <= n; i++) {
+            for (j = 1; j <= n; j++) {
+                a[i][j] = 0;
+            }
+        }
+        print("\n");
+        print("WE ALTERNATE MOVES.  YOU GO FIRST...\n");
+        print("\n");
+        while (1) {
+            print("YOUR PLAY (I,J)");
+            str = await input();
+            i = parseInt(str);
+            j = parseInt(str.substr(str.indexOf(",") + 1));
+            print("\n");
+            if (i == -1)
+                break;
+            x = i;
+            y = j;
+            if (!is_valid()) {
+                print("ILLEGAL MOVE.  TRY AGAIN...\n");
+                continue;
+            }
+            if (a[i][j] != 0) {
+                print("SQUARE OCCUPIED.  TRY AGAIN...\n");
+                continue;
+            }
+            a[i][j] = 1;
+            // *** Computer tries an intelligent move ***
+            found = false;
+            for (e = -1; e <= 1; e++) {
+                for (f = -1; f <= 1; f++) {
+                    if (e + f - e * f == 0)
+                        continue;
+                    x = i + f;
+                    y = j + f;
+                    if (!is_valid())
+                        continue;
+                    if (a[x][y] == 1) {
+                        x = i - e;
+                        y = j - f;
+                        if (is_valid() || a[x][y] == 0)
+                            found = true;
+                        break;
+                    }
+                }
+            }
+            if (!found) {
+                // *** Computer tries a random move ***
+                do {
+                    x = Math.floor(n * Math.random() + 1);
+                    y = Math.floor(n * Math.random() + 1);
+                } while (!is_valid() || a[x][y] != 0) ;
+            }
+            a[x][y] = 2;
+            print_board();
+        }
+        print("\n");
+        print("THANKS FOR THE GAME!!\n");
+        print("PLAY AGAIN (1 FOR YES, 0 FOR NO)");
+        q = parseInt(await input());
+        if (q != 1)
+            break;
+    }
+}
+
+main();

From 55b17eafc0b242229473ed53754b0c26753d4e49 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Thu, 4 Mar 2021 20:49:01 -0800
Subject: [PATCH 232/749] port LIFE to python

not a lot to do here, there's just one big loop.
---
 55 Life/python/life.py | 173 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 55 Life/python/life.py

diff --git a/55 Life/python/life.py b/55 Life/python/life.py
new file mode 100644
index 00000000..71016871
--- /dev/null
+++ b/55 Life/python/life.py	
@@ -0,0 +1,173 @@
+"""
+LIFE
+
+An implementation of John Conway's popular cellular automaton
+
+Ported by Dave LeCompte
+"""
+
+
+PAGE_WIDTH = 64
+
+MAX_WIDTH = 70
+MAX_HEIGHT = 24
+
+
+def print_centered(msg):
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
+
+
+def print_header(title):
+    print_centered(title)
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+
+def get_pattern():
+    print("ENTER YOUR PATTERN:")
+    c = 0
+
+    pattern = {}
+    while True:
+        line = input()
+        if line == "DONE":
+            return pattern
+
+        # BASIC input would strip of leading whitespace.
+        # Python input does not. The following allows you to start a
+        # line with a dot to disable the whitespace stripping. This is
+        # unnecessary for Python, but for historical accuracy, it's
+        # staying in.
+
+        if line[0] == ".":
+            line = " " + line[1:]
+        pattern[c] = line
+        c += 1
+
+
+def main():
+    print_header("LIFE")
+
+    pattern = get_pattern()
+
+    pattern_height = len(pattern)
+    pattern_width = 0
+    for line_num, line in pattern.items():
+        pattern_width = max(pattern_width, len(line))
+
+    min_x = 11 - pattern_height // 2
+    min_y = 33 - pattern_width // 2
+    max_x = MAX_HEIGHT - 1
+    max_y = MAX_WIDTH - 1
+
+    a = [[0 for y in range(MAX_WIDTH)] for x in range(MAX_HEIGHT)]
+    p = 0
+    g = 0
+    invalid = False
+
+    # line 140
+    # transcribe the input pattern into the active array
+    for x in range(0, pattern_height):
+        for y in range(0, len(pattern[x])):
+            if pattern[x][y] != " ":
+                a[min_x + x][min_y + y] = 1
+                p += 1
+
+    print()
+    print()
+    print()
+    while True:
+        if invalid:
+            inv_str = "INVALID!"
+        else:
+            inv_str = ""
+
+        print(f"GENERATION: {g}\tPOPULATION: {p} {inv_str}")
+
+        next_min_x = MAX_HEIGHT - 1
+        next_min_y = MAX_WIDTH - 1
+        next_max_x = 0
+        next_max_y = 0
+
+        p = 0
+        g += 1
+        for x in range(0, min_x):
+            print()
+
+        for x in range(min_x, max_x + 1):
+            print
+            line = [" "] * MAX_WIDTH
+            for y in range(min_y, max_y + 1):
+                if a[x][y] == 2:
+                    a[x][y] = 0
+                    continue
+                elif a[x][y] == 3:
+                    a[x][y] = 1
+                elif a[x][y] != 1:
+                    continue
+
+                # line 261
+                line[y] = "*"
+
+                next_min_x = min(x, next_min_x)
+                next_max_x = max(x, next_max_x)
+                next_min_y = min(y, next_min_y)
+                next_max_y = max(y, next_max_y)
+
+            print("".join(line))
+
+        # line 295
+        for x in range(max_x + 1, MAX_HEIGHT):
+            print()
+
+        print()
+
+        min_x = next_min_x
+        max_x = next_max_x
+        min_y = next_min_y
+        max_y = next_max_y
+
+        if min_x < 3:
+            min_x = 3
+            invalid = True
+        if max_x > 22:
+            max_x = 22
+            invalid = True
+        if min_y < 3:
+            min_y = 3
+            invalid = True
+        if max_y > 68:
+            max_y = 68
+            invalid = True
+
+        # line 309
+        p = 0
+
+        for x in range(min_x - 1, max_x + 2):
+            for y in range(min_y - 1, max_y + 2):
+                count = 0
+                for i in range(x - 1, x + 2):
+                    for j in range(y - 1, y + 2):
+                        if a[i][j] == 1 or a[i][j] == 2:
+                            count += 1
+                if a[x][y] == 0:
+                    if count == 3:
+                        a[x][y] = 3
+                        p += 1
+                elif (count < 3) or (count > 4):
+                    a[x][y] = 2
+                else:
+                    p += 1
+
+        # line 635
+        min_x = min_x - 1
+        min_y = min_y - 1
+        max_x = max_x + 1
+        max_y = max_y + 1
+
+
+if __name__ == "__main__":
+    main()

From 9349aa089008b681d3cfb304aca9e00010b8f2ea Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Thu, 4 Mar 2021 23:50:54 -0600
Subject: [PATCH 233/749] Ported HEXAPAWN to Javascript

---
 46 Hexapawn/javascript/hexapawn.html |   9 +
 46 Hexapawn/javascript/hexapawn.js   | 337 +++++++++++++++++++++++++++
 2 files changed, 346 insertions(+)
 create mode 100644 46 Hexapawn/javascript/hexapawn.html
 create mode 100644 46 Hexapawn/javascript/hexapawn.js

diff --git a/46 Hexapawn/javascript/hexapawn.html b/46 Hexapawn/javascript/hexapawn.html
new file mode 100644
index 00000000..5ac2b08c
--- /dev/null
+++ b/46 Hexapawn/javascript/hexapawn.html	
@@ -0,0 +1,9 @@
+
+
+HEXAPAWN
+
+
+

+
+
+
diff --git a/46 Hexapawn/javascript/hexapawn.js b/46 Hexapawn/javascript/hexapawn.js
new file mode 100644
index 00000000..6e36428c
--- /dev/null
+++ b/46 Hexapawn/javascript/hexapawn.js	
@@ -0,0 +1,337 @@
+// HEXAPAWN
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var ba = [,
+          [,-1,-1,-1,1,0,0,0,1,1],
+          [,-1,-1,-1,0,1,0,1,0,1],
+          [,-1,0,-1,-1,1,0,0,0,1],
+          [,0,-1,-1,1,-1,0,0,0,1],
+          [,-1,0,-1,1,1,0,0,1,0],
+          [,-1,-1,0,1,0,1,0,0,1],
+          [,0,-1,-1,0,-1,1,1,0,0],
+          [,0,-1,-1,-1,1,1,1,0,0],
+          [,-1,0,-1,-1,0,1,0,1,0],
+          [,0,-1,-1,0,1,0,0,0,1],
+          [,0,-1,-1,0,1,0,1,0,0],
+          [,-1,0,-1,1,0,0,0,0,1],
+          [,0,0,-1,-1,-1,1,0,0,0],
+          [,-1,0,0,1,1,1,0,0,0],
+          [,0,-1,0,-1,1,1,0,0,0],
+          [,-1,0,0,-1,-1,1,0,0,0],
+          [,0,0,-1,-1,1,0,0,0,0],
+          [,0,-1,0,1,-1,0,0,0,0],
+          [,-1,0,0,-1,1,0,0,0,0]];
+var ma = [,
+          [,24,25,36,0],
+          [,14,15,36,0],
+          [,15,35,36,47],
+          [,36,58,59,0],
+          [,15,35,36,0],
+          [,24,25,26,0],
+          [,26,57,58,0],
+          [,26,35,0,0],
+          [,47,48,0,0],
+          [,35,36,0,0],
+          [,35,36,0,0],
+          [,36,0,0,0],
+          [,47,58,0,0],
+          [,15,0,0,0],
+          [,26,47,0,0],
+          [,47,58,0,0],
+          [,35,36,47,0],
+          [,28,58,0,0],
+          [,15,47,0,0]];
+var s = [];
+var t = [];
+var ps = "X.O";
+
+function show_board()
+{
+    print("\n");
+    for (var i = 1; i <= 3; i++) {
+        print(tab(10));
+        for (var j = 1; j <= 3; j++) {
+            print(ps[s[(i - 1) * 3 + j] + 1]);
+        }
+        print("\n");
+    }
+}
+
+function mirror(x)
+{
+    if (x == 1)
+        return 3;
+    if (x == 3)
+        return 1;
+    if (x == 6)
+        return 4;
+    if (x == 4)
+        return 6;
+    if (x == 9)
+        return 7;
+    if (x == 7)
+        return 9;
+    return x;
+}
+
+// Main program
+async function main()
+{
+    print(tab(32) + "HEXAPAWN\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // HEXAPAWN:  INTERPRETATION OF HEXAPAWN GAME AS PRESENTED IN
+    // MARTIN GARDNER'S "THE UNEXPECTED HANGING AND OTHER MATHEMATIC-
+    // AL DIVERSIONS", CHAPTER EIGHT:  A MATCHBOX GAME-LEARNING MACHINE
+    // ORIGINAL VERSION FOR H-P TIMESHARE SYSTEM BY R.A. KAAPKE 5/5/76
+    // INSTRUCTIONS BY JEFF DALTON
+    // CONVERSION TO MITS BASIC BY STEVE NORTH
+    for (i = 0; i <= 9; i++) {
+        s[i] = 0;
+    }
+    w = 0;
+    l = 0;
+    do {
+        print("INSTRUCTIONS (Y-N)");
+        str = await input();
+        str = str.substr(0, 1);
+    } while (str != "Y" && str != "N") ;
+    if (str == "Y") {
+        print("\n");
+        print("THIS PROGRAM PLAYS THE GAME OF HEXAPAWN.\n");
+        print("HEXAPAWN IS PLAYED WITH CHESS PAWNS ON A 3 BY 3 BOARD.\n");
+        print("THE PAWNS ARE MOVED AS IN CHESS - ONE SPACE FORWARD TO\n");
+        print("AN EMPTY SPACE OR ONE SPACE FORWARD AND DIAGONALLY TO\n");
+        print("CAPTURE AN OPPOSING MAN.  ON THE BOARD, YOUR PAWNS\n");
+        print("ARE 'O', THE COMPUTER'S PAWNS ARE 'X', AND EMPTY \n");
+        print("SQUARES ARE '.'.  TO ENTER A MOVE, TYPE THE NUMBER OF\n");
+        print("THE SQUARE YOU ARE MOVING FROM, FOLLOWED BY THE NUMBER\n");
+        print("OF THE SQUARE YOU WILL MOVE TO.  THE NUMBERS MUST BE\n");
+        print("SEPERATED BY A COMMA.\n");
+        print("\n");
+        print("THE COMPUTER STARTS A SERIES OF GAMES KNOWING ONLY WHEN\n");
+        print("THE GAME IS WON (A DRAW IS IMPOSSIBLE) AND HOW TO MOVE.\n");
+        print("IT HAS NO STRATEGY AT FIRST AND JUST MOVES RANDOMLY.\n");
+        print("HOWEVER, IT LEARNS FROM EACH GAME.  THUS, WINNING BECOMES\n");
+        print("MORE AND MORE DIFFICULT.  ALSO, TO HELP OFFSET YOUR\n");
+        print("INITIAL ADVANTAGE, YOU WILL NOT BE TOLD HOW TO WIN THE\n");
+        print("GAME BUT MUST LEARN THIS BY PLAYING.\n");
+        print("\n");
+        print("THE NUMBERING OF THE BOARD IS AS FOLLOWS:\n");
+        print(tab(10) + "123\n");
+        print(tab(10) + "456\n");
+        print(tab(10) + "789\n");
+        print("\n");
+        print("FOR EXAMPLE, TO MOVE YOUR RIGHTMOST PAWN FORWARD,\n");
+        print("YOU WOULD TYPE 9,6 IN RESPONSE TO THE QUESTION\n");
+        print("'YOUR MOVE ?'.  SINCE I'M A GOOD SPORT, YOU'LL ALWAYS\n");
+        print("GO FIRST.\n");
+        print("\n");
+    }
+    while (1) {
+        x = 0;
+        y = 0;
+        s[4] = 0;
+        s[5] = 0;
+        s[6] = 0;
+        s[1] = -1;
+        s[2] = -1;
+        s[3] = -1;
+        s[7] = 1;
+        s[8] = 1;
+        s[9] = 1;
+        show_board();
+        while (1) {
+            while (1) {
+                print("YOUR MOVE");
+                str = await input();
+                m1 = parseInt(str);
+                m2 = parseInt(str.substr(str.indexOf(",") + 1));
+                if (m1 > 0 && m1 < 10 && m2 > 0 && m2 < 10) {
+                    if (s[m1] != 1 || s[m2] == 1 || (m2 - m1 != -3 && s[m2] != -1) || (m2 > m1) || (m2 - m1 == -3 && s[m2] != 0) || (m2 - m1 < -4) || (m1 == 7 && m2 == 3))
+                        print("ILLEGAL MOVE.\n");
+                    else
+                        break;
+                } else {
+                    print("ILLEGAL CO-ORDINATES.\n");
+                }
+            }
+            
+            // Move player's pawn
+            s[m1] = 0;
+            s[m2] = 1;
+            show_board();
+            
+            // Find computer pawns
+            for (i = 1; i <= 9; i++) {
+                if (s[i] == -1)
+                    break;
+            }
+            // If none or player reached top then finish
+            if (i > 9 || s[1] == 1 || s[2] == 1 || s[3] == 1) {
+                computer = false;
+                break;
+            }
+            // Find computer pawns with valid move
+            for (i = 1; i <= 9; i++) {
+                if (s[i] != -1)
+                    continue;
+                if (s[i + 3] == 0
+                 || (mirror(i) == i && (s[i + 2] == 1 || s[i + 4] == 1))
+                 || (i <= 3 && s[5] == 1)
+                 || s[8] == 1)
+                    break;
+            }
+            if (i > 9) {  // Finish if none possible
+                computer = false;
+                break;
+            }
+            for (i = 1; i <= 19; i++) {
+                for (j = 1; j <= 3; j++) {
+                    for (k = 3; k >= 1; k--) {
+                        t[(j - 1) * 3 + k] = ba[i][(j - 1) * 3 + 4 - k];
+                    }
+                }
+                for (j = 1; j <= 9; j++) {
+                    if (s[j] != ba[i][j])
+                        break;
+                }
+                if (j > 9) {
+                    r = 0;
+                    break;
+                }
+                for (j = 1; j <= 9; j++) {
+                    if (s[j] != t[j])
+                        break;
+                }
+                if (j > 9) {
+                    r = 1;
+                    break;
+                }
+            }
+            if (i > 19) {
+                print("ILLEGAL BOARD PATTERN\n");
+                break;
+            }
+            x = i;
+            for (i = 1; i <= 4; i++) {
+                if (ma[x][i] != 0)
+                    break;
+            }
+            if (i > 4) {
+                print("I RESIGN.\n");
+                computer = false;
+                break;
+            }
+            // Select random move from possibilities
+            do {
+                y = Math.floor(Math.random() * 4 + 1);
+            } while (ma[x][y] == 0) ;
+            // Announce move
+            if (r == 0) {
+                print("I MOVE FROM " + Math.floor(ma[x][y] / 10) + " TO " + ma[x][y] % 10 + "\n");
+                s[Math.floor(ma[x][y] / 10)] = 0;
+                s[ma[x][y] % 10] = -1;
+            } else {
+                print("I MOVE FROM " + mirror(Math.floor(ma[x][y] / 10)) + " TO " + mirror(ma[x][y]) % 10 + "\n");
+                s[mirror(Math.floor(ma[x][y] / 10))] = 0;
+                s[mirror(ma[x][y] % 10)] = -1;
+            }
+            show_board();
+            // Finish if computer reaches bottom
+            if (s[7] == -1 || s[8] == -1 || s[9] == -1) {
+                computer = true;
+                break;
+            }
+            // Finish if no player pawns
+            for (i = 1; i <= 9; i++) {
+                if (s[i] == 1)
+                    break;
+            }
+            if (i > 9) {
+                computer = true;
+                break;
+            }
+            // Finish if player cannot move
+            for (i = 1; i <= 9; i++) {
+                if (s[i] != 1)
+                    continue;
+                if (s[i - 3] == 0)
+                    break;
+                if (mirror(i) != i) {
+                    if (i >= 7) {
+                        if (s[5] == -1)
+                            break;
+                    } else {
+                        if (s[2] == -1)
+                            break;
+                    }
+                } else {
+                    if (s[i - 2] == -1 || s[i - 4] == -1)
+                        break;
+                }
+                
+            }
+            if (i > 9) {
+                print("YOU CAN'T MOVE, SO ");
+                computer = true;
+                break;
+            }
+        }
+        if (computer) {
+            print("I WIN.\n");
+            w++;
+        } else {
+            print("YOU WIN\n");
+            ma[x][y] = 0;
+            l++;
+        }
+        print("I HAVE WON " + w + " AND YOU " + l + " OUT OF " + (l + w) + " GAMES.\n");
+        print("\n");
+    }
+}
+
+main();

From c95819b7628986a4b154b78ec7c4bc3e3c2bea9c Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Fri, 5 Mar 2021 17:24:27 +1030
Subject: [PATCH 234/749] Bugfixes and cleanup for Hamurabi

---
 43 Hammurabi/java/src/Hamurabi.java | 273 +++++++++++++++++-----------
 1 file changed, 168 insertions(+), 105 deletions(-)

diff --git a/43 Hammurabi/java/src/Hamurabi.java b/43 Hammurabi/java/src/Hamurabi.java
index d157c489..6e2d1cee 100644
--- a/43 Hammurabi/java/src/Hamurabi.java	
+++ b/43 Hammurabi/java/src/Hamurabi.java	
@@ -12,6 +12,14 @@ import java.util.Scanner;
  */
 public class Hamurabi {
 
+    public static final int INITIAL_POPULATION = 95;
+    public static final int INITIAL_BUSHELS = 2800;
+    public static final int INITIAL_HARVEST = 3000;
+    public static final int INITIAL_LAND_TRADING_AT = 3;
+    public static final int INITIAL_CAME_TO_CITY = 5;
+    public static final int MAX_GAME_YEARS = 10;
+    public static final double MAX_STARVATION_IN_A_YEAR = .45d;
+
     private int year;
     private int population;
     private int acres;
@@ -19,11 +27,11 @@ public class Hamurabi {
     private int harvest;
     private int landTradingAt;
     private int cameToCity;
-    private int died;
-    private int q;
+    private int starvedInAYear;
+    private int starvedOverall;
+    private boolean chanceOfPlague;
     private int ratsAte;
     private double peopleFed;
-    private double totalPlanted;
     private double percentageStarved;
     private int acresToPlant;
     private int bushelsToFeedPeople;
@@ -42,6 +50,7 @@ public class Hamurabi {
         CALCULATE_HARVEST,
         CALCULATE_BABIES,
         RESULTS,
+        FINISH_GAME,
         GAME_OVER
     }
 
@@ -70,17 +79,17 @@ public class Hamurabi {
 
                     // These are hard coded startup figures from the basic program
                     year = 0;
-                    population = 95;
-                    bushels = 2800;
-                    harvest = 3000;
-                    landTradingAt = 3;
-                    acres = harvest / landTradingAt;
-                    cameToCity = 5;
-                    died = 0;
-                    q = 1;
-                    ratsAte = harvest - bushels;
+                    population = INITIAL_POPULATION;
+                    bushels = INITIAL_BUSHELS;
+                    harvest = INITIAL_HARVEST;
+                    landTradingAt = INITIAL_LAND_TRADING_AT;
+                    acres = INITIAL_HARVEST / INITIAL_LAND_TRADING_AT;
+                    cameToCity = INITIAL_CAME_TO_CITY;
+                    starvedInAYear = 0;
+                    starvedOverall = 0;
+                    chanceOfPlague = false;
+                    ratsAte = INITIAL_HARVEST - INITIAL_BUSHELS;
                     peopleFed = 0;
-                    totalPlanted = 0;
                     percentageStarved = 0;
                     acresToPlant = 0;
                     bushelsToFeedPeople = 0;
@@ -91,10 +100,16 @@ public class Hamurabi {
                 case YEAR_CYCLE:
                     System.out.println();
                     year += 1;
+                    // End of game?
+                    if (year > MAX_GAME_YEARS) {
+                        gameState = GAME_STATE.RESULTS;
+                        break;
+
+                    }
                     System.out.println("HAMURABI:  I BEG TO REPORT TO YOU,");
-                    System.out.println("IN YEAR " + year + "," + died + " PEOPLE STARVED," + cameToCity + " CAME TO THE CITY,");
+                    System.out.println("IN YEAR " + year + "," + starvedInAYear + " PEOPLE STARVED," + cameToCity + " CAME TO THE CITY,");
                     population += cameToCity;
-                    if (q == 0) {
+                    if (chanceOfPlague) {
                         population /= 2;
                         System.out.println("A HORRIBLE PLAGUE STRUCK!  HALF THE PEOPLE DIED.");
                     }
@@ -105,103 +120,95 @@ public class Hamurabi {
                     System.out.println("YOU NOW HAVE " + bushels + " BUSHELS IN STORE.");
                     System.out.println();
 
-                    peopleFed = (int) (Math.random() * 10);
-                    landTradingAt = (int) peopleFed + 17;
+                    landTradingAt = (int) (Math.random() * 10) + 17;  // Original formula unchanged
                     System.out.println("LAND IS TRADING AT " + landTradingAt + " BUSHELS PER ACRE.");
 
                     gameState = GAME_STATE.BUY_ACRES;
                     break;
 
                 case BUY_ACRES:
-                        int acresToBuy = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO BUY? ");
-                        if (acresToBuy < 0) {
-                            gameState = GAME_STATE.GAME_OVER;
-                        }
+                    int acresToBuy = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO BUY? ");
+                    if (acresToBuy < 0) {
+                        gameState = GAME_STATE.FINISH_GAME;
+                    }
 
-                        if(acresToBuy >0) {
-                            if ((landTradingAt * acresToBuy) > bushels) {
-                                System.out.println("HAMURABI:  THINK AGAIN.  YOU HAVE ONLY");
-                                System.out.println(bushels + " BUSHELS OF GRAIN.  NOW THEN,");
-                            } else {
-                                if (q == 0) {
-                                    gameState = GAME_STATE.SELL_ACRES;
-                                } else {
-                                    acres += acresToBuy;
-                                    bushels -= (landTradingAt * acresToBuy);
-                                    peopleFed = 0;
-                                    gameState = GAME_STATE.FEED_PEOPLE;
-                                }
-                            }
+                    if (acresToBuy > 0) {
+                        if ((landTradingAt * acresToBuy) > bushels) {
+                            notEnoughBushelsMessage();
                         } else {
-                            // 0 entered as buy so try to sell
-                            gameState = GAME_STATE.SELL_ACRES;
+                            acres += acresToBuy;
+                            bushels -= (landTradingAt * acresToBuy);
+                            peopleFed = 0;
+                            gameState = GAME_STATE.FEED_PEOPLE;
                         }
-                        break;
+                    } else {
+                        // 0 entered as buy so try to sell
+                        gameState = GAME_STATE.SELL_ACRES;
+                    }
+                    break;
 
                 case SELL_ACRES:
-                        int acresToSell = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO SELL? ");
-                        if (acresToSell < 0) {
-                            gameState = GAME_STATE.GAME_OVER;
-                        }
-                        if (acresToSell < acres) {
-                            acres -= acresToSell;
-                            bushels += (landTradingAt * acresToSell);
-                            gameState = GAME_STATE.FEED_PEOPLE;
-                        } else {
-                            System.out.println("HAMURABI:  THINK AGAIN.  YOU OWN ONLY " + acres + " ACRES.  NOW THEN,");
-                        }
-                        break;
+                    int acresToSell = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO SELL? ");
+                    if (acresToSell < 0) {
+                        gameState = GAME_STATE.FINISH_GAME;
+                    }
+                    if (acresToSell < acres) {
+                        acres -= acresToSell;
+                        bushels += (landTradingAt * acresToSell);
+                        gameState = GAME_STATE.FEED_PEOPLE;
+                    } else {
+                        notEnoughLandMessage();
+                    }
+                    break;
 
                 case FEED_PEOPLE:
 
-                        bushelsToFeedPeople = displayTextAndGetNumber("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE ? ");
-                        if (bushelsToFeedPeople < 0) {
-                            gameState = GAME_STATE.GAME_OVER;
-                        }
+                    bushelsToFeedPeople = displayTextAndGetNumber("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE ? ");
+                    if (bushelsToFeedPeople < 0) {
+                        gameState = GAME_STATE.FINISH_GAME;
+                    }
 
-                        if (bushelsToFeedPeople <= bushels) {
-                            bushels -= bushelsToFeedPeople;
-                            peopleFed = 1;
-                            gameState = GAME_STATE.PLANT_SEED;
-                        } else {
-                            System.out.println("HAMURABI:  THINK AGAIN.  YOU HAVE ONLY");
-                            System.out.println(bushels + " BUSHELS OF GRAIN.  NOW THEN,");
-                        }
-                        break;
+                    if (bushelsToFeedPeople <= bushels) {
+                        bushels -= bushelsToFeedPeople;
+                        peopleFed = 1;
+                        gameState = GAME_STATE.PLANT_SEED;
+                    } else {
+                        notEnoughBushelsMessage();
+                    }
+                    break;
 
                 case PLANT_SEED:
 
                     acresToPlant = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED ? ");
                     if (acresToPlant < 0) {
-                        gameState = GAME_STATE.GAME_OVER;
+                        gameState = GAME_STATE.FINISH_GAME;
                     }
 
                     if (acresToPlant <= acres) {
-                        if(acresToPlant/2 <= bushels) {
-                            if(acresToPlant < 10*population) {
-                                bushels -= acresToPlant/2;
-                                peopleFed = (int) (Math.random()*5)+1;
+                        if (acresToPlant / 2 <= bushels) {
+                            if (acresToPlant < 10 * population) {
+                                bushels -= acresToPlant / 2;
+                                peopleFed = (int) (Math.random() * 5) + 1;
                                 landTradingAt = (int) peopleFed;
                                 harvest = acresToPlant * landTradingAt;
                                 ratsAte = 0;
                                 gameState = GAME_STATE.CALCULATE_HARVEST;
                             } else {
-                                System.out.println("BUT YOU HAVE ONLY " + population + " PEOPLE TO TEND THE FIELDS!  NOW THEN,");
+                                notEnoughPeopleMessage();
                             }
                         } else {
-                            System.out.println("HAMURABI:  THINK AGAIN.  YOU HAVE ONLY");
-                            System.out.println("BUSHELS OF GRAIN.  NOW THEN,");
+                            notEnoughBushelsMessage();
                         }
                     } else {
-                        System.out.println("HAMURABI:  THINK AGAIN.  YOU OWN ONLY " + acres + " ACRES.  NOW THEN,");
+                        notEnoughLandMessage();
                     }
                     break;
 
                 case CALCULATE_HARVEST:
 
-                    if( (int) (peopleFed/2) == peopleFed/2) {
+                    if ((int) (peopleFed / 2) == peopleFed / 2) {
                         // Rats are running wild
-                            ratsAte = (int) (bushels / peopleFed);
+                        ratsAte = (int) (bushels / peopleFed);
                     }
                     bushels = bushels - ratsAte;
                     bushels += harvest;
@@ -210,41 +217,112 @@ public class Hamurabi {
 
                 case CALCULATE_BABIES:
 
-                    cameToCity = (int) (peopleFed*(20*acres+bushels)/population/100+1);
-                    peopleFed = (int) (bushelsToFeedPeople/20);
-                    q = (int) ((10*(Math.random()*2)-.3));
-                    if(population .45*population) {
-                        System.out.println();
-                        System.out.println("YOU STARVED " + (int) starved + " PEOPLE IN ONE YEAR!!!");
-                        System.out.println("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY");
-                        System.out.println("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE");
-                        System.out.println("ALSO BEEN DECLARED NATIONAL FINK!!!!");
-                        gameState = GAME_STATE.GAME_OVER;
-                    } else {
-                        percentageStarved = ((year-1)*percentageStarved+(double) (acresToPlant*100/population))/year;
-                        population = (int) peopleFed;
-                        totalPlanted  += acresToPlant;
+                    if (starved < 0.0d) {
+                        starvedInAYear = 0;
                         gameState = GAME_STATE.YEAR_CYCLE;
+                    } else {
+                        System.out.println("STARVED = " + starved);
+                        starvedInAYear = (int) starved;
+                        starvedOverall += starvedInAYear;
+                        if (starved > MAX_STARVATION_IN_A_YEAR * population) {
+                            starvedTooManyPeopleMessage((int) starved);
+                            gameState = GAME_STATE.FINISH_GAME;
+                        } else {
+                            percentageStarved = ((year - 1) * percentageStarved + starved * 100 / population) / year;
+                            System.out.println("PERCENTAGE STARVED = " + percentageStarved);
+                            population = (int) peopleFed;
+                            gameState = GAME_STATE.YEAR_CYCLE;
+                        }
+
                     }
 
                     break;
 
 
+                case RESULTS:
+
+                    int acresPerPerson = acres / population;
+
+                    System.out.println("IN YOUR 10-YEAR TERM OF OFFICE," + percentageStarved + " PERCENT OF THE");
+                    System.out.println("POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF");
+                    System.out.println(starvedOverall + " PEOPLE DIED!!");
+                    System.out.println("YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH");
+                    System.out.println(acresPerPerson + " ACRES PER PERSON.");
+                    System.out.println();
+
+                    if (percentageStarved > 33.0d || acresPerPerson < 7) {
+                        starvedTooManyPeopleMessage(starvedOverall);
+                    } else if (percentageStarved > 10.0d || acresPerPerson < 9) {
+                        heavyHandedMessage();
+                    } else if (percentageStarved > 3.0d || acresPerPerson < 10) {
+                        couldHaveBeenBetterMessage();
+                    } else {
+                        fantasticPerformanceMessage();
+                    }
 
 
+                    gameState = GAME_STATE.FINISH_GAME;
 
-
+                case FINISH_GAME:
+                    System.out.println("SO LONG FOR NOW.");
+                    gameState = GAME_STATE.GAME_OVER;
 
             }
 
         } while (gameState != GAME_STATE.GAME_OVER);
     }
 
+    private void starvedTooManyPeopleMessage(int starved) {
+        System.out.println();
+        System.out.println("YOU STARVED " + starved + " PEOPLE IN ONE YEAR!!!");
+        System.out.println("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY");
+        System.out.println("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE");
+        System.out.println("ALSO BEEN DECLARED NATIONAL FINK!!!!");
+
+    }
+
+    private void heavyHandedMessage() {
+        System.out.println("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY");
+        System.out.println("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE");
+        System.out.println("ALSO BEEN DECLARED NATIONAL FINK!!!!");
+    }
+
+    private void couldHaveBeenBetterMessage() {
+        System.out.println("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT");
+        System.out.println("REALLY WASN'T TOO BAD AT ALL. " + (int) (Math.random() * (population * .8)) + "PEOPLE");
+        System.out.println("WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR");
+        System.out.println("TRIVIAL PROBLEMS.");
+    }
+
+    private void fantasticPerformanceMessage() {
+        System.out.println("A FANTASTIC PERFORMANCE!!!  CHARLEMANGE, DISRAELI, AND");
+        System.out.println("JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!");
+    }
+
+    private void notEnoughPeopleMessage() {
+        System.out.println("BUT YOU HAVE ONLY " + population + " PEOPLE TO TEND THE FIELDS!  NOW THEN,");
+
+    }
+
+    private void notEnoughBushelsMessage() {
+        System.out.println("HAMURABI:  THINK AGAIN.  YOU HAVE ONLY");
+        System.out.println(bushels + " BUSHELS OF GRAIN.  NOW THEN,");
+    }
+
+    private void notEnoughLandMessage() {
+        System.out.println("HAMURABI:  THINK AGAIN.  YOU OWN ONLY " + acres + " ACRES.  NOW THEN,");
+    }
+
+
     private void intro() {
         System.out.println(simulateTabs(32) + "HAMURABI");
         System.out.println(simulateTabs(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
@@ -254,21 +332,6 @@ public class Hamurabi {
         System.out.println();
     }
 
-    private boolean calculate(double playerAnswer, double correctAnswer) {
-
-        boolean gotItRight = false;
-
-        if (Math.abs((playerAnswer - correctAnswer) / correctAnswer) < 0.15) {
-            System.out.println("CLOSE ENOUGH");
-            gotItRight = true;
-        } else {
-            System.out.println("NOT EVEN CLOSE");
-        }
-        System.out.println("CORRECT ANSWER IS " + correctAnswer);
-        System.out.println();
-
-        return gotItRight;
-    }
 
     /*
      * Print a message on the screen, then accept input from Keyboard.

From 943250f37672825078be01abb190e80bc483c354 Mon Sep 17 00:00:00 2001
From: Gustavo Carreno 
Date: Fri, 5 Mar 2021 15:13:13 +0000
Subject: [PATCH 235/749] Adding 02 Amazing pascal simple

---
 02 Amazing/pascal/.gitattributes     |  36 ++++
 02 Amazing/pascal/.gitignore         |  63 ++++++
 02 Amazing/pascal/README.md          |   2 +-
 02 Amazing/pascal/simple/amazing.lpi |  58 ++++++
 02 Amazing/pascal/simple/amazing.pas | 284 +++++++++++++++++++++++++++
 5 files changed, 442 insertions(+), 1 deletion(-)
 create mode 100644 02 Amazing/pascal/.gitattributes
 create mode 100644 02 Amazing/pascal/.gitignore
 create mode 100644 02 Amazing/pascal/simple/amazing.lpi
 create mode 100644 02 Amazing/pascal/simple/amazing.pas

diff --git a/02 Amazing/pascal/.gitattributes b/02 Amazing/pascal/.gitattributes
new file mode 100644
index 00000000..f59d5ede
--- /dev/null
+++ b/02 Amazing/pascal/.gitattributes	
@@ -0,0 +1,36 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files you want to always be normalized and converted
+# to native line endings on checkout.
+*.inc  text
+*.pas  text
+*.pp   text
+*.lpk  text
+*.lpi  text
+*.lps  text
+*.lpr  text
+*.def  text
+*.css  text
+*.html text
+*.xml  text
+*.sql  text
+
+# Declare files that will always have CRLF line endings on checkout.
+*.dpk   text eol=crlf
+*.dproj text eol=crlf
+
+# Declare files that will always have LF line endings on checkout.
+
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.exe binary
+*.res binary
+*.ico binary
+*.dll binary
+
+# Keep these files from archive/exports, mainly from production.
+.gitignore      export-ignore
+.gitattributes  export-ignore
diff --git a/02 Amazing/pascal/.gitignore b/02 Amazing/pascal/.gitignore
new file mode 100644
index 00000000..f9028d41
--- /dev/null
+++ b/02 Amazing/pascal/.gitignore	
@@ -0,0 +1,63 @@
+# Basic Computer Programs project specific
+amazing
+amazing.exe
+
+# Compiled l10n files: .mo should be ignored
+*.mo
+
+# Ghostwriter backups
+*.backup
+
+# nano editor backup files
+*.swp
+
+# Uncomment these types if you want even more clean repository. But be careful.
+# It can make harm to an existing project source. Read explanations below.
+#
+# Resource files are binaries containing manifest, project icon and version info.
+# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
+*.res
+
+# Delphi/Lazarus compiler-generated binaries (safe to delete)
+*.exe
+*.dll
+*.bpl
+*.bpi
+*.dcp
+*.so
+*.apk
+*.drc
+*.map
+*.dres
+*.rsm
+*.tds
+*.dcu
+*.lib
+*.[ao]
+*.or
+*.ppu
+*.dbg
+*.compiled
+
+# Delphi autogenerated files (duplicated info)
+*.cfg
+*Resource.rc
+
+# Delphi local files (user-specific info)
+*.local
+*.identcache
+*.projdata
+*.tvsconfig
+*.dsk
+
+# Delphi history and backups
+__history/
+*.~*
+
+# Lazarus history, backups and session
+backup/
+*.bak
+*.lps
+
+# Castalia statistics file
+*.stat
diff --git a/02 Amazing/pascal/README.md b/02 Amazing/pascal/README.md
index aa1b3ae5..3f97be91 100644
--- a/02 Amazing/pascal/README.md	
+++ b/02 Amazing/pascal/README.md	
@@ -1,3 +1,3 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
-Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))
+Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language)) by Gustavo Carreno [gcarreno@github](https://github.com/gcarreno)
diff --git a/02 Amazing/pascal/simple/amazing.lpi b/02 Amazing/pascal/simple/amazing.lpi
new file mode 100644
index 00000000..b401a451
--- /dev/null
+++ b/02 Amazing/pascal/simple/amazing.lpi	
@@ -0,0 +1,58 @@
+
+
+  
+    
+    
+      
+        
+        
+        
+        
+      
+      
+      
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="amazing.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="Amazing"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="amazing"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>
diff --git a/02 Amazing/pascal/simple/amazing.pas b/02 Amazing/pascal/simple/amazing.pas
new file mode 100644
index 00000000..dc5d7610
--- /dev/null
+++ b/02 Amazing/pascal/simple/amazing.pas	
@@ -0,0 +1,284 @@
+program Amazing;
+
+{$IFDEF FPC}
+{$mode objfpc}{$H+}
+{$ENDIF}
+
+uses
+  Crt;
+
+type
+  TDirection = (dUp, dRight, dDown, dLeft);
+  TDirections = set of TDirection;
+
+var
+  Width: Integer;   // H
+  Length: Integer;  // V
+  Entry: Integer;
+  MatrixWalls: Array of Array of Integer;
+  MatrixVisited: Array of Array of Integer;
+
+const
+  EXIT_DOWN  = 1;
+  EXIT_RIGHT = 2;
+
+procedure PrintGreeting;
+begin
+  WriteLN(' ':28, 'AMAZING PROGRAM');
+  WriteLN(' ':15, 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY');
+  WriteLN;
+  WriteLN;
+  WriteLN;
+  WriteLN;
+end;
+
+procedure GetDimensions;
+begin
+  repeat
+    Write('WHAT ARE YOUR WIDTH AND LENGTH (SPACE IN BETWEEN): ');
+    ReadLN(Width, Length);
+    if (Width = 1) or (Length = 1) then
+    begin
+      WriteLN('MEANINGLESS DIMENSIONS.  TRY AGAIN.');
+    end;
+  until (Width > 1) and (Length > 1);
+  WriteLN;
+  WriteLN;
+  WriteLN;
+  WriteLN;
+end;
+
+procedure ClearMatrices;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  SetLength(MatrixWalls, Width, Length);
+  SetLength(MatrixVisited, Width, Length);
+  for indexW:= 0 to Pred(Width) do
+  begin
+    for indexL:= 0 to Pred(Length) do
+    begin
+      MatrixWalls[indexW][indexL]:= 0;
+      MatrixVisited[indexW][indexL]:= 0;
+    end;
+  end;
+end;
+
+function GetRandomDirection(const ADirections: TDirections): TDirection;
+var
+  count: Integer;
+  position: Integer;
+  directions: array [0..3] of TDirection;
+begin
+  count:= 0;
+  position:= 0;
+  if dUp in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dUp;
+    Inc(position);
+  end;
+  if dRight in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dRight;
+    Inc(position);
+  end;
+  if dDown in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dDown;
+    Inc(position);
+  end;
+  if dLeft in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dLeft;
+    Inc(position);
+  end;
+  Result:= directions[Random(count)];
+end;
+
+procedure BuildMaze;
+var
+  indexW: Integer;
+  indexL: Integer;
+  direction: TDirection;
+  directions: TDirections;
+  count: Integer;
+begin
+  Entry:= Random(Width);
+  indexW:= Entry;
+  indexL:= 0;
+  count:= 1;
+  MatrixVisited[indexW][indexL]:= count;
+  Inc(count);
+  repeat
+    directions:= [dUp, dRight, dDown, dLeft];
+    if (indexW = 0) or (MatrixVisited[Pred(indexW)][indexL] <> 0) then
+    begin
+      Exclude(directions, dLeft);
+    end;
+    if (indexL = 0) or (MatrixVisited[indexW][Pred(indexL)] <> 0) then
+    begin
+      Exclude(directions, dUp);
+    end;
+    if (indexW = Pred(Width)) or (MatrixVisited[Succ(indexW)][indexL] <> 0) then
+    begin
+      Exclude(directions, dRight);
+    end;
+    if (indexL = Pred(Length)) or (MatrixVisited[indexW][Succ(indexL)] <> 0) then
+    begin
+      Exclude(directions, dDown);
+    end;
+
+    if directions <> [] then
+    begin
+      direction:= GetRandomDirection(directions);
+      case direction of
+        dLeft:begin
+          Dec(indexW);
+          MatrixWalls[indexW][indexL]:= EXIT_RIGHT;
+        end;
+        dUp:begin
+          Dec(indexL);
+          MatrixWalls[indexW][indexL]:= EXIT_DOWN;
+        end;
+        dRight:begin
+          Inc(MatrixWalls[indexW][indexL], EXIT_RIGHT);
+          Inc(indexW);
+        end;
+        dDown:begin
+          Inc(MatrixWalls[indexW][indexL], EXIT_DOWN);
+          Inc(indexL);
+        end;
+      end;
+      MatrixVisited[indexW][indexL]:= count;
+      Inc(count);
+    end
+    else
+    begin
+      while True do
+      begin
+        if indexW <> Pred(Width) then
+        begin
+          Inc(indexW);
+        end
+        else if indexL <> Pred(Length) then
+        begin
+          Inc(indexL);
+          indexW:= 0;
+        end
+        else
+        begin
+          indexW:= 0;
+          indexL:= 0;
+        end;
+        if MatrixVisited[indexW][indexL] <> 0 then
+        begin
+          break;
+        end;
+      end;
+    end;
+  until count = (Width * Length) + 1;
+  indexW:= Random(Width);
+  indexL:= Pred(Length);
+  Inc(MatrixWalls[indexW][indexL]);
+end;
+
+procedure DegubVisited;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  WriteLN('Visited');
+  for indexL:= 0 to Pred(Length) do
+  begin
+    for indexW:= 0 to Pred(Width) do
+    begin
+      Write(MatrixVisited[indexW][indexL]:2,' ');
+    end;
+    WriteLN;
+  end;
+  WriteLN;
+end;
+
+procedure DebugWalls;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  WriteLN('Walls');
+  for indexL:= 0 to Pred(Length) do
+  begin
+    for indexW:= 0 to Pred(Width) do
+    begin
+      Write(MatrixWalls[indexW, indexL]:2, ' ');
+    end;
+    WriteLN;
+  end;
+  WriteLN;
+end;
+
+procedure PrintMaze;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+
+  for indexW:= 0 to Pred(Width) do
+  begin
+    if indexW = Entry then
+    begin
+      Write('.  ');
+    end
+    else
+    begin
+      Write('.--');
+    end;
+  end;
+  WriteLN('.');
+  for indexL:= 0 to Pred(Length) do
+  begin
+    Write('I');
+    for indexW:= 0 to Pred(Width) do
+    begin
+      if MatrixWalls[indexW, indexL] < 2 then
+      begin
+        Write('  I');
+      end
+      else
+      begin
+        Write('   ');
+      end;
+    end;
+    WriteLN;
+    for indexW:= 0 to Pred(Width) do
+    begin
+      if (MatrixWalls[indexW, indexL] = 0) or (MatrixWalls[indexW, indexL] = 2) then
+      begin
+        Write(':--');
+      end
+      else
+      begin
+        Write(':  ');
+      end;
+    end;
+    WriteLN('.');
+  end;
+  WriteLN;
+end;
+
+begin
+  Randomize;
+  ClrScr;
+  PrintGreeting;
+  GetDimensions;
+  ClearMatrices;
+  BuildMaze;
+  //DegubVisited;
+  //DebugWalls;
+  PrintMaze;
+end.
+

From d0fa4d31f58afc1073a9b7b36ead8eda1e694630 Mon Sep 17 00:00:00 2001
From: Gustavo Carreno <guscarreno@gmail.com>
Date: Fri, 5 Mar 2021 15:30:19 +0000
Subject: [PATCH 236/749] Minor fix in 01-AceyDucey object pascal

---
 01 Acey Ducey/pascal/object-pascal/aceyducey.pas | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/01 Acey Ducey/pascal/object-pascal/aceyducey.pas b/01 Acey Ducey/pascal/object-pascal/aceyducey.pas
index 733221f5..9e72952b 100644
--- a/01 Acey Ducey/pascal/object-pascal/aceyducey.pas	
+++ b/01 Acey Ducey/pascal/object-pascal/aceyducey.pas	
@@ -5,7 +5,8 @@ program aceyducey;
 {$ENDIF}
 
 uses
-  Game, Deck
+  Game
+, Deck
 ;
 
 var

From 26afc87d6563aed25d71f6995d804456a22ba1ff Mon Sep 17 00:00:00 2001
From: Dave LeCompte <tsmaster@gmail.com>
Date: Fri, 5 Mar 2021 08:24:52 -0800
Subject: [PATCH 237/749] port BOUNCE to python

straightforward, minor trickery with PRINT TAB construct. Renamed some variables to be a little easier to read (and to match with what I remember from freshman physics).
---
 13 Bounce/python/bounce.py | 110 +++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)
 create mode 100644 13 Bounce/python/bounce.py

diff --git a/13 Bounce/python/bounce.py b/13 Bounce/python/bounce.py
new file mode 100644
index 00000000..702f7687
--- /dev/null
+++ b/13 Bounce/python/bounce.py	
@@ -0,0 +1,110 @@
+"""
+BOUNCE
+
+A physics simulation
+
+Ported by Dave LeCompte
+"""
+
+
+PAGE_WIDTH = 64
+
+
+def print_centered(msg):
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
+
+
+def print_header(title):
+    print_centered(title)
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+
+def print_instructions():
+    print("THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY")
+    print("OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF")
+    print("ELASTICITY OF THE BALL.  PLEASE USE A DECIMAL FRACTION")
+    print("COEFFICIENCY (LESS THAN 1).")
+    print()
+    print("YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN")
+    print("'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY).")
+    print()
+
+
+def get_initial_conditions():
+    delta_t = float(input("TIME INCREMENT (SEC)? "))
+    print()
+    v0 = float(input("VELOCITY (FPS)? "))
+    print()
+    coeff_rest = float(input("COEFFICIENT? "))
+    print()
+
+    return delta_t, v0, coeff_rest
+
+
+def print_at_tab(line, tab, s):
+    line += (" " * (tab - len(line))) + s
+    return line
+
+
+def run_simulation(delta_t, v0, coeff_rest):
+    t = [0] * 20  # time of each bounce?
+
+    print("FEET")
+    print()
+
+    sim_dur = int(70 / (v0 / (16 * delta_t)))
+    for i in range(1, sim_dur + 1):
+        t[i] = v0 * coeff_rest ** (i - 1) / 16
+
+    # Draw the trajectory of the bouncing ball, one slice of height at a time
+    h = int(-16 * (v0 / 32) ** 2 + v0 ** 2 / 32 + 0.5)
+    while h >= 0:
+        line = ""
+        if int(h) == h:
+            line += str(int(h))
+        l = 0
+        for i in range(1, sim_dur + 1):
+            tm = 0
+            while tm <= t[i]:
+                l += delta_t
+                if (
+                    abs(h - (0.5 * (-32) * tm ** 2 + v0 * coeff_rest ** (i - 1) * tm))
+                    <= 0.25
+                ):
+                    line = print_at_tab(line, int(l / delta_t), "0")
+                tm += delta_t
+            tm = t[i + 1] / 2
+
+            if -16 * tm ** 2 + v0 * coeff_rest ** (i - 1) * tm < h:
+                break
+        print(line)
+        h = h - 0.5
+
+    print("." * (int((l + 1) / delta_t) + 1))
+    print
+    line = " 0"
+    for i in range(1, int(l + 0.9995) + 1):
+        line = print_at_tab(line, int(i / delta_t), str(i))
+    print(line)
+    print()
+    print(print_at_tab("", int((l + 1) / (2 * delta_t) - 2), "SECONDS"))
+    print()
+
+
+def main():
+    print_header("BOUNCE")
+    print_instructions()
+
+    while True:
+        delta_t, v0, coeff_rest = get_initial_conditions()
+
+        run_simulation(delta_t, v0, coeff_rest)
+        break
+
+
+if __name__ == "__main__":
+    main()

From bd3cd748903c9a0ed0d3aa8162153a6eb5149918 Mon Sep 17 00:00:00 2001
From: Dave LeCompte <tsmaster@gmail.com>
Date: Fri, 5 Mar 2021 08:30:18 -0800
Subject: [PATCH 238/749] update BOUNCE for python

Edited a comment to be more authoritative.
---
 13 Bounce/python/bounce.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/13 Bounce/python/bounce.py b/13 Bounce/python/bounce.py
index 702f7687..3ab7411c 100644
--- a/13 Bounce/python/bounce.py	
+++ b/13 Bounce/python/bounce.py	
@@ -51,7 +51,7 @@ def print_at_tab(line, tab, s):
 
 
 def run_simulation(delta_t, v0, coeff_rest):
-    t = [0] * 20  # time of each bounce?
+    t = [0] * 20  # time of each bounce
 
     print("FEET")
     print()

From 7db223b11c9df781da6d364414efd3b4b8fef5fc Mon Sep 17 00:00:00 2001
From: peratik <peratik@gmail.com>
Date: Fri, 5 Mar 2021 11:53:01 -0500
Subject: [PATCH 239/749] Update README.md

---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index 6b368c4b..0a1c48d5 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
 
 We're updating the first million selling computer book, [BASIC Computer Games](https://en.wikipedia.org/wiki/BASIC_Computer_Games), for 2021!
 
+[Read book] (https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf)
+
 ### Where can we discuss it?
 
 Please see [the discussion here](https://discourse.codinghorror.com/t/updating-101-basic-computer-games-for-2021/7927) for a worklog and conversation around this project.

From edbad882513f2b2035b448e15b26e821b3567a60 Mon Sep 17 00:00:00 2001
From: Dave LeCompte <tsmaster@gmail.com>
Date: Fri, 5 Mar 2021 09:25:14 -0800
Subject: [PATCH 240/749] port SUPERSTARTREKINS to python

The original BASIC presentation of this has some interesting archaeological hints of days when memory was low, users would print out hard copy instructions, and then proceed to load the actual game off of cassette.

For modern users, this would probably be most usefully turned into a README.txt file.
---
 84 Super Star Trek/python/superstartrekins.py | 147 ++++++++++++++++++
 84 Super Star Trek/superstartrekins.bas       |   2 +-
 2 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 84 Super Star Trek/python/superstartrekins.py

diff --git a/84 Super Star Trek/python/superstartrekins.py b/84 Super Star Trek/python/superstartrekins.py
new file mode 100644
index 00000000..2260c807
--- /dev/null
+++ b/84 Super Star Trek/python/superstartrekins.py	
@@ -0,0 +1,147 @@
+"""
+SUPER STARTREK INSTRUCTIONS
+MAR 5, 1978
+
+Just the instructions for SUPERSTARTREK
+
+Ported by Dave LeCompte
+"""
+
+def get_yes_no(prompt):
+    response = input(prompt).upper()
+    return response[0] != 'N'
+
+def print_header():
+    for i in range(12):
+        print()
+    t10 = " " * 10
+    print(t10 + "*************************************")
+    print(t10 + "*                                   *")
+    print(t10 + "*                                   *")
+    print(t10 + "*      * * SUPER STAR TREK * *      *")
+    print(t10 + "*                                   *")
+    print(t10 + "*                                   *")
+    print(t10 + "*************************************")
+    for i in range(8):
+        print()
+
+def print_instructions():
+    # Back in the 70s, at this point, the user would be prompted to
+    # turn on their (printing) TTY to capture the output to hard copy.
+
+    print("      INSTRUCTIONS FOR 'SUPER STAR TREK'")
+    print()
+    print("1. WHEN YOU SEE \\COMMAND ?\\ PRINTED, ENTER ONE OF THE LEGAL")
+    print("     COMMANDS (NAV,SRS,LRS,PHA,TOR,SHE,DAM,COM, OR XXX).")
+    print("2. IF YOU SHOULD TYPE IN AN ILLEGAL COMMAND, YOU'LL GET A SHORT")
+    print("     LIST OF THE LEGAL COMMANDS PRINTED OUT.")
+    print("3. SOME COMMANDS REQUIRE YOU TO ENTER DATA (FOR EXAMPLE, THE")
+    print("     'NAV' COMMAND COMES BACK WITH 'COURSE (1-9) ?'.)  IF YOU")
+    print("     TYPE IN ILLEGAL DATA (LIKE NEGATIVE NUMBERS), THAN COMMAND")
+    print("     WILL BE ABORTED")
+    print()
+    print("     THE GALAXY IS DIVIDED INTO AN 8 X 8 QUADRANT GRID,")
+    print("AND EACH QUADRANT IS FURTHER DIVIDED INTO AN 8 X 8 SECTOR GRID.")
+    print()
+    print("     YOU WILL BE ASSIGNED A STARTING POINT SOMEWHERE IN THE")
+    print("GALAXY TO BEGIN A TOUR OF DUTY AS COMANDER OF THE STARSHIP")
+    print("\\ENTERPRISE\\; YOUR MISSION: TO SEEK AND DESTROY THE FLEET OF")
+    print("KLINGON WARWHIPS WHICH ARE MENACING THE UNITED FEDERATION OF")
+    print("PLANETS.")
+    print()
+    print("     YOU HAVE THE FOLLOWING COMMANDS AVAILABLE TO YOU AS CAPTAIN")
+    print("OF THE STARSHIP ENTERPRISE:")
+    print()
+    print("\\NAV\\ COMMAND = WARP ENGINE CONTROL --")
+    print("     COURSE IS IN A CIRCULAR NUMERICAL      4  3  2")
+    print("     VECTOR ARRANGEMENT AS SHOWN             . . .")
+    print("     INTEGER AND REAL VALUES MAY BE           ...")
+    print("     USED.  (THUS COURSE 1.5 IS HALF-     5 ---*--- 1")
+    print("     WAY BETWEEN 1 AND 2                      ...")
+    print("                                             . . .")
+    print("     VALUES MAY APPROACH 9.0, WHICH         6  7  8")
+    print("     ITSELF IS EQUIVALENT TO 1.0"         )
+    print("                                            COURSE")
+    print("     ONE WARP FACTOR IS THE SIZE OF ")
+    print("     ONE QUADTANT.  THEREFORE, TO GET")
+    print("     FROM QUADRANT 6,5 TO 5,5, YOU WOULD")
+    print("     USE COURSE 3, WARP FACTOR 1.")
+    print()
+    print("\\SRS\\ COMMAND = SHORT RANGE SENSOR SCAN")
+    print("     SHOWS YOU A SCAN OF YOUR PRESENT QUADRANT.")
+    print()
+    print("     SYMBOLOGY ON YOUR SENSOR SCREEN IS AS FOLLOWS:")
+    print("        <*> = YOUR STARSHIP'S POSITION")
+    print("        +K+ = KLINGON BATTLE CRUISER")
+    print("        >!< = FEDERATION STARBASE (REFUEL/REPAIR/RE-ARM HERE!)")
+    print("         *  = STAR")
+    print()
+    print("     A CONDENSED 'STATUS REPORT' WILL ALSO BE PRESENTED.")
+    print()
+    print("\\LRS\\ COMMAND = LONG RANGE SENSOR SCAN")
+    print("     SHOWS CONDITIONS IN SPACE FOR ONE QUADRANT ON EACH SIDE")
+    print("     OF THE ENTERPRISE (WHICH IS IN THE MIDDLE OF THE SCAN)")
+    print("     THE SCAN IS CODED IN THE FORM \\###\\, WHERE TH UNITS DIGIT")
+    print("     IS THE NUMBER OF STARS, THE TENS DIGIT IS THE NUMBER OF")
+    print("     STARBASES, AND THE HUNDRESDS DIGIT IS THE NUMBER OF")
+    print("     KLINGONS.")
+    print()
+    print("     EXAMPLE - 207 = 2 KLINGONS, NO STARBASES, & 7 STARS.")
+    print()
+    print("\\PHA\\ COMMAND = PHASER CONTROL.")
+    print("     ALLOWS YOU TO DESTROY THE KLINGON BATTLE CRUISERS BY ")
+    print("     ZAPPING THEM WITH SUITABLY LARGE UNITS OF ENERGY TO")
+    print("     DEPLETE THEIR SHIELD POWER.  (REMEMBER, KLINGONS HAVE")
+    print("     PHASERS TOO!)")
+    print()
+    print("\\TOR\\ COMMAND = PHOTON TORPEDO CONTROL")
+    print("     TORPEDO COURSE IS THE SAME AS USED IN WARP ENGINE CONTROL")
+    print("     IF YOU HIT THE KLINGON VESSEL, HE IS DESTROYED AND")
+    print("     CANNOT FIRE BACK AT YOU.  IF YOU MISS, YOU ARE SUBJECT TO")
+    print("     HIS PHASER FIRE.  IN EITHER CASE, YOU ARE ALSO SUBJECT TO ")
+    print("     THE PHASER FIRE OF ALL OTHER KLINGONS IN THE QUADRANT.")
+    print()
+    print("     THE LIBRARY-COMPUTER (\\COM\\ COMMAND) HAS AN OPTION TO ")
+    print("     COMPUTE TORPEDO TRAJECTORY FOR YOU (OPTION 2)")
+    print()
+    print("\\SHE\\ COMMAND = SHIELD CONTROL")
+    print("     DEFINES THE NUMBER OF ENERGY UNITS TO BE ASSIGNED TO THE")
+    print("     SHIELDS.  ENERGY IS TAKEN FROM TOTAL SHIP'S ENERGY.  NOTE")
+    print("     THAN THE STATUS DISPLAY TOTAL ENERGY INCLUDES SHIELD ENERGY")
+    print()
+    print("\\DAM\\ COMMAND = DAMMAGE CONTROL REPORT")
+    print("     GIVES THE STATE OF REPAIR OF ALL DEVICES.  WHERE A NEGATIVE")
+    print("     'STATE OF REPAIR' SHOWS THAT THE DEVICE IS TEMPORARILY")
+    print("     DAMAGED.")
+    print()
+    print("\\COM\\ COMMAND = LIBRARY-COMPUTER")
+    print("     THE LIBRARY-COMPUTER CONTAINS SIX OPTIONS:")
+    print("     OPTION 0 = CUMULATIVE GALACTIC RECORD")
+    print("        THIS OPTION SHOWES COMPUTER MEMORY OF THE RESULTS OF ALL")
+    print("        PREVIOUS SHORT AND LONG RANGE SENSOR SCANS")
+    print("     OPTION 1 = STATUS REPORT")
+    print("        THIS OPTION SHOWS THE NUMBER OF KLINGONS, STARDATES,")
+    print("        AND STARBASES REMAINING IN THE GAME.")
+    print("     OPTION 2 = PHOTON TORPEDO DATA")
+    print("        WHICH GIVES DIRECTIONS AND DISTANCE FROM THE ENTERPRISE")
+    print("        TO ALL KLINGONS IN YOUR QUADRANT")
+    print("     OPTION 3 = STARBASE NAV DATA")
+    print("        THIS OPTION GIVES DIRECTION AND DISTANCE TO ANY ")
+    print("        STARBASE WITHIN YOUR QUADRANT")
+    print("     OPTION 4 = DIRECTION/DISTANCE CALCULATOR")
+    print("        THIS OPTION ALLOWS YOU TO ENTER COORDINATES FOR")
+    print("        DIRECTION/DISTANCE CALCULATIONS")
+    print("     OPTION 5 = GALACTIC /REGION NAME/ MAP")
+    print("        THIS OPTION PRINTS THE NAMES OF THE SIXTEEN MAJOR ")
+    print("        GALACTIC REGIONS REFERRED TO IN THE GAME.")
+    
+    
+
+def main():
+    print_header()
+    if not get_yes_no("DO YOU NEED INSTRUCTIONS (Y/N)? "):
+        return
+    print_instructions()
+
+if __name__ == "__main__":
+    main()
diff --git a/84 Super Star Trek/superstartrekins.bas b/84 Super Star Trek/superstartrekins.bas
index 4e145633..9f5f3a33 100644
--- a/84 Super Star Trek/superstartrekins.bas	
+++ b/84 Super Star Trek/superstartrekins.bas	
@@ -75,7 +75,7 @@
 720 PRINT"\PHA\ COMMAND = PHASER CONTROL."
 730 PRINT"     ALLOWS YOU TO DESTROY THE KLINGON BATTLE CRUISERS BY "
 740 PRINT"     ZAPPING THEM WITH SUITABLY LARGE UNITS OF ENERGY TO"
-750 PRINT"     DEPLETE THEIR SHIELD POWER.  (REMBER, KLINGONS HAVE"
+750 PRINT"     DEPLETE THEIR SHIELD POWER.  (REMEMBER, KLINGONS HAVE"
 760 PRINT"     PHASERS TOO!)"
 770 PRINT
 780 PRINT"\TOR\ COMMAND = PHOTON TORPEDO CONTROL"

From 212a1c292d5d56d543a7f0157b673fc184b45a5a Mon Sep 17 00:00:00 2001
From: Gustavo Carreno <guscarreno@gmail.com>
Date: Fri, 5 Mar 2021 17:25:46 +0000
Subject: [PATCH 241/749] Adding port of 02 Amazing to pascal object-pascal

Adding complete implementation of 02 Amazing in Object-Pascal
---
 02 Amazing/pascal/object-pascal/amazing.lpi   |  71 +++++
 02 Amazing/pascal/object-pascal/amazing.pas   |  17 ++
 .../object-pascal/amazingapplication.pas      | 104 +++++++
 02 Amazing/pascal/object-pascal/maze.pas      | 280 ++++++++++++++++++
 02 Amazing/pascal/object-pascal/room.pas      |  71 +++++
 5 files changed, 543 insertions(+)
 create mode 100644 02 Amazing/pascal/object-pascal/amazing.lpi
 create mode 100644 02 Amazing/pascal/object-pascal/amazing.pas
 create mode 100644 02 Amazing/pascal/object-pascal/amazingapplication.pas
 create mode 100644 02 Amazing/pascal/object-pascal/maze.pas
 create mode 100644 02 Amazing/pascal/object-pascal/room.pas

diff --git a/02 Amazing/pascal/object-pascal/amazing.lpi b/02 Amazing/pascal/object-pascal/amazing.lpi
new file mode 100644
index 00000000..0c53b6db
--- /dev/null
+++ b/02 Amazing/pascal/object-pascal/amazing.lpi	
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="12"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <Title Value="amazing"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+    </RunParams>
+    <Units Count="4">
+      <Unit0>
+        <Filename Value="amazing.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="amazingapplication.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="AmazingApplication"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="maze.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="Maze"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="room.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="Room"/>
+      </Unit3>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="amazing"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>
diff --git a/02 Amazing/pascal/object-pascal/amazing.pas b/02 Amazing/pascal/object-pascal/amazing.pas
new file mode 100644
index 00000000..716bd1da
--- /dev/null
+++ b/02 Amazing/pascal/object-pascal/amazing.pas	
@@ -0,0 +1,17 @@
+program amazing;
+
+{$IFDEF FPC}
+{$mode ObjFPC}{$H+}
+{$ENDIF}
+
+uses
+  AmazingApplication, maze, Room;
+
+var
+  AmazingApp: TAmazingApplication;
+
+begin
+  AmazingApp:= TAmazingApplication.Create;
+  AmazingApp.Run;
+end.
+
diff --git a/02 Amazing/pascal/object-pascal/amazingapplication.pas b/02 Amazing/pascal/object-pascal/amazingapplication.pas
new file mode 100644
index 00000000..1431fd67
--- /dev/null
+++ b/02 Amazing/pascal/object-pascal/amazingapplication.pas	
@@ -0,0 +1,104 @@
+unit AmazingApplication;
+
+{$IFDEF FPC}
+{$mode ObjFPC}{$H+}
+{$ENDIF}
+
+interface
+
+uses
+  Classes
+, SysUtils
+, Crt
+, Maze
+;
+
+type
+{ TAmazingApplication }
+  TAmazingApplication = class(TObject)
+  private
+    FMaze: TMaze;
+
+    procedure PrintGreeting;
+    procedure GetDimensions;
+    procedure BuildMaze;
+    procedure PrintMaze;
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    procedure Run;
+  published
+  end;
+
+implementation
+
+{ TAmazingApplication }
+
+procedure TAmazingApplication.PrintGreeting;
+begin
+  WriteLN(' ':28, 'AMAZING PROGRAM');
+  WriteLN(' ':15, 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY');
+  WriteLN;
+  WriteLN;
+  WriteLN;
+  WriteLN;
+end;
+
+procedure TAmazingApplication.GetDimensions;
+var
+  width: Integer;
+  length: Integer;
+begin
+  repeat
+    Write('WHAT ARE YOUR WIDTH AND LENGTH (SPACE IN BETWEEN): ');
+    ReadLN(width, length);
+    if (width = 1) or (length = 1) then
+    begin
+      WriteLN('MEANINGLESS DIMENSIONS.  TRY AGAIN.');
+    end;
+  until (width > 1) and (length > 1);
+  FMaze:= TMaze.Create(width, length);
+  WriteLN;
+  WriteLN;
+  WriteLN;
+  WriteLN;
+end;
+
+procedure TAmazingApplication.BuildMaze;
+begin
+  FMaze.Build;
+end;
+
+procedure TAmazingApplication.PrintMaze;
+begin
+  FMaze.Print;
+  WriteLN;
+end;
+
+constructor TAmazingApplication.Create;
+begin
+  //
+end;
+
+destructor TAmazingApplication.Destroy;
+begin
+  if Assigned(FMaze) then
+  begin
+    FMaze.Free;
+  end;
+  inherited Destroy;
+end;
+
+procedure TAmazingApplication.Run;
+begin
+  //ClrScr;
+  PrintGreeting;
+  GetDimensions;
+  BuildMaze;
+  PrintMaze;
+end;
+
+end.
+
diff --git a/02 Amazing/pascal/object-pascal/maze.pas b/02 Amazing/pascal/object-pascal/maze.pas
new file mode 100644
index 00000000..1f5b3247
--- /dev/null
+++ b/02 Amazing/pascal/object-pascal/maze.pas	
@@ -0,0 +1,280 @@
+unit Maze;
+
+{$IFDEF FPC}
+{$mode ObjFPC}{$H+}
+{$ENDIF}
+
+interface
+
+uses
+  Classes
+, SysUtils
+, Room
+;
+
+type
+  TDirection = (dUp, dRight, dDown, dLeft);
+  TDirections = set of TDirection;
+{ TMaze }
+  TMaze = class(TObject)
+  private
+    FWidth: Integer;
+    FLength: Integer;
+    FEntry: Integer;
+    FLabyrinth: Array of Array of TRoom;
+
+    function GetRandomDirection(const ADirections: TDirections): TDirection;
+
+    procedure DebugVisited;
+    procedure DebugWalls;
+  protected
+  public
+    constructor Create(const AWidth, ALength: Integer);
+    destructor Destroy; override;
+
+    procedure Build;
+    procedure Print;
+  published
+  end;
+
+implementation
+
+const
+  EXIT_DOWN  = 1;
+  EXIT_RIGHT = 2;
+
+{ TMaze }
+
+function TMaze.GetRandomDirection(const ADirections: TDirections): TDirection;
+var
+  count: Integer;
+  position: Integer;
+  directions: array [0..3] of TDirection;
+begin
+  count:= 0;
+  position:= 0;
+  if dUp in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dUp;
+    Inc(position);
+  end;
+  if dRight in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dRight;
+    Inc(position);
+  end;
+  if dDown in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dDown;
+    Inc(position);
+  end;
+  if dLeft in ADirections then
+  begin
+    Inc(count);
+    directions[position]:= dLeft;
+    Inc(position);
+  end;
+  Result:= directions[Random(count)];
+end;
+
+procedure TMaze.DebugVisited;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  WriteLN('Visited');
+  for indexL:= 0 to Pred(FLength) do
+  begin
+    for indexW:= 0 to Pred(FWidth) do
+    begin
+      Write(FLabyrinth[indexW][indexL].Visited:3,' ');
+    end;
+    WriteLN;
+  end;
+  WriteLN;
+end;
+
+procedure TMaze.DebugWalls;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  WriteLN('Walls');
+  for indexL:= 0 to Pred(FLength) do
+  begin
+    for indexW:= 0 to Pred(FWidth) do
+    begin
+      Write(FLabyrinth[indexW][indexL].Walls:3,' ');
+    end;
+    WriteLN;
+  end;
+  WriteLN;
+end;
+
+constructor TMaze.Create(const AWidth, ALength: Integer);
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  Randomize;
+  FWidth:= AWidth;
+  FLength:= ALength;
+  FEntry:= Random(FWidth);
+  SetLength(FLabyrinth, FWidth, FLength);
+  for indexW:= 0 to Pred(FWidth) do
+  begin
+    for indexL:= 0 to Pred(FLength) do
+    begin
+      FLabyrinth[indexW][indexL]:= TRoom.Create;
+    end;
+  end;
+end;
+
+destructor TMaze.Destroy;
+var
+  indexW: Integer;
+  indexL: Integer;
+begin
+  for indexW:= 0 to Pred(FWidth) do
+  begin
+    for indexL:= 0 to Pred(FLength) do
+    begin
+      if Assigned(FLabyrinth[indexW][indexL]) then
+      begin
+        FLabyrinth[indexW][indexL].Free;
+      end;
+    end;
+  end;
+  inherited Destroy;
+end;
+
+procedure TMaze.Build;
+var
+  indexW: Integer;
+  indexL: Integer;
+  direction: TDirection;
+  directions: TDirections;
+  count: Integer;
+begin
+  FEntry:= Random(FWidth);
+  indexW:= FEntry;
+  indexL:= 0;
+  count:= 1;
+  FLabyrinth[indexW][indexL].Visited:= count;
+  Inc(count);
+  repeat
+    directions:= [dUp, dRight, dDown, dLeft];
+    if (indexW = 0) or (FLabyrinth[Pred(indexW)][indexL].Visited <> 0) then
+    begin
+      Exclude(directions, dLeft);
+    end;
+    if (indexL = 0) or (FLabyrinth[indexW][Pred(indexL)].Visited <> 0) then
+    begin
+      Exclude(directions, dUp);
+    end;
+    if (indexW = Pred(FWidth)) or (FLabyrinth[Succ(indexW)][indexL].Visited <> 0) then
+    begin
+      Exclude(directions, dRight);
+    end;
+    if (indexL = Pred(FLength)) or (FLabyrinth[indexW][Succ(indexL)].Visited <> 0) then
+    begin
+      Exclude(directions, dDown);
+    end;
+
+    if directions <> [] then
+    begin
+      direction:= GetRandomDirection(directions);
+      case direction of
+        dLeft:begin
+          Dec(indexW);
+          FLabyrinth[indexW][indexL].Walls:= EXIT_RIGHT;
+        end;
+        dUp:begin
+          Dec(indexL);
+          FLabyrinth[indexW][indexL].Walls:= EXIT_DOWN;
+        end;
+        dRight:begin
+          FLabyrinth[indexW][indexL].Walls:= FLabyrinth[indexW][indexL].Walls + EXIT_RIGHT;
+          Inc(indexW);
+        end;
+        dDown:begin
+          FLabyrinth[indexW][indexL].Walls:= FLabyrinth[indexW][indexL].Walls + EXIT_DOWN;
+          Inc(indexL);
+        end;
+      end;
+      FLabyrinth[indexW][indexL].Visited:= count;
+      Inc(count);
+    end
+    else
+    begin
+      while True do
+      begin
+        if indexW <> Pred(FWidth) then
+        begin
+          Inc(indexW);
+        end
+        else if indexL <> Pred(FLength) then
+        begin
+          Inc(indexL);
+          indexW:= 0;
+        end
+        else
+        begin
+          indexW:= 0;
+          indexL:= 0;
+        end;
+        if FLabyrinth[indexW][indexL].Visited <> 0 then
+        begin
+          break;
+        end;
+      end;
+    end;
+  until count = (FWidth * FLength) + 1;
+  indexW:= Random(FWidth);
+  indexL:= Pred(FLength);
+  FLabyrinth[indexW][indexL].Walls:= FLabyrinth[indexW][indexL].Walls + 1;
+end;
+
+procedure TMaze.Print;
+var
+  indexW:Integer;
+  indexL: Integer;
+begin
+
+  //DebugVisited;
+  //DebugWalls;
+
+  for indexW:= 0 to Pred(FWidth) do
+  begin
+    if indexW = FEntry then
+    begin
+      Write('.  ');
+    end
+    else
+    begin
+      Write('.--');
+    end;
+  end;
+  WriteLN('.');
+
+  for indexL:= 0 to Pred(FLength) do
+  begin
+    Write('I');
+    for indexW:= 0 to Pred(FWidth) do
+    begin
+      FLabyrinth[indexW][indexL].PrintRoom;
+    end;
+    WriteLN;
+    for indexW:= 0 to Pred(FWidth) do
+    begin
+      FLabyrinth[indexW][indexL].PrintWall;
+    end;
+    WriteLN('.');
+  end;
+end;
+
+end.
+
diff --git a/02 Amazing/pascal/object-pascal/room.pas b/02 Amazing/pascal/object-pascal/room.pas
new file mode 100644
index 00000000..f0b74103
--- /dev/null
+++ b/02 Amazing/pascal/object-pascal/room.pas	
@@ -0,0 +1,71 @@
+unit Room;
+
+{$IFDEF FPC}
+{$mode ObjFPC}{$H+}
+{$ENDIF}
+
+interface
+
+uses
+  Classes
+, SysUtils
+;
+
+type
+{ TRoom }
+  TRoom = class(TObject)
+  private
+    FVisited: Integer;
+    FWalls: Integer;
+  protected
+  public
+    constructor Create;
+
+    procedure PrintRoom;
+    procedure PrintWall;
+
+    property Visited: Integer
+      read FVisited
+      write FVisited;
+    property Walls: Integer
+      read FWalls
+      write FWalls;
+  published
+  end;
+
+implementation
+
+{ TRoom }
+
+constructor TRoom.Create;
+begin
+  FVisited:= 0;
+  FWalls:= 0;
+end;
+
+procedure TRoom.PrintRoom;
+begin
+  if FWalls < 2 then
+  begin
+    Write('  I');
+  end
+  else
+  begin
+    Write('   ');
+  end;
+end;
+
+procedure TRoom.PrintWall;
+begin
+  if (FWalls = 0) or (FWalls = 2) then
+  begin
+    Write(':--');
+  end
+  else
+  begin
+    Write(':  ');
+  end;
+end;
+
+end.
+

From 56f3875b49e6cbe363a13d1d1d52573a3e28f1b9 Mon Sep 17 00:00:00 2001
From: Haydn Kane <haydn@tanjecterly.co.uk>
Date: Fri, 5 Mar 2021 22:06:36 +0000
Subject: [PATCH 242/749] C# port of MathDice

---
 61 Math Dice/csharp/GameState.cs        |   8 ++
 61 Math Dice/csharp/MathDice.csproj     |   9 ++
 61 Math Dice/csharp/MathDice.sln        |  25 +++++
 61 Math Dice/csharp/Program.cs          | 121 ++++++++++++++++++++++++
 61 Math Dice/csharp/README.md           |   7 ++
 61 Math Dice/csharp/StringExtensions.cs |  15 +++
 6 files changed, 185 insertions(+)
 create mode 100644 61 Math Dice/csharp/GameState.cs
 create mode 100644 61 Math Dice/csharp/MathDice.csproj
 create mode 100644 61 Math Dice/csharp/MathDice.sln
 create mode 100644 61 Math Dice/csharp/Program.cs
 create mode 100644 61 Math Dice/csharp/StringExtensions.cs

diff --git a/61 Math Dice/csharp/GameState.cs b/61 Math Dice/csharp/GameState.cs
new file mode 100644
index 00000000..ef538781
--- /dev/null
+++ b/61 Math Dice/csharp/GameState.cs	
@@ -0,0 +1,8 @@
+namespace MathDice
+{
+    public enum GameState
+    {
+        FirstAttempt = 0,
+        SecondAttempt = 1,
+    }
+}
diff --git a/61 Math Dice/csharp/MathDice.csproj b/61 Math Dice/csharp/MathDice.csproj
new file mode 100644
index 00000000..38aa472a
--- /dev/null
+++ b/61 Math Dice/csharp/MathDice.csproj	
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net5.0</TargetFramework>
+    <RootNamespace>MathDice</RootNamespace>
+  </PropertyGroup>
+
+</Project>
diff --git a/61 Math Dice/csharp/MathDice.sln b/61 Math Dice/csharp/MathDice.sln
new file mode 100644
index 00000000..4efc8c9c
--- /dev/null
+++ b/61 Math Dice/csharp/MathDice.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31025.194
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MathDice", "MathDice.csproj", "{4F28D7EB-3CD6-434F-B643-0CEA5F09F96D}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{4F28D7EB-3CD6-434F-B643-0CEA5F09F96D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4F28D7EB-3CD6-434F-B643-0CEA5F09F96D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4F28D7EB-3CD6-434F-B643-0CEA5F09F96D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4F28D7EB-3CD6-434F-B643-0CEA5F09F96D}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {A1337DCA-4EFA-45EE-A1A9-22E37E74F362}
+	EndGlobalSection
+EndGlobal
diff --git a/61 Math Dice/csharp/Program.cs b/61 Math Dice/csharp/Program.cs
new file mode 100644
index 00000000..e755f1f2
--- /dev/null
+++ b/61 Math Dice/csharp/Program.cs	
@@ -0,0 +1,121 @@
+using System;
+
+namespace MathDice
+{
+    public static class Program
+    {
+        readonly static Random random = new Random();
+
+        static int DieOne = 0;
+        static int DieTwo = 0;
+
+        private const string NoPips = "I     I";
+        private const string LeftPip = "I *   I";
+        private const string CentrePip = "I  *  I";
+        private const string RightPip = "I   * I";
+        private const string TwoPips = "I * * I";
+        private const string Edge = " ----- ";
+
+        static void Main(string[] args)
+        {
+            int answer;
+
+            GameState gameState = GameState.FirstAttempt;
+
+            Console.WriteLine("MATH DICE".CentreAlign());
+            Console.WriteLine("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY".CentreAlign());
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE.");
+            Console.WriteLine("WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION");
+            Console.WriteLine("MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY.");
+            Console.WriteLine("TO CONCLUDE THE LESSON, TYPE CONTROL-C AS YOUR ANSWER.");
+            Console.WriteLine();
+            Console.WriteLine();
+
+            while (true)
+            {
+                if (gameState == GameState.FirstAttempt)
+                {
+                    Roll(ref DieOne);
+                    Roll(ref DieTwo);
+
+                    DrawDie(DieOne);
+                    Console.WriteLine("   +");
+                    DrawDie(DieTwo);
+                }
+
+                answer = GetAnswer();
+
+                if (answer == DieOne + DieTwo)
+                {
+                    Console.WriteLine("RIGHT!");
+                    Console.WriteLine();
+                    Console.WriteLine("THE DICE ROLL AGAIN...");
+
+                    gameState = GameState.FirstAttempt;
+                }
+                else
+                {
+                    if (gameState == GameState.FirstAttempt)
+                    {
+                        Console.WriteLine("NO, COUNT THE SPOTS AND GIVE ANOTHER ANSWER.");
+                        gameState = GameState.SecondAttempt;
+                    }
+                    else
+                    {
+                        Console.WriteLine($"NO, THE ANSWER IS{DieOne + DieTwo}");
+                        Console.WriteLine();
+                        Console.WriteLine("THE DICE ROLL AGAIN...");
+                        gameState = GameState.FirstAttempt;
+                    }
+                }
+            }
+        }
+
+        private static int GetAnswer()
+        {
+            int answer;
+
+            Console.Write("      =?");
+            var input = Console.ReadLine();
+
+            int.TryParse(input, out answer);
+
+            return answer;
+        }
+
+        private static void DrawDie(int pips)
+        {
+            Console.WriteLine(Edge);
+            Console.WriteLine(OuterRow(pips, true));
+            Console.WriteLine(CentreRow(pips));
+            Console.WriteLine(OuterRow(pips, false));
+            Console.WriteLine(Edge);
+            Console.WriteLine();
+        }
+
+        private static void Roll(ref int die) => die = random.Next(1, 7);
+
+        private static string OuterRow(int pips, bool top)
+        {
+            return pips switch
+            {
+                1 => NoPips,
+                var x when x == 2 || x == 3 => top ? LeftPip : RightPip,
+                _ => TwoPips
+            };
+        }
+
+        private static string CentreRow(int pips)
+        {
+            return pips switch
+            {
+                var x when x == 2 || x == 4 => NoPips,
+                6 => TwoPips,
+                _ => CentrePip
+            };
+        }
+    }
+}
diff --git a/61 Math Dice/csharp/README.md b/61 Math Dice/csharp/README.md
index 4daabb5c..7017b45a 100644
--- a/61 Math Dice/csharp/README.md	
+++ b/61 Math Dice/csharp/README.md	
@@ -1,3 +1,10 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
 Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/)
+
+Conversion Notes
+
+- There are minor spacing issues which have been preserved in this port.
+- This implementation uses switch expressions to concisely place the dice pips in the right place.
+- Random() is only pseudo-random but perfectly adequate for the purposes of simulating dice rolls.
+- Console width is assumed to be 120 chars for the purposes of centrally aligned the intro text.
\ No newline at end of file
diff --git a/61 Math Dice/csharp/StringExtensions.cs b/61 Math Dice/csharp/StringExtensions.cs
new file mode 100644
index 00000000..b87ed30c
--- /dev/null
+++ b/61 Math Dice/csharp/StringExtensions.cs	
@@ -0,0 +1,15 @@
+namespace MathDice
+{
+    public static class StringExtensions
+    {
+        private const int ConsoleWidth = 120; // default console width
+
+        public static string CentreAlign(this string value)
+        {
+            int spaces = ConsoleWidth - value.Length;
+            int leftPadding = spaces / 2 + value.Length;
+
+            return value.PadLeft(leftPadding).PadRight(ConsoleWidth);
+        }
+    }
+}

From 68ebd50b83fe5dbee6865546ad321005786d5e63 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Sat, 6 Mar 2021 09:35:13 +1030
Subject: [PATCH 243/749] Final bugfixes and remove test output code

---
 43 Hammurabi/java/src/Hamurabi.java | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/43 Hammurabi/java/src/Hamurabi.java b/43 Hammurabi/java/src/Hamurabi.java
index 6e2d1cee..a8bf8b74 100644
--- a/43 Hammurabi/java/src/Hamurabi.java	
+++ b/43 Hammurabi/java/src/Hamurabi.java	
@@ -33,7 +33,6 @@ public class Hamurabi {
     private int ratsAte;
     private double peopleFed;
     private double percentageStarved;
-    private int acresToPlant;
     private int bushelsToFeedPeople;
 
     // Used for keyboard input
@@ -91,7 +90,6 @@ public class Hamurabi {
                     ratsAte = INITIAL_HARVEST - INITIAL_BUSHELS;
                     peopleFed = 0;
                     percentageStarved = 0;
-                    acresToPlant = 0;
                     bushelsToFeedPeople = 0;
 
                     gameState = GAME_STATE.YEAR_CYCLE;
@@ -179,7 +177,7 @@ public class Hamurabi {
 
                 case PLANT_SEED:
 
-                    acresToPlant = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED ? ");
+                    int acresToPlant = displayTextAndGetNumber("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED ? ");
                     if (acresToPlant < 0) {
                         gameState = GAME_STATE.FINISH_GAME;
                     }
@@ -230,7 +228,6 @@ public class Hamurabi {
                         starvedInAYear = 0;
                         gameState = GAME_STATE.YEAR_CYCLE;
                     } else {
-                        System.out.println("STARVED = " + starved);
                         starvedInAYear = (int) starved;
                         starvedOverall += starvedInAYear;
                         if (starved > MAX_STARVATION_IN_A_YEAR * population) {
@@ -238,7 +235,6 @@ public class Hamurabi {
                             gameState = GAME_STATE.FINISH_GAME;
                         } else {
                             percentageStarved = ((year - 1) * percentageStarved + starved * 100 / population) / year;
-                            System.out.println("PERCENTAGE STARVED = " + percentageStarved);
                             population = (int) peopleFed;
                             gameState = GAME_STATE.YEAR_CYCLE;
                         }
@@ -252,7 +248,7 @@ public class Hamurabi {
 
                     int acresPerPerson = acres / population;
 
-                    System.out.println("IN YOUR 10-YEAR TERM OF OFFICE," + percentageStarved + " PERCENT OF THE");
+                    System.out.println("IN YOUR 10-YEAR TERM OF OFFICE," + String.format("%.2f", percentageStarved) + "% PERCENT OF THE");
                     System.out.println("POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF");
                     System.out.println(starvedOverall + " PEOPLE DIED!!");
                     System.out.println("YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH");
@@ -298,7 +294,7 @@ public class Hamurabi {
 
     private void couldHaveBeenBetterMessage() {
         System.out.println("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT");
-        System.out.println("REALLY WASN'T TOO BAD AT ALL. " + (int) (Math.random() * (population * .8)) + "PEOPLE");
+        System.out.println("REALLY WASN'T TOO BAD AT ALL. " + (int) (Math.random() * (population * .8)) + " PEOPLE");
         System.out.println("WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR");
         System.out.println("TRIVIAL PROBLEMS.");
     }

From 40aa35f347fb282c1c4d96e7a958d6526ad8a1d2 Mon Sep 17 00:00:00 2001
From: nanochess <biyubi@gmail.com>
Date: Fri, 5 Mar 2021 17:07:22 -0600
Subject: [PATCH 244/749] Ported HI-LO to Javascript

---
 47 Hi-Lo/javascript/hi-lo.html |  9 ++++
 47 Hi-Lo/javascript/hi-lo.js   | 96 ++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)
 create mode 100644 47 Hi-Lo/javascript/hi-lo.html
 create mode 100644 47 Hi-Lo/javascript/hi-lo.js

diff --git a/47 Hi-Lo/javascript/hi-lo.html b/47 Hi-Lo/javascript/hi-lo.html
new file mode 100644
index 00000000..2610591d
--- /dev/null
+++ b/47 Hi-Lo/javascript/hi-lo.html	
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>HI-LO
+
+
+

+
+
+
diff --git a/47 Hi-Lo/javascript/hi-lo.js b/47 Hi-Lo/javascript/hi-lo.js
new file mode 100644
index 00000000..fc7b1dbf
--- /dev/null
+++ b/47 Hi-Lo/javascript/hi-lo.js	
@@ -0,0 +1,96 @@
+// HI-LO
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "HI LO\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("THIS IS THE GAME OF HI LO.\n");
+    print("\n");
+    print("YOU WILL HAVE 6 TRIES TO GUESS THE AMOUNT OF MONEY IN THE\n");
+    print("HI LO JACKPOT, WHICH IS BETWEEN 1 AND 100 DOLLARS.  IF YOU\n");
+    print("GUESS THE AMOUNT, YOU WIN ALL THE MONEY IN THE JACKPOT!\n");
+    print("THEN YOU GET ANOTHER CHANCE TO WIN MORE MONEY.  HOWEVER,\n");
+    print("IF YOU DO NOT GUESS THE AMOUNT, THE GAME ENDS.\n");
+    print("\n");
+    r = 0;
+    while (1) {
+        b = 0;
+        print("\n");
+        y = Math.floor(100 * Math.random());
+        for (b = 1; b <= 6; b++) {
+            print("YOUR GUESS");
+            a = parseInt(await input());
+            if (a < y) {
+                print("YOUR GUESS IS TOO LOW.\n");
+            } else if (a > y) {
+                print("YOUR GUESS IS TOO HIGH.\n");
+            } else {
+                break;
+            }
+            print("\n");
+        }
+        if (b > 6) {
+            print("YOU BLEW IT...TOO BAD...THE NUMBER WAS " + y + "\n");
+            r = 0;
+        } else {
+            print("GOT IT!!!!!!!!!!   YOU WIN " + y + " DOLLARS.\n");
+            r += y;
+            print("YOUR TOTAL WINNINGS ARE NOW " + r + " DOLLARS.\n");
+        }
+        print("\n");
+        print("PLAY AGAIN (YES OR NO)");
+        str = await input();
+        if (str != "YES")
+            break;
+    }
+    print("\n");
+    print("SO LONG.  HOPE YOU ENJOYED YOURSELF!!!\n");
+}
+
+main();

From 5035c0eca2e54af83154ac91463788917176231a Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Fri, 5 Mar 2021 15:56:24 -0800
Subject: [PATCH 245/749] Begin porting LUNAR to python

got much of the structure moved around, but the flow isn't right yet. Probably will refactor to be object-oriented.
---
 59 Lunar LEM Rocket/lunar.bas       |   6 +-
 59 Lunar LEM Rocket/python/lunar.py | 206 ++++++++++++++++++++++++++++
 2 files changed, 209 insertions(+), 3 deletions(-)
 create mode 100644 59 Lunar LEM Rocket/python/lunar.py

diff --git a/59 Lunar LEM Rocket/lunar.bas b/59 Lunar LEM Rocket/lunar.bas
index 17b8ed11..db07b0a5 100644
--- a/59 Lunar LEM Rocket/lunar.bas	
+++ b/59 Lunar LEM Rocket/lunar.bas	
@@ -18,7 +18,7 @@
 170 IF T<1E-03 THEN 150
 180 S=T: IF M>=N+S*K THEN 200
 190 S=(M-N)/K
-200 GOSUB 420: IF I<=O THEN 340
+200 GOSUB 420: IF I<=0 THEN 340
 210 IF V<=0 THEN 230
 220 IF J<0 THEN 370
 230 GOSUB 330: GOTO 160
@@ -26,12 +26,12 @@
 250 V=V+G*S: L=L+S
 260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH" 
 274 IF W<=1.2 THEN PRINT "PERFECT LANDING!": GOTO 440 
-280 IF W<=10 THEN PRINT "GOOD LANDING (COULD RE BETTER)":GOTO 440 
+280 IF W<=10 THEN PRINT "GOOD LANDING (COULD BE BETTER)":GOTO 440 
 282 IF W>60 THEN 300
 284 PRINT "CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE" 
 286 PRINT "PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!" 
 288 GOTO 440
-300 PRINT "SORRY THERE NERE NO SURVIVORS. YOU BLOW IT!"
+300 PRINT "SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!"
 310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"
 320 GOTO 440
 330 L=L+S: T=T-S: M=M-S*K: A=I: V=J: RETURN
diff --git a/59 Lunar LEM Rocket/python/lunar.py b/59 Lunar LEM Rocket/python/lunar.py
new file mode 100644
index 00000000..da2329ef
--- /dev/null
+++ b/59 Lunar LEM Rocket/python/lunar.py	
@@ -0,0 +1,206 @@
+"""
+LUNAR
+
+Lunar landing simulation
+
+Ported by Dave LeCompte
+"""
+
+PAGE_WIDTH = 64
+
+
+def print_centered(msg):
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
+
+
+def print_header(title):
+    print_centered(title)
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+
+def print_instructions():
+    print("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR")
+    print("LANDING CAPSULE.")
+    print()
+    print()
+    print("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY")
+    print("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.")
+    print()
+
+def print_intro():
+    print("SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN")
+    print("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.")
+    print("SET NEW BURN RATE EVERY 10 SECONDS.")
+    print()
+    print("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.")
+    print()
+    print()
+    print()
+    print("GOOD LUCK")
+    print()
+
+def show_landing(l, v):
+    w = 3600 * v
+    print("ON MOON AT {l} SECONDS - IMPACT VELOCITY {w} MPH")
+    if w < 1.2:
+        print("PERFECT LANDING!")
+    elif w < 10:
+        print("GOOD LANDING (COULD BE BETTER)")
+    elif w <= 60:
+        print("CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE")
+        print("PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!")
+    else:
+        print("SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!")
+        print("IN FACT, YOU BLASTED A NEW LUNAR CRATER {w*.227:.4f} FEET DEEP!")
+    end_sim()
+
+        
+def update_physics():
+    # line 330
+    elapsed_time += delta_t
+    time_to_prompt -= delta_t
+    m = m - delta_t * k
+    a = i
+    v = j
+    return
+
+def update_burn():
+    # line 420
+    q = delta_t * k / m
+    j = (v +
+         g * delta_t +
+         z * (-q - q*q/2 - q**3/3 - q**4/4 - q**5/5))
+    i = (a -
+         g * delta_t * delta_t/2 -
+         v * delta_t +
+         z * delta_t * (q / 2 +
+                        q ** 2 / 6 +
+                        q ** 3 / 12 +
+                        q ** 4 / 20 +
+                        q ** 5 / 30))
+
+    return q,j,i
+
+def end_sim():
+    print()
+    print()
+    print()
+    print("TRY AGAIN??")
+
+
+def prompt_for_burn():
+    # line 150
+    print("{l}\t{a}\t{int(5280*(a-int(a)))}\t{3600 * v}\t{m-n}")
+    k = input()
+
+def run_simulation():
+    print()
+    print("SEC\tMI + FT\tMPH\tLB FUEL\tBURN RATE")
+    print()
+    
+    elapsed_time = 0
+    a = 120
+    v = 1 
+    m = 33000 # mass of capsule with fuel
+    n = 16500 # mass of capsule without fuel
+    g = 1e-3
+    z = 1.8
+
+    k = prompt_for_burn()
+    time_to_prompt = 10
+
+    while True:
+        # line 160
+        if M-N < 1e-3:
+            # line 240
+            print(f"FUEL OUT AT {elapsed_time} SECONDS")
+            delta_t = (-v + math.sqrt(v*v + 2*a*g)) / g
+            v += g * delta_t
+            elapsed_time += delta_t
+            show_landing(elapsed_time, v)
+            return
+
+        if t < 1e-3:
+            k = prompt_for_burn()
+            continue
+
+        # line 180
+        delta_t = time_to_prompt
+        if m < n + delta_t * k:
+            delta_t = (m-n) / k
+            
+        # line 200
+        q,j,i = update_burn()
+
+        if i <= 0:
+            # line 340
+            while True:
+                if delta_t < 5e-3:
+                    show_landing(elapsed_time, v)
+                #line 350
+                d = v + math.sqrt(v*v + 2*a*(g-z*k/m))
+                delta_t = 2 * a / d
+                update_burn()
+                update_physics()
+
+        else:
+            # line 210
+            if ((v > 0) and (j < 0)):
+                GOTO 370
+            # line 230
+            update_physics()
+
+
+
+        
+        
+
+
+def main():
+    print_header("LUNAR")
+    print_instructions()
+    while True:
+        print_intro()
+        run_simulation()
+        
+
+"""
+120 L=0
+130 PRINT: PRINT "SEC","MI + FT","MPH","LB FUEL","BURN RATE":PRINT 
+140 A=120:V=1:M=33000:N=16500:G=1E-03:Z=1.8
+150 PRINT L,INT(A);INT(5280*(A-INT(A))),3600*V,M-N,:INPUT K:T=10 
+160 IF M-N<1E-03 THEN 240
+170 IF T<1E-03 THEN 150
+180 S=T: IF M>=N+S*K THEN 200
+190 S=(M-N)/K
+200 GOSUB 420: IF I<=O THEN 340
+210 IF V<=0 THEN 230
+220 IF J<0 THEN 370
+230 GOSUB 330: GOTO 160
+240 PRINT "FUEL OUT AT";L;"SECONDS":S=(-V+SQR(V*V+2*A*G))/G
+250 V=V+G*S: L=L+S
+260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH" 
+274 IF W<=1.2 THEN PRINT "PERFECT LANDING!": GOTO 440 
+280 IF W<=10 THEN PRINT "GOOD LANDING (COULD RE BETTER)":GOTO 440 
+282 IF W>60 THEN 300
+284 PRINT "CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE" 
+286 PRINT "PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!" 
+288 GOTO 440
+300 PRINT "SORRY THERE NERE NO SURVIVORS. YOU BLOW IT!"
+310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"
+320 GOTO 440
+330 L=L+S: T=T-S: M=M-S*K: A=I: V=J: RETURN
+340 IF S<5E-03 THEN 260
+350 D=V+SQR(V*V+2*A*(G-Z*K/M)):S=2*A/D
+360 GOSUB 420: GOSUB 330: GOTO 340
+370 W=(1-M*G/(Z*K))/2: S=M*V/(Z*K*(W+SQR(W*W+V/Z)))+.05:GOSUB 420
+380 IF I<=0 THEN 340
+390 GOSUB 330: IF J>0 THEN 160
+400 IF V>0 THEN 370
+410 GOTO 160
+
+"""

From cb91ed2151ba06e1f0d0adef17bb00c257608430 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Fri, 5 Mar 2021 18:23:06 -0600
Subject: [PATCH 246/749] Ported HIGHIQ to Javascript

---
 48 High IQ/javascript/highiq.html |   9 ++
 48 High IQ/javascript/highiq.js   | 244 ++++++++++++++++++++++++++++++
 2 files changed, 253 insertions(+)
 create mode 100644 48 High IQ/javascript/highiq.html
 create mode 100644 48 High IQ/javascript/highiq.js

diff --git a/48 High IQ/javascript/highiq.html b/48 High IQ/javascript/highiq.html
new file mode 100644
index 00000000..03ea2f26
--- /dev/null
+++ b/48 High IQ/javascript/highiq.html	
@@ -0,0 +1,9 @@
+
+
+H-I-Q
+
+
+

+
+
+
diff --git a/48 High IQ/javascript/highiq.js b/48 High IQ/javascript/highiq.js
new file mode 100644
index 00000000..3dbb6aa1
--- /dev/null
+++ b/48 High IQ/javascript/highiq.js	
@@ -0,0 +1,244 @@
+// H-I-Q
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var b = [];
+var t = [];
+var m = [,13,14,15,
+          22,23,24,
+    29,30,31,32,33,34,35,
+    38,39,40,41,42,43,44,
+    47,48,49,50,51,52,53,
+          58,59,60,
+          67,68,69];
+var z;
+var p;
+
+//
+// Print board
+//
+function print_board()
+{
+    for (x = 1; x <= 9; x++) {
+        str = "";
+        for (y = 1; y <= 9; y++) {
+            if (x == 1 || x == 9 || y == 1 || y == 9)
+                continue;
+            if (x == 4 || x == 5 || x == 6 || y == 4 || y == 5 || y == 6) {
+                while (str.length < y * 2)
+                    str += " ";
+                if (t[x][y] == 5)
+                    str += "!";
+                else
+                    str += "O";
+            }
+        }
+        print(str + "\n");
+    }
+}
+
+//
+// Update board
+//
+function update_board()
+{
+    c = 1;
+    for (var x = 1; x <= 9; x++) {
+        for (var y = 1; y <= 9; y++, c++) {
+            if (c != z)
+                continue;
+            if (c + 2 == p) {
+                if (t[x][y + 1] == 0)
+                    return false;
+                t[x][y + 2] = 5;
+                t[x][y + 1] = 0;
+                b[c + 1] = -3;
+            } else if (c + 18 == p) {
+                if (t[x + 1][y] == 0)
+                    return false;
+                t[x + 2][y] = 5;
+                t[x + 1][y] = 0;
+                b[c + 9] = -3;
+            } else if (c - 2 == p) {
+                if (t[x][y - 1] == 0)
+                    return false;
+                t[x][y - 2] = 5;
+                t[x][y - 1] = 0;
+                b[c - 1] = -3;
+            } else if (c - 18 == p) {
+                if (t[x - 1][y] == 0)
+                    return false;
+                t[x - 2][y] = 5;
+                t[x - 1][y] = 0;
+                b[c - 9] = -3;
+            } else {
+                continue;
+            }
+            b[z] = -3;
+            b[p] = -7;
+            t[x][y] = 0;
+            return true;
+        }
+    }
+}
+
+//
+// Check for game over
+//
+// Rewritten because original subroutine was buggy
+//
+function check_game_over()
+{
+    f = 0;
+    for (r = 2; r <= 8; r++) {
+        for (c = 2; c <= 8; c++) {
+            if (t[r][c] != 5)
+                continue;
+            f++;
+            if (r > 3 && t[r - 1][c] == 5 && t[r - 2][c] == 0)
+                return false;
+            if (c > 3 && t[r][c - 1] == 5 && t[r][c - 2] == 0)
+                return false;
+            if (r < 7 && t[r + 1][c] == 5 && t[r + 2][c] == 0)
+                return false;
+            if (c < 7 && t[r][c + 1] == 5 && t[r][c + 2] == 0)
+                return false;
+        }
+    }
+    return true;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "H-I-Q\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (r = 0; r <= 70; r++)
+        b[r] = 0;
+    print("HERE IS THE BOARD:\n");
+    print("\n");
+    print("          !    !    !\n");
+    print("         13   14   15\n");
+    print("\n");
+    print("          !    !    !\n");
+    print("         22   23   24\n");
+    print("\n");
+    print("!    !    !    !    !    !    !\n");
+    print("29   30   31   32   33   34   35\n");
+    print("\n");
+    print("!    !    !    !    !    !    !\n");
+    print("38   39   40   41   42   43   44\n");
+    print("\n");
+    print("!    !    !    !    !    !    !\n");
+    print("47   48   49   50   51   52   53\n");
+    print("\n");
+    print("          !    !    !\n");
+    print("         58   59   60\n");
+    print("\n");
+    print("          !    !    !\n");
+    print("         67   68   69\n");
+    print("\n");
+    print("TO SAVE TYPING TIME, A COMPRESSED VERSION OF THE GAME BOARD\n");
+    print("WILL BE USED DURING PLAY.  REFER TO THE ABOVE ONE FOR PEG\n");
+    print("NUMBERS.  OK, LET'S BEGIN.\n");
+    while (1) {
+        // Set up board
+        for (r = 1; r <= 9; r++) {
+            t[r] = [];
+            for (c = 1; c <= 9; c++) {
+                if (r == 4 || r == 5 || r == 6 || c == 4 || c == 5 || c == 6 && (r != 1 && c != 1 && r != 9 && c != 9)) {
+                    t[r][c] = 5;
+                } else {
+                    t[r][c] = -5;
+                }
+            }
+        }
+        t[5][5] = 0;
+        print_board();
+        // Init secondary board
+        for (w = 1; w <= 33; w++) {
+            b[m[w]] = -7;
+        }
+        b[41] = -3;
+        // Input move and check on legality
+        do {
+            while (1) {
+                print("MOVE WHICH PIECE");
+                z = parseInt(await input());
+                if (b[z] == -7) {
+                    print("TO WHERE");
+                    p = parseInt(await input());
+                    if (p != z
+                        && b[p] != 0
+                        && b[p] != -7
+                        && (z + p) % 2 == 0
+                        && (Math.abs(z - p) - 2) * (Math.abs(z - p) - 18) == 0
+                        && update_board())
+                        break;
+                }
+                print("ILLEGAL MOVE, TRY AGAIN...\n");
+            }
+            print_board();
+        } while (!check_game_over()) ;
+        // Game is over
+        print("THE GAME IS OVER.\n");
+        print("YOU HAD " + f + " PIECES REMAINING.\n");
+        if (f == 1) {
+            print("BRAVO!  YOU MADE A PERFECT SCORE!\n");
+            print("SAVE THIS PAPER AS A RECORD OF YOUR ACCOMPLISHMENT!\n");
+        }
+        print("\n");
+        print("PLAY AGAIN (YES OR NO)");
+        str = await input();
+        if (str == "NO")
+            break;
+    }
+    print("\n");
+    print("SO LONG FOR NOW.\n");
+    print("\n");
+}
+
+main();

From 4d95b8763f9a3c916b7c4dcc5e6336befe7dfed4 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Fri, 5 Mar 2021 18:51:50 -0600
Subject: [PATCH 247/749] Ported LIFE to Javascript

---
 55 Life/javascript/life.html |   9 ++
 55 Life/javascript/life.js   | 191 +++++++++++++++++++++++++++++++++++
 2 files changed, 200 insertions(+)
 create mode 100644 55 Life/javascript/life.html
 create mode 100644 55 Life/javascript/life.js

diff --git a/55 Life/javascript/life.html b/55 Life/javascript/life.html
new file mode 100644
index 00000000..bebc6e82
--- /dev/null
+++ b/55 Life/javascript/life.html	
@@ -0,0 +1,9 @@
+
+
+LIFE
+
+
+

+
+
+
diff --git a/55 Life/javascript/life.js b/55 Life/javascript/life.js
new file mode 100644
index 00000000..338d48d5
--- /dev/null
+++ b/55 Life/javascript/life.js	
@@ -0,0 +1,191 @@
+// LIFE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var bs = [];
+var a = [];
+
+// Main program
+async function main()
+{
+    print(tab(34) + "LIFE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("ENTER YOUR PATTERN:\n");
+    x1 = 1;
+    y1 = 1;
+    x2 = 24;
+    y2 = 70;
+    for (c = 1; c <= 24; c++) {
+        bs[c] = "";
+        a[c] = [];
+        for (d = 1; d <= 70; d++)
+            a[c][d] = 0;
+    }
+    c = 1;
+    while (1) {
+        bs[c] = await input();
+        if (bs[c] == "DONE") {
+            bs[c] = "";
+            break;
+        }
+        if (bs[c].substr(0, 1) == ".")
+            bs[c] = " " + bs[c].substr(1);
+        c++;
+    }
+    c--;
+    l = 0;
+    for (x = 1; x <= c - 1; x++) {
+        if (bs[x].length > l)
+            l = bs[x].length;
+    }
+    x1 = 11 - (c >> 1);
+    y1 = 33 - (l >> 1);
+    p = 0;
+    for (x = 1; x <= c; x++) {
+        for (y = 1; y <= bs[x].length; y++) {
+            if (bs[x][y - 1] != " ") {
+                a[x1 + x][y1 + y] = 1;
+                p++;
+            }
+        }
+    }
+    print("\n");
+    print("\n");
+    print("\n");
+    i9 = false;
+    g = 0;
+    while (g < 100) {
+        print("GENERATION: " + g + " POPULATION: " + p + " ");
+        if (i9)
+            print("INVALID!");
+        x3 = 24;
+        y3 = 70;
+        x4 = 1;
+        y4 = 1;
+        p = 0;
+        g++;
+        for (x = 1; x <= x1 - 1; x++)
+            print("\n");
+        for (x = x1; x <= x2; x++) {
+            print("\n");
+            str = "";
+            for (y = y1; y <= y2; y++) {
+                if (a[x][y] == 2) {
+                    a[x][y] = 0;
+                    continue;
+                } else if (a[x][y] == 3) {
+                    a[x][y] = 1;
+                } else if (a[x][y] != 1) {
+                    continue;
+                }
+                while (str.length < y)
+                    str += " ";
+                str += "*";
+                if (x < x3)
+                    x3 = x;
+                if (x > x4)
+                    x4 = x;
+                if (y < y3)
+                    y3 = y;
+                if (y > y4)
+                    y4 = y;
+            }
+            print(str);
+        }
+        for (x = x2 + 1; x <= 24; x++)
+            print("\n");
+        x1 = x3;
+        x2 = x4;
+        y1 = y3;
+        y2 = y4;
+        if (x1 < 3) {
+            x1 = 3;
+            i9 = true;
+        }
+        if (x2 > 22) {
+            x2 = 22;
+            i9 = true;
+        }
+        if (y1 < 3) {
+            y1 = 3;
+            i9 = true;
+        }
+        if (y2 > 68) {
+            y2 = 68;
+            i9 = true;
+        }
+        p = 0;
+        for (x = x1 - 1; x <= x2 + 1; x++) {
+            for (y = y1 - 1; y <= y2 + 1; y++) {
+                c = 0;
+                for (i = x - 1; i <= x + 1; i++) {
+                    for (j = y - 1; j <= y + 1; j++) {
+                        if (a[i][j] == 1 || a[i][j] == 2)
+                            c++;
+                    }
+                }
+                if (a[x][y] == 0) {
+                    if (c == 3) {
+                        a[x][y] = 3;
+                        p++;
+                    }
+                } else {
+                    if (c < 3 || c > 4) {
+                        a[x][y] = 2;
+                    } else {
+                        p++;
+                    }
+                }
+            }
+        }
+        x1--;
+        y1--;
+        x2++;
+        y2++;
+    }
+}
+
+main();

From 1cc3d9f3c7ae306e1701e67189fd8235343d0b9f Mon Sep 17 00:00:00 2001
From: Qeubd-Bsjso 
Date: Sat, 6 Mar 2021 18:40:19 +0530
Subject: [PATCH 248/749] added Awari.java and AwariGame.java

---
 04 Awari/java/Awari.java     | 183 +++++++++++++++++++++++++++++++++++
 04 Awari/java/AwariGame.java |   5 +
 2 files changed, 188 insertions(+)
 create mode 100644 04 Awari/java/Awari.java
 create mode 100644 04 Awari/java/AwariGame.java

diff --git a/04 Awari/java/Awari.java b/04 Awari/java/Awari.java
new file mode 100644
index 00000000..3238d4de
--- /dev/null
+++ b/04 Awari/java/Awari.java	
@@ -0,0 +1,183 @@
+import java.util.Scanner;
+import java.util.Random;
+
+public class Awari{
+	int []board;
+	private final int playerPits;
+	private final int computerPits;
+	private final int playerHome;
+	private final int computerHome;
+	Scanner input;
+	int sumPlayer;
+	int sumComputer;
+	Awari(){
+		input = new Scanner(System.in);
+		playerPits = 0;
+		computerPits = 7;
+		playerHome = 6;
+		computerHome = 13;
+		sumPlayer = 18;
+		sumComputer = 18;
+		board = new int [14];
+		for (int i=0;i<6;i++){
+			board[playerPits+i]=3;
+			board[computerPits+i]=3;
+		}
+		System.out.println("		 AWARI");
+		System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
+		printBoard();
+		playerMove(true);
+	}
+
+	private void printBoard(){
+		System.out.print("\n    ");
+		for (int i=0;i<6;i++){
+			System.out.print(String.format("%2d",board[12-i]));
+			System.out.print("  ");
+		}
+		System.out.println("");
+		System.out.print(String.format("%2d",board[computerHome]));
+		System.out.print("                          ");
+		System.out.println(String.format("%2d",board[playerHome]));
+		System.out.print("    ");
+		for(int i=0;i<6;i++){
+			System.out.print(String.format("%2d",board[playerPits+i]));
+                        System.out.print("  ");
+		}
+		System.out.println("");
+	}
+
+	private void playerMove(boolean val){
+		if(val == true)
+			System.out.print("YOUR MOVE? ");
+		else
+			System.out.print("AGAIN? ");
+		int move =  input.nextInt();
+		while(move<1||move>6||board[move-1]==0){
+			System.out.print("INVALID MOVE!!! TRY AGAIN  ");
+			move = input.nextInt();
+		}
+		int seeds = board[move-1];
+		board[move-1] = 0;
+		sumPlayer -= seeds;
+		int last_pos = distribute(seeds,move);
+		if(last_pos == playerHome){
+			printBoard();
+			playerMove(false);
+		}
+		else if(board[last_pos] == 1&&last_pos != computerHome){
+			int opp = calculateOpposite(last_pos);
+			board[last_pos]+=board[opp];
+			board[opp] = 0;
+			printBoard();
+			if(isGameOver()){
+				System.exit(0);
+			}
+			computerMove(true);
+		}
+		else{
+			printBoard();
+			if(isGameOver()){
+				System.exit(0);
+			}
+			computerMove(true);
+		}
+	}
+
+	private void computerMove(boolean value){
+		int val=-1;
+		for(int i=0;i<6;i++){
+			if(6-i == board[computerPits+i])
+				val = i;
+		}
+		int move ;
+		if(val == -1)
+		{
+			Random random = new Random();
+			move = random.nextInt(6)+computerPits;
+			while(board[move] == 0){
+				move = random.nextInt(6)+computerPits;
+			}
+			if(value == true)
+				System.out.println(String.format("MY MOVE IS %d ",move-computerPits+1));
+			else
+				System.out.println(String.format(",%d",move-computerPits+1));
+			int seeds = board[move];
+			board[move] = 0;
+			sumComputer-=seeds;
+			int last_pos = distribute(seeds,move+1);
+			if(board[last_pos] == 1&&last_pos != playerHome){
+                	        int opp = calculateOpposite(last_pos);
+        	                board[last_pos]+=board[opp];
+	                        board[opp] = 0;
+                        	printBoard();
+                	        if(isGameOver()){
+        	                        System.exit(0);
+	                        }
+                	}
+			else{
+				printBoard();
+	                        if(isGameOver()){
+        	                        System.exit(0);
+                	        }
+			}
+			playerMove(true);
+		}
+		else {
+			move = val+computerPits;
+			if(value == true)
+				System.out.print(String.format("MY MOVE IS %d",move-computerPits+1));
+			else
+				System.out.print(String.format(",%d",move-computerPits+1));
+			int seeds = board[move];
+                        board[move] = 0;
+                        sumComputer-=seeds;
+                        int last_pos = distribute(seeds,move+1);
+			if(last_pos == computerHome){
+				if(isGameOver() ){
+					System.exit(0);
+				}
+				computerMove(false);
+			}
+		}
+	}
+
+
+	private int distribute(int seeds, int pos){
+		while(seeds!=0){
+			if(pos==14)
+				pos=0;
+			if(pos<6)
+				sumPlayer++;
+			else if(pos>6&&pos<13)
+				sumComputer++;
+			board[pos]++;
+			pos++;
+			seeds--;
+		}
+		return pos-1;
+	}
+
+	private int calculateOpposite(int pos){
+		return 12-pos;
+	}
+
+	private boolean isGameOver(){
+		if(sumPlayer == 0 || sumComputer == 0){
+			System.out.println("GAME OVER");
+			if(board[playerHome]>board[computerHome]){
+				System.out.println(String.format("YOU WIN BY %d POINTS",board[playerHome]-board[computerHome]));
+			}
+			else if(board[playerHome]
Date: Sat, 6 Mar 2021 19:13:11 +0530
Subject: [PATCH 249/749] Debugging in Awari.java

---
 04 Awari/java/Awari.java | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/04 Awari/java/Awari.java b/04 Awari/java/Awari.java
index 3238d4de..058daa11 100644
--- a/04 Awari/java/Awari.java	
+++ b/04 Awari/java/Awari.java	
@@ -48,6 +48,7 @@ public class Awari{
 	}
 
 	private void playerMove(boolean val){
+		System.out.println("\nComputerSum PlayerSum"+sumComputer+" "+sumPlayer);
 		if(val == true)
 			System.out.print("YOUR MOVE? ");
 		else
@@ -63,21 +64,32 @@ public class Awari{
 		int last_pos = distribute(seeds,move);
 		if(last_pos == playerHome){
 			printBoard();
+			if(isGameOver(true)){
+				System.exit(0);
+			}
 			playerMove(false);
 		}
 		else if(board[last_pos] == 1&&last_pos != computerHome){
 			int opp = calculateOpposite(last_pos);
+			if(last_pos<6){
+				sumPlayer+=board[opp];
+				sumComputer-=board[opp];
+			}
+			else{
+				sumComputer+=board[opp];
+				sumPlayer-=board[opp];
+			}
 			board[last_pos]+=board[opp];
 			board[opp] = 0;
 			printBoard();
-			if(isGameOver()){
+			if(isGameOver(false)){
 				System.exit(0);
 			}
 			computerMove(true);
 		}
 		else{
 			printBoard();
-			if(isGameOver()){
+			if(isGameOver(false)){
 				System.exit(0);
 			}
 			computerMove(true);
@@ -86,6 +98,7 @@ public class Awari{
 
 	private void computerMove(boolean value){
 		int val=-1;
+		System.out.println("\nComputerSum PlayerSum"+sumComputer+" "+sumPlayer);
 		for(int i=0;i<6;i++){
 			if(6-i == board[computerPits+i])
 				val = i;
@@ -108,16 +121,24 @@ public class Awari{
 			int last_pos = distribute(seeds,move+1);
 			if(board[last_pos] == 1&&last_pos != playerHome){
                 	        int opp = calculateOpposite(last_pos);
+				 if(last_pos<6){
+	                                sumPlayer+=board[opp];
+        	                        sumComputer-=board[opp];
+                	        }
+                        	else{
+	                                sumComputer+=board[opp];
+        	                        sumPlayer-=board[opp];
+                	        }
         	                board[last_pos]+=board[opp];
 	                        board[opp] = 0;
                         	printBoard();
-                	        if(isGameOver()){
+                	        if(isGameOver(false)){
         	                        System.exit(0);
 	                        }
                 	}
 			else{
 				printBoard();
-	                        if(isGameOver()){
+	                        if(isGameOver(false)){
         	                        System.exit(0);
                 	        }
 			}
@@ -134,7 +155,7 @@ public class Awari{
                         sumComputer-=seeds;
                         int last_pos = distribute(seeds,move+1);
 			if(last_pos == computerHome){
-				if(isGameOver() ){
+				if(isGameOver(true) ){
 					System.exit(0);
 				}
 				computerMove(false);
@@ -162,8 +183,10 @@ public class Awari{
 		return 12-pos;
 	}
 
-	private boolean isGameOver(){
+	private boolean isGameOver(boolean show){
 		if(sumPlayer == 0 || sumComputer == 0){
+			if(show)
+				printBoard();
 			System.out.println("GAME OVER");
 			if(board[playerHome]>board[computerHome]){
 				System.out.println(String.format("YOU WIN BY %d POINTS",board[playerHome]-board[computerHome]));

From 9d6a427976c2ff011379f4f52ce9a32d70ed1369 Mon Sep 17 00:00:00 2001
From: Fred Wenzel 
Date: Sat, 6 Mar 2021 10:23:03 -0800
Subject: [PATCH 250/749] gitignore cleanup

---
 .gitignore | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2973d79d..fc50f7f2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,4 @@
-/01 Acey Ducey/csharp/obj
-/47 Hi-Lo/csharp/obj
-/.vs
-/33 Dice/csharp/obj
-/01 Acey Ducey/csharp/.vs/AceyDucey
-/01 Acey Ducey/csharp/bin/Debug/netcoreapp3.1
-/33 Dice/csharp/bin/Debug/net5.0
-/basic-computer-games-dot-net/.vs/basic-computer-games-dot-net/v16
+*/.vs
 
 */csharp/bin
 */csharp/obj
@@ -15,3 +8,6 @@
 *.iml
 *.ipr
 out/
+
+*.py[co]
+Pipfile

From 92819187ef11457e244cc0d222ca7a0cf2700116 Mon Sep 17 00:00:00 2001
From: Marc Heiligers 
Date: Sat, 6 Mar 2021 11:42:35 -0700
Subject: [PATCH 251/749] Translate Python version for main algorithm

---
 02 Amazing/ruby/amazing.rb | 374 +++++++++++++------------------------
 1 file changed, 130 insertions(+), 244 deletions(-)

diff --git a/02 Amazing/ruby/amazing.rb b/02 Amazing/ruby/amazing.rb
index 7e7db0ce..c14148b1 100644
--- a/02 Amazing/ruby/amazing.rb	
+++ b/02 Amazing/ruby/amazing.rb	
@@ -1,276 +1,162 @@
 # frozen_string_literal: true
 
-# BASIC arrays are 1-based, unlike Ruby 0-based arrays
+# Set up a constant hash for directions
+DIRECTIONS = {
+  left: 0,
+  up: 1,
+  right: 2,
+  down: 3
+}.freeze
+
+EXIT_DOWN = 1
+EXIT_RIGHT = 2
+
+# BASIC arrays are 1-based, unlike Ruby 0-based arrays,
+#   and this class simulates that. BASIC arrays are also zero-filled,
+#   which is also done here.
 class BasicArrayTwoD
-  def initialize(width, height)
-    @val = Array.new(height) { Array.new(width, 0) }
+  def initialize(rows, cols)
+    @val = Array.new(rows) { Array.new(cols, 0) }
   end
 
-  def [](x, y)
-    @val[y - 1][x - 1]
+  def [](row, col = nil)
+    if col
+      @val[row - 1][col - 1]
+    else
+      @val[row - 1]
+    end
   end
 
-  def []=(x, y, n)
-    @val[y - 1][x - 1] = n
+  def []=(row, col, n)
+    @val[row - 1][col - 1] = n
   end
 
   def to_s
-    @val.map { |r| r.join(' ') }.join("\n")
+    @val.map { |row| row.join(' ') }.join("\n")
   end
 end
 
-# 10 PRINT TAB(28);"AMAZING PROGRAM"
-# 20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
-# 30 PRINT:PRINT:PRINT:PRINT
-puts ' ' * 28 + 'AMAZING PROGRAM'
-puts ' ' * 15 + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY'
-puts "\n" * 4
-
-# 100 INPUT "WHAT ARE YOUR WIDTH AND LENGTH";H,V
-# 102 IF H<>1 AND V<>1 THEN 110
-# 104 PRINT "MEANINGLESS DIMENSIONS.  TRY AGAIN.":GOTO 100
-def ask_dimensions
-  print 'WHAT ARE YOUR WIDTH AND LENGTH? '
-  h = gets.to_i
-  print '?? '
-  v = gets.to_i
-  [h, v]
-end
-
-h, v = ask_dimensions
-while h < 1 || v < 1
-  puts "MEANINGLESS DIMENSIONS.  TRY AGAIN."
-  h, v = ask_dimensions
-end
-
-# 110 DIM W(H,V),V(H,V)
-# BASIC programs can have the same variable names for different types,
-#   so the v array is not the same as the v int. Here we're using suffixes.
-w_arr = BasicArrayTwoD.new(h, v)
-v_arr = BasicArrayTwoD.new(h, v)
-
-# 120 PRINT
-# 130 PRINT
-# 140 PRINT
-# 150 PRINT
-puts "\n" * 4
-
-# 160 Q=0:Z=0:X=INT(RND(1)*H+1)
-q = 0
-z = 0
-
-def draw_top(x, h)
-  # 165 FOR I=1 TO H
-  # 170 IF I=X THEN 173
-  # 171 PRINT ".--";:GOTO 180
-  # 173 PRINT ".  ";
-  # 180 NEXT I
-  (1..h).each do |i|
-    if i == x
+def draw_top(entry, width)
+  (1..width).each do |i|
+    if i == entry
       print i == 1 ? '┏  ' : '┳  '
     else
       print i == 1 ? '┏━━' : '┳━━'
     end
   end
 
-  # 190 PRINT "."
   puts '┓'
-
-  x # return this because we need it
 end
 
-# x represents the location of the opening
-x = (rand * h).round + 1
-draw_top(x, h)
+def draw_row(row)
+  print '┃'
+  row.each { |val| print val < 2 ? '  ┃' : '   ' }
+  puts
+  row.each { |val| print val == 0 || val == 2 ? '┣━━' : '┃  ' }
+  puts '┫'
+end
 
-# 195 C=1:W(X,1)=C:C=C+1
+
+# 10 PRINT TAB(28);"AMAZING PROGRAM"
+# 20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
+# 30 PRINT:PRINT:PRINT:PRINT
+puts ' ' * 28 + 'AMAZING PROGRAM'
+puts ' ' * 15 + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY'
+puts "\n" * 3
+
+# 100 INPUT "WHAT ARE YOUR WIDTH AND LENGTH";H,V
+# 102 IF H<>1 AND V<>1 THEN 110
+# 104 PRINT "MEANINGLESS DIMENSIONS.  TRY AGAIN.":GOTO 100
+def ask_dimensions
+  print 'WHAT ARE YOUR WIDTH AND HEIGHT? '
+  width = gets.to_i
+  print '?? '
+  height = gets.to_i
+  [width, height]
+end
+
+width, height = ask_dimensions
+while width <= 1 || height <= 1
+  puts "MEANINGLESS DIMENSIONS.  TRY AGAIN."
+  width, height = ask_dimensions
+end
+
+# 110 DIM W(H,V),V(H,V)
+# BASIC programs can have the same variable names for different types,
+#   so the v array is not the same as the v int. Here we're renaming the arrays
+#   to have more friendly names
+used = BasicArrayTwoD.new(height, width)
+walls = BasicArrayTwoD.new(height, width)
+
+puts "\n" * 3
+
+
+# entry represents the location of the opening
+entry = (rand * width).round + 1
+
+# Set up our current row and column, starting at the top and the locations of the opening
+row = 1
+col = entry
 c = 1
-w_arr[x, 1] = c # This marks the opening in the first row
+used[row, col] = c # This marks the opening in the first row
 c += 1
 
-puts w_arr
+while c != width * height + 1 do
+  # remove possible directions that are blocked or
+  # hit cells that we have already processed
+  possible_dirs = DIRECTIONS.keys
+  if col == 0 || used[row, col - 1] != 0
+    possible_dirs.delete(:left)
+  end
+  if row == 0 || used[row - 1, col] != 0
+    possible_dirs.delete(:up)
+  end
+  if col == width || used[row, col + 1] != 0
+    possible_dirs.delete(:right)
+  end
+  if row == height || used[row + 1, col] != 0
+    possible_dirs.delete(:down)
+  end
 
-# 200 R=X:S=1:GOTO 260
-r = x
-s = 1
-# 260 IF R-1=0 THEN 530
-if r - 1 == 0
-  # 530 IF S-1=0 THEN 670
-  if s - 1 == 0
-    # 670 IF R=H THEN 740
-    if r == h
-      # 740 IF S<>V THEN 760
-      if s != v
-        # 760 IF W(R,S+1)<>0 THEN 780
-        if w_arr[r, s + 1] != 0
-          # 780 GOTO 1000
-          # Well, we'll just go directly to 1000
-          # 1000 GOTO 210
-          # Well, now. I just got here, now back to 210
-          # 210 IF R<>H THEN 240
-          if r != h
-            # 240 R=R+1
-            r += 1
-            # 250 IF W(R,S)=0 THEN 210
-            if w_arr[r, s] == 0
-              # GOTO 210 -- this is a loop
-            end
-            # 260 IF R-1=0 THEN 530
-            if r - 1 == 0
-              # 530 IF S-1=0 THEN 670
-              # 540 IF W(R,S-1)<>0 THEN 670
-              if s - 1 == 0 || w_arr[r, s - 1] != 0
-                # 670 IF R=H THEN 740
-                # 680 IF W(R+1,S)<>0 THEN 740
-                # 685 IF S<>V THEN 700
-                # 690 IF Z=1 THEN 730
-                # 695 Q=1:GOTO 710
-              end
-              # 545 IF R=H THEN 610
-              # 547 IF W(R+1,S)<>0 THEN 610
-              if r == h || w_arr[r + 1, s] != 0
-                # 610 IF S<>V THEN 630
-                # 620 IF Z=1 THEN 660
-                # 625 Q=1:GOTO 640
-              end
-              # 550 IF S<>V THEN 560
-              if s != v
-                # 560 IF W(R,S+1)<>0 THEN 590
-                # 570 X=INT(RND(1)*3+1)
-                # 580 ON X GOTO 820,860,910
-              end
-              # 552 IF Z=1 THEN 590
-              if z == 1
-                # 590 X=INT(RND(1)*2+1)
-                # 600 ON X GOTO 820,860
-              end
-              # 554 Q=1:GOTO 570
-              q = 1
-              # 570 X=INT(RND(1)*3+1)
-              # 580 ON X GOTO 820,860,910
-            end
-          end
-        end
+  # If we can move in a direction, move and make opening
+  if possible_dirs.size != 0
+    direction = possible_dirs.sample # pick a random direction
+    if direction == :left
+      col = col - 1
+      walls[row, col] = EXIT_RIGHT
+    elsif direction == :up
+      row = row - 1
+      walls[row, col] = EXIT_DOWN
+    elsif direction == :right
+      walls[row, col] += EXIT_RIGHT
+      col = col + 1
+    elsif direction == :down
+      walls[row, col] += EXIT_DOWN
+      row = row + 1
+    end
+    used[row, col] = c
+    c = c + 1
+  # otherwise, move to the next used cell, and try again
+  else
+    while true do
+      if col != width
+        col += 1
+      elsif row != height
+        row += 1
+        col = 1
+      else
+        row = col = 1
       end
+      break if used[row, col] != 0
     end
   end
 end
 
-# 210 IF R<>H THEN 240
-# 215 IF S<>V THEN 230
-# 220 R=1:S=1:GOTO 250
-# 230 R=1:S=S+1:GOTO 250
-# 240 R=R+1
-# 250 IF W(R,S)=0 THEN 210
-# 260 IF R-1=0 THEN 530
-# 265 IF W(R-1,S)<>0 THEN 530
-# 270 IF S-1=0 THEN 390
-# 280 IF W(R,S-1)<>0 THEN 390
-# 290 IF R=H THEN 330
-# 300 IF W(R+1,S)<>0 THEN 330
-# 310 X=INT(RND(1)*3+1)
-# 320 ON X GOTO 790,820,860
-# 330 IF S<>V THEN 340
-# 334 IF Z=1 THEN 370
-# 338 Q=1:GOTO 350
-# 340 IF W(R,S+1)<>0 THEN 370
-# 350 X=INT(RND(1)*3+1)
-# 360 ON X GOTO 790,820,910
-# 370 X=INT(RND(1)*2+1)
-# 380 ON X GOTO 790,820
-# 390 IF R=H THEN 470
-# 400 IF W(R+1,S)<>0 THEN 470
-# 405 IF S<>V THEN 420
-# 410 IF Z=1 THEN 450
-# 415 Q=1:GOTO 430
-# 420 IF W(R,S+1)<>0 THEN 450
-# 430 X=INT(RND(1)*3+1)
-# 440 ON X GOTO 790,860,910
-# 450 X=INT(RND(1)*2+1)
-# 460 ON X GOTO 790,860
-# 470 IF S<>V THEN 490
-# 480 IF Z=1 THEN 520
-# 485 Q=1:GOTO 500
-# 490 IF W(R,S+1)<>0 THEN 520
-# 500 X=INT(RND(1)*2+1)
-# 510 ON X GOTO 790,910
-# 520 GOTO 790
-# 530 IF S-1=0 THEN 670
-# 540 IF W(R,S-1)<>0 THEN 670
-# 545 IF R=H THEN 610
-# 547 IF W(R+1,S)<>0 THEN 610
-# 550 IF S<>V THEN 560
-# 552 IF Z=1 THEN 590
-# 554 Q=1:GOTO 570
-# 560 IF W(R,S+1)<>0 THEN 590
-# 570 X=INT(RND(1)*3+1)
-# 580 ON X GOTO 820,860,910
-# 590 X=INT(RND(1)*2+1)
-# 600 ON X GOTO 820,860
-# 610 IF S<>V THEN 630
-# 620 IF Z=1 THEN 660
-# 625 Q=1:GOTO 640
-# 630 IF W(R,S+1)<>0 THEN 660
-# 640 X=INT(RND(1)*2+1)
-# 650 ON X GOTO 820,910
-# 660 GOTO 820
-# 670 IF R=H THEN 740
-# 680 IF W(R+1,S)<>0 THEN 740
-# 685 IF S<>V THEN 700
-# 690 IF Z=1 THEN 730
-# 695 Q=1:GOTO 710
-# 700 IF W(R,S+1)<>0 THEN 730
-# 710 X=INT(RND(1)*2+1)
-# 720 ON X GOTO 860,910
-# 730 GOTO 860
-# 740 IF S<>V THEN 760
-# 750 IF Z=1 THEN 780
-# 755 Q=1:GOTO 770
-# 760 IF W(R,S+1)<>0 THEN 780
-# 770 GOTO 910
-# 780 GOTO 1000
-# 790 W(R-1,S)=C
-# 800 C=C+1:V(R-1,S)=2:R=R-1
-# 810 IF C=H*V+1 THEN 1010
-# 815 Q=0:GOTO 260
-# 820 W(R,S-1)=C
-# 830 C=C+1
-# 840 V(R,S-1)=1:S=S-1:IF C=H*V+1 THEN 1010
-# 850 Q=0:GOTO 260
-# 860 W(R+1,S)=C
-# 870 C=C+1:IF V(R,S)=0 THEN 880
-# 875 V(R,S)=3:GOTO 890
-# 880 V(R,S)=2
-# 890 R=R+1
-# 900 IF C=H*V+1 THEN 1010
-# 905 GOTO 530
-# 910 IF Q=1 THEN 960
-# 920 W(R,S+1)=C:C=C+1:IF V(R,S)=0 THEN 940
-# 930 V(R,S)=3:GOTO 950
-# 940 V(R,S)=1
-# 950 S=S+1:IF C=H*V+1 THEN 1010
-# 955 GOTO 260
-# 960 Z=1
-# 970 IF V(R,S)=0 THEN 980
-# 975 V(R,S)=3:Q=0:GOTO 1000
-# 980 V(R,S)=1:Q=0:R=1:S=1:GOTO 250
-# 1000 GOTO 210
-# 1010 FOR J=1 TO V
-# 1011 PRINT "I";
-# 1012 FOR I=1 TO H
-# 1013 IF V(I,J)<2 THEN 1030
-# 1020 PRINT "   ";
-# 1021 GOTO 1040
-# 1030 PRINT "  I";
-# 1040 NEXT I
-# 1041 PRINT
-# 1043 FOR I=1 TO H
-# 1045 IF V(I,J)=0 THEN 1060
-# 1050 IF V(I,J)=2 THEN 1060
-# 1051 PRINT ":  ";
-# 1052 GOTO 1070
-# 1060 PRINT ":--";
-# 1070 NEXT I
-# 1071 PRINT "."
-# 1072 NEXT J
-# 1073 END
+# Add a random exit
+walls[height, (rand * width).round + 1] += 1
+
+# Print the maze
+draw_top(entry, width)
+(1..height).each do |row|
+  draw_row(walls[row])
+end

From 71a9c4828235073f1c783fad817540497d59a983 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sat, 6 Mar 2021 14:15:40 -0800
Subject: [PATCH 252/749] WIP port LUNAR to python

refactored a bunch, did some debugging - more testing, cleanup remains.
---
 59 Lunar LEM Rocket/python/lunar.py | 384 ++++++++++++++++++++++------
 1 file changed, 308 insertions(+), 76 deletions(-)

diff --git a/59 Lunar LEM Rocket/python/lunar.py b/59 Lunar LEM Rocket/python/lunar.py
index da2329ef..93a73082 100644
--- a/59 Lunar LEM Rocket/python/lunar.py	
+++ b/59 Lunar LEM Rocket/python/lunar.py	
@@ -6,8 +6,34 @@ Lunar landing simulation
 Ported by Dave LeCompte
 """
 
+import collections
+import math
+
+
 PAGE_WIDTH = 64
 
+COLUMN_WIDTH = 2
+SECONDS_WIDTH = 4
+MPH_WIDTH = 6
+ALT_MI_WIDTH = 6
+ALT_FT_WIDTH = 4
+MPH_WIDTH = 6
+FUEL_WIDTH = 8
+BURN_WIDTH = 10
+
+SECONDS_LEFT = 0
+SECONDS_RIGHT = SECONDS_LEFT + SECONDS_WIDTH
+ALT_LEFT = SECONDS_RIGHT + COLUMN_WIDTH
+ALT_MI_RIGHT = ALT_LEFT + ALT_MI_WIDTH
+ALT_FT_RIGHT = ALT_MI_RIGHT + COLUMN_WIDTH + ALT_FT_WIDTH
+MPH_LEFT = ALT_FT_RIGHT + COLUMN_WIDTH
+MPH_RIGHT = MPH_LEFT + MPH_WIDTH
+FUEL_LEFT = MPH_RIGHT + COLUMN_WIDTH
+FUEL_RIGHT = FUEL_LEFT + FUEL_WIDTH
+BURN_LEFT = FUEL_RIGHT + COLUMN_WIDTH
+BURN_RIGHT = BURN_LEFT + BURN_WIDTH
+
+PhysicalState = collections.namedtuple('PhysicalState', ['velocity', 'altitude'])
 
 def print_centered(msg):
     spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
@@ -21,8 +47,35 @@ def print_header(title):
     print()
     print()
 
+def add_rjust(line, s, pos):
+    # adds a new field to a line right justified to end at pos
+    
+    s = str(s)
+    slen = len(s)
+    if len(line) + slen > pos:
+        new_len = pos - slen
+        line = line[:new_len]
+    if len(line) + slen < pos:
+        spaces = " " * (pos - slen - len(line))
+        line = line + spaces
+    return line + s
+
+def add_ljust(line, s, pos):
+    # adds a new field to a line left justified starting at pos
+    
+    s = str(s)
+    slen = len(s)
+    if len(line) > pos:
+        line = line[:pos]
+    if len(line) < pos:
+        spaces = " " * (pos - len(line))
+        line = line + spaces
+    return line + s
+
 
 def print_instructions():
+    # Somebody had a bad experience with Xerox.
+    
     print("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR")
     print("LANDING CAPSULE.")
     print()
@@ -43,9 +96,9 @@ def print_intro():
     print("GOOD LUCK")
     print()
 
-def show_landing(l, v):
-    w = 3600 * v
-    print("ON MOON AT {l} SECONDS - IMPACT VELOCITY {w} MPH")
+def show_landing(sim_clock, capsule):
+    w = 3600 * capsule.v
+    print(f"ON MOON AT {sim_clock.elapsed_time} SECONDS - IMPACT VELOCITY {w} MPH")
     if w < 1.2:
         print("PERFECT LANDING!")
     elif w < 10:
@@ -55,104 +108,248 @@ def show_landing(l, v):
         print("PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!")
     else:
         print("SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!")
-        print("IN FACT, YOU BLASTED A NEW LUNAR CRATER {w*.227:.4f} FEET DEEP!")
+        print(f"IN FACT, YOU BLASTED A NEW LUNAR CRATER {w*.227:.4f} FEET DEEP!")
     end_sim()
 
+
+def show_out_of_fuel(sim_clock, capsule):
+    # line 240
+    print(f"FUEL OUT AT {sim_clock.elapsed_time} SECONDS")
+    delta_t = (-capsule.v + math.sqrt(capsule.v ** 2 + 2 *
+                                      capsule.a * capsule.g)) / capsule.g
+    capsule.v += capsule.g * delta_t
+    sim_clock.advance(delta_t)
+    show_landing(sim_clock, capsule)
+
+def format_line_for_report(t, miles, feet, velocity, fuel, burn_rate, is_header):
+    line = add_rjust("", t, SECONDS_RIGHT)
+    line = add_rjust(line, miles, ALT_MI_RIGHT)
+    line = add_rjust(line, feet, ALT_FT_RIGHT)
+    line = add_rjust(line, velocity, MPH_RIGHT)
+    line = add_rjust(line, fuel, FUEL_RIGHT)
+    if is_header:
+        line = add_rjust(line, burn_rate, BURN_RIGHT)
+    else:
+        line = add_ljust(line, burn_rate, BURN_LEFT)
+    return line
+
+class Capsule:
+    def __init__(self,
+                 altitude = 120,
+                 velocity = 1,
+                 mass_with_fuel = 33000,
+                 mass_without_fuel = 16500,
+                 g = 1e-3,
+                 z = 1.8):
+        self.a = altitude # in miles above the surface
+        self.v = velocity # downward
+        self.m = mass_with_fuel
+        self.n = mass_without_fuel
+        self.g = g
+        self.z = z
+        self.fuel_per_second = 0
+
+    def remaining_fuel(self):
+        return self.m - self.n
+
+    def is_out_of_fuel(self):
+        return self.remaining_fuel() < 1e-3
+
+    def update_state(self, sim_clock, delta_t, new_state):
+        # line 330
+        sim_clock.advance(delta_t)
+        self.m = self.m - delta_t * self.fuel_per_second
+        self.a = new_state.altitude
+        self.v = new_state.velocity
+
+    def fuel_time_remaining(self):
+        # extrapolates out how many seconds we have at the current fuel burn rate
+        assert(self.fuel_per_second > 0)
+        return self.remaining_fuel() / self.fuel_per_second
+
+    def predict_motion(self, delta_t):
+        # Perform an Euler's Method numerical integration of the equations of motion.
+
+        # line 420
+        q = delta_t * self.fuel_per_second / self.m
+
+        # new velocity
+        new_velocity = (self.v +
+                        self.g * delta_t +
+                        self.z * (-q -
+                                  q ** 2 / 2 -
+                                  q ** 3 / 3 -
+                                  q ** 4 / 4 -
+                                  q ** 5 / 5))
+
+        # new altitude
+        new_altitude = (self.a -
+                        self.g * delta_t ** 2 / 2 -
+                        self.v * delta_t +
+                        self.z * delta_t * (q / 2 +
+                                            q ** 2 / 6 +
+                                            q ** 3 / 12 +
+                                            q ** 4 / 20 +
+                                            q ** 5 / 30))
+
         
-def update_physics():
-    # line 330
-    elapsed_time += delta_t
-    time_to_prompt -= delta_t
-    m = m - delta_t * k
-    a = i
-    v = j
-    return
+        return PhysicalState(altitude = new_altitude,
+                             velocity = new_velocity)
 
-def update_burn():
-    # line 420
-    q = delta_t * k / m
-    j = (v +
-         g * delta_t +
-         z * (-q - q*q/2 - q**3/3 - q**4/4 - q**5/5))
-    i = (a -
-         g * delta_t * delta_t/2 -
-         v * delta_t +
-         z * delta_t * (q / 2 +
-                        q ** 2 / 6 +
-                        q ** 3 / 12 +
-                        q ** 4 / 20 +
-                        q ** 5 / 30))
+    def make_state_display_string(self, sim_clock):
+        seconds = sim_clock.elapsed_time
+        miles = int(self.a)
+        feet = int(5280 * (self.a - miles))
+        velocity = int(3600 * self.v)
+        fuel = int(self.remaining_fuel())
+        burn_rate = " ? "
 
-    return q,j,i
+        return format_line_for_report(seconds, miles, feet, velocity, fuel, burn_rate, False)
+
+    def prompt_for_burn(self, sim_clock):
+        # line 150
+        PROMPT = True
+
+        msg = self.make_state_display_string(sim_clock)
+        if PROMPT:
+            self.fuel_per_second = float(input(msg))
+        else:
+            print(msg)
+            self.fuel_per_second = 0.0
+        sim_clock.time_until_next_prompt = 10
+    
+
+class SimulationClock:
+    def __init__(self, elapsed_time, time_until_next_prompt):
+        self.elapsed_time = elapsed_time
+        self.time_until_next_prompt = time_until_next_prompt
+
+    def time_for_prompt(self):
+        return self.time_until_next_prompt < 1e-3
+
+    def advance(self, delta_t):
+        self.elapsed_time += delta_t
+        self.time_until_next_prompt -= delta_t
+        
+
+def process_final_tick(delta_t, sim_clock, capsule):
+    # When we extrapolated our position based on our velocity
+    # and delta_t, we overshot the surface. For better
+    # accuracy, we will back up and do shorter time advances.
+            
+    # line 340
+    while True:
+        if delta_t < 5e-3:
+            show_landing(sim_clock, capsule)
+            return
+        #line 35
+        average_vel = (capsule.v +
+                       math.sqrt(capsule.v **2  +
+                                 2 * capsule.a * (capsule.g -
+                                                  capsule.z *
+                                                  capsule.fuel_per_second / capsule.m))) / 2
+        delta_t = capsule.a / average_vel
+        new_state = capsule.predict_motion(delta_t)
+        capsule.update_state(sim_clock, delta_t, new_state)
+
+def handle_flyaway(capsule):
+    """
+    The user has started flying away from the moon. Since this is a
+    lunar LANDING simulation, we wait until the capsule's velocity is
+    positive (downward) before prompting for more input.
+    
+    Returns True if landed, False if simulation should continue.
+    """
+    
+    while True:
+        # line 370
+        w = (1 - capsule.m * capsule.g / (capsule.z * capsule.fuel_per_second)) / 2
+        delta_t = (capsule.m * capsule.v /
+                   (capsule.z * capsule.fuel_per_second *
+                    math.sqrt(w**2 + capsule.v / capsule.z))) + 0.05
+                
+        new_state = capsule.predict_motion(delta_t)
+
+        # line 380
+        if new_state.altitude <= 0:
+            # have landed
+            return True
+
+        # line 390
+        capsule.update_state(sim_clock, delta_t, new_state)
+
+        if ((new_state.velocity > 0) or (capsule.v <= 0)):
+            # return to normal sim
+            return False
+
+
+
+    
 
 def end_sim():
     print()
     print()
     print()
     print("TRY AGAIN??")
+    print()
+    print()
+    print()
 
 
-def prompt_for_burn():
-    # line 150
-    print("{l}\t{a}\t{int(5280*(a-int(a)))}\t{3600 * v}\t{m-n}")
-    k = input()
-
 def run_simulation():
     print()
-    print("SEC\tMI + FT\tMPH\tLB FUEL\tBURN RATE")
-    print()
-    
-    elapsed_time = 0
-    a = 120
-    v = 1 
-    m = 33000 # mass of capsule with fuel
-    n = 16500 # mass of capsule without fuel
-    g = 1e-3
-    z = 1.8
+    print(format_line_for_report("SEC",
+                                 "MI",
+                                 "FT",
+                                 "MPH",
+                                 "LB FUEL",
+                                 "BURN RATE",
+                                 True))
 
-    k = prompt_for_burn()
-    time_to_prompt = 10
+    sim_clock = SimulationClock(0, 10)
+    capsule = Capsule()
+
+    capsule.prompt_for_burn(sim_clock)
 
     while True:
         # line 160
-        if M-N < 1e-3:
-            # line 240
-            print(f"FUEL OUT AT {elapsed_time} SECONDS")
-            delta_t = (-v + math.sqrt(v*v + 2*a*g)) / g
-            v += g * delta_t
-            elapsed_time += delta_t
-            show_landing(elapsed_time, v)
+        if capsule.is_out_of_fuel():
+            show_out_of_fuel(sim_clock, capsule)
             return
 
-        if t < 1e-3:
-            k = prompt_for_burn()
+        # line 170
+        if sim_clock.time_for_prompt():
+            capsule.prompt_for_burn(sim_clock)
             continue
 
         # line 180
-        delta_t = time_to_prompt
-        if m < n + delta_t * k:
-            delta_t = (m-n) / k
-            
-        # line 200
-        q,j,i = update_burn()
+        # clock advance is the shorter of the time to the next prompt,
+        # or when we run out of fuel.
+        if capsule.fuel_per_second > 0:
+            delta_t = min(sim_clock.time_until_next_prompt,
+                          capsule.fuel_time_remaining())
+        else:
+            delta_t = sim_clock.time_until_next_prompt
 
-        if i <= 0:
-            # line 340
-            while True:
-                if delta_t < 5e-3:
-                    show_landing(elapsed_time, v)
-                #line 350
-                d = v + math.sqrt(v*v + 2*a*(g-z*k/m))
-                delta_t = 2 * a / d
-                update_burn()
-                update_physics()
+        # line 200
+        new_state = capsule.predict_motion(delta_t)
+
+        if new_state.altitude <= 0:
+            process_final_tick(delta_t, sim_clock, capsule)
+            return
+
+        # line 210
+        if capsule.v > 0 and new_state.velocity < 0:
+            # moving away from the moon
+
+            landed = handle_flyaway(capsule)
+            if landed:
+                process_final_tick(delta_t, sim_clock, capsule)
+                return
 
         else:
-            # line 210
-            if ((v > 0) and (j < 0)):
-                GOTO 370
             # line 230
-            update_physics()
+            capsule.update_state(sim_clock, delta_t, new_state)
 
 
 
@@ -166,41 +363,76 @@ def main():
     while True:
         print_intro()
         run_simulation()
+
+if __name__ == "__main__":
+    main()
         
 
 """
+10 PRINT TAB(33);"LUNAR"
+20 PRINT TAB(l5);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" 
+25 PRINT:PRINT:PRINT
+30 PRINT "THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR" 
+40 PRINT "LANDING CAPSULE.": PRINT: PRINT
+50 PRINT "THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY" 
+60 PRINT "XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY."
+70 PRINT: PRINT "SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN" 
+80 PRINT "0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND." 
+90 PRINT "SET NEW BURN RATE EVERY 10 SECONDS.": PRINT 
+100 PRINT "CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS."
+110 PRINT: PRINT: PRINT: PRINT "GOOD LUCK"
 120 L=0
 130 PRINT: PRINT "SEC","MI + FT","MPH","LB FUEL","BURN RATE":PRINT 
 140 A=120:V=1:M=33000:N=16500:G=1E-03:Z=1.8
+
+149 REM DWL capsule.prompt_for_burn
 150 PRINT L,INT(A);INT(5280*(A-INT(A))),3600*V,M-N,:INPUT K:T=10 
+
+159 REM main loop
 160 IF M-N<1E-03 THEN 240
 170 IF T<1E-03 THEN 150
 180 S=T: IF M>=N+S*K THEN 200
 190 S=(M-N)/K
-200 GOSUB 420: IF I<=O THEN 340
+200 GOSUB 420: IF I<=0 THEN 340
 210 IF V<=0 THEN 230
 220 IF J<0 THEN 370
 230 GOSUB 330: GOTO 160
+
+239 REM DWL show_out_of_fuel
 240 PRINT "FUEL OUT AT";L;"SECONDS":S=(-V+SQR(V*V+2*A*G))/G
 250 V=V+G*S: L=L+S
+
+259 REM DWL show_landing
 260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH" 
 274 IF W<=1.2 THEN PRINT "PERFECT LANDING!": GOTO 440 
-280 IF W<=10 THEN PRINT "GOOD LANDING (COULD RE BETTER)":GOTO 440 
+280 IF W<=10 THEN PRINT "GOOD LANDING (COULD BE BETTER)":GOTO 440 
 282 IF W>60 THEN 300
 284 PRINT "CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE" 
 286 PRINT "PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!" 
 288 GOTO 440
-300 PRINT "SORRY THERE NERE NO SURVIVORS. YOU BLOW IT!"
+300 PRINT "SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!"
 310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"
 320 GOTO 440
+
+329 REM DWL capsule.update_state
 330 L=L+S: T=T-S: M=M-S*K: A=I: V=J: RETURN
+
+339 REM DWL process_final_tick
 340 IF S<5E-03 THEN 260
 350 D=V+SQR(V*V+2*A*(G-Z*K/M)):S=2*A/D
 360 GOSUB 420: GOSUB 330: GOTO 340
+
+369 REM DWL handle_flyaway
 370 W=(1-M*G/(Z*K))/2: S=M*V/(Z*K*(W+SQR(W*W+V/Z)))+.05:GOSUB 420
 380 IF I<=0 THEN 340
 390 GOSUB 330: IF J>0 THEN 160
 400 IF V>0 THEN 370
 410 GOTO 160
 
+419 REM DWL capsule.predict_motion
+420 Q=S*K/M: J=V+G*S+Z*(-Q-Q*Q/2-Q^3/3-Q^4/4-Q^5/5)
+430 I=A-G*S*S/2-V*S+Z*S*(Q/2+Q^2/6+Q^3/12+Q^4/20+Q^5/30):RETURN
+
+439 REM DWL end_sim
+440 PRINT:PRINT:PRINT:PRINT "TRY AGAIN??": GOTO 70
 """

From dece05cb39351273a9d4299f008104b246113387 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sat, 6 Mar 2021 14:26:24 -0800
Subject: [PATCH 253/749] Super Star Trek Instructions as TXT file

You can read it on a PADD or in notepad.
---
 84 Super Star Trek/instructions.txt | 131 ++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 84 Super Star Trek/instructions.txt

diff --git a/84 Super Star Trek/instructions.txt b/84 Super Star Trek/instructions.txt
new file mode 100644
index 00000000..91f26b42
--- /dev/null
+++ b/84 Super Star Trek/instructions.txt	
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+*************************************
+*                                   *
+*                                   *
+*      * * SUPER STAR TREK * *      *
+*                                   *
+*                                   *
+*************************************
+
+
+
+
+
+
+
+
+      INSTRUCTIONS FOR 'SUPER STAR TREK'
+
+1. WHEN YOU SEE \COMMAND ?\ PRINTED, ENTER ONE OF THE LEGAL
+     COMMANDS (NAV,SRS,LRS,PHA,TOR,SHE,DAM,COM, OR XXX).
+2. IF YOU SHOULD TYPE IN AN ILLEGAL COMMAND, YOU'LL GET A SHORT
+     LIST OF THE LEGAL COMMANDS PRINTED OUT.
+3. SOME COMMANDS REQUIRE YOU TO ENTER DATA (FOR EXAMPLE, THE
+     'NAV' COMMAND COMES BACK WITH 'COURSE (1-9) ?'.)  IF YOU
+     TYPE IN ILLEGAL DATA (LIKE NEGATIVE NUMBERS), THAN COMMAND
+     WILL BE ABORTED
+
+     THE GALAXY IS DIVIDED INTO AN 8 X 8 QUADRANT GRID,
+AND EACH QUADRANT IS FURTHER DIVIDED INTO AN 8 X 8 SECTOR GRID.
+
+     YOU WILL BE ASSIGNED A STARTING POINT SOMEWHERE IN THE
+GALAXY TO BEGIN A TOUR OF DUTY AS COMANDER OF THE STARSHIP
+\ENTERPRISE\; YOUR MISSION: TO SEEK AND DESTROY THE FLEET OF
+KLINGON WARWHIPS WHICH ARE MENACING THE UNITED FEDERATION OF
+PLANETS.
+
+     YOU HAVE THE FOLLOWING COMMANDS AVAILABLE TO YOU AS CAPTAIN
+OF THE STARSHIP ENTERPRISE:
+
+\NAV\ COMMAND = WARP ENGINE CONTROL --
+     COURSE IS IN A CIRCULAR NUMERICAL      4  3  2
+     VECTOR ARRANGEMENT AS SHOWN             . . .
+     INTEGER AND REAL VALUES MAY BE           ...
+     USED.  (THUS COURSE 1.5 IS HALF-     5 ---*--- 1
+     WAY BETWEEN 1 AND 2                      ...
+                                             . . .
+     VALUES MAY APPROACH 9.0, WHICH         6  7  8
+     ITSELF IS EQUIVALENT TO 1.0"        
+                                            COURSE
+     ONE WARP FACTOR IS THE SIZE OF 
+     ONE QUADTANT.  THEREFORE, TO GET
+     FROM QUADRANT 6,5 TO 5,5, YOU WOULD
+     USE COURSE 3, WARP FACTOR 1.
+
+\SRS\ COMMAND = SHORT RANGE SENSOR SCAN
+     SHOWS YOU A SCAN OF YOUR PRESENT QUADRANT.
+
+     SYMBOLOGY ON YOUR SENSOR SCREEN IS AS FOLLOWS:
+        <*> = YOUR STARSHIP'S POSITION
+        +K+ = KLINGON BATTLE CRUISER
+        >!< = FEDERATION STARBASE (REFUEL/REPAIR/RE-ARM HERE!)
+         *  = STAR
+
+     A CONDENSED 'STATUS REPORT' WILL ALSO BE PRESENTED.
+
+\LRS\ COMMAND = LONG RANGE SENSOR SCAN
+     SHOWS CONDITIONS IN SPACE FOR ONE QUADRANT ON EACH SIDE
+     OF THE ENTERPRISE (WHICH IS IN THE MIDDLE OF THE SCAN)
+     THE SCAN IS CODED IN THE FORM \###\, WHERE TH UNITS DIGIT
+     IS THE NUMBER OF STARS, THE TENS DIGIT IS THE NUMBER OF
+     STARBASES, AND THE HUNDRESDS DIGIT IS THE NUMBER OF
+     KLINGONS.
+
+     EXAMPLE - 207 = 2 KLINGONS, NO STARBASES, & 7 STARS.
+
+\PHA\ COMMAND = PHASER CONTROL.
+     ALLOWS YOU TO DESTROY THE KLINGON BATTLE CRUISERS BY 
+     ZAPPING THEM WITH SUITABLY LARGE UNITS OF ENERGY TO
+     DEPLETE THEIR SHIELD POWER.  (REMEMBER, KLINGONS HAVE
+     PHASERS TOO!)
+
+\TOR\ COMMAND = PHOTON TORPEDO CONTROL
+     TORPEDO COURSE IS THE SAME AS USED IN WARP ENGINE CONTROL
+     IF YOU HIT THE KLINGON VESSEL, HE IS DESTROYED AND
+     CANNOT FIRE BACK AT YOU.  IF YOU MISS, YOU ARE SUBJECT TO
+     HIS PHASER FIRE.  IN EITHER CASE, YOU ARE ALSO SUBJECT TO 
+     THE PHASER FIRE OF ALL OTHER KLINGONS IN THE QUADRANT.
+
+     THE LIBRARY-COMPUTER (\COM\ COMMAND) HAS AN OPTION TO 
+     COMPUTE TORPEDO TRAJECTORY FOR YOU (OPTION 2)
+
+\SHE\ COMMAND = SHIELD CONTROL
+     DEFINES THE NUMBER OF ENERGY UNITS TO BE ASSIGNED TO THE
+     SHIELDS.  ENERGY IS TAKEN FROM TOTAL SHIP'S ENERGY.  NOTE
+     THAN THE STATUS DISPLAY TOTAL ENERGY INCLUDES SHIELD ENERGY
+
+\DAM\ COMMAND = DAMMAGE CONTROL REPORT
+     GIVES THE STATE OF REPAIR OF ALL DEVICES.  WHERE A NEGATIVE
+     'STATE OF REPAIR' SHOWS THAT THE DEVICE IS TEMPORARILY
+     DAMAGED.
+
+\COM\ COMMAND = LIBRARY-COMPUTER
+     THE LIBRARY-COMPUTER CONTAINS SIX OPTIONS:
+     OPTION 0 = CUMULATIVE GALACTIC RECORD
+        THIS OPTION SHOWES COMPUTER MEMORY OF THE RESULTS OF ALL
+        PREVIOUS SHORT AND LONG RANGE SENSOR SCANS
+     OPTION 1 = STATUS REPORT
+        THIS OPTION SHOWS THE NUMBER OF KLINGONS, STARDATES,
+        AND STARBASES REMAINING IN THE GAME.
+     OPTION 2 = PHOTON TORPEDO DATA
+        WHICH GIVES DIRECTIONS AND DISTANCE FROM THE ENTERPRISE
+        TO ALL KLINGONS IN YOUR QUADRANT
+     OPTION 3 = STARBASE NAV DATA
+        THIS OPTION GIVES DIRECTION AND DISTANCE TO ANY 
+        STARBASE WITHIN YOUR QUADRANT
+     OPTION 4 = DIRECTION/DISTANCE CALCULATOR
+        THIS OPTION ALLOWS YOU TO ENTER COORDINATES FOR
+        DIRECTION/DISTANCE CALCULATIONS
+     OPTION 5 = GALACTIC /REGION NAME/ MAP
+        THIS OPTION PRINTS THE NAMES OF THE SIXTEEN MAJOR 
+        GALACTIC REGIONS REFERRED TO IN THE GAME.
+ 

From 1773fbe4181fe9dfcf2952cab63dd2f77f2472ee Mon Sep 17 00:00:00 2001
From: Marc Heiligers 
Date: Sat, 6 Mar 2021 15:40:56 -0700
Subject: [PATCH 254/749] Refactor

---
 02 Amazing/ruby/amazing.rb | 298 ++++++++++++++++++++++---------------
 1 file changed, 176 insertions(+), 122 deletions(-)

diff --git a/02 Amazing/ruby/amazing.rb b/02 Amazing/ruby/amazing.rb
index c14148b1..d9a4f9d0 100644
--- a/02 Amazing/ruby/amazing.rb	
+++ b/02 Amazing/ruby/amazing.rb	
@@ -1,19 +1,15 @@
 # frozen_string_literal: true
 
-# Set up a constant hash for directions
-DIRECTIONS = {
-  left: 0,
-  up: 1,
-  right: 2,
-  down: 3
-}.freeze
+DEBUG = !ENV['DEBUG'].nil?
 
-EXIT_DOWN = 1
-EXIT_RIGHT = 2
+require 'io/console' if DEBUG
 
 # BASIC arrays are 1-based, unlike Ruby 0-based arrays,
-#   and this class simulates that. BASIC arrays are also zero-filled,
-#   which is also done here.
+# and this class simulates that. BASIC arrays are zero-filled,
+# which is also done here. While we could easily update the
+# algorithm to work with zero-based arrays, this class makes
+# the problem easier to reason about, row or col 1 are the
+# first row or column.
 class BasicArrayTwoD
   def initialize(rows, cols)
     @val = Array.new(rows) { Array.new(cols, 0) }
@@ -31,132 +27,190 @@ class BasicArrayTwoD
     @val[row - 1][col - 1] = n
   end
 
-  def to_s
-    @val.map { |row| row.join(' ') }.join("\n")
+  def to_s(width: max_width, row_hilite: nil, col_hilite: nil)
+    @val.map.with_index do |row, row_index|
+      row.map.with_index do |val, col_index|
+        if row_hilite == row_index + 1 && col_hilite == col_index + 1
+          "[#{val.to_s.center(width)}]"
+        else
+          val.to_s.center(width + 2)
+        end
+      end.join
+    end.join("\n")
+  end
+
+  def max_width
+    @val.flat_map { |row| row.map { |val| val.to_s.length } }.sort.last
   end
 end
 
-def draw_top(entry, width)
-  (1..width).each do |i|
-    if i == entry
-      print i == 1 ? '┏  ' : '┳  '
-    else
-      print i == 1 ? '┏━━' : '┳━━'
+class Maze
+  EXIT_DOWN = 1
+  EXIT_RIGHT = 2
+
+  # Set up a constant hash for directions
+  # The values represent the direction of the move as changes to row, col
+  # and the type of exit when moving in that direction
+  DIRECTIONS = {
+    left: { row: 0, col: -1, exit: EXIT_RIGHT },
+    up: { row: -1, col: 0, exit: EXIT_DOWN },
+    right: { row: 0, col: 1, exit: EXIT_RIGHT },
+    down: { row: 1, col: 0, exit: EXIT_DOWN }
+  }.freeze
+
+  attr_reader :width, :height, :used, :walls, :entry
+
+  def initialize(width, height)
+    @width = width
+    @height = height
+
+    @used = BasicArrayTwoD.new(height, width)
+    @walls = BasicArrayTwoD.new(height, width)
+
+    create
+  end
+
+  def draw
+    # Print the maze
+    draw_top(entry, width)
+    (1..height - 1).each do |row|
+      draw_row(walls[row])
     end
+    draw_bottom(walls[height])
   end
 
-  puts '┓'
-end
+  private
 
-def draw_row(row)
-  print '┃'
-  row.each { |val| print val < 2 ? '  ┃' : '   ' }
-  puts
-  row.each { |val| print val == 0 || val == 2 ? '┣━━' : '┃  ' }
-  puts '┫'
-end
+  def create
+    # entry represents the location of the opening
+    @entry = (rand * width).round + 1
 
+    # Set up our current row and column, starting at the top and the locations of the opening
+    row = 1
+    col = entry
+    c = 1
+    used[row, col] = c # This marks the opening in the first row
+    c += 1
 
-# 10 PRINT TAB(28);"AMAZING PROGRAM"
-# 20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
-# 30 PRINT:PRINT:PRINT:PRINT
-puts ' ' * 28 + 'AMAZING PROGRAM'
-puts ' ' * 15 + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY'
-puts "\n" * 3
+    while c != width * height + 1 do
+      debug walls, row, col
+      # remove possible directions that are blocked or
+      # hit cells that we have already processed
+      possible_dirs = DIRECTIONS.reject do |dir, change|
+        nrow = row + change[:row]
+        ncol = col + change[:col]
+        nrow < 1 || nrow > height || ncol < 1 || ncol > width || used[nrow, ncol] != 0
+      end.keys
 
-# 100 INPUT "WHAT ARE YOUR WIDTH AND LENGTH";H,V
-# 102 IF H<>1 AND V<>1 THEN 110
-# 104 PRINT "MEANINGLESS DIMENSIONS.  TRY AGAIN.":GOTO 100
-def ask_dimensions
-  print 'WHAT ARE YOUR WIDTH AND HEIGHT? '
-  width = gets.to_i
-  print '?? '
-  height = gets.to_i
-  [width, height]
-end
-
-width, height = ask_dimensions
-while width <= 1 || height <= 1
-  puts "MEANINGLESS DIMENSIONS.  TRY AGAIN."
-  width, height = ask_dimensions
-end
-
-# 110 DIM W(H,V),V(H,V)
-# BASIC programs can have the same variable names for different types,
-#   so the v array is not the same as the v int. Here we're renaming the arrays
-#   to have more friendly names
-used = BasicArrayTwoD.new(height, width)
-walls = BasicArrayTwoD.new(height, width)
-
-puts "\n" * 3
-
-
-# entry represents the location of the opening
-entry = (rand * width).round + 1
-
-# Set up our current row and column, starting at the top and the locations of the opening
-row = 1
-col = entry
-c = 1
-used[row, col] = c # This marks the opening in the first row
-c += 1
-
-while c != width * height + 1 do
-  # remove possible directions that are blocked or
-  # hit cells that we have already processed
-  possible_dirs = DIRECTIONS.keys
-  if col == 0 || used[row, col - 1] != 0
-    possible_dirs.delete(:left)
-  end
-  if row == 0 || used[row - 1, col] != 0
-    possible_dirs.delete(:up)
-  end
-  if col == width || used[row, col + 1] != 0
-    possible_dirs.delete(:right)
-  end
-  if row == height || used[row + 1, col] != 0
-    possible_dirs.delete(:down)
-  end
-
-  # If we can move in a direction, move and make opening
-  if possible_dirs.size != 0
-    direction = possible_dirs.sample # pick a random direction
-    if direction == :left
-      col = col - 1
-      walls[row, col] = EXIT_RIGHT
-    elsif direction == :up
-      row = row - 1
-      walls[row, col] = EXIT_DOWN
-    elsif direction == :right
-      walls[row, col] += EXIT_RIGHT
-      col = col + 1
-    elsif direction == :down
-      walls[row, col] += EXIT_DOWN
-      row = row + 1
-    end
-    used[row, col] = c
-    c = c + 1
-  # otherwise, move to the next used cell, and try again
-  else
-    while true do
-      if col != width
-        col += 1
-      elsif row != height
-        row += 1
-        col = 1
+      # If we can move in a direction, move and make opening
+      if possible_dirs.size != 0
+        direction = possible_dirs.sample
+        change = DIRECTIONS[direction] # pick a random direction
+        if %i[left up].include?(direction)
+          row += change[:row]
+          col += change[:col]
+          walls[row, col] = change[:exit]
+        else
+          walls[row, col] += change[:exit]
+          row += change[:row]
+          col += change[:col]
+        end
+        used[row, col] = c
+        c = c + 1
+      # otherwise, move to the next used cell, and try again
       else
-        row = col = 1
+        loop do
+          if col != width
+            col += 1
+          elsif row != height
+            row += 1
+            col = 1
+          else
+            row = col = 1
+          end
+          break if used[row, col] != 0
+          debug walls, row, col
+        end
       end
-      break if used[row, col] != 0
     end
+
+    # Add a random exit
+    walls[height, (rand * width).round] += 1
+  end
+
+  def draw_top(entry, width)
+    (1..width).each do |i|
+      if i == entry
+        print i == 1 ? '┏  ' : '┳  '
+      else
+        print i == 1 ? '┏━━' : '┳━━'
+      end
+    end
+
+    puts '┓'
+  end
+
+  def draw_row(row)
+    print '┃'
+    row.each.with_index do |val, col|
+      print val < 2 ? '  ┃' : '   '
+    end
+    puts
+    row.each.with_index do |val, col|
+      print val == 0 || val == 2 ? (col == 0 ? '┣━━' : '╋━━') : (col == 0 ? '┃  ' : '┫  ')
+    end
+    puts '┫'
+  end
+
+  def draw_bottom(row)
+    print '┃'
+    row.each.with_index do |val, col|
+      print val < 2 ? '  ┃' : '   '
+    end
+    puts
+    row.each.with_index do |val, col|
+      print val == 0 || val == 2 ? (col == 0 ? '┗━━' : '┻━━') : (col == 0 ? '┗  ' : '┻  ')
+    end
+    puts '┛'
+  end
+
+  def debug(walls, row, col)
+    return unless DEBUG
+
+    STDOUT.clear_screen
+    puts walls.to_s(row_hilite: row, col_hilite: col)
+    sleep 0.1
   end
 end
 
-# Add a random exit
-walls[height, (rand * width).round + 1] += 1
+class Amazing
+  def run
+    draw_header
 
-# Print the maze
-draw_top(entry, width)
-(1..height).each do |row|
-  draw_row(walls[row])
+    width, height = ask_dimensions
+    while width <= 1 || height <= 1
+      puts "MEANINGLESS DIMENSIONS.  TRY AGAIN."
+      width, height = ask_dimensions
+    end
+
+    maze = Maze.new(width, height)
+    puts "\n" * 3
+    maze.draw
+  end
+
+  def draw_header
+    puts ' ' * 28 + 'AMAZING PROGRAM'
+    puts ' ' * 15 + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY'
+    puts "\n" * 3
+  end
+
+  def ask_dimensions
+    print 'WHAT ARE YOUR WIDTH AND HEIGHT? '
+    width = gets.to_i
+    print '?? '
+    height = gets.to_i
+    [width, height]
+  end
 end
+
+Amazing.new.run
\ No newline at end of file

From 92ba86f67587c3417ab6c0ff3c7474e89392ca2d Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sat, 6 Mar 2021 14:45:29 -0800
Subject: [PATCH 255/749] more work on porting LUNAR to python

I have yet to beat this game, so I haven't fully tested it.
---
 59 Lunar LEM Rocket/python/lunar.py | 248 ++++++++++------------------
 1 file changed, 85 insertions(+), 163 deletions(-)

diff --git a/59 Lunar LEM Rocket/python/lunar.py b/59 Lunar LEM Rocket/python/lunar.py
index 93a73082..b55fc6f2 100644
--- a/59 Lunar LEM Rocket/python/lunar.py	
+++ b/59 Lunar LEM Rocket/python/lunar.py	
@@ -33,7 +33,8 @@ FUEL_RIGHT = FUEL_LEFT + FUEL_WIDTH
 BURN_LEFT = FUEL_RIGHT + COLUMN_WIDTH
 BURN_RIGHT = BURN_LEFT + BURN_WIDTH
 
-PhysicalState = collections.namedtuple('PhysicalState', ['velocity', 'altitude'])
+PhysicalState = collections.namedtuple("PhysicalState", ["velocity", "altitude"])
+
 
 def print_centered(msg):
     spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
@@ -47,9 +48,10 @@ def print_header(title):
     print()
     print()
 
+
 def add_rjust(line, s, pos):
     # adds a new field to a line right justified to end at pos
-    
+
     s = str(s)
     slen = len(s)
     if len(line) + slen > pos:
@@ -60,9 +62,10 @@ def add_rjust(line, s, pos):
         line = line + spaces
     return line + s
 
+
 def add_ljust(line, s, pos):
     # adds a new field to a line left justified starting at pos
-    
+
     s = str(s)
     slen = len(s)
     if len(line) > pos:
@@ -75,7 +78,7 @@ def add_ljust(line, s, pos):
 
 def print_instructions():
     # Somebody had a bad experience with Xerox.
-    
+
     print("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR")
     print("LANDING CAPSULE.")
     print()
@@ -84,6 +87,7 @@ def print_instructions():
     print("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.")
     print()
 
+
 def print_intro():
     print("SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN")
     print("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.")
@@ -96,9 +100,12 @@ def print_intro():
     print("GOOD LUCK")
     print()
 
+
 def show_landing(sim_clock, capsule):
     w = 3600 * capsule.v
-    print(f"ON MOON AT {sim_clock.elapsed_time} SECONDS - IMPACT VELOCITY {w} MPH")
+    print(
+        f"ON MOON AT {sim_clock.elapsed_time:.2f} SECONDS - IMPACT VELOCITY {w:.2f} MPH"
+    )
     if w < 1.2:
         print("PERFECT LANDING!")
     elif w < 10:
@@ -108,19 +115,20 @@ def show_landing(sim_clock, capsule):
         print("PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!")
     else:
         print("SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!")
-        print(f"IN FACT, YOU BLASTED A NEW LUNAR CRATER {w*.227:.4f} FEET DEEP!")
+        print(f"IN FACT, YOU BLASTED A NEW LUNAR CRATER {w*.227:.2f} FEET DEEP!")
     end_sim()
 
 
 def show_out_of_fuel(sim_clock, capsule):
-    # line 240
     print(f"FUEL OUT AT {sim_clock.elapsed_time} SECONDS")
-    delta_t = (-capsule.v + math.sqrt(capsule.v ** 2 + 2 *
-                                      capsule.a * capsule.g)) / capsule.g
+    delta_t = (
+        -capsule.v + math.sqrt(capsule.v ** 2 + 2 * capsule.a * capsule.g)
+    ) / capsule.g
     capsule.v += capsule.g * delta_t
     sim_clock.advance(delta_t)
     show_landing(sim_clock, capsule)
 
+
 def format_line_for_report(t, miles, feet, velocity, fuel, burn_rate, is_header):
     line = add_rjust("", t, SECONDS_RIGHT)
     line = add_rjust(line, miles, ALT_MI_RIGHT)
@@ -133,16 +141,19 @@ def format_line_for_report(t, miles, feet, velocity, fuel, burn_rate, is_header)
         line = add_ljust(line, burn_rate, BURN_LEFT)
     return line
 
+
 class Capsule:
-    def __init__(self,
-                 altitude = 120,
-                 velocity = 1,
-                 mass_with_fuel = 33000,
-                 mass_without_fuel = 16500,
-                 g = 1e-3,
-                 z = 1.8):
-        self.a = altitude # in miles above the surface
-        self.v = velocity # downward
+    def __init__(
+        self,
+        altitude=120,
+        velocity=1,
+        mass_with_fuel=33000,
+        mass_without_fuel=16500,
+        g=1e-3,
+        z=1.8,
+    ):
+        self.a = altitude  # in miles above the surface
+        self.v = velocity  # downward
         self.m = mass_with_fuel
         self.n = mass_without_fuel
         self.g = g
@@ -156,7 +167,6 @@ class Capsule:
         return self.remaining_fuel() < 1e-3
 
     def update_state(self, sim_clock, delta_t, new_state):
-        # line 330
         sim_clock.advance(delta_t)
         self.m = self.m - delta_t * self.fuel_per_second
         self.a = new_state.altitude
@@ -164,37 +174,32 @@ class Capsule:
 
     def fuel_time_remaining(self):
         # extrapolates out how many seconds we have at the current fuel burn rate
-        assert(self.fuel_per_second > 0)
+        assert self.fuel_per_second > 0
         return self.remaining_fuel() / self.fuel_per_second
 
     def predict_motion(self, delta_t):
         # Perform an Euler's Method numerical integration of the equations of motion.
 
-        # line 420
         q = delta_t * self.fuel_per_second / self.m
 
         # new velocity
-        new_velocity = (self.v +
-                        self.g * delta_t +
-                        self.z * (-q -
-                                  q ** 2 / 2 -
-                                  q ** 3 / 3 -
-                                  q ** 4 / 4 -
-                                  q ** 5 / 5))
+        new_velocity = (
+            self.v
+            + self.g * delta_t
+            + self.z * (-q - q ** 2 / 2 - q ** 3 / 3 - q ** 4 / 4 - q ** 5 / 5)
+        )
 
         # new altitude
-        new_altitude = (self.a -
-                        self.g * delta_t ** 2 / 2 -
-                        self.v * delta_t +
-                        self.z * delta_t * (q / 2 +
-                                            q ** 2 / 6 +
-                                            q ** 3 / 12 +
-                                            q ** 4 / 20 +
-                                            q ** 5 / 30))
+        new_altitude = (
+            self.a
+            - self.g * delta_t ** 2 / 2
+            - self.v * delta_t
+            + self.z
+            * delta_t
+            * (q / 2 + q ** 2 / 6 + q ** 3 / 12 + q ** 4 / 20 + q ** 5 / 30)
+        )
 
-        
-        return PhysicalState(altitude = new_altitude,
-                             velocity = new_velocity)
+        return PhysicalState(altitude=new_altitude, velocity=new_velocity)
 
     def make_state_display_string(self, sim_clock):
         seconds = sim_clock.elapsed_time
@@ -204,20 +209,16 @@ class Capsule:
         fuel = int(self.remaining_fuel())
         burn_rate = " ? "
 
-        return format_line_for_report(seconds, miles, feet, velocity, fuel, burn_rate, False)
+        return format_line_for_report(
+            seconds, miles, feet, velocity, fuel, burn_rate, False
+        )
 
     def prompt_for_burn(self, sim_clock):
-        # line 150
-        PROMPT = True
-
         msg = self.make_state_display_string(sim_clock)
-        if PROMPT:
-            self.fuel_per_second = float(input(msg))
-        else:
-            print(msg)
-            self.fuel_per_second = 0.0
+
+        self.fuel_per_second = float(input(msg))
         sim_clock.time_until_next_prompt = 10
-    
+
 
 class SimulationClock:
     def __init__(self, elapsed_time, time_until_next_prompt):
@@ -230,62 +231,66 @@ class SimulationClock:
     def advance(self, delta_t):
         self.elapsed_time += delta_t
         self.time_until_next_prompt -= delta_t
-        
+
 
 def process_final_tick(delta_t, sim_clock, capsule):
     # When we extrapolated our position based on our velocity
     # and delta_t, we overshot the surface. For better
     # accuracy, we will back up and do shorter time advances.
-            
-    # line 340
+
     while True:
         if delta_t < 5e-3:
             show_landing(sim_clock, capsule)
             return
-        #line 35
-        average_vel = (capsule.v +
-                       math.sqrt(capsule.v **2  +
-                                 2 * capsule.a * (capsule.g -
-                                                  capsule.z *
-                                                  capsule.fuel_per_second / capsule.m))) / 2
+        # line 35
+        average_vel = (
+            capsule.v
+            + math.sqrt(
+                capsule.v ** 2
+                + 2
+                * capsule.a
+                * (capsule.g - capsule.z * capsule.fuel_per_second / capsule.m)
+            )
+        ) / 2
         delta_t = capsule.a / average_vel
         new_state = capsule.predict_motion(delta_t)
         capsule.update_state(sim_clock, delta_t, new_state)
 
-def handle_flyaway(capsule):
+
+def handle_flyaway(sim_clock, capsule):
     """
     The user has started flying away from the moon. Since this is a
     lunar LANDING simulation, we wait until the capsule's velocity is
     positive (downward) before prompting for more input.
-    
+
     Returns True if landed, False if simulation should continue.
     """
-    
+
     while True:
-        # line 370
         w = (1 - capsule.m * capsule.g / (capsule.z * capsule.fuel_per_second)) / 2
-        delta_t = (capsule.m * capsule.v /
-                   (capsule.z * capsule.fuel_per_second *
-                    math.sqrt(w**2 + capsule.v / capsule.z))) + 0.05
-                
+        delta_t = (
+            capsule.m
+            * capsule.v
+            / (
+                capsule.z
+                * capsule.fuel_per_second
+                * math.sqrt(w ** 2 + capsule.v / capsule.z)
+            )
+        ) + 0.05
+
         new_state = capsule.predict_motion(delta_t)
 
-        # line 380
         if new_state.altitude <= 0:
             # have landed
             return True
 
-        # line 390
         capsule.update_state(sim_clock, delta_t, new_state)
 
-        if ((new_state.velocity > 0) or (capsule.v <= 0)):
+        if (new_state.velocity > 0) or (capsule.v <= 0):
             # return to normal sim
             return False
 
 
-
-    
-
 def end_sim():
     print()
     print()
@@ -298,13 +303,9 @@ def end_sim():
 
 def run_simulation():
     print()
-    print(format_line_for_report("SEC",
-                                 "MI",
-                                 "FT",
-                                 "MPH",
-                                 "LB FUEL",
-                                 "BURN RATE",
-                                 True))
+    print(
+        format_line_for_report("SEC", "MI", "FT", "MPH", "LB FUEL", "BURN RATE", True)
+    )
 
     sim_clock = SimulationClock(0, 10)
     capsule = Capsule()
@@ -312,51 +313,41 @@ def run_simulation():
     capsule.prompt_for_burn(sim_clock)
 
     while True:
-        # line 160
         if capsule.is_out_of_fuel():
             show_out_of_fuel(sim_clock, capsule)
             return
 
-        # line 170
         if sim_clock.time_for_prompt():
             capsule.prompt_for_burn(sim_clock)
             continue
 
-        # line 180
         # clock advance is the shorter of the time to the next prompt,
         # or when we run out of fuel.
         if capsule.fuel_per_second > 0:
-            delta_t = min(sim_clock.time_until_next_prompt,
-                          capsule.fuel_time_remaining())
+            delta_t = min(
+                sim_clock.time_until_next_prompt, capsule.fuel_time_remaining()
+            )
         else:
             delta_t = sim_clock.time_until_next_prompt
 
-        # line 200
         new_state = capsule.predict_motion(delta_t)
 
         if new_state.altitude <= 0:
             process_final_tick(delta_t, sim_clock, capsule)
             return
 
-        # line 210
         if capsule.v > 0 and new_state.velocity < 0:
             # moving away from the moon
 
-            landed = handle_flyaway(capsule)
+            landed = handle_flyaway(sim_clock, capsule)
             if landed:
                 process_final_tick(delta_t, sim_clock, capsule)
                 return
 
         else:
-            # line 230
             capsule.update_state(sim_clock, delta_t, new_state)
 
 
-
-        
-        
-
-
 def main():
     print_header("LUNAR")
     print_instructions()
@@ -364,75 +355,6 @@ def main():
         print_intro()
         run_simulation()
 
+
 if __name__ == "__main__":
     main()
-        
-
-"""
-10 PRINT TAB(33);"LUNAR"
-20 PRINT TAB(l5);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" 
-25 PRINT:PRINT:PRINT
-30 PRINT "THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR" 
-40 PRINT "LANDING CAPSULE.": PRINT: PRINT
-50 PRINT "THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY" 
-60 PRINT "XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY."
-70 PRINT: PRINT "SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN" 
-80 PRINT "0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND." 
-90 PRINT "SET NEW BURN RATE EVERY 10 SECONDS.": PRINT 
-100 PRINT "CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS."
-110 PRINT: PRINT: PRINT: PRINT "GOOD LUCK"
-120 L=0
-130 PRINT: PRINT "SEC","MI + FT","MPH","LB FUEL","BURN RATE":PRINT 
-140 A=120:V=1:M=33000:N=16500:G=1E-03:Z=1.8
-
-149 REM DWL capsule.prompt_for_burn
-150 PRINT L,INT(A);INT(5280*(A-INT(A))),3600*V,M-N,:INPUT K:T=10 
-
-159 REM main loop
-160 IF M-N<1E-03 THEN 240
-170 IF T<1E-03 THEN 150
-180 S=T: IF M>=N+S*K THEN 200
-190 S=(M-N)/K
-200 GOSUB 420: IF I<=0 THEN 340
-210 IF V<=0 THEN 230
-220 IF J<0 THEN 370
-230 GOSUB 330: GOTO 160
-
-239 REM DWL show_out_of_fuel
-240 PRINT "FUEL OUT AT";L;"SECONDS":S=(-V+SQR(V*V+2*A*G))/G
-250 V=V+G*S: L=L+S
-
-259 REM DWL show_landing
-260 W=3600*V: PRINT "ON MOON AT";L;"SECONDS - IMPACT VELOCITY";W;"MPH" 
-274 IF W<=1.2 THEN PRINT "PERFECT LANDING!": GOTO 440 
-280 IF W<=10 THEN PRINT "GOOD LANDING (COULD BE BETTER)":GOTO 440 
-282 IF W>60 THEN 300
-284 PRINT "CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE" 
-286 PRINT "PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!" 
-288 GOTO 440
-300 PRINT "SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!"
-310 PRINT "IN FACT, YOU BLASTED A NEW LUNAR CRATER";W*.227;"FEET DEEP!"
-320 GOTO 440
-
-329 REM DWL capsule.update_state
-330 L=L+S: T=T-S: M=M-S*K: A=I: V=J: RETURN
-
-339 REM DWL process_final_tick
-340 IF S<5E-03 THEN 260
-350 D=V+SQR(V*V+2*A*(G-Z*K/M)):S=2*A/D
-360 GOSUB 420: GOSUB 330: GOTO 340
-
-369 REM DWL handle_flyaway
-370 W=(1-M*G/(Z*K))/2: S=M*V/(Z*K*(W+SQR(W*W+V/Z)))+.05:GOSUB 420
-380 IF I<=0 THEN 340
-390 GOSUB 330: IF J>0 THEN 160
-400 IF V>0 THEN 370
-410 GOTO 160
-
-419 REM DWL capsule.predict_motion
-420 Q=S*K/M: J=V+G*S+Z*(-Q-Q*Q/2-Q^3/3-Q^4/4-Q^5/5)
-430 I=A-G*S*S/2-V*S+Z*S*(Q/2+Q^2/6+Q^3/12+Q^4/20+Q^5/30):RETURN
-
-439 REM DWL end_sim
-440 PRINT:PRINT:PRINT:PRINT "TRY AGAIN??": GOTO 70
-"""

From 3f1358e083cf02356296c54e8eef4c25abcd360b Mon Sep 17 00:00:00 2001
From: Marc Heiligers 
Date: Sat, 6 Mar 2021 15:46:40 -0700
Subject: [PATCH 256/749] Add some notes to README

---
 02 Amazing/ruby/README.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/02 Amazing/ruby/README.md b/02 Amazing/ruby/README.md
index fb32811e..8bf7896b 100644
--- a/02 Amazing/ruby/README.md	
+++ b/02 Amazing/ruby/README.md	
@@ -1,3 +1,9 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
 Conversion to [Ruby](https://www.ruby-lang.org/en/)
+
+Converted to Ruby (with tons of inspiration from the Python version) by @marcheiligers
+
+Run `ruby amazing.rb`.
+
+Run `DEBUG=1 ruby amazing.ruby` to see how it works (requires at least Ruby 2.7).

From 2766ff3f6918bc38265d0e69bf2619b08d39117e Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sat, 6 Mar 2021 14:53:23 -0800
Subject: [PATCH 257/749] Link to Super Star Trek instructions

mentioned instructions.txt in README.md
---
 84 Super Star Trek/README.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/84 Super Star Trek/README.md b/84 Super Star Trek/README.md
index a67e2eb8..495ce9ae 100644
--- a/84 Super Star Trek/README.md	
+++ b/84 Super Star Trek/README.md	
@@ -6,6 +6,9 @@ https://www.atariarchives.org/basicgames/showpage.php?page=157
 Downloaded from Vintage Basic at
 http://www.vintage-basic.net/games.html
 
+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
 

From 345545a27d452b5bda4b803bf992b711f6150242 Mon Sep 17 00:00:00 2001
From: Andrew Cooper 
Date: Sun, 7 Mar 2021 14:36:11 +1100
Subject: [PATCH 258/749] Add Photon Tubes

---
 84 Super Star Trek/csharp/Game.cs             |  6 +-
 84 Super Star Trek/csharp/Input.cs            |  6 +-
 .../csharp/Objects/Enterprise.cs              | 36 ++++++++-
 84 Super Star Trek/csharp/Objects/Klingon.cs  | 20 ++++-
 84 Super Star Trek/csharp/Objects/Starbase.cs |  5 +-
 .../csharp/Resources/CourtMartial.txt         |  3 +
 .../csharp/Resources/Protected.txt            |  1 +
 .../csharp/Resources/RelievedOfCommand.txt    |  3 +
 .../csharp/Resources/Strings.cs               |  3 +
 84 Super Star Trek/csharp/Space/Coordinate.cs | 28 +++++++
 84 Super Star Trek/csharp/Space/Course.cs     | 25 +++++-
 84 Super Star Trek/csharp/Space/Quadrant.cs   | 80 ++++++++++++++++---
 .../csharp/Space/QuadrantInfo.cs              | 17 +++-
 .../csharp/Systems/DamageControl.cs           |  4 +-
 .../csharp/Systems/LongRangeSensors.cs        | 21 ++---
 .../csharp/Systems/PhotonTubes.cs             | 63 +++++++++++++++
 .../csharp/Systems/ShieldControl.cs           | 22 ++---
 .../csharp/Systems/ShortRangeSensors.cs       |  4 +-
 .../csharp/Systems/Subsystem.cs               | 35 +++++++-
 19 files changed, 319 insertions(+), 63 deletions(-)
 create mode 100644 84 Super Star Trek/csharp/Resources/CourtMartial.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/Protected.txt
 create mode 100644 84 Super Star Trek/csharp/Resources/RelievedOfCommand.txt
 create mode 100644 84 Super Star Trek/csharp/Systems/PhotonTubes.cs

diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs
index 0547103b..6473877e 100644
--- a/84 Super Star Trek/csharp/Game.cs	
+++ b/84 Super Star Trek/csharp/Game.cs	
@@ -79,15 +79,14 @@ namespace SuperStarTrek
             _galaxy = new Galaxy();
             _initialKlingonCount = _galaxy.KlingonCount;
 
-            _enterprise = new Enterprise(3000, random.GetCoordinate(), _output);
+            _enterprise = new Enterprise(3000, random.GetCoordinate(), _output, random);
             _enterprise
                 .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
                 .Add(new LongRangeSensors(_galaxy, _output))
+                .Add(new PhotonTubes(10, _enterprise, _output, _input))
                 .Add(new ShieldControl(_enterprise, _output, _input))
                 .Add(new DamageControl(_enterprise, _output));
 
-            var quadrant = new Quadrant(_galaxy[_currentQuadrant], _enterprise);
-
             _output.Write(Strings.Enterprise);
             _output.Write(
                 Strings.Orders,
@@ -100,6 +99,7 @@ namespace SuperStarTrek
 
             _input.WaitForAnyKeyButEnter("when ready to accept command");
 
+            var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy);
             _enterprise.Enter(quadrant, Strings.StartText);
         }
 
diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs
index 0fba2e4c..c632007f 100644
--- a/84 Super Star Trek/csharp/Input.cs	
+++ b/84 Super Star Trek/csharp/Input.cs	
@@ -27,14 +27,14 @@ namespace SuperStarTrek
             return Console.ReadLine();
         }
 
-        public double GetNumber(string prompt)
+        public float GetNumber(string prompt)
         {
             _output.Prompt(prompt);
 
             while (true)
             {
                 var response = Console.ReadLine();
-                if (double.TryParse(response, out var value))
+                if (float.TryParse(response, out var value))
                 {
                     return value;
                 }
@@ -44,7 +44,7 @@ namespace SuperStarTrek
             }
         }
 
-        public bool TryGetNumber(string prompt, double minValue, double maxValue, out double value)
+        public bool TryGetNumber(string prompt, float minValue, float maxValue, out float value)
         {
             value = GetNumber($"{prompt} ({minValue}-{maxValue})");
 
diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs
index 97e5e3cd..ddaa10a9 100644
--- a/84 Super Star Trek/csharp/Objects/Enterprise.cs	
+++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs	
@@ -15,9 +15,10 @@ namespace SuperStarTrek.Objects
         private readonly Output _output;
         private readonly List _systems;
         private readonly Dictionary _commandExecutors;
+        private readonly Random _random;
         private Quadrant _quadrant;
 
-        public Enterprise(int maxEnergy, Coordinates sector, Output output)
+        public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random)
         {
             Sector = sector;
             TotalEnergy = _maxEnergy = maxEnergy;
@@ -25,6 +26,7 @@ namespace SuperStarTrek.Objects
             _systems = new List();
             _commandExecutors = new Dictionary();
             _output = output;
+            _random = random;
         }
 
         public Coordinates Quadrant => _quadrant.Coordinates;
@@ -88,5 +90,37 @@ namespace SuperStarTrek.Objects
         }
 
         public override string ToString() => "<*>";
+
+        internal CommandResult TakeHit(Coordinates sector, int hitStrength)
+        {
+            _output.WriteLine($"{hitStrength} unit hit on Enterprise from sector {sector}");
+            ShieldControl.AbsorbHit(hitStrength);
+
+            if (ShieldControl.ShieldEnergy <= 0)
+            {
+                _output.WriteLine(Strings.Destroyed);
+                return CommandResult.GameOver;
+            }
+
+            _output.WriteLine($"      ");
+
+            if (hitStrength >= 20)
+            {
+                TakeDamage(hitStrength);
+            }
+
+            return CommandResult.Ok;
+        }
+
+        private void TakeDamage(double hitStrength)
+        {
+            var hitShieldRatio = hitStrength / ShieldControl.ShieldEnergy;
+            if (_random.GetDouble() > 0.6 || hitShieldRatio <= 0.02)
+            {
+                return;
+            }
+
+            _systems[_random.Get1To8Inclusive() - 1].TakeDamage(hitShieldRatio + 0.5 * _random.GetDouble());
+        }
     }
 }
diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs
index fdf47031..0bbaf984 100644
--- a/84 Super Star Trek/csharp/Objects/Klingon.cs	
+++ b/84 Super Star Trek/csharp/Objects/Klingon.cs	
@@ -1,14 +1,30 @@
+using SuperStarTrek.Commands;
+using SuperStarTrek.Space;
+
 namespace SuperStarTrek.Objects
 {
     internal class Klingon
     {
         private double _energy;
+        private Coordinates _sector;
+        private readonly Random _random;
 
-        public Klingon()
+        public Klingon(Coordinates sector, Random random)
         {
-            _energy = new Random().GetDouble(100, 300);
+            _sector = sector;
+            _random = random;
+            _energy = _random.GetDouble(100, 300);
         }
 
         public override string ToString() => "+K+";
+
+        public CommandResult FireOn(Enterprise enterprise)
+        {
+            var attackStrength = _random.GetDouble();
+            var hitStrength = (int)(_energy * (2 + attackStrength) / _sector.GetDistanceTo(enterprise.Sector));
+            _energy /= 3 + attackStrength;
+
+            return enterprise.TakeHit(_sector, hitStrength);
+        }
     }
 }
diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs
index e11ca9f5..b96ffab1 100644
--- a/84 Super Star Trek/csharp/Objects/Starbase.cs	
+++ b/84 Super Star Trek/csharp/Objects/Starbase.cs	
@@ -8,10 +8,11 @@ namespace SuperStarTrek.Objects
         private readonly Output _output;
         private readonly double _repairDelay;
 
-        public Starbase(Random random, Input input)
+        public Starbase(Random random, Input input, Output output)
         {
             _repairDelay = random.GetDouble() * 0.5;
             _input = input;
+            _output = output;
         }
 
         public override string ToString() => ">!<";
@@ -34,5 +35,7 @@ namespace SuperStarTrek.Objects
             repairTime = 0;
             return false;
         }
+
+        internal void ProtectEnterprise() => _output.WriteLine(Strings.Protected);
     }
 }
diff --git a/84 Super Star Trek/csharp/Resources/CourtMartial.txt b/84 Super Star Trek/csharp/Resources/CourtMartial.txt
new file mode 100644
index 00000000..7d05a5b8
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/CourtMartial.txt	
@@ -0,0 +1,3 @@
+
+Starfleet Command reviewing your record to consider
+court martial!
\ No newline at end of file
diff --git a/84 Super Star Trek/csharp/Resources/Protected.txt b/84 Super Star Trek/csharp/Resources/Protected.txt
new file mode 100644
index 00000000..27c4a5f8
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/Protected.txt	
@@ -0,0 +1 @@
+Starbase shields protect the Enterprise
\ No newline at end of file
diff --git a/84 Super Star Trek/csharp/Resources/RelievedOfCommand.txt b/84 Super Star Trek/csharp/Resources/RelievedOfCommand.txt
new file mode 100644
index 00000000..8086e3ca
--- /dev/null
+++ b/84 Super Star Trek/csharp/Resources/RelievedOfCommand.txt	
@@ -0,0 +1,3 @@
+
+That does it, Captain!!  You are hereby relieved of command
+and sentenced to 99 stardates at hard labor on Cygnus 12!!
\ No newline at end of file
diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs
index 210d22ba..c76fe691 100644
--- a/84 Super Star Trek/csharp/Resources/Strings.cs	
+++ b/84 Super Star Trek/csharp/Resources/Strings.cs	
@@ -8,13 +8,16 @@ namespace SuperStarTrek.Resources
     {
         public static string CombatArea => GetResource();
         public static string Congratulations => GetResource();
+        public static string CourtMartial => GetResource();
         public static string Destroyed => GetResource();
         public static string EndOfMission => GetResource();
         public static string Enterprise => GetResource();
         public static string Instructions => GetResource();
         public static string LowShields => GetResource();
         public static string Orders => GetResource();
+        public static string Protected => GetResource();
         public static string RegionNames => GetResource();
+        public static string RelievedOfCommand => GetResource();
         public static string RepairEstimate => GetResource();
         public static string RepairPrompt => GetResource();
         public static string ReplayPrompt => GetResource();
diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinate.cs
index aa5b5285..b103a528 100644
--- a/84 Super Star Trek/csharp/Space/Coordinate.cs	
+++ b/84 Super Star Trek/csharp/Space/Coordinate.cs	
@@ -24,6 +24,34 @@ namespace SuperStarTrek.Space
             throw new ArgumentOutOfRangeException(argumentName, value, "Must be 0 to 7 inclusive");
         }
 
+        private static bool IsValid(int value) => value >= 0 && value <= 7;
+
         public override string ToString() => $"{X+1} , {Y+1}";
+
+        internal void Deconstruct(out int x, out int y)
+        {
+            x = X;
+            y = Y;
+        }
+
+        internal static bool TryCreate(float x, float y, out Coordinates coordinates)
+        {
+            var roundedX = Round(x);
+            var roundedY = Round(y);
+
+            if (IsValid(roundedX) && IsValid(roundedY))
+            {
+                coordinates = new Coordinates(roundedX, roundedY);
+                return true;
+            }
+
+            coordinates = default;
+            return false;
+
+            int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
+        }
+
+        internal float GetDistanceTo(Coordinates destination) =>
+            (float)Math.Sqrt(Math.Pow(X - destination.X, 2) + Math.Pow(Y - destination.Y, 2));
     }
 }
diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs
index dd9ecfba..99c48c1a 100644
--- a/84 Super Star Trek/csharp/Space/Course.cs	
+++ b/84 Super Star Trek/csharp/Space/Course.cs	
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 
 namespace SuperStarTrek.Space
 {
@@ -24,7 +25,7 @@ namespace SuperStarTrek.Space
             (0, 1)
         };
 
-        public Course(double direction)
+        public Course(float direction)
         {
             if (direction < 1 || direction > 9)
             {
@@ -44,7 +45,25 @@ namespace SuperStarTrek.Space
             DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
         }
 
-        public double DeltaX { get; }
-        public double DeltaY { get; }
+        public float DeltaX { get; }
+        public float DeltaY { get; }
+
+        public IEnumerable GetSectorsFrom(Coordinates start)
+        {
+            (double x, double y) = start;
+
+            while(true)
+            {
+                x += DeltaX;
+                y += DeltaY;
+
+                if (!Coordinates.TryCreate(x, y, out var coordinates))
+                {
+                    yield break;
+                }
+
+                yield return coordinates;
+            }
+        }
     }
 }
diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs
index e483604f..d89d60e0 100644
--- a/84 Super Star Trek/csharp/Space/Quadrant.cs	
+++ b/84 Super Star Trek/csharp/Space/Quadrant.cs	
@@ -1,7 +1,9 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using SuperStarTrek.Commands;
 using SuperStarTrek.Objects;
+using SuperStarTrek.Resources;
 
 namespace SuperStarTrek.Space
 {
@@ -10,43 +12,47 @@ namespace SuperStarTrek.Space
         private readonly QuadrantInfo _info;
         private readonly Random _random;
         private readonly Dictionary _sectors;
-        private readonly Coordinates _enterpriseSector;
+        private readonly Enterprise _enterprise;
         private readonly Coordinates _starbaseSector;
+        private readonly Galaxy _galaxy;
 
-        public Quadrant(QuadrantInfo info, Enterprise enterprise)
+        public Quadrant(QuadrantInfo info, Enterprise enterprise, Random random, Galaxy galaxy)
         {
             _info = info;
-            _random = new Random();
+            _random = random;
+            _galaxy = galaxy;
 
-            _enterpriseSector = enterprise.Sector;
-            _sectors = new Dictionary { [enterprise.Sector] = enterprise };
-            PositionObject(() => new Klingon(), _info.KlingonCount);
+            _sectors = new() { [enterprise.Sector] = _enterprise = enterprise };
+            PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
             if (_info.HasStarbase)
             {
-                _starbaseSector = PositionObject(() => new Starbase(_random, new Input(new Output())));
+                _starbaseSector = PositionObject(_ => new Starbase(_random, new Input(new Output()), new Output()));
             }
-            PositionObject(() => new Star(), _info.StarCount);
+            PositionObject(_ => new Star(), _info.StarCount);
         }
 
+        public object this[Coordinates coordinates] => _sectors.GetValueOrDefault(coordinates);
         public Coordinates Coordinates => _info.Coordinates;
         public bool HasKlingons => _info.KlingonCount > 0;
         public bool HasStarbase => _info.HasStarbase;
         public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null;
         public bool EnterpriseIsNextToStarbase =>
             _info.HasStarbase &&
-            Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 &&
-            Math.Abs(_enterpriseSector.Y - _starbaseSector.Y) <= 1;
+            Math.Abs(_enterprise.Sector.X - _starbaseSector.X) <= 1 &&
+            Math.Abs(_enterprise.Sector.Y - _starbaseSector.Y) <= 1;
+
+        private IEnumerable Klingons => _sectors.Values.OfType();
 
         public override string ToString() => _info.Name;
 
-        private Coordinates PositionObject(Func objectFactory)
+        private Coordinates PositionObject(Func objectFactory)
         {
             var sector = GetRandomEmptySector();
-            _sectors[sector] = objectFactory.Invoke();
+            _sectors[sector] = objectFactory.Invoke(sector);
             return sector;
         }
 
-        private void PositionObject(Func objectFactory, int count)
+        private void PositionObject(Func objectFactory, int count)
         {
             for (int i = 0; i < count; i++)
             {
@@ -54,6 +60,54 @@ namespace SuperStarTrek.Space
             }
         }
 
+        internal bool TorpedoCollisionAt(Coordinates coordinates, out string message, out bool gameOver)
+        {
+            gameOver = false;
+            message = default;
+
+            switch (_sectors.GetValueOrDefault(coordinates))
+            {
+                case Klingon _:
+                    _sectors.Remove(coordinates);
+                    _info.RemoveKlingon();
+                    message = "*** Klingon destroyed ***";
+                    gameOver = _galaxy.KlingonCount == 0;
+                    return true;
+
+                case Star _:
+                    message = $"Star at {coordinates} absorbed torpedo energy.";
+                    return true;
+
+                case Starbase _:
+                    _sectors.Remove(coordinates);
+                    _info.RemoveStarbase();
+                    message = "*** Starbase destroyed ***" +
+                        (_galaxy.StarbaseCount > 0 ? Strings.CourtMartial : Strings.RelievedOfCommand);
+                    gameOver = _galaxy.StarbaseCount == 0;
+                    return true;
+
+                default:
+                    return false;
+            }
+        }
+
+        internal CommandResult KlingonsFireOnEnterprise()
+        {
+            if (EnterpriseIsNextToStarbase && Klingons.Any())
+            {
+                Starbase.ProtectEnterprise();
+                return CommandResult.Ok;
+            }
+
+            foreach (var klingon in Klingons)
+            {
+                var result = klingon.FireOn(_enterprise);
+                if (result.IsGameOver) { return result; }
+            }
+
+            return CommandResult.Ok;
+        }
+
         private Coordinates GetRandomEmptySector()
         {
             while (true)
diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs
index 20f21ee2..284c8c84 100644
--- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs	
+++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs	
@@ -1,3 +1,5 @@
+using SuperStarTrek.Objects;
+
 namespace SuperStarTrek.Space
 {
     internal class QuadrantInfo
@@ -39,12 +41,25 @@ namespace SuperStarTrek.Space
 
         internal void AddStarbase() => HasStarbase = true;
 
-        public string Scan()
+        internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy) =>
+            new(this, enterprise, random, galaxy);
+
+        internal string Scan()
         {
             _isKnown = true;
             return ToString();
         }
 
         public override string ToString() => _isKnown ? $"{KlingonCount}{(HasStarbase ? 1 : 0)}{StarCount}" : "***";
+
+        internal void RemoveKlingon()
+        {
+            if (KlingonCount > 0)
+            {
+                KlingonCount -= 1;
+            }
+        }
+
+        internal void RemoveStarbase() => HasStarbase = false;
     }
 }
diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84 Super Star Trek/csharp/Systems/DamageControl.cs
index b4587add..25f5ad78 100644
--- a/84 Super Star Trek/csharp/Systems/DamageControl.cs	
+++ b/84 Super Star Trek/csharp/Systems/DamageControl.cs	
@@ -10,13 +10,13 @@ namespace SuperStarTrek.Systems
         private readonly Output _output;
 
         public DamageControl(Enterprise enterprise, Output output)
-            : base("Damage Control", Command.DAM)
+            : base("Damage Control", Command.DAM, output)
         {
             _enterprise = enterprise;
             _output = output;
         }
 
-        public override CommandResult ExecuteCommand(Quadrant quadrant)
+        protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
         {
             if (IsDamaged)
             {
diff --git a/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs b/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs
index 233af4a6..84ed7a87 100644
--- a/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs	
+++ b/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs	
@@ -15,27 +15,22 @@ namespace SuperStarTrek.Systems
         private readonly Output _output;
 
         public LongRangeSensors(Galaxy galaxy, Output output)
-            : base("Long Range Sensors", Command.LRS)
+            : base("Long Range Sensors", Command.LRS, output)
         {
             _galaxy = galaxy;
             _output = output;
         }
 
-        public override CommandResult ExecuteCommand(Quadrant quadrant)
+        protected override bool CanExecuteCommand() => IsOperational("{name} are inoperable");
+
+        protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
         {
-            if (Condition < 0)
+            _output.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}");
+            _output.WriteLine("-------------------");
+            foreach (var quadrants in _galaxy.GetNeighborhood(quadrant))
             {
-                _output.WriteLine("Long Range Sensors are inoperable");
-            }
-            else
-            {
-                _output.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}");
+                _output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
                 _output.WriteLine("-------------------");
-                foreach (var quadrants in _galaxy.GetNeighborhood(quadrant))
-                {
-                    _output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
-                    _output.WriteLine("-------------------");
-                }
             }
 
             return CommandResult.Ok;
diff --git a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs
new file mode 100644
index 00000000..034199c9
--- /dev/null
+++ b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs	
@@ -0,0 +1,63 @@
+using SuperStarTrek.Commands;
+using SuperStarTrek.Objects;
+using SuperStarTrek.Space;
+
+namespace SuperStarTrek.Systems
+{
+    internal class PhotonTubes : Subsystem
+    {
+        private readonly int _tubeCount;
+        private readonly Enterprise _enterprise;
+        private readonly Output _output;
+        private readonly Input _input;
+
+        public PhotonTubes(int tubeCount, Enterprise enterprise, Output output, Input input)
+            : base("Photon Tubes", Command.TOR, output)
+        {
+            TorpedoCount = _tubeCount = tubeCount;
+            _enterprise = enterprise;
+            _output = output;
+            _input = input;
+        }
+
+        public int TorpedoCount { get; private set; }
+
+        protected override bool CanExecuteCommand() => HasTorpedoes() && IsOperational("{name} are not operational");
+
+        private bool HasTorpedoes()
+        {
+            if (TorpedoCount > 0) { return true; }
+
+            _output.WriteLine("All photon torpedoes expended");
+            return false;
+        }
+
+        protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+        {
+            if (!_input.TryGetNumber("Photon torpedo course", 1, 9, out var direction))
+            {
+                _output.WriteLine("Ensign Chekov reports, 'Incorrect course data, sir!'");
+                return CommandResult.Ok;
+            }
+
+            var isHit = false;
+            _output.WriteLine("Torpedo track:");
+            foreach (var sector in new Course(direction).GetSectorsFrom(_enterprise.Sector))
+            {
+                _output.WriteLine($"                {sector}");
+
+                if (quadrant.TorpedoCollisionAt(sector, out var message, out var gameOver))
+                {
+                    _output.WriteLine(message);
+                    isHit = true;
+                    if (gameOver) { return CommandResult.GameOver; }
+                    break;
+                }
+            }
+
+            if (!isHit) { _output.WriteLine("Torpedo missed!"); }
+
+            return quadrant.KlingonsFireOnEnterprise();
+        }
+    }
+}
diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs
index 9c4a3c16..48320588 100644
--- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
+++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
@@ -11,7 +11,7 @@ namespace SuperStarTrek.Systems
         private readonly Input _input;
 
         public ShieldControl(Enterprise enterprise, Output output, Input input)
-            : base("Shield Control", Command.SHE)
+            : base("Shield Control", Command.SHE, output)
         {
             _enterprise = enterprise;
             _output = output;
@@ -20,21 +20,9 @@ namespace SuperStarTrek.Systems
 
         public double ShieldEnergy { get; private set; }
 
-        public override CommandResult ExecuteCommand(Quadrant quadrant)
-        {
-            if (Condition < 0)
-            {
-                _output.WriteLine("Shield Control inoperable");
-            }
-            else
-            {
-                UpdateShields();
-            }
+        protected override bool CanExecuteCommand() => IsOperational("{name} inoperable");
 
-            return CommandResult.Ok;
-        }
-
-        private void UpdateShields()
+        protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
         {
             _output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
             var requested = _input.GetNumber($"Number of units to shields");
@@ -47,6 +35,8 @@ namespace SuperStarTrek.Systems
             {
                 _output.WriteLine("");
             }
+
+            return CommandResult.Ok;
         }
 
         private bool Validate(double requested)
@@ -59,5 +49,7 @@ namespace SuperStarTrek.Systems
 
             return requested >= 0 && requested != ShieldEnergy;
         }
+
+        internal void AbsorbHit(int hitStrength) => ShieldEnergy -= hitStrength;
     }
 }
diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs
index 953ec66e..e01c829e 100644
--- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs	
+++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs	
@@ -17,7 +17,7 @@ namespace SuperStarTrek.Systems
         private readonly Output _output;
 
         public ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, Output output)
-            : base("Short Range Sensors", Command.SRS)
+            : base("Short Range Sensors", Command.SRS, output)
         {
             _enterprise = enterprise;
             _galaxy = galaxy;
@@ -25,7 +25,7 @@ namespace SuperStarTrek.Systems
             _output = output;
         }
 
-        public override CommandResult ExecuteCommand(Quadrant quadrant)
+        protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
         {
             if (_enterprise.IsDocked)
             {
diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs
index 53398b41..88924a8c 100644
--- a/84 Super Star Trek/csharp/Systems/Subsystem.cs	
+++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs	
@@ -1,3 +1,4 @@
+using System;
 using SuperStarTrek.Commands;
 using SuperStarTrek.Space;
 
@@ -5,11 +6,14 @@ namespace SuperStarTrek.Systems
 {
     internal abstract class Subsystem
     {
-        protected Subsystem(string name, Command command)
+        private readonly Output _output;
+
+        protected Subsystem(string name, Command command, Output output)
         {
             Name = name;
             Command = command;
             Condition = 0;
+            _output = output;
         }
 
         public string Name { get; }
@@ -17,10 +21,33 @@ namespace SuperStarTrek.Systems
         public bool IsDamaged => Condition < 0;
         public Command Command { get; }
 
-        public abstract CommandResult ExecuteCommand(Quadrant quadrant);
-        public void Repair()
+        protected virtual bool CanExecuteCommand() => true;
+
+        protected bool IsOperational(string notOperationalMessage)
         {
-            if (Condition < 0) { Condition = 0; }
+            if (IsDamaged)
+            {
+                _output.WriteLine(notOperationalMessage.Replace("{name}", Name));
+                return false;
+            }
+
+            return true;
+        }
+
+        public CommandResult ExecuteCommand(Quadrant quadrant)
+            => CanExecuteCommand() ? ExecuteCommandCore(quadrant) : CommandResult.Ok;
+
+        protected abstract CommandResult ExecuteCommandCore(Quadrant quadrant);
+
+        public virtual void Repair()
+        {
+            if (IsDamaged) { Condition = 0; }
+        }
+
+        internal void TakeDamage(double damage)
+        {
+            Condition -= damage;
+            _output.WriteLine($"Damage Control reports, '{Name} damaged by the hit.'");
         }
     }
 }

From 528c9e69f62db78d867626efa1841f9078fbe0af Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 6 Mar 2021 22:15:18 -0600
Subject: [PATCH 259/749] Ported TARGET to Javascript

---
 86 Target/javascript/target.html |   9 ++
 86 Target/javascript/target.js   | 157 +++++++++++++++++++++++++++++++
 2 files changed, 166 insertions(+)
 create mode 100644 86 Target/javascript/target.html
 create mode 100644 86 Target/javascript/target.js

diff --git a/86 Target/javascript/target.html b/86 Target/javascript/target.html
new file mode 100644
index 00000000..97bba5ea
--- /dev/null
+++ b/86 Target/javascript/target.html	
@@ -0,0 +1,9 @@
+
+
+TARGET
+
+
+

+
+
+
diff --git a/86 Target/javascript/target.js b/86 Target/javascript/target.js
new file mode 100644
index 00000000..e61fba8b
--- /dev/null
+++ b/86 Target/javascript/target.js	
@@ -0,0 +1,157 @@
+// TARGET
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "TARGET\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    r = 0;  // 1 in original
+    r1 = 57.296;
+    p = Math.PI;
+    print("YOU ARE THE WEAPONS OFFICER ON THE STARSHIP ENTERPRISE\n");
+    print("AND THIS IS A TEST TO SEE HOW ACCURATE A SHOT YOU\n");
+    print("ARE IN A THREE-DIMENSIONAL RANGE.  YOU WILL BE TOLD\n");
+    print("THE RADIAN OFFSET FOR THE X AND Z AXES, THE LOCATION\n");
+    print("OF THE TARGET IN THREE DIMENSIONAL RECTANGULAR COORDINATES,\n");
+    print("THE APPROXIMATE NUMBER OF DEGREES FROM THE X AND Z\n");
+    print("AXES, AND THE APPROXIMATE DISTANCE TO THE TARGET.\n");
+    print("YOU WILL THEN PROCEEED TO SHOOT AT THE TARGET UNTIL IT IS\n");
+    print("DESTROYED!\n");
+    print("\n");
+    print("GOOD LUCK!!\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        a = Math.random() * 2 * p;
+        b = Math.random() * 2 * p;
+        q = Math.floor(a * r1);
+        w = Math.floor(b * r1);
+        print("RADIANS FROM X AXIS = " + a + "   FROM Z AXIS = " + b + "\n");
+        p1 = 100000 * Math.random() + Math.random();
+        x = Math.sin(b) * Math.cos(a) * p1;
+        y = Math.sin(b) * Math.sin(a) * p1;
+        z = Math.cos(b) * p1;
+        print("TARGET SIGHTED: APPROXIMATE COORDINATES:  X=" + x + "  Y=" + y + "  Z=" + z + "\n");
+        while (1) {
+            r++;
+            switch (r) {
+                case 1:
+                    p3 = Math.floor(p1 * 0.05) * 20;
+                    break;
+                case 2:
+                    p3 = Math.floor(p1 * 0.1) * 10;
+                    break;
+                case 3:
+                    p3 = Math.floor(p1 * 0.5) * 2;
+                    break;
+                case 4:
+                    p3 = Math.floor(p1);
+                    break;
+                case 5:
+                    p3 = p1;
+                    break;
+            }
+            print("     ESTIMATED DISTANCE: " + p3 + "\n");
+            print("\n");
+            print("INPUT ANGLE DEVIATION FROM X, DEVIATION FROM Z, DISTANCE");
+            str = await input();
+            a1 = parseInt(str);
+            b1 = parseInt(str.substr(str.indexOf(",") + 1));
+            p2 = parseInt(str.substr(str.lastIndexOf(",") + 1));
+            print("\n");
+            if (p2 < 20) {
+                print("YOU BLEW YOURSELF UP!!\n");
+                break;
+            }
+            a1 /= r1;
+            b1 /= r1;
+            print("RADIANS FROM X AXIS = " + a1 + "  ");
+            print("FROM Z AXIS = " + b1 + "\n");
+            x1 = p2 * Math.sin(b1) * Math.cos(a1);
+            y1 = p2 * Math.sin(b1) * Math.sin(a1);
+            z1 = p2 * Math.cos(b1);
+            d = Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y) + (z1 - z) * (z1 - z));
+            if (d <= 20) {
+                print("\n");
+                print(" * * * HIT * * *   TARGET IS NON-FUNCTIONAL\n");
+                print("\n");
+                print("DISTANCE OF EXPLOSION FROM TARGET WAS " + d + " KILOMETERS.");
+                print("\n");
+                print("MISSION ACCOMPLISHED IN " + r + " SHOTS.\n");
+                r = 0;
+                for (i = 1; i <= 5; i++)
+                    print("\n");
+                print("NEXT TARGET...\n");
+                print("\n");
+                break;
+            }
+            x2 = x1 - x;
+            y2 = y1 - y;
+            z2 = z1 - z;
+            if (x2 >= 0)
+                print("SHOT IN FRONT OF TARGET " + x2 + " KILOMETERS.\n");
+            else
+                print("SHOT BEHIND TARGET " + -x2 + " KILOMETERS.\n");
+            if (y2 >= 0)
+                print("SHOT TO LEFT OF TARGET " + y2 + " KILOMETERS.\n");
+            else
+                print("SHOT TO RIGHT OF TARGET " + -y2 + " KILOMETERS.\n");
+            if (z2 >= 0)
+                print("SHOT ABOVE TARGET " + z2 + " KILOMETERS.\n");
+            else
+                print("SHOT BELOW TARGET " + -z2 + " KILOMETERS.\n");
+            print("APPROX POSITION OF EXPLOSION:  X=" + x1 + "   Y=" + y1 + "   Z=" + z1 + "\n");
+            print("     DISTANCE FROM TARGET = " + d + "\n");
+            print("\n");
+            print("\n");
+            print("\n");
+        }
+    }
+}
+
+main();

From 64775c4b2af39bd8c366e82c70c2262dace2fef8 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 6 Mar 2021 23:15:20 -0600
Subject: [PATCH 260/749] Ported SPLAT to Javascript

---
 81 Splat/javascript/splat.html |   9 ++
 81 Splat/javascript/splat.js   | 283 +++++++++++++++++++++++++++++++++
 2 files changed, 292 insertions(+)
 create mode 100644 81 Splat/javascript/splat.html
 create mode 100644 81 Splat/javascript/splat.js

diff --git a/81 Splat/javascript/splat.html b/81 Splat/javascript/splat.html
new file mode 100644
index 00000000..19503973
--- /dev/null
+++ b/81 Splat/javascript/splat.html	
@@ -0,0 +1,9 @@
+
+
+SPLAT
+
+
+

+
+
+
diff --git a/81 Splat/javascript/splat.js b/81 Splat/javascript/splat.js
new file mode 100644
index 00000000..e037d190
--- /dev/null
+++ b/81 Splat/javascript/splat.js	
@@ -0,0 +1,283 @@
+// SPLAT
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var aa = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "SPLAT\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 0; i <= 42; i++)
+        aa[i] = 0;
+    print("WELCOME TO 'SPLAT' -- THE GAME THAT SIMULATES A PARACHUTE\n");
+    print("JUMP.  TRY TO OPEN YOUR CHUTE AT THE LAST POSSIBLE\n");
+    print("MOMENT WITHOUT GOING SPLAT.\n");
+    while (1) {
+        print("\n");
+        print("\n");
+        d1 = 0;
+        v = 0;
+        a = 0;
+        n = 0;
+        m = 0;
+        d1 = Math.floor(9001 * Math.random() + 1000);
+        print("SELECT YOUR OWN TERMINAL VELOCITY (YES OR NO)");
+        while (1) {
+            a1s = await input();
+            if (a1s == "YES" || a1s == "NO")
+                break;
+            print("YES OR NO");
+        }
+        if (a1s == "YES") {
+            print("WHAT TERMINAL VELOCITY (MI/HR)");
+            v1 = parseFloat(await input());
+            v1 = v1 * (5280 / 3600);
+        } else {
+            v1 = Math.floor(1000 * Math.random());
+            print("OK.  TERMINAL VELOCITY = " + v1 + " MI/HR\n");
+        }
+        v = v1 + ((v1 * Math.random()) / 20) - ((v1 * Math.random()) / 20);
+        print("WANT TO SELECT ACCELERATION DUE TO GRAVITY (YES OR NO)");
+        while (1) {
+            b1s = await input();
+            if (b1s == "YES" || b1s == "NO")
+                break;
+            print("YES OR NO");
+        }
+        if (b1s == "YES") {
+            print("WHAT ACCELERATION (FT/SEC/SEC)");
+            a2 = parseFloat(await input());
+        } else {
+            switch (Math.floor(1 + (10 * Math.random()))) {
+                case 1:
+                    print("FINE. YOU'RE ON MERCURY. ACCELERATION=12.2 FT/SEC/SEC.\n");
+                    a2 = 12.2;
+                    break;
+                case 2:
+                    print("ALL RIGHT. YOU'RE ON VENUS. ACCELERATION=28.3 FT/SEC/SEC.\n");
+                    a2 = 28.3;
+                    break;
+                case 3:
+                    print("THEN YOU'RE ON EARTH. ACCELERATION=32.16 FT/SEC/SEC.\n");
+                    a2 = 32.16;
+                    break;
+                case 4:
+                    print("FINE. YOU'RE ON THE MOON. ACCELERATION=5.15 FT/SEC/SEC.\n");
+                    a2 = 5.15;
+                    break;
+                case 5:
+                    print("ALL RIGHT. YOU'RE ON MARS. ACCELERATION=12.5 FT/SEC/SEC.\n");
+                    a2 = 12.5;
+                    break;
+                case 6:
+                    print("THEN YOU'RE ON JUPITER. ACCELERATION=85.2 FT/SEC/SEC.\n");
+                    a2 = 85.2;
+                    break;
+                case 7:
+                    print("FINE. YOU'RE ON SATURN. ACCELERATION=37.6 FT/SEC/SEC.\n");
+                    a2 = 37.6;
+                    break;
+                case 8:
+                    print("ALL RIGHT. YOU'RE ON URANUS. ACCELERATION=33.8 FT/SEC/SEC.\n");
+                    a2 = 33.8;
+                    break;
+                case 9:
+                    print("THEN YOU'RE ON NEPTUNE. ACCELERATION=39.6 FT/SEC/SEC.\n");
+                    a2 = 39.6;
+                    break;
+                case 10:
+                    print("FINE. YOU'RE ON THE SUN. ACCELERATION=896 FT/SEC/SEC.\n");
+                    a2 = 896;
+                    break;
+            }
+        }
+        a = a2 + ((a2 * Math.random()) / 20) - ((a2 * Math.random()) / 20);
+        print("\n");
+        print("    ALTITUDE         = " + d1 + " FT\n");
+        print("    TERM. VELOCITY   = " + v1 + " FT/SEC +/-5%\n");
+        print("    ACCELERATION     = " + a2 + " FT/SEC/SEC +/-5%\n");
+        print("SET THE TIMER FOR YOUR FREEFALL.\n");
+        print("HOW MANY SECONDS");
+        t = parseFloat(await input());
+        print("HERE WE GO.\n");
+        print("\n");
+        print("TIME (SEC)\tDIST TO FALL (FT)\n");
+        print("==========\t=================\n");
+        terminal = false;
+        crash = false;
+        for (i = 0; i <= t; i += t / 8) {
+            if (i > v / a) {
+                terminal = true;
+                break;
+            }
+            d = d1 - ((a / 2) * Math.pow(i, 2));
+            if (d <= 0) {
+                print(Math.sqrt(2 * d1 / a) + "\tSPLAT\n");
+                crash = true;
+                break;
+            }
+            print(i + "\t" + d + "\n");
+        }
+        if (terminal) {
+            print("TERMINAL VELOCITY REACHED AT T PLUS " + v/a + " SECONDS.\n");
+            for (; i <= t; i += t / 8) {
+                d = d1 - ((Math.pow(v, 2) / (2 * a)) + (v * (i - (v / a))));
+                if (d <= 0) {
+                    print(((v / a) + ((d1 - (Math.pow(v, 2) / (2 * a))) / v)) + "\tSPLAT\n");
+                    crash = true;
+                    break;
+                }
+                print(i + "\t" + d + "\n");
+            }
+        }
+        if (!crash) {
+            print("CHUTE OPEN\n");
+            k = 0;
+            k1 = 0;
+            for (j = 0; j <= 42; j++) {
+                if (aa[j] == 0)
+                    break;
+                k++;
+                if (d < aa[j])
+                    k1++;
+            }
+            // In original jumps to line 540 (undefined) when table is full
+            aa[j] = d;
+            if (j <= 2) {
+                print("AMAZING!!! NOT BAD FOR YOUR ");
+                if (j == 0)
+                    print("1ST ");
+                else if (j == 1)
+                    print("2ND ");
+                else
+                    print("3RD ");
+                print("SUCCESSFUL JUMP!!!\n");
+            } else {
+                if (k - k1 <= 0.1 * k) {
+                    print("WOW!  THAT'S SOME JUMPING.  OF THE " + k + " SUCCESSFUL JUMPS\n");
+                    print("BEFORE YOURS, ONLY " + (k - k1) + " OPENED THEIR CHUTES LOWER THAN\n");
+                    print("YOU DID.\n");
+                } else if (k - k1 <= 0.25 * k) {
+                    print("PRETTY GOOD! " + k + " SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n");
+                    print((k - k1) + " OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n");
+                    print("OPENED.\n");
+                } else if (k - k1 <= 0.5 * k) {
+                    print("NOT BAD.  THERE HAVE BEEN " + k + " SUCCESSFUL JUMPS BEFORE YOURS.\n");
+                    print("YOU WERE BEATEN OUT BY " + (k - k1) + " OF THEM.\n");
+                } else if (k - k1 <= 0.75 * k) {
+                    print("CONSERVATIVE, AREN'T YOU?  YOU RANKED ONLY " + (k - k1) + " IN THE\n");
+                    print(k + " SUCCESSFUL JUMPS BEFORE YOURS.\n");
+                } else if (k - k1 <= 0.9 * k) {
+                    print("HUMPH!  DON'T YOU HAVE ANY SPORTING BLOOD?  THERE WERE\n");
+                    print(k + " SUCCESSFUL JUMPS BEFORE YOURS AND YOU CAME IN " + k1 + "JUMPS\n");
+                    print("BETTER THAN THE WORST.  SHAPE UP!!!\n");
+                } else {
+                    print("HEY!  YOU PULLED THE RIP CORD MUCH TOO SOON.  " + k + " SUCCESSFUL\n");
+                    print("JUMPS BEFORE YOURS AND YOU CAME IN NUMBER " + (k - k1) + "!  GET WITH IT!\n");
+                }
+            }
+        } else {
+            switch (Math.floor(1 + 10 * Math.random())) {
+                case 1:
+                    print("REQUIESCAT IN PACE.\n");
+                    break;
+                case 2:
+                    print("MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE.\n");
+                    break;
+                case 3:
+                    print("REST IN PEACE.\n");
+                    break;
+                case 4:
+                    print("SON-OF-A-GUN.\n");
+                    break;
+                case 5:
+                    print("#%&&%!$\n");
+                    break;
+                case 6:
+                    print("A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT.\n");
+                    break;
+                case 7:
+                    print("HMMM. SHOULD HAVE PICKED A SHORTER TIME.\n");
+                    break;
+                case 8:
+                    print("MUTTER. MUTTER. MUTTER.\n");
+                    break;
+                case 9:
+                    print("PUSHING UP DAISIES.\n");
+                    break;
+                case 10:
+                    print("EASY COME, EASY GO.\n");
+                    break;
+            }
+            print("I'LL GIVE YOU ANOTHER CHANCE.\n");
+        }
+        while (1) {
+            print("DO YOU WANT TO PLAY AGAIN");
+            str = await input();
+            if (str == "YES" || str == "NO")
+                break;
+            print("YES OR NO\n");
+        }
+        if (str == "YES")
+            continue;
+        print("PLEASE");
+        while (1) {
+            str = await input();
+            if (str == "YES" || str == "NO")
+                break;
+            print("YES OR NO");
+        }
+        if (str == "YES")
+            continue;
+        break;
+    }
+    print("SSSSSSSSSS.\n");
+    print("\n");
+}
+
+main();

From d6d7123bb3a9a226e512c33a789980a327b95bf6 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 6 Mar 2021 23:33:44 -0600
Subject: [PATCH 261/749] Ported SLOTS to Javascript

---
 80 Slots/javascript/slots.html |   9 +++
 80 Slots/javascript/slots.js   | 135 +++++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+)
 create mode 100644 80 Slots/javascript/slots.html
 create mode 100644 80 Slots/javascript/slots.js

diff --git a/80 Slots/javascript/slots.html b/80 Slots/javascript/slots.html
new file mode 100644
index 00000000..33b8e73f
--- /dev/null
+++ b/80 Slots/javascript/slots.html	
@@ -0,0 +1,9 @@
+
+
+SLOTS
+
+
+

+
+
+
diff --git a/80 Slots/javascript/slots.js b/80 Slots/javascript/slots.js
new file mode 100644
index 00000000..2bafd26e
--- /dev/null
+++ b/80 Slots/javascript/slots.js	
@@ -0,0 +1,135 @@
+// SLOTS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var figures = [, "BAR", "BELL", "ORANGE", "LEMON", "PLUM", "CHERRY"];
+
+// Main program
+async function main()
+{
+    print(tab(30) + "SLOTS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // Produced by Fred Mirabelle and Bob Harper on Jan 29, 1973
+    // It simulates the slot machine.
+    print("YOU ARE IN THE H&M CASINO,IN FRONT ON ONE OF OUR\n");
+    print("ONE-ARM BANDITS. BET FROM $1 TO $100.\n");
+    print("TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET.\n");
+    p = 0;
+    while (1) {
+        while (1) {
+            print("\n");
+            print("YOUR BET");
+            m = parseInt(await input());
+            if (m > 100) {
+                print("HOUSE LIMITS ARE $100\n");
+            } else if (m < 1) {
+                print("MINIMUM BET IS $1\n");
+            } else {
+                break;
+            }
+        }
+        // Not implemented: GOSUB 1270 ten chimes
+        print("\n");
+        x = Math.floor(6 * Math.random() + 1);
+        y = Math.floor(6 * Math.random() + 1);
+        z = Math.floor(6 * Math.random() + 1);
+        print("\n");
+        // Not implemented: GOSUB 1310 seven chimes after figure x and y
+        print(figures[x] + " " + figures[y] + " " + figures[z] + "\n");
+        lost = false;
+        if (x == y && y == z) {  // Three figure
+            print("\n");
+            if (z != 1) {
+                print("**TOP DOLLAR**\n");
+                p += ((10 * m) + m);
+            } else {
+                print("***JACKPOT***\n");
+                p += ((100 * m) + m);
+            }
+            print("YOU WON!\n");
+        } else if (x == y || y == z || x == z) {
+            if (x == y)
+                c = x;
+            else
+                c = z;
+            if (c == 1) {
+                print("\n");
+                print("*DOUBLE BAR*\n");
+                print("YOU WON\n");
+                p += ((5 * m) + m);
+            } else if (x != z) {
+                print("\n");
+                print("DOUBLE!!\n");
+                print("YOU WON!\n");
+                p += ((2 * m) + m);
+            } else {
+                lost = true;
+            }
+        } else {
+            lost = true;
+        }
+        if (lost) {
+            print("\n");
+            print("YOU LOST.\n");
+            p -= m;
+        }
+        print("YOUR STANDINGS ARE $" + p + "\n");
+        print("AGAIN");
+        str = await input();
+        if (str.substr(0, 1) != "Y")
+            break;
+    }
+    print("\n");
+    if (p < 0) {
+        print("PAY UP!  PLEASE LEAVE YOUR MONEY ON THE TERMINAL.\n");
+    } else if (p == 0) {
+        print("HEY, YOU BROKE EVEN.\n");
+    } else {
+        print("COLLECT YOUR WINNINGS FROM THE H&M CASHIER.\n");
+    }
+}
+
+main();

From d0ed8d2f35c74fe23fa2877320bd30e2842e8b60 Mon Sep 17 00:00:00 2001
From: Andrew Cooper 
Date: Sun, 7 Mar 2021 18:27:55 +1100
Subject: [PATCH 262/749] Reduce precision to float

---
 84 Super Star Trek/csharp/Commands/CommandResult.cs |  6 +++---
 84 Super Star Trek/csharp/Game.cs                   |  8 ++++----
 84 Super Star Trek/csharp/Objects/Enterprise.cs     | 12 ++++++------
 84 Super Star Trek/csharp/Objects/Klingon.cs        |  6 +++---
 84 Super Star Trek/csharp/Objects/Starbase.cs       | 10 +++++-----
 84 Super Star Trek/csharp/Random.cs                 |  8 ++++----
 84 Super Star Trek/csharp/Space/Course.cs           |  2 +-
 84 Super Star Trek/csharp/Space/QuadrantInfo.cs     | 10 +++++-----
 84 Super Star Trek/csharp/Systems/ShieldControl.cs  |  4 ++--
 84 Super Star Trek/csharp/Systems/Subsystem.cs      |  4 ++--
 10 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/84 Super Star Trek/csharp/Commands/CommandResult.cs b/84 Super Star Trek/csharp/Commands/CommandResult.cs
index d92fba09..1b02780c 100644
--- a/84 Super Star Trek/csharp/Commands/CommandResult.cs	
+++ b/84 Super Star Trek/csharp/Commands/CommandResult.cs	
@@ -10,14 +10,14 @@ namespace SuperStarTrek.Commands
             IsGameOver = isGameOver;
         }
 
-        private CommandResult(double timeElapsed)
+        private CommandResult(float timeElapsed)
         {
             TimeElapsed = timeElapsed;
         }
 
         public bool IsGameOver { get; }
-        public double TimeElapsed { get; }
+        public float TimeElapsed { get; }
 
-        public static CommandResult Elapsed(double timeElapsed) => new(timeElapsed);
+        public static CommandResult Elapsed(float timeElapsed) => new(timeElapsed);
     }
 }
diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs
index 6473877e..0d5539ba 100644
--- a/84 Super Star Trek/csharp/Game.cs	
+++ b/84 Super Star Trek/csharp/Game.cs	
@@ -14,7 +14,7 @@ namespace SuperStarTrek
 
         private int _initialStardate;
         private int _finalStarDate;
-        private double _currentStardate;
+        private float _currentStardate;
         private Coordinates _currentQuadrant;
         private Coordinates _currentSector;
         private Galaxy _galaxy;
@@ -27,7 +27,7 @@ namespace SuperStarTrek
             _input = new Input(_output);
         }
 
-        public double Stardate => _currentStardate;
+        public float Stardate => _currentStardate;
 
         public void DoIntroduction()
         {
@@ -111,7 +111,7 @@ namespace SuperStarTrek
             return _enterprise.IsStranded;
         }
 
-        private double GetEfficiency() =>
-            1000 * Math.Pow(_initialKlingonCount / (_currentStardate - _initialStardate), 2);
+        private float GetEfficiency() =>
+            1000 * (float)Math.Pow(_initialKlingonCount / (_currentStardate - _initialStardate), 2);
     }
 }
diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs
index ddaa10a9..ed11bb1e 100644
--- a/84 Super Star Trek/csharp/Objects/Enterprise.cs	
+++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs	
@@ -33,8 +33,8 @@ namespace SuperStarTrek.Objects
         public Coordinates Sector { get; }
         public string Condition => GetCondition();
         public ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE];
-        public double Energy => TotalEnergy - ShieldControl.ShieldEnergy;
-        public double TotalEnergy { get; private set; }
+        public float Energy => TotalEnergy - ShieldControl.ShieldEnergy;
+        public float TotalEnergy { get; private set; }
         public int DamagedSystemCount => _systems.Count(s => s.IsDamaged);
         public IEnumerable Systems => _systems;
         public int TorpedoCount { get; }
@@ -68,7 +68,7 @@ namespace SuperStarTrek.Objects
             (_quadrant.HasKlingons, Energy / _maxEnergy) switch
             {
                 (true, _) => "*Red*",
-                (_, < 0.1) => "Yellow",
+                (_, < 0.1f) => "Yellow",
                 _ => "Green"
             };
 
@@ -112,15 +112,15 @@ namespace SuperStarTrek.Objects
             return CommandResult.Ok;
         }
 
-        private void TakeDamage(double hitStrength)
+        private void TakeDamage(float hitStrength)
         {
             var hitShieldRatio = hitStrength / ShieldControl.ShieldEnergy;
-            if (_random.GetDouble() > 0.6 || hitShieldRatio <= 0.02)
+            if (_random.GetFloat() > 0.6 || hitShieldRatio <= 0.02f)
             {
                 return;
             }
 
-            _systems[_random.Get1To8Inclusive() - 1].TakeDamage(hitShieldRatio + 0.5 * _random.GetDouble());
+            _systems[_random.Get1To8Inclusive() - 1].TakeDamage(hitShieldRatio + 0.5f * _random.GetFloat());
         }
     }
 }
diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs
index 0bbaf984..29584aec 100644
--- a/84 Super Star Trek/csharp/Objects/Klingon.cs	
+++ b/84 Super Star Trek/csharp/Objects/Klingon.cs	
@@ -5,7 +5,7 @@ namespace SuperStarTrek.Objects
 {
     internal class Klingon
     {
-        private double _energy;
+        private float _energy;
         private Coordinates _sector;
         private readonly Random _random;
 
@@ -13,14 +13,14 @@ namespace SuperStarTrek.Objects
         {
             _sector = sector;
             _random = random;
-            _energy = _random.GetDouble(100, 300);
+            _energy = _random.GetFloat(100, 300);
         }
 
         public override string ToString() => "+K+";
 
         public CommandResult FireOn(Enterprise enterprise)
         {
-            var attackStrength = _random.GetDouble();
+            var attackStrength = _random.GetFloat();
             var hitStrength = (int)(_energy * (2 + attackStrength) / _sector.GetDistanceTo(enterprise.Sector));
             _energy /= 3 + attackStrength;
 
diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs
index b96ffab1..4d854efd 100644
--- a/84 Super Star Trek/csharp/Objects/Starbase.cs	
+++ b/84 Super Star Trek/csharp/Objects/Starbase.cs	
@@ -6,21 +6,21 @@ namespace SuperStarTrek.Objects
     {
         private readonly Input _input;
         private readonly Output _output;
-        private readonly double _repairDelay;
+        private readonly float _repairDelay;
 
         public Starbase(Random random, Input input, Output output)
         {
-            _repairDelay = random.GetDouble() * 0.5;
+            _repairDelay = random.GetFloat() * 0.5f;
             _input = input;
             _output = output;
         }
 
         public override string ToString() => ">!<";
 
-        internal bool TryRepair(Enterprise enterprise, out double repairTime)
+        internal bool TryRepair(Enterprise enterprise, out float repairTime)
         {
-            repairTime = enterprise.DamagedSystemCount * 0.1 + _repairDelay;
-            if (repairTime >= 1) { repairTime = 0.9; }
+            repairTime = enterprise.DamagedSystemCount * 0.1f + _repairDelay;
+            if (repairTime >= 1) { repairTime = 0.9f; }
 
             _output.Write(Strings.RepairEstimate, repairTime);
             if (_input.GetYesNo(Strings.RepairPrompt, Input.YesNoMode.TrueOnY))
diff --git a/84 Super Star Trek/csharp/Random.cs b/84 Super Star Trek/csharp/Random.cs
index 460c1cef..5ed47805 100644
--- a/84 Super Star Trek/csharp/Random.cs	
+++ b/84 Super Star Trek/csharp/Random.cs	
@@ -12,14 +12,14 @@ namespace SuperStarTrek
         //     475 DEF FNR(R)=INT(RND(R)*7.98+1.01)
         // Returns a value from 1 to 8, inclusive.
         // Note there's a slight bias away from the extreme values, 1 and 8.
-        public int Get1To8Inclusive() => (int)(_random.NextDouble() * 7.98 + 1.01);
+        public int Get1To8Inclusive() => (int)(GetFloat() * 7.98 + 1.01);
 
         public int GetInt(int inclusiveMinValue, int exclusiveMaxValue) =>
             _random.Next(inclusiveMinValue, exclusiveMaxValue);
 
-        public double GetDouble() => _random.NextDouble();
+        public float GetFloat() => (float)_random.NextDouble();
 
-        public double GetDouble(double inclusiveMinValue, double exclusiveMaxValue)
-            => _random.NextDouble() * (exclusiveMaxValue - inclusiveMinValue) + inclusiveMinValue;
+        public float GetFloat(float inclusiveMinValue, float exclusiveMaxValue)
+            => GetFloat() * (exclusiveMaxValue - inclusiveMinValue) + inclusiveMinValue;
     }
 }
diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs
index 99c48c1a..40bf4bb2 100644
--- a/84 Super Star Trek/csharp/Space/Course.cs	
+++ b/84 Super Star Trek/csharp/Space/Course.cs	
@@ -50,7 +50,7 @@ namespace SuperStarTrek.Space
 
         public IEnumerable GetSectorsFrom(Coordinates start)
         {
-            (double x, double y) = start;
+            (float x, float y) = start;
 
             while(true)
             {
diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs
index 284c8c84..04780a27 100644
--- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs	
+++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs	
@@ -24,14 +24,14 @@ namespace SuperStarTrek.Space
         public static QuadrantInfo Create(Coordinates coordinates, string name)
         {
             var random = new Random();
-            var klingonCount = random.GetDouble() switch
+            var klingonCount = random.GetFloat() switch
             {
-                > 0.98 => 3,
-                > 0.95 => 2,
-                > 0.80 => 1,
+                > 0.98f => 3,
+                > 0.95f => 2,
+                > 0.80f => 1,
                 _ => 0
             };
-            var hasStarbase = random.GetDouble() > 0.96;
+            var hasStarbase = random.GetFloat() > 0.96f;
             var starCount = random.Get1To8Inclusive();
 
             return new QuadrantInfo(coordinates, name, klingonCount, starCount, hasStarbase);
diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs
index 48320588..6ceefcf4 100644
--- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
+++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs	
@@ -18,7 +18,7 @@ namespace SuperStarTrek.Systems
             _input = input;
         }
 
-        public double ShieldEnergy { get; private set; }
+        public float ShieldEnergy { get; private set; }
 
         protected override bool CanExecuteCommand() => IsOperational("{name} inoperable");
 
@@ -39,7 +39,7 @@ namespace SuperStarTrek.Systems
             return CommandResult.Ok;
         }
 
-        private bool Validate(double requested)
+        private bool Validate(float requested)
         {
             if (requested > _enterprise.TotalEnergy)
             {
diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs
index 88924a8c..ab7bef4c 100644
--- a/84 Super Star Trek/csharp/Systems/Subsystem.cs	
+++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs	
@@ -17,7 +17,7 @@ namespace SuperStarTrek.Systems
         }
 
         public string Name { get; }
-        public double Condition { get; private set; }
+        public float Condition { get; private set; }
         public bool IsDamaged => Condition < 0;
         public Command Command { get; }
 
@@ -44,7 +44,7 @@ namespace SuperStarTrek.Systems
             if (IsDamaged) { Condition = 0; }
         }
 
-        internal void TakeDamage(double damage)
+        internal void TakeDamage(float damage)
         {
             Condition -= damage;
             _output.WriteLine($"Damage Control reports, '{Name} damaged by the hit.'");

From a51870c2bde726a6cdb290d2e7e4367dce243efd Mon Sep 17 00:00:00 2001
From: Qeubd-Bsjso 
Date: Sun, 7 Mar 2021 20:55:15 +0530
Subject: [PATCH 263/749] Port Chomp to java

---
 26 Chomp/java/Chomp.java | 157 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 157 insertions(+)
 create mode 100644 26 Chomp/java/Chomp.java

diff --git a/26 Chomp/java/Chomp.java b/26 Chomp/java/Chomp.java
new file mode 100644
index 00000000..c11a5647
--- /dev/null
+++ b/26 Chomp/java/Chomp.java	
@@ -0,0 +1,157 @@
+import java.util.Scanner;
+public class Chomp{
+	int rows;
+	int cols;
+	int numberOfPlayers;
+	int []board;
+	Scanner scanner;
+	Chomp(){
+		System.out.println("\t\t\t\tCHOMP");
+		System.out.println("\t\tCREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+		System.out.println("THIS IS THE GAME OF CHOMP (SCIENTIFIC AMERICAN, JAN 1973)");
+		System.out.print("Do you want the rules (1=Yes, 0=No!)  ");
+
+		scanner = new Scanner(System.in);
+		int choice = scanner.nextInt();
+		if(choice != 0){
+			System.out.println("Chomp is for 1 or more players (Humans only).\n");
+			System.out.println("Here's how a board looks (This one is 5 by 7):");
+			System.out.println("\t1 2 3 4 5 6 7");
+			System.out.println(" 1     P * * * * * *\n 2     * * * * * * *\n 3     * * * * * * *\n 4     * * * * * * *\n 5     * * * * * * *");
+			System.out.println("\nThe board is a big cookie - R rows high and C columns \nwide. You input R and C at the start. In the upper left\ncorner of the cookie is a poison square (P). The one who\nchomps the poison square loses. To take a chomp, type the\nrow and column of one of the squares on the cookie.\nAll of the squares below and to the right of that square\n(Including that square, too) disappear -- CHOMP!!\nNo fair chomping squares that have already been chomped,\nor that are outside the original dimensions of the cookie.\n");
+			System.out.println("Here we go...\n");
+		}
+		startGame();
+	}
+
+	private void startGame(){
+		System.out.print("How many players ");
+		numberOfPlayers = scanner.nextInt();
+		while(numberOfPlayers < 2){
+			System.out.print("How many players ");
+                	numberOfPlayers = scanner.nextInt();
+		}
+		System.out.print("How many rows ");
+		rows = scanner.nextInt();
+		while(rows<=0 || rows >9){
+			if(rows <= 0){
+				System.out.println("Minimun 1 row is required !!");
+			}
+			else{
+				System.out.println("Too many rows(9 is maximum). ");
+			}
+			System.out.print("How many rows ");
+			rows = scanner.nextInt();
+		}
+		System.out.print("How many columns ");
+                cols = scanner.nextInt();
+                while(cols<=0 || cols >9){
+                        if(cols <= 0){
+                                System.out.println("Minimun 1 column is required !!");
+                        }
+                        else{
+                                System.out.println("Too many columns(9 is maximum). ");
+                        }
+                        System.out.print("How many columns ");
+                        cols = scanner.nextInt();
+                }
+		board = new int[rows];
+		for(int i=0;irows || x <1 || y>cols || y<1 || board[x-1]= y){
+					board[i] = y-1;
+				}
+			}
+			printBoard();
+			move((player+1)%numberOfPlayers);
+		}
+	}
+
+
+	public static void main(String []args){
+		new Chomp();
+	}
+}

From 010fdc9c05d4e3fe4339cd2d128b8e25b6e000d2 Mon Sep 17 00:00:00 2001
From: Dave LeCompte 
Date: Sun, 7 Mar 2021 07:54:31 -0800
Subject: [PATCH 264/749] port TARGET to python

Pretty straightforward port, a loop in a loop.

This game is basically an exercise in converting radians to degrees. Possibly in the player's head.
---
 86 Target/python/target.py | 172 +++++++++++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)
 create mode 100644 86 Target/python/target.py

diff --git a/86 Target/python/target.py b/86 Target/python/target.py
new file mode 100644
index 00000000..68fd9521
--- /dev/null
+++ b/86 Target/python/target.py	
@@ -0,0 +1,172 @@
+"""
+TARGET
+
+Weapon targeting simulation / 3d trigonometry practice
+
+Ported by Dave LeCompte
+"""
+
+import collections
+import math
+import random
+
+PAGE_WIDTH = 64
+
+
+def print_centered(msg):
+    spaces = " " * ((PAGE_WIDTH - len(msg)) // 2)
+    print(spaces + msg)
+
+
+def print_header(title):
+    print_centered(title)
+    print_centered("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print()
+    print()
+    print()
+
+
+def print_instructions():
+    print("YOU ARE THE WEAPONS OFFICER ON THE STARSHIP ENTERPRISE")
+    print("AND THIS IS A TEST TO SEE HOW ACCURATE A SHOT YOU")
+    print("ARE IN A THREE-DIMENSIONAL RANGE.  YOU WILL BE TOLD")
+    print("THE RADIAN OFFSET FOR THE X AND Z AXES, THE LOCATION")
+    print("OF THE TARGET IN THREE DIMENSIONAL RECTANGULAR COORDINATES,")
+    print("THE APPROXIMATE NUMBER OF DEGREES FROM THE X AND Z")
+    print("AXES, AND THE APPROXIMATE DISTANCE TO THE TARGET.")
+    print("YOU WILL THEN PROCEEED TO SHOOT AT THE TARGET UNTIL IT IS")
+    print("DESTROYED!")
+    print()
+    print("GOOD LUCK!!")
+    print()
+    print()
+
+
+def prompt():
+    while True:
+        response = input("INPUT ANGLE DEVIATION FROM X, DEVIATION FROM Z, DISTANCE? ")
+        if not ("," in response):
+            continue
+
+        terms = response.split(",")
+        if len(terms) != 3:
+            continue
+
+        return [float(t) for t in terms]
+
+
+def next_target():
+    for i in range(5):
+        print()
+    print("NEXT TARGET...")
+    print()
+
+
+def describe_miss(x, y, z, x1, y1, z1, d):
+    x2 = x1 - x
+    y2 = y1 - y
+    z2 = z1 - z
+
+    if x2 < 0:
+        print(f"SHOT BEHIND TARGET {-x2:.2f} KILOMETERS.")
+    else:
+        print(f"SHOT IN FRONT OF TARGET {x2:.2f} KILOMETERS.")
+
+    if y2 < 0:
+        print(f"SHOT TO RIGHT OF TARGET {-y2:.2f} KILOMETERS.")
+    else:
+        print(f"SHOT TO LEFT OF TARGET {y2:.2f} KILOMETERS.")
+
+    if z2 < 0:
+        print(f"SHOT BELOW TARGET {-z2:.2f} KILOMETERS.")
+    else:
+        print(f"SHOT ABOVE TARGET {z2:.2f} KILOMETERS.")
+
+    print(f"APPROX POSITION OF EXPLOSION:  X={x1:.4f}   Y={y1:.4f}   Z={z1:.4f}")
+    print(f"     DISTANCE FROM TARGET = {d:.2f}")
+    print()
+    print()
+    print()
+
+
+def do_shot_loop(p1, x, y, z):
+    shot_count = 0
+    while True:
+        shot_count += 1
+        if shot_count == 1:
+            p3 = int(p1 * 0.05) * 20
+        elif shot_count == 2:
+            p3 = int(p1 * 0.1) * 10
+        elif shot_count == 3:
+            p3 = int(p1 * 0.5) * 2
+        elif shot_count == 4:
+            p3 = int(p1)
+        else:
+            p3 = p1
+
+        if p3 == int(p3):
+            print(f"     ESTIMATED DISTANCE: {p3}")
+        else:
+            print(f"     ESTIMATED DISTANCE: {p3:.2f}")
+        print()
+        a1, b1, p2 = prompt()
+
+        if p2 < 20:
+            print("YOU BLEW YOURSELF UP!!")
+            return
+
+        a1 = math.radians(a1)
+        b1 = math.radians(b1)
+        show_radians(a1, b1)
+
+        x1 = p2 * math.sin(b1) * math.cos(a1)
+        y1 = p2 * math.sin(b1) * math.sin(a1)
+        z1 = p2 * math.cos(b1)
+
+        distance = math.sqrt((x1 - x) ** 2 + (y1 - y) ** 2 + (z1 - z) ** 2)
+
+        if distance <= 20:
+            print()
+            print(" * * * HIT * * *   TARGET IS NON FUNCTIONAL")
+            print()
+            print(f"DISTANCE OF EXPLOSION FROM TARGET WAS {d:.4f} KILOMETERS")
+            print()
+            print(f"MISSION ACCOMPLISHED IN {r} SHOTS.")
+
+            return
+        else:
+            describe_miss(x, y, z, x1, y1, z1, distance)
+
+
+def show_radians(a, b):
+    print(f"RADIANS FROM X AXIS = {a:.4f}   FROM Z AXIS = {b:.4f}")
+
+
+def play_game():
+    while True:
+        a = random.uniform(0, 2 * math.pi)  # random angle
+        b = random.uniform(0, 2 * math.pi)  # random angle
+
+        show_radians(a, b)
+
+        p1 = random.uniform(0, 100000) + random.uniform(0, 1)
+        x = math.sin(b) * math.cos(a) * p1
+        y = math.sin(b) * math.sin(a) * p1
+        z = math.cos(b) * p1
+        print(
+            f"TARGET SIGHTED: APPROXIMATE COORDINATES:  X={x:.1f}  Y={y:.1f}  Z={z:.1f}"
+        )
+
+        do_shot_loop(p1, x, y, z)
+        next_target()
+
+
+def main():
+    print_header("TARGET")
+    print_instructions()
+
+    play_game()
+
+
+if __name__ == "__main__":
+    main()

From 78817766f96672cd07d1489c46a4c260b7dca614 Mon Sep 17 00:00:00 2001
From: olliehcrook <53153427+olliehcrook@users.noreply.github.com>
Date: Sun, 7 Mar 2021 17:44:55 +0000
Subject: [PATCH 265/749] Update Board.java

Originally uploaded old version that didn't check for draws, just noticed .. my bad
---
 89 Tic-Tac-Toe/java/src/Board.java | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/89 Tic-Tac-Toe/java/src/Board.java b/89 Tic-Tac-Toe/java/src/Board.java
index 091f7bb2..834c91ca 100644
--- a/89 Tic-Tac-Toe/java/src/Board.java	
+++ b/89 Tic-Tac-Toe/java/src/Board.java	
@@ -75,7 +75,15 @@ public class Board {
 
         return false;
     }
-
+    public boolean checkDraw() {
+        if(this.checkWin('X') == false && this.checkWin('O') == false) {
+            if(this.getBoardValue(1) != ' ' && this.getBoardValue(2) != ' ' && this.getBoardValue(3) != ' ' && this.getBoardValue(4) != ' ' && this.getBoardValue(5) != ' ' && this.getBoardValue(6) != ' ' && this.getBoardValue(7) != ' ' && this.getBoardValue(8) != ' ' && this.getBoardValue(9) != ' ' ) {
+                return true;
+            }
+        } 
+        
+        return false; 
+    }
     /**
      * Reset the board
      */
@@ -85,4 +93,4 @@ public class Board {
         }
     }
 
-}
\ No newline at end of file
+}

From b627ea6e7eb6ad75dfc3b3fe6a23fbddf06900c0 Mon Sep 17 00:00:00 2001
From: olliehcrook <53153427+olliehcrook@users.noreply.github.com>
Date: Sun, 7 Mar 2021 17:46:03 +0000
Subject: [PATCH 266/749] Update TicTacToe2.java

Originally uploaded old version that didn't check for draws, just noticed .. my bad
---
 89 Tic-Tac-Toe/java/src/TicTacToe2.java | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/89 Tic-Tac-Toe/java/src/TicTacToe2.java b/89 Tic-Tac-Toe/java/src/TicTacToe2.java
index c186ea1d..bda3793c 100644
--- a/89 Tic-Tac-Toe/java/src/TicTacToe2.java	
+++ b/89 Tic-Tac-Toe/java/src/TicTacToe2.java	
@@ -126,7 +126,30 @@ public class TicTacToe2 {
                         }
                     }
                     break;
-                }
+                } else if (gameBoard.checkDraw()) {
+                    System.out.println("DRAW, PLAY AGAIN? (Y/N)");
+                    gameBoard.clear();
+                    while (true) {
+                        try {
+                            char input;
+                            input = in.next().charAt(0);
+
+                            if (input == 'Y' || input == 'y') {
+                                break;
+                            } else if (input == 'N' || input == 'n') {
+                                System.exit(0);
+                            } else {
+                                System.out.println("THATS NOT 'Y' OR 'N', TRY AGAIN");
+                                in.nextLine();
+                            }
+
+                        } catch (Exception e) {
+                            System.out.println("THATS NOT 'Y' OR 'N', TRY AGAIN");
+                            in.nextLine();
+                        }
+                    } 
+                    break;
+                } 
 
             }
         }

From 540b6b763a3639fb85451b3c500f271fca54ba6c Mon Sep 17 00:00:00 2001
From: Todd Kaiser 
Date: Sun, 7 Mar 2021 18:31:24 -0700
Subject: [PATCH 267/749] Initial version of the salvo.py program. Added
 initial user input functions for ship coordinates.

---
 77 Salvo/python/salvo.py | 82 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 77 Salvo/python/salvo.py

diff --git a/77 Salvo/python/salvo.py b/77 Salvo/python/salvo.py
new file mode 100644
index 00000000..3d36dcbd
--- /dev/null
+++ b/77 Salvo/python/salvo.py	
@@ -0,0 +1,82 @@
+import re
+
+# declare static variables
+BOARD_WIDTH = 10
+BOARD_HEIGHT = 10
+
+SHIPS = [("BATTLESHIP", 5),
+         ("CRUISER", 3),
+         ("DESTROYER", 2),
+         ("DESTROYER", 2)]
+
+VALID_MOVES = [[-1, 0],
+               [-1, 1],
+               [0, 1],
+               [1, 1],
+               [1, 0],
+               [1, -1],
+               [0, -1],
+               [1, -1]]
+
+COORD_REGEX = '[ \t]{0,}(-?[0-9]{1,3})[ \t]{0,},[ \t]{0,}(-?[0-9]{1,2})'
+
+
+# input_coord
+#
+# ask user for single (x,y) coordinate
+# validate the coordinates are within the bounds
+# of the board width and height. mimic the behavior
+# of the original program which exited with error
+# messages if coordinates where outside of array bounds.
+# if input is not numeric, print error out to user and
+# let them try again.
+def input_coord():
+    match = None
+    while not match:
+        coords = input("? ")
+        match = re.match(COORD_REGEX, coords)
+        if not match:
+            print("!NUMBER EXPECTED - RETRY INPUT LINE")
+    x = int(match.group(1))
+    y = int(match.group(2))
+
+    if x > BOARD_HEIGHT or y > BOARD_WIDTH:
+        print("!OUT OF ARRAY BOUNDS IN LINE 1540")
+        exit()
+
+    if x <= 0 or y <= 0:
+        print("!NEGATIVE ARRAY DIM IN LINE 1540")
+        exit()
+
+    return x, y
+
+
+# input_ship_coords
+#
+# ask the user for coordinates for each
+# ship on their board. uses input_coord()
+# to read each coord.
+# returns an array of arrays, one array for
+# each ship's coordinates, which is an array 
+# of (x,y) sets.
+def input_ship_coords():
+    print("ENTER COORDINATES FOR...")
+
+    coords = []
+    for ship in SHIPS:
+        print(ship[0])
+        list = []
+        for i in range(ship[1]):
+            x, y = input_coord()
+            list.append((x, y))
+        coords.append(list)
+    return coords
+
+
+# print out the title 'screen'
+print('{0:>38}'.format("SALVO"))
+print('{0:>57s}'.format("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"))
+print('\n\n')
+
+# ask the user for ship coordinates
+coords = input_ship_coords()

From fd76dee2688439eec3db224d22fec362c9400b58 Mon Sep 17 00:00:00 2001
From: Jack Boyce 
Date: Mon, 8 Mar 2021 12:05:16 -0800
Subject: [PATCH 268/749] refactor direction-finder, general cleanup

---
 84 Super Star Trek/python/superstartrek.py | 74 +++++++++-------------
 1 file changed, 31 insertions(+), 43 deletions(-)

diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py
index c5858798..36db1ba8 100644
--- a/84 Super Star Trek/python/superstartrek.py	
+++ b/84 Super Star Trek/python/superstartrek.py	
@@ -8,7 +8,7 @@
 # **** LEEDOM - APRIL & DECEMBER 1974,
 # **** WITH A LITTLE HELP FROM HIS FRIENDS . . .
 #
-# Python translation by Jack Boyce - 2/2021
+# Python translation by Jack Boyce - February 2021
 #   Output is identical to BASIC version except for a few
 #   fixes (as noted, search `bug`) and minor cleanup.
 
@@ -59,8 +59,6 @@ def insert_marker(row, col, marker):
 def compare_marker(row, col, test_marker):
     # Check whether the position in the current quadrant is occupied with a
     # given marker.
-    global qs
-
     pos = round(col) * 3 + round(row) * 24
     return qs[pos:(pos + 3)] == test_marker
 
@@ -504,7 +502,7 @@ def klingons_fire():
 
 def shield_control():
     # Raise or lower the shields.
-    global e, s, d
+    global e, s
 
     if d[6] < 0:
         print("SHIELD CONTROL INOPERABLE")
@@ -557,7 +555,8 @@ def damage_control():
     print("\nTECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;")
     print("ESTIMATED TIME TO REPAIR: "
           f"{round(0.01 * int(100 * d3), 2)} STARDATES")
-    if input("WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N)? ").upper() != 'Y':
+    if input("WILL YOU AUTHORIZE THE "
+             "REPAIR ORDER (Y/N)? ").upper().strip() != 'Y':
         return
 
     for i in range(8):
@@ -685,43 +684,32 @@ def computer():
 
 
 def print_direction(from1, from2, to1, to2):
-    # Print a direction and distance between two locations in the quadrant
-    # grid.
-    to2 -= from2
-    from2 = from1 - to1
+    # Print a direction and distance between two locations in the grid.
+    delta1 = -(to1 - from1)  # flip so positive is up (heading = 3)
+    delta2 = to2 - from2
 
-    def f1(c1, a, x):
-        if abs(a) >= abs(x):
-            print(f"DIRECTION = {round(c1 + (abs(x)/abs(a)), 6)}")
+    if delta2 > 0:
+        if delta1 < 0:
+            base = 7
         else:
-            print("DIRECTION = "
-                  f"{round(c1 + (((abs(x)-abs(a))+abs(x))/abs(x)), 6)}")
-
-    def f2(c1, a, x):
-        if abs(a) <= abs(x):
-            print(f"DIRECTION = {round(c1 + (abs(a)/abs(x)), 6)}")
-        else:
-            print("DIRECTION = "
-                  f"{round(c1 + (((abs(a)-abs(x))+abs(a))/abs(a)), 6)}")
-
-    if to2 < 0:
-        if from2 > 0:
-            f1(3, from2, to2)
-        elif to2 != 0:
-            f2(5, from2, to2)
-        else:
-            f1(7, from2, to2)
+            base = 1
+            delta1, delta2 = delta2, delta1
     else:
-        if from2 < 0:
-            f1(7, from2, to2)
-        elif to2 > 0:
-            f2(1, from2, to2)
-        elif from2 == 0:
-            f2(5, from2, to2)
+        if delta1 > 0:
+            base = 3
         else:
-            f2(1, from2, to2)
+            base = 5
+            delta1, delta2 = delta2, delta1
 
-    print(f"DISTANCE = {round(sqrt(to2 ** 2 + from2 ** 2), 6)}")
+    delta1, delta2 = abs(delta1), abs(delta2)
+
+    if delta1 > 0 or delta2 > 0:  # bug in original; no check for divide by 0
+        if delta1 >= delta2:
+            print(f"DIRECTION = {round(base + delta2 / delta1, 6)}")
+        else:
+            print(f"DIRECTION = {round(base + 2 - delta1 / delta2, 6)}")
+
+    print(f"DISTANCE = {round(sqrt(delta1 ** 2 + delta2 ** 2), 6)}")
 
 
 # -------------------------------------------------------------------------
@@ -796,7 +784,7 @@ def startup():
         g[q1][q2] += 10
         q1, q2 = fnr(), fnr()
 
-    k7 = k9
+    k7 = k9                                 # Klingons at start of game
 
     print("YOUR ORDERS ARE AS FOLLOWS:\n"
           f"     DESTROY THE {k9} KLINGON WARSHIPS WHICH HAVE INVADED\n"
@@ -809,8 +797,7 @@ def startup():
 
 def new_quadrant():
     # Enter a new quadrant: populate map and print a short range scan.
-    global g, z, t, t0, s9, q1, q2, s1, s2
-    global k3, b3, s3, d4, k, qs, b4, b5
+    global z, k3, b3, s3, d4, k, qs, b4, b5
 
     k3 = b3 = s3 = 0                        # Klingons, bases, stars in quad.
     d4 = 0.5 * random.random()              # extra delay in repairs at base
@@ -854,7 +841,7 @@ def new_quadrant():
 
 def end_game(won=False, quit=True, enterprise_killed=False):
     # Handle end-of-game situations.
-    global t, t0, b9, k7, restart
+    global restart
 
     if won:
         print("CONGRATULATIONS, CAPTAIN! THE LAST KLINGON BATTLE CRUISER")
@@ -876,7 +863,8 @@ def end_game(won=False, quit=True, enterprise_killed=False):
 
     print("THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER")
     print("FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,")
-    if input("LET HIM STEP FORWARD AND ENTER 'AYE'? ").upper() != 'AYE':
+    if input("LET HIM STEP FORWARD AND "
+             "ENTER 'AYE'? ").upper().strip() != 'AYE':
         exit()
     restart = True
 
@@ -902,7 +890,7 @@ while True:
                   "SHIELD CONTROL\nIS PRESENTLY INCAPABLE OF CROSS-CIRCUITING "
                   "TO ENGINE ROOM!!")
 
-        command = input('COMMAND? ').upper()
+        command = input('COMMAND? ').upper().strip()
 
         if command in f:
             f[command]()

From 27d7ec75bc3af28411bd15b4d79dc8eec4be2fa9 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 8 Mar 2021 15:55:05 -0600
Subject: [PATCH 269/749] Ported SYNONYM to Javascript

---
 85 Synonym/javascript/synonym.html |   9 +++
 85 Synonym/javascript/synonym.js   | 124 +++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+)
 create mode 100644 85 Synonym/javascript/synonym.html
 create mode 100644 85 Synonym/javascript/synonym.js

diff --git a/85 Synonym/javascript/synonym.html b/85 Synonym/javascript/synonym.html
new file mode 100644
index 00000000..ec24a89a
--- /dev/null
+++ b/85 Synonym/javascript/synonym.html	
@@ -0,0 +1,9 @@
+
+
+SYNONYM
+
+
+

+
+
+
diff --git a/85 Synonym/javascript/synonym.js b/85 Synonym/javascript/synonym.js
new file mode 100644
index 00000000..ad3175b7
--- /dev/null
+++ b/85 Synonym/javascript/synonym.js	
@@ -0,0 +1,124 @@
+// SYNONYM
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var ra = [, "RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"];
+var la = [];
+var tried = [];
+
+var synonym = [[5,"FIRST","START","BEGINNING","ONSET","INITIAL"],
+               [5,"SIMILAR","ALIKE","SAME","LIKE","RESEMBLING"],
+               [5,"MODEL","PATTERN","PROTOTYPE","STANDARD","CRITERION"],
+               [5,"SMALL","INSIGNIFICANT","LITTLE","TINY","MINUTE"],
+               [6,"STOP","HALT","STAY","ARREST","CHECK","STANDSTILL"],
+               [6,"HOUSE","DWELLING","RESIDENCE","DOMICILE","LODGING","HABITATION"],
+               [7,"PIT","HOLE","HOLLOW","WELL","GULF","CHASM","ABYSS"],
+               [7,"PUSH","SHOVE","THRUST","PROD","POKE","BUTT","PRESS"],
+               [6,"RED","ROUGE","SCARLET","CRIMSON","FLAME","RUBY"],
+               [7,"PAIN","SUFFERING","HURT","MISERY","DISTRESS","ACHE","DISCOMFORT"]
+               ];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "SYNONYM\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (c = 0; c <= synonym.length; c++)
+        tried[c] = false;
+    print("A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH\n");
+    print("LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME");
+    print(" MEANING.\n");
+    print("I CHOOSE A WORD -- YOU TYPE A SYNONYM.\n");
+    print("IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP'\n");
+    print("AND I WILL TELL YOU A SYNONYM.\n");
+    print("\n");
+    c = 0;
+    while (c < synonym.length) {
+        c++;
+        do {
+            n1 = Math.floor(Math.random() * synonym.length + 1);
+        } while (tried[n1]) ;
+        tried[n1] = true;
+        n2 = synonym[n1][0];    // Length of synonym list
+        // This array keeps a list of words not shown
+        for (j = 1; j <= n2; j++)
+            la[j] = j;
+        la[0] = n2;
+        g = 1;  // Always show first word
+        print("\n");
+        la[g] = la[la[0]];  // Replace first word with last word
+        la[0] = n2 - 1; // Reduce size of list by one.
+        print("\n");
+        while (1) {
+            print("     WHAT IS A SYNONYM OF " + synonym[n1][g]);
+            str = await input();
+            if (str == "HELP") {
+                g1 = Math.floor(Math.random() * la[0] + 1);
+                print("**** A SYNONYM OF " + synonym[n1][g] + " IS " + synonym[n1][la[g1]] + ".\n");
+                print("\n");
+                la[g1] = la[la[0]];
+                la[0]--;
+                continue;
+            }
+            for (k = 1; k <= n2; k++) {
+                if (g == k)
+                    continue;
+                if (str == synonym[n1][k])
+                    break;
+            }
+            if (k > n2) {
+                print("     TRY AGAIN.\n");
+            } else {
+                print(synonym[n1][Math.floor(Math.random() * 5 + 1)] + "\n");
+                break;
+            }
+        }
+    }
+    print("\n");
+    print("SYNONYM DRILL COMPLETED.\n");
+}
+
+main();

From ffdf0ed8ec8812544ab521295524f4ac032d2e30 Mon Sep 17 00:00:00 2001
From: Darren Cardenas 
Date: Mon, 8 Mar 2021 20:29:43 -0500
Subject: [PATCH 270/749] Add Java port of 28-Combat.

---
 28 Combat/java/Combat.java | 268 +++++++++++++++++++++++++++++++++++++
 1 file changed, 268 insertions(+)
 create mode 100644 28 Combat/java/Combat.java

diff --git a/28 Combat/java/Combat.java b/28 Combat/java/Combat.java
new file mode 100644
index 00000000..11b4ae42
--- /dev/null
+++ b/28 Combat/java/Combat.java	
@@ -0,0 +1,268 @@
+import java.lang.Math;
+import java.util.Scanner;
+
+/**
+ * Game of Combat
+ * 

+ * Based on the BASIC game of Combat here + * https://github.com/coding-horror/basic-computer-games/blob/main/28%20Combat/combat.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Combat { + + private static final int MAX_UNITS = 72000; // Maximum number of total units per player + + private final Scanner scan; // For user input + + private boolean planeCrashWin = false; + + private int usrArmy = 0; // Number of user Army units + private int usrNavy = 0; // Number of user Navy units + private int usrAir = 0; // Number of user Air Force units + private int cpuArmy = 30000; // Number of cpu Army units + private int cpuNavy = 20000; // Number of cpu Navy units + private int cpuAir = 22000; // Number of cpu Air Force units + + public Combat() { + + scan = new Scanner(System.in); + + } // End of constructor Combat + + public void play() { + + showIntro(); + getForces(); + attackFirst(); + attackSecond(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(32) + "COMBAT"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + System.out.println("I AM AT WAR WITH YOU."); + System.out.println("WE HAVE " + MAX_UNITS + " SOLDIERS APIECE.\n"); + + } // End of method showIntro + + private void getForces() { + + do { + System.out.println("DISTRIBUTE YOUR FORCES."); + System.out.println(" ME YOU"); + System.out.print("ARMY " + cpuArmy + " ? "); + usrArmy = scan.nextInt(); + System.out.print("NAVY " + cpuNavy + " ? "); + usrNavy = scan.nextInt(); + System.out.print("A. F. " + cpuAir + " ? "); + usrAir = scan.nextInt(); + + } while ((usrArmy + usrNavy + usrAir) > MAX_UNITS); // Avoid exceeding the maximum number of total units + + } // End of method getForces + + private void attackFirst() { + + int numUnits = 0; + int unitType = 0; + + do { + System.out.println("YOU ATTACK FIRST. TYPE (1) FOR ARMY; (2) FOR NAVY;"); + System.out.println("AND (3) FOR AIR FORCE."); + System.out.print("? "); + unitType = scan.nextInt(); + } while ((unitType < 1) || (unitType > 3)); // Avoid out-of-range values + + do { + System.out.println("HOW MANY MEN"); + System.out.print("? "); + numUnits = scan.nextInt(); + } while ((numUnits < 0) || // Avoid negative values + ((unitType == 1) && (numUnits > usrArmy)) || // Avoid exceeding the number of available Army units + ((unitType == 2) && (numUnits > usrNavy)) || // Avoid exceeding the number of available Navy units + ((unitType == 3) && (numUnits > usrAir))); // Avoid exceeding the number of available Air Force units + + // Begin handling deployment type + switch (unitType) { + case 1: // Army deployed + + if (numUnits < (usrArmy / 3.0)) { // User deployed less than one-third of their Army units + System.out.println("YOU LOST " + numUnits + " MEN FROM YOUR ARMY."); + usrArmy = usrArmy - numUnits; + } + else if (numUnits < (2.0 * usrArmy / 3.0)) { // User deployed less than two-thirds of their Army units + System.out.println("YOU LOST " + (int) Math.floor(numUnits / 3.0) + " MEN, BUT I LOST " + (int) Math.floor(2.0 * cpuArmy / 3.0)); + usrArmy = (int) Math.floor(usrArmy - numUnits / 3.0); + cpuArmy = 0; + } + else { // User deployed two-thirds or more of their Army units + System.out.println("YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO"); + System.out.println("OF YOUR AIR FORCE BASES AND 3 ARMY BASES."); + usrArmy = (int) Math.floor(usrArmy / 3.0); + usrAir = (int) Math.floor(usrAir / 3.0); + cpuNavy = (int) Math.floor(2.0 * cpuNavy / 3.0); + } + break; + + case 2: // Navy deployed + + if (numUnits < (cpuNavy / 3.0)) { // User deployed less than one-third relative to cpu Navy units + System.out.println("YOUR ATTACK WAS STOPPED!"); + usrNavy = usrNavy - numUnits; + } + else if (numUnits < (2.0 * cpuNavy / 3.0)) { // User deployed less than two-thirds relative to cpu Navy units + System.out.println("YOU DESTROYED " + (int) Math.floor(2.0 * cpuNavy / 3.0) + " OF MY ARMY."); + cpuNavy = (int) Math.floor(cpuNavy / 3.0); + } + else { // User deployed two-thirds or more relative to cpu Navy units + System.out.println("YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO"); + System.out.println("OF YOUR AIR FORCE BASES AND 3 ARMY BASES."); + usrArmy = (int) Math.floor(usrArmy / 3.0); + usrAir = (int) Math.floor(usrAir / 3.0); + cpuNavy = (int) Math.floor(2.0 * cpuNavy / 3.0); + } + break; + + case 3: // Air Force deployed + + if (numUnits < (usrAir / 3.0)) { // User deployed less than one-third of their Air Force units + System.out.println("YOUR ATTACK WAS WIPED OUT."); + usrAir = usrAir - numUnits; + } + else if (numUnits < (2.0 * usrAir / 3.0)) { // User deployed less than two-thirds of their Air Force units + System.out.println("WE HAD A DOGFIGHT. YOU WON - AND FINISHED YOUR MISSION."); + cpuArmy = (int) Math.floor(2.0 * cpuArmy / 3.0); + cpuNavy = (int) Math.floor(cpuNavy / 3.0); + cpuAir = (int) Math.floor(cpuAir / 3.0); + } + else { // User deployed two-thirds or more of their Air Force units + System.out.println("YOU WIPED OUT ONE OF MY ARMY PATROLS, BUT I DESTROYED"); + System.out.println("TWO NAVY BASES AND BOMBED THREE ARMY BASES."); + usrArmy = (int) Math.floor(usrArmy / 4.0); + usrNavy = (int) Math.floor(usrNavy / 3.0); + cpuArmy = (int) Math.floor(2.0 * cpuArmy / 3.0); + } + break; + + } // End handling deployment type + + } // End of method attackFirst + + private void attackSecond() { + + int numUnits = 0; + int unitType = 0; + + System.out.println(""); + System.out.println(" YOU ME"); + System.out.print("ARMY "); + System.out.format("%-14s%s\n", usrArmy, cpuArmy); + System.out.print("NAVY "); + System.out.format("%-14s%s\n", usrNavy, cpuNavy); + System.out.print("A. F. "); + System.out.format("%-14s%s\n", usrAir, cpuAir); + + do { + System.out.println("WHAT IS YOUR NEXT MOVE?"); + System.out.println("ARMY=1 NAVY=2 AIR FORCE=3"); + System.out.print("? "); + unitType = scan.nextInt(); + } while ((unitType < 1) || (unitType > 3)); // Avoid out-of-range values + + do { + System.out.println("HOW MANY MEN"); + System.out.print("? "); + numUnits = scan.nextInt(); + } while ((numUnits < 0) || // Avoid negative values + ((unitType == 1) && (numUnits > usrArmy)) || // Avoid exceeding the number of available Army units + ((unitType == 2) && (numUnits > usrNavy)) || // Avoid exceeding the number of available Navy units + ((unitType == 3) && (numUnits > usrAir))); // Avoid exceeding the number of available Air Force units + + // Begin handling deployment type + switch (unitType) { + case 1: // Army deployed + + if (numUnits < (cpuArmy / 2.0)) { // User deployed less than half relative to cpu Army units + System.out.println("I WIPED OUT YOUR ATTACK!"); + usrArmy = usrArmy - numUnits; + } + else { // User deployed half or more relative to cpu Army units + System.out.println("YOU DESTROYED MY ARMY!"); + cpuArmy = 0; + } + break; + + case 2: // Navy deployed + + if (numUnits < (cpuNavy / 2.0)) { // User deployed less than half relative to cpu Navy units + System.out.println("I SUNK TWO OF YOUR BATTLESHIPS, AND MY AIR FORCE"); + System.out.println("WIPED OUT YOUR UNGUARDED CAPITOL."); + usrArmy = (int) Math.floor(usrArmy / 4.0); + usrNavy = (int) Math.floor(usrNavy / 2.0); + } + else { // User deployed half or more relative to cpu Navy units + System.out.println("YOUR NAVY SHOT DOWN THREE OF MY XIII PLANES,"); + System.out.println("AND SUNK THREE BATTLESHIPS."); + cpuAir = (int) Math.floor(2.0 * cpuAir / 3.0); + cpuNavy = (int) Math.floor(cpuNavy / 2.0); + } + break; + + case 3: // Air Force deployed + + if (numUnits > (cpuAir / 2.0)) { // User deployed more than half relative to cpu Air Force units + System.out.println("MY NAVY AND AIR FORCE IN A COMBINED ATTACK LEFT"); + System.out.println("YOUR COUNTRY IN SHAMBLES."); + usrArmy = (int) Math.floor(usrArmy / 3.0); + usrNavy = (int) Math.floor(usrNavy / 3.0); + usrAir = (int) Math.floor(usrAir / 3.0); + } + else { // User deployed half or less relative to cpu Air Force units + System.out.println("ONE OF YOUR PLANES CRASHED INTO MY HOUSE. I AM DEAD."); + System.out.println("MY COUNTRY FELL APART."); + planeCrashWin = true; + } + break; + + } // End handling deployment type + + // Suppress message for plane crashes + if (planeCrashWin == false) { + System.out.println(""); + System.out.println("FROM THE RESULTS OF BOTH OF YOUR ATTACKS,"); + } + + // User wins + if ((planeCrashWin == true) || + ((usrArmy + usrNavy + usrAir) > ((int) Math.floor((3.0 / 2.0 * (cpuArmy + cpuNavy + cpuAir)))))) { + System.out.println("YOU WON, OH! SHUCKS!!!!"); + } + // User loses + else if ((usrArmy + usrNavy + usrAir) < ((int) Math.floor((2.0 / 3.0 * (cpuArmy + cpuNavy + cpuAir))))) { // User loss + System.out.println("YOU LOST-I CONQUERED YOUR COUNTRY. IT SERVES YOU"); + System.out.println("RIGHT FOR PLAYING THIS STUPID GAME!!!"); + } + // Peaceful outcome + else { + System.out.println("THE TREATY OF PARIS CONCLUDED THAT WE TAKE OUR"); + System.out.println("RESPECTIVE COUNTRIES AND LIVE IN PEACE."); + } + + } // End of method attackSecond + + public static void main(String[] args) { + + Combat combat = new Combat(); + combat.play(); + + } // End of method main + +} // End of class Combat \ No newline at end of file From 4cd772a6d7536aba127aac368cd7826bbacf4d14 Mon Sep 17 00:00:00 2001 From: nanochess Date: Mon, 8 Mar 2021 22:31:10 -0600 Subject: [PATCH 271/749] Ported SLALOM to Javascript --- 79 Slalom/javascript/slalom.html | 9 ++ 79 Slalom/javascript/slalom.js | 260 +++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 79 Slalom/javascript/slalom.html create mode 100644 79 Slalom/javascript/slalom.js diff --git a/79 Slalom/javascript/slalom.html b/79 Slalom/javascript/slalom.html new file mode 100644 index 00000000..d91f71ad --- /dev/null +++ b/79 Slalom/javascript/slalom.html @@ -0,0 +1,9 @@ + + +SLALOM + + +


+
+
+
diff --git a/79 Slalom/javascript/slalom.js b/79 Slalom/javascript/slalom.js
new file mode 100644
index 00000000..7944e62e
--- /dev/null
+++ b/79 Slalom/javascript/slalom.js	
@@ -0,0 +1,260 @@
+// SLALOM
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var speed = [,14,18,26,29,18,
+             25,28,32,29,20,
+             29,29,25,21,26,
+             29,20,21,20,18,
+             26,25,33,31,22];
+
+function show_instructions()
+{
+    print("\n");
+    print("*** SLALOM: THIS IS THE 1976 WINTER OLYMPIC GIANT SLALOM.  YOU ARE\n");
+    print("            THE AMERICAN TEAM'S ONLY HOPE OF A GOLD MEDAL.\n");
+    print("\n");
+    print("     0 -- TYPE THIS IS YOU WANT TO SEE HOW LONG YOU'VE TAKEN.\n");
+    print("     1 -- TYPE THIS IF YOU WANT TO SPEED UP A LOT.\n");
+    print("     2 -- TYPE THIS IF YOU WANT TO SPEED UP A LITTLE.\n");
+    print("     3 -- TYPE THIS IF YOU WANT TO SPEED UP A TEENSY.\n");
+    print("     4 -- TYPE THIS IF YOU WANT TO KEEP GOING THE SAME SPEED.\n");
+    print("     5 -- TYPE THIS IF YOU WANT TO CHECK A TEENSY.\n");
+    print("     6 -- TYPE THIS IF YOU WANT TO CHECK A LITTLE.\n");
+    print("     7 -- TYPE THIS IF YOU WANT TO CHECK A LOT.\n");
+    print("     8 -- TYPE THIS IF YOU WANT TO CHEAT AND TRY TO SKIP A GATE.\n");
+    print("\n");
+    print(" THE PLACE TO USE THESE OPTIONS IS WHEN THE COMPUTER ASKS:\n");
+    print("\n");
+    print("OPTION?\n");
+    print("\n");
+    print("                GOOD LUCK!\n");
+    print("\n");
+}
+
+function show_speeds()
+{
+    print("GATE MAX\n");
+    print(" #  M.P.H.\n");
+    print("----------\n");
+    for (var b = 1; b <= v; b++) {
+        print(" " + b + "  " + speed[b] + "\n");
+    }
+}
+
+// Main program
+async function main()
+{
+    var gold = 0;
+    var silver = 0;
+    var bronze = 0;
+    
+    print(tab(33) + "SLALOM\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("HOW MANY GATES DOES THIS COURSE HAVE (1 TO 25)");
+        v = parseInt(await input());
+        if (v >= 25) {
+            print("25 IS THE LIMIT\n");
+            v = 25;
+        } else if (v < 1) {
+            print("TRY AGAIN.\n");
+        } else {
+            break;
+        }
+    }
+    print("\n");
+    print("TYPE \"INS\" FOR INSTRUCTIONS\n");
+    print("TYPE \"MAX\" FOR APPROXIMATE MAXIMUM SPEEDS\n");
+    print("TYPE \"RUN\" FOR THE BEGINNING OF THE RACE\n");
+    while (1) {
+        print("COMMAND--");
+        str = await input();
+        if (str == "INS") {
+            show_instructions();
+        } else if (str == "MAX") {
+            show_speeds();
+        } else if (str == "RUN") {
+            break;
+        } else {
+            print("\"" + str + "\" IS AN ILLEGAL COMMAND--RETRY");
+        }
+    }
+    while (1) {
+        print("RATE YOURSELF AS A SKIER, (1=WORST, 3=BEST)");
+        a = parseInt(await input());
+        if (a < 1 || a > 3)
+            print("THE BOUNDS ARE 1-3\n");
+        else
+            break;
+    }
+    while (1) {
+        print("THE STARTER COUNTS DOWN...5...4...3...2...1...GO!");
+        t = 0;
+        s = Math.floor(Math.random(1) * (18 - 9) + 9);
+        print("\n");
+        print("YOU'RE OFF!\n");
+        for (o = 1; o <= v; o++) {
+            q = speed[o];
+            print("\n");
+            print("HERE COMES GATE #" + o + " :\n");
+            print(s + " M.P.H.\n");
+            s1 = s;
+            while (1) {
+                print("OPTION");
+                o1 = parseInt(await input());
+                if (o1 < 0 || o1 > 8)
+                    print("WHAT?\n");
+                else if (o1 == 0)
+                    print("YOU'VE TAKEN " + (t + Math.random()) + " SECONDS.\n");
+                else
+                    break;
+            }
+            finish = false;
+            switch (o1) {
+                case 1:
+                    s += Math.floor(Math.random() * (10 - 5) + 5);
+                    break;
+                case 2:
+                    s += Math.floor(Math.random() * (5 - 3) + 3);
+                    break;
+                case 3:
+                    s += Math.floor(Math.random() * (4 - 1) + 1);
+                    break;
+                case 4:
+                    break;
+                case 5:
+                    s -= Math.floor(Math.random() * (4 - 1) + 1);
+                    break;
+                case 6:
+                    s -= Math.floor(Math.random() * (5 - 3) + 3);
+                    break;
+                case 7:
+                    s -= Math.floor(Math.random() * (10 - 5) + 5);
+                    break;
+                case 8:
+                    print("***CHEAT\n");
+                    if (Math.random() >= 0.7) {
+                        print("YOU MADE IT!\n");
+                        t += 1.5;
+                    } else {
+                        print("AN OFFICIAL CAUGHT YOU!\n");
+                        print("YOU TOOK " + (t + Math.random()) + " SECONDS.\n");
+                        finish = true;
+                    }
+                    break;
+            }
+            if (!finish) {
+                if (o1 != 4)
+                    print(s + " M.P.H.\n");
+                if (s > q) {
+                    if (Math.random() < ((s - q) * 0.1) + 0.2) {
+                        print("YOU WENT OVER THE MAXIMUM SPEED AND ");
+                        if (Math.random() < 0.5) {
+                            print("SNAGGED A FLAG!\n");
+                        } else {
+                            print("WIPED OUT!\n");
+                        }
+                        print("YOU TOOK " + (t + Math.random()) + " SECONDS.\n");
+                        finish = true;
+                    } else {
+                        print("YOU WENT OVER THE MAXIMUM SPEED AND MADE IT!\n");
+                    }
+                } else if (s > q - 1) {
+                    print("CLOSE ONE!\n");
+                }
+            }
+            if (finish)
+                break;
+            if (s < 7) {
+                print("LET'S BE REALISTIC, OK?  LET'S GO BACK AND TRY AGAIN...\n");
+                s = s1;
+                o--;
+                continue;
+            }
+            t += q - s + 1;
+            if (s > q) {
+                t += 0.5;
+            }
+        }
+        if (!finish) {
+            print("\n");
+            print("YOU TOOK " + (t + Math.random()) + " SECONDS.\n");
+            m = t;
+            m /= v;
+            if (m < 1.5 - (a * 0.1)) {
+                print("YOU WON A GOLD MEDAL!\n");
+                gold++;
+            } else if (m < 2.9 - (a * 0.1)) {
+                print("YOU WON A SILVER MEDAL\n");
+                silver++;
+            } else if (m < 4.4 - (a * 0.1)) {
+                print("YOU WON A BRONZE MEDAL\n");
+                bronze++;
+            }
+        }
+        while (1) {
+            print("\n");
+            print("DO YOU WANT TO RACE AGAIN");
+            str = await input();
+            if (str != "YES" && str != "NO")
+                print("PLEASE TYPE 'YES' OR 'NO'\n");
+            else
+                break;
+        }
+        if (str != "YES")
+            break;
+    }
+    print("THANKS FOR THE RACE\n");
+    if (gold >= 1)
+        print("GOLD MEDALS: " + gold + "\n");
+    if (silver >= 1)
+        print("SILVER MEDALS: " + silver + "\n");
+    if (bronze >= 1)
+        print("BRONZE MEDALS: " + bronze + "\n");
+}
+
+main();

From ba70ff65346b4f38da3a2e3da82593a35c7d7d26 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 8 Mar 2021 23:12:04 -0600
Subject: [PATCH 272/749] Ported ROULETTE to Javascript

---
 75 Roulette/javascript/roulette.html |   9 +
 75 Roulette/javascript/roulette.js   | 339 +++++++++++++++++++++++++++
 2 files changed, 348 insertions(+)
 create mode 100644 75 Roulette/javascript/roulette.html
 create mode 100644 75 Roulette/javascript/roulette.js

diff --git a/75 Roulette/javascript/roulette.html b/75 Roulette/javascript/roulette.html
new file mode 100644
index 00000000..02495892
--- /dev/null
+++ b/75 Roulette/javascript/roulette.html	
@@ -0,0 +1,9 @@
+
+
+ROULETTE
+
+
+

+
+
+
diff --git a/75 Roulette/javascript/roulette.js b/75 Roulette/javascript/roulette.js
new file mode 100644
index 00000000..7c3399bd
--- /dev/null
+++ b/75 Roulette/javascript/roulette.js	
@@ -0,0 +1,339 @@
+// ROULETTE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var ba = [];
+var ca = [];
+var ta = [];
+var xa = [];
+var aa = [];
+
+var numbers = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
+
+// Main program
+async function main()
+{
+    print(tab(32) + "ROULETTE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // Roulette
+    // David Joslin
+    print("WELCOME TO THE ROULETTE TABLE\n");
+    print("\n");
+    print("DO YOU WANT INSTRUCTIONS");
+    str = await input();
+    if (str.substr(0, 1) != "N") {
+        print("\n");
+        print("THIS IS THE BETTING LAYOUT\n");
+        print("  (*=RED)\n");
+        print("\n");
+        print(" 1*    2     3*\n");
+        print(" 4     5*    6 \n");
+        print(" 7*    8     9*\n");
+        print("10    11    12*\n");
+        print("---------------\n");
+        print("13    14*   15 \n");
+        print("16*   17    18*\n");
+        print("19*   20    21*\n");
+        print("22    23*   24 \n");
+        print("---------------\n");
+        print("25*   26    27*\n");
+        print("28    29    30*\n");
+        print("31    32*   33 \n");
+        print("34*   35    36*\n");
+        print("---------------\n");
+        print("    00    0    \n");
+        print("\n");
+        print("TYPES OF BETS\n");
+        print("\n");
+        print("THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET\n");
+        print("ON THAT NUMBER.\n");
+        print("THESE PAY OFF 35:1\n");
+        print("\n");
+        print("THE 2:1 BETS ARE:\n");
+        print(" 37) 1-12     40) FIRST COLUMN\n");
+        print(" 38) 13-24    41) SECOND COLUMN\n");
+        print(" 39) 25-36    42) THIRD COLUMN\n");
+        print("\n");
+        print("THE EVEN MONEY BETS ARE:\n");
+        print(" 43) 1-18     46) ODD\n");
+        print(" 44) 19-36    47) RED\n");
+        print(" 45) EVEN     48) BLACK\n");
+        print("\n");
+        print(" 49)0 AND 50)00 PAY OFF 35:1\n");
+        print(" NOTE: 0 AND 00 DO NOT COUNT UNDER ANY\n");
+        print("       BETS EXCEPT THEIR OWN.\n");
+        print("\n");
+        print("WHEN I ASK FOR EACH BET, TYPE THE NUMBER\n");
+        print("AND THE AMOUNT, SEPARATED BY A COMMA.\n");
+        print("FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500\n");
+        print("WHEN I ASK FOR A BET.\n");
+        print("\n");
+        print("THE MINIMUM BET IS $5, THE MAXIMUM IS $500.\n");
+        print("\n");
+    }
+    // Program begins here
+    // Type of bet(number) odds
+    for (i = 1; i <= 100; i++) {
+        ba[i] = 0;
+        ca[i] = 0;
+        ta[i] = 0;
+    }
+    for (i = 1; i <= 38; i++)
+        xa[i] = 0;
+    p = 1000;
+    d = 100000;
+    while (1) {
+        do {
+            print("HOW MANY BETS");
+            y = parseInt(await input());
+        } while (y < 1) ;
+        for (i = 1; i <= 50; i++) {
+            aa[i] = 0;
+        }
+        for (c = 1; c <= y; c++) {
+            while (1) {
+                print("NUMBER " + c + " ");
+                str = await input();
+                x = parseInt(str);
+                z = parseInt(str.substr(str.indexOf(",") + 1));
+                ba[c] = z;
+                ta[c] = x;
+                if (x < 1 || x > 50)
+                    continue;
+                if (z < 1)
+                    continue;
+                if (z < 5 || z > 500)
+                    continue;
+                if (aa[x] != 0) {
+                    print("YOU MADE THAT BET ONCE ALREADY,DUM-DUM\n");
+                    continue;
+                }
+                aa[x] = 1;
+                break;
+            }
+        }
+        print("SPINNING\n");
+        print("\n");
+        print("\n");
+        do {
+            s = Math.floor(Math.random() * 100);
+        } while (s == 0 || s > 38) ;
+        xa[s]++;    // Not used
+        if (s > 37) {
+            print("00\n");
+        } else if (s == 37) {
+            print("0\n");
+        } else {
+            for (i1 = 1; i1 <= 18; i1++) {
+                if (s == numbers[i1 - 1])
+                    break;
+            }
+            if (i1 <= 18)
+                print(s + " RED\n");
+            else
+                print(s + " BLACK\n");
+        }
+        print("\n");
+        for (c = 1; c <= y; c++) {
+            won = 0;
+            switch (ta[c]) {
+                case 37:    // 1-12 (37) 2:1
+                    if (s > 12) {
+                        won = -ba[c];
+                    } else {
+                        won = ba[c] * 2;
+                    }
+                    break;
+                case 38:    // 13-24 (38) 2:1
+                    if (s > 12 && s < 25) {
+                        won = ba[c] * 2;
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 39:    // 25-36 (39) 2:1
+                    if (s > 24 && s < 37) {
+                        won = ba[c] * 2;
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 40:    // First column (40) 2:1
+                    if (s < 37 && s % 3 == 1) {
+                        won = ba[c] * 2;
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 41:    // Second column (41) 2:1
+                    if (s < 37 && s % 3 == 2) {
+                        won = ba[c] * 2;
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 42:    // Third column (42) 2:1
+                    if (s < 37 && s % 3 == 0) {
+                        won = ba[c] * 2;
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 43:    // 1-18 (43) 1:1
+                    if (s < 19) {
+                        won = ba[c];
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 44:    // 19-36 (44) 1:1
+                    if (s > 18 && s < 37) {
+                        won = ba[c];
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 45:    // Even (45) 1:1
+                    if (s < 37 && s % 2 == 0) {
+                        won = ba[c];
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 46:    // Odd (46) 1:1
+                    if (s < 37 && s % 2 != 0) {
+                        won = ba[c];
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 47:    // Red (47) 1:1
+                    for (i = 1; i <= 18; i++) {
+                        if (s == numbers[i - 1])
+                            break;
+                    }
+                    if (i <= 18) {
+                        won = ba[c];
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+                case 48:    // Black (48) 1:1
+                    for (i = 1; i <= 18; i++) {
+                        if (s == numbers[i - 1])
+                            break;
+                    }
+                    if (i <= 18 || s > 36) {
+                        won = -ba[c];
+                    } else {
+                        won = ba[c];
+                    }
+                    break;
+                default:    // 1-36,0,00 (1-36,49,50) 35:1
+                    if (ta[c] < 49 && ta[c] == s
+                        || ta[c] == 49 && s == 37
+                        || ta[c] == 50 && s == 38) {
+                        won = ba[c] * 35;
+                    } else {
+                        won = -ba[c];
+                    }
+                    break;
+            }
+            d -= won;
+            p += won;
+            if (won < 0) {
+                print("YOU LOSE " + -won + " DOLLARS ON BET " + c + "\n");
+            } else {
+                print("YOU WIN " + won + " DOLLARS ON BET " + c + "\n");
+            }
+        }
+        print("\n");
+        print("TOTALS:\tME\tYOU\n");
+        print(" \t" + d + "\t" + p + "\n");
+        if (p <= 0) {
+            print("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!\n");
+            break;
+        } else if (d <= 0) {
+            print("YOU BROKE THE HOUSE!\n");
+            p = 101000;
+        }
+        print("AGAIN");
+        str = await input();
+        if (str.substr(0, 1) != "Y")
+            break;
+    }
+    if (p < 1) {
+        print("THANKS FOR YOUR MONEY.\n");
+        print("I'LL USE IT TO BUY A SOLID GOLD ROULETTE WHEEL\n");
+    } else {
+        print("TO WHOM SHALL I MAKE THE CHECK");
+        str = await input();
+        print("\n");
+        for (i = 1; i <= 72; i++)
+            print("-");
+        print("\n");
+        print(tab(50) + "CHECK NO. " + Math.floor(Math.random() * 100) + "\n");
+        print("\n");
+        print(tab(40) + new Date().toDateString());
+        print("\n");
+        print("\n");
+        print("PAY TO THE ORDER OF-----" + str + "-----$ " + p + "\n");
+        print("\n");
+        print("\n");
+        print(tab(10) + "\tTHE MEMORY BANK OF NEW YORK\n");
+        print("\n");
+        print(tab(40) + "\tTHE COMPUTER\n");
+        print(tab(40) + "----------X-----\n");
+        print("\n");
+        for (i = 1; i <= 72; i++)
+            print("-");
+        print("\n");
+        print("COME BACK SOON!\n");
+    }
+    print("\n");
+}
+
+main();

From 9fd26b21921bcdc516b5f4e4b29211cc4df14cd8 Mon Sep 17 00:00:00 2001
From: journich <70119791+journich@users.noreply.github.com>
Date: Tue, 9 Mar 2021 15:46:17 +1030
Subject: [PATCH 273/749] Initial code for Java version of Fur Trader

---
 38 Fur Trader/java/src/FurTrader.java     | 408 ++++++++++++++++++++++
 38 Fur Trader/java/src/FurTraderGame.java |   7 +
 38 Fur Trader/java/src/Pelt.java          |  23 ++
 3 files changed, 438 insertions(+)
 create mode 100644 38 Fur Trader/java/src/FurTrader.java
 create mode 100644 38 Fur Trader/java/src/FurTraderGame.java
 create mode 100644 38 Fur Trader/java/src/Pelt.java

diff --git a/38 Fur Trader/java/src/FurTrader.java b/38 Fur Trader/java/src/FurTrader.java
new file mode 100644
index 00000000..c9bc3272
--- /dev/null
+++ b/38 Fur Trader/java/src/FurTrader.java	
@@ -0,0 +1,408 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of Fur Trader
+ * 

+ * Based on the Basic game of Fur Trader here + * https://github.com/coding-horror/basic-computer-games/blob/main/38%20Fur%20Trader/furtrader.bas + *

+ * 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 FurTrader { + + public static final double START_SAVINGS_AMOUNT = 600.0; + public static final int STARTING_FURS = 190; + + public static final int FORT_HOCHELAGA_MONTREAL = 1; + public static final int FORT_STADACONA_QUEBEC = 2; + public static final int FORT_NEW_YORK = 3; + + public static final String MINK = "MINK"; + public static final int MINK_ENTRY = 0; + public static final String BEAVER = "BEAVER"; + public static final int BEAVER_ENTRY = 1; + public static final String ERMINE = "ERMINE"; + public static final int ERMINE_ENTRY = 2; + public static final String FOX = "FOX"; + public static final int FOX_ENTRY = 3; + + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + STARTUP, + INIT, + TRADE_AT_FORT, + TRADE_SUMMARY, + TRADE_AGAIN, + GAME_OVER + } + + // Current game state + private GAME_STATE gameState; + + private double savings; + private double minkPrice; + private double beaverPrice; + private double erminePrice; + private double foxPrice; + + private ArrayList pelts; + + public FurTrader() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.INIT; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case INIT: + savings = START_SAVINGS_AMOUNT; + + gameStartupMessage(); + + if (yesEntered(displayTextAndGetInput("DO YOU WISH TO TRADE FURS? "))) { + gameState = GAME_STATE.STARTUP; + intro(); + } else { + gameState = GAME_STATE.GAME_OVER; + } + + System.out.println("YOU HAVE $" + savings + " SAVINGS."); + System.out.println("AND " + STARTING_FURS + " FURS TO BEGIN THE EXPEDITION."); + + break; + + case STARTUP: + + pelts = new ArrayList<>(); + + pelts.add(getPelt(MINK)); + pelts.add(getPelt(BEAVER)); + pelts.add(getPelt(ERMINE)); + pelts.add(getPelt(FOX)); + + // Determine if count of total pelts exceeds the maximum + // N.B. Original game was fine with entering less than the + // maximum so this functionality has been left in. + if (pelts.stream().mapToInt(Pelt::getNumber).sum() > STARTING_FURS) { + System.out.println("YOU MAY NOT HAVE THAT MANY FURS."); + System.out.println("DO NOT TRY TO CHEAT. I CAN ADD."); + System.out.println("YOU MUST START AGAIN."); + gameState = GAME_STATE.STARTUP; + } else { + // No cheating, so start trading + erminePrice = ((.15 * Math.random() + .95) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + beaverPrice = ((.25 * Math.random() + 1.00) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + gameState = GAME_STATE.TRADE_AT_FORT; + } + break; + + case TRADE_AT_FORT: + + extendedTradingInfo(); + int answer = displayTextAndGetNumber("ANSWER 1, 2, OR 3. "); + + // Now show the details of the fort they are about to trade + // and give the player the chance to NOT proceed. + // A "No" or false means they do not want to change to another fort + if (!confirmFort(answer)) { + switch (answer) { + case 1: + tradeAtFortHochelagaMontreal(); + gameState = GAME_STATE.TRADE_SUMMARY; + break; + + case 2: + tradeAtFortStadaconaQuebec(); + gameState = GAME_STATE.TRADE_SUMMARY; + break; + case 3: + // Did the player and party all die? + if(!tradeAtFortNewYork()) { + gameState = GAME_STATE.GAME_OVER; + } else { + gameState = GAME_STATE.TRADE_SUMMARY; + } + break; + } + + break; + } + + case TRADE_SUMMARY: + + double beaverTotal = beaverPrice * pelts.get(BEAVER_ENTRY).getNumber(); + System.out.println("YOUR BEAVER SOLD FOR $ " + beaverTotal); + + double foxTotal = foxPrice * pelts.get(FOX_ENTRY).getNumber(); + System.out.println("YOUR FOX SOLD FOR $ " + foxTotal); + + double erMineTotal = erminePrice * pelts.get(ERMINE_ENTRY).getNumber(); + System.out.println("YOUR ERMINE SOLD FOR $ " + erMineTotal); + + double minkTotal = minkPrice * pelts.get(MINK_ENTRY).getNumber(); + System.out.println("YOUR MINK SOLD FOR $ " + minkTotal); + + savings += beaverTotal + foxTotal + erMineTotal + minkTotal; + System.out.println(); + System.out.println("YOU NOW HAVE $" + savings + " INCLUDING YOUR PREVIOUS SAVINGS"); + + gameState = GAME_STATE.TRADE_AGAIN; + break; + + case TRADE_AGAIN: + if(yesEntered(displayTextAndGetInput("DO YOU WANT TO TRADE FURS NEXT YEAR? "))) { + gameState = GAME_STATE.STARTUP; + } else { + gameState = GAME_STATE.GAME_OVER; + } + + } + } while (gameState != GAME_STATE.GAME_OVER); + } + + /** + * Display a message about trading at each fort and confirm if the player wants to trade + * at ANOTHER fort + * @param fort the fort in question + * @return true if YES was typed by player + */ + private boolean confirmFort(int fort) { + switch(fort) { + case FORT_HOCHELAGA_MONTREAL: + System.out.println("YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT"); + System.out.println("IS FAR FROM ANY SEAPORT. THE VALUE"); + System.out.println("YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST"); + System.out.println("OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK."); + break; + case FORT_STADACONA_QUEBEC: + System.out.println("YOU HAVE CHOSEN A HARD ROUTE. IT IS, IN COMPARSION,"); + System.out.println("HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN"); + System.out.println("THE ROUTE TO NEW YORK. YOU WILL RECEIVE AN AVERAGE VALUE"); + System.out.println("FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE."); + break; + case FORT_NEW_YORK: + System.out.println("YOU HAVE CHOSEN THE MOST DIFFICULT ROUTE. AT"); + System.out.println("FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE"); + System.out.println("FOR YOUR FURS. THE COST OF YOUR SUPPLIES"); + System.out.println("WILL BE LOWER THAN AT ALL THE OTHER FORTS."); + break; + } + + System.out.println("DO YOU WANT TO TRADE AT ANOTHER FORT?"); + return yesEntered(displayTextAndGetInput("ANSWER YES OR NO ")); + + } + + /** + * Trade at the safest fort - Fort Hochelaga + * No chance of anything bad happening, so just calculate amount per pelt + * and return + */ + private void tradeAtFortHochelagaMontreal() { + savings -= 160; + System.out.println(); + System.out.println("SUPPLIES AT FORT HOCHELAGA COST $150.00."); + System.out.println("YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00."); + minkPrice = ((.2 * Math.random() + .7) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + erminePrice = ((.2 * Math.random() + .65) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + beaverPrice = ((.2 * Math.random() + .75) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + foxPrice = ((.2 * Math.random() + .8) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + return; + } + + + private void tradeAtFortStadaconaQuebec() { + savings -= 140; + System.out.println(); + minkPrice = ((.2 * Math.random() + .85) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + erminePrice = ((.2 * Math.random() + .8) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + beaverPrice = ((.2 * Math.random() + .9) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + + // What happened during the trip to the fort? + int tripResult = (int) (Math.random()*10) + 1; + if(tripResult <= 2) { + // Find the Beaver pelt in our Arraylist + Pelt beaverPelt = pelts.get(BEAVER_ENTRY); + // Pelts got stolen, so update to a count of zero + beaverPelt.lostPelts(); + // Update it back in the ArrayList + pelts.set(BEAVER_ENTRY, beaverPelt); + + System.out.println("YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS"); + System.out.println("THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND"); + System.out.println("THEM STOLEN WHEN YOU RETURNED."); + } else if (tripResult <= 6) { + System.out.println("YOU ARRIVED SAFELY AT FORT STADACONA."); + } else if (tripResult <= 8) { + System.out.println("YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU"); + System.out.println("LOST ALL YOUR FURS."); + // Clear out all pelts. + for(int i=0; i<3; i++) { + Pelt pelt = pelts.get(i); + pelt.lostPelts(); + pelts.set(i, pelt); + } + } else if(tripResult <= 10) { + // Fox pelts not cured + // Bug because Fox furs were not calculated above in original basic program + // Find the Beaver pelt in our Arraylist + Pelt foxPelt = pelts.get(FOX_ENTRY); + // Pelts got stolen, so update to a count of zero + foxPelt.lostPelts(); + // Update it back in the ArrayList + pelts.set(FOX_ENTRY, foxPelt); + } + + System.out.println("SUPPLIES AT FORT STADACONA COST $125.00."); + System.out.println("YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00."); + } + + private boolean tradeAtFortNewYork() { + + boolean playerAlive = true; + savings -= 105; + System.out.println(); + minkPrice = ((.2 * Math.random() + 1.05) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + foxPrice = ((.2 * Math.random() + 1.1) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); + + // What happened during the trip to the fort? + int tripResult = (int) (Math.random()*10) + 1; + if(tripResult <= 2) { + System.out.println("YOU WERE ATTACKED BY A PARTY OF IROQUOIS."); + System.out.println("ALL PEOPLE IN YOUR TRADING GROUP WERE"); + System.out.println("KILLED. THIS ENDS THE GAME."); + playerAlive = false; + } else if (tripResult <= 6) { + System.out.println("YOU WERE LUCKY. YOU ARRIVED SAFELY"); + System.out.println("AT FORT NEW YORK."); + } else if (tripResult <= 8) { + System.out.println("YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY."); + System.out.println("HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND."); + // Clear out all pelts. + for(int i=0; i<3; i++) { + Pelt pelt = pelts.get(i); + pelt.lostPelts(); + pelts.set(i, pelt); + } + } else if(tripResult <= 10) { + beaverPrice /= 2; + minkPrice /= 2; + System.out.println("YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP."); + System.out.println("YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS."); + } + + if (playerAlive) { + System.out.println("SUPPLIES AT NEW YORK COST $80.00."); + System.out.println("YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00."); + } + + return playerAlive; + } + /** + * Return a pelt object containing the user entered number of pelts. + * + * @param peltName Type of pelt + * @return Pelt object containing name and number of pelts. + */ + private Pelt getPelt(String peltName) { + int pelts = displayTextAndGetNumber("HOW MANY " + peltName + " PELTS DO YOU HAVE? "); + return new Pelt(peltName, pelts); + } + + private void extendedTradingInfo() { + System.out.println("YOU MAY TRADE YOUR FURS AT FORT 1, FORT 2,"); + System.out.println("OR FORT 3. FORT 1 IS FORT HOCHELAGA (MONTREAL)"); + System.out.println("AND IS UNDER THE PROTECTION OF THE FRENCH ARMY."); + System.out.println("FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE"); + System.out.println("PROTECTION OF THE FRENCH ARMY. HOWEVER, YOU MUST"); + System.out.println("MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS."); + System.out.println("FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL."); + System.out.println("YOU MUST CROSS THROUGH IROQUOIS LAND."); + + } + private void gameStartupMessage() { + System.out.println(simulateTabs(31) + "FUR TRADER"); + System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + } + + private void intro() { + System.out.println("YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN "); + System.out.println("1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET"); + System.out.println("SUPPLIES FOR THE NEXT YEAR. YOU HAVE A CHOICE OF THREE"); + System.out.println("FORTS AT WHICH YOU MAY TRADE. THE COST OF SUPPLIES"); + System.out.println("AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND"); + System.out.println("ON THE FORT THAT YOU CHOOSE."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.next(); + } + + /** + * Simulate the old basic tab(xx) command which indented text by xx spaces. + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String simulateTabs(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * 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. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + } + +} diff --git a/38 Fur Trader/java/src/FurTraderGame.java b/38 Fur Trader/java/src/FurTraderGame.java new file mode 100644 index 00000000..9c7aaa1c --- /dev/null +++ b/38 Fur Trader/java/src/FurTraderGame.java @@ -0,0 +1,7 @@ +public class FurTraderGame { + public static void main(String[] args) { + + FurTrader furTrader = new FurTrader(); + furTrader.play(); + } +} diff --git a/38 Fur Trader/java/src/Pelt.java b/38 Fur Trader/java/src/Pelt.java new file mode 100644 index 00000000..d27985b0 --- /dev/null +++ b/38 Fur Trader/java/src/Pelt.java @@ -0,0 +1,23 @@ +public class Pelt { + + private String name; + private int number; + + public Pelt(String name, int number) { + this.name = name; + this.number = number; + } + + public int getNumber() { + return this.number; + } + + public String getName() { + return this.name; + } + + public Object lostPelts() { + this.number = 0; + return null; + } +} From a5389e587c72a24a438ca2438416f582a8e91b46 Mon Sep 17 00:00:00 2001 From: Jack Boyce Date: Tue, 9 Mar 2021 10:42:39 -0800 Subject: [PATCH 274/749] minor cleanup --- 84 Super Star Trek/python/superstartrek.py | 60 ++++++++++++---------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py index 36db1ba8..bcaab094 100644 --- a/84 Super Star Trek/python/superstartrek.py +++ b/84 Super Star Trek/python/superstartrek.py @@ -684,7 +684,7 @@ def computer(): def print_direction(from1, from2, to1, to2): - # Print a direction and distance between two locations in the grid. + # Print direction and distance between two locations in the grid. delta1 = -(to1 - from1) # flip so positive is up (heading = 3) delta2 = to2 - from2 @@ -873,35 +873,39 @@ def end_game(won=False, quit=True, enterprise_killed=False): # Entry point and main game loop # ------------------------------------------------------------------------- +def main(): + f = {'NAV': navigation, 'SRS': short_range_scan, 'LRS': long_range_scan, + 'PHA': phaser_control, 'TOR': photon_torpedoes, 'SHE': shield_control, + 'DAM': damage_control, 'COM': computer, 'XXX': end_game} -f = {'NAV': navigation, 'SRS': short_range_scan, 'LRS': long_range_scan, - 'PHA': phaser_control, 'TOR': photon_torpedoes, 'SHE': shield_control, - 'DAM': damage_control, 'COM': computer, 'XXX': end_game} + while True: + startup() + new_quadrant() + restart = False -while True: - startup() - new_quadrant() - restart = False + while not restart: + if s + e <= 10 or (e <= 10 and d[6] != 0): + print("\n** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP " + "IN SPACE.\nYOU HAVE INSUFFICIENT MANEUVERING ENERGY, " + "AND SHIELD CONTROL\nIS PRESENTLY INCAPABLE OF CROSS-" + "CIRCUITING TO ENGINE ROOM!!") - while not restart: - if s + e <= 10 or (e <= 10 and d[6] != 0): - print("\n** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP IN " - "SPACE.\nYOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND " - "SHIELD CONTROL\nIS PRESENTLY INCAPABLE OF CROSS-CIRCUITING " - "TO ENGINE ROOM!!") + command = input('COMMAND? ').upper().strip() - command = input('COMMAND? ').upper().strip() + if command in f: + f[command]() + else: + print("ENTER ONE OF THE FOLLOWING:\n" + " NAV (TO SET COURSE)\n" + " SRS (FOR SHORT RANGE SENSOR SCAN)\n" + " LRS (FOR LONG RANGE SENSOR SCAN)\n" + " PHA (TO FIRE PHASERS)\n" + " TOR (TO FIRE PHOTON TORPEDOES)\n" + " SHE (TO RAISE OR LOWER SHIELDS)\n" + " DAM (FOR DAMAGE CONTROL REPORTS)\n" + " COM (TO CALL ON LIBRARY-COMPUTER)\n" + " XXX (TO RESIGN YOUR COMMAND)\n") - if command in f: - f[command]() - else: - print("ENTER ONE OF THE FOLLOWING:\n" - " NAV (TO SET COURSE)\n" - " SRS (FOR SHORT RANGE SENSOR SCAN)\n" - " LRS (FOR LONG RANGE SENSOR SCAN)\n" - " PHA (TO FIRE PHASERS)\n" - " TOR (TO FIRE PHOTON TORPEDOES)\n" - " SHE (TO RAISE OR LOWER SHIELDS)\n" - " DAM (FOR DAMAGE CONTROL REPORTS)\n" - " COM (TO CALL ON LIBRARY-COMPUTER)\n" - " XXX (TO RESIGN YOUR COMMAND)\n") + +if __name__ == "__main__": + main() From a932507da623928922a1129cbce3445dc0946abd Mon Sep 17 00:00:00 2001 From: Jack Boyce Date: Tue, 9 Mar 2021 10:52:04 -0800 Subject: [PATCH 275/749] fix restart bug --- 84 Super Star Trek/python/superstartrek.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/84 Super Star Trek/python/superstartrek.py b/84 Super Star Trek/python/superstartrek.py index bcaab094..f6898c0d 100644 --- a/84 Super Star Trek/python/superstartrek.py +++ b/84 Super Star Trek/python/superstartrek.py @@ -873,7 +873,10 @@ def end_game(won=False, quit=True, enterprise_killed=False): # Entry point and main game loop # ------------------------------------------------------------------------- + def main(): + global restart + f = {'NAV': navigation, 'SRS': short_range_scan, 'LRS': long_range_scan, 'PHA': phaser_control, 'TOR': photon_torpedoes, 'SHE': shield_control, 'DAM': damage_control, 'COM': computer, 'XXX': end_game} From 1ce47dd8969e487b11c161c4000c58011598d2e4 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 10 Mar 2021 08:40:09 +1030 Subject: [PATCH 276/749] Final update to FurTrader Java port --- 38 Fur Trader/java/src/FurTrader.java | 178 +++++++++++++++++--------- 38 Fur Trader/java/src/Pelt.java | 12 +- 2 files changed, 130 insertions(+), 60 deletions(-) diff --git a/38 Fur Trader/java/src/FurTrader.java b/38 Fur Trader/java/src/FurTrader.java index c9bc3272..789adb25 100644 --- a/38 Fur Trader/java/src/FurTrader.java +++ b/38 Fur Trader/java/src/FurTrader.java @@ -29,7 +29,6 @@ public class FurTrader { public static final String FOX = "FOX"; public static final int FOX_ENTRY = 3; - // Used for keyboard input private final Scanner kbScanner; @@ -53,9 +52,12 @@ public class FurTrader { private ArrayList pelts; + private boolean playedOnce; + public FurTrader() { kbScanner = new Scanner(System.in); gameState = GAME_STATE.INIT; + playedOnce = false; } /** @@ -69,42 +71,70 @@ public class FurTrader { case INIT: savings = START_SAVINGS_AMOUNT; - gameStartupMessage(); + // Only display initial game heading once + if (!playedOnce) { + playedOnce = true; + gameStartupMessage(); + } + intro(); if (yesEntered(displayTextAndGetInput("DO YOU WISH TO TRADE FURS? "))) { + System.out.println("YOU HAVE $" + formatNumber(savings) + " SAVINGS."); + System.out.println("AND " + STARTING_FURS + " FURS TO BEGIN THE EXPEDITION."); + + // Create a new array of Pelts. + pelts = initPelts(); gameState = GAME_STATE.STARTUP; - intro(); } else { gameState = GAME_STATE.GAME_OVER; } - System.out.println("YOU HAVE $" + savings + " SAVINGS."); - System.out.println("AND " + STARTING_FURS + " FURS TO BEGIN THE EXPEDITION."); - break; case STARTUP: - pelts = new ArrayList<>(); + // Reset count of pelts (all types) + resetPelts(); - pelts.add(getPelt(MINK)); - pelts.add(getPelt(BEAVER)); - pelts.add(getPelt(ERMINE)); - pelts.add(getPelt(FOX)); + // This is where we will go to after processing all pelts. + gameState = GAME_STATE.TRADE_AT_FORT; - // Determine if count of total pelts exceeds the maximum - // N.B. Original game was fine with entering less than the - // maximum so this functionality has been left in. - if (pelts.stream().mapToInt(Pelt::getNumber).sum() > STARTING_FURS) { - System.out.println("YOU MAY NOT HAVE THAT MANY FURS."); - System.out.println("DO NOT TRY TO CHEAT. I CAN ADD."); - System.out.println("YOU MUST START AGAIN."); - gameState = GAME_STATE.STARTUP; - } else { - // No cheating, so start trading + int totalPelts = 0; + // Cycle through all types of pelts + for (int i = 0; i < pelts.size(); i++) { + Pelt pelt = pelts.get(i); + int number = getPeltCount(pelt.getName()); + totalPelts += number; + if (totalPelts > STARTING_FURS) { + System.out.println("YOU MAY NOT HAVE THAT MANY FURS."); + System.out.println("DO NOT TRY TO CHEAT. I CAN ADD."); + System.out.println("YOU MUST START AGAIN."); + System.out.println(); + // Restart the game + gameState = GAME_STATE.INIT; + break; + } else { + // update count entered by player and save back to ArrayList. + pelt.setPeltCount(number); + pelts.set(i, pelt); + // Its possible for the player to put all their pelt allocation + // into one or more different pelts. They don't have to use all four types. + // If we have an exact count of pelts matching the MAX + // don't bother continuing to ask for more. + if (totalPelts == STARTING_FURS) { + break; + } + } + } + + // Only move onto the trading part of the game if the player didn't add too many pelts + if (gameState != GAME_STATE.STARTUP) { + // Set ermine and beaver default prices here, depending on where you trade these + // defaults will either be used or overwritten with other values. + // check out the tradeAt??? methods for more info. erminePrice = ((.15 * Math.random() + .95) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); beaverPrice = ((.25 * Math.random() + 1.00) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); - gameState = GAME_STATE.TRADE_AT_FORT; + System.out.println(); } break; @@ -113,6 +143,8 @@ public class FurTrader { extendedTradingInfo(); int answer = displayTextAndGetNumber("ANSWER 1, 2, OR 3. "); + System.out.println(); + // Now show the details of the fort they are about to trade // and give the player the chance to NOT proceed. // A "No" or false means they do not want to change to another fort @@ -129,7 +161,7 @@ public class FurTrader { break; case 3: // Did the player and party all die? - if(!tradeAtFortNewYork()) { + if (!tradeAtFortNewYork()) { gameState = GAME_STATE.GAME_OVER; } else { gameState = GAME_STATE.TRADE_SUMMARY; @@ -142,27 +174,28 @@ public class FurTrader { case TRADE_SUMMARY: + System.out.println(); double beaverTotal = beaverPrice * pelts.get(BEAVER_ENTRY).getNumber(); - System.out.println("YOUR BEAVER SOLD FOR $ " + beaverTotal); + System.out.print("YOUR BEAVER SOLD FOR $ " + formatNumber(beaverTotal)); double foxTotal = foxPrice * pelts.get(FOX_ENTRY).getNumber(); - System.out.println("YOUR FOX SOLD FOR $ " + foxTotal); + System.out.println(simulateTabs(5) + "YOUR FOX SOLD FOR $ " + formatNumber(foxTotal)); double erMineTotal = erminePrice * pelts.get(ERMINE_ENTRY).getNumber(); - System.out.println("YOUR ERMINE SOLD FOR $ " + erMineTotal); + System.out.print("YOUR ERMINE SOLD FOR $ " + formatNumber(erMineTotal)); double minkTotal = minkPrice * pelts.get(MINK_ENTRY).getNumber(); - System.out.println("YOUR MINK SOLD FOR $ " + minkTotal); + System.out.println(simulateTabs(5) + "YOUR MINK SOLD FOR $ " + formatNumber(minkTotal)); savings += beaverTotal + foxTotal + erMineTotal + minkTotal; System.out.println(); - System.out.println("YOU NOW HAVE $" + savings + " INCLUDING YOUR PREVIOUS SAVINGS"); + System.out.println("YOU NOW HAVE $" + formatNumber(savings) + " INCLUDING YOUR PREVIOUS SAVINGS"); gameState = GAME_STATE.TRADE_AGAIN; break; case TRADE_AGAIN: - if(yesEntered(displayTextAndGetInput("DO YOU WANT TO TRADE FURS NEXT YEAR? "))) { + if (yesEntered(displayTextAndGetInput("DO YOU WANT TO TRADE FURS NEXT YEAR? "))) { gameState = GAME_STATE.STARTUP; } else { gameState = GAME_STATE.GAME_OVER; @@ -172,14 +205,30 @@ public class FurTrader { } while (gameState != GAME_STATE.GAME_OVER); } + /** + * Create all pelt types with a count of zero + * + * @return Arraylist of initialised Pelt objects. + */ + private ArrayList initPelts() { + + ArrayList tempPelts = new ArrayList<>(); + tempPelts.add(new Pelt(MINK, 0)); + tempPelts.add(new Pelt(BEAVER, 0)); + tempPelts.add(new Pelt(ERMINE, 0)); + tempPelts.add(new Pelt(FOX, 0)); + return tempPelts; + } + /** * Display a message about trading at each fort and confirm if the player wants to trade * at ANOTHER fort + * * @param fort the fort in question * @return true if YES was typed by player */ private boolean confirmFort(int fort) { - switch(fort) { + switch (fort) { case FORT_HOCHELAGA_MONTREAL: System.out.println("YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT"); System.out.println("IS FAR FROM ANY SEAPORT. THE VALUE"); @@ -211,7 +260,7 @@ public class FurTrader { * and return */ private void tradeAtFortHochelagaMontreal() { - savings -= 160; + savings -= 160.0; System.out.println(); System.out.println("SUPPLIES AT FORT HOCHELAGA COST $150.00."); System.out.println("YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00."); @@ -219,27 +268,25 @@ public class FurTrader { erminePrice = ((.2 * Math.random() + .65) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); beaverPrice = ((.2 * Math.random() + .75) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); foxPrice = ((.2 * Math.random() + .8) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); - return; } private void tradeAtFortStadaconaQuebec() { - savings -= 140; + savings -= 140.0; System.out.println(); minkPrice = ((.2 * Math.random() + .85) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); erminePrice = ((.2 * Math.random() + .8) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); beaverPrice = ((.2 * Math.random() + .9) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); // What happened during the trip to the fort? - int tripResult = (int) (Math.random()*10) + 1; - if(tripResult <= 2) { + int tripResult = (int) (Math.random() * 10) + 1; + if (tripResult <= 2) { // Find the Beaver pelt in our Arraylist Pelt beaverPelt = pelts.get(BEAVER_ENTRY); // Pelts got stolen, so update to a count of zero beaverPelt.lostPelts(); // Update it back in the ArrayList pelts.set(BEAVER_ENTRY, beaverPelt); - System.out.println("YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS"); System.out.println("THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND"); System.out.println("THEM STOLEN WHEN YOU RETURNED."); @@ -249,13 +296,11 @@ public class FurTrader { System.out.println("YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU"); System.out.println("LOST ALL YOUR FURS."); // Clear out all pelts. - for(int i=0; i<3; i++) { - Pelt pelt = pelts.get(i); - pelt.lostPelts(); - pelts.set(i, pelt); - } - } else if(tripResult <= 10) { + resetPelts(); + } else if (tripResult <= 10) { // Fox pelts not cured + System.out.println("YOUR FOX PELTS WERE NOT CURED PROPERLY."); + System.out.println("NO ONE WILL BUY THEM."); // Bug because Fox furs were not calculated above in original basic program // Find the Beaver pelt in our Arraylist Pelt foxPelt = pelts.get(FOX_ENTRY); @@ -272,14 +317,14 @@ public class FurTrader { private boolean tradeAtFortNewYork() { boolean playerAlive = true; - savings -= 105; + savings -= 105.0; System.out.println(); minkPrice = ((.2 * Math.random() + 1.05) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); foxPrice = ((.2 * Math.random() + 1.1) * (Math.pow(10, 2) + .5)) / Math.pow(10, 2); // What happened during the trip to the fort? - int tripResult = (int) (Math.random()*10) + 1; - if(tripResult <= 2) { + int tripResult = (int) (Math.random() * 10) + 1; + if (tripResult <= 2) { System.out.println("YOU WERE ATTACKED BY A PARTY OF IROQUOIS."); System.out.println("ALL PEOPLE IN YOUR TRADING GROUP WERE"); System.out.println("KILLED. THIS ENDS THE GAME."); @@ -291,12 +336,8 @@ public class FurTrader { System.out.println("YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY."); System.out.println("HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND."); // Clear out all pelts. - for(int i=0; i<3; i++) { - Pelt pelt = pelts.get(i); - pelt.lostPelts(); - pelts.set(i, pelt); - } - } else if(tripResult <= 10) { + resetPelts(); + } else if (tripResult <= 10) { beaverPrice /= 2; minkPrice /= 2; System.out.println("YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP."); @@ -310,15 +351,26 @@ public class FurTrader { return playerAlive; } + + /** + * Reset pelt count for all Pelt types to zero. + */ + private void resetPelts() { + for (int i = 0; i < pelts.size(); i++) { + Pelt pelt = pelts.get(i); + pelt.lostPelts(); + pelts.set(i, pelt); + } + } + /** * Return a pelt object containing the user entered number of pelts. * - * @param peltName Type of pelt - * @return Pelt object containing name and number of pelts. + * @param peltName Name of pelt (Type) + * @return number of pelts assigned by player */ - private Pelt getPelt(String peltName) { - int pelts = displayTextAndGetNumber("HOW MANY " + peltName + " PELTS DO YOU HAVE? "); - return new Pelt(peltName, pelts); + private int getPeltCount(String peltName) { + return displayTextAndGetNumber("HOW MANY " + peltName + " PELTS DO YOU HAVE? "); } private void extendedTradingInfo() { @@ -330,8 +382,10 @@ public class FurTrader { System.out.println("MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS."); System.out.println("FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL."); System.out.println("YOU MUST CROSS THROUGH IROQUOIS LAND."); + System.out.println(); } + private void gameStartupMessage() { System.out.println(simulateTabs(31) + "FUR TRADER"); System.out.println(simulateTabs(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); @@ -345,6 +399,17 @@ public class FurTrader { System.out.println("FORTS AT WHICH YOU MAY TRADE. THE COST OF SUPPLIES"); System.out.println("AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND"); System.out.println("ON THE FORT THAT YOU CHOOSE."); + System.out.println(); + } + + /** + * Format a double number to two decimal points for output. + * + * @param number double number + * @return formatted number as a string + */ + private String formatNumber(double number) { + return String.format("%.2f", number); } /* @@ -404,5 +469,4 @@ public class FurTrader { return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); } - } diff --git a/38 Fur Trader/java/src/Pelt.java b/38 Fur Trader/java/src/Pelt.java index d27985b0..92c9629d 100644 --- a/38 Fur Trader/java/src/Pelt.java +++ b/38 Fur Trader/java/src/Pelt.java @@ -1,6 +1,9 @@ +/** + * Pelt object - tracks the name and number of pelts the player has for this pelt type + */ public class Pelt { - private String name; + private final String name; private int number; public Pelt(String name, int number) { @@ -8,6 +11,10 @@ public class Pelt { this.number = number; } + public void setPeltCount(int pelts) { + this.number = pelts; + } + public int getNumber() { return this.number; } @@ -16,8 +23,7 @@ public class Pelt { return this.name; } - public Object lostPelts() { + public void lostPelts() { this.number = 0; - return null; } } From 14944781b8fd790aeaaa715073bf67d31ea2754b Mon Sep 17 00:00:00 2001 From: nanochess Date: Tue, 9 Mar 2021 20:56:10 -0600 Subject: [PATCH 277/749] Ported EVENWINS to Javascript --- 35 Even Wins/javascript/evenwins.html | 9 + 35 Even Wins/javascript/evenwins.js | 197 ++++++++++++++++++++ 35 Even Wins/javascript/gameofevenwins.html | 9 + 35 Even Wins/javascript/gameofevenwins.js | 152 +++++++++++++++ 4 files changed, 367 insertions(+) create mode 100644 35 Even Wins/javascript/evenwins.html create mode 100644 35 Even Wins/javascript/evenwins.js create mode 100644 35 Even Wins/javascript/gameofevenwins.html create mode 100644 35 Even Wins/javascript/gameofevenwins.js diff --git a/35 Even Wins/javascript/evenwins.html b/35 Even Wins/javascript/evenwins.html new file mode 100644 index 00000000..c39d09ba --- /dev/null +++ b/35 Even Wins/javascript/evenwins.html @@ -0,0 +1,9 @@ + + +EVEN WINS + + +


+
+
+
diff --git a/35 Even Wins/javascript/evenwins.js b/35 Even Wins/javascript/evenwins.js
new file mode 100644
index 00000000..90f273f1
--- /dev/null
+++ b/35 Even Wins/javascript/evenwins.js	
@@ -0,0 +1,197 @@
+// EVEN WINS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var ma = [];
+var ya = [];
+
+// Main program
+async function main()
+{
+    print(tab(31) + "EVEN WINS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    y1 = 0;
+    m1 = 0;
+    print("     THIS IS A TWO PERSON GAME CALLED 'EVEN WINS.'\n");
+    print("TO PLAY THE GAME, THE PLAYERS NEED 27 MARBLES OR\n");
+    print("OTHER OBJECTS ON A TABLE.\n");
+    print("\n");
+    print("\n");
+    print("     THE 2 PLAYERS ALTERNATE TURNS, WITH EACH PLAYER\n");
+    print("REMOVING FROM 1 TO 4 MARBLES ON EACH MOVE.  THE GAME\n");
+    print("ENDS WHEN THERE ARE NO MARBLES LEFT, AND THE WINNER\n");
+    print("IS THE ONE WITH AN EVEN NUMBER OF MARBLES.\n");
+    print("\n");
+    print("\n");
+    print("     THE ONLY RULES ARE THAT (1) YOU MUST ALTERNATE TURNS,\n");
+    print("(2) YOU MUST TAKE BETWEEN 1 AND 4 MARBLES EACH TURN,\n");
+    print("AND (3) YOU CANNOT SKIP A TURN.\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("     TYPE A '1' IF YOU WANT TO GO FIRST, AND TYPE\n");
+        print("A '0' IF YOU WANT ME TO GO FIRST.\n");
+        c = parseInt(await input());
+        print("\n");
+        if (c != 0) {
+            t = 27;
+            print("\n");
+            print("\n");
+            print("\n");
+            print("TOTAL= " + t + "\n");
+            print("\n");
+            print("\n");
+            print("WHAT IS YOUR FIRST MOVE");
+            m = 0;
+        } else {
+            t = 27;
+            m = 2;
+            print("\n");
+            print("TOTAL= " + t + "\n");
+            print("\n");
+            m1 += m;
+            t -= m;
+        }
+        while (1) {
+            if (m) {
+                print("I PICK UP " + m + " MARBLES.\n");
+                if (t == 0)
+                    break;
+                print("\n");
+                print("TOTAL= " + t + "\n");
+                print("\n");
+                print("     AND WHAT IS YOUR NEXT MOVE, MY TOTAL IS " + m1 + "\n");
+            }
+            while (1) {
+                y = parseInt(await input());
+                print("\n");
+                if (y < 1 || y > 4) {
+                    print("\n");
+                    print("THE NUMBER OF MARBLES YOU MUST TAKE BE A POSITIVE\n");
+                    print("INTEGER BETWEEN 1 AND 4.\n");
+                    print("\n");
+                    print("     WHAT IS YOUR NEXT MOVE?\n");
+                    print("\n");
+                } else if (y > t) {
+                    print("     YOU HAVE TRIED TO TAKE MORE MARBLES THAN THERE ARE\n");
+                    print("LEFT.  TRY AGAIN.\n");
+                } else {
+                    break;
+                }
+            }
+            
+            y1 += y;
+            t -= y;
+            if (t == 0)
+                break;
+            print("TOTAL= " + t + "\n");
+            print("\n");
+            print("YOUR TOTAL IS " + y1 + "\n");
+            if (t < 0.5)
+                break;
+            r = t % 6;
+            if (y1 % 2 != 0) {
+                if (t >= 4.2) {
+                    if (r <= 3.4) {
+                        m = r + 1;
+                        m1 += m;
+                        t -= m;
+                    } else if (r < 4.7 || r > 3.5) {
+                        m = 4;
+                        m1 += m;
+                        t -= m;
+                    } else {
+                        m = 1;
+                        m1 += m;
+                        t -= m;
+                    }
+                } else {
+                    m = t;
+                    t -= m;
+                    print("I PICK UP " + m + " MARBLES.\n");
+                    print("\n");
+                    print("TOTAL = 0\n");
+                    m1 += m;
+                    break;
+                }
+            } else {
+                if (r < 1.5 || r > 5.3) {
+                    m = 1;
+                    m1 += m;
+                    t -= m;
+                } else {
+                    m = r - 1;
+                    m1 += m;
+                    t -= m;
+                    if (t < 0.2) {
+                        print("I PICK UP " + m + " MARBLES.\n");
+                        print("\n");
+                        break;
+                    }
+                }
+            }
+        }
+        print("THAT IS ALL OF THE MARBLES.\n");
+        print("\n");
+        print(" MY TOTAL IS " + m1 + ", YOUR TOTAL IS " + y1 +"\n");
+        print("\n");
+        if (m1 % 2 != 0) {
+            print("     YOU WON.  DO YOU WANT TO PLAY\n");
+        } else {
+            print("     I WON.  DO YOU WANT TO PLAY\n");
+        }
+        print("AGAIN?  TYPE 1 FOR YES AND 0 FOR NO.\n");
+        a1 = parseInt(await input());
+        if (a1 == 0)
+            break;
+        m1 = 0;
+        y1 = 0;
+    }
+    print("\n");
+    print("OK.  SEE YOU LATER\n");
+}
+
+main();
diff --git a/35 Even Wins/javascript/gameofevenwins.html b/35 Even Wins/javascript/gameofevenwins.html
new file mode 100644
index 00000000..9359f077
--- /dev/null
+++ b/35 Even Wins/javascript/gameofevenwins.html	
@@ -0,0 +1,9 @@
+
+
+GAME OF EVEN WINS
+
+
+

+
+
+
diff --git a/35 Even Wins/javascript/gameofevenwins.js b/35 Even Wins/javascript/gameofevenwins.js
new file mode 100644
index 00000000..945bc0ba
--- /dev/null
+++ b/35 Even Wins/javascript/gameofevenwins.js	
@@ -0,0 +1,152 @@
+// GAME OF EVEN WINS
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var r = [[], []];
+
+// Main program
+async function main()
+{
+    print(tab(28) + "GAME OF EVEN WINS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("DO YOU WANT INSTRUCTIONS (YES OR NO)");
+    str = await input();
+    print("\n");
+    if (str != "NO") {
+        print("THE GAME IS PLAYED AS FOLLOWS:\n");
+        print("\n");
+        print("AT THE BEGINNING OF THE GAME, A RANDOM NUMBER OF CHIPS ARE\n");
+        print("PLACED ON THE BOARD.  THE NUMBER OF CHIPS ALWAYS STARTS\n");
+        print("AS AN ODD NUMBER.  ON EACH TURN, A PLAYER MUST TAKE ONE,\n");
+        print("TWO, THREE, OR FOUR CHIPS.  THE WINNER IS THE PLAYER WHO\n");
+        print("FINISHES WITH A TOTAL NUMBER OF CHIPS THAT IS EVEN.\n");
+        print("THE COMPUTER STARTS OUT KNOWING ONLY THE RULES OF THE\n");
+        print("GAME.  IT GRADUALLY LEARNS TO PLAY WELL.  IT SHOULD BE\n");
+        print("DIFFICULT TO BEAT THE COMPUTER AFTER TWENTY GAMES IN A ROW.\n");
+        print("TRY IT!!!!\n");
+        print("\n");
+        print("TO QUIT AT ANY TIME, TYPE A '0' AS YOUR MOVE.\n");
+        print("\n");
+    }
+    l = 0;
+    b = 0;
+    for (i = 0; i <= 5; i++) {
+        r[1][i] = 4;
+        r[0][i] = 4;
+    }
+    while (1) {
+        a = 0;
+        b = 0;
+        e = 0;
+        l = 0;
+        p = Math.floor((13 * Math.random() + 9) / 2) * 2 + 1;
+        while (1) {
+            if (p == 1) {
+                print("THERE IS 1 CHIP ON THE BOARD.\n");
+            } else {
+                print("THERE ARE " + p + " CHIPS ON THE BOARD.\n");
+            }
+            e1 = e;
+            l1 = l;
+            e = a % 2;
+            l = p % 6;
+            if (r[e][l] < p) {
+                m = r[e][l];
+                if (m <= 0) {
+                    m = 1;
+                    b = 1;
+                    break;
+                }
+                p -= m;
+                if (m == 1)
+                    print("COMPUTER TAKES 1 CHIP LEAVING " + p + "... YOUR MOVE");
+                else
+                    print("COMPUTER TAKES " + m + " CHIPS LEAVING " + p + "... YOUR MOVE");
+                b += m;
+                while (1) {
+                    m = parseInt(await input());
+                    if (m == 0)
+                        break;
+                    if (m < 1 || m > 4 || m > p) {
+                        print(m + " IS AN ILLEGAL MOVE ... YOUR MOVE");
+                    } else {
+                        break;
+                    }
+                }
+                if (m == 0)
+                    break;
+                if (m == p)
+                    break;
+                p -= m;
+                a += m;
+            } else {
+                if (p == 1) {
+                    print("COMPUTER TAKES 1 CHIP.\n");
+                } else {
+                    print("COMPUTER TAKES " + p + " CHIPS.\n");
+                }
+                r[e][l] = p;
+                b += p;
+                break;
+            }
+        }
+        if (m == 0)
+            break;
+        if (b % 2 != 0) {
+            print("GAME OVER ... YOU WIN!!!\n");
+            print("\n");
+            if (r[e][l] != 1) {
+                r[e][l]--;
+            } else if (r[e1][l1] != 1) {
+                r[e1][l1]--;
+            }
+        } else {
+            print("GAME OVER ... I WIN!!!\n");
+            print("\n");
+        }
+    }
+}
+
+main();

From 799c1201924535269f19a001cde6097b3af75b06 Mon Sep 17 00:00:00 2001
From: NezumiRonin 
Date: Tue, 9 Mar 2021 22:13:54 -0600
Subject: [PATCH 278/749] Create russianroulette.pl

Automatic converted with a Perl Script. Yes, it looks horrible with the gotos, but it works!
---
 76 Russian Roulette/perl/russianroulette.pl | 39 +++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 76 Russian Roulette/perl/russianroulette.pl

diff --git a/76 Russian Roulette/perl/russianroulette.pl b/76 Russian Roulette/perl/russianroulette.pl
new file mode 100644
index 00000000..0fa0cff7
--- /dev/null
+++ b/76 Russian Roulette/perl/russianroulette.pl	
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+#use strict;
+# Automatic converted by bas2perl.pl
+
+print ' 'x28 . "RUSSIAN ROULETTE\n";
+print ' 'x15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n"; print "\n"; print "\n";
+print "THIS IS A GAME OF >>>>>>>>>>RUSSIAN ROULETTE.\n";
+Line10:
+print "\n"; print "HERE IS A REVOLVER.\n";
+Line20:
+print "TYPE '1' TO SPIN CHAMBER AND PULL TRIGGER.\n";
+print "TYPE '2' TO GIVE UP.\n";
+print "GO";
+$N=0;
+Line30:
+print "? "; chomp($I = );
+if ($I ne 2) { goto Line35; }
+print " CHICKEN!!!!!\n";
+goto Line72;
+Line35:
+$N=$N+1;
+if (rand(1)>.833333) { goto Line70; }
+if ($N>10) { goto Line80; }
+print "- CLICK -\n";
+print "\n"; goto Line30;
+Line70:
+print " BANG!!!!! YOU'RE DEAD!\n";
+print "CONDOLENCES WILL BE SENT TO YOUR RELATIVES.\n";
+Line72:
+print "\n"; print "\n"; print "\n";
+print "...NEXT VICTIM...\n"; goto Line20;
+Line80:
+print "YOU WIN!!!!!\n";
+print "LET SOMEONE ELSE BLOW HIS BRAINS OUT.\n";
+goto Line10;
+exit;
+
+

From d03e7df85bc3320c15d0e8cca5afdb02215a8942 Mon Sep 17 00:00:00 2001
From: NezumiRonin 
Date: Tue, 9 Mar 2021 22:50:45 -0600
Subject: [PATCH 279/749] Create perlchemist.pl

Chemist ported to Perl!
---
 24 Chemist/perlchemist.pl | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)
 create mode 100644 24 Chemist/perlchemist.pl

diff --git a/24 Chemist/perlchemist.pl b/24 Chemist/perlchemist.pl
new file mode 100644
index 00000000..01ed9f02
--- /dev/null
+++ b/24 Chemist/perlchemist.pl	
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+use strict;
+
+print ' 'x33 . "CHEMIST\n";
+print ' 'x15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n"; print "\n"; print "\n";
+print "THE FICTITIOUS CHECMICAL KRYPTOCYANIC ACID CAN ONLY BE\n";
+print "DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID.\n";
+print "IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE\n";
+print "AND SOON EXPLODES. GIVEN THE AMOUNT OF ACID, YOU MUST\n";
+print "DECIDE WHO MUCH WATER TO ADD FOR DILUTION. IF YOU MISS\n";
+print "YOU FACE THE CONSEQUENCES.\n";
+
+my $T=0;
+while ($T<9) {
+	my $A= int(rand(1)*50);
+	my $W= 7*$A/3;
+	print "$A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER ($W)";
+	print "? "; chomp(my $R = );
+	my $D= abs($W-$R);
+	if ($D>$W/20) {
+		print " SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
+		print " OF QUIVERING PROTOPLASM!\n";
+		print " HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
+		print "\n";
+		$T++;
+		} else {
+		print " GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
+		print "\n";
+		}
+	}
+
+print " YOUR 9 LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR\n";
+print " YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.\n";
+exit;
+
+

From 053e8ecd5b6c89965f58cf437ada8e114e34618f Mon Sep 17 00:00:00 2001
From: NezumiRonin 
Date: Tue, 9 Mar 2021 23:25:47 -0600
Subject: [PATCH 280/749] Update README.md

Page number corrected.
---
 32 Diamond/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/32 Diamond/README.md b/32 Diamond/README.md
index 25ce1890..36bdb9e2 100644
--- a/32 Diamond/README.md	
+++ b/32 Diamond/README.md	
@@ -1,7 +1,7 @@
 ### Diamond
 
 As published in Basic Computer Games (1978)
-https://www.atariarchives.org/basicgames/showpage.php?page=55
+https://www.atariarchives.org/basicgames/showpage.php?page=56
 
 Downloaded from Vintage Basic at
 http://www.vintage-basic.net/games.html

From 613db180a3e6e0a042e9c8ac02f8ddcb5f847691 Mon Sep 17 00:00:00 2001
From: Les Orchard 
Date: Tue, 16 Feb 2021 23:10:46 -0800
Subject: [PATCH 281/749] Super Star Trek ported to JavaScript

---
 84 Super Star Trek/javascript/cli.mjs         |   35 +
 84 Super Star Trek/javascript/index.html      |  234 +++
 84 Super Star Trek/javascript/package.json    |   14 +
 .../javascript/superstartrek.mjs              | 1679 +++++++++++++++++
 4 files changed, 1962 insertions(+)
 create mode 100644 84 Super Star Trek/javascript/cli.mjs
 create mode 100644 84 Super Star Trek/javascript/index.html
 create mode 100644 84 Super Star Trek/javascript/package.json
 create mode 100644 84 Super Star Trek/javascript/superstartrek.mjs

diff --git a/84 Super Star Trek/javascript/cli.mjs b/84 Super Star Trek/javascript/cli.mjs
new file mode 100644
index 00000000..bacceff8
--- /dev/null
+++ b/84 Super Star Trek/javascript/cli.mjs	
@@ -0,0 +1,35 @@
+import {
+  onExit,
+  onPrint,
+  onInput,
+  setGameOptions,
+  getGameState,
+  gameMain,
+} from "./superstartrek.mjs";
+
+import util from "util";
+import readline from "readline";
+
+onExit(function exit() {
+  process.exit();
+});
+
+onPrint(function print(...messages) {
+  console.log(messages.join(""));
+});
+
+onInput(async function input(prompt) {
+  const rl = readline.createInterface({
+    input: process.stdin,
+    output: process.stdout,
+    terminal: false,
+  });
+  return new Promise((resolve, reject) => {
+    rl.question(`${prompt}? `, (response) => {
+      rl.close();
+      resolve(response);
+    });
+  });
+});
+
+gameMain().then(process.exit).catch(console.log);
diff --git a/84 Super Star Trek/javascript/index.html b/84 Super Star Trek/javascript/index.html
new file mode 100644
index 00000000..fd3a7e09
--- /dev/null
+++ b/84 Super Star Trek/javascript/index.html	
@@ -0,0 +1,234 @@
+
+  
+    Super Star Trek
+    
+    
+    
+  
+  
+    
+ + + + + + + diff --git a/84 Super Star Trek/javascript/package.json b/84 Super Star Trek/javascript/package.json new file mode 100644 index 00000000..7d75d554 --- /dev/null +++ b/84 Super Star Trek/javascript/package.json @@ -0,0 +1,14 @@ +{ + "name": "super-star-trek", + "version": "1.0.0", + "description": "As published in Basic Computer Games (1978) https://www.atariarchives.org/basicgames/showpage.php?page=157", + "main": "superstartrek.mjs", + "scripts": { + "start": "node cli.mjs" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "eslint": "^7.20.0" + } +} diff --git a/84 Super Star Trek/javascript/superstartrek.mjs b/84 Super Star Trek/javascript/superstartrek.mjs new file mode 100644 index 00000000..9a4573c6 --- /dev/null +++ b/84 Super Star Trek/javascript/superstartrek.mjs @@ -0,0 +1,1679 @@ +/** + * SUPER STARTREK - MAY 16,1978 - REQUIRES 24K MEMORY + * + * **** STAR TREK **** **** + * SIMULATION OF A MISSION OF THE STARSHIP ENTERPRISE, + * AS SEEN ON THE STAR TREK TV SHOW. + * ORIGIONAL PROGRAM BY MIKE MAYFIELD, MODIFIED VERSION + * PUBLISHED IN DEC'S "101 BASIC GAMES", BY DAVE AHL. + * MODIFICATIONS TO THE LATTER (PLUS DEBUGGING) BY BOB + * LEEDOM - APRIL & DECEMBER 1974, + * WITH A LITTLE HELP FROM HIS FRIENDS . . . + * COMMENTS, EPITHETS, AND SUGGESTIONS SOLICITED -- + * SEND TO: R. C. LEEDOM + * WESTINGHOUSE DEFENSE & ELECTRONICS SYSTEMS CNTR. + * BOX 746, M.S. 338 + * BALTIMORE, MD 21203 + * + * CONVERTED TO MICROSOFT 8 K BASIC 3/16/78 BY JOHN GORDERS + * LINE NUMBERS FROM VERSION STREK7 OF 1/12/75 PRESERVED AS + * MUCH AS POSSIBLE WHILE USING MULTIPLE STATEMENTS PER LINE + * SOME LINES ARE LONGER THAN 72 CHARACTERS; THIS WAS DONE + * BY USING "?" INSTEAD OF "PRINT" WHEN ENTERING LINES + * + * Translated and reworked into JavaScript in February 2021 + * by Les Orchard + */ + +export const setGameOptions = (options = {}) => + Object.assign(gameOptions, options); +export const getGameState = () => ({ ...gameState }); +export const onPrint = (fn) => (print = fn); +export const onInput = (fn) => (input = fn); +export const onExit = (fn) => (exit = fn); + +export async function gameMain() { + await gameReset(); + await gameLoop(); + await exit(); +} + +let gameState = {}; +let print = () => {}; +let input = () => {}; +let exit = () => {}; + +export const gameOptions = { + stardateStart: Math.floor(Math.random() * 20 + 20) * 100, + timeLimit: 25 + Math.floor(Math.random() * 10), + energyMax: 3000, + photonTorpedoesMax: 10, + starbaseSpawnChance: 0.96, + enemyMaxShield: 200, + enemySpawnChance: [0.8, 0.85, 0.98], + maxStarsPerSector: 8, + sectorWidth: 8, + sectorHeight: 8, + galaxyWidth: 8, + galaxyHeight: 8, + systemDamageChanceOnHit: 0.6, + systemDamageHitThroughShields: 0.02, + systemChanceAffectedInWarp: 0.2, + systemChanceDamageInWarp: 0.6, + nameEnemy: "KLINGON", + nameEnemies: "KLINGONS", + nameScienceOfficer: "SPOCK", + nameNavigationOfficer: "LT. SULU", + nameWeaponsOfficer: "ENSIGN CHEKOV", + nameCommunicationsOfficer: "LT. UHURA", + nameChiefEngineer: "SCOTT", + sectorMapSymbols: { + empty: " ", + star: " * ", + base: ">!<", + hero: "<*>", + enemy: "+K+", + }, + shipSystems: [ + "WARP ENGINES", + "SHORT RANGE SENSORS", + "LONG RANGE SENSORS", + "PHASER CONTROL", + "PHOTON TUBES", + "DAMAGE CONTROL", + "SHIELD CONTROL", + "LIBRARY-COMPUTER", + ], + quadrantNames: [ + [ + "ANTARES", + "RIGEL", + "PROCYON", + "VEGA", + "CANOPUS", + "ALTAIR", + "SAGITTARIUS", + "POLLUX", + ], + [ + "SIRIUS", + "DENEB", + "CAPELLA", + "BETELGEUSE", + "ALDEBARAN", + "REGULUS", + "ARCTURUS", + "SPICA", + ], + ], + quadrantNumbers: ["I", "II", "III", "IV"], +}; + +let SYSTEM_WARP_ENGINES, + SYSTEM_SHORT_RANGE_SENSORS, + SYSTEM_LONG_RANGE_SENSORS, + SYSTEM_PHASER_CONTROL, + SYSTEM_PHOTON_TUBES, + SYSTEM_DAMAGE_CONTROL, + SYSTEM_SHIELD_CONTROL, + SYSTEM_LIBRARY_COMPUTER; + +async function gameIntro() { + print("\n".repeat(10)); + print(" ,------*------,"); + print(" ,------------- '--- ------'"); + print(" '-------- --' / /"); + print(" ,---' '-------/ /--,"); + print(" '----------------'"); + print(""); + print(" THE USS ENTERPRISE --- NCC-1701"); + print("\n".repeat(4)); + + print("YOUR ORDERS ARE AS FOLLOWS:"); + print(); + print( + ` DESTROY THE ${gameState.enemiesRemaining} ${gameOptions.nameEnemy} WARSHIPS WHICH HAVE INVADED` + ); + print(" THE GALAXY BEFORE THEY CAN ATTACK FEDERATION HEADQUARTERS"); + print( + ` ON STARDATE ${formatStardate( + gameOptions.stardateStart + gameOptions.timeLimit + )} THIS GIVES YOU ${gameOptions.timeLimit} DAYS. THERE${ + gameState.starbasesRemaining > 1 ? " ARE " : " IS " + }` + ); + print( + ` ${gameState.starbasesRemaining} STARBASE${ + gameState.starbasesRemaining > 1 ? "S" : " ARE" + } IN THE GALAXY FOR RESUPPLYING YOUR SHIP` + ); +} + +async function gameReset() { + [ + SYSTEM_WARP_ENGINES, + SYSTEM_SHORT_RANGE_SENSORS, + SYSTEM_LONG_RANGE_SENSORS, + SYSTEM_PHASER_CONTROL, + SYSTEM_PHOTON_TUBES, + SYSTEM_DAMAGE_CONTROL, + SYSTEM_SHIELD_CONTROL, + SYSTEM_LIBRARY_COMPUTER, + ] = gameOptions.shipSystems; + + gameState = { + gameOver: false, + gameWon: false, + gameQuit: false, + destroyed: false, + shouldRestart: false, + sectorMap: "", + alertCondition: "", + stardateCurrent: gameOptions.stardateStart, + isDocked: false, + energyRemaining: gameOptions.energyMax, + photonTorpedoesRemaining: gameOptions.photonTorpedoesMax, + shieldsCurrent: 0, + starbasesRemaining: 0, + enemiesRemaining: 0, + quadrantPositionY: randomInt(gameOptions.galaxyHeight, 1), + quadrantPositionX: randomInt(gameOptions.galaxyWidth, 1), + sectorPositionY: randomInt(gameOptions.sectorHeight, 1), + sectorPositionX: randomInt(gameOptions.sectorWidth, 1), + sectorEnemiesCount: 0, + sectorStarbasesCount: 0, + sectorStarsCount: 0, + galacticMap: [], + galacticMapDiscovered: [], + }; + + gameState.systemsDamage = {}; + for (const systemName of gameOptions.shipSystems) { + gameState.systemsDamage[systemName] = 0; + } + + for (let mapY = 1; mapY <= gameOptions.galaxyHeight; mapY++) { + gameState.galacticMap[mapY] = []; + gameState.galacticMapDiscovered[mapY] = []; + for (let mapX = 1; mapX <= gameOptions.galaxyWidth; mapX++) { + gameState.galacticMapDiscovered[mapY][mapX] = 0; + + gameState.sectorEnemiesCount = 0; + + const enemySpawnRoll = Math.random(); + if (enemySpawnRoll > gameOptions.enemySpawnChance[2]) { + gameState.sectorEnemiesCount = 3; + gameState.enemiesRemaining = gameState.enemiesRemaining + 3; + } else if (enemySpawnRoll > gameOptions.enemySpawnChance[1]) { + gameState.sectorEnemiesCount = 2; + gameState.enemiesRemaining = gameState.enemiesRemaining + 2; + } else if (enemySpawnRoll > gameOptions.enemySpawnChance[0]) { + gameState.sectorEnemiesCount = 1; + gameState.enemiesRemaining = gameState.enemiesRemaining + 1; + } + + gameState.sectorStarbasesCount = 0; + if (Math.random() > gameOptions.starbaseSpawnChance) { + gameState.sectorStarbasesCount = 1; + gameState.starbasesRemaining = gameState.starbasesRemaining + 1; + } + + // 1040 + gameState.galacticMap[mapY][mapX] = + gameState.sectorEnemiesCount * 100 + + gameState.sectorStarbasesCount * 10 + + randomInt(gameOptions.maxStarsPerSector, 1); + } + } + + if (gameState.enemiesRemaining > gameOptions.timeLimit) { + // Ensure the player has at least one more stardate than the number of enemies + gameOptions.timeLimit = gameState.enemiesRemaining + 1; + } + + if (gameState.starbasesRemaining === 0) { + if ( + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] < 200 + ) { + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] = + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] + 120; + } + gameState.enemiesRemaining = gameState.enemiesRemaining + 1; + gameState.starbasesRemaining = 1; + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] = + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] + 10; + gameState.quadrantPositionY = randomInt(gameOptions.galaxyHeight, 1); + gameState.quadrantPositionX = randomInt(gameOptions.galaxyWidth, 1); + } + + gameState.enemiesInitialCount = gameState.enemiesRemaining; + + await gameIntro(); + await newQuadrantEntered(); +} + +async function newQuadrantEntered() { + gameState.sectorEnemiesCount = 0; + gameState.sectorStarbasesCount = 0; + gameState.sectorStarsCount = 0; + gameState.starbaseRepairDelay = 0.5 * Math.random(); + + // Add this sector to the known map + gameState.galacticMapDiscovered[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] = + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ]; + + // Initialize a sector enemy for each that had a chance to spawn + gameState.sectorEnemies = gameOptions.enemySpawnChance.map((c) => ({ + health: 0, + posY: 0, + posX: 0, + })); + + if ( + gameState.quadrantPositionY >= 1 && + gameState.quadrantPositionY <= gameOptions.galaxyHeight && + gameState.quadrantPositionX >= 1 && + gameState.quadrantPositionX <= gameOptions.galaxyWidth + ) { + let currentQuadrantName = buildQuadrantName( + gameState.quadrantPositionY, + gameState.quadrantPositionX + ); + print(); + if (gameOptions.stardateStart == gameState.stardateCurrent) { + print("YOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED"); + print(`IN THE GALACTIC QUADRANT, '${currentQuadrantName}'.`); + } else { + print(`NOW ENTERING ${currentQuadrantName} QUADRANT . . .`); + } + print(); + gameState.sectorEnemiesCount = Math.floor( + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] * 0.01 + ); + gameState.sectorStarbasesCount = + Math.floor( + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] * 0.1 + ) - + 10 * gameState.sectorEnemiesCount; + gameState.sectorStarsCount = + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] - + 100 * gameState.sectorEnemiesCount - + 10 * gameState.sectorStarbasesCount; + + if (gameState.sectorEnemiesCount != 0) { + print("COMBAT AREA CONDITION RED"); + if (gameState.shieldsCurrent <= 200) { + print(" SHIELDS DANGEROUSLY LOW"); + } + } + + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + gameState.sectorEnemies[enemyIdx].posY = 0; + gameState.sectorEnemies[enemyIdx].posX = 0; + } + } + + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + gameState.sectorEnemies[enemyIdx].health = 0; + } + + gameState.sectorMap = " ".repeat( + gameOptions.sectorMapSymbols.empty.length * + gameOptions.sectorHeight * + gameOptions.sectorWidth + ); + + insertInSectorMap( + gameOptions.sectorMapSymbols.hero, + gameState.sectorPositionY, + gameState.sectorPositionX + ); + + if (gameState.sectorEnemiesCount >= 1) { + // 1720 + for ( + let enemyIdx = 0; + enemyIdx < gameState.sectorEnemiesCount; + enemyIdx++ + ) { + const [posY, posX] = findSpaceInSectorMap(); + insertInSectorMap(gameOptions.sectorMapSymbols.enemy, posY, posX); + gameState.sectorEnemies[enemyIdx] = { + posY, + posX, + health: gameOptions.enemyMaxShield * (0.5 + Math.random()), + }; + } + } + + if (gameState.sectorStarbasesCount >= 1) { + const [R1, R2] = findSpaceInSectorMap(); + gameState.sectorStarbaseY = R1; + gameState.sectorStarbaseX = R2; + insertInSectorMap(gameOptions.sectorMapSymbols.base, R1, R2); + } + + for (let i = 1; i <= gameState.sectorStarsCount; i++) { + insertInSectorMap( + gameOptions.sectorMapSymbols.star, + ...findSpaceInSectorMap() + ); + } + + return shortRangeSensorScanAndStartup(); +} + +async function gameLoop() { + while (!gameState.gameOver) { + await acceptCommand(); + if (gameState.gameOver) { + await endOfGame(); + } + if (gameState.shouldRestart) { + await gameReset(); + } + } +} + +async function acceptCommand() { + if ( + gameState.shieldsCurrent + gameState.energyRemaining <= 10 || + (gameState.energyRemaining < 10 && + gameState.systemsDamage[SYSTEM_SHIELD_CONTROL] != 0) + ) { + print(); + print("** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP IN SPACE"); + print("YOU HAVE INSUFFICIENT MANEUVERING ENERGY, AND SHIELD CONTROL"); + print("IS PRESENTLY INCAPABLE OF CROSS-CIRCUITING TO ENGINE ROOM!!"); + print(); + gameState.gameOver = true; + return; + } + + const commandInput = (await input("COMMAND")).trim().toUpperCase(); + const command = COMMANDS[commandInput] || commandHelp; + await command(); +} + +/************************************************************************/ + +const COMMANDS = { + NAV: commandCourseControl, + SRS: shortRangeSensorScanAndStartup, + LRS: commandLongRangeScan, + PHA: commandPhaserControl, + TOR: commandPhotonTorpedo, + SHE: commandShieldControl, + DAM: commandDamageControl, + COM: commandLibraryComputer, + XXX: () => { + // todo more confirmation here? + gameState.gameOver = true; + gameState.gameQuit = true; + }, + DUMP: () => { + console.log(JSON.stringify(gameState)); + }, +}; + +async function commandHelp() { + print("ENTER ONE OF THE FOLLOWING:"); + print(" NAV (TO SET COURSE)"); + print(" SRS (FOR SHORT RANGE SENSOR SCAN)"); + print(" LRS (FOR LONG RANGE SENSOR SCAN)"); + print(" PHA (TO FIRE PHASERS)"); + print(" TOR (TO FIRE PHOTON TORPEDOES)"); + print(" SHE (TO RAISE OR LOWER SHIELDS)"); + print(" DAM (FOR DAMAGE CONTROL REPORTS)"); + print(" COM (TO CALL ON LIBRARY-COMPUTER)"); + print(" XXX (TO RESIGN YOUR COMMAND)"); + print(); +} + +async function shortRangeSensorScanAndStartup() { + checkIfDocked(); + + if (gameState.isDocked) { + gameState.alertCondition = "DOCKED"; + gameState.energyRemaining = gameOptions.energyMax; + gameState.photonTorpedoesRemaining = gameOptions.photonTorpedoesMax; + print("SHIELDS DROPPED FOR DOCKING PURPOSES"); + gameState.shieldsCurrent = 0; + } else { + gameState.alertCondition = "GREEN"; + if (gameState.energyRemaining < gameOptions.energyMax * 0.1) + gameState.alertCondition = "YELLOW"; + if (gameState.sectorEnemiesCount > 0) gameState.alertCondition = "RED"; + } + + if (gameState.systemsDamage[SYSTEM_SHORT_RANGE_SENSORS] < 0) { + print(); + print("*** SHORT RANGE SENSORS ARE OUT ***"); + print(); + return; + } + + const statusLines = [ + `STARDATE ${formatStardate(gameState.stardateCurrent)}`, + `CONDITION ${gameState.alertCondition}`, + `QUADRANT ${gameState.quadrantPositionY} , ${gameState.quadrantPositionX}`, + `SECTOR ${gameState.sectorPositionY} , ${gameState.sectorPositionX}`, + `PHOTON TORPEDOES ${gameState.photonTorpedoesRemaining}`, + `TOTAL ENERGY ${ + gameState.energyRemaining + gameState.shieldsCurrent + }`, + `SHIELDS ${gameState.shieldsCurrent}`, + `${gameOptions.nameEnemies} REMAINING ${gameState.enemiesRemaining}`, + ]; + + const lineSplit = new RegExp( + `.{${gameOptions.sectorMapSymbols.empty.length * gameOptions.sectorWidth}}`, + "g" + ); + const cellSplit = new RegExp( + `.{${gameOptions.sectorMapSymbols.empty.length}}`, + "g" + ); + const borderLine = "-".repeat( + (gameOptions.sectorMapSymbols.empty.length + 1) * gameOptions.sectorWidth + ); + print(borderLine); + print( + gameState.sectorMap + // Split the map into lines of 24 chars + .match(lineSplit) + // Split each line into cells of 3 chars + .map((line) => line.match(cellSplit)) + // Format each line with Y coord, spaced out cells, and a line of status + .map((line, idx) => line.join(" ") + " ".repeat(4) + statusLines[idx]) + // Finally, join all the lines with returns + .join("\n") + ); + print(borderLine); + print(); +} + +function checkIfDocked() { + const { sectorPositionY: sY, sectorPositionX: sX } = gameState; + for (let posY = sY - 1; posY <= sY + 1; posY++) { + for (let posX = sX - 1; posX <= sX + 1; posX++) { + if ( + posY >= 1 || + posY <= gameOptions.sectorHeight || + posX >= 1 || + posX <= gameOptions.sectorWidth + ) { + if (findInsectorMap(gameOptions.sectorMapSymbols.base, posY, posX)) { + gameState.isDocked = true; + return; + } + } + } + } + gameState.isDocked = false; +} + +async function commandCourseControl() { + let courseInput = parseFloat(await input("COURSE (0-9)")); + if (courseInput == 9) courseInput = 1; + if (isNaN(courseInput) || courseInput < 1 || courseInput > 9) { + print( + ` ${gameOptions.nameNavigationOfficer} REPORTS, 'INCORRECT COURSE DATA, SIR!'` + ); + return; + } + + const warpFactorInput = parseFloat( + await input( + `WARP FACTOR (0-${ + gameState.systemsDamage[SYSTEM_WARP_ENGINES] < 0 ? "0.2" : "8" + })` + ) + ); + if (warpFactorInput == 0 || isNaN(warpFactorInput)) return; + if ( + gameState.systemsDamage[SYSTEM_WARP_ENGINES] < 0 && + warpFactorInput > 0.2 + ) { + return print("WARP ENGINES ARE DAMAGED. MAXIMUM SPEED = WARP 0.2"); + } + if (warpFactorInput < 0 && warpFactorInput > 8) { + return print( + ` CHIEF ENGINEER ${gameOptions.nameChiefEngineer} REPORTS 'THE ENGINES WON'T TAKE WARP ${warpFactorInput}!'` + ); + } + + // FIXME: This seems to depend on square sectors - which we have, but could be changed in config + const sectorsToWarp = Math.floor(warpFactorInput * gameOptions.sectorWidth + 0.5); + + if (gameState.energyRemaining - sectorsToWarp < 0) { + print("ENGINEERING REPORTS 'INSUFFICIENT ENERGY AVAILABLE"); + print( + " FOR MANEUVERING AT WARP ", + warpFactorInput, + " !'" + ); + if ( + gameState.shieldsCurrent > sectorsToWarp - gameState.energyRemaining && + gameState.systemsDamage[SYSTEM_SHIELD_CONTROL] > 0 + ) { + print( + "DEFLECTOR CONTROL ROOM ACKNOWLEDGES ", + gameState.shieldsCurrent, + " UNITS OF ENERGY" + ); + print(" PRESENTLY DEPLOYED TO SHIELDS."); + } + } + + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + if (gameState.sectorEnemies[enemyIdx].health > 0) { + insertInSectorMap( + gameOptions.sectorMapSymbols.empty, + gameState.sectorEnemies[enemyIdx].posY, + gameState.sectorEnemies[enemyIdx].posX + ); + const [rY, rX] = findSpaceInSectorMap(); + gameState.sectorEnemies[enemyIdx].posY = rY; + gameState.sectorEnemies[enemyIdx].posX = rX; + insertInSectorMap( + gameOptions.sectorMapSymbols.enemy, + gameState.sectorEnemies[enemyIdx].posY, + gameState.sectorEnemies[enemyIdx].posX + ); + } + } + + enemiesShoot(); + + let damageControlHeaderPrinted = false; + const printDamageReport = (msg) => { + if (!damageControlHeaderPrinted) { + damageControlHeaderPrinted = true; + print("DAMAGE CONTROL REPORT:"); + } + print(msg); + }; + + let repairFactorDuringWarp = Math.min(1, warpFactorInput); + + // Continually repair damaged systems during warp + for (const systemName of gameOptions.shipSystems) { + if (gameState.systemsDamage[systemName] >= 0) continue; + + gameState.systemsDamage[systemName] = + gameState.systemsDamage[systemName] + repairFactorDuringWarp; + + if ( + gameState.systemsDamage[systemName] > -0.1 && + gameState.systemsDamage[systemName] < 0 + ) { + gameState.systemsDamage[systemName] = -0.1; + continue; + } + + if (gameState.systemsDamage[systemName] < 0) continue; + + printDamageReport(` ${systemName} REPAIR COMPLETED.`); + } + + // 20% chance of a random system being damaged, repaired, or improved in warp + if (Math.random() < gameOptions.systemChanceAffectedInWarp) { + const systemIdx = randomInt(gameOptions.shipSystems.length); + const systemName = gameOptions.shipSystems[systemIdx]; + + if (Math.random() < gameOptions.systemChanceDamageInWarp) { + // 60% chance of random system damage + gameState.systemsDamage[systemName] = + gameState.systemsDamage[systemName] - (Math.random() * 5 + 1); + printDamageReport(` ${systemName} DAMAGED`); + } else { + // 40% chance of random system repair or improvement + gameState.systemsDamage[systemName] = + gameState.systemsDamage[systemName] + Math.random() * 3 + 1; + printDamageReport(` ${systemName} STATE OF REPAIR IMPROVED`); + } + print(); + } + + // 3060 REM BEGIN MOVING STARSHIP + insertInSectorMap( + gameOptions.sectorMapSymbols.empty, + Math.floor(gameState.sectorPositionY), + Math.floor(gameState.sectorPositionX) + ); + + const [courseDeltaY, courseDeltaX] = courseToDeltaXY(courseInput); + let currentSectorPositionY = gameState.sectorPositionY; + let currentSectorPositionX = gameState.sectorPositionX; + let currentQuadrantPosY = gameState.quadrantPositionY; + let currentQuadrantPosX = gameState.quadrantPositionX; + + for (let sectorsWarped = 1; sectorsWarped < sectorsToWarp; sectorsWarped++) { + gameState.sectorPositionY = gameState.sectorPositionY + courseDeltaY; + gameState.sectorPositionX = gameState.sectorPositionX + courseDeltaX; + + if ( + gameState.sectorPositionY < 1 || + gameState.sectorPositionY >= 9 || + gameState.sectorPositionX < 1 || + gameState.sectorPositionX >= 9 + ) { + // 3490 REM EXCEEDED QUADRANT LIMITS + currentSectorPositionY = + gameOptions.sectorHeight * gameState.quadrantPositionY + + currentSectorPositionY + + sectorsToWarp * courseDeltaY; + + currentSectorPositionX = + gameOptions.sectorWidth * gameState.quadrantPositionX + + currentSectorPositionX + + sectorsToWarp * courseDeltaX; + + gameState.quadrantPositionY = Math.floor(currentSectorPositionY / 8); + gameState.quadrantPositionX = Math.floor(currentSectorPositionX / 8); + + gameState.sectorPositionY = Math.floor( + currentSectorPositionY - gameState.quadrantPositionY * 8 + ); + gameState.sectorPositionX = Math.floor( + currentSectorPositionX - gameState.quadrantPositionX * 8 + ); + + if (gameState.sectorPositionY == 0) { + gameState.quadrantPositionY = gameState.quadrantPositionY - 1; + gameState.sectorPositionY = 8; + } + if (gameState.sectorPositionX == 0) { + gameState.quadrantPositionX = gameState.quadrantPositionX - 1; + gameState.sectorPositionX = 8; + } + + let galacticPerimeterHit = false; + if (gameState.quadrantPositionY < 1) { + galacticPerimeterHit = true; + gameState.quadrantPositionY = 1; + gameState.sectorPositionY = 1; + } + if (gameState.quadrantPositionY > 8) { + galacticPerimeterHit = true; + gameState.quadrantPositionY = 8; + gameState.sectorPositionY = 8; + } + if (gameState.quadrantPositionX < 1) { + galacticPerimeterHit = true; + gameState.quadrantPositionX = 1; + gameState.sectorPositionX = 1; + } + if (gameState.quadrantPositionX > 8) { + galacticPerimeterHit = true; + gameState.quadrantPositionX = 8; + gameState.sectorPositionX = 8; + } + + if (galacticPerimeterHit) { + print( + `${gameOptions.nameCommunicationsOfficer} REPORTS MESSAGE FROM STARFLEET COMMAND:` + ); + print(" 'PERMISSION TO ATTEMPT CROSSING OF GALACTIC PERIMETER"); + print(" IS HEREBY *DENIED*. SHUT DOWN YOUR ENGINES.'"); + print( + `CHIEF ENGINEER ${gameOptions.nameChiefEngineer} REPORTS 'WARP ENGINES SHUT DOWN` + ); + print( + ` AT SECTOR ${gameState.sectorPositionY} , ${gameState.sectorPositionX} OF QUADRANT ${gameState.quadrantPositionY} , ${gameState.quadrantPositionX}.'` + ); + + if (checkIfTimeExpired()) { + return; + } + } + + if ( + gameOptions.sectorHeight * gameState.quadrantPositionY + gameState.quadrantPositionX == + gameOptions.sectorHeight * currentQuadrantPosY + currentQuadrantPosX + ) { + break; + } + + gameState.stardateCurrent = gameState.stardateCurrent + 1; + consumeEnergyForWarp(sectorsToWarp); + return newQuadrantEntered(); + } + + if ( + !findInsectorMap( + gameOptions.sectorMapSymbols.empty, + gameState.sectorPositionY, + gameState.sectorPositionX + ) + ) { + // Undo this step of warp travel if the space isn't empty + gameState.sectorPositionY = Math.floor( + gameState.sectorPositionY - courseDeltaY + ); + gameState.sectorPositionX = Math.floor( + gameState.sectorPositionX - courseDeltaX + ); + print( + `WARP ENGINES SHUT DOWN AT SECTOR ${gameState.sectorPositionY} , ${gameState.sectorPositionX} DUE TO BAD NAVAGATION` + ); + break; + } + } + + gameState.sectorPositionY = Math.floor(gameState.sectorPositionY); + gameState.sectorPositionX = Math.floor(gameState.sectorPositionX); + + insertInSectorMap( + gameOptions.sectorMapSymbols.hero, + Math.floor(gameState.sectorPositionY), + Math.floor(gameState.sectorPositionX) + ); + + consumeEnergyForWarp(sectorsToWarp); + + let timeElapsedDuringWarp = 1; + if (warpFactorInput < 1) { + timeElapsedDuringWarp = 0.1 * Math.floor(10 * warpFactorInput); + } + + gameState.stardateCurrent = gameState.stardateCurrent + timeElapsedDuringWarp; + if (checkIfTimeExpired()) { + return; + } + + await shortRangeSensorScanAndStartup(); +} + +function checkIfTimeExpired() { + if ( + gameState.stardateCurrent > + gameOptions.stardateStart + gameOptions.timeLimit + ) { + gameState.gameOver = true; + } + return gameState.gameOver; +} + +function consumeEnergyForWarp(sectorsToWarp) { + // 3900 REM MANEUVER ENERGY S/R ** + gameState.energyRemaining = gameState.energyRemaining - sectorsToWarp - 10; + if (gameState.energyRemaining >= 0) { + return; + } + + print("SHIELD CONTROL SUPPLIES ENERGY TO COMPLETE THE MANEUVER."); + gameState.shieldsCurrent = + gameState.shieldsCurrent + gameState.energyRemaining; + gameState.energyRemaining = 0; + if (gameState.shieldsCurrent <= 0) { + gameState.shieldsCurrent = 0; + } +} + +async function commandLongRangeScan() { + // 3990 REM LONG RANGE SENSOR SCAN CODE + if (gameState.systemsDamage[SYSTEM_LONG_RANGE_SENSORS] < 0) { + print("LONG RANGE SENSORS ARE INOPERABLE"); + return; + } + + print( + "LONG RANGE SCAN FOR QUADRANT ", + gameState.quadrantPositionY, + " , ", + gameState.quadrantPositionX + ); + + const separatorLine = "-------------------"; + print(separatorLine); + + for ( + let posY = gameState.quadrantPositionY - 1; + posY <= gameState.quadrantPositionY + 1; + posY++ + ) { + // Scan a line of sectors + const lineSectors = [null, null, null]; + for ( + let posX = gameState.quadrantPositionX - 1; + posX <= gameState.quadrantPositionX + 1; + posX++ + ) { + if (posY > 0 && posY < 9 && posX > 0 && posX < 9) { + // Add the scanned cell to the current scan output + lineSectors[posX - gameState.quadrantPositionX + 1] = + gameState.galacticMap[posY][posX]; + // Add the scanned cell to the discovered map + gameState.galacticMapDiscovered[posY][posX] = + gameState.galacticMap[posY][posX]; + } + } + + // Print a formatted line of the scan - e.g. ": 004 : 205 : 004 :" + print( + ": " + + lineSectors + .map((sector) => + sector === null ? "***" : sector.toString().padStart(3, "0") + ) + .join(" : ") + + " :" + ); + + print(separatorLine); + } +} + +async function commandPhaserControl() { + // 4250 REM PHASER CONTROL CODE BEGINS HERE + if (gameState.systemsDamage[SYSTEM_PHASER_CONTROL] < 0) { + print("PHASERS INOPERATIVE"); + return; + } + + if (gameState.sectorEnemiesCount <= 0) { + print( + `SCIENCE OFFICER ${gameOptions.nameScienceOfficer} REPORTS 'SENSORS SHOW NO ENEMY SHIPS` + ); + print(" IN THIS QUADRANT'"); + return; + } + + if (gameState.systemsDamage[SYSTEM_LIBRARY_COMPUTER] < 0) { + print("COMPUTER FAILURE HAMPERS ACCURACY"); + } + + print( + "PHASERS LOCKED ON TARGET; ENERGY AVAILABLE = ", + gameState.energyRemaining, + " UNITS" + ); + let phaserUnitsToFire; + const continueCommandLoop = true; + while (continueCommandLoop) { + phaserUnitsToFire = parseFloat(await input("NUMBER OF UNITS TO FIRE")); + if (phaserUnitsToFire <= 0) return; + if (gameState.energyRemaining - phaserUnitsToFire >= 0) { + break; + } + print(`ENERGY AVAILABLE = ${gameState.energyRemaining} UNITS`); + } + + gameState.energyRemaining = gameState.energyRemaining - phaserUnitsToFire; + + // FIXED: in the original, this was shield system. Changed to phaser system. + if (gameState.systemsDamage[SYSTEM_PHASER_CONTROL] < 0) { + phaserUnitsToFire = phaserUnitsToFire * Math.random(); + } + + // Spread phaser fire between all enemies + let phaserUnitsPerEnemy = Math.floor( + phaserUnitsToFire / gameState.sectorEnemiesCount + ); + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + if (gameState.sectorEnemies[enemyIdx].health <= 0) { + // Skip dead enemies + continue; + } + print(); + + // Phaser damage falls off based on distance and a bit of chance + let phaserDamage = Math.floor( + (phaserUnitsPerEnemy / distanceFromEnemy(enemyIdx)) * (Math.random() + 2) + ); + if (phaserDamage <= 0.15 * gameState.sectorEnemies[enemyIdx].health) { + print( + "SENSORS SHOW NO DAMAGE TO ENEMY AT ", + gameState.sectorEnemies[enemyIdx].posY, + " , ", + gameState.sectorEnemies[enemyIdx].posX + ); + continue; + } + gameState.sectorEnemies[enemyIdx].health -= phaserDamage; + + print( + `${phaserDamage} UNIT HIT ON ${gameOptions.nameEnemy} AT SECTOR ${gameState.sectorEnemies[enemyIdx].posY} , ${gameState.sectorEnemies[enemyIdx].posX}` + ); + + if (gameState.sectorEnemies[enemyIdx].health > 0) { + print( + ` (SENSORS SHOW ${gameState.sectorEnemies[enemyIdx].health} UNITS REMAINING)` + ); + print(); + } else { + print(`*** ${gameOptions.nameEnemy} DESTROYED ***`); + print(); + gameState.sectorEnemiesCount = gameState.sectorEnemiesCount - 1; + gameState.enemiesRemaining = gameState.enemiesRemaining - 1; + + // Remove enemy from display + insertInSectorMap( + gameOptions.sectorMapSymbols.empty, + gameState.sectorEnemies[enemyIdx].posY, + gameState.sectorEnemies[enemyIdx].posX + ); + + // Set enemy health at exactly zero + gameState.sectorEnemies[enemyIdx].health = 0; + + // Update the galactic map with one fewer enemy + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] -= 100; + + // Copy updated galactic map sector to discovered map. + gameState.galacticMapDiscovered[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] = + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ]; + + if (gameState.enemiesRemaining <= 0) { + // If that was the last enemy, we've won! + gameState.gameOver = true; + gameState.gameWon = true; + return; + } + } + } + + enemiesShoot(); +} + +async function commandPhotonTorpedo() { + // 4690 REM PHOTON TORPEDO CODE BEGINS HERE + // 4700 + if (gameState.photonTorpedoesRemaining <= 0) { + return print("ALL PHOTON TORPEDOES EXPENDED"); + } + if (gameState.systemsDamage[SYSTEM_PHOTON_TUBES] < 0) { + return print("PHOTON TUBES ARE NOT OPERATIONAL"); + } + + let torpedoCourse = parseFloat(await input("PHOTON TORPEDO COURSE (1-9)")); + if (torpedoCourse == 9) torpedoCourse = 1; + + if (torpedoCourse < 1 || torpedoCourse > 9) { + print( + `${gameOptions.nameWeaponsOfficer} REPORTS, 'INCORRECT COURSE DATA, SIR!'` + ); + } + + const [courseDeltaY, courseDeltaX] = courseToDeltaXY(torpedoCourse); + + gameState.energyRemaining = gameState.energyRemaining - 2; + gameState.photonTorpedoesRemaining = gameState.photonTorpedoesRemaining - 1; + let currPosY = gameState.sectorPositionY; + let currPosX = gameState.sectorPositionX; + + print("TORPEDO TRACK:"); + + // Fly the torpedo along its course... + let quantizedPosY, quantizedPosX; + const forever = true; + while (forever) { + currPosY = currPosY + courseDeltaY; + currPosX = currPosX + courseDeltaX; + + // The course will move in decimals, quantize to whole numbers + quantizedPosY = Math.floor(currPosY + 0.5); + quantizedPosX = Math.floor(currPosX + 0.5); + + // Exiting the sector means the torpedo missed + if ( + quantizedPosY < 1 || + quantizedPosY > gameOptions.sectorHeight || + quantizedPosX < 1 || + quantizedPosX > gameOptions.sectorWidth + ) { + print("TORPEDO MISSED"); + return enemiesShoot(); + } + + print(` ${quantizedPosY} , ${quantizedPosX}`); + + if ( + !findInsectorMap( + gameOptions.sectorMapSymbols.empty, + quantizedPosY, + quantizedPosX + ) + ) { + // Torpedo hit something solid, so stop flying. + break; + } + } + + // Did the torpedo hit an enemy? + if ( + findInsectorMap( + gameOptions.sectorMapSymbols.enemy, + quantizedPosY, + quantizedPosX + ) + ) { + print(`*** ${gameOptions.nameEnemy} DESTROYED ***`); + gameState.sectorEnemiesCount = gameState.sectorEnemiesCount - 1; + gameState.enemiesRemaining = gameState.enemiesRemaining - 1; + + if (gameState.enemiesRemaining <= 0) { + // If that was the last enemy, then we've won! + gameState.gameOver = true; + gameState.gameWon = true; + return; + } + + // Find which enemy was hit and set health to zero + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + if ( + quantizedPosY == gameState.sectorEnemies[enemyIdx].posY && + quantizedPosX == gameState.sectorEnemies[enemyIdx].posX + ) { + gameState.sectorEnemies[enemyIdx].health = 0; + break; + } + } + } + + // Did the torpedo hit a star? + if ( + findInsectorMap( + gameOptions.sectorMapSymbols.star, + quantizedPosY, + quantizedPosX + ) + ) { + print( + `STAR AT ${quantizedPosY} , ${quantizedPosX} ABSORBED TORPEDO ENERGY.` + ); + return enemiesShoot(); + } + + // Did the torpedo hit a starbase? + if ( + findInsectorMap( + gameOptions.sectorMapSymbols.base, + quantizedPosY, + quantizedPosX + ) + ) { + print("*** STARBASE DESTROYED ***"); + gameState.sectorStarbasesCount = gameState.sectorStarbasesCount - 1; + gameState.starbasesRemaining = gameState.starbasesRemaining - 1; + if ( + gameState.starbasesRemaining <= 0 || + gameState.enemiesRemaining <= + gameState.stardateCurrent - + gameOptions.stardateStart - + gameOptions.timeLimit + ) { + print("THAT DOES IT, CAPTAIN!! YOU ARE HEREBY RELIEVED OF COMMAND"); + print("AND SENTENCED TO 99 STARDATES AT HARD LABOR ON CYGNUS 12!!"); + gameState.gameOver = true; + return; + } else { + print("STARFLEET COMMAND REVIEWING YOUR RECORD TO CONSIDER"); + print("COURT MARTIAL!"); + gameState.isDocked = false; + } + } + + // If we hit an enemy or a starbase, update the sector and galaxy map to + // remove the thing destroyed + insertInSectorMap( + gameOptions.sectorMapSymbols.empty, + quantizedPosY, + quantizedPosX + ); + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] = + gameState.sectorEnemiesCount * 100 + + gameState.sectorStarbasesCount * 10 + + gameState.sectorStarsCount; + gameState.galacticMapDiscovered[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ] = + gameState.galacticMap[gameState.quadrantPositionY][ + gameState.quadrantPositionX + ]; + + return enemiesShoot(); +} + +async function enemiesShoot() { + if (gameState.sectorEnemiesCount <= 0) { + return; + } + + if (gameState.isDocked) { + print("STARBASE SHIELDS PROTECT THE ENTERPRISE"); + return; + } + + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + if (gameState.sectorEnemies[enemyIdx].health <= 0) { + continue; + } + + // Enemy damage based on health with drop-off for distance and chance + const enemyWeaponDamage = Math.floor( + (gameState.sectorEnemies[enemyIdx].health / distanceFromEnemy(enemyIdx)) * + (2 + Math.random()) + ); + gameState.shieldsCurrent = gameState.shieldsCurrent - enemyWeaponDamage; + + // Consume enemy health for firing weapon + gameState.sectorEnemies[enemyIdx].health = Math.floor( + gameState.sectorEnemies[enemyIdx].health / (3 + Math.random()) + ); + + print( + `${enemyWeaponDamage} UNIT HIT ON ENTERPRISE FROM SECTOR ${gameState.sectorEnemies[enemyIdx].posY} , ${gameState.sectorEnemies[enemyIdx].posX}` + ); + + if (gameState.shieldsCurrent <= 0) { + // If we're out of shields, we're out of luck + gameState.gameOver = true; + gameState.destroyed = true; + return; + } + + print(` `); + if (enemyWeaponDamage < 20) { + continue; + } + + // Systems damage with 60% chance or a hit of more than 2% of shields + if ( + Math.random() > gameOptions.systemDamageChanceOnHit || + enemyWeaponDamage / gameState.shieldsCurrent <= + gameOptions.systemDamageHitThroughShields + ) { + continue; + } + + // Random system damaged proportional to enemy damage and current shields + const systemIdx = randomInt(gameOptions.shipSystems.length); + const systemName = gameOptions.shipSystems[systemIdx]; + gameState.systemsDamage[systemName] = + gameState.systemsDamage[systemName] - + enemyWeaponDamage / gameState.shieldsCurrent - + 0.5 * Math.random(); + + print(`DAMAGE CONTROL REPORTS ${systemName} DAMAGED BY THE HIT`); + } +} + +async function commandShieldControl() { + // 5520 REM SHIELD CONTROL + if (gameState.systemsDamage[SYSTEM_SHIELD_CONTROL] < 0) { + print("SHIELD CONTROL INOPERABLE"); + return; + } + + print( + "ENERGY AVAILABLE = ", + gameState.energyRemaining + gameState.shieldsCurrent + ); + const shieldUnits = parseFloat(await input("NUMBER OF UNITS TO SHIELDS")); + if (shieldUnits < 0 || gameState.shieldsCurrent == shieldUnits) { + print(""); + return; + } + if (shieldUnits > gameState.energyRemaining + gameState.shieldsCurrent) { + print("SHIELD CONTROL REPORTS 'THIS IS NOT THE FEDERATION TREASURY.'"); + print(""); + return; + } + + gameState.energyRemaining = + gameState.energyRemaining + gameState.shieldsCurrent - shieldUnits; + gameState.shieldsCurrent = shieldUnits; + + print("DEFLECTOR CONTROL ROOM REPORT:"); + print( + ` 'SHIELDS NOW AT ${Math.floor( + gameState.shieldsCurrent + )} UNITS PER YOUR COMMAND.` + ); +} + +async function commandDamageControl() { + // 5680 REM DAMAGE CONTROL + // 5690 + // FIXME: Seems like damage control should work while docked? + if (gameState.systemsDamage[SYSTEM_DAMAGE_CONTROL] < 0) { + print("DAMAGE CONTROL REPORT NOT AVAILABLE"); + return; + } + + // 5910 + print(); + print("DEVICE STATE OF REPAIR"); + for (const systemName of gameOptions.shipSystems) { + print( + systemName.padEnd(25, " "), + Math.floor(gameState.systemsDamage[systemName] * 100) * 0.01 + ); + } + print(); + + if (gameState.isDocked) { + let repairTimeEstimate = 0; + for (const systemName of gameOptions.shipSystems) { + if (gameState.systemsDamage[systemName] < 0) { + repairTimeEstimate = repairTimeEstimate + 0.1; + } + } + if (repairTimeEstimate == 0) { + return; + } + print(); + repairTimeEstimate = repairTimeEstimate + gameState.starbaseRepairDelay; + if (repairTimeEstimate >= 1) { + repairTimeEstimate = 0.9; + } + print("TECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;"); + print( + `ESTIMATED TIME TO REPAIR: ${ + 0.01 * Math.floor(100 * repairTimeEstimate) + } STARDATES` + ); + const authorizeRepairInput = await input( + "WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N)" + ); + if (authorizeRepairInput.toUpperCase() != "Y") { + return; + } + for (const systemName of gameOptions.shipSystems) { + gameState.systemsDamage[systemName] = 0; + } + gameState.stardateCurrent = + gameState.stardateCurrent + repairTimeEstimate + 0.1; + } +} + +async function commandLibraryComputer() { + // 7280 REM LIBRARY COMPUTER CODE + // 7290 + if (gameState.systemsDamage[SYSTEM_LIBRARY_COMPUTER] < 0) { + print("COMPUTER DISABLED"); + return; + } + const commandInput = parseInt( + await input("COMPUTER ACTIVE AND AWAITING COMMAND") + ); + if (commandInput < 0) return; + const command = COMMANDS_COMPUTER[commandInput] || computerHelp; + print(); + await command(); +} + +const COMMANDS_COMPUTER = [ + computerCumulativeRecord, + computerStatusReport, + computerPhotonData, + computerStarbaseData, + computerDirectionData, + computerGalaxyMap, +]; + +async function computerHelp() { + print("FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:"); + print(" 0 = CUMULATIVE GALACTIC RECORD"); + print(" 1 = STATUS REPORT"); + print(" 2 = PHOTON TORPEDO DATA"); + print(" 3 = STARBASE NAV DATA"); + print(" 4 = DIRECTION/DISTANCE CALCULATOR"); + print(" 5 = GALAXY 'REGION NAME' MAP"); + print(); +} + +async function computerPhotonData() { + if (gameState.sectorEnemiesCount <= 0) { + print( + `SCIENCE OFFICER ${gameOptions.nameScienceOfficer} REPORTS 'SENSORS SHOW NO ENEMY SHIPS` + ); + print(" IN THIS QUADRANT'"); + return; + } + + print( + `FROM ENTERPRISE TO ${gameOptions.nameEnemy} BATTLE CRUISER${ + gameState.sectorEnemiesCount > 1 ? "S" : "" + }` + ); + + for ( + let enemyIdx = 0; + enemyIdx < gameOptions.enemySpawnChance.length; + enemyIdx++ + ) { + if (gameState.sectorEnemies[enemyIdx].health <= 0) continue; + computerDirectionCommon({ + fromY: gameState.sectorPositionY, + fromX: gameState.sectorPositionX, + toY: gameState.sectorEnemies[enemyIdx].posY, + toX: gameState.sectorEnemies[enemyIdx].posX, + }); + } +} + +async function computerStarbaseData() { + if (gameState.sectorStarbasesCount == 0) { + print( + `MR. ${gameOptions.nameScienceOfficer} REPORTS, 'SENSORS SHOW NO STARBASES IN THIS QUADRANT.'` + ); + return; + } + print("FROM ENTERPRISE TO STARBASE:"); + computerDirectionCommon({ + fromY: gameState.sectorPositionY, + fromX: gameState.sectorPositionX, + toY: gameState.sectorStarbaseY, + toX: gameState.sectorStarbaseX, + }); +} + +const inputCoords = async (prompt) => + (await input(prompt)).split(",").map((s) => parseInt(s.trim())); + +async function computerDirectionData() { + print("DIRECTION/DISTANCE CALCULATOR:"); + print( + `YOU ARE AT QUADRANT ${gameState.quadrantPositionY} , ${gameState.quadrantPositionX} SECTOR ${gameState.sectorPositionY} , ${gameState.sectorPositionX}` + ); + print("PLEASE ENTER"); + const [fromY, fromX] = await inputCoords(" INITIAL COORDINATES (Y,X)"); + const [toY, toX] = await inputCoords(" FINAL COORDINATES (Y,X)"); + computerDirectionCommon({ fromX, fromY, toX, toY }); +} + +async function computerDirectionCommon({ fromX, fromY, toX, toY }) { + const distance = Math.sqrt( + Math.pow(toX - fromX, 2) + Math.pow(toY - fromY, 2) + ); + const direction = + 1 + + (8 / (Math.PI * 2)) * + ((Math.atan2(0 - fromY - (0 - toY), fromX - toX) + Math.PI) % + (Math.PI * 2)); + + print(`DIRECTION = ${direction}`); + print(`DISTANCE = ${distance}`); +} + +async function computerStatusReport() { + print("STATUS REPORT:"); + print(); + print( + `${ + gameState.enemiesRemaining > 1 + ? gameOptions.nameEnemies + : gameOptions.nameEnemy + } LEFT: ${gameState.enemiesRemaining}` + ); + print( + `MISSION MUST BE COMPLETED IN ${ + 0.1 * + Math.floor( + (gameOptions.stardateStart + + gameOptions.timeLimit - + gameState.stardateCurrent) * + 10 + ) + } STARDATES` + ); + if (gameState.starbasesRemaining < 1) { + print("YOUR STUPIDITY HAS LEFT YOU ON YOUR ON IN"); + print(" THE GALAXY -- YOU HAVE NO STARBASES LEFT!"); + } else { + print( + `THE FEDERATION IS MAINTAINING ${gameState.starbasesRemaining} STARBASE${ + gameState.starbasesRemaining < 2 ? "" : "S" + } IN THE GALAXY` + ); + } + commandDamageControl(); +} + +async function computerGalaxyMap() { + print(" THE GALAXY"); + computerCommonMap(false); +} + +async function computerCumulativeRecord() { + print(); + print( + ` COMPUTER RECORD OF GALAXY FOR QUADRANT ${gameState.quadrantPositionY} , ${gameState.quadrantPositionX}` + ); + print(); + computerCommonMap(); +} + +async function computerCommonMap(showMapCells = true) { + // Print the X column number header based on width of first galaxy row + print( + " " + + gameState.galacticMap[1] + .map((_, idx) => idx.toString().padStart(3, " ")) + .join(" ") + ); + + // Assemble X column separator based on width of first galaxy row + const separator = + " " + gameState.galacticMap[1].map((_, idx) => "----- ").join(""); + + print(separator); + for (let mapY = 1; mapY <= gameOptions.galaxyHeight; mapY++) { + let out = mapY.toString().padStart(3, " "); + + if (showMapCells) { + // 7630 + for (let mapX = 1; mapX <= gameOptions.galaxyWidth; mapX++) { + out += ` ${ + gameState.galacticMapDiscovered[mapY][mapX] == 0 + ? "***" + : ("" + gameState.galacticMapDiscovered[mapY][mapX]).padStart( + 3, + "0" + ) + }`; + } + } else { + let quadrantName = buildQuadrantName(mapY, 1, true); + let centerSpacing = Math.floor(12 - 0.5 * quadrantName.length); + out += ` ${" ".repeat(centerSpacing)}${quadrantName}${" ".repeat( + centerSpacing + )}`; + quadrantName = buildQuadrantName(mapY, 5, true); + centerSpacing = Math.floor(12 - 0.5 * quadrantName.length); + out += `${" ".repeat(centerSpacing)}${quadrantName}`; + } + + print(out); + print(separator); + } +} + +async function endOfGame() { + if (gameState.destroyed) { + print(); + print( + "THE ENTERPRISE HAS BEEN DESTROYED. THEN FEDERATION WILL BE CONQUERED" + ); + } + + print(`IT IS STARDATE ${formatStardate(gameState.stardateCurrent)}`); + + if (!gameState.gameWon) { + print( + `THERE WERE ${gameState.enemiesRemaining} ${gameOptions.nameEnemy} BATTLE CRUISERS LEFT AT` + ); + print("THE END OF YOUR MISSION."); + } else { + print( + `CONGRULATION, CAPTAIN! THEN LAST ${gameOptions.nameEnemy} BATTLE CRUISER` + ); + print("MENACING THE FEDERATION HAS BEEN DESTROYED."); + print(); + print( + "YOUR EFFICIENCY RATING IS ", + (1000 * + (gameState.enemiesInitialCount / + (gameState.stardateCurrent - gameOptions.stardateStart))) ^ + 2 + ); + } + + print(); + print(); + + if (gameState.starbasesRemaining > 0) { + print("THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER"); + print("FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,"); + const playAgainInput = await input("LET HIM STEP FORWARD AND ENTER 'AYE'"); + if (playAgainInput.toUpperCase() == "AYE") { + gameState.shouldRestart = true; + return; + } + } +} + +const COURSE_TO_XY = [ + [0, 1], + [-1, 1], + [-1, 0], + [-1, -1], + [0, -1], + [1, -1], + [1, 0], + [1, 1], + [0, 1], +]; + +function courseToDeltaXY(course) { + const courseIdx = Math.floor(course) - 1; + //3110 X1=C(C1,1)+(C(C1+1,1)-C(C1,1))*(C1-INT(C1)):X=S1:Y=S2 + //3140 X2=C(C1,2)+(C(C1+1,2)-C(C1,2))*(C1-INT(C1)):Q4=Q1:Q5=Q2 + const courseDeltaY = + COURSE_TO_XY[courseIdx][0] + + (COURSE_TO_XY[courseIdx + 1][0] - COURSE_TO_XY[courseIdx][0]) * + (course - Math.floor(course)); + const courseDeltaX = + COURSE_TO_XY[courseIdx][1] + + (COURSE_TO_XY[courseIdx + 1][1] - COURSE_TO_XY[courseIdx][1]) * + (course - Math.floor(course)); + return [courseDeltaY, courseDeltaX]; +} + +function findSpaceInSectorMap() { + let posY, + posX, + foundEmptyPlace = false; + while (!foundEmptyPlace) { + posY = randomInt(8, 1); + posX = randomInt(8, 1); + foundEmptyPlace = findInsectorMap( + gameOptions.sectorMapSymbols.empty, + posY, + posX + ); + } + return [posY, posX]; +} + +function findInsectorMap(str, y, x) { + const idx = (x - 1) * 3 + (y - 1) * 24; + return gameState.sectorMap.substring(idx, idx + 3) == str; +} + +// 8660 REM INSERT IN STRING ARRAY FOR QUADRANT +function insertInSectorMap(str, y, x) { + // 8670 + const strPos = (x - 1) * 3 + (y - 1) * 24; + if (str.length != 3) { + throw "ERROR"; + } + gameState.sectorMap = + gameState.sectorMap.slice(0, strPos) + + str + + gameState.sectorMap.slice(strPos + 3); +} + +function buildQuadrantName(y, x, regionNameOnly = false) { + const xIdx = x - 1; + const yIdx = y - 1; + const name = gameOptions.quadrantNames[xIdx < 4 ? 0 : 1][yIdx]; + return `${name}${ + regionNameOnly ? "" : ` ${gameOptions.quadrantNumbers[xIdx % 4]}` + }`; +} + +const randomInt = (max, min = 0) => + Math.floor(min + Math.random() * (max - min)); + +const formatStardate = (stardate) => Math.floor(stardate * 10) / 10; + +const distanceFromEnemy = (sectorEnemyIndex) => + Math.sqrt( + Math.pow( + gameState.sectorEnemies[sectorEnemyIndex].posY - + gameState.sectorPositionY, + 2 + ) + + Math.pow( + gameState.sectorEnemies[sectorEnemyIndex].posX - + gameState.sectorPositionX, + 2 + ) + ); From b422db3f4a12a7904b55474a2d7843c3cdd69673 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 11 Mar 2021 07:20:28 +1100 Subject: [PATCH 282/749] Add Library-Computer --- 84 Super Star Trek/csharp/Game.cs | 17 +++-- 84 Super Star Trek/csharp/Input.cs | 47 ++++++++++++++ 84 Super Star Trek/csharp/Objects/Klingon.cs | 10 +-- 84 Super Star Trek/csharp/Objects/Starbase.cs | 5 +- 84 Super Star Trek/csharp/Program.cs | 1 + .../csharp/Resources/ComputerFunctions.txt | 9 +++ .../csharp/Resources/NoEnemyShips.txt | 2 + .../csharp/Resources/NoStarbase.txt | 1 + .../csharp/Resources/RegionNames.txt | 16 ++--- .../csharp/Resources/Strings.cs | 3 + 84 Super Star Trek/csharp/Space/Coordinate.cs | 12 ++-- 84 Super Star Trek/csharp/Space/Galaxy.cs | 1 + 84 Super Star Trek/csharp/Space/Quadrant.cs | 25 ++++--- .../csharp/Space/QuadrantInfo.cs | 7 +- 84 Super Star Trek/csharp/StringExtensions.cs | 7 ++ .../ComputerFunctions/ComputerFunction.cs | 18 +++++ .../CumulativeGalacticRecord.cs | 21 ++++++ .../DirectionDistanceCalculator.cs | 32 +++++++++ .../ComputerFunctions/GalacticReport.cs | 34 ++++++++++ .../ComputerFunctions/GalaxyRegionMap.cs | 21 ++++++ .../ComputerFunctions/NavigationCalculator.cs | 29 +++++++++ .../StarbaseDataCalculator.cs | 30 +++++++++ .../Systems/ComputerFunctions/StatusReport.cs | 41 ++++++++++++ .../TorpedoDataCalculator.cs | 33 ++++++++++ .../csharp/Systems/DamageControl.cs | 3 +- .../csharp/Systems/LibraryComputer.cs | 47 ++++++++++++++ .../csharp/Utils/DirectionAndDistance.cs | 65 +++++++++++++++++++ 27 files changed, 503 insertions(+), 34 deletions(-) create mode 100644 84 Super Star Trek/csharp/Resources/ComputerFunctions.txt create mode 100644 84 Super Star Trek/csharp/Resources/NoEnemyShips.txt create mode 100644 84 Super Star Trek/csharp/Resources/NoStarbase.txt create mode 100644 84 Super Star Trek/csharp/StringExtensions.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs create mode 100644 84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs create mode 100644 84 Super Star Trek/csharp/Systems/LibraryComputer.cs create mode 100644 84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index 0d5539ba..e32f15c8 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -3,6 +3,7 @@ using SuperStarTrek.Objects; using SuperStarTrek.Resources; using SuperStarTrek.Space; using SuperStarTrek.Systems; +using SuperStarTrek.Systems.ComputerFunctions; using static System.StringComparison; namespace SuperStarTrek @@ -16,7 +17,6 @@ namespace SuperStarTrek private int _finalStarDate; private float _currentStardate; private Coordinates _currentQuadrant; - private Coordinates _currentSector; private Galaxy _galaxy; private int _initialKlingonCount; private Enterprise _enterprise; @@ -28,6 +28,7 @@ namespace SuperStarTrek } public float Stardate => _currentStardate; + public float StardatesRemaining => _finalStarDate - _currentStardate; public void DoIntroduction() { @@ -74,7 +75,6 @@ namespace SuperStarTrek _finalStarDate = _initialStardate + random.GetInt(25, 35); _currentQuadrant = random.GetCoordinate(); - _currentSector = random.GetCoordinate(); _galaxy = new Galaxy(); _initialKlingonCount = _galaxy.KlingonCount; @@ -85,7 +85,16 @@ namespace SuperStarTrek .Add(new LongRangeSensors(_galaxy, _output)) .Add(new PhotonTubes(10, _enterprise, _output, _input)) .Add(new ShieldControl(_enterprise, _output, _input)) - .Add(new DamageControl(_enterprise, _output)); + .Add(new DamageControl(_enterprise, _output)) + .Add(new LibraryComputer( + _output, + _input, + new CumulativeGalacticRecord(_output, _galaxy), + new StatusReport(this, _galaxy, _enterprise, _output), + new TorpedoDataCalculator(_enterprise, _output), + new StarbaseDataCalculator(_enterprise, _output), + new DirectionDistanceCalculator(_enterprise, _output, _input), + new GalaxyRegionMap(_output, _galaxy))); _output.Write(Strings.Enterprise); _output.Write( @@ -99,7 +108,7 @@ namespace SuperStarTrek _input.WaitForAnyKeyButEnter("when ready to accept command"); - var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy); + var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy, _input, _output); _enterprise.Enter(quadrant, Strings.StartText); } diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs index c632007f..af17f3c4 100644 --- a/84 Super Star Trek/csharp/Input.cs +++ b/84 Super Star Trek/csharp/Input.cs @@ -44,6 +44,13 @@ namespace SuperStarTrek } } + public (float X, float Y) GetCoordinates(string prompt) + { + _output.Prompt($"{prompt} (X,Y)"); + var responses = ReadNumbers(2); + return (responses[0], responses[1]); + } + public bool TryGetNumber(string prompt, float minValue, float maxValue, out float value) { value = GetNumber($"{prompt} ({minValue}-{maxValue})"); @@ -90,6 +97,46 @@ namespace SuperStarTrek }; } + private float[] ReadNumbers(int quantity) + { + var numbers = new float[quantity]; + var index = 0; + bool tryAgain; + + do + { + tryAgain = false; + var responses = Console.ReadLine().Split(','); + if (responses.Length > quantity) + { + _output.WriteLine("!Extra input ingored"); + } + + for (; index < responses.Length; index++) + { + if (!float.TryParse(responses[index], out numbers[index])) + { + _output.WriteLine("!Number expected - retry input line"); + _output.Prompt(); + tryAgain = true; + break; + } + } + } while (tryAgain); + + if (index < quantity) + { + _output.Prompt("?"); + var responses = ReadNumbers(quantity - index); + for (int i = 0; i < responses.Length; i++, index++) + { + numbers[index] = responses[i]; + } + } + + return numbers; + } + public enum YesNoMode { TrueOnY, diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs index 29584aec..f722fe06 100644 --- a/84 Super Star Trek/csharp/Objects/Klingon.cs +++ b/84 Super Star Trek/csharp/Objects/Klingon.cs @@ -6,25 +6,27 @@ namespace SuperStarTrek.Objects internal class Klingon { private float _energy; - private Coordinates _sector; private readonly Random _random; public Klingon(Coordinates sector, Random random) { - _sector = sector; + Sector = sector; _random = random; _energy = _random.GetFloat(100, 300); } + public Coordinates Sector { get; private set; } + public override string ToString() => "+K+"; public CommandResult FireOn(Enterprise enterprise) { var attackStrength = _random.GetFloat(); - var hitStrength = (int)(_energy * (2 + attackStrength) / _sector.GetDistanceTo(enterprise.Sector)); + var (_, distanceToEnterprise) = Sector.GetDirectionAndDistanceTo(enterprise.Sector); + var hitStrength = (int)(_energy * (2 + attackStrength) / distanceToEnterprise); _energy /= 3 + attackStrength; - return enterprise.TakeHit(_sector, hitStrength); + return enterprise.TakeHit(Sector, hitStrength); } } } diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs index 4d854efd..4befa73a 100644 --- a/84 Super Star Trek/csharp/Objects/Starbase.cs +++ b/84 Super Star Trek/csharp/Objects/Starbase.cs @@ -1,4 +1,5 @@ using SuperStarTrek.Resources; +using SuperStarTrek.Space; namespace SuperStarTrek.Objects { @@ -8,13 +9,15 @@ namespace SuperStarTrek.Objects private readonly Output _output; private readonly float _repairDelay; - public Starbase(Random random, Input input, Output output) + public Starbase(Coordinates sector, Random random, Input input, Output output) { + Sector = sector; _repairDelay = random.GetFloat() * 0.5f; _input = input; _output = output; } + internal Coordinates Sector { get; } public override string ToString() => ">!<"; internal bool TryRepair(Enterprise enterprise, out float repairTime) diff --git a/84 Super Star Trek/csharp/Program.cs b/84 Super Star Trek/csharp/Program.cs index 30360ee0..7f8395a6 100644 --- a/84 Super Star Trek/csharp/Program.cs +++ b/84 Super Star Trek/csharp/Program.cs @@ -29,6 +29,7 @@ namespace SuperStarTrek { static void Main() { + var foo = Utils.DirectionAndDistance.From(1,1).To(4,5); var game = new Game(); game.DoIntroduction(); diff --git a/84 Super Star Trek/csharp/Resources/ComputerFunctions.txt b/84 Super Star Trek/csharp/Resources/ComputerFunctions.txt new file mode 100644 index 00000000..4827b0fe --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/ComputerFunctions.txt @@ -0,0 +1,9 @@ + +Functions available from Library-Computer: + 0 = Cumulative galactic record + 1 = Status report + 2 = Photon torpedo data + 3 = Starbase nav data + 4 = Direction/distance calculator + 5 = Galaxy 'region name' map + diff --git a/84 Super Star Trek/csharp/Resources/NoEnemyShips.txt b/84 Super Star Trek/csharp/Resources/NoEnemyShips.txt new file mode 100644 index 00000000..394f1057 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/NoEnemyShips.txt @@ -0,0 +1,2 @@ +Science Officer Spock reports, 'Sensors show no enemy ships + in this quadrant' \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/NoStarbase.txt b/84 Super Star Trek/csharp/Resources/NoStarbase.txt new file mode 100644 index 00000000..5bb4e5fb --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/NoStarbase.txt @@ -0,0 +1 @@ +Mr. Spock reports, 'Sensors show no starbases in this quadrant.' \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/RegionNames.txt b/84 Super Star Trek/csharp/Resources/RegionNames.txt index e2f47d79..f84fe43b 100644 --- a/84 Super Star Trek/csharp/Resources/RegionNames.txt +++ b/84 Super Star Trek/csharp/Resources/RegionNames.txt @@ -1,8 +1,8 @@ -Antares Sirius -Rigel Deneb -Procyon Capella -Vega Betelgeuse -Canopus Aldebaran -Altair Regulus -Sagittarius Arcturus -Pollux Spica \ No newline at end of file + Antares Sirius + Rigel Deneb + Procyon Capella + Vega Betelgeuse + Canopus Aldebaran + Altair Regulus + Sagittarius Arcturus + Pollux Spica \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index c76fe691..7b315545 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -7,6 +7,7 @@ namespace SuperStarTrek.Resources internal static class Strings { public static string CombatArea => GetResource(); + public static string ComputerFunctions => GetResource(); public static string Congratulations => GetResource(); public static string CourtMartial => GetResource(); public static string Destroyed => GetResource(); @@ -14,6 +15,8 @@ namespace SuperStarTrek.Resources public static string Enterprise => GetResource(); public static string Instructions => GetResource(); public static string LowShields => GetResource(); + public static string NoEnemyShips => GetResource(); + public static string NoStarbase => GetResource(); public static string Orders => GetResource(); public static string Protected => GetResource(); public static string RegionNames => GetResource(); diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinate.cs index b103a528..b8660d52 100644 --- a/84 Super Star Trek/csharp/Space/Coordinate.cs +++ b/84 Super Star Trek/csharp/Space/Coordinate.cs @@ -1,4 +1,5 @@ using System; +using SuperStarTrek.Utils; namespace SuperStarTrek.Space { @@ -10,12 +11,15 @@ namespace SuperStarTrek.Space { X = Validated(x, nameof(x)); Y = Validated(y, nameof(y)); + + RegionIndex = (X << 1) + (Y >> 2); + SubRegionIndex = Y % 4; } public int X { get; } public int Y { get; } - public int RegionIndex => (X << 1) + (Y >> 2); - public int SubRegionIndex => Y % 4; + public int RegionIndex { get; } + public int SubRegionIndex { get; } private int Validated(int value, string argumentName) { @@ -51,7 +55,7 @@ namespace SuperStarTrek.Space int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero); } - internal float GetDistanceTo(Coordinates destination) => - (float)Math.Sqrt(Math.Pow(X - destination.X, 2) + Math.Pow(Y - destination.Y, 2)); + internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) => + DirectionAndDistance.From(this).To(destination); } } diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 0392b335..38382754 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -48,6 +48,7 @@ namespace SuperStarTrek.Space public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount); public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase); + public IEnumerable> Quadrants => _quadrants; private static string GetQuadrantName(Coordinates coordinates) => $"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}"; diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index d89d60e0..efcaadb2 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -13,10 +13,15 @@ namespace SuperStarTrek.Space private readonly Random _random; private readonly Dictionary _sectors; private readonly Enterprise _enterprise; - private readonly Coordinates _starbaseSector; private readonly Galaxy _galaxy; - public Quadrant(QuadrantInfo info, Enterprise enterprise, Random random, Galaxy galaxy) + public Quadrant( + QuadrantInfo info, + Enterprise enterprise, + Random random, + Galaxy galaxy, + Input input, + Output output) { _info = info; _random = random; @@ -26,30 +31,30 @@ namespace SuperStarTrek.Space PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount); if (_info.HasStarbase) { - _starbaseSector = PositionObject(_ => new Starbase(_random, new Input(new Output()), new Output())); + Starbase = PositionObject(sector => new Starbase(sector, _random, input, output)); } PositionObject(_ => new Star(), _info.StarCount); } - public object this[Coordinates coordinates] => _sectors.GetValueOrDefault(coordinates); public Coordinates Coordinates => _info.Coordinates; public bool HasKlingons => _info.KlingonCount > 0; + public int KlingonCount => _info.KlingonCount; public bool HasStarbase => _info.HasStarbase; - public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null; + public Starbase Starbase { get; } public bool EnterpriseIsNextToStarbase => _info.HasStarbase && - Math.Abs(_enterprise.Sector.X - _starbaseSector.X) <= 1 && - Math.Abs(_enterprise.Sector.Y - _starbaseSector.Y) <= 1; + Math.Abs(_enterprise.Sector.X - Starbase.Sector.X) <= 1 && + Math.Abs(_enterprise.Sector.Y - Starbase.Sector.Y) <= 1; - private IEnumerable Klingons => _sectors.Values.OfType(); + internal IEnumerable Klingons => _sectors.Values.OfType(); public override string ToString() => _info.Name; - private Coordinates PositionObject(Func objectFactory) + private T PositionObject(Func objectFactory) { var sector = GetRandomEmptySector(); _sectors[sector] = objectFactory.Invoke(sector); - return sector; + return (T)_sectors[sector]; } private void PositionObject(Func objectFactory, int count) diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs index 04780a27..8b4357db 100644 --- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs +++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs @@ -41,8 +41,11 @@ namespace SuperStarTrek.Space internal void AddStarbase() => HasStarbase = true; - internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy) => - new(this, enterprise, random, galaxy); + internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy, Input input, Output output) + { + _isKnown = true; + return new(this, enterprise, random, galaxy, input, output); + } internal string Scan() { diff --git a/84 Super Star Trek/csharp/StringExtensions.cs b/84 Super Star Trek/csharp/StringExtensions.cs new file mode 100644 index 00000000..02e9794f --- /dev/null +++ b/84 Super Star Trek/csharp/StringExtensions.cs @@ -0,0 +1,7 @@ +namespace SuperStarTrek +{ + internal static class StringExtensions + { + internal static string Pluralize(this string singular, int quantity) => singular + (quantity > 1 ? "s" : ""); + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs new file mode 100644 index 00000000..400c1f62 --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs @@ -0,0 +1,18 @@ +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal abstract class ComputerFunction + { + protected ComputerFunction(string description, Output output) + { + Description = description; + Output = output; + } + + internal string Description { get; } + protected Output Output { get; } + + internal abstract void Execute(Quadrant quadrant); + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs new file mode 100644 index 00000000..f02677ca --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal class CumulativeGalacticRecord : GalacticReport + { + internal CumulativeGalacticRecord(Output output, Galaxy galaxy) + : base("Cumulative galactic record", output, galaxy) + { + } + + protected override void WriteHeader(Quadrant quadrant) => + Output.NextLine().WriteLine($"Computer record of galaxy for quadrant {quadrant.Coordinates}").NextLine(); + + protected override IEnumerable GetRowData() => + Galaxy.Quadrants.Select(row => " " + string.Join(" ", row)); + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs new file mode 100644 index 00000000..c8b195f4 --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SuperStarTrek.Objects; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal class DirectionDistanceCalculator : NavigationCalculator + { + private readonly Enterprise _enterprise; + private readonly Input _input; + + public DirectionDistanceCalculator(Enterprise enterprise, Output output, Input input) + : base("Starbase nav data", output) + { + _enterprise = enterprise; + _input = input; + } + + internal override void Execute(Quadrant quadrant) + { + Output.WriteLine("Direction/distance calculator:") + .WriteLine($"You are at quadrant {_enterprise.Quadrant} sector {_enterprise.Sector}") + .WriteLine("Please enter"); + + WriteDirectionAndDistance( + _input.GetCoordinates(" Initial coordinates"), + _input.GetCoordinates(" Final coordinates")); + } + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs new file mode 100644 index 00000000..8b26cc2e --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal abstract class GalacticReport : ComputerFunction + { + public GalacticReport(string description, Output output, Galaxy galaxy) + : base(description, output) + { + Galaxy = galaxy; + } + + protected Galaxy Galaxy { get; } + + protected abstract void WriteHeader(Quadrant quadrant); + + protected abstract IEnumerable GetRowData(); + + internal sealed override void Execute(Quadrant quadrant) + { + WriteHeader(quadrant); + Output.WriteLine(" 1 2 3 4 5 6 7 8") + .WriteLine(" ----- ----- ----- ----- ----- ----- ----- -----"); + + foreach (var (row, index) in GetRowData().Select((r, i) => (r, i))) + { + Output.WriteLine($" {index+1} {row}") + .WriteLine(" ----- ----- ----- ----- ----- ----- ----- -----"); + } + } + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs new file mode 100644 index 00000000..f6fe0305 --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Linq; +using SuperStarTrek.Resources; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal class GalaxyRegionMap : GalacticReport + { + internal GalaxyRegionMap(Output output, Galaxy galaxy) + : base("Galaxy 'region name' map", output, galaxy) + { + } + + protected override void WriteHeader(Quadrant quadrant) => + Output.WriteLine(" The Galaxy"); + + protected override IEnumerable GetRowData() => + Strings.RegionNames.Split('\n').Select(n => n.TrimEnd('\r')); + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs new file mode 100644 index 00000000..680f3d18 --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs @@ -0,0 +1,29 @@ +using SuperStarTrek.Space; +using SuperStarTrek.Utils; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal abstract class NavigationCalculator : ComputerFunction + { + protected NavigationCalculator(string description, Output output) + : base(description, output) + { + } + + protected void WriteDirectionAndDistance(Coordinates from, Coordinates to) + { + var (direction, distance) = from.GetDirectionAndDistanceTo(to); + Write(direction, distance); + } + + protected void WriteDirectionAndDistance((float X, float Y) from, (float X, float Y) to) + { + var (direction, distance) = DirectionAndDistance.From(from.X, from.Y).To(to.X, to.Y); + Write(direction, distance); + } + + private void Write(float direction, float distance) => + Output.WriteLine($"Direction = {direction}") + .WriteLine($"Distance = {distance}"); + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs new file mode 100644 index 00000000..b81a353d --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs @@ -0,0 +1,30 @@ +using SuperStarTrek.Objects; +using SuperStarTrek.Resources; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal class StarbaseDataCalculator : NavigationCalculator + { + private readonly Enterprise _enterprise; + + public StarbaseDataCalculator(Enterprise enterprise, Output output) + : base("Starbase nav data", output) + { + _enterprise = enterprise; + } + + internal override void Execute(Quadrant quadrant) + { + if (!quadrant.HasStarbase) + { + Output.WriteLine(Strings.NoStarbase); + return; + } + + Output.WriteLine("From Enterprise to Starbase:"); + + WriteDirectionAndDistance(_enterprise.Sector, quadrant.Starbase.Sector); + } + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs new file mode 100644 index 00000000..f80ba7bb --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs @@ -0,0 +1,41 @@ +using SuperStarTrek.Commands; +using SuperStarTrek.Objects; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal class StatusReport : ComputerFunction + { + private readonly Game _game; + private readonly Galaxy _galaxy; + private readonly Enterprise _enterprise; + + public StatusReport(Game game, Galaxy galaxy, Enterprise enterprise, Output output) + : base("Status report", output) + { + _game = game; + _galaxy = galaxy; + _enterprise = enterprise; + } + + internal override void Execute(Quadrant quadrant) + { + Output.WriteLine(" Status report:") + .Write("Klingon".Pluralize(_galaxy.KlingonCount)).WriteLine($" left: {_galaxy.KlingonCount}") + .WriteLine($"Mission must be completed in {_game.StardatesRemaining:0.#} stardates."); + + if (_galaxy.StarbaseCount > 0) + { + Output.Write($"The Federation is maintaining {_galaxy.StarbaseCount} ") + .Write("starbase".Pluralize(_galaxy.StarbaseCount)).WriteLine(" in the galaxy."); + } + else + { + Output.WriteLine("Your stupidity has left you on your own in") + .WriteLine(" the galaxy -- you have no starbases left!"); + } + + _enterprise.Execute(Command.DAM); + } + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs new file mode 100644 index 00000000..6afa7b8c --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs @@ -0,0 +1,33 @@ +using SuperStarTrek.Objects; +using SuperStarTrek.Resources; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems.ComputerFunctions +{ + internal class TorpedoDataCalculator : NavigationCalculator + { + private readonly Enterprise _enterprise; + + public TorpedoDataCalculator(Enterprise enterprise, Output output) + : base("Photon torpedo data", output) + { + _enterprise = enterprise; + } + + internal override void Execute(Quadrant quadrant) + { + if (!quadrant.HasKlingons) + { + Output.WriteLine(Strings.NoEnemyShips); + return; + } + + Output.WriteLine("From Enterprise to Klingon battle cruiser".Pluralize(quadrant.KlingonCount)); + + foreach (var klingon in quadrant.Klingons) + { + WriteDirectionAndDistance(_enterprise.Sector, klingon.Sector); + } + } + } +} \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84 Super Star Trek/csharp/Systems/DamageControl.cs index 25f5ad78..6ce41bbe 100644 --- a/84 Super Star Trek/csharp/Systems/DamageControl.cs +++ b/84 Super Star Trek/csharp/Systems/DamageControl.cs @@ -24,6 +24,7 @@ namespace SuperStarTrek.Systems } else { + _output.NextLine(); WriteDamageReport(); } @@ -41,7 +42,7 @@ namespace SuperStarTrek.Systems public void WriteDamageReport() { - _output.NextLine().NextLine().WriteLine("Device State of Repair"); + _output.NextLine().WriteLine("Device State of Repair"); foreach (var system in _enterprise.Systems) { _output.Write(system.Name.PadRight(25)) diff --git a/84 Super Star Trek/csharp/Systems/LibraryComputer.cs b/84 Super Star Trek/csharp/Systems/LibraryComputer.cs new file mode 100644 index 00000000..b2e47d2a --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/LibraryComputer.cs @@ -0,0 +1,47 @@ +using SuperStarTrek.Commands; +using SuperStarTrek.Space; +using SuperStarTrek.Systems.ComputerFunctions; + +namespace SuperStarTrek.Systems +{ + internal class LibraryComputer : Subsystem + { + private readonly Output _output; + private readonly Input _input; + private readonly ComputerFunction[] _functions; + + public LibraryComputer(Output output, Input input, params ComputerFunction[] functions) + : base("Library-Computer", Command.COM, output) + { + _output = output; + _input = input; + _functions = functions; + } + + protected override bool CanExecuteCommand() => IsOperational("Computer disabled"); + + protected override CommandResult ExecuteCommandCore(Quadrant quadrant) + { + var index = GetFunctionIndex(); + _output.NextLine(); + + _functions[index].Execute(quadrant); + + return CommandResult.Ok; + } + + private int GetFunctionIndex() + { + while (true) + { + var index = (int)_input.GetNumber("Computer active and waiting command"); + if (index >= 0 && index <= 5) { return index; } + + for (int i = 0; i < _functions.Length; i++) + { + _output.WriteLine($" {i} = {_functions[i].Description}"); + } + } + } + } +} diff --git a/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs b/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs new file mode 100644 index 00000000..3fa9f4b8 --- /dev/null +++ b/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs @@ -0,0 +1,65 @@ +using System; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Utils +{ + internal class DirectionAndDistance + { + private readonly float _fromX; + private readonly float _fromY; + + private DirectionAndDistance(float fromX, float fromY) + { + _fromX = fromX; + _fromY = fromY; + } + + public static DirectionAndDistance From(Coordinates coordinates) => From(coordinates.X, coordinates.Y); + + public static DirectionAndDistance From(float x, float y) => new DirectionAndDistance(x, y); + + public (float Direction, float Distance) To(Coordinates coordinates) => To(coordinates.X, coordinates.Y); + + public (float Direction, float Distance) To(float x, float y) + { + var deltaX = x - _fromX; + var deltaY = y - _fromY; + + return (GetDirection(deltaX, deltaY), GetDistance(deltaX, deltaY)); + } + + // The algorithm here is mathematically equivalent to the following code in the original, + // where X is deltaY and A is deltaX + // 8220 X=X-A:A=C1-W1:IFX<0THEN8350 + // 8250 IFA<0THEN8410 + // 8260 IFX>0THEN8280 + // 8270 IFA=0THENC1=5:GOTO8290 + // 8280 C1=1 + // 8290 IFABS(A)<=ABS(X)THEN8330 + // 8310 PRINT"DIRECTION =";C1+(((ABS(A)-ABS(X))+ABS(A))/ABS(A)):GOTO8460 + // 8330 PRINT"DIRECTION =";C1+(ABS(A)/ABS(X)):GOTO8460 + // 8350 IFA>0THENC1=3:GOTO8420 + // 8360 IFX<>0THENC1=5:GOTO8290 + // 8410 C1=7 + // 8420 IFABS(A)>=ABS(X)THEN8450 + // 8430 PRINT"DIRECTION =";C1+(((ABS(X)-ABS(A))+ABS(X))/ABS(X)):GOTO8460 + // 8450 PRINT"DIRECTION =";C1+(ABS(X)/ABS(A)) + // 8460 PRINT"DISTANCE =";SQR(X^2+A^2):IFH8=1THEN1990 + private float GetDirection(float deltaX, float deltaY) + { + var deltaXDominant = Math.Abs(deltaX) > Math.Abs(deltaY); + var fractionalPart = deltaXDominant ? deltaY / deltaX : -deltaX / deltaY; + var nearestCardinal = deltaXDominant switch + { + true => deltaX > 0 ? 7 : 3, + false => deltaY > 0 ? 1 : 5 + }; + + var direction = nearestCardinal + fractionalPart; + return direction < 1 ? direction + 8 : direction; + } + + private float GetDistance(float deltaX, float deltaY) => + (float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2)); + } +} \ No newline at end of file From 4b352db8ef72e1c8e76204639c8b43995b9e7ca3 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 11 Mar 2021 12:13:02 +1100 Subject: [PATCH 283/749] Add Phaser Control --- 84 Super Star Trek/csharp/Game.cs | 1 + .../csharp/Objects/Enterprise.cs | 1 + 84 Super Star Trek/csharp/Objects/Klingon.cs | 18 +++- 84 Super Star Trek/csharp/Space/Coordinate.cs | 6 ++ 84 Super Star Trek/csharp/Space/Quadrant.cs | 13 ++- .../csharp/Systems/PhaserControl.cs | 95 +++++++++++++++++++ 6 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 84 Super Star Trek/csharp/Systems/PhaserControl.cs diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index e32f15c8..de3c2c4c 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -83,6 +83,7 @@ namespace SuperStarTrek _enterprise .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) .Add(new LongRangeSensors(_galaxy, _output)) + .Add(new PhaserControl(_enterprise, _output, _input, random)) .Add(new PhotonTubes(10, _enterprise, _output, _input)) .Add(new ShieldControl(_enterprise, _output, _input)) .Add(new DamageControl(_enterprise, _output)) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index ed11bb1e..d87a3aec 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -32,6 +32,7 @@ namespace SuperStarTrek.Objects public Coordinates Quadrant => _quadrant.Coordinates; public Coordinates Sector { get; } public string Condition => GetCondition(); + public LibraryComputer Computer => (LibraryComputer)_commandExecutors[Command.COM]; public ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE]; public float Energy => TotalEnergy - ShieldControl.ShieldEnergy; public float TotalEnergy { get; private set; } diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs index f722fe06..d16c6792 100644 --- a/84 Super Star Trek/csharp/Objects/Klingon.cs +++ b/84 Super Star Trek/csharp/Objects/Klingon.cs @@ -5,16 +5,16 @@ namespace SuperStarTrek.Objects { internal class Klingon { - private float _energy; private readonly Random _random; public Klingon(Coordinates sector, Random random) { Sector = sector; _random = random; - _energy = _random.GetFloat(100, 300); + Energy = _random.GetFloat(100, 300); } + public float Energy { get; private set; } public Coordinates Sector { get; private set; } public override string ToString() => "+K+"; @@ -22,11 +22,19 @@ namespace SuperStarTrek.Objects public CommandResult FireOn(Enterprise enterprise) { var attackStrength = _random.GetFloat(); - var (_, distanceToEnterprise) = Sector.GetDirectionAndDistanceTo(enterprise.Sector); - var hitStrength = (int)(_energy * (2 + attackStrength) / distanceToEnterprise); - _energy /= 3 + attackStrength; + var distanceToEnterprise = Sector.GetDistanceTo(enterprise.Sector); + var hitStrength = (int)(Energy * (2 + attackStrength) / distanceToEnterprise); + Energy /= 3 + attackStrength; return enterprise.TakeHit(Sector, hitStrength); } + + internal bool TakeHit(int hitStrength) + { + if (hitStrength < 0.15 * Energy) { return false; } + + Energy -= hitStrength; + return true; + } } } diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinate.cs index b8660d52..759ca45e 100644 --- a/84 Super Star Trek/csharp/Space/Coordinate.cs +++ b/84 Super Star Trek/csharp/Space/Coordinate.cs @@ -57,5 +57,11 @@ namespace SuperStarTrek.Space internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) => DirectionAndDistance.From(this).To(destination); + + internal float GetDistanceTo(Coordinates destination) + { + var (_, distance) = GetDirectionAndDistanceTo(destination); + return distance; + } } } diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index efcaadb2..8d9d0556 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -72,10 +72,8 @@ namespace SuperStarTrek.Space switch (_sectors.GetValueOrDefault(coordinates)) { - case Klingon _: - _sectors.Remove(coordinates); - _info.RemoveKlingon(); - message = "*** Klingon destroyed ***"; + case Klingon klingon: + message = Remove(klingon); gameOver = _galaxy.KlingonCount == 0; return true; @@ -96,6 +94,13 @@ namespace SuperStarTrek.Space } } + internal string Remove(Klingon klingon) + { + _sectors.Remove(klingon.Sector); + _info.RemoveKlingon(); + return "*** Klingon destroyed ***"; + } + internal CommandResult KlingonsFireOnEnterprise() { if (EnterpriseIsNextToStarbase && Klingons.Any()) diff --git a/84 Super Star Trek/csharp/Systems/PhaserControl.cs b/84 Super Star Trek/csharp/Systems/PhaserControl.cs new file mode 100644 index 00000000..48da4ace --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/PhaserControl.cs @@ -0,0 +1,95 @@ +using System.Linq; +using SuperStarTrek.Commands; +using SuperStarTrek.Objects; +using SuperStarTrek.Resources; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems +{ + internal class PhaserControl : Subsystem + { + private readonly Enterprise _enterprise; + private readonly Output _output; + private readonly Input _input; + private readonly Random _random; + + public PhaserControl(Enterprise enterprise, Output output, Input input, Random random) + : base("Phaser Control", Command.PHA, output) + { + _enterprise = enterprise; + _output = output; + _input = input; + _random = random; + } + + protected override bool CanExecuteCommand() => IsOperational("Phasers inoperative"); + + protected override CommandResult ExecuteCommandCore(Quadrant quadrant) + { + if (!quadrant.HasKlingons) + { + _output.WriteLine(Strings.NoEnemyShips); + return CommandResult.Ok; + } + + if (_enterprise.Computer.IsDamaged) + { + _output.WriteLine("Computer failure hampers accuracy"); + } + + _output.Write($"Phasers locked on target; "); + + var phaserStrength = GetPhaserStrength(); + if (phaserStrength < 0) { return CommandResult.Ok; } + + var perEnemyStrength = GetPerTargetPhaserStrength(phaserStrength, quadrant.KlingonCount); + + foreach (var klingon in quadrant.Klingons.ToList()) + { + ResolveHitOn(klingon, perEnemyStrength, quadrant); + } + + return quadrant.KlingonsFireOnEnterprise(); + } + + private float GetPhaserStrength() + { + while (true) + { + _output.WriteLine($"Energy available = {_enterprise.Energy} units"); + var phaserStrength = _input.GetNumber("Number of units to fire"); + + if (phaserStrength <= _enterprise.Energy) { return phaserStrength; } + } + } + + private float GetPerTargetPhaserStrength(float phaserStrength, int targetCount) + { + if (_enterprise.Computer.IsDamaged) + { + phaserStrength *= _random.GetFloat(); + } + + return phaserStrength / targetCount; + } + + private void ResolveHitOn(Klingon klingon, float perEnemyStrength, Quadrant quadrant) + { + var distance = _enterprise.Sector.GetDistanceTo(klingon.Sector); + var hitStrength = (int)(perEnemyStrength / distance * (2 + _random.GetFloat())); + + if (klingon.TakeHit(hitStrength)) + { + _output.WriteLine($"{hitStrength} unit hit on Klingon at sector {klingon.Sector}"); + _output.WriteLine( + klingon.Energy <= 0 + ? quadrant.Remove(klingon) + : $" (sensors show {klingon.Energy} units remaining)"); + } + else + { + _output.WriteLine($"Sensors show no damage to enemy at {klingon.Sector}"); + } + } + } +} From a6558c9f25fe31907f138f3126b1cd4b2e770757 Mon Sep 17 00:00:00 2001 From: NezumiRonin Date: Wed, 10 Mar 2021 23:09:31 -0600 Subject: [PATCH 284/749] Create diamond.pl Ported to Perl! --- 32 Diamond/perl/diamond.pl | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 32 Diamond/perl/diamond.pl diff --git a/32 Diamond/perl/diamond.pl b/32 Diamond/perl/diamond.pl new file mode 100644 index 00000000..62311c14 --- /dev/null +++ b/32 Diamond/perl/diamond.pl @@ -0,0 +1,37 @@ +#!/usr/bin/perl +use strict; + +################ +# PORTING NOTES: +# * In basic "Tab" function are not spaces, but absolute col position on screen. +# * It was too dificult to port this one, couldn't figure out the original algorithm. +# * So the algorithm was remake. +# + +print ' 'x 33 . "DIAMOND\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +print "FOR A PRETTY DIAMOND PATTERN,\n"; +print "TYPE IN AN ODD NUMBER BETWEEN 5 AND 21? "; chomp(my $R = ); print "\n"; + + +my $Wid= int(60/$R)+1; +my $Dia="CC". "!" x ($R-2); + +for (my $J=1; $J<$Wid; $J++) { + for (my $K=1; $K<($R+2)*2-4; $K+=2) { + my $Size= $K; + if ($K>$R) { $Size=$R+($R-$K); } + my $Chunk= substr($Dia, 0, $Size); + for (my $L=1; $L<$Wid; $L++) { + my $Space= " " x (($R-$Size)/2); + if ($L>1) { $Space.=$Space; } + print $Space.$Chunk; + } + print "\n"; + } + } + +exit; + + From 1e41a764a33f6bce63432bc8a05fc54f261720dd Mon Sep 17 00:00:00 2001 From: nanochess Date: Fri, 12 Mar 2021 16:56:05 -0600 Subject: [PATCH 285/749] Ported KING to Javascript --- 53 King/javascript/king.html | 9 + 53 King/javascript/king.js | 376 +++++++++++++++++++++++++++++++++++ 2 files changed, 385 insertions(+) create mode 100644 53 King/javascript/king.html create mode 100644 53 King/javascript/king.js diff --git a/53 King/javascript/king.html b/53 King/javascript/king.html new file mode 100644 index 00000000..56b5e7e2 --- /dev/null +++ b/53 King/javascript/king.html @@ -0,0 +1,9 @@ + + +KING + + +

+
+
+
diff --git a/53 King/javascript/king.js b/53 King/javascript/king.js
new file mode 100644
index 00000000..faaeb253
--- /dev/null
+++ b/53 King/javascript/king.js	
@@ -0,0 +1,376 @@
+// KING
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+function hate_your_guts()
+{
+    print("\n");
+    print("\n");
+    print("OVER ONE THIRD OF THE POPULATION HAS DIED SINCE YOU\n");
+    print("WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING)\n");
+    print("HATE YOUR GUTS.\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "KING\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("DO YOU WANT INSTRUCTIONS");
+    str = await input();
+    n5 = 8;
+    if (str == "AGAIN") {
+        while (1) {
+            print("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED");
+            x5 = parseInt(await input());
+            if (x5 == 0)
+                return;
+            if (x5 < 8)
+                break;
+            print("   COME ON, YOUR TERM IN OFFICE IS ONLY " + n5 + " YEARS.\n");
+        }
+        print("HOW MUCH DID YOU HAVE IN THE TREASURY");
+        a = parseInt(await input());
+        if (a < 0)
+            return;
+        print("HOW MANY COUNTRYMEN");
+        b = parseInt(await input());
+        if (b < 0)
+            return;
+        print("HOW MANY WORKERS");
+        c = parseInt(await input());
+        if (c < 0)
+            return;
+        while (1) {
+            print("HOW MANY SQUARE MILES OF LAND");
+            d = parseInt(await input());
+            if (d < 0)
+                return;
+            if (d > 1000 && d <= 2000)
+                break;
+            print("   COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND\n");
+            print("   AND 10,000 SQ. MILES OF FOREST LAND.\n");
+        }
+    } else {
+        if (str.substr(0, 1) != "N") {
+            print("\n");
+            print("\n");
+            print("\n");
+            print("CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS\n");
+            print("DETINU, A SMALL COMMUNIST ISLAND 30 BY 70 MILES LONG. YOUR\n");
+            print("JOB IS TO DECIDE UPON THE CONTRY'S BUDGET AND DISTRIBUTE\n");
+            print("MONEY TO YOUR COUNTRYMEN FROM THE COMMUNAL TREASURY.\n");
+            print("THE MONEY SYSTEM IS RALLODS, AND EACH PERSON NEEDS 100\n");
+            print("RALLODS PER YEAR TO SURVIVE. YOUR COUNTRY'S INCOME COMES\n");
+            print("FROM FARM PRODUCE AND TOURISTS VISITING YOUR MAGNIFICENT\n");
+            print("FORESTS, HUNTING, FISHING, ETC. HALF YOUR LAND IS FARM LAND\n");
+            print("WHICH ALSO HAS AN EXCELLENT MINERAL CONTENT AND MAY BE SOLD\n");
+            print("TO FOREIGN INDUSTRY (STRIP MINING) WHO IMPORT AND SUPPORT\n");
+            print("THEIR OWN WORKERS. CROPS COST BETWEEN 10 AND 15 RALLODS PER\n");
+            print("SQUARE MILE TO PLANT.\n");
+            print("YOUR GOAL IS TO COMPLETE YOUR " + n5 + " YEAR TERM OF OFFICE.\n");
+            print("GOOD LUCK!\n");
+        }
+        print("\n");
+        a = Math.floor(60000 + (1000 * Math.random()) - (1000 * Math.random()));
+        b = Math.floor(500 + (10 * Math.random()) - (10 * Math.random()));
+        c = 0;
+        d = 2000;
+        x5 = 0;
+    }
+    v3 = 0;
+    b5 = 0;
+    x = false;
+    while (1) {
+        w = Math.floor(10 * Math.random() + 95);
+        print("\n");
+        print("YOU NOW HAVE " + a + " RALLODS IN THE TREASURY.\n");
+        print(b + " COUNTRYMEN, ");
+        v9 = Math.floor(((Math.random() / 2) * 10 + 10));
+        if (c != 0)
+            print(c + " FOREIGN WORKERS, ");
+        print("AND " + Math.floor(d) + " SQ. MILES OF LAND.\n");
+        print("THIS YEAR INDUSTRY WILL BUY LAND FOR " + w + " ");
+        print("RALLODS PER SQUARE MILE.\n");
+        print("LAND CURRENTLY COSTS " + v9 + " RALLODS PER SQUARE MILE TO PLANT.\n");
+        print("\n");
+        while (1) {
+            print("HOW MANY SQUARE MILES DO YOU WISH TO SELL TO INDUSTRY");
+            h = parseInt(await input());
+            if (h < 0)
+                continue;
+            if (h <= d - 1000)
+                break;
+            print("***  THINK AGAIN. YOU ONLY HAVE " + (d - 1000) + " SQUARE MILES OF FARM LAND.\n");
+            if (x == false) {
+                print("\n");
+                print("(FOREIGN INDUSTRY WILL ONLY BUY FARM LAND BECAUSE\n");
+                print("FOREST LAND IS UNECONOMICAL TO STRIP MINE DUE TO TREES,\n");
+                print("THICKER TOP SOIL, ETC.)\n");
+                x = true;
+            }
+        }
+        d = Math.floor(d - h);
+        a = Math.floor(a + (h * w));
+        while (1) {
+            print("HOW MANY RALLODS WILL YOU DISTRIBUTE AMONG YOUR COUNTRYMEN");
+            i = parseInt(await input());
+            if (i < 0)
+                continue;
+            if (i < a)
+                break;
+            if (i == a) {
+                j = 0;
+                k = 0;
+                a = 0;
+                break;
+            }
+            print("   THINK AGAIN. YOU'VE ONLY " + a + " RALLODS IN THE TREASURY\n");
+        }
+        if (a) {
+            a = Math.floor(a - i);
+            while (1) {
+                print("HOW MANY SQUARE MILES DO YOU WISH TO PLANT");
+                j = parseInt(await input());
+                if (j < 0)
+                    continue;
+                if (j <= b * 2) {
+                    if (j <= d - 1000) {
+                        u1 = Math.floor(j * v9);
+                        if (u1 > a) {
+                            print("   THINK AGAIN. YOU'VE ONLY " + a + " RALLODS LEFT IN THE TREASURY.\n");
+                            continue;
+                        } else if (u1 == a) {
+                            k = 0;
+                            a = 0;
+                        }
+                        break;
+                    }
+                    print("   SORRY, BUT YOU'VE ONLY " + (d - 1000) + " SQ. MILES OF FARM LAND.\n");
+                    continue;
+                }
+                print("   SORRY, BUT EACH COUNTRYMAN CAN ONLY PLANT 2 SQ. MILES.\n");
+            }
+        }
+        if (a) {
+            a -= u1;
+            while (1) {
+                print("HOW MANY RALLODS DO YOU WISH TO SPEND ON POLLUTION CONTROL");
+                k = parseInt(await input());
+                if (k < 0)
+                    continue;
+                if (k <= a)
+                    break;
+                print("   THINK AGAIN. YOU ONLY HAVE " + a + " RALLODS REMAINING.\n");
+            }
+        }
+        if (h == 0 && i == 0 && j == 0 && k == 0) {
+            print("GOODBYE.\n");
+            print("(IF YOU WISH TO CONTINUE THIS GAME AT A LATER DATE, ANSWER\n");
+            print("'AGAIN' WHEN ASKED IF YOU WANT INSTRUCTIONS AT THE START\n");
+            print("OF THE GAME).\n");
+            return;
+        }
+        print("\n");
+        print("\n");
+        a = Math.floor(a - k);
+        a4 = a;
+        if (Math.floor(i / 100 - b) < 0) {
+            if (i / 100 < 50) {
+                hate_your_guts();
+                break;
+            }
+            print(Math.floor(b - (i / 100)) + " COUNTRYMEN DIED OF STARVATION\n");
+        }
+        f1 = Math.floor(Math.random() * (2000 - d));
+        if (k >= 25)
+            f1 = Math.floor(f1 / (k / 25));
+        if (f1 > 0)
+            print(f1 + " COUNTRYMEN DIED OF CARBON-MONOXIDE AND DUST INHALATION\n");
+        funeral = false;
+        if (Math.floor((i / 100) - b) >= 0) {
+            if (f1 > 0) {
+                print("   YOU WERE FORCED TO SPEND " + Math.floor(f1 * 9) + " RALLODS ON ");
+                print("FUNERAL EXPENSES.\n");
+                b5 = f1;
+                a = Math.floor(a - (f1 * 9));
+                funeral = true;
+            }
+        } else {
+            print("   YOU WERE FORCED TO SPEND " + Math.floor((f1 + (b - (i / 100))) * 9));
+            print(" RALLODS ON FUNERAL EXPENSES.\n");
+            b5 = Math.floor(f1 + (b - (i / 100)));
+            a = Math.floor(a - ((f1 + (b - (i / 100))) * 9));
+            funeral = true;
+        }
+        if (funeral) {
+            if (a < 0) {
+                print("   INSUFFICIENT RESERVES TO COVER COST - LAND WAS SOLD\n");
+                d = Math.floor(d + (a / w));
+                a = 0;
+            }
+            b = Math.floor(b - b5);
+        }
+        c1 = 0;
+        if (h != 0) {
+            c1 = Math.floor(h + (Math.random() * 10) - (Math.random() * 20));
+            if (c <= 0)
+                c1 += 20;
+            print(c1 + " WORKERS CAME TO THE COUNTRY AND ");
+        }
+        p1 = Math.floor(((i / 100 - b) / 10) + (k / 25) - ((2000 - d) / 50) - (f1 / 2));
+        print(Math.abs(p1) + " COUNTRYMEN ");
+        if (p1 >= 0)
+            print("CAME TO");
+        else
+            print("LEFT");
+        print(" THE ISLAND.\n");
+        b = Math.floor(b + p1);
+        c = Math.floor(c + c1);
+        u2 = Math.floor(((2000 - d) * ((Math.random() + 1.5) / 2)));
+        if (c != 0) {
+            print("OF " + Math.floor(j) + " SQ. MILES PLANTED,");
+        }
+        if (j <= u2)
+            u2 = j;
+        print(" YOU HARVESTED " + Math.floor(j - u2) + " SQ. MILES OF CROPS.\n");
+        if (u2 != 0 && t1 < 2) {
+            print("   (DUE TO ");
+            if (t1 != 0)
+                print("INCREASED ");
+            print("AIR AND WATER POLLUTION FROM FOREIGN INDUSTRY.)\n");
+        }
+        q = Math.floor((j - u2) * (w / 2));
+        print("MAKING " + q + " RALLODS.\n");
+        a = Math.floor(a + q);
+        v1 = Math.floor(((b - p1) * 22) + (Math.random() * 500));
+        v2 = Math.floor((2000 - d) * 15);
+        print(" YOU MADE " + Math.abs(Math.floor(v1 - v2)) + " RALLODS FROM TOURIST TRADE.\n");
+        if (v2 != 0 && v1 - v2 < v3) {
+            print("   DECREASE BECAUSE ");
+            g1 = 10 * Math.random();
+            if (g1 <= 2)
+                print("FISH POPULATION HAS DWINDLED DUE TO WATER POLLUTION.\n");
+            else if (g1 <= 4)
+                print("AIR POLLUTION IS KILLING GAME BIRD POPULATION.\n");
+            else if (g1 <= 6)
+                print("MINERAL BATHS ARE BEING RUINED BY WATER POLLUTION.\n");
+            else if (g1 <= 8)
+                print("UNPLEASANT SMOG IS DISCOURAGING SUN BATHERS.\n");
+            else if (g1 <= 10)
+                print("HOTELS ARE LOOKING SHABBY DUE TO SMOG GRIT.\n");
+        }
+        v3 = Math.floor(a + v3);    // Probable bug from original game
+        a = Math.floor(a + v3);
+        if (b5 > 200) {
+            print("\n");
+            print("\n");
+            print(b5 + " COUNTRYMEN DIED IN ONE YEAR!!!!!\n");
+            print("DUE TO THIS EXTREME MISMANAGEMENT, YOU HAVE NOT ONLY\n");
+            print("BEEN IMPEACHED AND THROWN OUT OF OFFICE, BUT YOU\n");
+            m6 = Math.floor(Math.random() * 10);
+            if (m6 <= 3)
+                print("ALSO HAD YOUR LEFT EYE GOUGED OUT!\n");
+            else if (m6 <= 6)
+                print("HAVE ALSO GAINED A VERY BAD REPUTATION.\n");
+            else
+                print("HAVE ALSO BEEN DECLARED NATIONAL FINK.\n");
+            print("\n");
+            print("\n");
+            return;
+        }
+        if (b < 343) {
+            hate_your_guts();
+            break;
+        }
+        if (a4 / 100 > 5 && b5 - f1 >= 2) {
+            print("\n");
+            print("MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID\n");
+            print("NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED\n");
+            print("OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE\n");
+            print("BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE.\n");
+            print("THE CHOICE IS YOURS.\n");
+            print("IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER\n");
+            print("BEFORE PROCEEDING.\n");
+            print("\n");
+            print("\n");
+            return;
+        }
+        if (c > b) {
+            print("\n");
+            print("\n");
+            print("THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER\n");
+            print("OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND\n");
+            print("TAKEN OVER THE COUNTRY.\n");
+            break;
+        }
+        if (n5 - 1 == x5) {
+            print("\n");
+            print("\n");
+            print("CONGRATULATIONS!!!!!!!!!!!!!!!!!!\n");
+            print("YOU HAVE SUCCESFULLY COMPLETED YOUR " + n5 + " YEAR TERM\n");
+            print("OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT\n");
+            print("NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD\n");
+            print("LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT\n");
+            print("PLAYS THIS GAME.\n");
+            print("\n");
+            print("\n");
+            return;
+        }
+        x5++;
+        b5 = 0;
+    }
+    if (Math.random() <= 0.5) {
+        print("YOU HAVE BEEN ASSASSINATED.\n");
+    } else {
+        print("YOU HAVE BEEN THROWN OUT OF OFFICE AND ARE NOW\n");
+        print("RESIDING IN PRISON.\n");
+    }
+    print("\n");
+    print("\n");
+}
+
+main();

From bb8cfe9fb4a8ce53fa3ed8ed1727dbe64efc16c1 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Fri, 12 Mar 2021 21:35:46 -0600
Subject: [PATCH 286/749] Ported LEM to Javascript

---
 59 Lunar LEM Rocket/javascript/lem.html   |   9 +
 59 Lunar LEM Rocket/javascript/lem.js     | 326 +++++++++++++++++++
 59 Lunar LEM Rocket/javascript/lunar.html |   9 +
 59 Lunar LEM Rocket/javascript/lunar.js   | 376 ++++++++++++++++++++++
 4 files changed, 720 insertions(+)
 create mode 100644 59 Lunar LEM Rocket/javascript/lem.html
 create mode 100644 59 Lunar LEM Rocket/javascript/lem.js
 create mode 100644 59 Lunar LEM Rocket/javascript/lunar.html
 create mode 100644 59 Lunar LEM Rocket/javascript/lunar.js

diff --git a/59 Lunar LEM Rocket/javascript/lem.html b/59 Lunar LEM Rocket/javascript/lem.html
new file mode 100644
index 00000000..717ae005
--- /dev/null
+++ b/59 Lunar LEM Rocket/javascript/lem.html	
@@ -0,0 +1,9 @@
+
+
+LEM
+
+
+

+
+
+
diff --git a/59 Lunar LEM Rocket/javascript/lem.js b/59 Lunar LEM Rocket/javascript/lem.js
new file mode 100644
index 00000000..4f5ffd30
--- /dev/null
+++ b/59 Lunar LEM Rocket/javascript/lem.js	
@@ -0,0 +1,326 @@
+// LEM
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "LEM\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    // ROCKT2 is an interactive game that simulates a lunar
+    // landing is similar to that of the Apollo program.
+    // There is absolutely no chance involved
+    zs = "GO";
+    b1 = 1;
+    while (1) {
+        m = 17.95;
+        f1 = 5.25;
+        n = 7.5;
+        r0 = 926;
+        v0 = 1.29;
+        t = 0;
+        h0 = 60;
+        r = r0 + h0;
+        a = -3,425;
+        r1 = 0;
+        a1 = 8.84361e-4;
+        r3 = 0;
+        a3 = 0;
+        m1 = 7.45;
+        m0 = m1;
+        b = 750;
+        t1 = 0;
+        f = 0;
+        p = 0;
+        n = 1;
+        m2 = 0;
+        s = 0;
+        c = 0;
+        if (zs == "YES") {
+            print("\n");
+            print("OK, DO YOU WANT THE COMPLETE INSTRUCTIONS OR THE INPUT -\n");
+            print("OUTPUT STATEMENTS?\n");
+            while (1) {
+                print("1=COMPLETE INSTRUCTIONS\n");
+                print("2=INPUT-OUTPUT STATEMENTS\n");
+                print("3=NEITHER\n");
+                b1 = parseInt(await input());
+                qs = "NO";
+                if (b1 == 1)
+                    break;
+                qs = "YES";
+                if (b1 == 2 || b1 == 3)
+                    break;
+            }
+        } else {
+            print("\n");
+            print("LUNAR LANDING SIMULATION\n");
+            print("\n");
+            print("HAVE YOU FLOWN AN APOLLO/LEM MISSION BEFORE");
+            while (1) {
+                print(" (YES OR NO)");
+                qs = await input();
+                if (qs == "YES" || qs == "NO")
+                    break;
+                print("JUST ANSWER THE QUESTION, PLEASE, ");
+            }
+        }
+        if (qs == "YES") {
+            print("\n");
+            print("INPUT MEASUREMENT OPTION NUMBER");
+        } else {
+            print("\n");
+            print("WHICH SYSTEM OF MEASUREMENT DO YOU PREFER?\n");
+            print(" 1=METRIC     0=ENGLISH\n");
+            print("ENTER THE APPROPIATE NUMBER");
+        }
+        while (1) {
+            k = parseInt(await input());
+            if (k == 0 || k == 1)
+                break;
+            print("ENTER THE APPROPIATE NUMBER");
+        }
+        if (k == 1) {
+            z = 1852.8;
+            ms = "METERS";
+            g3 = 3.6;
+            ns = " KILOMETERS";
+            g5 = 1000;
+        } else {
+            z = 6080;
+            ms = "FEET";
+            g3 = 0.592;
+            ns = "N.MILES";
+            g5 = z;
+        }
+        if (b1 != 3) {
+            if (qs != "YES") {
+                print("\n");
+                print("  YOU ARE ON A LUNAR LANDING MISSION.  AS THE PILOT OF\n");
+                print("THE LUNAR EXCURSION MODULE, YOU WILL BE EXPECTED TO\n");
+                print("GIVE CERTAIN COMMANDS TO THE MODULE NAVIGATION SYSTEM.\n");
+                print("THE ON-BOARD COMPUTER WILL GIVE A RUNNING ACCOUNT\n");
+                print("OF INFORMATION NEEDED TO NAVIGATE THE SHIP.\n");
+                print("\n");
+                print("\n");
+                print("THE ATTITUDE ANGLE CALLED FOR IS DESCRIBED AS FOLLOWS.\n");
+                print("+ OR -180 DEGREES IS DIRECTLY AWAY FROM THE MOON\n");
+                print("-90 DEGREES IS ON A TANGENT IN THE DIRECTION OF ORBIT\n");
+                print("+90 DEGREES IS ON A TANGENT FROM THE DIRECTION OF ORBIT\n");
+                print("0 (ZERO) DEGREES IS DIRECTLY TOWARD THE MOON\n");
+                print("\n");
+                print(tab(30) + "-180|+180\n");
+                print(tab(34) + "^\n");
+                print(tab(27) + "-90 < -+- > +90\n");
+                print(tab(34) + "!\n");
+                print(tab(34) + "0\n");
+                print(tab(21) + "<<<< DIRECTION OF ORBIT <<<<\n");
+                print("\n");
+                print(tab(20) + "------ SURFACE OF MOON ------\n");
+                print("\n");
+                print("\n");
+                print("ALL ANGLES BETWEEN -180 AND +180 DEGREES ARE ACCEPTED.\n");
+                print("\n");
+                print("1 FUEL UNIT = 1 SEC. AT MAX THRUST\n");
+                print("ANY DISCREPANCIES ARE ACCOUNTED FOR IN THE USE OF FUEL\n");
+                print("FOR AN ATTITUDE CHANGE.\n");
+                print("AVAILABLE ENGINE POWER: 0 (ZERO) AND ANY VALUE BETWEEN\n");
+                print("10 AND 100 PERCENT.\n");
+                print("\n");
+                print("NEGATIVE THRUST OR TIME IS PROHIBITED.\n");
+                print("\n");
+            }
+            print("\n");
+            print("INPUT: TIME INTERVAL IN SECONDS ------ (T)\n");
+            print("       PERCENTAGE OF THRUST ---------- (P)\n");
+            print("       ATTITUDE ANGLE IN DEGREES ----- (A)\n");
+            print("\n");
+            if (qs != "YES") {
+                print("FOR EXAMPLE:\n");
+                print("T,P,A? 10,65,-60\n");
+                print("TO ABORT THE MISSION AT ANY TIME, ENTER 0,0,0\n");
+                print("\n");
+            }
+            print("OUTPUT: TOTAL TIME IN ELAPSED SECONDS\n");
+            print("        HEIGHT IN " + ms + "\n");
+            print("        DISTANCE FROM LANDING SITE IN " + ms + "\n");
+            print("        VERTICAL VELOCITY IN " + ms + "/SECOND\n");
+            print("        HORIZONTAL VELOCITY IN " + ms + "/SECOND\n");
+            print("        FUEL UNITS REMAINING\n");
+            print("\n");
+        }
+        while (1) {
+            for (i = 1; i <= n; i++) {
+                if (m1 != 0) {
+                    m1 -= m2;
+                    if (m1 <= 0) {
+                        f = f * (1 + m1 / m2);
+                        m2 = m1 + m2;
+                        print("YOU ARE OUT OF FUEL.\n");
+                        m1 = 0;
+                    }
+                } else {
+                    f = 0;
+                    m2 = 0;
+                }
+                m = m - 0.5 * m2;
+                r4 = r3;
+                r3 = -0.5 * r0 * Math.pow(v0 / r, 2) + r * a1 * a1;
+                r2 = (3 * r3 - r4) / 2 + 0.00526 * f1 * f * c / m;
+                a4 = a3;
+                a3 = -2 * r1 * a1 / r;
+                a2 = (3 * a3 - a4) / 2 + 0.0056 * f1 * f * s / (m * r);
+                x = r1 * t1 + 0.5 * r2 * t1 * t1;
+                r = r + x;
+                h0 = h0 + x;
+                r1 = r1 + r2 * t1;
+                a = a + a1 * t1 + 0.5 * a2 * t1 * t1;
+                a1 = a1 + a2 * t1;
+                m = m - 0.5 * m2;
+                t = t + t1;
+                if (h0 < 3.287828e-4)
+                    break;
+            }
+            h = h0 * z;
+            h1 = r1 * z;
+            d = r0 * a * z;
+            d1 = r * a1 * z;
+            t2 = m1 * b / m0;
+            print(" " + t + "\t" + h + "\t" + d + "\t" + h1 + "\t" + d1 + "\t" + t2 + "\n");
+            if (h0 < 3.287828e-4) {
+                if (r1 < -8.21957e-4 || Math.abs(r * a1) > 4.93174e-4 || h0 < -3.287828e-4) {
+                    print("\n");
+                    print("CRASH !!!!!!!!!!!!!!!!\n");
+                    print("YOUR IMPACT CREATED A CRATER " + Math.abs(h) + " " + ms + " DEEP.\n");
+                    x1 = Math.sqrt(d1 * d1 + h1 * h1) * g3;
+                    print("AT CONTACT YOU WERE TRAVELING " + x1 + " " + ns + "/HR\n");
+                    break;
+                }
+                if (Math.abs(d) > 10 * z) {
+                    print("YOU ARE DOWN SAFELY - \n");
+                    print("\n");
+                    print("BUT MISSED THE LANDING SITE BY " + Math.abs(d / g5) + " " + ns + ".\n");
+                    break;
+                }
+                print("\n");
+                print("TRANQUILITY BASE HERE -- THE EAGLE HAS LANDED.\n");
+                print("CONGRATULATIONS -- THERE WAS NO SPACECRAFT DAMAGE.\n");
+                print("YOU MAY NOW PROCEED WITH SURFACE EXPLORATION.\n");
+                break;
+            }
+            if (r0 * a > 164.474) {
+                print("\n");
+                print("YOU HAVE BEEN LOST IN SPACE WITH NO HOPE OF RECOVERY.\n");
+                break;
+            }
+            if (m1 > 0) {
+                while (1) {
+                    print("T,P,A");
+                    str = await input();
+                    t1 = parseFloat(str);
+                    f = parseFloat(str.substr(str.indexOf(",") + 1));
+                    p = parseFloat(str.substr(str.lastIndexOf(",") + 1));
+                    f = f / 100;
+                    if (t1 < 0) {
+                        print("\n");
+                        print("THIS SPACECRAFT IS NOT ABLE TO VIOLATE THE SPACE-");
+                        print("TIME CONTINUUM.\n");
+                        print("\n");
+                    } else if (t1 == 0) {
+                        break;
+                    } else if (Math.abs(f - 0.05) > 1 || Math.abs(f - 0.05) < 0.05) {
+                        print("IMPOSSIBLE THRUST VALUE ");
+                        if (f < 0) {
+                            print("NEGATIVE\n");
+                        } else if (f - 0.05 < 0.05) {
+                            print("TOO SMALL\n");
+                        } else {
+                            print("TOO LARGE\n");
+                        }
+                        print("\n");
+                    } else if (Math.abs(p) > 180) {
+                        print("\n");
+                        print("IF YOU WANT TO SPIN AROUND, GO OUTSIDE THE MODULE\n");
+                        print("FOR AN E.V.A.\n");
+                        print("\n");
+                    } else {
+                        break;
+                    }
+                }
+                if (t1 == 0) {
+                    print("\n");
+                    print("MISSION ABENDED\n");
+                    break;
+                }
+            } else {
+                t1 = 20;
+                f = 0;
+                p = 0;
+            }
+            n = 20;
+            if (t1 >= 400)
+                n = t1 / 20;
+            t1 = t1 / n;
+            p = p * 3.14159 / 180;
+            s = Math.sin(p);
+            c = Math.cos(p);
+            m2 = m0 * t1 * f / b;
+            r3 = -0.5 * r0 * Math.pow(v0 / r, 2) + r * a1 * a1;
+            a3 = -2 * r1 * a1 / r;
+        }
+        print("\n");
+        while (1) {
+            print("DO YOU WANT TO TRY IT AGAIN (YES/NO)?\n");
+            zs = await input();
+            if (zs == "YES" || zs == "NO")
+                break;
+        }
+        if (zs != "YES")
+            break;
+    }
+    print("\n");
+    print("TOO BAD, THE SPACE PROGRAM HATES TO LOSE EXPERIENCED\n");
+    print("ASTRONAUTS.\n");
+}
+
+main();
diff --git a/59 Lunar LEM Rocket/javascript/lunar.html b/59 Lunar LEM Rocket/javascript/lunar.html
new file mode 100644
index 00000000..cdcabc2d
--- /dev/null
+++ b/59 Lunar LEM Rocket/javascript/lunar.html	
@@ -0,0 +1,9 @@
+
+
+LUNAR
+
+
+

+
+
+
diff --git a/59 Lunar LEM Rocket/javascript/lunar.js b/59 Lunar LEM Rocket/javascript/lunar.js
new file mode 100644
index 00000000..faaeb253
--- /dev/null
+++ b/59 Lunar LEM Rocket/javascript/lunar.js	
@@ -0,0 +1,376 @@
+// KING
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+function hate_your_guts()
+{
+    print("\n");
+    print("\n");
+    print("OVER ONE THIRD OF THE POPULATION HAS DIED SINCE YOU\n");
+    print("WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING)\n");
+    print("HATE YOUR GUTS.\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "KING\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("DO YOU WANT INSTRUCTIONS");
+    str = await input();
+    n5 = 8;
+    if (str == "AGAIN") {
+        while (1) {
+            print("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED");
+            x5 = parseInt(await input());
+            if (x5 == 0)
+                return;
+            if (x5 < 8)
+                break;
+            print("   COME ON, YOUR TERM IN OFFICE IS ONLY " + n5 + " YEARS.\n");
+        }
+        print("HOW MUCH DID YOU HAVE IN THE TREASURY");
+        a = parseInt(await input());
+        if (a < 0)
+            return;
+        print("HOW MANY COUNTRYMEN");
+        b = parseInt(await input());
+        if (b < 0)
+            return;
+        print("HOW MANY WORKERS");
+        c = parseInt(await input());
+        if (c < 0)
+            return;
+        while (1) {
+            print("HOW MANY SQUARE MILES OF LAND");
+            d = parseInt(await input());
+            if (d < 0)
+                return;
+            if (d > 1000 && d <= 2000)
+                break;
+            print("   COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND\n");
+            print("   AND 10,000 SQ. MILES OF FOREST LAND.\n");
+        }
+    } else {
+        if (str.substr(0, 1) != "N") {
+            print("\n");
+            print("\n");
+            print("\n");
+            print("CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS\n");
+            print("DETINU, A SMALL COMMUNIST ISLAND 30 BY 70 MILES LONG. YOUR\n");
+            print("JOB IS TO DECIDE UPON THE CONTRY'S BUDGET AND DISTRIBUTE\n");
+            print("MONEY TO YOUR COUNTRYMEN FROM THE COMMUNAL TREASURY.\n");
+            print("THE MONEY SYSTEM IS RALLODS, AND EACH PERSON NEEDS 100\n");
+            print("RALLODS PER YEAR TO SURVIVE. YOUR COUNTRY'S INCOME COMES\n");
+            print("FROM FARM PRODUCE AND TOURISTS VISITING YOUR MAGNIFICENT\n");
+            print("FORESTS, HUNTING, FISHING, ETC. HALF YOUR LAND IS FARM LAND\n");
+            print("WHICH ALSO HAS AN EXCELLENT MINERAL CONTENT AND MAY BE SOLD\n");
+            print("TO FOREIGN INDUSTRY (STRIP MINING) WHO IMPORT AND SUPPORT\n");
+            print("THEIR OWN WORKERS. CROPS COST BETWEEN 10 AND 15 RALLODS PER\n");
+            print("SQUARE MILE TO PLANT.\n");
+            print("YOUR GOAL IS TO COMPLETE YOUR " + n5 + " YEAR TERM OF OFFICE.\n");
+            print("GOOD LUCK!\n");
+        }
+        print("\n");
+        a = Math.floor(60000 + (1000 * Math.random()) - (1000 * Math.random()));
+        b = Math.floor(500 + (10 * Math.random()) - (10 * Math.random()));
+        c = 0;
+        d = 2000;
+        x5 = 0;
+    }
+    v3 = 0;
+    b5 = 0;
+    x = false;
+    while (1) {
+        w = Math.floor(10 * Math.random() + 95);
+        print("\n");
+        print("YOU NOW HAVE " + a + " RALLODS IN THE TREASURY.\n");
+        print(b + " COUNTRYMEN, ");
+        v9 = Math.floor(((Math.random() / 2) * 10 + 10));
+        if (c != 0)
+            print(c + " FOREIGN WORKERS, ");
+        print("AND " + Math.floor(d) + " SQ. MILES OF LAND.\n");
+        print("THIS YEAR INDUSTRY WILL BUY LAND FOR " + w + " ");
+        print("RALLODS PER SQUARE MILE.\n");
+        print("LAND CURRENTLY COSTS " + v9 + " RALLODS PER SQUARE MILE TO PLANT.\n");
+        print("\n");
+        while (1) {
+            print("HOW MANY SQUARE MILES DO YOU WISH TO SELL TO INDUSTRY");
+            h = parseInt(await input());
+            if (h < 0)
+                continue;
+            if (h <= d - 1000)
+                break;
+            print("***  THINK AGAIN. YOU ONLY HAVE " + (d - 1000) + " SQUARE MILES OF FARM LAND.\n");
+            if (x == false) {
+                print("\n");
+                print("(FOREIGN INDUSTRY WILL ONLY BUY FARM LAND BECAUSE\n");
+                print("FOREST LAND IS UNECONOMICAL TO STRIP MINE DUE TO TREES,\n");
+                print("THICKER TOP SOIL, ETC.)\n");
+                x = true;
+            }
+        }
+        d = Math.floor(d - h);
+        a = Math.floor(a + (h * w));
+        while (1) {
+            print("HOW MANY RALLODS WILL YOU DISTRIBUTE AMONG YOUR COUNTRYMEN");
+            i = parseInt(await input());
+            if (i < 0)
+                continue;
+            if (i < a)
+                break;
+            if (i == a) {
+                j = 0;
+                k = 0;
+                a = 0;
+                break;
+            }
+            print("   THINK AGAIN. YOU'VE ONLY " + a + " RALLODS IN THE TREASURY\n");
+        }
+        if (a) {
+            a = Math.floor(a - i);
+            while (1) {
+                print("HOW MANY SQUARE MILES DO YOU WISH TO PLANT");
+                j = parseInt(await input());
+                if (j < 0)
+                    continue;
+                if (j <= b * 2) {
+                    if (j <= d - 1000) {
+                        u1 = Math.floor(j * v9);
+                        if (u1 > a) {
+                            print("   THINK AGAIN. YOU'VE ONLY " + a + " RALLODS LEFT IN THE TREASURY.\n");
+                            continue;
+                        } else if (u1 == a) {
+                            k = 0;
+                            a = 0;
+                        }
+                        break;
+                    }
+                    print("   SORRY, BUT YOU'VE ONLY " + (d - 1000) + " SQ. MILES OF FARM LAND.\n");
+                    continue;
+                }
+                print("   SORRY, BUT EACH COUNTRYMAN CAN ONLY PLANT 2 SQ. MILES.\n");
+            }
+        }
+        if (a) {
+            a -= u1;
+            while (1) {
+                print("HOW MANY RALLODS DO YOU WISH TO SPEND ON POLLUTION CONTROL");
+                k = parseInt(await input());
+                if (k < 0)
+                    continue;
+                if (k <= a)
+                    break;
+                print("   THINK AGAIN. YOU ONLY HAVE " + a + " RALLODS REMAINING.\n");
+            }
+        }
+        if (h == 0 && i == 0 && j == 0 && k == 0) {
+            print("GOODBYE.\n");
+            print("(IF YOU WISH TO CONTINUE THIS GAME AT A LATER DATE, ANSWER\n");
+            print("'AGAIN' WHEN ASKED IF YOU WANT INSTRUCTIONS AT THE START\n");
+            print("OF THE GAME).\n");
+            return;
+        }
+        print("\n");
+        print("\n");
+        a = Math.floor(a - k);
+        a4 = a;
+        if (Math.floor(i / 100 - b) < 0) {
+            if (i / 100 < 50) {
+                hate_your_guts();
+                break;
+            }
+            print(Math.floor(b - (i / 100)) + " COUNTRYMEN DIED OF STARVATION\n");
+        }
+        f1 = Math.floor(Math.random() * (2000 - d));
+        if (k >= 25)
+            f1 = Math.floor(f1 / (k / 25));
+        if (f1 > 0)
+            print(f1 + " COUNTRYMEN DIED OF CARBON-MONOXIDE AND DUST INHALATION\n");
+        funeral = false;
+        if (Math.floor((i / 100) - b) >= 0) {
+            if (f1 > 0) {
+                print("   YOU WERE FORCED TO SPEND " + Math.floor(f1 * 9) + " RALLODS ON ");
+                print("FUNERAL EXPENSES.\n");
+                b5 = f1;
+                a = Math.floor(a - (f1 * 9));
+                funeral = true;
+            }
+        } else {
+            print("   YOU WERE FORCED TO SPEND " + Math.floor((f1 + (b - (i / 100))) * 9));
+            print(" RALLODS ON FUNERAL EXPENSES.\n");
+            b5 = Math.floor(f1 + (b - (i / 100)));
+            a = Math.floor(a - ((f1 + (b - (i / 100))) * 9));
+            funeral = true;
+        }
+        if (funeral) {
+            if (a < 0) {
+                print("   INSUFFICIENT RESERVES TO COVER COST - LAND WAS SOLD\n");
+                d = Math.floor(d + (a / w));
+                a = 0;
+            }
+            b = Math.floor(b - b5);
+        }
+        c1 = 0;
+        if (h != 0) {
+            c1 = Math.floor(h + (Math.random() * 10) - (Math.random() * 20));
+            if (c <= 0)
+                c1 += 20;
+            print(c1 + " WORKERS CAME TO THE COUNTRY AND ");
+        }
+        p1 = Math.floor(((i / 100 - b) / 10) + (k / 25) - ((2000 - d) / 50) - (f1 / 2));
+        print(Math.abs(p1) + " COUNTRYMEN ");
+        if (p1 >= 0)
+            print("CAME TO");
+        else
+            print("LEFT");
+        print(" THE ISLAND.\n");
+        b = Math.floor(b + p1);
+        c = Math.floor(c + c1);
+        u2 = Math.floor(((2000 - d) * ((Math.random() + 1.5) / 2)));
+        if (c != 0) {
+            print("OF " + Math.floor(j) + " SQ. MILES PLANTED,");
+        }
+        if (j <= u2)
+            u2 = j;
+        print(" YOU HARVESTED " + Math.floor(j - u2) + " SQ. MILES OF CROPS.\n");
+        if (u2 != 0 && t1 < 2) {
+            print("   (DUE TO ");
+            if (t1 != 0)
+                print("INCREASED ");
+            print("AIR AND WATER POLLUTION FROM FOREIGN INDUSTRY.)\n");
+        }
+        q = Math.floor((j - u2) * (w / 2));
+        print("MAKING " + q + " RALLODS.\n");
+        a = Math.floor(a + q);
+        v1 = Math.floor(((b - p1) * 22) + (Math.random() * 500));
+        v2 = Math.floor((2000 - d) * 15);
+        print(" YOU MADE " + Math.abs(Math.floor(v1 - v2)) + " RALLODS FROM TOURIST TRADE.\n");
+        if (v2 != 0 && v1 - v2 < v3) {
+            print("   DECREASE BECAUSE ");
+            g1 = 10 * Math.random();
+            if (g1 <= 2)
+                print("FISH POPULATION HAS DWINDLED DUE TO WATER POLLUTION.\n");
+            else if (g1 <= 4)
+                print("AIR POLLUTION IS KILLING GAME BIRD POPULATION.\n");
+            else if (g1 <= 6)
+                print("MINERAL BATHS ARE BEING RUINED BY WATER POLLUTION.\n");
+            else if (g1 <= 8)
+                print("UNPLEASANT SMOG IS DISCOURAGING SUN BATHERS.\n");
+            else if (g1 <= 10)
+                print("HOTELS ARE LOOKING SHABBY DUE TO SMOG GRIT.\n");
+        }
+        v3 = Math.floor(a + v3);    // Probable bug from original game
+        a = Math.floor(a + v3);
+        if (b5 > 200) {
+            print("\n");
+            print("\n");
+            print(b5 + " COUNTRYMEN DIED IN ONE YEAR!!!!!\n");
+            print("DUE TO THIS EXTREME MISMANAGEMENT, YOU HAVE NOT ONLY\n");
+            print("BEEN IMPEACHED AND THROWN OUT OF OFFICE, BUT YOU\n");
+            m6 = Math.floor(Math.random() * 10);
+            if (m6 <= 3)
+                print("ALSO HAD YOUR LEFT EYE GOUGED OUT!\n");
+            else if (m6 <= 6)
+                print("HAVE ALSO GAINED A VERY BAD REPUTATION.\n");
+            else
+                print("HAVE ALSO BEEN DECLARED NATIONAL FINK.\n");
+            print("\n");
+            print("\n");
+            return;
+        }
+        if (b < 343) {
+            hate_your_guts();
+            break;
+        }
+        if (a4 / 100 > 5 && b5 - f1 >= 2) {
+            print("\n");
+            print("MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID\n");
+            print("NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED\n");
+            print("OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE\n");
+            print("BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE.\n");
+            print("THE CHOICE IS YOURS.\n");
+            print("IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER\n");
+            print("BEFORE PROCEEDING.\n");
+            print("\n");
+            print("\n");
+            return;
+        }
+        if (c > b) {
+            print("\n");
+            print("\n");
+            print("THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER\n");
+            print("OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND\n");
+            print("TAKEN OVER THE COUNTRY.\n");
+            break;
+        }
+        if (n5 - 1 == x5) {
+            print("\n");
+            print("\n");
+            print("CONGRATULATIONS!!!!!!!!!!!!!!!!!!\n");
+            print("YOU HAVE SUCCESFULLY COMPLETED YOUR " + n5 + " YEAR TERM\n");
+            print("OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT\n");
+            print("NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD\n");
+            print("LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT\n");
+            print("PLAYS THIS GAME.\n");
+            print("\n");
+            print("\n");
+            return;
+        }
+        x5++;
+        b5 = 0;
+    }
+    if (Math.random() <= 0.5) {
+        print("YOU HAVE BEEN ASSASSINATED.\n");
+    } else {
+        print("YOU HAVE BEEN THROWN OUT OF OFFICE AND ARE NOW\n");
+        print("RESIDING IN PRISON.\n");
+    }
+    print("\n");
+    print("\n");
+}
+
+main();

From e8ebdb3b84acf44e0a7e0d98138b5ba8893aca25 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Fri, 12 Mar 2021 22:02:32 -0600
Subject: [PATCH 287/749] Ported LUNAR to Javascript

---
 59 Lunar LEM Rocket/javascript/lunar.js | 429 +++++++-----------------
 1 file changed, 122 insertions(+), 307 deletions(-)

diff --git a/59 Lunar LEM Rocket/javascript/lunar.js b/59 Lunar LEM Rocket/javascript/lunar.js
index faaeb253..f95d1d16 100644
--- a/59 Lunar LEM Rocket/javascript/lunar.js	
+++ b/59 Lunar LEM Rocket/javascript/lunar.js	
@@ -1,4 +1,4 @@
-// KING
+// LUNAR
 //
 // Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
 //
@@ -42,335 +42,150 @@ function tab(space)
     return str;
 }
 
-function hate_your_guts()
+var l;
+var t;
+var m;
+var s;
+var k;
+var a;
+var v;
+var i;
+var j;
+var q;
+var g;
+var z;
+var d;
+
+function formula_set_1()
 {
-    print("\n");
-    print("\n");
-    print("OVER ONE THIRD OF THE POPULATION HAS DIED SINCE YOU\n");
-    print("WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING)\n");
-    print("HATE YOUR GUTS.\n");
+    l = l + s;
+    t = t - s;
+    m = m - s * k;
+    a = i;
+    v = j;
+}
+
+function formula_set_2()
+{
+    q = s * k / m;
+    j = v + g * s + z * (-q - q * q / 2 - Math.pow(q, 3) / 3 - Math.pow(q, 4) / 4 - Math.pow(q, 5) / 5);
+    i = a - g * s * s / 2 - v * s + z * s * (q / 2 + Math.pow(q, 2) / 6 + Math.pow(q, 3) / 12 + Math.pow(q, 4) / 20 + Math.pow(q, 5) / 30);
+}
+
+function formula_set_3()
+{
+    while (s >= 5e-3) {
+        d = v + Math.sqrt(v * v + 2 * a * (g - z * k / m));
+        s = 2 * a / d;
+        formula_set_2();
+        formula_set_1();
+    }
 }
 
 // Main program
 async function main()
 {
-    print(tab(34) + "KING\n");
+    print(tab(33) + "LUNAR\n");
     print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
     print("\n");
     print("\n");
     print("\n");
-    print("DO YOU WANT INSTRUCTIONS");
-    str = await input();
-    n5 = 8;
-    if (str == "AGAIN") {
-        while (1) {
-            print("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED");
-            x5 = parseInt(await input());
-            if (x5 == 0)
-                return;
-            if (x5 < 8)
-                break;
-            print("   COME ON, YOUR TERM IN OFFICE IS ONLY " + n5 + " YEARS.\n");
-        }
-        print("HOW MUCH DID YOU HAVE IN THE TREASURY");
-        a = parseInt(await input());
-        if (a < 0)
-            return;
-        print("HOW MANY COUNTRYMEN");
-        b = parseInt(await input());
-        if (b < 0)
-            return;
-        print("HOW MANY WORKERS");
-        c = parseInt(await input());
-        if (c < 0)
-            return;
-        while (1) {
-            print("HOW MANY SQUARE MILES OF LAND");
-            d = parseInt(await input());
-            if (d < 0)
-                return;
-            if (d > 1000 && d <= 2000)
-                break;
-            print("   COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND\n");
-            print("   AND 10,000 SQ. MILES OF FOREST LAND.\n");
-        }
-    } else {
-        if (str.substr(0, 1) != "N") {
-            print("\n");
-            print("\n");
-            print("\n");
-            print("CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS\n");
-            print("DETINU, A SMALL COMMUNIST ISLAND 30 BY 70 MILES LONG. YOUR\n");
-            print("JOB IS TO DECIDE UPON THE CONTRY'S BUDGET AND DISTRIBUTE\n");
-            print("MONEY TO YOUR COUNTRYMEN FROM THE COMMUNAL TREASURY.\n");
-            print("THE MONEY SYSTEM IS RALLODS, AND EACH PERSON NEEDS 100\n");
-            print("RALLODS PER YEAR TO SURVIVE. YOUR COUNTRY'S INCOME COMES\n");
-            print("FROM FARM PRODUCE AND TOURISTS VISITING YOUR MAGNIFICENT\n");
-            print("FORESTS, HUNTING, FISHING, ETC. HALF YOUR LAND IS FARM LAND\n");
-            print("WHICH ALSO HAS AN EXCELLENT MINERAL CONTENT AND MAY BE SOLD\n");
-            print("TO FOREIGN INDUSTRY (STRIP MINING) WHO IMPORT AND SUPPORT\n");
-            print("THEIR OWN WORKERS. CROPS COST BETWEEN 10 AND 15 RALLODS PER\n");
-            print("SQUARE MILE TO PLANT.\n");
-            print("YOUR GOAL IS TO COMPLETE YOUR " + n5 + " YEAR TERM OF OFFICE.\n");
-            print("GOOD LUCK!\n");
-        }
-        print("\n");
-        a = Math.floor(60000 + (1000 * Math.random()) - (1000 * Math.random()));
-        b = Math.floor(500 + (10 * Math.random()) - (10 * Math.random()));
-        c = 0;
-        d = 2000;
-        x5 = 0;
-    }
-    v3 = 0;
-    b5 = 0;
-    x = false;
+    print("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR\n");
+    print("LANDING CAPSULE.\n");
+    print("\n");
+    print("\n");
+    print("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY\n");
+    print("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.\n");
     while (1) {
-        w = Math.floor(10 * Math.random() + 95);
         print("\n");
-        print("YOU NOW HAVE " + a + " RALLODS IN THE TREASURY.\n");
-        print(b + " COUNTRYMEN, ");
-        v9 = Math.floor(((Math.random() / 2) * 10 + 10));
-        if (c != 0)
-            print(c + " FOREIGN WORKERS, ");
-        print("AND " + Math.floor(d) + " SQ. MILES OF LAND.\n");
-        print("THIS YEAR INDUSTRY WILL BUY LAND FOR " + w + " ");
-        print("RALLODS PER SQUARE MILE.\n");
-        print("LAND CURRENTLY COSTS " + v9 + " RALLODS PER SQUARE MILE TO PLANT.\n");
+        print("SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN\n");
+        print("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.\n");
+        print("SET NEW BURN RATE EVERY 10 SECONDS.\n");
         print("\n");
+        print("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.\n");
+        print("\n");
+        print("\n");
+        print("\n");
+        print("GOOD LUCK\n");
+        l = 0;
+        print("\n");
+        print("SEC\tMI + FT\t\tMPH\tLB FUEL\tBURN RATE\n");
+        print("\n");
+        a = 120;
+        v = 1;
+        m = 33000;
+        n = 16500;
+        g = 1e-3;
+        z = 1.8;
         while (1) {
-            print("HOW MANY SQUARE MILES DO YOU WISH TO SELL TO INDUSTRY");
-            h = parseInt(await input());
-            if (h < 0)
-                continue;
-            if (h <= d - 1000)
-                break;
-            print("***  THINK AGAIN. YOU ONLY HAVE " + (d - 1000) + " SQUARE MILES OF FARM LAND.\n");
-            if (x == false) {
-                print("\n");
-                print("(FOREIGN INDUSTRY WILL ONLY BUY FARM LAND BECAUSE\n");
-                print("FOREST LAND IS UNECONOMICAL TO STRIP MINE DUE TO TREES,\n");
-                print("THICKER TOP SOIL, ETC.)\n");
-                x = true;
-            }
-        }
-        d = Math.floor(d - h);
-        a = Math.floor(a + (h * w));
-        while (1) {
-            print("HOW MANY RALLODS WILL YOU DISTRIBUTE AMONG YOUR COUNTRYMEN");
-            i = parseInt(await input());
-            if (i < 0)
-                continue;
-            if (i < a)
-                break;
-            if (i == a) {
-                j = 0;
-                k = 0;
-                a = 0;
-                break;
-            }
-            print("   THINK AGAIN. YOU'VE ONLY " + a + " RALLODS IN THE TREASURY\n");
-        }
-        if (a) {
-            a = Math.floor(a - i);
+            print(l + "\t" + Math.floor(a) + " + " + Math.floor(5280 * (a - Math.floor(a))) + " \t" + Math.floor(3600 * v * 100) / 100 + "\t" + (m - n) + "\t");
+            k = parseFloat(await input());
+            t = 10;
+            should_exit = false;
             while (1) {
-                print("HOW MANY SQUARE MILES DO YOU WISH TO PLANT");
-                j = parseInt(await input());
-                if (j < 0)
-                    continue;
-                if (j <= b * 2) {
-                    if (j <= d - 1000) {
-                        u1 = Math.floor(j * v9);
-                        if (u1 > a) {
-                            print("   THINK AGAIN. YOU'VE ONLY " + a + " RALLODS LEFT IN THE TREASURY.\n");
-                            continue;
-                        } else if (u1 == a) {
-                            k = 0;
-                            a = 0;
-                        }
-                        break;
-                    }
-                    print("   SORRY, BUT YOU'VE ONLY " + (d - 1000) + " SQ. MILES OF FARM LAND.\n");
-                    continue;
-                }
-                print("   SORRY, BUT EACH COUNTRYMAN CAN ONLY PLANT 2 SQ. MILES.\n");
-            }
-        }
-        if (a) {
-            a -= u1;
-            while (1) {
-                print("HOW MANY RALLODS DO YOU WISH TO SPEND ON POLLUTION CONTROL");
-                k = parseInt(await input());
-                if (k < 0)
-                    continue;
-                if (k <= a)
+                if (m - n < 1e-3)
                     break;
-                print("   THINK AGAIN. YOU ONLY HAVE " + a + " RALLODS REMAINING.\n");
+                if (t < 1e-3)
+                    break;
+                s = t;
+                if (m < n + s * k)
+                    s = (m - n) / k;
+                formula_set_2();
+                if (i <= 0) {
+                    formula_set_3();
+                    should_exit = true;
+                    break;
+                }
+                if (v > 0) {
+                    if (j < 0) {
+                        do {
+                            w = (1 - m * g / (z * k)) / 2;
+                            s = m * v / (z * k * (w + Math.sqrt(w * w + v / z))) + 0.05;
+                            formula_set_2();
+                            if (i <= 0) {
+                                formula_set_3();
+                                should_exit = true;
+                                break;
+                            }
+                            formula_set_1();
+                            if (j > 0)
+                                break;
+                        } while (v > 0) ;
+                        if (should_exit)
+                            break;
+                        continue;
+                    }
+                }
+                formula_set_1();
             }
-        }
-        if (h == 0 && i == 0 && j == 0 && k == 0) {
-            print("GOODBYE.\n");
-            print("(IF YOU WISH TO CONTINUE THIS GAME AT A LATER DATE, ANSWER\n");
-            print("'AGAIN' WHEN ASKED IF YOU WANT INSTRUCTIONS AT THE START\n");
-            print("OF THE GAME).\n");
-            return;
-        }
-        print("\n");
-        print("\n");
-        a = Math.floor(a - k);
-        a4 = a;
-        if (Math.floor(i / 100 - b) < 0) {
-            if (i / 100 < 50) {
-                hate_your_guts();
+            if (should_exit)
+                break;
+            if (m - n < 1e-3) {
+                print("FUEL OUT AT " + l + " SECOND\n");
+                s = (-v * Math.sqrt(v * v + 2 * a * g)) / g;
+                v = v + g * s;
+                l = l + s;
                 break;
             }
-            print(Math.floor(b - (i / 100)) + " COUNTRYMEN DIED OF STARVATION\n");
         }
-        f1 = Math.floor(Math.random() * (2000 - d));
-        if (k >= 25)
-            f1 = Math.floor(f1 / (k / 25));
-        if (f1 > 0)
-            print(f1 + " COUNTRYMEN DIED OF CARBON-MONOXIDE AND DUST INHALATION\n");
-        funeral = false;
-        if (Math.floor((i / 100) - b) >= 0) {
-            if (f1 > 0) {
-                print("   YOU WERE FORCED TO SPEND " + Math.floor(f1 * 9) + " RALLODS ON ");
-                print("FUNERAL EXPENSES.\n");
-                b5 = f1;
-                a = Math.floor(a - (f1 * 9));
-                funeral = true;
-            }
+        w = 3600 * v;
+        print("ON MOON AT " + l + " SECONDS - IMPACT VELOCITY " + w + " MPH\n");
+        if (w <= 1.2) {
+            print("PERFECT LANDING!\n");
+        } else if (w <= 10) {
+            print("GOOD LANDING (COULD BE BETTER)\n");
+        } else if (w <= 60) {
+            print("CRAFT DAMAGE... YOU'RE STRANDED HERE UNTIL A RESCUE\n");
+            print("PARTY ARRIVES. HOPE YOU HAVE ENOUGH OXYGEN!\n");
         } else {
-            print("   YOU WERE FORCED TO SPEND " + Math.floor((f1 + (b - (i / 100))) * 9));
-            print(" RALLODS ON FUNERAL EXPENSES.\n");
-            b5 = Math.floor(f1 + (b - (i / 100)));
-            a = Math.floor(a - ((f1 + (b - (i / 100))) * 9));
-            funeral = true;
+            print("SORRY THERE WERE NO SURVIVORS. YOU BLEW IT!\n");
+            print("IN FACT, YOU BLASTED A NEW LUNAR CRATER " + (w * 0.227) + " FEET DEEP!\n");
         }
-        if (funeral) {
-            if (a < 0) {
-                print("   INSUFFICIENT RESERVES TO COVER COST - LAND WAS SOLD\n");
-                d = Math.floor(d + (a / w));
-                a = 0;
-            }
-            b = Math.floor(b - b5);
-        }
-        c1 = 0;
-        if (h != 0) {
-            c1 = Math.floor(h + (Math.random() * 10) - (Math.random() * 20));
-            if (c <= 0)
-                c1 += 20;
-            print(c1 + " WORKERS CAME TO THE COUNTRY AND ");
-        }
-        p1 = Math.floor(((i / 100 - b) / 10) + (k / 25) - ((2000 - d) / 50) - (f1 / 2));
-        print(Math.abs(p1) + " COUNTRYMEN ");
-        if (p1 >= 0)
-            print("CAME TO");
-        else
-            print("LEFT");
-        print(" THE ISLAND.\n");
-        b = Math.floor(b + p1);
-        c = Math.floor(c + c1);
-        u2 = Math.floor(((2000 - d) * ((Math.random() + 1.5) / 2)));
-        if (c != 0) {
-            print("OF " + Math.floor(j) + " SQ. MILES PLANTED,");
-        }
-        if (j <= u2)
-            u2 = j;
-        print(" YOU HARVESTED " + Math.floor(j - u2) + " SQ. MILES OF CROPS.\n");
-        if (u2 != 0 && t1 < 2) {
-            print("   (DUE TO ");
-            if (t1 != 0)
-                print("INCREASED ");
-            print("AIR AND WATER POLLUTION FROM FOREIGN INDUSTRY.)\n");
-        }
-        q = Math.floor((j - u2) * (w / 2));
-        print("MAKING " + q + " RALLODS.\n");
-        a = Math.floor(a + q);
-        v1 = Math.floor(((b - p1) * 22) + (Math.random() * 500));
-        v2 = Math.floor((2000 - d) * 15);
-        print(" YOU MADE " + Math.abs(Math.floor(v1 - v2)) + " RALLODS FROM TOURIST TRADE.\n");
-        if (v2 != 0 && v1 - v2 < v3) {
-            print("   DECREASE BECAUSE ");
-            g1 = 10 * Math.random();
-            if (g1 <= 2)
-                print("FISH POPULATION HAS DWINDLED DUE TO WATER POLLUTION.\n");
-            else if (g1 <= 4)
-                print("AIR POLLUTION IS KILLING GAME BIRD POPULATION.\n");
-            else if (g1 <= 6)
-                print("MINERAL BATHS ARE BEING RUINED BY WATER POLLUTION.\n");
-            else if (g1 <= 8)
-                print("UNPLEASANT SMOG IS DISCOURAGING SUN BATHERS.\n");
-            else if (g1 <= 10)
-                print("HOTELS ARE LOOKING SHABBY DUE TO SMOG GRIT.\n");
-        }
-        v3 = Math.floor(a + v3);    // Probable bug from original game
-        a = Math.floor(a + v3);
-        if (b5 > 200) {
-            print("\n");
-            print("\n");
-            print(b5 + " COUNTRYMEN DIED IN ONE YEAR!!!!!\n");
-            print("DUE TO THIS EXTREME MISMANAGEMENT, YOU HAVE NOT ONLY\n");
-            print("BEEN IMPEACHED AND THROWN OUT OF OFFICE, BUT YOU\n");
-            m6 = Math.floor(Math.random() * 10);
-            if (m6 <= 3)
-                print("ALSO HAD YOUR LEFT EYE GOUGED OUT!\n");
-            else if (m6 <= 6)
-                print("HAVE ALSO GAINED A VERY BAD REPUTATION.\n");
-            else
-                print("HAVE ALSO BEEN DECLARED NATIONAL FINK.\n");
-            print("\n");
-            print("\n");
-            return;
-        }
-        if (b < 343) {
-            hate_your_guts();
-            break;
-        }
-        if (a4 / 100 > 5 && b5 - f1 >= 2) {
-            print("\n");
-            print("MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID\n");
-            print("NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED\n");
-            print("OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE\n");
-            print("BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE.\n");
-            print("THE CHOICE IS YOURS.\n");
-            print("IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER\n");
-            print("BEFORE PROCEEDING.\n");
-            print("\n");
-            print("\n");
-            return;
-        }
-        if (c > b) {
-            print("\n");
-            print("\n");
-            print("THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER\n");
-            print("OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND\n");
-            print("TAKEN OVER THE COUNTRY.\n");
-            break;
-        }
-        if (n5 - 1 == x5) {
-            print("\n");
-            print("\n");
-            print("CONGRATULATIONS!!!!!!!!!!!!!!!!!!\n");
-            print("YOU HAVE SUCCESFULLY COMPLETED YOUR " + n5 + " YEAR TERM\n");
-            print("OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT\n");
-            print("NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD\n");
-            print("LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT\n");
-            print("PLAYS THIS GAME.\n");
-            print("\n");
-            print("\n");
-            return;
-        }
-        x5++;
-        b5 = 0;
+        print("\n");
+        print("\n");
+        print("\n");
+        print("TRY AGAIN??\n");
     }
-    if (Math.random() <= 0.5) {
-        print("YOU HAVE BEEN ASSASSINATED.\n");
-    } else {
-        print("YOU HAVE BEEN THROWN OUT OF OFFICE AND ARE NOW\n");
-        print("RESIDING IN PRISON.\n");
-    }
-    print("\n");
-    print("\n");
 }
 
 main();

From 990dd614d4565172f375970c42157ec257d9fa32 Mon Sep 17 00:00:00 2001
From: Aldrin Misquitta 
Date: Sat, 13 Mar 2021 14:51:42 +0400
Subject: [PATCH 288/749] Ported 66 Number to Java

---
 66 Number/java/Number.java | 62 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 66 Number/java/Number.java

diff --git a/66 Number/java/Number.java b/66 Number/java/Number.java
new file mode 100644
index 00000000..2e481fca
--- /dev/null
+++ b/66 Number/java/Number.java	
@@ -0,0 +1,62 @@
+import java.util.Scanner;
+
+public class Number {
+
+	public static void main(String[] args) {
+		printIntro();
+		int points = 100; //start with 100 points for the user
+
+		Scanner scan = new Scanner(System.in);
+		boolean done = false;
+		while (!done) {
+			System.out.print("GUESS A NUMBER FROM 1 TO 5? ");
+			int g = scan.nextInt();
+
+			//Initialize 5 random numbers between 1-5
+			var r = randomNumber(1);
+			var s = randomNumber(1);
+			var t = randomNumber(1);
+			var u = randomNumber(1);
+			var v = randomNumber(1);
+
+			if (r == g) {
+				points -= 5;
+			} else if (s == g) {
+				points += 5;
+			} else if (t == g) {
+				points += points;
+			} else if (u == g) {
+				points += 1;
+			} else if (v == g) {
+				points -= points * 0.5;
+			} else {
+				continue; //Doesn't match any of our random numbers, so just ask for another guess
+			}
+
+			if (points > 500) {
+				done = true;
+			} else {
+				System.out.println("YOU HAVE " + points + " POINTS.");
+			}
+		}
+
+		System.out.println("!!!!YOU WIN!!!! WITH " + points + " POINTS.\n");
+	}
+
+	private static int randomNumber(int x) {
+		//Note: 'x' is totally ignored as was in the original basic listing
+		return (int) (5 * Math.random() + 1);
+	}
+
+	private static void printIntro() {
+		System.out.println("                                NUMBER");
+		System.out.println("              CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+		System.out.println("\n\n\n");
+		System.out.println("YOU HAVE 100 POINTS.  BY GUESSING NUMBERS FROM 1 TO 5, YOU");
+		System.out.println("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO");
+		System.out.println("A RANDOM NUMBER SELECTED BY THE COMPUTER.");
+		System.out.println("\n");
+		System.out.println("YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)");
+		System.out.println("YOUR POINT COUNT.  YOU WIN WHEN YOU GET 500 POINTS.");
+	}
+}

From 4e5d65b621bad96621c2e06fac8e97098f85b384 Mon Sep 17 00:00:00 2001
From: Aldrin Misquitta 
Date: Sat, 13 Mar 2021 14:52:18 +0400
Subject: [PATCH 289/749] Deleted main.class. Not sure what it is doing here

---
 66 Number/java/main.class | 69 ---------------------------------------
 1 file changed, 69 deletions(-)
 delete mode 100644 66 Number/java/main.class

diff --git a/66 Number/java/main.class b/66 Number/java/main.class
deleted file mode 100644
index c3df4ebf..00000000
--- a/66 Number/java/main.class	
+++ /dev/null
@@ -1,69 +0,0 @@
-
-import java.time.temporal.ValueRange;
-import java.util.Arrays;
-import java.util.Random;
-import java.util.Scanner;
-
-public class Number {
-
-    public static int points = 0;
-
-    public static void printempty() { System.out.println(" "); }
-
-    public static void print(String toprint) { System.out.println(toprint); }
-
-    public static void main(String[] args) {
-        print("YOU HAVE 100 POINTS.  BY GUESSING NUMBERS FROM 1 TO 5, YOU");
-        print("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO");
-        print("A RANDOM NUMBER SELECTED BY THE COMPUTER.");
-        printempty();
-        print("YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)");
-        print("YOUR POINT COUNT.  YOU WIN WHEN YOU GET 500 POINTS.");
-        printempty();
-
-        try {
-            while (true) {
-                print("GUESS A NUMBER FROM 1 TO 5");
-
-
-                Scanner numbersc = new Scanner(System.in);
-                String numberstring = numbersc.nextLine();
-
-                int number = Integer.parseInt(numberstring);
-
-                if (!(number < 1| number > 5)) {
-
-                    Random rand = new Random();
-
-                    int randomNum = rand.nextInt((5 - 1) + 1) + 1;
-
-                    if (randomNum == number) {
-                        print("YOU HIT THE JACKPOT!!!");
-                        points = points * 2;
-                    } else if(ValueRange.of(randomNum, randomNum + 1).isValidIntValue(number)) {
-                        print("+5");
-                        points = points + 5;
-                    } else if(ValueRange.of(randomNum - 1, randomNum + 2).isValidIntValue(number)) {
-                        print("+1");
-                        points = points + 1;
-                    } else if(ValueRange.of(randomNum - 3, randomNum + 1).isValidIntValue(number)) {
-                        print("-1");
-                        points = points - 1;
-                    } else {
-                        print("-half");
-                        points = (int) (points * 0.5);
-                    }
-
-                    print("YOU HAVE " + points + " POINTS.");
-                }
-
-                if (points >= 500) {
-                    print("!!!!YOU WIN!!!! WITH " + points + " POINTS.");
-                    return;
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-}

From 8ef694996f2d83d06b7f51481a056bb781a19dfa Mon Sep 17 00:00:00 2001
From: Chris Reuter 
Date: Sat, 13 Mar 2021 14:58:08 -0500
Subject: [PATCH 290/749] Added ruby implemention of Checkers.

Also added my annotated version of the BASIC source code on the off
chance that it would be useful.
---
 23 Checkers/README.md              |   5 +-
 23 Checkers/checkers.annotated.bas | 315 ++++++++++++++
 23 Checkers/ruby/README.md         |   5 +
 23 Checkers/ruby/checkers.rb       | 651 +++++++++++++++++++++++++++++
 4 files changed, 975 insertions(+), 1 deletion(-)
 create mode 100644 23 Checkers/checkers.annotated.bas
 create mode 100644 23 Checkers/ruby/checkers.rb

diff --git a/23 Checkers/README.md b/23 Checkers/README.md
index 05681815..0a3c57a2 100644
--- a/23 Checkers/README.md	
+++ b/23 Checkers/README.md	
@@ -6,10 +6,13 @@ https://www.atariarchives.org/basicgames/showpage.php?page=40
 Downloaded from Vintage Basic at
 http://www.vintage-basic.net/games.html
 
+The file `checkers.annotated.bas` contains an indented and annotated
+version of the source code.  This is no longer valid BASIC code but
+should be more readable.
 
 ## Known Issues In the Original BASIC Code
  - If the computer moves a checker to the bottom row, it promotes, but
    leaves the original checker in place. (See line 1240)
  - Human players may move non-kings as if they were kings. (See lines 1590 to 1810)
+ - Human players are not required to jump if it is possible.
  - Curious writing to "I" variable without ever reading it. (See lines 1700 and 1806)
- 
\ No newline at end of file
diff --git a/23 Checkers/checkers.annotated.bas b/23 Checkers/checkers.annotated.bas
new file mode 100644
index 00000000..af8ffabc
--- /dev/null
+++ b/23 Checkers/checkers.annotated.bas	
@@ -0,0 +1,315 @@
+     # Annotated version of CHECKERS.BAS, modified to improve readability.
+     #
+     # I've made the following changes:
+     #
+     #  1. Added many comments and blank lines.
+     #  2. Separated each statement into its own line.
+     #  3. Indented loops, conditionals and subroutines.
+     #  4. Turned *SOME* conditionals and loops into
+     #     structured-BASIC-style if/endif and loop/endloop blocks.
+     #  5. Switched to using '#' to delimit comments.
+     #  6. Subroutines now begin with "Sub_Start"
+     #  7. All non-string text has been converted to lower-case
+     #  8. All line numbers that are not jump destinations have been removed.
+     #
+     # This has helped me make sense of the code.  I hope it will also help you.
+     #
+
+     # Print the banner
+     print tab(32);"CHECKERS"
+     print tab(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
+     print
+     print
+     print
+     print "THIS IS THE GAME OF CHECKERS.  THE COMPUTER IS X,"
+     print "AND YOU ARE O.  THE COMPUTER WILL MOVE FIRST."
+     print "SQUARES ARE REFERRED TO BY A COORDINATE SYSTEM."
+     print "(0,0) IS THE LOWER LEFT CORNER"
+     print "(0,7) IS THE UPPER LEFT CORNER"
+     print "(7,0) IS THE LOWER RIGHT CORNER"
+     print "(7,7) IS THE UPPER RIGHT CORNER"
+     print "THE COMPUTER WILL TYPE '+TO' WHEN YOU HAVE ANOTHER"
+     print "JUMP.  TYPE TWO NEGATIVE NUMBERS IF YOU CANNOT JUMP."
+     print
+     print
+     print
+
+     # Declare the "globals":
+
+     # The current move: (rating, current x, current y, new x, new y)
+     # 'rating' represents how good the move is; higher is better.
+     dim r(4)
+     r(0)=-99       # Start with minimum score
+
+     # The board.  Pieces are represented by numeric values:
+     #
+     #      - 0     = empty square
+     #      - -1,-2 = X (-1 for regular piece, -2 for king)
+     #      - 1,2   = O (1 for regular piece, 2 for king)
+     #
+     # This program's player ("me") plays X.
+     dim s(7,7)
+
+     g=-1           # constant holding -1
+
+     # Initialize the board.  Data is 2 length-wise strips repeated.
+     data 1,0,1,0,0,0,-1,0,0,1,0,0,0,-1,0,-1,15
+     for x=0 to 7
+       for y=0 to 7
+         read j
+         if j=15 then 180
+         s(x,y)=j
+         goto 200
+180      restore
+         read s(x,y)
+200  next y,x
+
+230  # Start of game loop.  First, my turn.
+
+     # For each square on the board, search for one of my pieces
+     # and if it can make the best move so far, store that move in 'r'
+     for x=0 to 7
+       for y=0 to 7
+
+         # Skip if this is empty or an opponent's piece
+         if s(x,y) > -1 then 350
+
+         # If this is one of my ordinary pieces, analyze possible
+         # forward moves.
+         if s(x,y) = -1 then
+           for a=-1 to 1 step 2
+             b=g
+             gosub 650
+           next a
+         endif
+
+         # If this is one of my kings, analyze possible forward
+         # and backward moves.
+         if s(x,y) = -2 then
+           for a=-1 to 1 step 2
+             for b=-1 to 1 step 2
+               gosub 650
+           next b,a
+         endif
+
+350  next y,x
+     goto 1140  # Skip the subs
+
+
+     # Analyze a move from (x,y) to (x+a, y+b) and schedule it if it's
+     # the best candidate so far.
+650  Sub_Start
+       u=x+a
+       v=y+b
+
+       # Done if it's off the board
+       if u<0 or u>7 or v<0 or v>7 then 870
+
+       # Consider the destination if it's empty
+       if s(u,v) = 0 then
+         gosub 910
+         goto 870
+       endif
+
+       # If it's got an opponent's piece, jump it instead
+       if s(u,v) > 0
+
+           # Restore u and v, then return if it's off the board
+           u=u+a
+           v=v+b
+           if u<0 or v<0 or u>7 or v>7 then 870
+
+           # Otherwise, consider u,v
+           if s(u,v)=0 then gosub 910
+       endif           
+870  return
+
+     # Evaluate jumping (x,y) to (u,v).
+     #
+     # Computes a score for the proposed move and if it's higher
+     # than the best-so-far move, uses that instead by storing it
+     # and its score in array 'r'.
+910  Sub_Start
+
+       # q is the score; it starts at 0
+
+       # +2 if it promotes this piece
+       if v=0 and s(x,y)=-1 then q=q+2
+
+       # +5 if it takes an opponent's piece
+       if abs(y-v)=2 then q=q+5
+
+       # -2 if the piece is moving away from the top boundary
+       if y=7 then q=q-2
+
+       # +1 for putting the piece against a vertical boundary
+       if u=0 or u=7 then q=q+1
+
+       for c=-1 to 1 step 2
+         if u+c < 0 or u+c > 7 or v+g < 0 then 1080
+
+         # +1 for each adjacent friendly piece
+         if s(u+c, v+g) < 0 then
+           q=q+1
+           goto 1080
+         endif
+
+         # Prevent out-of-bounds testing
+         if u-c < 0 or u-c > 7 or v-g > 7 then 1080
+
+         # -2 for each opponent piece that can now take this piece here
+         if s(u+c,v+g) > 0 and(s(u-c,v-g)=0 or(u-c=x and v-g=y))then q=q-2
+1080   next c
+
+       # Use this move if it's better than the previous best
+       if q>r(0) then
+         r(0)=q
+         r(1)=x
+         r(2)=y
+         r(3)=u
+         r(4)=v
+       endif
+
+       q=0  # reset the score
+     return
+
+1140 if r(0)=-99 then 1880  # Game is lost if no move could be found.
+
+     # Print the computer's move.  (Note: chr$(30) is an ASCII RS
+     # (record separator) code; probably no longer relevant.)
+     print chr$(30)"FROM"r(1);r(2)"TO"r(3);r(4);
+     r(0)=-99
+
+     # Make the computer's move.  If the piece finds its way to the
+     # end of the board, crown it.
+1240 if r(4)=0 then
+       s(r(3),r(4))=-2
+       goto 1420
+     endif
+     s(r(3),r(4))=s(r(1),r(2))
+     s(r(1),r(2))=0
+
+     # If the piece has jumped 2 squares, it means the computer has
+     # taken an opponents' piece.
+     if abs(r(1)-r(3)) == 2 then
+       s((r(1)+r(3))/2,(r(2)+r(4))/2)=0     # Delete the opponent's piece
+
+       # See if we can jump again.  Evaluate all possible moves.
+       x=r(3)
+       y=r(4)
+       for a=-2 to 2 step 4
+         if s(x,y)=-1 then
+           b=-2
+           gosub 1370
+         endif
+         if s(x,y)=-2 then
+           for b=-2 to 2 step 4
+             gosub 1370
+           next b
+         endif
+       next a
+
+       # If we've found a move, go back and make that one as well
+       if r(0) <> -99 then
+         print "TO" r(3); r(4);
+         r(0)=-99
+         goto 1240
+       endif
+
+       goto 1420   # Skip the sub
+
+       # If (u,v) is in the bounds, evaluate it as a move using
+       # the sub at 910
+1370   Sub_Start
+         u=x+a
+         v=y+b
+         if u<0 or u>7 or v<0 or v>7 then 1400
+         if s(u,v)=0 and s(x+a/2,y+b/2)>0 then gosub 910
+1400   return
+
+1420 endif
+
+     # Now, print the board
+     print
+     print
+     print
+     for y=7 to 0 step-1
+       for x=0 to 7
+         i=5*x
+         print tab(i);
+         if s(x,y)=0 then print".";
+         if s(x,y)=1 then print"O";
+         if s(x,y)=-1 then print"X";
+         if s(x,y)=-2 then print"X*";
+         if s(x,y)=2 then print"O*";
+       next x
+       print" "
+       print
+     next y
+     print
+
+     # Check if either player is out of pieces.  If so, announce the
+     # winner.
+     for l=0 to 7
+       for m=0 to 7
+         if s(l,m)=1 or s(l,m)=2 then z=1
+         if s(l,m)=-1 or s(l,m)=-2 then t=1
+       next m
+     next l
+     if z<>1 then 1885
+     if t<>1 then 1880
+
+     # Prompt the player for their move.
+     z=0
+     t=0
+1590 input "FROM";e,h
+     x=e
+     y=h
+     if s(x,y)<=0 then 1590
+1670 input "TO";a,b
+     x=a
+     y=b
+     if s(x,y)=0 and abs(a-e)<=2 and abs(a-e)=abs(b-h)then 1700
+     print chr$(7)chr$(11);     # bell, vertical tab; invalid move
+     goto 1670
+
+1700 i=46       # Not used; probably a bug
+1750 loop
+       # Make the move and stop unless it might be a jump.
+       s(a,b) = s(e,h)
+       s(e,h) = 0
+       if abs(e-a) <> 2 then break
+
+       # Remove the piece jumped over
+       s((e+a)/2,(h+b)/2) = 0
+
+       # Prompt for another move; -1 means player can't, so I've won.
+       # Keep prompting until there's a valid move or the player gives
+       # up.
+1802   input "+TO";a1,b1
+       if a1 < 0 then break
+       if s(a1,b1) <> 0 or abs(a1-a) <>2  or abs(b1-b) <> 2 then 1802
+
+       # Update the move variables to correspond to the next jump
+       e=a
+       h=b
+       a=a1
+       b=b1
+
+       i=i+15   # Not used; probably a bug
+     endloop
+
+     # If the player has reached the end of the board, crown this piece
+1810 if b=7 then s(a,b)=2
+
+     # And play the next turn.
+     goto 230
+
+     # Endgame:
+1880 print
+     print "YOU WIN."
+     end
+
+1885 print
+     print "I WIN."
+     end
diff --git a/23 Checkers/ruby/README.md b/23 Checkers/ruby/README.md
index fb32811e..3b53879b 100644
--- a/23 Checkers/ruby/README.md	
+++ b/23 Checkers/ruby/README.md	
@@ -1,3 +1,8 @@
 Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
 
 Conversion to [Ruby](https://www.ruby-lang.org/en/)
+
+This version preserves the underlying algorithms and functionality of
+the original while using more modern programming constructs
+(functions, classes, symbols) and providing much more detailed
+comments.  It also fixes some (but not all) of the bugs.
diff --git a/23 Checkers/ruby/checkers.rb b/23 Checkers/ruby/checkers.rb
new file mode 100644
index 00000000..cac0ab06
--- /dev/null
+++ b/23 Checkers/ruby/checkers.rb	
@@ -0,0 +1,651 @@
+#!/usr/bin/env ruby
+
+# Checkers in Ruby, Version 1
+#
+# This version of the game attempts to preserve the underlying
+# algorithm(s) and feel of the BASIC version while using more modern
+# coding techniques.  Specifically:
+#
+# 1. The major data structures (the board and current move, known as S
+#    and R in the BASIC version) have been turned into classes.  In
+#    addition, I made a class for coordinates so that you don't always
+#    have to deal with pairs of numbers.
+#
+# 2. Much of the functionality associated with this data has been moved
+#    into methods of these classes in line with the philosophy that objects
+#    are smart data.
+#
+# 3. While I've kept the board as a single object (not global, though),
+#    this program will create many Move objects (i.e. copies of the move
+#    under consideration) rather than operating on a single global
+#    instance.
+#
+# 4. The rest of the code has been extracted into Ruby functions with
+#    all variables as local as reasonably possible.
+#
+# 5. Pieces are now represented with Symbols instead of integers; this
+#    made it *much* easier to understand what was going on.
+#
+# 6. There are various internal sanity checks.  They fail by throwing
+#    a string as an exception.  (This is generally frowned upon if
+#    you're going to catch the exception later but we never do that;
+#    an exception here means a bug in the software and the way to fix
+#    that is to fix the program.)
+#
+# And probably other stuff.
+#
+
+
+# Note: I've ordered the various major definitions here from (roughly)
+# general to specific so that if you read the code starting from the
+# beginning, you'll (hopefully) get a big-picture view first and then
+# get into details.  Normally, I'd order things by topic and define
+# things before using them, which is a better ordering.  So in this
+# case, do what I say and not what I do.
+
+
+#
+# Some global constants
+#
+
+BOARD_TEXT_INDENT = 30  # Number of spaces to indent the board when printing
+
+# Various constants related to the game of Checkers.
+#
+# (Yes, they're obvious but if you see BOARD_WIDTH, you know this is
+# related to board dimensions in a way that you wouldn't if you saw
+# '8'.)
+BOARD_WIDTH = 8
+KING_ROW_X = 0
+KING_ROW_Y = BOARD_WIDTH - 1
+
+
+
+# This is the mainline routine of the program.  Ruby doesn't require
+# that you put this in a function but this way, your local variables
+# are contained here.  It's also neater, IMO.
+#
+# The name 'main' isn't special; it's just a function.  The last line
+# of this program is a call to it.
+def main
+  print < move.from.y
+      return false if !is_me && move.to.y < move.from.y
+    end
+
+    # If jumping, that there's an opponent's piece between the start
+    # and end.
+    return false if
+      move.jump? &&
+      (empty_at?(move.midpoint) || opponent_at?(move.midpoint) != is_me)
+
+    # Otherwise, it's legal
+    return true
+  end
+
+  # Perform 'move' on the board.  'move' must be legal; the player
+  # performing it is determined by the move's starting ('from')
+  # position.
+  def make_move!(move)
+    piece = self[move.from]
+
+    # Sanity check
+    raise "Illegal move: #{move}" unless legal_move?(piece.downcase == :x,move)
+
+    # Promote the piece if it's reached the end row
+    piece = piece.upcase if
+      (piece == :x && move.to.y == KING_ROW_X) ||
+      (piece == :o && move.to.y == KING_ROW_Y)
+
+    # And do the move
+    self[move.to] = piece
+    self[move.from] = :_
+
+    # Remove the piece jumped over if this is a jump
+    self[move.midpoint] = :_ if move.jump?
+  end
+
+
+  # Return the best (i.e. likely to win) move possible for the
+  # piece (mine) at 'coord'.
+  def bestMoveFrom(coord, mustJump)
+    so_far = Move.invalid
+    return so_far unless coord.valid?
+
+    offsets = [ [-1, -1], [1, -1]]
+    offsets += [ [-1, 1], [1, 1]] if king_at?(coord)
+
+    for ofx, ofy in offsets
+      new_coord = coord.by(ofx, ofy)
+
+      if opponent_at?(new_coord)
+        new_coord = new_coord.by(ofx, ofy)
+      elsif mustJump
+        next
+      end
+
+      next unless new_coord.valid?
+
+      so_far = so_far.betterOf( ratedMove(coord, new_coord) )
+    end
+
+    return so_far
+  end
+
+
+  # Create and return a move for *me* from Coords 'from' to 'to' with
+  # its 'rating' set to how good the move looks according to criteria
+  # used by the BASIC version of this program.  If the move is
+  # illegal, returns an invalid Move object.
+  def ratedMove(from, to)
+    return Move.invalid unless legal_move?(true, Move.new(from, to))
+
+    rating = 0
+
+    # +2 if it promotes this piece
+    rating += 2 if to.y == 0
+
+    # +50 if it takes the opponent's piece.  (Captures are mandatory
+    # so we ensure that a capture will always outrank a non-capture.)
+    rating += 4 if (from.y - to.y).abs == 2
+
+    # -2 if we're moving away from the king row
+    rating -= 2 if from.y == BOARD_WIDTH - 1
+
+    # +1 for putting the piece against a vertical boundary
+    rating += 1 if to.x == 0 || to.x == BOARD_WIDTH - 1
+
+    # +1 for each friendly piece behind this one
+    [-1, 1].each {|c|
+      rating += 1 if mine_at?( to.by(c, -1) )
+    }
+
+    # -2 for each opponent's piece that can now capture this one.
+    # (This includes a piece that may be captured when moving here;
+    # this is a bug.)
+    [ -1, 1].each {|c|
+      there = to.by(c, -1)
+      opposite = to.by(-c, 1)
+      rating -= 2 if
+        opponent_at?(there) && (empty_at?(opposite) || opposite == from)
+    }
+
+    return Move.new(from, to, rating)
+  end
+end
+
+
+# Class to hold the X and Y coordinates of a position on the board.
+#
+# Coord objects are immutable--that is, they never change after
+# creation.  Instead, you will always get a modified copy back.
+class Coord
+
+  # Coordinates are readable
+  attr_reader :x, :y
+
+  # Initialize
+  def initialize(x, y)
+    @x, @y = [x,y]
+  end
+
+  # Test if this move is on the board.
+  def valid?
+    return x >= 0 && y >= 0 && x < BOARD_WIDTH && y < BOARD_WIDTH
+  end
+
+  # Test if this Coord is equal to another Coord.
+  def ==(other)
+    return other.class == self.class && other.x == @x && other.y == y
+  end
+
+  # Return a string that describes this Coord in a human-friendly way.
+  def to_s
+    return "(#{@x},#{@y})"
+  end
+
+  # Return a new Coord whose x and y coordinates have been adjusted by
+  # arguments 'x' and 'y'.
+  def by(x, y)
+    return Coord.new(@x + x, @y + y)
+  end
+end
+
+
+# Class to represent a move by a player between two positions,
+# possibly with a rating that can be used to select the best of a
+# collection of moves.
+#
+# An (intentionally) invalid move will have a value of nil for both
+# 'from' and 'to'.  Most methods other than 'valid?' assume the Move
+# is valid.
+class Move
+  # Readable fields:
+  attr_reader :from, :to, :rating
+
+  # The initializer; -99 is the lowest rating from the BASIC version
+  # so we use that here as well.
+  def initialize(from, to, rating = -99)
+    @from, @to, @rating = [from, to, rating]
+
+    # Sanity check; the only invalid Move tolerated is the official
+    # one (i.e. with nil for each endpoint.)
+    raise "Malformed Move: #{self}" if @from && @to && !valid?
+  end
+
+  # Return an invalid Move object.
+  def self.invalid
+    return self.new(nil, nil, -99)
+  end
+
+  # Return true if this is a valid move (i.e. as close to legal as we
+  # can determine without seeing the board.)
+  def valid?
+    # Not valid if @from or @to is nil
+    return false unless @from && @to
+
+    # Not valid unless both endpoints are on the board
+    return false unless @from.valid? && @to.valid?
+
+    # Not valid unless it's a diagonal move by 1 or 2 squares
+    dx, dy = delta
+    return false if dx.abs != dy.abs || (dx.abs != 1 && dx.abs != 2)
+
+    # Otherwise, valid
+    return true
+  end
+
+  # Return true if this move is a jump, false otherwise
+  def jump?
+    return valid? && magnitude() == 2
+  end
+
+  # Return the coordinates of the piece being jumped over by this
+  # move.
+  def midpoint
+    raise "Called 'midpoint' on a non-jump move!" unless jump?
+    dx, dy = delta
+    return @from.by(dx / dx.abs, dy / dy.abs)
+  end
+
+  # Return the better-rated of self or otherMove.
+  def betterOf(otherMove)
+    return otherMove if !valid?
+    return rating > otherMove.rating ? self : otherMove
+  end
+
+  # Return a human-friendly string representing this move.
+  def to_s
+    return "[NOMOVE]" if !@from && !@to     # Well-known invalid move
+
+    jumpover = jump? ?
+                 "-> #{midpoint} ->"
+               : "->"
+
+    return "#{@from} #{jumpover} #{to}#{valid? ? '' : ' [INVALID]'}"
+  end
+
+  private
+
+  # Return the distance (x, y) between the 'from' and 'to' locations.
+  def delta
+    return [to.x - from.x, to.y - from.y]
+  end
+
+  # Return the number of squares this move will take the piece (either
+  # 1 or 2).
+  def magnitude
+    # Note: we assume that this move is a legal move (and therefore
+    # diagonal); otherwise, this may not be correct.
+    return (to.x - from.x).abs
+  end
+end
+
+
+
+# Start the game
+main()

From e7078460917963bea1a780e50fe687e46d62ec59 Mon Sep 17 00:00:00 2001
From: Todd Kaiser 
Date: Sat, 13 Mar 2021 16:17:49 -0700
Subject: [PATCH 291/749] Copied functions from Jupyter notebook to salvo.py.
 Started adding interactive player interface.

---
 77 Salvo/python/salvo.ipynb |  55 ++++---
 77 Salvo/python/salvo.py    | 279 +++++++++++++++++++++++++++++++-----
 2 files changed, 273 insertions(+), 61 deletions(-)

diff --git a/77 Salvo/python/salvo.ipynb b/77 Salvo/python/salvo.ipynb
index 0c8287af..7b98691b 100644
--- a/77 Salvo/python/salvo.ipynb	
+++ b/77 Salvo/python/salvo.ipynb	
@@ -24,7 +24,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 715,
+   "execution_count": 727,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 716,
+   "execution_count": 728,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -57,7 +57,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 717,
+   "execution_count": 729,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -80,14 +80,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 718,
+   "execution_count": 730,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
      "text": [
-      "8 4\n"
+      "5 3\n"
      ]
     }
    ],
@@ -98,7 +98,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 719,
+   "execution_count": 731,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -155,14 +155,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 720,
+   "execution_count": 732,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
      "text": [
-      "BATTLESHIP       5 [(9, 2), (8, 3), (7, 4), (6, 5), (5, 6)]\nCRUISER          3 [(3, 8), (2, 9), (1, 10)]\nDESTROYER     2 [(3, 5), (3, 6)]\nDESTROYER     2 [(6, 5), (7, 4)]\n"
+      "BATTLESHIP       5 [(10, 2), (10, 3), (10, 4), (10, 5), (10, 6)]\nCRUISER          3 [(9, 4), (8, 4), (7, 4)]\nDESTROYER     2 [(2, 5), (1, 5)]\nDESTROYER     2 [(7, 8), (7, 9)]\n"
      ]
     }
    ],
@@ -175,7 +175,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 721,
+   "execution_count": 733,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -186,7 +186,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 722,
+   "execution_count": 734,
    "metadata": {},
    "outputs": [
     {
@@ -221,7 +221,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 723,
+   "execution_count": 735,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -232,25 +232,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 724,
+   "execution_count": 736,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
      "text": [
-      "DESTROYER     2 [(1, 7), (2, 6), (3, 5), (4, 4), (5, 3)]\n",
-      "    1  2  3  4  5  6  7  8  9 10\n",
-      " 1                    0         \n",
-      " 2                 0            \n",
-      " 3              0               \n",
-      " 4           0                  \n",
-      " 5        0                     \n",
-      " 6                              \n",
-      " 7                              \n",
-      " 8                              \n",
-      " 9                              \n",
-      "10                              \n"
+      "DESTROYER     2 [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]\n    1  2  3  4  5  6  7  8  9 10\n 1     0                        \n 2        0                     \n 3           0                  \n 4              0               \n 5                 0            \n 6                              \n 7                              \n 8                              \n 9                              \n10                              \n"
      ]
     }
    ],
@@ -265,14 +254,24 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 725,
+   "execution_count": 737,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
      "text": [
-      "    1  2  3  4  5  6  7  8  9 10\n 1           1           0      \n 2        1           0         \n 3     1           0            \n 4              0               \n 5        2  0                  \n 6     2                        \n 7                 3  3         \n 8                              \n 9                              \n10                              \n"
+      "    1  2  3  4  5  6  7  8  9 10\n",
+      " 1                              \n",
+      " 2              1               \n",
+      " 3                 1  2         \n",
+      " 4                    1  2      \n",
+      " 5  0                           \n",
+      " 6     0                        \n",
+      " 7        0                     \n",
+      " 8           0                  \n",
+      " 9              0           3   \n",
+      "10                       3      \n"
      ]
     }
    ],
@@ -305,14 +304,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 726,
+   "execution_count": 738,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
      "text": [
-      "[(4, 4), (2, 8), (10, 6), (2, 4), (10, 7)]\n"
+      "[(4, 1), (3, 6), (6, 10), (10, 6), (4, 5)]\n"
      ]
     }
    ],
diff --git a/77 Salvo/python/salvo.py b/77 Salvo/python/salvo.py
index 3d36dcbd..2061943d 100644
--- a/77 Salvo/python/salvo.py	
+++ b/77 Salvo/python/salvo.py	
@@ -1,6 +1,12 @@
 import re
+import random
+
+###################
+#
+# static variables
+#
+###################
 
-# declare static variables
 BOARD_WIDTH = 10
 BOARD_HEIGHT = 10
 
@@ -9,17 +15,64 @@ SHIPS = [("BATTLESHIP", 5),
          ("DESTROYER", 2),
          ("DESTROYER", 2)]
 
-VALID_MOVES = [[-1, 0],
-               [-1, 1],
-               [0, 1],
-               [1, 1],
-               [1, 0],
-               [1, -1],
-               [0, -1],
-               [1, -1]]
+VALID_MOVES = [[-1, 0],   # North
+               [-1, 1],   # North East
+               [0, 1],    # East
+               [1, 1],    # South East
+               [1, 0],    # South
+               [1, -1],   # South West
+               [0, -1],   # West
+               [-1, -1]]  # North West
 
 COORD_REGEX = '[ \t]{0,}(-?[0-9]{1,3})[ \t]{0,},[ \t]{0,}(-?[0-9]{1,2})'
 
+####################
+#
+# global variables
+#
+####################
+
+# array of BOARD_HEIGHT arrays, BOARD_WIDTH in length,
+# representing the human player and computer
+player_board = []
+computer_board = []
+
+# array representing the coordinates
+# for each ship for player and computer
+# array is in the same order as SHIPS
+player_ship_coords = []
+computer_ship_coords = []
+
+# keep track of the turn
+current_turn = 0
+
+# flag indicating if computer's shots are
+# printed out during computer's turn
+print_computer_shots = False
+
+####################
+#
+# game functions
+#
+####################
+
+# random number functions
+#
+# seed the random number generator
+random.seed()
+
+
+# random_x_y
+#
+# generate a valid x,y coordinate on the board
+# returns: x,y
+#   x: integer between 1 and BOARD_HEIGHT
+#   y: integer between 1 and BOARD WIDTH
+def random_x_y():
+    x = random.randrange(1, BOARD_WIDTH+1)
+    y = random.randrange(1, BOARD_HEIGHT+1)
+    return (x, y)
+
 
 # input_coord
 #
@@ -51,32 +104,192 @@ def input_coord():
     return x, y
 
 
-# input_ship_coords
-#
-# ask the user for coordinates for each
-# ship on their board. uses input_coord()
-# to read each coord.
-# returns an array of arrays, one array for
-# each ship's coordinates, which is an array 
-# of (x,y) sets.
-def input_ship_coords():
-    print("ENTER COORDINATES FOR...")
+# TODO: add an optional starting coordinate for testing
+#       purposes
+def generate_ship_coordinates(ship):
+    # randomly generate starting x,y coordinates
+    start_x, start_y = random_x_y()
 
-    coords = []
-    for ship in SHIPS:
-        print(ship[0])
-        list = []
-        for i in range(ship[1]):
-            x, y = input_coord()
-            list.append((x, y))
-        coords.append(list)
+    # using starting coordinates and the ship type,
+    # generate a vector of possible directions the ship
+    # could be placed. directions are numbered 0-7 along
+    # points of the compass (N, NE, E, SE, S, SW, W, NW)
+    # clockwise. a vector of valid directions where the
+    # ship does not go off the board is determined
+    ship_len = SHIPS[ship][1] - 1
+    dirs = [False for x in range(8)]
+    dirs[0] = (start_x - ship_len) >= 1
+    dirs[2] = (start_y + ship_len) <= BOARD_WIDTH
+    dirs[1] = dirs[0] and dirs[2]
+    dirs[4] = (start_x + ship_len) <= BOARD_HEIGHT
+    dirs[3] = dirs[2] and dirs[4]
+    dirs[6] = (start_y - ship_len) >= 1
+    dirs[5] = dirs[4] and dirs[6]
+    dirs[7] = dirs[6] and dirs[0]
+    directions = [p for p in range(len(dirs)) if dirs[p]]
+
+    # using the vector of valid directions, pick a
+    # random direction to place the ship
+    dir_idx = random.randrange(len(directions))
+    direction = directions[dir_idx]
+
+    # using the starting x,y, direction and ship
+    # type, return the coordinates of each point
+    # of the ship. VALID_MOVES is a staic array
+    # of coordinate offsets to walk from starting
+    # coordinate to the end coordinate in the
+    # chosen direction
+    ship_len = SHIPS[ship][1] - 1
+    d_x = VALID_MOVES[direction][0]
+    d_y = VALID_MOVES[direction][1]
+
+    coords = [(start_x, start_y)]
+    x_coord = start_x
+    y_coord = start_y
+    for i in range(ship_len):
+        x_coord = x_coord + d_x
+        y_coord = y_coord + d_y
+        coords.append((x_coord, y_coord))
     return coords
 
 
-# print out the title 'screen'
-print('{0:>38}'.format("SALVO"))
-print('{0:>57s}'.format("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"))
-print('\n\n')
+# create_blank_board
+#
+# helper function to create a game board
+# that is blank
+def create_blank_board():
+    return [[None for y in range(BOARD_WIDTH)]
+            for x in range(BOARD_HEIGHT)]
+
+
+def print_board(board):
+
+    # print board header (column numbers)
+    print('  ', end='')
+    for z in range(BOARD_WIDTH):
+        print(f'{z+1:3}', end='')
+    print('')
+
+    for x in range(len(board)):
+        print(f'{x+1:2}', end='')
+        for y in range(len(board[x])):
+            if(board[x][y] is None):
+                print(f"{' ':3}", end='')
+            else:
+                print(f"{board[x][y]:3}", end='')
+        print('')
+
+
+# place_ship
+#
+# place a ship on a given board. updates
+# the board's row,column value at the given
+# coordinates to indicate where a ship is
+# on the board.
+#
+# inputs: board - array of BOARD_HEIGHT by BOARD_WIDTH
+#         coords - array of sets of (x,y) coordinates of each
+#                  part of the given ship
+#         ship - integer repreesnting the type of ship (given in SHIPS)
+def place_ship(board, coords, ship):
+    for coord in coords:
+        board[coord[0]-1][coord[1]-1] = ship
+
+
+# NOTE: A little quirk that exists here and in the orginal
+#       game: Ships are allowed to cross each other!
+#       For example: 2 destroyers, length 2, one at
+#       [(1,1),(2,2)] and other at [(2,1),(1,2)]
+def generate_board():
+    board = create_blank_board()
+
+    ship_coords = []
+    for ship in range(len(SHIPS)):
+        placed = False
+        coords = []
+        while not placed:
+            coords = generate_ship_coordinates(ship)
+            clear = True
+            for coord in coords:
+                if board[coord[0]-1][coord[1]-1] is not None:
+                    clear = False
+                    break
+            if clear:
+                placed = True
+        place_ship(board, coords, ship)
+        ship_coords.append(coords)
+    return board, ship_coords
+
+
+# initialize
+#
+# function to initialize global variables used
+# during game play.
+def initialize_game():
+
+    # initialize the global player and computer
+    # boards
+    global player_board
+    player_board = create_blank_board()
+
+    # generate the ships for the computer's
+    # board
+    global computer_board
+    global computer_ship_coords
+    computer_board, computer_ship_coords = generate_board()
+
+    # print out the title 'screen'
+    print('{0:>38}'.format("SALVO"))
+    print('{0:>57s}'.format("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"))
+    print('\n\n')
+
+
+######################
+#
+# main game flow
+#
+######################
+
+# initialize the player and computer
+# boards
+initialize_game()
+
+# ask the player for ship coordinates
+print("ENTER COORDINATES FOR...")
+ship_coords = []
+for ship in SHIPS:
+    print(ship[0])
+    list = []
+    for i in range(ship[1]):
+        x, y = input_coord()
+        list.append((x, y))
+    ship_coords.append(list)
+
+# add ships to the user's board
+for ship in range(len(SHIPS)):
+    place_ship(player_board, ship_coords[ship], ship)
+
+# see if the player wants the computer's ship
+# locations printed out and if the player wants to
+# start
+input_loop = True
+player_start = "YES"
+while input_loop:
+    player_start = input("DO YOU WANT TO START? ")
+    if player_start == "WHERE ARE YOUR SHIPS?":
+        for ship in range(len(SHIPS)):
+            print(SHIPS[ship][0])
+            coords = computer_ship_coords[ship]
+            for coord in coords:
+                x = coord[0]
+                y = coord[1]
+                print('{0:2}'.format(x), '{0:2}'.format(y))
+    else:
+        input_loop = False
+
+# ask the player if they want the computer's shots
+# printed out each turn
+see_computer_shots = input("DO YOU WANT TO SEE MY SHOTS? ")
+if see_computer_shots.lower() == "yes":
+    print_computer_shots = True
 
-# ask the user for ship coordinates
-coords = input_ship_coords()

From 1726f79336bc429cb224c3b18b3916bfa4cbddb2 Mon Sep 17 00:00:00 2001
From: John Welch 
Date: Sat, 13 Mar 2021 23:46:49 +0000
Subject: [PATCH 292/749] CivilWar in C#

---
 27 Civil War/civilwar.bas                     |   4 +-
 27 Civil War/csharp/CivilWar/CivilWar.sln     |  25 ++
 27 Civil War/csharp/CivilWar/CivilWar/Army.cs | 261 ++++++++++++++++++
 .../csharp/CivilWar/CivilWar/Battle.cs        |  40 +++
 .../csharp/CivilWar/CivilWar/CivilWar.csproj  |   9 +
 .../csharp/CivilWar/CivilWar/ConsoleUtils.cs  | 105 +++++++
 .../csharp/CivilWar/CivilWar/GameOptions.cs   |  55 ++++
 .../csharp/CivilWar/CivilWar/Program.cs       | 119 ++++++++
 8 files changed, 616 insertions(+), 2 deletions(-)
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar.sln
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar/Army.cs
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar/Battle.cs
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar/CivilWar.csproj
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar/ConsoleUtils.cs
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar/GameOptions.cs
 create mode 100644 27 Civil War/csharp/CivilWar/CivilWar/Program.cs

diff --git a/27 Civil War/civilwar.bas b/27 Civil War/civilwar.bas
index 5720d767..7f192414 100644
--- a/27 Civil War/civilwar.bas	
+++ b/27 Civil War/civilwar.bas	
@@ -221,7 +221,7 @@
 2330  PRINT "CONFEDERATE:"INT(100*(C5/C1)+.5)"% OF THE ORIGINAL"
 2340  PRINT "UNION:      "INT(100*(C6/C2)+.5)"% OF THE ORIGINAL"
 2350  PRINT
-2360  REM - 1 WHO ONE
+2360  REM - 1 WHO WON
 2370  IF U <> 1 THEN 2380
 2375  IF U2=1 THEN 2460
 2380  IF U=1 THEN 2420
@@ -295,7 +295,7 @@
 3050  PRINT
 3060  PRINT "UNION INTELLIGENCE SUGGESTS THAT THE SOUTH USED "
 3070  PRINT "STRATEGIES 1, 2, 3, 4 IN THE FOLLOWING PERCENTAGES"
-3080  PRINT S(1);S2(2);S(3);S(4)
+3080  PRINT S(1);S(2);S(3);S(4)
 3090  REM---------------------------------
 3100  STOP
 3110  REM - UNION STRATEGY IS COMPUTER CHOSEN
diff --git a/27 Civil War/csharp/CivilWar/CivilWar.sln b/27 Civil War/csharp/CivilWar/CivilWar.sln
new file mode 100644
index 00000000..17da385e
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar.sln	
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CivilWar", "CivilWar\CivilWar.csproj", "{09C22BBE-8480-4B8C-9A07-E2DAA24B692B}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{09C22BBE-8480-4B8C-9A07-E2DAA24B692B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{09C22BBE-8480-4B8C-9A07-E2DAA24B692B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{09C22BBE-8480-4B8C-9A07-E2DAA24B692B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{09C22BBE-8480-4B8C-9A07-E2DAA24B692B}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {59BCA2DE-D5C7-40F7-BB99-B5C8D2416D8B}
+	EndGlobalSection
+EndGlobal
diff --git a/27 Civil War/csharp/CivilWar/CivilWar/Army.cs b/27 Civil War/csharp/CivilWar/CivilWar/Army.cs
new file mode 100644
index 00000000..5b8441a0
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar/Army.cs	
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace CivilWar
+{
+    public class Army
+    {
+        private enum Resource
+        {
+            Food,
+            Salaries,
+            Ammunition
+        }
+
+        public Army(Side side)
+        {
+            Side = side;
+        }
+
+        public Side Side { get; }
+
+        // Cumulative
+        public int Wins { get; private set; } // W, L
+        public int Losses { get; private set; } // L, W
+        public int Draws { get; private set; } // W0
+        public int BattlesFought => Wins + Draws + Losses;
+        public bool Surrendered { get; private set; } // Y, Y2 == 5
+
+        public int CumulativeHistoricCasualties { get; private set; } // P1, P2
+        public int CumulativeSimulatedCasualties { get; private set; } // T1, T2
+        public int CumulativeHistoricMen { get; private set; } // M3, M4
+
+        private int income; // R1, R2
+        private int moneySpent; // Q1, Q2
+
+        private bool IsFirstBattle => income == 0;
+
+        // This battle
+        private int historicMen; // M1, M2
+        public int HistoricCasualties { get; private set; }
+
+        public int Money { get; private set; } // D(n)
+        public int Men { get; private set; } // M5, M6
+        public int Inflation { get; private set; } // I1, I2
+        public int InflationDisplay => Side == Side.Confederate ? Inflation + 15 : Inflation; // Confederate inflation is shown with 15 added - no idea why!
+
+        private readonly Dictionary allocations = new(); // F(n), H(n), B(n) for food, salaries, ammunition
+
+        public int Strategy { get; protected set; } // Y1, Y2
+
+        public double Morale => (2.0 * allocations[Resource.Food] * allocations[Resource.Food] + allocations[Resource.Salaries] * allocations[Resource.Salaries]) / (reducedAvailableMen * reducedAvailableMen + 1); // O, O2
+
+        public int Casualties { get; protected set; } // C5, C6
+        public int Desertions { get; protected set; } // E, E2
+        public int MenLost => Casualties + Desertions;
+        public bool AllLost { get; private set; } // U, U2
+
+        private double reducedAvailableMen; // F1
+
+        protected virtual double FractionUnspent => (income - moneySpent) / (income + 1.0);
+
+        public void PrepareBattle(int men, int casualties)
+        {
+            historicMen = men;
+            HistoricCasualties = casualties;
+            Inflation = 10 + (Losses - Wins) * 2;
+            Money = 100 * (int)(men * (100 - Inflation) / 2000.0 * (1 + FractionUnspent) + 0.5);
+            Men = (int)(men * 1 + (CumulativeHistoricCasualties - CumulativeSimulatedCasualties) / (CumulativeHistoricMen + 1.0));
+            reducedAvailableMen = men * 5.0 / 6.0;
+        }
+
+        public virtual void AllocateResources()
+        {
+            Console.WriteLine($"{Side} General ---\nHow much do you wish to spend for");
+            while (true)
+            {
+                foreach (Resource resource in Enum.GetValues())
+                {
+                    if (EnterResource(resource))
+                        break;
+                }
+                if (allocations.Values.Sum() <= Money)
+                    return;
+                Console.WriteLine($"Think again! You have only ${Money}");
+            }
+        }
+
+        private bool EnterResource(Resource resource)
+        {
+            while (true)
+            {
+                Console.WriteLine($" - {resource}");
+                switch ((int.TryParse(Console.ReadLine(), out int val), val))
+                {
+                    case (false, _):
+                        Console.WriteLine("Not a valid number");
+                        break;
+                    case (_, < 0):
+                        Console.WriteLine("Negative values not allowed");
+                        break;
+                    case (_, 0) when IsFirstBattle:
+                        Console.WriteLine("No previous entries");
+                        break;
+                    case (_, 0):
+                        Console.WriteLine("Assume you want to keep same allocations");
+                        return true;
+                    case (_, > 0):
+                        allocations[resource] = val;
+                        return false;
+                }
+            }
+        }
+
+        public virtual void DisplayMorale()
+        {
+            Console.WriteLine($"{Side} morale is {Morale switch { < 5 => "Poor", < 10 => "Fair", _ => "High" }}");
+        }
+
+        public virtual bool ChooseStrategy(bool isReplay) => EnterStrategy(true, "(1-5)");
+
+        protected bool EnterStrategy(bool canSurrender, string hint)
+        {
+            Console.WriteLine($"{Side} strategy {hint}");
+            while (true)
+            {
+                switch ((int.TryParse(Console.ReadLine(), out int val), val))
+                {
+                    case (false, _):
+                        Console.WriteLine("Not a valid number");
+                        break;
+                    case (_, 5) when canSurrender:
+                        Surrendered = true;
+                        Console.WriteLine($"The {Side} general has surrendered");
+                        return true;
+                    case (_, < 1 or >= 5):
+                        Console.WriteLine($"Strategy {val} not allowed.");
+                        break;
+                    default:
+                        Strategy = val;
+                        return false;
+                }
+            }
+        }
+
+        public virtual void CalculateLosses(Army opponent)
+        {
+            AllLost = false;
+            int stratFactor = 2 * (Math.Abs(Strategy - opponent.Strategy) + 1);
+            Casualties = (int)Math.Round(HistoricCasualties * 0.4 * (1 + 1.0 / stratFactor) * (1 + 1 / Morale) * (1.28 + reducedAvailableMen / (allocations[Resource.Ammunition] + 1)));
+            Desertions = (int)Math.Round(100 / Morale);
+
+            // If losses > men present, rescale losses
+            if (MenLost > Men)
+            {
+                Casualties = 13 * Men / 20;
+                Desertions = Men - Casualties;
+                AllLost = true;
+            }
+        }
+
+        public void RecordResult(Side winner)
+        {
+            if (winner == Side)
+                Wins++;
+            else if (winner == Side.Both)
+                Draws++;
+            else
+                Losses++;
+
+            CumulativeSimulatedCasualties += MenLost;
+            CumulativeHistoricCasualties += HistoricCasualties;
+            moneySpent += allocations.Values.Sum();
+            income += historicMen * (100 - Inflation) / 20;
+            CumulativeHistoricMen += historicMen;
+
+            LearnStrategy();
+        }
+
+        protected virtual void LearnStrategy() { }
+
+        public void DisplayWarResult(Army opponent)
+        {
+            Console.WriteLine("\n\n\n\n");
+            Console.WriteLine($"The {Side} general has won {Wins} battles and lost {Losses}");
+            Side winner = (Surrendered, opponent.Surrendered, Wins < Losses) switch
+            {
+                (_, true, _) => Side,
+                (true, _, _) or (_, _, true) => opponent.Side,
+                _ => Side
+            };
+            Console.WriteLine($"The {winner} general has won the war\n");
+        }
+
+        public virtual void DisplayStrategies() { }
+    }
+
+    class ComputerArmy : Army
+    {
+        public int[] StrategyProb { get; } = { 25, 25, 25, 25 }; // S(n)
+        private readonly Random strategyRng = new();
+
+        public ComputerArmy(Side side) : base(side) { }
+
+        protected override double FractionUnspent => 0.0;
+
+        public override void AllocateResources() { }
+
+        public override void DisplayMorale() { }
+
+        public override bool ChooseStrategy(bool isReplay)
+        {
+            if (isReplay)
+                return EnterStrategy(false, $"(1-4; usually previous {Side} strategy)");
+
+            // Basic code comments say "If actual strategy info is in  data then r-100 is extra weight given to that strategy" but there's no data or code to do it.
+            int strategyChosenProb = strategyRng.Next(100); // 0-99
+            int sumProbs = 0;
+            for (int i = 0; i < 4; i++)
+            {
+                sumProbs += StrategyProb[i];
+                if (strategyChosenProb < sumProbs)
+                {
+                    Strategy = i + 1;
+                    break;
+                }
+            }
+            Console.WriteLine($"{Side} strategy is {Strategy}");
+            return false;
+        }
+
+        protected override void LearnStrategy()
+        {
+            // Learn  present strategy, start forgetting old ones
+            // - present strategy gains 3 * s, others lose s probability points, unless a strategy falls below 5 %.
+            const int s = 3;
+            int presentGain = 0;
+            for (int i = 0; i < 4; i++)
+            {
+                if (StrategyProb[i] >= 5)
+                {
+                    StrategyProb[i] -= s;
+                    presentGain += s;
+                }
+            }
+            StrategyProb[Strategy - 1] += presentGain;
+        }
+
+        public override void CalculateLosses(Army opponent)
+        {
+            Casualties = (int)(17.0 * HistoricCasualties * opponent.HistoricCasualties / (opponent.Casualties * 20));
+            Desertions = (int)(5 * opponent.Morale);
+        }
+
+        public override void DisplayStrategies()
+        {
+            ConsoleUtils.WriteWordWrap($"\nIntelligence suggests that the {Side} general used strategies 1, 2, 3, 4 in the following percentages:");
+            Console.WriteLine(string.Join(", ", StrategyProb));
+        }
+    }
+}
diff --git a/27 Civil War/csharp/CivilWar/CivilWar/Battle.cs b/27 Civil War/csharp/CivilWar/CivilWar/Battle.cs
new file mode 100644
index 00000000..8b5acb79
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar/Battle.cs	
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+
+namespace CivilWar
+{
+    public enum Side { Confederate, Union, Both }
+    public enum Option { Battle, Replay, Quit }
+
+    public record Battle(string Name, int[] Men, int[] Casualties, Side Offensive, string Description)
+    {
+        public static readonly List Historic = new()
+        {
+            new("Bull Run", new[] { 18000, 18500 }, new[] { 1967, 2708 }, Side.Union, "July 21, 1861.  Gen. Beauregard, commanding the south, met Union forces with Gen. McDowell in a premature battle at Bull Run. Gen. Jackson helped push back the union attack."),
+            new("Shiloh", new[] { 40000, 44894 }, new[] { 10699, 13047 }, Side.Both, "April 6-7, 1862.  The confederate surprise attack at Shiloh failed due to poor organization."),
+            new("Seven Days", new[] { 95000, 115000 }, new[] { 20614, 15849 }, Side.Both, "June 25-july 1, 1862.  General Lee (csa) upheld the offensive throughout the battle and forced Gen. McClellan and the union forces away from Richmond."),
+            new("Second Bull Run", new[] { 54000, 63000 }, new[] { 10000, 14000 }, Side.Confederate, "Aug 29-30, 1862.  The combined confederate forces under Lee and Jackson drove the union forces back into Washington."),
+            new("Antietam", new[] { 40000, 50000 }, new[] { 10000, 12000 }, Side.Both, "Sept 17, 1862.  The south failed to incorporate Maryland into the confederacy."),
+            new("Fredericksburg", new[] { 75000, 120000 }, new[] { 5377, 12653 }, Side.Union, "Dec 13, 1862.  The confederacy under Lee successfully repulsed an attack by the union under Gen. Burnside."),
+            new("Murfreesboro", new[] { 38000, 45000 }, new[] { 11000, 12000 }, Side.Union, "Dec 31, 1862.  The south under Gen. Bragg won a close battle."),
+            new("Chancellorsville", new[] { 32000, 90000 }, new[] { 13000, 17197 }, Side.Confederate, "May 1-6, 1863.  The south had a costly victory and lost one of their outstanding generals, 'stonewall' Jackson."),
+            new("Vicksburg", new[] { 50000, 70000 }, new[] { 12000, 19000 }, Side.Union, "July 4, 1863.  Vicksburg was a costly defeat for the south because it gave the union access to the Mississippi."),
+            new("Gettysburg", new[] { 72500, 85000 }, new[] { 20000, 23000 }, Side.Both, "July 1-3, 1863.  A southern mistake by Gen. Lee at Gettysburg cost them one of the most crucial battles of the war."),
+            new("Chickamauga", new[] { 66000, 60000 }, new[] { 18000, 16000 }, Side.Confederate, "Sept. 15, 1863. Confusion in a forest near Chickamauga led to a costly southern victory."),
+            new("Chattanooga", new[] { 37000, 60000 }, new[] { 36700, 5800 }, Side.Confederate, "Nov. 25, 1863. After the south had sieged Gen. Rosencrans’ army for three months, Gen. Grant broke the siege."),
+            new("Spotsylvania", new[] { 62000, 110000 }, new[] { 17723, 18000 }, Side.Confederate, "May 5, 1864.  Grant's plan to keep Lee isolated began to fail here, and continued at Cold Harbor and Petersburg."),
+            new("Atlanta", new[] { 65000, 100000 }, new[] { 8500, 3700 }, Side.Union, "August, 1864.  Sherman and three veteran armies converged on Atlanta and dealt the death blow to the confederacy."),
+        };
+
+        public static (Option, Battle?) SelectBattle()
+        {
+            Console.WriteLine("\n\n\nWhich battle do you wish to simulate?");
+            return int.Parse(Console.ReadLine() ?? "") switch
+            {
+                0 => (Option.Replay, null),
+                >0 and <15 and int n  => (Option.Battle, Historic[n-1]),
+                _ => (Option.Quit, null)
+            };
+        }
+    }
+}
diff --git a/27 Civil War/csharp/CivilWar/CivilWar/CivilWar.csproj b/27 Civil War/csharp/CivilWar/CivilWar/CivilWar.csproj
new file mode 100644
index 00000000..d75be916
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar/CivilWar.csproj	
@@ -0,0 +1,9 @@
+
+
+  
+    Exe
+    net5.0
+    enable
+  
+
+
diff --git a/27 Civil War/csharp/CivilWar/CivilWar/ConsoleUtils.cs b/27 Civil War/csharp/CivilWar/CivilWar/ConsoleUtils.cs
new file mode 100644
index 00000000..5c5c9f05
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar/ConsoleUtils.cs	
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CivilWar
+{
+    static class ConsoleUtils
+    {
+        public static bool InputYesOrNo()
+        {
+            while (true)
+            {
+                var answer = Console.ReadLine();
+                switch (answer?.ToLower())
+                {
+                    case "no":
+                        return false;
+                    case "yes":
+                        return true;
+                    default:
+                        Console.WriteLine("(Answer Yes or No)");
+                        break;
+                }
+            }
+        }
+
+        public static void WriteWordWrap(string text)
+        {
+            var line = new StringBuilder(Console.WindowWidth);
+            foreach (var paragraph in text.Split(Environment.NewLine))
+            {
+                line.Clear();
+                foreach (var word in paragraph.Split(' '))
+                {
+                    if (line.Length + word.Length < Console.WindowWidth)
+                    {
+                        if (line.Length > 0)
+                            line.Append(' ');
+                        line.Append(word);
+                    }
+                    else
+                    {
+                        Console.WriteLine(line.ToString());
+                        line.Clear().Append(word);
+                    }
+                }
+                Console.WriteLine(line.ToString());
+            }
+        }
+
+        public static void WriteTable(ICollection items, List> rows, bool transpose = false)
+        {
+            int cols = items.Count + 1;
+            var content = rows.Select(r => r.Format(items)).ToList();
+            if (transpose)
+            {
+                content = Enumerable.Range(0, cols).Select(col => content.Select(r => r[col]).ToArray()).ToList();
+                cols = rows.Count;
+            }
+            var colWidths = Enumerable.Range(0, cols).Select(col => content.Max(c => c[col].Length)).ToArray();
+
+            foreach (var row in content)
+            {
+                for (int col = 0; col < cols; col++)
+                {
+                    var space = new string(' ', colWidths[col] - row[col].Length);
+                    row[col] = col == 0 ? row[col] + space : space + row[col]; // left-align first col; right-align other cols
+                }
+            }
+
+            var sb = new StringBuilder();
+            var horizBars = colWidths.Select(w => new string('═', w)).ToArray();
+
+            void OneRow(string[] cells, char before, char between, char after)
+            {
+                sb.Append(before);
+                sb.AppendJoin(between, cells);
+                sb.Append(after);
+                sb.AppendLine();
+            }
+
+            OneRow(horizBars, '╔', '╦', '╗');
+            bool first = true;
+            foreach (var row in content)
+            {
+                if (first)
+                    first = false;
+                else
+                    OneRow(horizBars, '╠', '╬', '╣');
+                OneRow(row, '║', '║', '║');
+            }
+            OneRow(horizBars, '╚', '╩', '╝');
+
+            Console.WriteLine(sb.ToString());
+        }
+
+        public record TableRow(string Name, Func Data, string Before = "", string After = "")
+        {
+            private string FormatItem(T item) => $" {Before}{Data(item)}{After} ";
+
+            public string[] Format(IEnumerable items) => items.Select(FormatItem).Prepend($" {Name} ").ToArray();
+        }
+    }
+}
diff --git a/27 Civil War/csharp/CivilWar/CivilWar/GameOptions.cs b/27 Civil War/csharp/CivilWar/CivilWar/GameOptions.cs
new file mode 100644
index 00000000..9e7e4b31
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar/GameOptions.cs	
@@ -0,0 +1,55 @@
+using System;
+
+using static CivilWar.ConsoleUtils;
+
+namespace CivilWar
+{
+    public record GameOptions(bool TwoPlayers, bool ShowDescriptions)
+    {
+        public static GameOptions Input()
+        {
+            Console.WriteLine(
+@"                          Civil War
+               Creative Computing, Morristown, New Jersey
+
+
+Do you want instructions?");
+
+            const string instructions = @"This is a civil war simulation.
+To play type a response when the computer asks.
+Remember that all factors are interrelated and that your responses could change history. Facts and figures used are based on the actual occurrence. Most battles tend to result as they did in the civil war, but it all depends on you!!
+
+The object of the game is to win as many battles as possible.
+
+Your choices for defensive strategy are:
+        (1) artillery attack
+        (2) fortification against frontal attack
+        (3) fortification against flanking maneuvers
+        (4) falling back
+Your choices for offensive strategy are:
+        (1) artillery attack
+        (2) frontal attack
+        (3) flanking maneuvers
+        (4) encirclement
+You may surrender by typing a '5' for your strategy.";
+
+            if (InputYesOrNo())
+                WriteWordWrap(instructions);
+
+            Console.WriteLine("\n\nAre there two generals present?");
+            bool twoPlayers = InputYesOrNo();
+            if (!twoPlayers)
+                Console.WriteLine("\nYou are the confederacy.  Good luck!\n");
+
+            WriteWordWrap(
+            @"Select a battle by typing a number from 1 to 14 on request.  Type any other number to end the simulation. But '0' brings back exact previous battle situation allowing you to replay it.
+
+Note: a negative Food$ entry causes the program to use the entries from the previous battle
+
+After requesting a battle, do you wish battle descriptions (answer yes or no)");
+            bool showDescriptions = InputYesOrNo();
+
+            return new GameOptions(twoPlayers, showDescriptions);
+        }
+    }
+}
diff --git a/27 Civil War/csharp/CivilWar/CivilWar/Program.cs b/27 Civil War/csharp/CivilWar/CivilWar/Program.cs
new file mode 100644
index 00000000..c79d1a3a
--- /dev/null
+++ b/27 Civil War/csharp/CivilWar/CivilWar/Program.cs	
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CivilWar;
+
+var options = GameOptions.Input();
+var armies = new List { new Army(Side.Confederate), options.TwoPlayers ? new Army(Side.Union) : new ComputerArmy(Side.Union) };
+
+Battle? battle = null;
+while (OneBattle(ref battle)) { }
+DisplayResult();
+
+bool OneBattle(ref Battle? previous)
+{
+    var (option, selected) = Battle.SelectBattle();
+    var (battle, isReplay, quit) = option switch
+    {
+        Option.Battle => (selected!, false, false),
+        Option.Replay when previous != null => (previous, true, false), // can't replay if no previous battle
+        _ => (null!, false, true),
+    };
+    if (quit)
+        return false;
+
+    if (!isReplay)
+    {
+        Console.WriteLine($"This is the battle of {battle.Name}.");
+        if (options.ShowDescriptions)
+            ConsoleUtils.WriteWordWrap(battle.Description);
+        armies.ForEach(a => a.PrepareBattle(battle.Men[(int)a.Side], battle.Casualties[(int)a.Side]));
+    }
+
+    ConsoleUtils.WriteTable(armies, new()
+    {
+        new("", a => a.Side),
+        new("Men", a => a.Men),
+        new("Money", a => a.Money, Before: "$"),
+        new("Inflation", a => a.InflationDisplay, After: "%")
+    });
+
+    armies.ForEach(a => a.AllocateResources());
+    armies.ForEach(a => a.DisplayMorale());
+
+    string offensive = battle.Offensive switch
+    {
+        Side.Confederate => "You are on the offensive",
+        Side.Union => "You are on the defensive",
+        _ => "Both sides are on the offensive"
+    };
+    Console.WriteLine($"Confederate general---{offensive}");
+
+    if (armies.Any(a => a.ChooseStrategy(isReplay)))
+    {
+        return false; // someone surrendered
+    }
+    armies[0].CalculateLosses(armies[1]);
+    armies[1].CalculateLosses(armies[0]);
+
+    ConsoleUtils.WriteTable(armies, new()
+    {
+        new("", a => a.Side),
+        new("Casualties", a => a.Casualties),
+        new("Desertions", a => a.Desertions),
+    });
+    if (options.TwoPlayers)
+    {
+        var oneDataCol = new[] { 1 };
+        Console.WriteLine($"Compared to the actual casualties at {battle.Name}");
+        ConsoleUtils.WriteTable(oneDataCol, armies.Select(a => new ConsoleUtils.TableRow(
+            a.Side.ToString(),
+            _ => $"{(double)a.Casualties / battle.Casualties[(int)a.Side]}", After: "% of the original")
+        ).ToList());
+    }
+
+    Side winner;
+    switch (armies[0].AllLost, armies[1].AllLost, armies[0].MenLost - armies[1].MenLost)
+    {
+        case (true, true, _) or (false, false, 0):
+            Console.WriteLine("Battle outcome unresolved");
+            winner = Side.Both; // Draw
+            break;
+        case (false, true, _) or (false, false, < 0):
+            Console.WriteLine($"The Confederacy wins {battle.Name}");
+            winner = Side.Confederate;
+            break;
+        case (true, false, _) or (false, false, > 0):
+            Console.WriteLine($"The Union wins {battle.Name}");
+            winner = Side.Union;
+            break;
+    }
+    if (!isReplay)
+    {
+        armies.ForEach(a => a.RecordResult(winner));
+    }
+    Console.WriteLine("---------------");
+    previous = battle;
+    return true;
+}
+
+void DisplayResult()
+{
+    armies[0].DisplayWarResult(armies[1]);
+
+    int battles = armies[0].BattlesFought;
+    if (battles > 0)
+    {
+        Console.WriteLine($"For the {battles} battles fought (excluding reruns)");
+
+        ConsoleUtils.WriteTable(armies, new()
+        {
+            new("", a => a.Side),
+            new("Historical Losses", a => a.CumulativeHistoricCasualties),
+            new("Simulated Losses", a => a.CumulativeSimulatedCasualties),
+            new("  % of original", a => ((double)a.CumulativeSimulatedCasualties / a.CumulativeHistoricCasualties).ToString("p2"))
+        }, transpose: true);
+
+        armies[1].DisplayStrategies();
+    }
+}
\ No newline at end of file

From 9e07a5a2e9429c43fbc0a4cc79430ae678e32b04 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 13 Mar 2021 20:50:17 -0600
Subject: [PATCH 293/749] Ported QUEEN to Javascript

---
 72 Queen/javascript/queen.html |   9 ++
 72 Queen/javascript/queen.js   | 237 +++++++++++++++++++++++++++++++++
 2 files changed, 246 insertions(+)
 create mode 100644 72 Queen/javascript/queen.html
 create mode 100644 72 Queen/javascript/queen.js

diff --git a/72 Queen/javascript/queen.html b/72 Queen/javascript/queen.html
new file mode 100644
index 00000000..ce191813
--- /dev/null
+++ b/72 Queen/javascript/queen.html	
@@ -0,0 +1,9 @@
+
+
+QUEEN
+
+
+

+
+
+
diff --git a/72 Queen/javascript/queen.js b/72 Queen/javascript/queen.js
new file mode 100644
index 00000000..0adee46c
--- /dev/null
+++ b/72 Queen/javascript/queen.js	
@@ -0,0 +1,237 @@
+// QUEEN
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var sa = [,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];
+
+var m;
+var m1;
+var u;
+var t;
+var u1;
+var t1;
+
+function show_instructions()
+{
+    print("WE ARE GOING TO PLAY A GAME BASED ON ONE OF THE CHESS\n");
+    print("MOVES.  OUR QUEEN WILL BE ABLE TO MOVE ONLY TO THE LEFT,\n");
+    print("DOWN, OR DIAGONALLY DOWN AND TO THE LEFT.\n");
+    print("\n");
+    print("THE OBJECT OF THE GAME IS TO PLACE THE QUEEN IN THE LOWER\n");
+    print("LEFT HAND SQUARE BY ALTERNATING MOVES BETWEEN YOU AND THE\n");
+    print("COMPUTER.  THE FIRST ONE TO PLACE THE QUEEN THERE WINS.\n");
+    print("\n");
+    print("YOU GO FIRST AND PLACE THE QUEEN IN ANY ONE OF THE SQUARES\n");
+    print("ON THE TOP ROW OR RIGHT HAND COLUMN.\n");
+    print("THAT WILL BE YOUR FIRST MOVE.\n");
+    print("WE ALTERNATE MOVES.\n");
+    print("YOU MAY FORFEIT BY TYPING '0' AS YOUR MOVE.\n");
+    print("BE SURE TO PRESS THE RETURN KEY AFTER EACH RESPONSE.\n");
+    print("\n");
+    print("\n");
+}
+
+function show_map()
+{
+    print("\n");
+    for (var a = 0; a <= 7; a++) {
+        for (var b = 1; b <= 8; b++) {
+            i = 8 * a + b;
+            print(" " + sa[i] + " ");
+        }
+        print("\n");
+        print("\n");
+        print("\n");
+    }
+    print("\n");
+}
+
+function test_move()
+{
+    m = 10 * t + u;
+    if (m == 158 || m == 127 || m == 126 || m == 75 || m == 73)
+        return true;
+    return false;
+}
+
+function random_move()
+{
+    // Random move
+    z = Math.random();
+    if (z > 0.6) {
+        u = u1 + 1;
+        t = t1 + 1;
+    } else if (z > 0.3) {
+        u = u1 + 1;
+        t = t1 + 2;
+    } else {
+        u = u1;
+        t = t1 + 1;
+    }
+    m = 10 * t + u;
+}
+
+function computer_move()
+{
+    if (m1 == 41 || m1 == 44 || m1 == 73 || m1 == 75 || m1 == 126 || m1 == 127) {
+        random_move();
+        return;
+    }
+    for (k = 7; k >= 1; k--) {
+        u = u1;
+        t = t1 + k;
+        if (test_move())
+            return;
+        u += k;
+        if (test_move())
+            return;
+        t += k;
+        if (test_move())
+            return;
+    }
+    random_move();
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "QUEEN\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    
+    while (1) {
+        print("DO YOU WANT INSTRUCTIONS");
+        str = await input();
+        if (str == "YES" || str == "NO")
+            break;
+        print("PLEASE ANSWER 'YES' OR 'NO'.\n");
+    }
+    if (str == "YES")
+        show_instructions();
+    while (1) {
+        show_map();
+        while (1) {
+            print("WHERE WOULD YOU LIKE TO START");
+            m1 = parseInt(await input());
+            if (m1 == 0) {
+                print("\n");
+                print("IT LOOKS LIKE I HAVE WON BY FORFEIT.\n");
+                print("\n");
+                break;
+            }
+            t1 = Math.floor(m1 / 10);
+            u1 = m1 - 10 * t1;
+            if (u1 == 1 || u1 == t1)
+                break;
+            print("PLEASE READ THE DIRECTIONS AGAIN.\n");
+            print("YOU HAVE BEGUN ILLEGALLY.\n");
+            print("\n");
+        }
+        while (m1) {
+            if (m1 == 158) {
+                print("\n");
+                print("C O N G R A T U L A T I O N S . . .\n");
+                print("\n");
+                print("YOU HAVE WON--VERY WELL PLAYED.\n");
+                print("IT LOOKS LIKE I HAVE MET MY MATCH.\n");
+                print("THANKS FOR PLAYING--I CAN'T WIN ALL THE TIME.\n");
+                print("\n");
+                break;
+            }
+            computer_move();
+            print("COMPUTER MOVES TO SQUARE " + m + "\n");
+            if (m == 158) {
+                print("\n");
+                print("NICE TRY, BUT IT LOOKS LIKE I HAVE WON.\n");
+                print("THANKS FOR PLAYING.\n");
+                print("\n");
+                break;
+            }
+            print("WHAT IS YOUR MOVE");
+            while (1) {
+                m1 = parseInt(await input());
+                if (m1 == 0)
+                    break;
+                t1 = Math.floor(m1 / 10);
+                u1 = m1 - 10 * t1;
+                p = u1 - u;
+                l = t1 - t;
+                if (m1 <= m || p == 0 && l <= 0 || p != 0 && l != p && l != 2 * p) {
+                    print("\n");
+                    print("Y O U   C H E A T . . .  TRY AGAIN");
+                    continue;
+                }
+                break;
+            }
+            if (m1 == 0) {
+                print("\n");
+                print("IT LOOKS LIKE I HAVE WON BY FORFEIT.\n");
+                print("\n");
+                break;
+            }
+        }
+        while (1) {
+            print("ANYONE ELSE CARE TO TRY");
+            str = await input();
+            print("\n");
+            if (str == "YES" || str == "NO")
+                break;
+            print("PLEASE ANSWER 'YES' OR 'NO'.\n");
+        }
+        if (str != "YES")
+            break;
+    }
+    print("\n");
+    print("OK --- THANKS AGAIN.\n");
+}
+
+main();

From 80f557a7b78b9a8134c7b478dc940c2a9662c0b2 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 13 Mar 2021 21:09:33 -0600
Subject: [PATCH 294/749] Ported TICTACTOE1 to Javascript

---
 89 Tic-Tac-Toe/javascript/tictactoe1.html |   9 ++
 89 Tic-Tac-Toe/javascript/tictactoe1.js   | 147 ++++++++++++++++++++++
 2 files changed, 156 insertions(+)
 create mode 100644 89 Tic-Tac-Toe/javascript/tictactoe1.html
 create mode 100644 89 Tic-Tac-Toe/javascript/tictactoe1.js

diff --git a/89 Tic-Tac-Toe/javascript/tictactoe1.html b/89 Tic-Tac-Toe/javascript/tictactoe1.html
new file mode 100644
index 00000000..7aafc617
--- /dev/null
+++ b/89 Tic-Tac-Toe/javascript/tictactoe1.html	
@@ -0,0 +1,9 @@
+
+
+TIC TAC TOE 1
+
+
+

+
+
+
diff --git a/89 Tic-Tac-Toe/javascript/tictactoe1.js b/89 Tic-Tac-Toe/javascript/tictactoe1.js
new file mode 100644
index 00000000..fce4b7da
--- /dev/null
+++ b/89 Tic-Tac-Toe/javascript/tictactoe1.js	
@@ -0,0 +1,147 @@
+// TIC TAC TOE 1
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+function mf(x)
+{
+    return x - 8 * Math.floor((x - 1) / 8);
+}
+
+function computer_moves()
+{
+    print("COMPUTER MOVES " + m + "\n");
+}
+
+var m;
+
+// Main control section
+async function main()
+{
+    print(tab(30) + "TIC TAC TOE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    //
+    // This program plays Tic Tac Toe
+    // The machine goes first
+    print("THE GAME BOARD IS NUMBERED:\n");
+    print("\n");
+    print("1  2  3\n");
+    print("8  9  4\n");
+    print("7  6  5\n");
+    print("\n");
+    //
+    // Main program
+    while (1) {
+        print("\n");
+        print("\n");
+        a = 9;
+        m = a;
+        
+        computer_moves();
+        print("YOUR MOVE");
+        m = parseInt(await input());
+        
+        p = m;
+        b = mf(p + 1);
+        m = b;
+        
+        computer_moves();
+        print("YOUR MOVE");
+        m = parseInt(await input());
+        
+        q = m;
+        if (q != mf(b + 4)) {
+            c = mf(b + 4);
+            m = c;
+            computer_moves();
+            print("AND WINS ********\n");
+            continue;
+        }
+        
+        c = mf(b + 2);
+        m = c;
+
+        computer_moves();
+        print("YOUR MOVE");
+        m = parseInt(await input());
+
+        r = m;
+        if (r != mf(c + 4)) {
+            d = mf(c + 4);
+            m = d;
+            computer_moves();
+            print("AND WINS ********\n");
+            continue;
+        }
+        
+        if (p % 2 == 0) {
+            d = mf(c + 7);
+            m = d;
+            computer_moves();
+            print("AND WINS ********\n");
+            continue;
+        }
+        
+        d = mf(c + 3);
+        m = d;
+        
+        computer_moves();
+        print("YOUR MOVE");
+        m = parseInt(await input());
+        
+        s = m;
+        if (s != mf(d + 4)) {
+            e = mf(d + 4);
+            m = e;
+            computer_moves();
+        }
+        e = mf(d + 6);
+        m = e;
+        computer_moves();
+        print("THE GAME IS A DRAW.\n");
+    }
+}
+
+main();

From 7e1576809a0f0049660ed91053847a0bf25baf5c Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 13 Mar 2021 21:55:16 -0600
Subject: [PATCH 295/749] Ported TICTACTOE2 to Javascript

---
 89 Tic-Tac-Toe/javascript/tictactoe2.html |   9 +
 89 Tic-Tac-Toe/javascript/tictactoe2.js   | 288 ++++++++++++++++++++++
 2 files changed, 297 insertions(+)
 create mode 100644 89 Tic-Tac-Toe/javascript/tictactoe2.html
 create mode 100644 89 Tic-Tac-Toe/javascript/tictactoe2.js

diff --git a/89 Tic-Tac-Toe/javascript/tictactoe2.html b/89 Tic-Tac-Toe/javascript/tictactoe2.html
new file mode 100644
index 00000000..418bf65c
--- /dev/null
+++ b/89 Tic-Tac-Toe/javascript/tictactoe2.html	
@@ -0,0 +1,9 @@
+
+
+TIC TAC TOE 2
+
+
+

+
+
+
diff --git a/89 Tic-Tac-Toe/javascript/tictactoe2.js b/89 Tic-Tac-Toe/javascript/tictactoe2.js
new file mode 100644
index 00000000..beab1df6
--- /dev/null
+++ b/89 Tic-Tac-Toe/javascript/tictactoe2.js	
@@ -0,0 +1,288 @@
+// TIC TAC TOE 2
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var s = [];
+
+function who_win(piece)
+{
+    if (piece == -1) {
+        print("I WIN, TURKEY!!!\n");
+    } else if (piece == 1) {
+        print("YOU BEAT ME!! GOOD GAME.\n");
+    }
+}
+
+function show_board()
+{
+    print("\n");
+    for (i = 1; i <= 9; i++) {
+        print(" ");
+        if (s[i] == -1) {
+            print(qs + " ");
+        } else if (s[i] == 0) {
+            print("  ");
+        } else {
+            print(ps + " ");
+        }
+        if (i == 3 || i == 6) {
+            print("\n");
+            print("---+---+---\n");
+        } else if (i != 9) {
+            print("!");
+        }
+    }
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 1; i <= 7; i += 3) {
+        if (s[i] && s[i] == s[i + 1] && s[i] == s[i + 2]) {
+            who_win(s[i]);
+            return true;
+        }
+    }
+    for (i = 1; i <= 3; i++) {
+        if (s[i] && s[i] == s[i + 3] && s[i] == s[i + 6]) {
+            who_win(s[i]);
+            return true;
+        }
+    }
+    if (s[1] && s[1] == s[5] && s[1] == s[9]) {
+        who_win(s[1]);
+        return true;
+    }
+    if (s[3] && s[3] == s[5] && s[3] == s[7]) {
+        who_win(s[3]);
+        return true;
+    }
+    for (i = 1; i <= 9; i++) {
+        if (s[i] == 0)
+            break;
+    }
+    if (i > 9) {
+        print("IT'S A DRAW. THANK YOU.\n");
+        return true;
+    }
+    return false;
+}
+
+// Main control section
+async function main()
+{
+    print(tab(30) + "TIC-TAC-TOE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    for (i = 1; i <= 9; i++)
+        s[i] = 0;
+    print("THE BOARD IS NUMBERED:\n");
+    print(" 1  2  3\n");
+    print(" 4  5  6\n");
+    print(" 7  8  9\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("DO YOU WANT 'X' OR 'O'");
+    str = await input();
+    if (str == "X") {
+        ps = "X";
+        qs = "O";
+        first_time = true;
+    } else {
+        ps = "O";
+        qs = "X";
+        first_time = false;
+    }
+    while (1) {
+        if (!first_time) {
+            g = -1;
+            h = 1;
+            if (s[5] == 0) {
+                s[5] = -1;
+            } else if (s[5] == 1 && s[1] == 0) {
+                s[1] = -1;
+            } else if (s[5] != 1 && s[2] == 1 && s[1] == 0 || s[5] != 1 && s[4] == 1 && s[1] == 0) {
+                s[1] = -1;
+            } else if (s[5] != 1 && s[6] == 1 && s[9] == 0 || s[5] != 1 && s[8] == 1 && s[9] == 0) {
+                s[9] = -1;
+            } else {
+                while (1) {
+                    played = false;
+                    if (g == 1) {
+                        j = 3 * Math.floor((m - 1) / 3) + 1;
+                        if (3 * Math.floor((m - 1) / 3) + 1 == m)
+                            k = 1;
+                        if (3 * Math.floor((m - 1) / 3) + 2 == m)
+                            k = 2;
+                        if (3 * Math.floor((m - 1) / 3) + 3 == m)
+                            k = 3;
+                    } else {
+                        j = 1;
+                        k = 1;
+                    }
+                    while (1) {
+                        if (s[j] == g) {
+                            if (s[j + 2] == g) {
+                                if (s[j + 1] == 0) {
+                                    s[j + 1] = -1;
+                                    played = true;
+                                    break;
+                                }
+                            } else {
+                                if (s[j + 2] == 0 && s[j + 1] == g) {
+                                    s[j + 2] = -1;
+                                    played = true;
+                                    break;
+                                }
+                            }
+                        } else {
+                            if (s[j] != h && s[j + 2] == g && s[j + 1] == g) {
+                                s[j] = -1;
+                                played = true;
+                                break;
+                            }
+                        }
+                        if (s[k] == g) {
+                            if (s[k + 6] == g) {
+                                if (s[k + 3] == 0) {
+                                    s[k + 3] = -1;
+                                    played = true;
+                                    break;
+                                }
+                            } else {
+                                if (s[k + 6] == 0 && s[k + 3] == g) {
+                                    s[k + 6] = -1;
+                                    played = true;
+                                    break;
+                                }
+                            }
+                        } else {
+                            if (s[k] != h && s[k + 6] == g && s[k + 3] == g) {
+                                s[k] = -1;
+                                played = true;
+                                break;
+                            }
+                        }
+                        if (g == 1)
+                            break;
+                        if (j == 7 && k == 3)
+                            break;
+                        k++;
+                        if (k > 3) {
+                            k = 1;
+                            j += 3;
+                            if (j > 7)
+                                break;
+                        }
+                    }
+                    if (!played) {
+                        if (s[5] == g) {
+                            if (s[3] == g && s[7] == 0) {
+                                s[7] = -1;
+                                played = true;
+                            } else if (s[9] == g && s[1] == 0) {
+                                s[1] = -1;
+                                played = true;
+                            } else if (s[7] == g && s[3] == 0) {
+                                s[3] = -1;
+                                played = true;
+                            } else if (s[9] == 0 && s[1] == g) {
+                                s[9] = -1;
+                                played = true;
+                            }
+                        }
+                        if (!played) {
+                            if (g == -1) {
+                                g = 1;
+                                h = -1;
+                            }
+                        }
+                    }
+                    if (played)
+                        break;
+                }
+                if (!played) {
+                    if (s[9] == 1 && s[3] == 0 && s[1] != 1) {
+                        s[3] = -1;
+                    } else {
+                        for (i = 2; i <= 9; i++) {
+                            if (s[i] == 0) {
+                                s[i] = -1;
+                                break;
+                            }
+                        }
+                        if (i > 9) {
+                            s[1] = -1;
+                        }
+                    }
+                }
+            }
+            print("\n");
+            print("THE COMPUTER MOVES TO...");
+            if (show_board())
+                break;
+        }
+        first_time = false;
+        while (1) {
+            print("\n");
+            print("WHERE DO YOU MOVE");
+            m = parseInt(await input());
+            if (m == 0) {
+                print("THANKS FOR THE GAME.\n");
+                break;
+            }
+            if (m >= 1 && m <= 9 && s[m] == 0)
+                break;
+            print("THAT SQUARE IS OCCUPIED.\n");
+            print("\n");
+            print("\n");
+        }
+        g = 1;
+        s[m] = 1;
+        if (show_board())
+            break;
+    }
+}
+
+main();

From 486e336224efd8ff8fd49a54ffc0562591b83422 Mon Sep 17 00:00:00 2001
From: Todd Kaiser 
Date: Sun, 14 Mar 2021 12:11:03 -0600
Subject: [PATCH 296/749] Refactored main flow, added function and loop for
 executing turns.

---
 77 Salvo/python/salvo.py | 154 +++++++++++++++++++++++++++++----------
 1 file changed, 117 insertions(+), 37 deletions(-)

diff --git a/77 Salvo/python/salvo.py b/77 Salvo/python/salvo.py
index 2061943d..73ff55ec 100644
--- a/77 Salvo/python/salvo.py	
+++ b/77 Salvo/python/salvo.py	
@@ -50,6 +50,16 @@ current_turn = 0
 # printed out during computer's turn
 print_computer_shots = False
 
+# keep track of the number
+# of available computer shots
+# inital shots are 7
+num_computer_shots = 7
+
+# keep track of the number
+# of available player shots
+# initial shots are 7
+num_player_shots = 7
+
 ####################
 #
 # game functions
@@ -162,6 +172,10 @@ def create_blank_board():
             for x in range(BOARD_HEIGHT)]
 
 
+# print_board
+#
+# print out the game board for testing
+# purposes
 def print_board(board):
 
     # print board header (column numbers)
@@ -221,6 +235,15 @@ def generate_board():
     return board, ship_coords
 
 
+# execute_shot
+#
+# given a board and x, y coordinates,
+# execute a shot. returns True if the shot
+# is valid, False if not
+def execute_shot(board, x, y):
+    print("execute shot:", x, y)
+
+
 # initialize
 #
 # function to initialize global variables used
@@ -243,6 +266,93 @@ def initialize_game():
     print('{0:>57s}'.format("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"))
     print('\n\n')
 
+    # ask the player for ship coordinates
+    print("ENTER COORDINATES FOR...")
+    ship_coords = []
+    for ship in SHIPS:
+        print(ship[0])
+        list = []
+        for i in range(ship[1]):
+            x, y = input_coord()
+            list.append((x, y))
+        ship_coords.append(list)
+
+    # add ships to the user's board
+    for ship in range(len(SHIPS)):
+        place_ship(player_board, ship_coords[ship], ship)
+
+    # see if the player wants the computer's ship
+    # locations printed out and if the player wants to
+    # start
+    input_loop = True
+    player_start = "YES"
+    while input_loop:
+        player_start = input("DO YOU WANT TO START? ")
+        if player_start == "WHERE ARE YOUR SHIPS?":
+            for ship in range(len(SHIPS)):
+                print(SHIPS[ship][0])
+                coords = computer_ship_coords[ship]
+                for coord in coords:
+                    x = coord[0]
+                    y = coord[1]
+                    print('{0:2}'.format(x), '{0:2}'.format(y))
+        else:
+            input_loop = False
+
+    # ask the player if they want the computer's shots
+    # printed out each turn
+    global print_computer_shots
+    see_computer_shots = input("DO YOU WANT TO SEE MY SHOTS? ")
+    if see_computer_shots.lower() == "yes":
+        print_computer_shots = True
+
+    global first_turn
+    global second_turn
+    if player_start.lower() != "yes":
+        first_turn = computer_turn
+        second_turn = player_turn
+
+
+####################################
+#
+# Turn Control
+#
+# define functions for executing the turns for
+# the player and the computer. By defining this as
+# functions, we can easily start the game with
+# either computer or player and alternate back and
+# forth, replicating the gotos in the original game
+def player_turn():
+    print("YOU HAVE", num_computer_shots, "SHOTS.")
+
+    shots = []
+    for shot in range(num_player_shots):
+        valid_shot = False
+        while not valid_shot:
+            x, y = input_coord()
+            valid_shot = execute_shot(player_board, x, y)
+            shots.append((x, y))
+
+    print(shots)
+
+
+# initialize the first_turn function to the
+# player's turn
+first_turn = player_turn
+
+
+def computer_turn():
+    print("I HAVE", num_computer_shots, "SHOTS.")
+
+
+# initialize the second_turn to the computer's
+# turn
+second_turn = computer_turn
+
+#
+# Turn Control
+#
+######################################
 
 ######################
 #
@@ -254,42 +364,12 @@ def initialize_game():
 # boards
 initialize_game()
 
-# ask the player for ship coordinates
-print("ENTER COORDINATES FOR...")
-ship_coords = []
-for ship in SHIPS:
-    print(ship[0])
-    list = []
-    for i in range(ship[1]):
-        x, y = input_coord()
-        list.append((x, y))
-    ship_coords.append(list)
+# execute turns until someone wins or we run
+# out of squares to shoot
 
-# add ships to the user's board
-for ship in range(len(SHIPS)):
-    place_ship(player_board, ship_coords[ship], ship)
-
-# see if the player wants the computer's ship
-# locations printed out and if the player wants to
-# start
-input_loop = True
-player_start = "YES"
-while input_loop:
-    player_start = input("DO YOU WANT TO START? ")
-    if player_start == "WHERE ARE YOUR SHIPS?":
-        for ship in range(len(SHIPS)):
-            print(SHIPS[ship][0])
-            coords = computer_ship_coords[ship]
-            for coord in coords:
-                x = coord[0]
-                y = coord[1]
-                print('{0:2}'.format(x), '{0:2}'.format(y))
-    else:
-        input_loop = False
-
-# ask the player if they want the computer's shots
-# printed out each turn
-see_computer_shots = input("DO YOU WANT TO SEE MY SHOTS? ")
-if see_computer_shots.lower() == "yes":
-    print_computer_shots = True
+current_turn = current_turn + 1
+print("\n")
+print("TURN", current_turn)
 
+first_turn()
+second_turn()

From 4e7374d89c4601fc510e15d6826dba969bc44fba Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Sun, 14 Mar 2021 16:35:20 -0400
Subject: [PATCH 297/749] Add Java port of Tower.

---
 90 Tower/java/Tower.java | 527 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 527 insertions(+)
 create mode 100644 90 Tower/java/Tower.java

diff --git a/90 Tower/java/Tower.java b/90 Tower/java/Tower.java
new file mode 100644
index 00000000..ed4c454f
--- /dev/null
+++ b/90 Tower/java/Tower.java	
@@ -0,0 +1,527 @@
+import java.lang.Math;
+import java.util.Scanner;
+
+/**
+ * Game of Tower
+ * 

+ * Based on the BASIC game of Tower here + * https://github.com/coding-horror/basic-computer-games/blob/main/90%20Tower/tower.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Tower { + + private final static int MAX_DISK_SIZE = 15; + + private final static int MAX_NUM_COLUMNS = 3; + + private final static int MAX_NUM_MOVES = 128; + + private final static int MAX_NUM_ROWS = 7; + + private final Scanner scan; // For user input + + // Represent all possible disk positions + private int[][] positions; + + private enum Step { + INITIALIZE, SELECT_TOTAL_DISKS, SELECT_DISK_MOVE, SELECT_NEEDLE, CHECK_SOLUTION + } + + + public Tower() { + + scan = new Scanner(System.in); + + // Row 0 and column 0 are not used + positions = new int[MAX_NUM_ROWS + 1][MAX_NUM_COLUMNS + 1]; + + } // End of constructor Tower + + + public class Position { + + public int row; + public int column; + + public Position(int row, int column) { + this.row = row; + this.column = column; + + } // End of constructor Position + + } // End of inner class Position + + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + + private void showIntro() { + + System.out.println(" ".repeat(32) + "TOWERS"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + + private void startGame() { + + boolean diskMoved = false; + + int column = 0; + int disk = 0; + int needle = 0; + int numDisks = 0; + int numErrors = 0; + int numMoves = 0; + int row = 0; + + Step nextStep = Step.INITIALIZE; + + String userResponse = ""; + + Position diskPosition = new Position(0, 0); + + // Begin outer while loop + while (true) { + + switch (nextStep) { + + + case INITIALIZE: + + // Initialize error count + numErrors = 0; + + // Initialize positions + for (row = 1; row <= MAX_NUM_ROWS; row++) { + for (column = 1; column <= MAX_NUM_COLUMNS; column++) { + positions[row][column] = 0; + } + } + + // Display description + System.out.println(""); + System.out.println("TOWERS OF HANOI PUZZLE.\n"); + System.out.println("YOU MUST TRANSFER THE DISKS FROM THE LEFT TO THE RIGHT"); + System.out.println("TOWER, ONE AT A TIME, NEVER PUTTING A LARGER DISK ON A"); + System.out.println("SMALLER DISK.\n"); + + nextStep = Step.SELECT_TOTAL_DISKS; + break; + + + case SELECT_TOTAL_DISKS: + + while (numErrors <= 2) { + + // Get user input + System.out.print("HOW MANY DISKS DO YOU WANT TO MOVE (" + MAX_NUM_ROWS + " IS MAX)? "); + numDisks = scan.nextInt(); + System.out.println(""); + + numMoves = 0; + + // Ensure the number of disks is valid + if ((numDisks < 1) || (numDisks > MAX_NUM_ROWS)) { + + numErrors++; + + // Handle user input errors + if (numErrors < 3) { + System.out.println("SORRY, BUT I CAN'T DO THAT JOB FOR YOU."); + } + + } + else { + break; // Leave the while loop + } + } + + // Too many user input errors + if (numErrors > 2) { + System.out.println("ALL RIGHT, WISE GUY, IF YOU CAN'T PLAY THE GAME RIGHT, I'LL"); + System.out.println("JUST TAKE MY PUZZLE AND GO HOME. SO LONG."); + return; + } + + // Display detailed instructions + System.out.println("IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE."); + System.out.println("3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,"); + System.out.println("7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH"); + System.out.println("2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS"); + System.out.println("THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES"); + System.out.println("ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL"); + System.out.println("START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM"); + System.out.println("TO NEEDLE 3.\n"); + System.out.println("GOOD LUCK!\n"); + + disk = MAX_DISK_SIZE; + + // Set disk starting positions + for (row = MAX_NUM_ROWS; row > (MAX_NUM_ROWS - numDisks); row--) { + positions[row][1] = disk; + disk = disk - 2; + } + + printPositions(); + + nextStep = Step.SELECT_DISK_MOVE; + break; + + + case SELECT_DISK_MOVE: + + System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? "); + + numErrors = 0; + + while (numErrors < 2) { + disk = scan.nextInt(); + + // Validate disk numbers + if ((disk - 3) * (disk - 5) * (disk - 7) * (disk - 9) * (disk - 11) * (disk - 13) * (disk - 15) == 0) { + + // Check if disk exists + diskPosition = getDiskPosition(disk); + + // Disk found + if ((diskPosition.row > 0) && (diskPosition.column > 0)) + { + // Disk can be moved + if (isDiskMovable(disk, diskPosition.row, diskPosition.column) == true) { + + break; + + } + // Disk cannot be moved + else { + + System.out.println("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE."); + System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? "); + + } + } + // Mimic legacy handling of valid disk number but disk not found + else { + + System.out.println("THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE."); + System.out.print("WHICH DISK WOULD YOU LIKE TO MOVE? "); + numErrors = 0; + continue; + + } + + } + // Invalid disk number + else { + + System.out.println("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15."); + numErrors++; + + if (numErrors > 1) { + break; + } + + System.out.print("? "); + + } + } + + if (numErrors > 1) { + + System.out.println("STOP WASTING MY TIME. GO BOTHER SOMEONE ELSE."); + return; + } + + nextStep = Step.SELECT_NEEDLE; + break; + + + case SELECT_NEEDLE: + + numErrors = 0; + + while (true) { + + System.out.print("PLACE DISK ON WHICH NEEDLE? "); + needle = scan.nextInt(); + + // Handle valid needle numbers + if ((needle - 1) * (needle - 2) * (needle - 3) == 0) { + + // Ensure needle is safe for disk move + if (isNeedleSafe(needle, disk, row) == false) { + + System.out.println("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE,"); + System.out.println("IT MIGHT CRUSH IT!"); + System.out.print("NOW THEN, "); + + nextStep = Step.SELECT_DISK_MOVE; + break; + } + + diskPosition = getDiskPosition(disk); + + // Attempt to move the disk on a non-empty needle + diskMoved = false; + for (row = 1; row <= MAX_NUM_ROWS; row++) { + if (positions[row][needle] != 0) { + row--; + + positions[row][needle] = positions[diskPosition.row][diskPosition.column]; + positions[diskPosition.row][diskPosition.column] = 0; + + diskMoved = true; + break; + } + } + + // Needle was empty, so move disk to the bottom + if (diskMoved == false) { + positions[MAX_NUM_ROWS][needle] = positions[diskPosition.row][diskPosition.column]; + positions[diskPosition.row][diskPosition.column] = 0; + } + + nextStep = Step.CHECK_SOLUTION; + break; + + } + // Handle invalid needle numbers + else { + + numErrors++; + + if (numErrors > 1) { + System.out.println("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN."); + System.out.println("BYE BYE, BIG SHOT."); + return; + } + else { + System.out.println("I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME. BUT WATCH IT,"); + System.out.println("I ONLY ALLOW ONE MISTAKE."); + } + } + + } + + break; + + + case CHECK_SOLUTION: + + printPositions(); + + numMoves++; + + // Puzzle is solved + if (isPuzzleSolved() == true) { + + // Check for optimal solution + if (numMoves == (Math.pow(2, numDisks) - 1)) { + System.out.println(""); + System.out.println("CONGRATULATIONS!!\n"); + } + + System.out.println("YOU HAVE PERFORMED THE TASK IN " + numMoves + " MOVES.\n"); + System.out.print("TRY AGAIN (YES OR NO)? "); + + // Prompt for retries + while (true) { + userResponse = scan.next(); + + if (userResponse.toUpperCase().equals("YES")) { + nextStep = Step.INITIALIZE; + break; + } + else if (userResponse.toUpperCase().equals("NO")) { + System.out.println(""); + System.out.println("THANKS FOR THE GAME!\n"); + return; + } + else { + System.out.print("'YES' OR 'NO' PLEASE? "); + } + } + } + // Puzzle is not solved + else { + + // Exceeded maximum number of moves + if (numMoves > MAX_NUM_MOVES) { + System.out.println("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN"); + System.out.println("128 MOVES."); + return; + } + + nextStep = Step.SELECT_DISK_MOVE; + break; + } + + break; + + default: + System.out.println("INVALID STEP"); + break; + + } + + } // End outer while loop + + } // End of method startGame + + + private boolean isPuzzleSolved() { + + int column = 0; + int row = 0; + + // Puzzle is solved if first 2 needles are empty + for (row = 1; row <= MAX_NUM_ROWS; row++) { + for (column = 1; column <= 2; column++) { + if (positions[row][column] != 0) { + return false; + } + } + } + + return true; + + } // End of method isPuzzleSolved + + + private Position getDiskPosition(int disk) { + + int column = 0; + int row = 0; + + Position pos = new Position(0, 0); + + // Begin loop through all rows + for (row = 1; row <= MAX_NUM_ROWS; row++) { + + // Begin loop through all columns + for (column = 1; column <= MAX_NUM_COLUMNS; column++) { + + // Found the disk + if (positions[row][column] == disk) { + + pos.row = row; + pos.column = column; + return pos; + + } + + } // End loop through all columns + + } // End loop through all rows + + return pos; + + } // End of method getDiskPosition + + + private boolean isDiskMovable(int disk, int row, int column) { + + int ii = 0; // Loop iterator + + // Begin loop through all rows above disk + for (ii = row; ii >= 1; ii--) { + + // Disk can be moved + if (positions[ii][column] == 0) { + continue; + } + + // Disk cannot be moved + if (positions[ii][column] < disk) { + return false; + } + + } // End loop through all rows above disk + + return true; + + } // End of method isDiskMovable + + + private boolean isNeedleSafe(int needle, int disk, int row) { + + for (row = 1; row <= MAX_NUM_ROWS; row++) { + + // Needle is not empty + if (positions[row][needle] != 0) { + + // Disk crush condition + if (disk >= positions[row][needle]) { + return false; + } + } + } + + return true; + + } // End of method isNeedleSafe + + + private void printPositions() { + + int column = 1; + int ii = 0; // Loop iterator + int numSpaces = 0; + int row = 1; + + // Begin loop through all rows + for (row = 1; row <= MAX_NUM_ROWS; row++) { + + numSpaces = 9; + + // Begin loop through all columns + for (column = 1; column <= MAX_NUM_COLUMNS; column++) { + + // No disk at the current position + if (positions[row][column] == 0) { + + System.out.print(" ".repeat(numSpaces) + "*"); + numSpaces = 20; + } + + // Draw a disk at the current position + else { + + System.out.print(" ".repeat(numSpaces - ((int) (positions[row][column] / 2)))); + + for (ii = 1; ii <= positions[row][column]; ii++) { + System.out.print("*"); + } + + numSpaces = 20 - ((int) (positions[row][column] / 2)); + } + + } // End loop through all columns + + System.out.println(""); + + } // End loop through all rows + + } // End of method printPositions + + + public static void main(String[] args) { + + Tower tower = new Tower(); + tower.play(); + + } // End of method main + +} // End of class Tower \ No newline at end of file From 297a2b5df9c61f7c0f087b89fa3d1a222c393b24 Mon Sep 17 00:00:00 2001 From: nanochess Date: Mon, 15 Mar 2021 16:38:38 -0600 Subject: [PATCH 298/749] Ported TOWER to Javascript --- 90 Tower/javascript/tower.html | 9 ++ 90 Tower/javascript/tower.js | 254 +++++++++++++++++++++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 90 Tower/javascript/tower.html create mode 100644 90 Tower/javascript/tower.js diff --git a/90 Tower/javascript/tower.html b/90 Tower/javascript/tower.html new file mode 100644 index 00000000..84318f33 --- /dev/null +++ b/90 Tower/javascript/tower.html @@ -0,0 +1,9 @@ + + +TOWER + + +


+
+
+
diff --git a/90 Tower/javascript/tower.js b/90 Tower/javascript/tower.js
new file mode 100644
index 00000000..06e8745c
--- /dev/null
+++ b/90 Tower/javascript/tower.js	
@@ -0,0 +1,254 @@
+// TOWER
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var ta = [];
+
+// Print subroutine
+function show_towers()
+{
+    var z;
+    
+    for (var k = 1; k <= 7; k++) {
+        z = 10;
+        str = "";
+        for (var j = 1; j <= 3; j++) {
+            if (ta[k][j] != 0) {
+                while (str.length < z - Math.floor(ta[k][j] / 2))
+                    str += " ";
+                for (v = 1; v <= ta[k][j]; v++)
+                    str += "*";
+            } else {
+                while (str.length < z)
+                    str += " ";
+                str += "*";
+            }
+            z += 21;
+        }
+        print(str + "\n");
+    }
+}
+
+// Main control section
+async function main()
+{
+    print(tab(33) + "TOWERS\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("\n");
+        // Initialize
+        e = 0;
+        for (d = 1; d <= 7; d++) {
+            ta[d] = [];
+            for (n = 1; n <= 3; n++)
+                ta[d][n] = 0;
+        }
+        print("TOWERS OF HANOI PUZZLE.\n");
+        print("\n");
+        print("YOU MUST TRANSFER THE DISKS FROM THE LEFT TO THE RIGHT\n");
+        print("TOWER, ONE AT A TIME, NEVER PUTTING A LARGER DISK ON A\n");
+        print("SMALLER DISK.\n");
+        print("\n");
+        while (1) {
+            print("HOW MANY DISKS DO YOU WANT TO MOVE (7 IS MAX)");
+            s = parseInt(await input());
+            print("\n");
+            m = 0;
+            if (s >= 1 && s <= 7)
+                break;
+            e++;
+            if (e < 2) {
+                print("SORRY, BUT I CAN'T DO THAT JOB FOR YOU.\n");
+                continue;
+            }
+            print("ALL RIGHT, WISE GUY, IF YOU CAN'T PLAY THE GAME RIGHT, I'LL\n");
+            print("JUST TAKE MY PUZZLE AND GO HOME.  SO LONG.\n");
+            return;
+        }
+        // Store disks from smallest to largest
+        print("IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.\n");
+        print("3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,\n");
+        print("7 THE NEXT, AND SO ON, UP TO 15.  IF YOU DO THE PUZZLE WITH\n");
+        print("2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15.  WITH 3 DISKS\n");
+        print("THE CODE NAMES WOULD BE 11, 13 AND 15, ETC.  THE NEEDLES\n");
+        print("ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3.  WE WILL\n");
+        print("START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM\n");
+        print("TO NEEDLE 3.\n");
+        print("\n");
+        print("GOOD LUCK!\n");
+        print("\n");
+        y = 7;
+        d = 15;
+        for (x = s; x >= 1; x--) {
+            ta[y][1] = d;
+            d -= 2;
+            y--;
+        }
+        show_towers();
+        while (1) {
+            print("WHICH DISK WOULD YOU LIKE TO MOVE");
+            e = 0;
+            while (1) {
+                d = parseInt(await input());
+                if (d % 2 == 0 || d < 3 || d > 15) {
+                    print("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.\n");
+                    e++;
+                    if (e <= 1)
+                        continue;
+                    print("STOP WASTING MY TIME.  GO BOTHER SOMEONE ELSE.\n");
+                    return;
+                } else {
+                    break;
+                }
+            }
+            // Check if requested disk is below another
+            for (r = 1; r <= 7; r++) {
+                for (c = 1; c <= 3; c++) {
+                    if (ta[r][c] == d)
+                        break;
+                }
+                if (c <= 3)
+                    break;
+            }
+            for (q = r; q >= 1; q--) {
+                if (ta[q][c] != 0 && ta[q][c] < d)
+                    break;
+            }
+            if (q >= 1) {
+                print("THAT DISK IS BELOW ANOTHER ONE.  MAKE ANOTHER CHOICE.\n");
+                continue;
+            }
+            e = 0;
+            while (1) {
+                print("PLACE DISK ON WHICH NEEDLE");
+                n = parseInt(await input());
+                if (n >= 1 && n <= 3)
+                    break;
+                e++;
+                if (e <= 1) {
+                    print("I'LL ASSUME YOU HIT THE WRONG KEY THI TIME.  BUT WATCH IT,\n");
+                    print("I ONLY ALLOW ONE MISTAKE.\n");
+                    continue;
+                } else {
+                    print("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN.\n");
+                    print("BYE BYE, BIG SHOT.\n");
+                    return;
+                }
+            }
+            // Check if requested disk is below another
+            for (r = 1; r <= 7; r++) {
+                if (ta[r][n] != 0)
+                    break;
+            }
+            if (r <= 7) {
+                // Check if disk to be placed on a larger one
+                if (d >= ta[r][n]) {
+                    print("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE,\n");
+                    print("IT MIGHT CRUSH IT!\n");
+                    print("NOW THEN, ");
+                    continue;
+                }
+            }
+            // Move relocated disk
+            for (v = 1; v <= 7; v++) {
+                for (w = 1; w <= 3; w++) {
+                    if (ta[v][w] == d)
+                        break;
+                }
+                if (w <= 3)
+                    break;
+            }
+            // Locate empty space on needle n
+            for (u = 1; u <= 7; u++) {
+                if (ta[u][n] != 0)
+                    break;
+            }
+            ta[--u][n] = ta[v][w];
+            ta[v][w] = 0;
+            // Print out current status
+            show_towers();
+            // Check if done
+            m++;
+            for (r = 1; r <= 7; r++) {
+                for (c = 1; c <= 2; c++) {
+                    if (ta[r][c] != 0)
+                        break;
+                }
+                if (c <= 2)
+                    break;
+            }
+            if (r > 7)
+                break;
+            if (m > 128) {
+                print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN\n");
+                print("128 MOVES.\n");
+                return;
+            }
+        }
+        if (m == Math.pow(2, s) - 1) {
+            print("\n");
+            print("CONGRATULATIONS!!\n");
+            print("\n");
+        }
+        print("YOU HAVE PERFORMED THE TASK IN " + m + " MOVES.\n");
+        print("\n");
+        print("TRY AGAIN (YES OR NO)");
+        while (1) {
+            str = await input();
+            if (str == "YES" || str == "NO")
+                break;
+            print("\n");
+            print("'YES' OR 'NO' PLEASE");
+        }
+        if (str == "NO")
+            break;
+    }
+    print("\n");
+    print("THANKS FOR THE GAME!\n");
+    print("\n");
+}
+
+main();

From 6b2952fa72066abd926a0f3827c768dd64e6386c Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 15 Mar 2021 22:10:32 -0600
Subject: [PATCH 299/749] Ported 3DTICTACTOE to Javascript

---
 88 3-D Tic-Tac-Toe/javascript/qubit.html |   9 +
 88 3-D Tic-Tac-Toe/javascript/qubit.js   | 448 +++++++++++++++++++++++
 2 files changed, 457 insertions(+)
 create mode 100644 88 3-D Tic-Tac-Toe/javascript/qubit.html
 create mode 100644 88 3-D Tic-Tac-Toe/javascript/qubit.js

diff --git a/88 3-D Tic-Tac-Toe/javascript/qubit.html b/88 3-D Tic-Tac-Toe/javascript/qubit.html
new file mode 100644
index 00000000..813015bb
--- /dev/null
+++ b/88 3-D Tic-Tac-Toe/javascript/qubit.html	
@@ -0,0 +1,9 @@
+
+
+QUBIT
+
+
+

+
+
+
diff --git a/88 3-D Tic-Tac-Toe/javascript/qubit.js b/88 3-D Tic-Tac-Toe/javascript/qubit.js
new file mode 100644
index 00000000..9d73734d
--- /dev/null
+++ b/88 3-D Tic-Tac-Toe/javascript/qubit.js	
@@ -0,0 +1,448 @@
+// QUBIT
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var xa = [];
+var la = [];
+var ma = [[],
+          [,1,2,3,4],    // 1
+          [,5,6,7,8],    // 2
+          [,9,10,11,12], // 3
+          [,13,14,15,16],    // 4
+          [,17,18,19,20],    // 5
+          [,21,22,23,24],    // 6
+          [,25,26,27,28],    // 7
+          [,29,30,31,32],    // 8
+          [,33,34,35,36],    // 9
+          [,37,38,39,40],    // 10
+          [,41,42,43,44],    // 11
+          [,45,46,47,48],    // 12
+          [,49,50,51,52],    // 13
+          [,53,54,55,56],    // 14
+          [,57,58,59,60],    // 15
+          [,61,62,63,64],    // 16
+          [,1,17,33,49], // 17
+          [,5,21,37,53],    // 18
+          [,9,25,41,57],   // 19
+          [,13,29,45,61], // 20
+          [,2,18,34,50], // 21
+          [,6,22,38,54],    // 22
+          [,10,26,42,58],  // 23
+          [,14,30,46,62],   // 24
+          [,3,19,35,51], // 25
+          [,7,23,39,55],    // 26
+          [,11,27,43,59],  // 27
+          [,15,31,47,63], // 28
+          [,4,20,36,52], // 29
+          [,8,24,40,56], // 30
+          [,12,28,44,60],    // 31
+          [,16,32,48,64],    // 32
+          [,1,5,9,13],   // 33
+          [,17,21,25,29],    // 34
+          [,33,37,41,45],    // 35
+          [,49,53,57,61],    // 36
+          [,2,6,10,14],  // 37
+          [,18,22,26,30],    // 38
+          [,34,38,42,46],    // 39
+          [,50,54,58,62],    // 40
+          [,3,7,11,15],  // 41
+          [,19,23,27,31],    // 42
+          [,35,39,43,47],    // 43
+          [,51,55,59,63],    // 44
+          [,4,8,12,16],  // 45
+          [,20,24,28,32],    // 46
+          [,36,40,44,48],    // 47
+          [,52,56,60,64],    // 48
+          [,1,6,11,16],  // 49
+          [,17,22,27,32],    // 50
+          [,33,38,43,48],    // 51
+          [,49,54,59,64],    // 52
+          [,13,10,7,4],  // 53
+          [,29,26,23,20],    // 54
+          [,45,42,39,36],    // 55
+          [,61,58,55,52],    // 56
+          [,1,21,41,61], // 57
+          [,2,22,42,62], // 58
+          [,3,23,43,63], // 59
+          [,4,24,44,64], // 60
+          [,49,37,25,13],    // 61
+          [,50,38,26,14],    // 62
+          [,51,39,27,15],    // 63
+          [,52,40,28,16],    // 64
+          [,1,18,35,52], // 65
+          [,5,22,39,56], // 66
+          [,9,26,43,60], // 67
+          [,13,30,47,64],    // 68
+          [,49,34,19,4], // 69
+          [,53,38,23,8], // 70
+          [,57,42,27,12],    // 71
+          [,61,46,31,16],    // 72
+          [,1,22,43,64], // 73
+          [,16,27,38,49],    // 74
+          [,4,23,42,61], // 75
+          [,13,26,39,52] // 76
+          ];
+var ya = [,1,49,52,4,13,61,64,16,22,39,23,38,26,42,27,43];
+
+function show_board()
+{
+    for (xx = 1; xx <= 9; xx++)
+        print("\n");
+    for (i = 1; i <= 4; i++) {
+        for (j = 1; j <= 4; j++) {
+            str = "";
+            for (i1 = 1; i1 <= j; i1++)
+                str += "   ";
+            for (k = 1; k <= 4; k++) {
+                q = 16 * i + 4 * j + k - 20;
+                if (xa[q] == 0)
+                    str += "( )      ";
+                if (xa[q] == 5)
+                    str += "(M)      ";
+                if (xa[q] == 1)
+                    str += "(Y)      ";
+                if (xa[q] == 1 / 8)
+                    str += "( )      ";
+            }
+            print(str + "\n");
+            print("\n");
+        }
+        print("\n");
+        print("\n");
+    }
+}
+
+function process_board()
+{
+    for (i = 1; i <= 64; i++) {
+        if (xa[i] == 1 / 8)
+            xa[i] = 0;
+    }
+}
+
+function check_for_lines()
+{
+    for (s = 1; s <= 76; s++) {
+        j1 = ma[s][1];
+        j2 = ma[s][2];
+        j3 = ma[s][3];
+        j4 = ma[s][4];
+        la[s] = xa[j1] + xa[j2] + xa[j3] + xa[j4];
+    }
+}
+
+function show_square(m)
+{
+    k1 = Math.floor((m - 1) / 16) + 1;
+    j2 = m - 16 * (k1 - 1);
+    k2 = Math.floor((j2 - 1) / 4) + 1;
+    k3 = m - (k1 - 1) * 16 - (k2 - 1) * 4;
+    m = k1 * 100 + k2 * 10 + k3;
+    print(" " + m + " ");
+}
+
+function select_move() {
+    if (i % 4 <= 1) {
+        a = 1;
+    } else {
+        a = 2;
+    }
+    for (j = a; j <= 5 - a; j += 5 - 2 * a) {
+        if (xa[ma[i][j]] == s)
+            break;
+    }
+    if (j > 5 - a)
+        return false;
+    xa[ma[i][j]] = s;
+    m = ma[i][j];
+    print("MACHINE TAKES");
+    show_square(m);
+    return true;
+}
+
+// Main control section
+async function main()
+{
+    print(tab(33) + "QUBIC\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("DO YOU WANT INSTRUCTIONS");
+        str = await input();
+        str = str.substr(0, 1);
+        if (str == "Y" || str == "N")
+            break;
+        print("INCORRECT ANSWER.  PLEASE TYPE 'YES' OR 'NO'");
+    }
+    if (str == "Y") {
+        print("\n");
+        print("THE GAME IS TIC-TAC-TOE IN A 4 X 4 X 4 CUBE.\n");
+        print("EACH MOVE IS INDICATED BY A 3 DIGIT NUMBER, WITH EACH\n");
+        print("DIGIT BETWEEN 1 AND 4 INCLUSIVE.  THE DIGITS INDICATE THE\n");
+        print("LEVEL, ROW, AND COLUMN, RESPECTIVELY, OF THE OCCUPIED\n");
+        print("PLACE.  \n");
+        print("\n");
+        print("TO PRINT THE PLAYING BOARD, TYPE 0 (ZERO) AS YOUR MOVE.\n");
+        print("THE PROGRAM WILL PRINT THE BOARD WITH YOUR MOVES INDI-\n");
+        print("CATED WITH A (Y), THE MACHINE'S MOVES WITH AN (M), AND\n");
+        print("UNUSED SQUARES WITH A ( ).  OUTPUT IS ON PAPER.\n");
+        print("\n");
+        print("TO STOP THE PROGRAM RUN, TYPE 1 AS YOUR MOVE.\n");
+        print("\n");
+        print("\n");
+    }
+    while (1) {
+        for (i = 1; i <= 64; i++)
+            xa[i] = 0;
+        z = 1;
+        print("DO YOU WANT TO MOVE FIRST");
+        while (1) {
+            str = await input();
+            str = str.substr(0, 1);
+            if (str == "Y" || str == "N")
+                break;
+            print("INCORRECT ANSWER.  PLEASE TYPE 'YES' OR 'NO'");
+        }
+        while (1) {
+            while (1) {
+                print(" \n");
+                print("YOUR MOVE");
+                j1 = parseInt(await input());
+                if (j1 == 0) {
+                    show_board();
+                    continue;
+                }
+                if (j1 == 1)
+                    return;
+                k1 = Math.floor(j1 / 100);
+                j2 = j1 - k1 * 100;
+                k2 = Math.floor(j2 / 10);
+                k3 = j2 - k2 * 10;
+                m = 16 * k1 + 4 * k2 + k3 - 20;
+                if (k1 < 1 || k2 < 1 || k3 < 1 || k1 > 4 || k2 > 4 || k3 >> 4) {
+                    print("INCORRECT MOVE, RETYPE IT--");
+                } else {
+                    process_board();
+                    if (xa[m] != 0) {
+                        print("THAT SQUARE IS USED, TRY AGAIN.\n");
+                    } else {
+                        break;
+                    }
+                }
+            }
+            xa[m] = 1;
+            check_for_lines();
+            status = 0;
+            for (j = 1; j <= 3; j++) {
+                for (i = 1; i <= 76; i++) {
+                    if (j == 1) {
+                        if (la[i] != 4)
+                            continue;
+                        print("YOU WIN AS FOLLOWS");
+                        for (j = 1; j <= 4; j++) {
+                            m = ma[i][j];
+                            show_square(m);
+                        }
+                        status = 1;
+                        break;
+                    }
+                    if (j == 2) {
+                        if (la[i] != 15)
+                            continue;
+                        for (j = 1; j <= 4; j++) {
+                            m = ma[i][j];
+                            if (xa[m] != 0)
+                                continue;
+                            xa[m] = 5;
+                            print("MACHINE MOVES TO ");
+                            show_square(m);
+                        }
+                        print(", AND WINS AS FOLLOWS");
+                        for (j = 1; j <= 4; j++) {
+                            m = ma[i][j];
+                            show_square(m);
+                        }
+                        status = 1;
+                        break;
+                    }
+                    if (j == 3) {
+                        if (la[i] != 3)
+                            continue;
+                        print("NICE TRY, MACHINE MOVES TO");
+                        for (j = 1; j <= 4; j++) {
+                            m = ma[i][j];
+                            if (xa[m] != 0)
+                                continue;
+                            xa[m] = 5;
+                            show_square(m);
+                            status = 2;
+                        }
+                        break;
+                    }
+                }
+                if (i <= 76)
+                    break;
+            }
+            if (status == 2)
+                continue;
+            if (status == 1)
+                break;
+            // x = x; non-useful in original
+            i = 1;
+            do {
+                la[i] = xa[ma[i][1]] + xa[ma[i][2]] + xa[ma[i][3]] + xa[ma[i][4]];
+                l = la[i];
+                if (l == 10) {
+                    for (j = 1; j <= 4; j++) {
+                        if (xa[ma[i][j]] == 0)
+                            xa[ma[i][j]] = 1 / 8;
+                    }
+                }
+            } while (++i <= 76) ;
+            check_for_lines();
+            i = 1;
+            do {
+                if (la[i] == 0.5) {
+                    s = 1 / 8;
+                    select_move();
+                    break;
+                }
+                if (la[i] == 5 + 3 / 8) {
+                    s = 1 / 8;
+                    select_move();
+                    break;
+                }
+            } while (++i <= 76) ;
+            if (i <= 76)
+                continue;
+            
+            process_board();
+            
+            i = 1;
+            do {
+                la[i] = xa[ma[i][1]] + xa[ma[i][2]] + xa[ma[i][3]] + xa[ma[i][4]];
+                l = la[i];
+                if (l == 2) {
+                    for (j = 1; j <= 4; j++) {
+                        if (xa[ma[i][j]] == 0)
+                            xa[ma[i][j]] = 1 / 8;
+                    }
+                }
+            } while (++i <= 76) ;
+            check_for_lines();
+            i = 1;
+            do {
+                if (la[i] == 0.5) {
+                    s = 1 / 8;
+                    select_move();
+                    break;
+                }
+                if (la[i] == 1 + 3 / 8) {
+                    s = 1 / 8;
+                    select_move();
+                    break;
+                }
+            } while (++i <= 76) ;
+            if (i <= 76)
+                continue;
+            
+            for (k = 1; k <= 18; k++) {
+                p = 0;
+                for (i = 4 * k - 3; i <= 4 * k; i++) {
+                    for (j = 1; j <= 4; j++)
+                        p += xa[ma[i][j]];
+                }
+                if (p == 4 || p == 9) {
+                    s = 1 / 8;
+                    for (i = 4 * k - 3; i <= 4 * k; i++) {
+                        if (select_move())
+                            break;
+                    }
+                    s = 0;
+                }
+            }
+            if (k <= 18)
+                continue
+            process_board();
+            z = 1;
+            do {
+                if (xa[ya[z]] == 0)
+                    break;
+            } while (++z < 17) ;
+            if (z >= 17) {
+                for (i = 1; i <= 64; i++) {
+                    if (xa[i] == 0) {
+                        xa[i] = 5;
+                        m = i;
+                        print("MACHINE LIKES");
+                        break;
+                    }
+                }
+                if (i > 64) {
+                    print("THE GAME IS A DRAW.\n");
+                    break;
+                }
+            } else {
+                m = ya[z];
+                xa[m] = 5;
+                print("MACHINE MOVES TO");
+            }
+            show_square(m);
+        }
+        print(" \n");
+        print("DO YOU WANT TO TRY ANOTHER GAME");
+        while (1) {
+            str = await input();
+            str = str.substr(0, 1);
+            if (str == "Y" || str == "N")
+                break;
+            print("INCORRECT ANSWER. PLEASE TYPE 'YES' OR 'NO'");
+        }
+        if (str == "N")
+            break;
+    }
+}
+
+main();

From 8bea3b92f4c547f8ffc61621050a3fa8bf4f605d Mon Sep 17 00:00:00 2001
From: Todd Kaiser 
Date: Tue, 16 Mar 2021 15:29:25 -0600
Subject: [PATCH 300/749] Added major turn logic.

---
 77 Salvo/python/salvo.py | 193 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 169 insertions(+), 24 deletions(-)

diff --git a/77 Salvo/python/salvo.py b/77 Salvo/python/salvo.py
index 73ff55ec..3ebdcddc 100644
--- a/77 Salvo/python/salvo.py	
+++ b/77 Salvo/python/salvo.py	
@@ -10,10 +10,20 @@ import random
 BOARD_WIDTH = 10
 BOARD_HEIGHT = 10
 
-SHIPS = [("BATTLESHIP", 5),
-         ("CRUISER", 3),
-         ("DESTROYER
", 2), - ("DESTROYER", 2)] +# game ships +# +# data structure keeping track of information +# about the ships in the game. for each ship, +# the following information is provided: +# +# name - string representation of the ship +# length - number of "parts" on the ship that +# can be shot +# shots - number of shots the ship counts for +SHIPS = [("BATTLESHIP", 5, 3), + ("CRUISER", 3, 2), + ("DESTROYER", 2, 1), + ("DESTROYER", 2, 1)] VALID_MOVES = [[-1, 0], # North [-1, 1], # North East @@ -46,6 +56,18 @@ computer_ship_coords = [] # keep track of the turn current_turn = 0 +#################################### +# +# SHOTS +# +# The number of shots computer/player +# has is determined by the shot "worth" +# of each ship the computer/player +# possesses. As long as the ship has one +# part not hit (i.e., ship was not +# sunk), the player gets all the shots +# from that ship. + # flag indicating if computer's shots are # printed out during computer's turn print_computer_shots = False @@ -60,6 +82,17 @@ num_computer_shots = 7 # initial shots are 7 num_player_shots = 7 +# +# SHOTS +# +#################################### + +# flag indicating whose turn +# it currently is +COMPUTER = 0 +PLAYER = 1 +active_turn = COMPUTER + #################### # # game functions @@ -241,7 +274,38 @@ def generate_board(): # execute a shot. returns True if the shot # is valid, False if not def execute_shot(board, x, y): - print("execute shot:", x, y) + + global current_turn + square = board[x-1][y-1] + if square is not None: + if square >= 0 and square < len(SHIPS): + if active_turn == PLAYER: + print("YOU HIT MY", SHIPS[square][0]) + else: + print("I HIT YOUR", SHIPS[square][0]) + + board[x-1][y-1] = 10 + current_turn + + +# calculate_shots +# +# function to examine each board +# and determine how many shots remaining +def calculate_shots(board): + + ships_found = [0 for x in range(len(SHIPS))] + for x in range(BOARD_HEIGHT): + for y in range(BOARD_WIDTH): + square = board[x-1][y-1] + if square is not None: + if square >= 0 and square < len(SHIPS): + ships_found[square] = 1 + shots = 0 + for ship in range(len(ships_found)): + if ships_found[ship] == 1: + shots += SHIPS[ship][2] + + return shots # initialize @@ -309,8 +373,14 @@ def initialize_game(): global first_turn global second_turn if player_start.lower() != "yes": - first_turn = computer_turn - second_turn = player_turn + first_turn = COMPUTER + second_turn = PLAYER + + # calculate the initial number of shots for each + global num_computer_shots + global num_player_shots + num_player_shots = calculate_shots(player_board) + num_computer_shots = calculate_shots(computer_board) #################################### @@ -322,32 +392,94 @@ def initialize_game(): # functions, we can easily start the game with # either computer or player and alternate back and # forth, replicating the gotos in the original game + + +# initialize the first_turn function to the +# player's turn +first_turn = PLAYER + + +# initialize the second_turn to the computer's +# turn +second_turn = COMPUTER + + def player_turn(): - print("YOU HAVE", num_computer_shots, "SHOTS.") + print("YOU HAVE", num_player_shots, "SHOTS.") + global active_turn + active_turn = PLAYER shots = [] for shot in range(num_player_shots): valid_shot = False while not valid_shot: x, y = input_coord() - valid_shot = execute_shot(player_board, x, y) + square = computer_board[x-1][y-1] + if square is not None: + if square > 10: + if active_turn == PLAYER: + print("YOU SHOT THERE BEFORE ON TURN", square - 10) + continue shots.append((x, y)) - - print(shots) + valid_shot = True + for shot in shots: + execute_shot(computer_board, shot[0], shot[1]) -# initialize the first_turn function to the -# player's turn -first_turn = player_turn +def execute_turn(turn): + global num_computer_shots + global num_player_shots -def computer_turn(): - print("I HAVE", num_computer_shots, "SHOTS.") + # print out the number of shots the current + # player has + board = None + num_shots = 0 + if turn == COMPUTER: + print("I HAVE", num_computer_shots, "SHOTS.") + board = player_board + num_shots = num_computer_shots + else: + print("YOU HAVE", num_player_shots, "SHOTS.") + board = computer_board + num_shots = num_player_shots + shots = [] + for shot in range(num_shots): + valid_shot = False + x = -1 + y = -1 + + # loop until we have a valid shot. for the + # computer, we randomly pick a shot. for the + # player we request shots + while not valid_shot: + if turn == COMPUTER: + x, y = random_x_y() + else: + x, y = input_coord() + square = board[x-1][y-1] + if square is not None: + if square > 10: + if turn == PLAYER: + print("YOU SHOT THERE BEFORE ON TURN", square - 10) + continue + shots.append((x, y)) + valid_shot = True + + for shot in shots: + execute_shot(board, shot[0], shot[1]) + if turn == COMPUTER: + if print_computer_shots: + print(shot[0], shot[1]) + + if turn == COMPUTER: + num_player_shots = calculate_shots(board) + return num_player_shots + else: + num_computer_shots = calculate_shots(board) + return num_computer_shots -# initialize the second_turn to the computer's -# turn -second_turn = computer_turn # # Turn Control @@ -367,9 +499,22 @@ initialize_game() # execute turns until someone wins or we run # out of squares to shoot -current_turn = current_turn + 1 -print("\n") -print("TURN", current_turn) +game_over = False +while not game_over: -first_turn() -second_turn() + # increment the turn + current_turn = current_turn + 1 + + print("\n") + print("TURN", current_turn) + print("computer") + print_board(computer_board) + print("player") + print_board(player_board) + + if execute_turn(first_turn) == 0: + game_over = True + continue + if execute_turn(second_turn) == 0: + game_over = True + continue From e6e6a52646053b956cd9b157d8762ddc9c12ef17 Mon Sep 17 00:00:00 2001 From: Todd Kaiser Date: Tue, 16 Mar 2021 18:19:01 -0600 Subject: [PATCH 301/749] Cleaned up debug statements and program flow. Fixed a couple of bugs from testing --- 77 Salvo/python/salvo.py | 44 +++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/77 Salvo/python/salvo.py b/77 Salvo/python/salvo.py index 3ebdcddc..bad23352 100644 --- a/77 Salvo/python/salvo.py +++ b/77 Salvo/python/salvo.py @@ -147,8 +147,24 @@ def input_coord(): return x, y -# TODO: add an optional starting coordinate for testing -# purposes +# generate_ship_coordinates +# +# given a ship from the SHIPS array, generate +# the coordinates of the ship. the starting point +# of the ship's first coordinate is generated randomly. +# once the starting coordinates are determined, the +# possible directions of the ship, accounting for the +# edges of the board, are determined. once possible +# directions are found, a direction is randomly +# determined and the remaining coordinates are +# generated by adding or substraction from the starting +# coordinates as determined by direction. +# +# arguments: +# ship - index into the SHIPS array +# +# returns: +# array of sets of coordinates (x,y) def generate_ship_coordinates(ship): # randomly generate starting x,y coordinates start_x, start_y = random_x_y() @@ -273,16 +289,16 @@ def generate_board(): # given a board and x, y coordinates, # execute a shot. returns True if the shot # is valid, False if not -def execute_shot(board, x, y): +def execute_shot(turn, board, x, y): global current_turn square = board[x-1][y-1] if square is not None: if square >= 0 and square < len(SHIPS): - if active_turn == PLAYER: - print("YOU HIT MY", SHIPS[square][0]) - else: + if turn == COMPUTER: print("I HIT YOUR", SHIPS[square][0]) + else: + print("YOU HIT MY", SHIPS[square][0]) board[x-1][y-1] = 10 + current_turn @@ -328,7 +344,10 @@ def initialize_game(): # print out the title 'screen' print('{0:>38}'.format("SALVO")) print('{0:>57s}'.format("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")) - print('\n\n') + print('') + print('{0:>52s}'.format("ORIGINAL BY LAWRENCE SIEGEL, 1973")) + print('{0:>56s}'.format("PYTHON 3 PORT BY TODD KAISER, MARCH 2021")) + print('\n') # ask the player for ship coordinates print("ENTER COORDINATES FOR...") @@ -468,7 +487,7 @@ def execute_turn(turn): valid_shot = True for shot in shots: - execute_shot(board, shot[0], shot[1]) + execute_shot(turn, board, shot[0], shot[1]) if turn == COMPUTER: if print_computer_shots: print(shot[0], shot[1]) @@ -507,10 +526,11 @@ while not game_over: print("\n") print("TURN", current_turn) - print("computer") - print_board(computer_board) - print("player") - print_board(player_board) + + # print("computer") + # print_board(computer_board) + # print("player") + # print_board(player_board) if execute_turn(first_turn) == 0: game_over = True From 7222546bcff87248551b26c89374960bb63c63d9 Mon Sep 17 00:00:00 2001 From: Todd Kaiser Date: Tue, 16 Mar 2021 19:28:55 -0600 Subject: [PATCH 302/749] Fixed the order of printing out which ships were hit. Original game printed out ships that were hit AFTER updating the board, not during. getting close to done! --- 77 Salvo/python/salvo.py | 42 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/77 Salvo/python/salvo.py b/77 Salvo/python/salvo.py index bad23352..0dd19816 100644 --- a/77 Salvo/python/salvo.py +++ b/77 Salvo/python/salvo.py @@ -293,14 +293,12 @@ def execute_shot(turn, board, x, y): global current_turn square = board[x-1][y-1] + ship_hit = -1 if square is not None: if square >= 0 and square < len(SHIPS): - if turn == COMPUTER: - print("I HIT YOUR", SHIPS[square][0]) - else: - print("YOU HIT MY", SHIPS[square][0]) - + ship_hit = square board[x-1][y-1] = 10 + current_turn + return ship_hit # calculate_shots @@ -423,28 +421,6 @@ first_turn = PLAYER second_turn = COMPUTER -def player_turn(): - print("YOU HAVE", num_player_shots, "SHOTS.") - global active_turn - active_turn = PLAYER - - shots = [] - for shot in range(num_player_shots): - valid_shot = False - while not valid_shot: - x, y = input_coord() - square = computer_board[x-1][y-1] - if square is not None: - if square > 10: - if active_turn == PLAYER: - print("YOU SHOT THERE BEFORE ON TURN", square - 10) - continue - shots.append((x, y)) - valid_shot = True - for shot in shots: - execute_shot(computer_board, shot[0], shot[1]) - - def execute_turn(turn): global num_computer_shots @@ -486,12 +462,22 @@ def execute_turn(turn): shots.append((x, y)) valid_shot = True + hits = [] for shot in shots: - execute_shot(turn, board, shot[0], shot[1]) + hit = execute_shot(turn, board, shot[0], shot[1]) + if hit >= 0: + hits.append(hit) if turn == COMPUTER: if print_computer_shots: print(shot[0], shot[1]) + for hit in hits: + if turn == COMPUTER: + print("I HIT YOUR", SHIPS[hit][0]) + else: + print("YOU HIT MY", SHIPS[hit][0]) + + if turn == COMPUTER: num_player_shots = calculate_shots(board) return num_player_shots From e96306d796afd78eda029600a0367e47459c0126 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Wed, 17 Mar 2021 10:31:39 -0600 Subject: [PATCH 303/749] Create hi-lo.pl Made with Perl! --- 47 Hi-Lo/perl/hi-lo.pl | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 47 Hi-Lo/perl/hi-lo.pl diff --git a/47 Hi-Lo/perl/hi-lo.pl b/47 Hi-Lo/perl/hi-lo.pl new file mode 100644 index 00000000..08173a56 --- /dev/null +++ b/47 Hi-Lo/perl/hi-lo.pl @@ -0,0 +1,45 @@ +#!/usr/bin/perl +use strict; + + +print ' 'x 34 . "HI LO\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +print "THIS IS THE GAME OF HI LO.\n"; print "\n"; +print "YOU WILL HAVE 6 TRIES TO GUESS THE AMOUNT OF MONEY IN THE\n"; +print "HI LO JACKPOT, WHICH IS BETWEEN 1 AND 100 DOLLARS. IF YOU\n"; +print "GUESS THE AMOUNT, YOU WIN ALL THE MONEY IN THE JACKPOT!\n"; +print "THEN YOU GET ANOTHER CHANCE TO WIN MORE MONEY. HOWEVER,\n"; +print "IF YOU DO NOT GUESS THE AMOUNT, THE GAME ENDS.\n"; print "\n"; +my $R=0; +my $A; +do { + print "\n"; + my $Y=int(100*rand(1)); + foreach (1..6) { + print "YOUR GUESS $Y"; + print "? "; chomp($A = ); + if ($A eq $Y) { last; } + if ($A>$Y) { + print "YOUR GUESS IS TOO HIGH.\n"; + } else { + print "YOUR GUESS IS TOO LOW.\n"; + } + print "\n"; + } + + if ($A==$Y) { + $R=$R+$Y; + print "GOT IT!!!!!!!!!! YOU WIN $Y DOLLARS.\n"; + print "YOUR TOTAL WINNINGS ARE NOW $R DOLLARS.\n"; + } else { + $R=0; + print "YOU BLEW IT...TOO BAD...THE NUMBER WAS $Y" + } + print "\n"; print "PLAY AGAIN (YES OR NO)"; + print "? "; chomp($A = ); + } until (uc($A) ne "YES"); +print "\n"; print "SO LONG. HOPE YOU ENJOYED YOURSELF!!!\n"; +exit; + + From 7874f924bf34624e2c19da050b5c4a0e7ebf13da Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Wed, 17 Mar 2021 11:44:37 -0600 Subject: [PATCH 304/749] Create dice.pl Made with Perl! --- 33 Dice/perl/dice.pl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 33 Dice/perl/dice.pl diff --git a/33 Dice/perl/dice.pl b/33 Dice/perl/dice.pl new file mode 100644 index 00000000..cb051b0a --- /dev/null +++ b/33 Dice/perl/dice.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl +use strict; + + +print ' 'x 34 . "DICE\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; +my @F; + +#REM DANNY FREIDUS; +print "THIS PROGRAM SIMULATES THE ROLLING OF A\n"; +print "PAIR OF DICE.\n"; +print "YOU ENTER THE NUMBER OF TIMES YOU WANT THE COMPUTER TO\n"; +print "'ROLL' THE DICE. WATCH OUT, VERY LARGE NUMBERS TAKE\n"; +print "A LONG TIME. IN PARTICULAR, NUMBERS OVER 5000.\n"; + +my $X; +my $Z; +do { + for (my $Q=1; $Q<=12; $Q++) { + $F[$Q]=0; + } + print "\n"; print "HOW MANY ROLLS"; + print "? "; chomp($X = ); + for (my $S=1; $S<=$X; $S++) { + my $A=int(6*rand(1)+1); + my $B=int(6*rand(1)+1); + my $R=$A+$B; + $F[$R]=$F[$R]+1; + } + print "\n"; + print "TOTAL SPOTS\tNUMBER OF TIMES\n"; + for (my $V=2; $V<=12; $V++) { + print "$V\t\t$F[$V]\n"; + } + print "\n"; + print "\n"; print "TRY AGAIN"; + print "? "; chomp($Z = ); + } until (uc($Z) ne "YES"); +exit; + + From 057ed8c6cff59d7fd988e874687f7863b6405de8 Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sat, 20 Mar 2021 16:21:42 +0400 Subject: [PATCH 305/749] Ported 95 Weekday to Java --- 95 Weekday/java/Weekday.java | 280 +++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 95 Weekday/java/Weekday.java diff --git a/95 Weekday/java/Weekday.java b/95 Weekday/java/Weekday.java new file mode 100644 index 00000000..9ca3db11 --- /dev/null +++ b/95 Weekday/java/Weekday.java @@ -0,0 +1,280 @@ +import java.util.Scanner; + +/** + * WEEKDAY + * + * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + * + */ +public class Weekday { + + //TABLE OF VALUES FOR THE MONTHS TO BE USED IN CALCULATIONS. + //Dummy value added at index 0, so we can reference directly by the month number value + private final static int[] t = new int[]{-1, 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; + + public static void main(String[] args) { + printIntro(); + + Scanner scanner = new Scanner(System.in); + System.out.print("ENTER TODAY'S DATE IN THE FORM: 3,24,1979 "); + DateStruct todaysDate = readDate(scanner); + + System.out.print("ENTER DAY OF BIRTH (OR OTHER DAY OF INTEREST) "); + DateStruct dateOfInterest = readDate(scanner); + + int I1 = (dateOfInterest.year - 1500) / 100; + //TEST FOR DATE BEFORE CURRENT CALENDAR. + if ((dateOfInterest.year - 1582) >= 0) { + int A = I1 * 5 + (I1 + 3) / 4; + int I2 = (A - b(A) * 7); + int Y2 = (dateOfInterest.year / 100); + int Y3 = (dateOfInterest.year - Y2 * 100); + A = Y3 / 4 + Y3 + dateOfInterest.day + t[dateOfInterest.month] + I2; + calculateAndPrintDayOfWeek(I1, A, todaysDate, dateOfInterest, Y3); + + if ((todaysDate.year * 12 + todaysDate.month) * 31 + todaysDate.day + == (dateOfInterest.year * 12 + dateOfInterest.month) * 31 + dateOfInterest.day) { + return; //stop the program + } + + int I5 = todaysDate.year - dateOfInterest.year; + System.out.print("\n"); + int I6 = todaysDate.month - dateOfInterest.month; + int I7 = todaysDate.day - dateOfInterest.day; + if (I7 < 0) { + I6 = I6 - 1; + I7 = I7 + 30; + } + if (I6 < 0) { + I5 = I5 - 1; + I6 = I6 + 12; + } + if (I5 < 0) { + return; //do nothing. end the program + } else { + if (I7 != 0) { + printHeadersAndAge(I5, I6, I7); + } else { + if (I6 != 0) { + printHeadersAndAge(I5, I6, I7); + } else { + System.out.println("***HAPPY BIRTHDAY***"); + printHeadersAndAge(I5, I6, I7); + } + } + } + + int A8 = (I5 * 365) + (I6 * 30) + I7 + (I6 / 2); + int K5 = I5; + int K6 = I6; + int K7 = I7; + //CALCULATE RETIREMENT DATE. + int E = dateOfInterest.year + 65; + // CALCULATE TIME SPENT IN THE FOLLOWING FUNCTIONS. + float F = 0.35f; + System.out.printf("%-28s", "YOU HAVE SLEPT"); + DateStruct scratchDate = new DateStruct(K6, K7, K5); //K5 is a temp year, K6 is month, K7 is day + printStatisticRow(F, A8, scratchDate); + K5 = scratchDate.year; + K6 = scratchDate.month; + K7 = scratchDate.day; + + F = 0.17f; + System.out.printf("%-28s", "YOU HAVE EATEN"); + + scratchDate = new DateStruct(K6, K7, K5); + printStatisticRow(F, A8, scratchDate); + K5 = scratchDate.year; + K6 = scratchDate.month; + K7 = scratchDate.day; + + F = 0.23f; + if (K5 > 3) { + if (K5 > 9) { + System.out.printf("%-28s", "YOU HAVE WORKED/PLAYED"); + } else { + System.out.printf("%-28s", "YOU HAVE PLAYED/STUDIED"); + } + } else { + System.out.printf("%-28s", "YOU HAVE PLAYED"); + } + + scratchDate = new DateStruct(K6, K7, K5); + printStatisticRow(F, A8, scratchDate); + K5 = scratchDate.year; + K6 = scratchDate.month; + K7 = scratchDate.day; + + if (K6 == 12) { + K5 = K5 + 1; + K6 = 0; + } + System.out.printf("%-28s%14s%14s%14s%n", "YOU HAVE RELAXED", K5, K6, K7); + System.out.printf("%16s*** YOU MAY RETIRE IN %s ***%n", " ", E); + System.out.printf("%n%n%n%n%n"); + } else { + System.out.println("NOT PREPARED TO GIVE DAY OF WEEK PRIOR TO MDLXXXII."); + } + } + + + private static void printStatisticRow(float F, int A8, DateStruct scratchDate) { + int K1 = (int) (F * A8); + int I5 = K1 / 365; + K1 = K1 - (I5 * 365); + int I6 = K1 / 30; + int I7 = K1 - (I6 * 30); + int K5 = scratchDate.year - I5; + int K6 = scratchDate.month - I6; + int K7 = scratchDate.day - I7; + if (K7 < 0) { + K7 = K7 + 30; + K6 = K6 - 1; + } + if (K6 <= 0) { + K6 = K6 + 12; + K5 = K5 - 1; + } + //to return the updated values of K5, K6, K7 we send them through the scratchDate + scratchDate.year = K5; + scratchDate.month = K6; + scratchDate.day = K7; + System.out.printf("%14s%14s%14s%n", I5, I6, I7); + } + + private static void printHeadersAndAge(int I5, int I6, int I7) { + System.out.printf("%14s%14s%14s%14s%14s%n", " ", " ", "YEARS", "MONTHS", "DAYS"); + System.out.printf("%14s%14s%14s%14s%14s%n", " ", " ", "-----", "------", "----"); + System.out.printf("%-28s%14s%14s%14s%n", "YOUR AGE (IF BIRTHDATE)", I5, I6, I7); + } + + private static void calculateAndPrintDayOfWeek(int i1, int a, DateStruct dateStruct, DateStruct dateOfInterest, int y3) { + int b = (a - b(a) * 7) + 1; + if (dateOfInterest.month > 2) { + printDayOfWeek(dateStruct, dateOfInterest, b); + } else { + if (y3 == 0) { + int aa = i1 - 1; + int t1 = aa - a(aa) * 4; + if (t1 == 0) { + if (b != 0) { + b = b - 1; + printDayOfWeek(dateStruct, dateOfInterest, b); + } else { + b = 6; + b = b - 1; + printDayOfWeek(dateStruct, dateOfInterest, b); + } + } + } + } + } + + /** + * PRINT THE DAY OF THE WEEK THE DATE FALLS ON. + */ + private static void printDayOfWeek(DateStruct dateStruct, DateStruct dateOfInterest, int b) { + if (b == 0) { + b = 7; + } + if ((dateStruct.year * 12 + dateStruct.month) * 31 + + dateStruct.day + < + (dateOfInterest.year * 12 + + dateOfInterest.month) * 31 + dateOfInterest.day) { + System.out.printf("%s / %s / %s WILL BE A ", dateOfInterest.month, dateOfInterest.day, dateOfInterest.year); + } else if ((dateStruct.year * 12 + dateStruct.month) * 31 + + dateStruct.day == (dateOfInterest.year * 12 + dateOfInterest.month) + * 31 + dateOfInterest.day) { + System.out.printf("%s / %s / %s IS A ", dateOfInterest.month, dateOfInterest.day, dateOfInterest.year); + } else { + System.out.printf("%s / %s / %s WAS A ", dateOfInterest.month, dateOfInterest.day, dateOfInterest.year); + } + switch (b) { + case 1: + System.out.println("SUNDAY."); + break; + case 2: + System.out.println("MONDAY."); + break; + case 3: + System.out.println("TUESDAY."); + break; + case 4: + System.out.println("WEDNESDAY."); + break; + case 5: + System.out.println("THURSDAY."); + break; + case 6: + if (dateOfInterest.day == 13) { + System.out.println("FRIDAY THE THIRTEENTH---BEWARE!"); + } else { + System.out.println("FRIDAY."); + } + break; + case 7: + System.out.println("SATURDAY."); + break; + } + } + + private static int a(int a) { + return a / 4; + } + + private static int b(int a) { + return a / 7; + } + + + private static void printIntro() { + System.out.println(" WEEKDAY"); + System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n\n"); + System.out.println("WEEKDAY IS A COMPUTER DEMONSTRATION THAT"); + System.out.println("GIVES FACTS ABOUT A DATE OF INTEREST TO YOU."); + System.out.println("\n"); + } + + /** + * Read user input for a date, do some validation and return a simple date structure + */ + private static DateStruct readDate(Scanner scanner) { + boolean done = false; + int mm = 0, dd = 0, yyyy = 0; + while (!done) { + String input = scanner.next(); + String[] tokens = input.split(","); + if (tokens.length < 3) { + System.out.println("DATE EXPECTED IN FORM: 3,24,1979 - RETRY INPUT LINE"); + } else { + try { + mm = Integer.parseInt(tokens[0]); + dd = Integer.parseInt(tokens[1]); + yyyy = Integer.parseInt(tokens[2]); + done = true; + } catch (NumberFormatException nfe) { + System.out.println("NUMBER EXPECTED - RETRY INPUT LINE"); + } + } + } + return new DateStruct(mm, dd, yyyy); + } + + /** + * Convenience date structure to hold user date input + */ + private static class DateStruct { + int month; + int day; + int year; + + public DateStruct(int month, int day, int year) { + this.month = month; + this.day = day; + this.year = year; + } + } + +} From 36588fc1dbce2c7a6dd95f19bfa1eef7823e11b8 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sat, 20 Mar 2021 12:00:27 -0400 Subject: [PATCH 306/749] Ported Diamond to Java. --- 32 Diamond/java/Diamond.java | 163 +++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 32 Diamond/java/Diamond.java diff --git a/32 Diamond/java/Diamond.java b/32 Diamond/java/Diamond.java new file mode 100644 index 00000000..bbad33a7 --- /dev/null +++ b/32 Diamond/java/Diamond.java @@ -0,0 +1,163 @@ +import java.util.Scanner; + +/** + * Game of Diamond + *

+ * Based on the BASIC game of Diamond here + * https://github.com/coding-horror/basic-computer-games/blob/main/32%20Diamond/diamond.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Diamond { + + private static final int LINE_WIDTH = 60; + + private static final String PREFIX = "CC"; + + private static final char SYMBOL = '!'; + + private final Scanner scan; // For user input + + + public Diamond() { + + scan = new Scanner(System.in); + + } // End of constructor Diamond + + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + + private void showIntro() { + + System.out.println(" ".repeat(32) + "DIAMOND"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + + private void startGame() { + + int body = 0; + int column = 0; + int end = 0; + int fill = 0; + int increment = 2; + int numPerSide = 0; + int prefixIndex = 0; + int row = 0; + int start = 1; + int userNum = 0; + + String lineContent = ""; + + // Get user input + System.out.println("FOR A PRETTY DIAMOND PATTERN,"); + System.out.print("TYPE IN AN ODD NUMBER BETWEEN 5 AND 21? "); + userNum = scan.nextInt(); + System.out.println(""); + + // Calcuate number of diamonds to be drawn on each side of screen + numPerSide = (int) (LINE_WIDTH / userNum); + + end = userNum; + + // Begin loop through each row of diamonds + for (row = 1; row <= numPerSide; row++) { + + // Begin loop through top and bottom halves of each diamond + for (body = start; increment < 0 ? body >= end : body <= end; body += increment) { + + lineContent = ""; + + // Add whitespace + while (lineContent.length() < ((userNum - body) / 2)) { + lineContent += " "; + } + + // Begin loop through each column of diamonds + for (column = 1; column <= numPerSide; column++) { + + prefixIndex = 1; + + // Begin loop that fills each diamond with characters + for (fill = 1; fill <= body; fill++) { + + // Right side of diamond + if (prefixIndex > PREFIX.length()) { + + lineContent += SYMBOL; + + } + // Left side of diamond + else { + + lineContent += PREFIX.charAt(prefixIndex - 1); + prefixIndex++; + + } + + } // End loop that fills each diamond with characters + + // Column finished + if (column == numPerSide) { + + break; + + } + // Column not finishd + else { + + // Add whitespace + while (lineContent.length() < (userNum * column + (userNum - body) / 2)) { + lineContent += " "; + } + + } + + } // End loop through each column of diamonds + + System.out.println(lineContent); + + } // End loop through top and bottom half of each diamond + + if (start != 1) { + + start = 1; + end = userNum; + increment = 2; + + } + else { + + start = userNum - 2; + end = 1; + increment = -2; + row--; + + } + + } // End loop through each row of diamonds + + } // End of method startGame + + + public static void main(String[] args) { + + Diamond diamond = new Diamond(); + diamond.play(); + + } // End of method main + +} // End of class Diamond \ No newline at end of file From 6b3afaea526f01f37140afc24dc9f36f3f4b87d7 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sat, 20 Mar 2021 12:03:19 -0400 Subject: [PATCH 307/749] Add newline to end of Diamond.java. --- 32 Diamond/java/Diamond.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/32 Diamond/java/Diamond.java b/32 Diamond/java/Diamond.java index bbad33a7..da56efe4 100644 --- a/32 Diamond/java/Diamond.java +++ b/32 Diamond/java/Diamond.java @@ -160,4 +160,4 @@ public class Diamond { } // End of method main -} // End of class Diamond \ No newline at end of file +} // End of class Diamond From 50ac7e5c6ed16cb5743c5756400f127d39640106 Mon Sep 17 00:00:00 2001 From: Mark Yocom Date: Sat, 20 Mar 2021 12:06:29 -0700 Subject: [PATCH 308/749] Adding Perl version of aceyducey --- 01 Acey Ducey/perl/aceyducey.pl | 171 ++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 01 Acey Ducey/perl/aceyducey.pl diff --git a/01 Acey Ducey/perl/aceyducey.pl b/01 Acey Ducey/perl/aceyducey.pl new file mode 100644 index 00000000..b193219e --- /dev/null +++ b/01 Acey Ducey/perl/aceyducey.pl @@ -0,0 +1,171 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use List::Util qw(shuffle first); + +# Rather than put in a number of print (or say) statements here, we use a +# "here document". This is very useful for long strings of text. In this +# case, everything between the end of the "print" line and the line with +# "END_INSTRUCTIONS" on it will be printed verbatim. +print << 'END_INSTRUCTIONS'; + +Acey-Ducey +Adapted from Creative Computing, Morristown, New Jersey + + +Acey-Ducey is played as follows. The dealer (computer) deals two cards face up. +You have an option to bet or not bet, depending on whether or not you feel that +the next card drawn will have a value between the first two. Aces are low. + +Bets must be in whole-dollar amounts only. + +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 $keepPlaying = 1; + +GAME: +while ($keepPlaying) +{ + my $playerBalance = 100; # The player starts with $100 + + 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. + my @shuffledDeck = shuffle(@cards); + + # Then, by taking the two "top cards" off the deck, we're guaranteed + # 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 ]; + + print "I drew ", nameOfCard($firstCard), " and ", nameOfCard($secondCard), ".\n"; + + my $bet = getValidBet($playerBalance); + if ($bet == 0) + { + print "Chicken!\n\n"; + next HAND; + } + + if ($bet < 0) + { + last GAME; + } + + # Now we re-shuffle the whole deck again and choose a third card. + # (Note: This is how the odds get stacked in favor of the dealer since + # the third card can be exactly the same as the first or second.) + @shuffledDeck = shuffle(@cards); + my $thirdCard = $shuffledDeck[0]; + + print "I drew ", nameOfCard($thirdCard), "!\n"; + + if (($firstCard < $thirdCard) && ($thirdCard < $secondCard)) + { + print "You win!\n\n"; + $playerBalance += $bet; + } + else + { + print "You lose!\n\n"; + $playerBalance -= $bet; + } + + if ($playerBalance <= 0) + { + print "Sorry, buddy, you blew your wad!\n\n"; + last HAND; + } + } + + $keepPlaying = promptUserToKeepPlaying(); +} + +print "Thanks for playing!\n"; + +############### +sub getValidBet +{ + my $maxBet = shift; + + print "\nWhat's your bet? "; + + my $input = ; + 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... + ) + { + print "Sorry, numbers only!\n"; + $input = getValidBet($maxBet); + } + + 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); + } + + if ($input != int($input)) + { + print "Sorry, you must bet in whole dollars. No change!\n"; + $input = getValidBet($maxBet); + } + + 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 +{ + my $value = shift; + + # Note that the Joker isn't used in this game, but since arrays in Perl are + # 0-based, it's useful to have something there to represent the "0th" + # position. This way the rest of the elements match their expected values + # (e.g., element 1 is Ace, element 7 is 7, and element 12 is Queen). + + my @cardlist = qw(Joker Ace 2 3 4 5 6 7 8 9 10 Jack Queen King); + return $cardlist[$value]; +} + +sub promptUserToKeepPlaying +{ + print "Try again (Y/N)? "; + my $input = ; + chomp $input; + + my $keepGoing; + if (uc($input) eq 'Y') + { + $keepGoing = 1; + } + elsif (uc($input) eq 'N') + { + $keepGoing = 0; + } + else + { + $keepGoing = promptUserToKeepPlaying(); + } + + return $keepGoing; +} From e596c041c32166bdd35de67b38a3e0d7a9ff37f8 Mon Sep 17 00:00:00 2001 From: Mark Yocom Date: Sat, 20 Mar 2021 12:11:11 -0700 Subject: [PATCH 309/749] Removing unused first() from List::Util import --- 01 Acey Ducey/perl/aceyducey.pl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/01 Acey Ducey/perl/aceyducey.pl b/01 Acey Ducey/perl/aceyducey.pl index b193219e..e2de13df 100644 --- a/01 Acey Ducey/perl/aceyducey.pl +++ b/01 Acey Ducey/perl/aceyducey.pl @@ -3,7 +3,10 @@ use strict; use warnings; -use List::Util qw(shuffle first); +# The List::Util module is part of the core Perl distribution. Using this +# means we don't need to re-invent the wheel and create a way to shuffle +# a list. +use List::Util qw(shuffle); # Rather than put in a number of print (or say) statements here, we use a # "here document". This is very useful for long strings of text. In this @@ -25,7 +28,7 @@ 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: From 835ee3546481a21904fae9ecccbdcc7d448e1ed8 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 21 Mar 2021 12:39:19 +1100 Subject: [PATCH 310/749] Add Warp Engines --- 84 Super Star Trek/csharp/Game.cs | 27 ++-- 84 Super Star Trek/csharp/Input.cs | 15 ++- .../csharp/Objects/Enterprise.cs | 120 +++++++++++++++--- 84 Super Star Trek/csharp/Objects/Klingon.cs | 4 +- .../csharp/Resources/NowEntering.txt | 2 + .../csharp/Resources/PermissionDenied.txt | 5 + .../csharp/Resources/Strings.cs | 2 + .../Space/{Coordinate.cs => Coordinates.cs} | 2 +- 84 Super Star Trek/csharp/Space/Course.cs | 36 +++++- 84 Super Star Trek/csharp/Space/Galaxy.cs | 6 +- 84 Super Star Trek/csharp/Space/Quadrant.cs | 52 ++++++-- .../csharp/Space/QuadrantInfo.cs | 6 +- .../DirectionDistanceCalculator.cs | 3 +- .../StarbaseDataCalculator.cs | 2 +- .../TorpedoDataCalculator.cs | 2 +- .../csharp/Systems/PhaserControl.cs | 2 +- .../csharp/Systems/PhotonTubes.cs | 5 +- .../csharp/Systems/ShortRangeSensors.cs | 4 +- .../csharp/Systems/Subsystem.cs | 21 ++- .../csharp/Systems/WarpEngines.cs | 75 +++++++++++ 20 files changed, 330 insertions(+), 61 deletions(-) create mode 100644 84 Super Star Trek/csharp/Resources/NowEntering.txt create mode 100644 84 Super Star Trek/csharp/Resources/PermissionDenied.txt rename 84 Super Star Trek/csharp/Space/{Coordinate.cs => Coordinates.cs} (95%) create mode 100644 84 Super Star Trek/csharp/Systems/WarpEngines.cs diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index de3c2c4c..f2e1c819 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -12,6 +12,7 @@ namespace SuperStarTrek { private readonly Output _output; private readonly Input _input; + private readonly Random _random; private int _initialStardate; private int _finalStarDate; @@ -25,6 +26,7 @@ namespace SuperStarTrek { _output = new Output(); _input = new Input(_output); + _random = new Random(); } public float Stardate => _currentStardate; @@ -46,15 +48,19 @@ namespace SuperStarTrek { Initialise(); var gameOver = false; + var newQuadrantText = Strings.StartText; while (!gameOver) { + _enterprise.Quadrant.Display(Strings.NowEntering); + var command = _input.GetCommand(); var result = _enterprise.Execute(command); gameOver = result.IsGameOver || CheckIfStranded(); _currentStardate += result.TimeElapsed; + gameOver |= _currentStardate > _finalStarDate; } if (_galaxy.KlingonCount > 0) @@ -69,21 +75,20 @@ namespace SuperStarTrek private void Initialise() { - var random = new Random(); + _currentStardate = _initialStardate = _random.GetInt(20, 40) * 100; + _finalStarDate = _initialStardate + _random.GetInt(25, 35); - _currentStardate = _initialStardate = random.GetInt(20, 40) * 100; - _finalStarDate = _initialStardate + random.GetInt(25, 35); + _currentQuadrant = _random.GetCoordinate(); - _currentQuadrant = random.GetCoordinate(); - - _galaxy = new Galaxy(); + _galaxy = new Galaxy(_random); _initialKlingonCount = _galaxy.KlingonCount; - _enterprise = new Enterprise(3000, random.GetCoordinate(), _output, random); + _enterprise = new Enterprise(3000, _random.GetCoordinate(), _output, _random, _input); _enterprise + .Add(new WarpEngines(_enterprise, _output, _input)) .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) .Add(new LongRangeSensors(_galaxy, _output)) - .Add(new PhaserControl(_enterprise, _output, _input, random)) + .Add(new PhaserControl(_enterprise, _output, _input, _random)) .Add(new PhotonTubes(10, _enterprise, _output, _input)) .Add(new ShieldControl(_enterprise, _output, _input)) .Add(new DamageControl(_enterprise, _output)) @@ -109,10 +114,12 @@ namespace SuperStarTrek _input.WaitForAnyKeyButEnter("when ready to accept command"); - var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy, _input, _output); - _enterprise.Enter(quadrant, Strings.StartText); + _enterprise.StartIn(BuildCurrentQuadrant()); } + private Quadrant BuildCurrentQuadrant() => + new Quadrant(_galaxy[_currentQuadrant], _enterprise, _random, _galaxy, _input, _output); + public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye"); private bool CheckIfStranded() diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs index af17f3c4..3011738b 100644 --- a/84 Super Star Trek/csharp/Input.cs +++ b/84 Super Star Trek/csharp/Input.cs @@ -1,7 +1,7 @@ using System; using System.Linq; using SuperStarTrek.Commands; - +using SuperStarTrek.Space; using static System.StringComparison; namespace SuperStarTrek @@ -82,6 +82,19 @@ namespace SuperStarTrek } } + public bool TryGetCourse(string prompt, string officer, out Course course) + { + if (!TryGetNumber(prompt, 1, 9, out var direction)) + { + _output.WriteLine($"{officer} reports, 'Incorrect course data, sir!'"); + course = default; + return false; + } + + course = new Course(direction); + return true; + } + public bool GetYesNo(string prompt, YesNoMode mode) { _output.Prompt($"{prompt} (Y/N)"); diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index d87a3aec..004ce893 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -16,21 +16,25 @@ namespace SuperStarTrek.Objects private readonly List _systems; private readonly Dictionary _commandExecutors; private readonly Random _random; + private readonly Input _input; private Quadrant _quadrant; - public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random) + public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random, Input input) { - Sector = sector; + SectorCoordinates = sector; TotalEnergy = _maxEnergy = maxEnergy; _systems = new List(); _commandExecutors = new Dictionary(); _output = output; _random = random; + _input = input; } - public Coordinates Quadrant => _quadrant.Coordinates; - public Coordinates Sector { get; } + public Quadrant Quadrant => _quadrant; + public Coordinates QuadrantCoordinates => _quadrant.Coordinates; + public Coordinates SectorCoordinates { get; private set; } + public string Condition => GetCondition(); public LibraryComputer Computer => (LibraryComputer)_commandExecutors[Command.COM]; public ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE]; @@ -50,19 +54,10 @@ namespace SuperStarTrek.Objects return this; } - public void Enter(Quadrant quadrant, string entryTextFormat) + public void StartIn(Quadrant quadrant) { _quadrant = quadrant; - - _output.Write(entryTextFormat, quadrant); - - if (quadrant.HasKlingons) - { - _output.Write(Strings.CombatArea); - if (ShieldControl.ShieldEnergy <= 200) { _output.Write(Strings.LowShields); } - } - - Execute(Command.SRS); + quadrant.Display(Strings.StartText); } private string GetCondition() => @@ -121,7 +116,100 @@ namespace SuperStarTrek.Objects return; } - _systems[_random.Get1To8Inclusive() - 1].TakeDamage(hitShieldRatio + 0.5f * _random.GetFloat()); + var system = _systems[_random.Get1To8Inclusive() - 1]; + system.TakeDamage(hitShieldRatio + 0.5f * _random.GetFloat()); + _output.WriteLine($"Damage Control reports, '{system.Name} damaged by the hit.'"); } + + internal void RepairSystems(float repairWorkDone) + { + var repairedSystems = new List(); + + foreach (var system in _systems.Where(s => s.IsDamaged)) + { + if (system.Repair(repairWorkDone)) + { + repairedSystems.Add(system.Name); + } + } + + if (repairedSystems.Any()) + { + _output.WriteLine("Damage Control report:"); + foreach (var systemName in repairedSystems) + { + _output.WriteLine($" {systemName} repair completed."); + } + } + } + + internal void VaryConditionOfRandomSystem() + { + if (_random.GetFloat() > 0.2f) { return; } + + var system = _systems[_random.Get1To8Inclusive() - 1]; + _output.Write($"Damage Control report: {system.Name} "); + if (_random.GetFloat() >= 0.6) + { + system.Repair(_random.GetFloat() * 3 + 1); + _output.WriteLine("state of repair improved"); + } + else + { + system.TakeDamage(_random.GetFloat() * 5 + 1); + _output.WriteLine("damaged"); + } + } + + internal float Move(Course course, float warpFactor, int distance) + { + var (quadrant, sector) = MoveWithinQuadrant(course, distance) ?? MoveBeyondQuadrant(course, distance); + + if (quadrant != _quadrant.Coordinates) + { + _quadrant = new Quadrant(_quadrant.Galaxy[quadrant], this, _random, _quadrant.Galaxy, _input, _output); + } + SectorCoordinates = sector; + + return GetTimeElapsed(quadrant, warpFactor); + } + + private (Coordinates, Coordinates)? MoveWithinQuadrant(Course course, int distance) + { + var currentSector = SectorCoordinates; + foreach (var (sector, index) in course.GetSectorsFrom(SectorCoordinates).Select((s, i) => (s, i))) + { + if (distance == 0) { break; } + + if (_quadrant.HasObjectAt(sector)) + { + _output.WriteLine($"Warp engines shut down at sector {currentSector} dues to bad navigation"); + distance = 0; + break; + } + + currentSector = sector; + distance -= 1; + } + + return distance == 0 ? (_quadrant.Coordinates, currentSector) : null; + } + + private (Coordinates, Coordinates) MoveBeyondQuadrant(Course course, int distance) + { + var (complete, quadrant, sector) = course.GetDestination(QuadrantCoordinates, SectorCoordinates, distance); + + if (!complete) + { + _output.Write(Strings.PermissionDenied, sector, quadrant); + } + + return (quadrant, sector); + } + + private float GetTimeElapsed(Coordinates finalQuadrant, float warpFactor) => + finalQuadrant == _quadrant.Coordinates + ? Math.Min(1, (float)Math.Round(warpFactor, 1, MidpointRounding.ToZero)) + : 1; } } diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs index d16c6792..4e277b07 100644 --- a/84 Super Star Trek/csharp/Objects/Klingon.cs +++ b/84 Super Star Trek/csharp/Objects/Klingon.cs @@ -22,7 +22,7 @@ namespace SuperStarTrek.Objects public CommandResult FireOn(Enterprise enterprise) { var attackStrength = _random.GetFloat(); - var distanceToEnterprise = Sector.GetDistanceTo(enterprise.Sector); + var distanceToEnterprise = Sector.GetDistanceTo(enterprise.SectorCoordinates); var hitStrength = (int)(Energy * (2 + attackStrength) / distanceToEnterprise); Energy /= 3 + attackStrength; @@ -36,5 +36,7 @@ namespace SuperStarTrek.Objects Energy -= hitStrength; return true; } + + internal void MoveTo(Coordinates newSector) => Sector = newSector; } } diff --git a/84 Super Star Trek/csharp/Resources/NowEntering.txt b/84 Super Star Trek/csharp/Resources/NowEntering.txt new file mode 100644 index 00000000..915b526f --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/NowEntering.txt @@ -0,0 +1,2 @@ +Now entering {0} quadrant . . . + diff --git a/84 Super Star Trek/csharp/Resources/PermissionDenied.txt b/84 Super Star Trek/csharp/Resources/PermissionDenied.txt new file mode 100644 index 00000000..c24d9da7 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/PermissionDenied.txt @@ -0,0 +1,5 @@ +Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter + is hereby *Denied*. Shut down your engines.' +Chief Engineer Scott reports, 'Warp engines shut down + at sector {0} of quadrant {1}.' diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index 7b315545..ddb768ca 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -17,7 +17,9 @@ namespace SuperStarTrek.Resources public static string LowShields => GetResource(); public static string NoEnemyShips => GetResource(); public static string NoStarbase => GetResource(); + public static string NowEntering => GetResource(); public static string Orders => GetResource(); + public static string PermissionDenied => GetResource(); public static string Protected => GetResource(); public static string RegionNames => GetResource(); public static string RelievedOfCommand => GetResource(); diff --git a/84 Super Star Trek/csharp/Space/Coordinate.cs b/84 Super Star Trek/csharp/Space/Coordinates.cs similarity index 95% rename from 84 Super Star Trek/csharp/Space/Coordinate.cs rename to 84 Super Star Trek/csharp/Space/Coordinates.cs index 759ca45e..1619d387 100644 --- a/84 Super Star Trek/csharp/Space/Coordinate.cs +++ b/84 Super Star Trek/csharp/Space/Coordinates.cs @@ -52,7 +52,7 @@ namespace SuperStarTrek.Space coordinates = default; return false; - int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero); + static int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero); } internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) => diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs index 40bf4bb2..a46385c3 100644 --- a/84 Super Star Trek/csharp/Space/Course.cs +++ b/84 Super Star Trek/csharp/Space/Course.cs @@ -25,7 +25,7 @@ namespace SuperStarTrek.Space (0, 1) }; - public Course(float direction) + internal Course(float direction) { if (direction < 1 || direction > 9) { @@ -45,10 +45,10 @@ namespace SuperStarTrek.Space DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection; } - public float DeltaX { get; } - public float DeltaY { get; } + internal float DeltaX { get; } + internal float DeltaY { get; } - public IEnumerable GetSectorsFrom(Coordinates start) + internal IEnumerable GetSectorsFrom(Coordinates start) { (float x, float y) = start; @@ -65,5 +65,33 @@ namespace SuperStarTrek.Space yield return coordinates; } } + + internal (bool, Coordinates, Coordinates) GetDestination(Coordinates quadrant, Coordinates sector, int distance) + { + var (xComplete, quadrantX, sectorX) = GetNewCoordinate(quadrant.X, sector.X, DeltaX * distance); + var (yComplete, quadrantY, sectorY) = GetNewCoordinate(quadrant.Y, sector.Y, DeltaY * distance); + + return (xComplete && yComplete, new Coordinates(quadrantX, quadrantY), new Coordinates(sectorX, sectorY)); + } + + private (bool, int, int) GetNewCoordinate(int quadrant, int sector, float sectorsTravelled) + { + var galacticCoordinate = quadrant * 8 + sector + sectorsTravelled; + var newQuadrant = (int)(galacticCoordinate / 8); + var newSector = (int)(galacticCoordinate - newQuadrant * 8); + + if (newSector == -1) + { + newQuadrant -= 1; + newSector = 7; + } + + return newQuadrant switch + { + < 0 => (false, 0, 0), + > 7 => (false, 7, 7), + _ => (true, newQuadrant, newSector) + }; + } } } diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 38382754..63838567 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using SuperStarTrek.Objects; using SuperStarTrek.Resources; using static System.StringSplitOptions; @@ -12,6 +13,7 @@ namespace SuperStarTrek.Space private static readonly string[] _regionNames; private static readonly string[] _subRegionIdentifiers; private readonly QuadrantInfo[][] _quadrants; + private readonly Random _random; static Galaxy() { @@ -19,9 +21,9 @@ namespace SuperStarTrek.Space _subRegionIdentifiers = new[] { "I", "II", "III", "IV" }; } - public Galaxy() + public Galaxy(Random random) { - var random = new Random(); + _random = random; _quadrants = Enumerable .Range(0, 8) diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index 8d9d0556..50c577e2 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -13,7 +13,8 @@ namespace SuperStarTrek.Space private readonly Random _random; private readonly Dictionary _sectors; private readonly Enterprise _enterprise; - private readonly Galaxy _galaxy; + private readonly Output _output; + private bool _displayed = false; public Quadrant( QuadrantInfo info, @@ -25,9 +26,11 @@ namespace SuperStarTrek.Space { _info = info; _random = random; - _galaxy = galaxy; + _output = output; + Galaxy = galaxy; - _sectors = new() { [enterprise.Sector] = _enterprise = enterprise }; + info.MarkAsKnown(); + _sectors = new() { [enterprise.SectorCoordinates] = _enterprise = enterprise }; PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount); if (_info.HasStarbase) { @@ -41,10 +44,11 @@ namespace SuperStarTrek.Space public int KlingonCount => _info.KlingonCount; public bool HasStarbase => _info.HasStarbase; public Starbase Starbase { get; } + internal Galaxy Galaxy { get; } public bool EnterpriseIsNextToStarbase => _info.HasStarbase && - Math.Abs(_enterprise.Sector.X - Starbase.Sector.X) <= 1 && - Math.Abs(_enterprise.Sector.Y - Starbase.Sector.Y) <= 1; + Math.Abs(_enterprise.SectorCoordinates.X - Starbase.Sector.X) <= 1 && + Math.Abs(_enterprise.SectorCoordinates.Y - Starbase.Sector.Y) <= 1; internal IEnumerable Klingons => _sectors.Values.OfType(); @@ -65,6 +69,25 @@ namespace SuperStarTrek.Space } } + internal void Display(string textFormat) + { + if (_displayed) { return; } + + _output.Write(textFormat, this); + + if (_info.KlingonCount > 0) + { + _output.Write(Strings.CombatArea); + if (_enterprise.ShieldControl.ShieldEnergy <= 200) { _output.Write(Strings.LowShields); } + } + + _enterprise.Execute(Command.SRS); + + _displayed = true; + } + + internal bool HasObjectAt(Coordinates coordinates) => _sectors.ContainsKey(coordinates); + internal bool TorpedoCollisionAt(Coordinates coordinates, out string message, out bool gameOver) { gameOver = false; @@ -74,7 +97,7 @@ namespace SuperStarTrek.Space { case Klingon klingon: message = Remove(klingon); - gameOver = _galaxy.KlingonCount == 0; + gameOver = Galaxy.KlingonCount == 0; return true; case Star _: @@ -85,8 +108,8 @@ namespace SuperStarTrek.Space _sectors.Remove(coordinates); _info.RemoveStarbase(); message = "*** Starbase destroyed ***" + - (_galaxy.StarbaseCount > 0 ? Strings.CourtMartial : Strings.RelievedOfCommand); - gameOver = _galaxy.StarbaseCount == 0; + (Galaxy.StarbaseCount > 0 ? Strings.CourtMartial : Strings.RelievedOfCommand); + gameOver = Galaxy.StarbaseCount == 0; return true; default: @@ -101,6 +124,19 @@ namespace SuperStarTrek.Space return "*** Klingon destroyed ***"; } + internal CommandResult KlingonsMoveAndFire() + { + foreach (var klingon in Klingons.ToList()) + { + var newSector = GetRandomEmptySector(); + _sectors.Remove(klingon.Sector); + _sectors[newSector] = klingon; + klingon.MoveTo(newSector); + } + + return KlingonsFireOnEnterprise(); + } + internal CommandResult KlingonsFireOnEnterprise() { if (EnterpriseIsNextToStarbase && Klingons.Any()) diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs index 8b4357db..70447250 100644 --- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs +++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs @@ -41,11 +41,7 @@ namespace SuperStarTrek.Space internal void AddStarbase() => HasStarbase = true; - internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy, Input input, Output output) - { - _isKnown = true; - return new(this, enterprise, random, galaxy, input, output); - } + internal void MarkAsKnown() => _isKnown = true; internal string Scan() { diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs index c8b195f4..ff6239ed 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs @@ -21,7 +21,8 @@ namespace SuperStarTrek.Systems.ComputerFunctions internal override void Execute(Quadrant quadrant) { Output.WriteLine("Direction/distance calculator:") - .WriteLine($"You are at quadrant {_enterprise.Quadrant} sector {_enterprise.Sector}") + .Write($"You are at quadrant {_enterprise.QuadrantCoordinates}") + .WriteLine($" sector {_enterprise.SectorCoordinates}") .WriteLine("Please enter"); WriteDirectionAndDistance( diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs index b81a353d..0d2c5b50 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs @@ -24,7 +24,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions Output.WriteLine("From Enterprise to Starbase:"); - WriteDirectionAndDistance(_enterprise.Sector, quadrant.Starbase.Sector); + WriteDirectionAndDistance(_enterprise.SectorCoordinates, quadrant.Starbase.Sector); } } } \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs index 6afa7b8c..09c71859 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs @@ -26,7 +26,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions foreach (var klingon in quadrant.Klingons) { - WriteDirectionAndDistance(_enterprise.Sector, klingon.Sector); + WriteDirectionAndDistance(_enterprise.SectorCoordinates, klingon.Sector); } } } diff --git a/84 Super Star Trek/csharp/Systems/PhaserControl.cs b/84 Super Star Trek/csharp/Systems/PhaserControl.cs index 48da4ace..5aa7cf8b 100644 --- a/84 Super Star Trek/csharp/Systems/PhaserControl.cs +++ b/84 Super Star Trek/csharp/Systems/PhaserControl.cs @@ -75,7 +75,7 @@ namespace SuperStarTrek.Systems private void ResolveHitOn(Klingon klingon, float perEnemyStrength, Quadrant quadrant) { - var distance = _enterprise.Sector.GetDistanceTo(klingon.Sector); + var distance = _enterprise.SectorCoordinates.GetDistanceTo(klingon.Sector); var hitStrength = (int)(perEnemyStrength / distance * (2 + _random.GetFloat())); if (klingon.TakeHit(hitStrength)) diff --git a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs index 034199c9..024cf7ea 100644 --- a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs +++ b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs @@ -34,15 +34,14 @@ namespace SuperStarTrek.Systems protected override CommandResult ExecuteCommandCore(Quadrant quadrant) { - if (!_input.TryGetNumber("Photon torpedo course", 1, 9, out var direction)) + if (!_input.TryGetCourse("Photon torpedo course", "Ensign Chekov", out var course)) { - _output.WriteLine("Ensign Chekov reports, 'Incorrect course data, sir!'"); return CommandResult.Ok; } var isHit = false; _output.WriteLine("Torpedo track:"); - foreach (var sector in new Course(direction).GetSectorsFrom(_enterprise.Sector)) + foreach (var sector in course.GetSectorsFrom(_enterprise.SectorCoordinates)) { _output.WriteLine($" {sector}"); diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs index e01c829e..e25cf966 100644 --- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs +++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs @@ -51,8 +51,8 @@ namespace SuperStarTrek.Systems { yield return $"Stardate {_game.Stardate}"; yield return $"Condition {_enterprise.Condition}"; - yield return $"Quadrant {_enterprise.Quadrant}"; - yield return $"Sector {_enterprise.Sector}"; + yield return $"Quadrant {_enterprise.QuadrantCoordinates}"; + yield return $"Sector {_enterprise.SectorCoordinates}"; yield return $"Photon torpedoes {_enterprise.TorpedoCount}"; yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}"; yield return $"Shields {(int)_enterprise.ShieldControl.ShieldEnergy}"; diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs index ab7bef4c..9e5f3570 100644 --- a/84 Super Star Trek/csharp/Systems/Subsystem.cs +++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs @@ -41,13 +41,26 @@ namespace SuperStarTrek.Systems public virtual void Repair() { - if (IsDamaged) { Condition = 0; } + if (IsDamaged) + { + Condition = 0; + } } - internal void TakeDamage(float damage) + public virtual bool Repair(float repairWorkDone) { - Condition -= damage; - _output.WriteLine($"Damage Control reports, '{Name} damaged by the hit.'"); + if (IsDamaged) + { + Condition += repairWorkDone; + if (Condition > -0.1f && Condition < 0) + { + Condition = -0.1f; + } + } + + return !IsDamaged; } + + internal void TakeDamage(float damage) => Condition -= damage; } } diff --git a/84 Super Star Trek/csharp/Systems/WarpEngines.cs b/84 Super Star Trek/csharp/Systems/WarpEngines.cs new file mode 100644 index 00000000..8e24b750 --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/WarpEngines.cs @@ -0,0 +1,75 @@ +using System; +using SuperStarTrek.Commands; +using SuperStarTrek.Objects; +using SuperStarTrek.Space; + +namespace SuperStarTrek.Systems +{ + internal class WarpEngines : Subsystem + { + private readonly Enterprise _enterprise; + private readonly Output _output; + private readonly Input _input; + + public WarpEngines(Enterprise enterprise, Output output, Input input) + : base("Warp Engines", Command.NAV, output) + { + _enterprise = enterprise; + _output = output; + _input = input; + } + + protected override CommandResult ExecuteCommandCore(Quadrant quadrant) + { + if (_input.TryGetCourse("Course", " Lt. Sulu", out var course) && + TryGetWarpFactor(out var warpFactor) && + TryGetDistanceToMove(warpFactor, out var distanceToMove)) + { + var result = quadrant.KlingonsMoveAndFire(); + if (result.IsGameOver) { return result; } + + _enterprise.RepairSystems(warpFactor); + _enterprise.VaryConditionOfRandomSystem(); + var timeElapsed = _enterprise.Move(course, warpFactor, distanceToMove); + + return CommandResult.Elapsed(timeElapsed); + } + + return CommandResult.Ok; + } + + private bool TryGetWarpFactor(out float warpFactor) + { + var maximumWarp = IsDamaged ? 0.2f : 8; + if (_input.TryGetNumber("Warp Factor", 0, maximumWarp, out warpFactor)) + { + return warpFactor > 0; + } + + _output.WriteLine( + IsDamaged && warpFactor > maximumWarp + ? "Warp engines are damaged. Maximum speed = warp 0.2" + : $" Chief Engineer Scott reports, 'The engines won't take warp {warpFactor} !'"); + + return false; + } + + private bool TryGetDistanceToMove(float warpFactor, out int distanceToTravel) + { + distanceToTravel = (int)Math.Round(warpFactor * 8, MidpointRounding.AwayFromZero); + if (distanceToTravel <= _enterprise.Energy) { return true; } + + _output.WriteLine("Engineering reports, 'Insufficient energy available") + .WriteLine($" for maneuvering at warp {warpFactor} !'"); + + if (distanceToTravel <= _enterprise.TotalEnergy && !_enterprise.ShieldControl.IsDamaged) + { + _output.Write($"Deflector control room acknowledges {_enterprise.ShieldControl.ShieldEnergy} ") + .WriteLine("units of energy") + .WriteLine(" presently deployed to shields."); + } + + return false; + } + } +} From 3777f835c145c135eba607b665ee6487300880e6 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 21 Mar 2021 12:46:32 +1100 Subject: [PATCH 311/749] Fix phaser energy use --- 84 Super Star Trek/csharp/Objects/Enterprise.cs | 5 +++++ 84 Super Star Trek/csharp/Systems/PhaserControl.cs | 2 ++ 2 files changed, 7 insertions(+) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index 004ce893..bb177369 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -87,6 +87,11 @@ namespace SuperStarTrek.Objects public override string ToString() => "<*>"; + internal void UseEnergy(float amountUsed) + { + TotalEnergy -= amountUsed; + } + internal CommandResult TakeHit(Coordinates sector, int hitStrength) { _output.WriteLine($"{hitStrength} unit hit on Enterprise from sector {sector}"); diff --git a/84 Super Star Trek/csharp/Systems/PhaserControl.cs b/84 Super Star Trek/csharp/Systems/PhaserControl.cs index 5aa7cf8b..18566294 100644 --- a/84 Super Star Trek/csharp/Systems/PhaserControl.cs +++ b/84 Super Star Trek/csharp/Systems/PhaserControl.cs @@ -42,6 +42,8 @@ namespace SuperStarTrek.Systems var phaserStrength = GetPhaserStrength(); if (phaserStrength < 0) { return CommandResult.Ok; } + _enterprise.UseEnergy(phaserStrength); + var perEnemyStrength = GetPerTargetPhaserStrength(phaserStrength, quadrant.KlingonCount); foreach (var klingon in quadrant.Klingons.ToList()) From 95ec6a2c024200453776594a4d9d68d8d830c0af Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 21 Mar 2021 12:54:14 +1100 Subject: [PATCH 312/749] Fix movement within quadrant --- 84 Super Star Trek/csharp/Objects/Enterprise.cs | 1 + 84 Super Star Trek/csharp/Space/Quadrant.cs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index bb177369..feb51646 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -174,6 +174,7 @@ namespace SuperStarTrek.Objects { _quadrant = new Quadrant(_quadrant.Galaxy[quadrant], this, _random, _quadrant.Galaxy, _input, _output); } + _quadrant.SetEnterpriseSector(sector); SectorCoordinates = sector; return GetTimeElapsed(quadrant, warpFactor); diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index 50c577e2..b333cb7e 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -176,5 +176,11 @@ namespace SuperStarTrek.Space .Select(y => new Coordinates(x, y)) .Select(c => _sectors.GetValueOrDefault(c)) .Select(o => o?.ToString() ?? " ")); + + internal void SetEnterpriseSector(Coordinates sector) + { + _sectors.Remove(_enterprise.SectorCoordinates); + _sectors[sector] = _enterprise; + } } } From 5e6aae3c195b2dade1f59936bc58595eea9e05ab Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 21 Mar 2021 13:00:54 +1100 Subject: [PATCH 313/749] Fix torpedo count --- 84 Super Star Trek/csharp/Objects/Enterprise.cs | 2 +- 84 Super Star Trek/csharp/Systems/PhotonTubes.cs | 2 ++ 84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index feb51646..1608b94b 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -42,7 +42,7 @@ namespace SuperStarTrek.Objects public float TotalEnergy { get; private set; } public int DamagedSystemCount => _systems.Count(s => s.IsDamaged); public IEnumerable Systems => _systems; - public int TorpedoCount { get; } + public PhotonTubes PhotonTubes => (PhotonTubes)_commandExecutors[Command.TOR]; public bool IsDocked => _quadrant.EnterpriseIsNextToStarbase; public bool IsStranded => TotalEnergy < 10 || Energy < 10 && ShieldControl.IsDamaged; diff --git a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs index 024cf7ea..656c65be 100644 --- a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs +++ b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs @@ -39,6 +39,8 @@ namespace SuperStarTrek.Systems return CommandResult.Ok; } + TorpedoCount -= 1; + var isHit = false; _output.WriteLine("Torpedo track:"); foreach (var sector in course.GetSectorsFrom(_enterprise.SectorCoordinates)) diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs index e25cf966..ad3929d1 100644 --- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs +++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs @@ -53,7 +53,7 @@ namespace SuperStarTrek.Systems yield return $"Condition {_enterprise.Condition}"; yield return $"Quadrant {_enterprise.QuadrantCoordinates}"; yield return $"Sector {_enterprise.SectorCoordinates}"; - yield return $"Photon torpedoes {_enterprise.TorpedoCount}"; + yield return $"Photon torpedoes {_enterprise.PhotonTubes.TorpedoCount}"; yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}"; yield return $"Shields {(int)_enterprise.ShieldControl.ShieldEnergy}"; yield return $"Klingons remaining {_galaxy.KlingonCount}"; From e3f53762481ce3720ceb92d75c35ac73ef8c8b4c Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 21 Mar 2021 13:12:44 +1100 Subject: [PATCH 314/749] Refuel Enterprise at starbase --- 84 Super Star Trek/csharp/Objects/Enterprise.cs | 2 ++ 84 Super Star Trek/csharp/Systems/PhotonTubes.cs | 2 ++ 84 Super Star Trek/csharp/Systems/ShieldControl.cs | 2 ++ 84 Super Star Trek/csharp/Systems/WarpEngines.cs | 7 +++++++ 4 files changed, 13 insertions(+) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index 1608b94b..e48c5f76 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -75,6 +75,8 @@ namespace SuperStarTrek.Objects return _commandExecutors[command].ExecuteCommand(_quadrant); } + public void Refuel() => TotalEnergy = _maxEnergy; + internal bool Recognises(string command) { throw new NotImplementedException(); diff --git a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs index 656c65be..a807d16c 100644 --- a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs +++ b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs @@ -60,5 +60,7 @@ namespace SuperStarTrek.Systems return quadrant.KlingonsFireOnEnterprise(); } + + internal void ReplenishTorpedoes() => TorpedoCount = _tubeCount; } } diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs index 6ceefcf4..5af343f1 100644 --- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs +++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs @@ -51,5 +51,7 @@ namespace SuperStarTrek.Systems } internal void AbsorbHit(int hitStrength) => ShieldEnergy -= hitStrength; + + internal void DropShields() => ShieldEnergy = 0; } } diff --git a/84 Super Star Trek/csharp/Systems/WarpEngines.cs b/84 Super Star Trek/csharp/Systems/WarpEngines.cs index 8e24b750..0dcf396c 100644 --- a/84 Super Star Trek/csharp/Systems/WarpEngines.cs +++ b/84 Super Star Trek/csharp/Systems/WarpEngines.cs @@ -32,6 +32,13 @@ namespace SuperStarTrek.Systems _enterprise.VaryConditionOfRandomSystem(); var timeElapsed = _enterprise.Move(course, warpFactor, distanceToMove); + if (_enterprise.IsDocked) + { + _enterprise.ShieldControl.DropShields(); + _enterprise.Refuel(); + _enterprise.PhotonTubes.ReplenishTorpedoes(); + } + return CommandResult.Elapsed(timeElapsed); } From 5418068462e91092ac60a0a58c0bdf522da001be Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 21 Mar 2021 13:55:55 +1100 Subject: [PATCH 315/749] Fix energy usage by warp engines. --- 84 Super Star Trek/csharp/Objects/Enterprise.cs | 7 +++++++ 84 Super Star Trek/csharp/Systems/ShieldControl.cs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index e48c5f76..4adf81df 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -179,6 +179,13 @@ namespace SuperStarTrek.Objects _quadrant.SetEnterpriseSector(sector); SectorCoordinates = sector; + TotalEnergy -= distance + 10; + if (Energy < 0) + { + _output.WriteLine("Shield Control supplies energy to complete the maneuver."); + ShieldControl.ShieldEnergy = Math.Max(0, TotalEnergy); + } + return GetTimeElapsed(quadrant, warpFactor); } diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs index 5af343f1..a7518359 100644 --- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs +++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs @@ -18,7 +18,7 @@ namespace SuperStarTrek.Systems _input = input; } - public float ShieldEnergy { get; private set; } + public float ShieldEnergy { get; set; } protected override bool CanExecuteCommand() => IsOperational("{name} inoperable"); From 6d7634fa1aa058107e0f75fdc8c55cca1a38aab3 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sun, 21 Mar 2021 11:38:43 -0400 Subject: [PATCH 316/749] Ported 3-D Plot to Java. --- 87 3-D Plot/java/Plot3D.java | 97 ++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 87 3-D Plot/java/Plot3D.java diff --git a/87 3-D Plot/java/Plot3D.java b/87 3-D Plot/java/Plot3D.java new file mode 100644 index 00000000..77ffbb8d --- /dev/null +++ b/87 3-D Plot/java/Plot3D.java @@ -0,0 +1,97 @@ +import java.lang.Math; + +/** + * Game of 3-D Plot + *

+ * Based on the BASIC game of 3-D Plot here + * https://github.com/coding-horror/basic-computer-games/blob/main/87%203-D%20Plot/3dplot.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +// Java class names cannot begin with a letter, so class name 3dplot cannot be used +public class Plot3D { + + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + + private void showIntro() { + + System.out.println(" ".repeat(31) + "3D PLOT"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n\n"); + + } // End of method showIntro + + + private void startGame() { + + float row = 0; + int column = 0; + int limit = 0; + int plotVal = 0; + int root = 0; + + String lineContent = ""; + + // Begin loop through all rows + for (row = -30; row <= 30; row += 1.5) { + + limit = 0; + + root = 5 * (int) Math.floor((Math.sqrt(900 - row * row) / 5)); + + // Begin loop through all columns + for (column = root; column >= -root; column += -5) { + + plotVal = 25 + (int) Math.floor(func(Math.sqrt(row * row + column * column)) - 0.7 * column); + + if (plotVal > limit) { + + limit = plotVal; + + // Add whitespace + while (lineContent.length() < (plotVal-1)) { + lineContent += " "; + } + + lineContent += "*"; + + } + + } // End loop through all columns + + System.out.println(lineContent); + + lineContent = ""; + + } // End loop through all rows + + } // End of method startGame + + + // Function to be plotted + public double func(double inputVal) { + + return (30 * Math.exp(-inputVal * inputVal / 100)); + + } + + + public static void main(String[] args) { + + Plot3D plot = new Plot3D(); + plot.play(); + + } // End of method main + +} // End of class Plot3D \ No newline at end of file From 5b0f5f67a718746894b1f36162fb60470325853c Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sun, 21 Mar 2021 11:40:29 -0400 Subject: [PATCH 317/749] Add newline to end of Plot3D.java. --- 87 3-D Plot/java/Plot3D.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/87 3-D Plot/java/Plot3D.java b/87 3-D Plot/java/Plot3D.java index 77ffbb8d..a12848d8 100644 --- a/87 3-D Plot/java/Plot3D.java +++ b/87 3-D Plot/java/Plot3D.java @@ -94,4 +94,4 @@ public class Plot3D { } // End of method main -} // End of class Plot3D \ No newline at end of file +} // End of class Plot3D From 2bb6bff9b87e2f1549a83879feaefc3fbbe6da93 Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Mon, 22 Mar 2021 11:59:50 +0000 Subject: [PATCH 318/749] Added initial files Added new Visual Studio solution. --- 94 War/csharp/War/War.sln | 25 +++++++++++++++++++++++++ 94 War/csharp/War/War/Program.cs | 12 ++++++++++++ 94 War/csharp/War/War/War.csproj | 8 ++++++++ 3 files changed, 45 insertions(+) create mode 100644 94 War/csharp/War/War.sln create mode 100644 94 War/csharp/War/War/Program.cs create mode 100644 94 War/csharp/War/War/War.csproj diff --git a/94 War/csharp/War/War.sln b/94 War/csharp/War/War.sln new file mode 100644 index 00000000..8f9560d8 --- /dev/null +++ b/94 War/csharp/War/War.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "War", "War\War.csproj", "{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3FA273C6-089E-4F3D-8DC0-F9143D1CDF3A} + EndGlobalSection +EndGlobal diff --git a/94 War/csharp/War/War/Program.cs b/94 War/csharp/War/War/Program.cs new file mode 100644 index 00000000..cf4b0edf --- /dev/null +++ b/94 War/csharp/War/War/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace War +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/94 War/csharp/War/War/War.csproj b/94 War/csharp/War/War/War.csproj new file mode 100644 index 00000000..c73e0d16 --- /dev/null +++ b/94 War/csharp/War/War/War.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + From 455755b6a433447cb3f74ec043908d981791c24a Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Mon, 22 Mar 2021 12:00:26 +0000 Subject: [PATCH 319/749] Added Cards and Deck classes --- 94 War/csharp/War/War/Cards.cs | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 94 War/csharp/War/War/Cards.cs diff --git a/94 War/csharp/War/War/Cards.cs b/94 War/csharp/War/War/Cards.cs new file mode 100644 index 00000000..ad84735a --- /dev/null +++ b/94 War/csharp/War/War/Cards.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace War +{ + public enum Suit + { + none = 0, + clubs, + diamonds, + hearts, + spades + } + + public enum Rank + { + none = 0, + // Skip 1 because ace is high. + two = 2, + three, + four, + five, + six, + seven, + eight, + nine, + ten, + jack, + queen, + king, + ace + } + + // TODO Testing + + class Card + { + // TODO Turn into properties, maybe?? + private Suit suit; + private Rank rank; + + public Card(Suit suit, Rank rank) // immutable + { + this.suit = suit; + this.rank = rank; + } + + // would normally consider suit and rank but in this case we only want to compare rank. + public static bool operator ==(Card lhs, Card rhs) + { + return lhs.rank == rhs.rank; + } + + public static bool operator !=(Card lhs, Card rhs) + { + return !(lhs == rhs); + } + + public static bool operator <(Card lhs, Card rhs) + { + return lhs.rank < rhs.rank; + } + public static bool operator >(Card lhs, Card rhs) + { + return rhs < lhs; + } + public static bool operator <=(Card lhs, Card rhs) + { + return !(lhs > rhs); + } + public static bool operator >=(Card lhs, Card rhs) + { + return !(lhs < rhs); + } + + public override string ToString() + { + // TODO No need to create the dictionaries each time this is called. + // Also make it static. + // Is there a C# equivalent of an initializer list? + var suitNames = new Dictionary(); + + suitNames[Suit.none] = "N"; + suitNames[Suit.clubs] = "C"; + suitNames[Suit.diamonds] = "D"; + suitNames[Suit.hearts] = "H"; + suitNames[Suit.spades] = "S"; + + var rankNames = new Dictionary(); + rankNames[Rank.none] = "0"; + rankNames[Rank.two] = "2"; + rankNames[Rank.three] = "3"; + rankNames[Rank.four] = "4"; + rankNames[Rank.five] = "5"; + rankNames[Rank.six] = "6"; + rankNames[Rank.seven] = "7"; + rankNames[Rank.eight] = "8"; + rankNames[Rank.nine] = "9"; + rankNames[Rank.ten] = "10"; + rankNames[Rank.jack] = "J"; + rankNames[Rank.queen] = "Q"; + rankNames[Rank.king] = "K"; + rankNames[Rank.ace] = "A"; + + return $"{suitNames[suit]}-{rankNames[rank]}"; // string interpolation + } + } + + class Deck + { + } +} From ed0663ccbec536fc373f4606d6195bf707bc6cd4 Mon Sep 17 00:00:00 2001 From: Ignacio Manzano Date: Mon, 22 Mar 2021 09:12:26 -0300 Subject: [PATCH 320/749] Boxing 15 - ported to java --- 15 Boxing/java/Basic.java | 45 +++++++ 15 Boxing/java/Boxing.java | 227 ++++++++++++++++++++++++++++++++ 15 Boxing/java/BoxingGame.java | 6 + 15 Boxing/java/GameSession.java | 67 ++++++++++ 15 Boxing/java/Player.java | 42 ++++++ 15 Boxing/java/Punch.java | 27 ++++ 66 Number/java/main.class | 69 ++++++++++ 7 files changed, 483 insertions(+) create mode 100644 15 Boxing/java/Basic.java create mode 100644 15 Boxing/java/Boxing.java create mode 100644 15 Boxing/java/BoxingGame.java create mode 100644 15 Boxing/java/GameSession.java create mode 100644 15 Boxing/java/Player.java create mode 100644 15 Boxing/java/Punch.java create mode 100644 66 Number/java/main.class diff --git a/15 Boxing/java/Basic.java b/15 Boxing/java/Basic.java new file mode 100644 index 00000000..3822e3f3 --- /dev/null +++ b/15 Boxing/java/Basic.java @@ -0,0 +1,45 @@ +import java.util.Scanner; + +/** + * It provide some kind of BASIC language behaviour simulations. + */ +final class Basic { + + public static int randomOf(int base) { + return (int)Math.round(Math.floor(base* Math.random() + 1)); + } + + /** + * The Console "simulate" the message error when input does not match with the expected type. + * Specifically for this game if you enter an String when and int was expected. + */ + public static class Console { + private final Scanner input = new Scanner(System.in); + + public String readLine() { + return input.nextLine(); + } + + public int readInt() { + int ret = -1; + boolean failedInput = true; + do { + boolean b = input.hasNextInt(); + if (b) { + ret = input.nextInt(); + failedInput = false; + } else { + input.next(); // discard read + System.out.print("!NUMBER EXPECTED - RETRY INPUT LINE\n? "); + } + + } while (failedInput); + + return ret; + } + + public void print(String message, Object... args) { + System.out.printf(message, args); + } + } +} \ No newline at end of file diff --git a/15 Boxing/java/Boxing.java b/15 Boxing/java/Boxing.java new file mode 100644 index 00000000..64b20155 --- /dev/null +++ b/15 Boxing/java/Boxing.java @@ -0,0 +1,227 @@ +/** + * Boxing + * + *

+ * Based on the Basic game of BatNum here + * https://github.com/coding-horror/basic-computer-games/tree/main/15%20Boxing + *

+ */ +public class Boxing { + + private static final Basic.Console console = new Basic.Console(); + + private GameSession session; + + public void play() { + showIntro(); + + loadPlayers(); + + console.print("%s'S ADVANTAGE IS %d AND VULNERABILITY IS SECRET.\n", session.getOpponent().getName(), session.getOpponent().getBestPunch().getCode()); + + + for (int roundNro = 1; roundNro <= 3; roundNro++) { + if (session.isOver()) + break; + + session.resetPoints(); + console.print("\nROUND %d BEGINS...%n", roundNro); + + for (int majorPunches = 1; majorPunches <= 7; majorPunches++) { + long i = Basic.randomOf(10); + + if (i > 5) { + boolean stopPunches = opponentPunch(); + if (stopPunches ) break; + } else { + playerPunch(); + } + } + showRoundWinner(roundNro); + } + showWinner(); + } + + private boolean opponentPunch() { + final Punch punch = Punch.random(); + + if (punch == session.getOpponent().getBestPunch()) session.addOpponentPoints(2); + + if (punch == Punch.FULL_SWING) { + console.print("%s TAKES A FULL SWING AND", session.getOpponent().getName()); + long r6 = Basic.randomOf(60); + + if (session.getPlayer().hitVulnerability(Punch.FULL_SWING) || r6 < 30) { + console.print(" POW!!!!! HE HITS HIM RIGHT IN THE FACE!\n"); + if (session.getPoints(session.getOpponent()) > 35) { + + session.setKnocked(); + return true; + } + session.addOpponentPoints(15); + } else { + console.print(" IT'S BLOCKED!\n"); + } + } + + if (punch == Punch.HOOK || punch == Punch.UPPERCUT) { + if (punch == Punch.HOOK) { + console.print("%s GETS %s IN THE JAW (OUCH!)\n", session.getOpponent().getName(), session.getPlayer().getName()); + + session.addOpponentPoints(7); + console.print("....AND AGAIN!\n"); + + session.addOpponentPoints(5); + if (session.getPoints(session.getOpponent()) > 35) { + session.setKnocked(); + return true; + } + console.print("\n"); + + } + console.print("%s IS ATTACKED BY AN UPPERCUT (OH,OH)...\n", session.getPlayer().getName()); + long q4 = Basic.randomOf(200); + if (session.getPlayer().hitVulnerability(Punch.UPPERCUT) || q4 <= 75) { + console.print("AND %s CONNECTS...\n", session.getOpponent().getName()); + + session.addOpponentPoints(8); + } else { + console.print(" BLOCKS AND HITS %s WITH A HOOK.\n", session.getOpponent().getName()); + + session.addPlayerPoints(5); + } + } + else { + console.print("%s JABS AND ", session.getOpponent().getName()); + long z4 = Basic.randomOf(7); + if (session.getPlayer().hitVulnerability(Punch.JAB)) + + session.addOpponentPoints(5); + else if (z4 > 4) { + console.print(" BLOOD SPILLS !!!\n"); + + session.addOpponentPoints(5); + } else { + console.print("IT'S BLOCKED!\n"); + } + } + return true; + } + + private void playerPunch() { + console.print("%s'S PUNCH? ", session.getPlayer().getName()); + final Punch punch = Punch.fromCode(console.readInt()); + + if (punch == session.getPlayer().getBestPunch()) session.addPlayerPoints(2); + + switch (punch) { + case FULL_SWING -> { + console.print("%s SWINGS AND ", session.getPlayer().getName()); + if (session.getOpponent().getBestPunch() == Punch.JAB) { + console.print("HE CONNECTS!\n"); + if (session.getPoints(session.getPlayer()) <= 35) session.addPlayerPoints(15); + } else { + long x3 = Basic.randomOf(30); + if (x3 < 10) { + console.print("HE CONNECTS!\n"); + if (session.getPoints(session.getPlayer()) <= 35) session.addPlayerPoints(15); + } else { + console.print("HE MISSES \n"); + if (session.getPoints(session.getPlayer()) != 1) console.print("\n\n"); + } + } + } + case HOOK -> { + console.print("\n%s GIVES THE HOOK... ", session.getPlayer().getName()); + long h1 = Basic.randomOf(2); + if (session.getOpponent().getBestPunch() == Punch.HOOK) { + + session.addPlayerPoints(7); + } else if (h1 == 1) { + console.print("BUT IT'S BLOCKED!!!!!!!!!!!!!\n"); + } else { + console.print("CONNECTS...\n"); + + session.addPlayerPoints(7); + } + } + case UPPERCUT -> { + console.print("\n%s TRIES AN UPPERCUT ", session.getPlayer().getName()); + long d5 = Basic.randomOf(100); + if (session.getOpponent().getBestPunch() == Punch.UPPERCUT || d5 < 51) { + console.print("AND HE CONNECTS!\n"); + + session.addPlayerPoints(4); + } else { + console.print("AND IT'S BLOCKED (LUCKY BLOCK!)\n"); + } + } + default -> { + console.print("%s JABS AT %s'S HEAD \n", session.getPlayer().getName(), session.getOpponent().getName()); + if (session.getOpponent().getBestPunch() == Punch.JAB) { + + session.addPlayerPoints(3); + } else { + long c = Basic.randomOf(8); + if (c < 4) { + console.print("IT'S BLOCKED.\n"); + } else { + + session.addPlayerPoints(3); + } + } + } + } + } + + private void showRoundWinner(int roundNro) { + if (session.isRoundWinner(session.getPlayer())) { + console.print("\n %s WINS ROUND %d\n", session.getPlayer().getName(), roundNro); + session.addRoundWind(session.getPlayer()); + } else { + console.print("\n %s WINS ROUND %d\n", session.getOpponent().getName(), roundNro); + session.addRoundWind(session.getOpponent()); + } + } + + private void showWinner() { + if (session.isGameWinner(session.getOpponent())) { + console.print("%s WINS (NICE GOING, " + session.getOpponent().getName() + ").", session.getOpponent().getName()); + } else if (session.isGameWinner(session.getPlayer())) { + console.print("%s AMAZINGLY WINS!!", session.getPlayer().getName()); + } else if (session.isPlayerKnocked()) { + console.print("%s IS KNOCKED COLD AND %s IS THE WINNER AND CHAMP!", session.getPlayer().getName(), session.getOpponent().getName()); + } else { + console.print("%s IS KNOCKED COLD AND %s IS THE WINNER AND CHAMP!", session.getOpponent().getName(), session.getPlayer().getName()); + } + + console.print("\n\nAND NOW GOODBYE FROM THE OLYMPIC ARENA.\n"); + } + + private void loadPlayers() { + console.print("WHAT IS YOUR OPPONENT'S NAME? "); + final String opponentName = console.readLine(); + + console.print("INPUT YOUR MAN'S NAME? "); + final String playerName = console.readLine(); + + console.print("DIFFERENT PUNCHES ARE: (1) FULL SWING; (2) HOOK; (3) UPPERCUT; (4) JAB.\n"); + console.print("WHAT IS YOUR MANS BEST? "); + + final int b = console.readInt(); + + console.print("WHAT IS HIS VULNERABILITY? "); + final int d = console.readInt(); + + final Player player = new Player(playerName, Punch.fromCode(b), Punch.fromCode(d)); + final Player opponent = new Player(opponentName); + + session = new GameSession(player, opponent); + } + + private void showIntro () { + console.print(" BOXING\n"); + console.print(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n"); + console.print("BOXING OLYMPIC STYLE (3 ROUNDS -- 2 OUT OF 3 WINS)\n\n"); + } +} \ No newline at end of file diff --git a/15 Boxing/java/BoxingGame.java b/15 Boxing/java/BoxingGame.java new file mode 100644 index 00000000..5e5f897b --- /dev/null +++ b/15 Boxing/java/BoxingGame.java @@ -0,0 +1,6 @@ +public class BoxingGame { + + public static void main(String[] args) { + new Boxing().play(); + } +} diff --git a/15 Boxing/java/GameSession.java b/15 Boxing/java/GameSession.java new file mode 100644 index 00000000..3a2c77a5 --- /dev/null +++ b/15 Boxing/java/GameSession.java @@ -0,0 +1,67 @@ +/** + * Game Session + * The session store the state of the game + */ +public class GameSession { + private final Player player; + private final Player opponent; + private int opponentRoundWins = 0; + private int playerRoundWins = 0; + + int playerPoints = 0; + int opponentPoints = 0; + boolean knocked = false; + + GameSession(Player player, Player opponent) { + this.player = player; + this.opponent = opponent; + } + + public Player getPlayer() { return player;} + public Player getOpponent() { return opponent;} + + public void setKnocked() { + knocked = true; + } + + public void resetPoints() { + playerPoints = 0; + opponentPoints = 0; + } + + public void addPlayerPoints(int ptos) { playerPoints+=ptos;} + public void addOpponentPoints(int ptos) { opponentPoints+=ptos;} + + public int getPoints(Player player) { + if(player.isPlayer()) + return playerPoints; + else + return opponentPoints; + } + + public void addRoundWind(Player player) { + if(player.isPlayer()) playerRoundWins++; else opponentRoundWins++; + } + + public boolean isOver() { + return (opponentRoundWins >= 2 || playerRoundWins >= 2); + } + + public boolean isRoundWinner(Player player) { + if (player.isPlayer()) + return playerPoints > opponentPoints; + else + return opponentPoints > playerPoints; + } + + public boolean isGameWinner(Player player) { + if (player.isPlayer()) + return playerRoundWins > 2; + else + return opponentRoundWins > 2; + } + + public boolean isPlayerKnocked() { + return knocked; + } +} \ No newline at end of file diff --git a/15 Boxing/java/Player.java b/15 Boxing/java/Player.java new file mode 100644 index 00000000..2462b9d0 --- /dev/null +++ b/15 Boxing/java/Player.java @@ -0,0 +1,42 @@ +/** + * The Player class model the user and compuer player + */ +public class Player { + private final String name; + private final Punch bestPunch; + private final Punch vulnerability; + private boolean isPlayer = false; + + public Player(String name, Punch bestPunch, Punch vulnerability) { + this.name = name; + this.bestPunch = bestPunch; + this.vulnerability = vulnerability; + this.isPlayer = true; + } + + /** + * Player with random Best Punch and Vulnerability + */ + public Player(String name) { + this.name = name; + + int b1; + int d1; + + do { + b1 = Basic.randomOf(4); + d1 = Basic.randomOf(4); + } while (b1 == d1); + + this.bestPunch = Punch.fromCode(b1); + this.vulnerability = Punch.fromCode(d1); + } + + public boolean isPlayer() { return isPlayer; } + public String getName() { return name; } + public Punch getBestPunch() { return bestPunch; } + + public boolean hitVulnerability(Punch punch) { + return vulnerability == punch; + } +} \ No newline at end of file diff --git a/15 Boxing/java/Punch.java b/15 Boxing/java/Punch.java new file mode 100644 index 00000000..24745b92 --- /dev/null +++ b/15 Boxing/java/Punch.java @@ -0,0 +1,27 @@ +import java.util.Arrays; + +/** + * Types of Punches + */ +public enum Punch { + FULL_SWING(1), + HOOK(2), + UPPERCUT(3), + JAB(4); + + private final int code; + + Punch(int code) { + this.code = code; + } + + int getCode() { return code;} + + public static Punch fromCode(int code) { + return Arrays.stream(Punch.values()).filter(p->p.code == code).findAny().orElse(null); + } + + public static Punch random() { + return Punch.fromCode(Basic.randomOf(4)); + } +} diff --git a/66 Number/java/main.class b/66 Number/java/main.class new file mode 100644 index 00000000..c3df4ebf --- /dev/null +++ b/66 Number/java/main.class @@ -0,0 +1,69 @@ + +import java.time.temporal.ValueRange; +import java.util.Arrays; +import java.util.Random; +import java.util.Scanner; + +public class Number { + + public static int points = 0; + + public static void printempty() { System.out.println(" "); } + + public static void print(String toprint) { System.out.println(toprint); } + + public static void main(String[] args) { + print("YOU HAVE 100 POINTS. BY GUESSING NUMBERS FROM 1 TO 5, YOU"); + print("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO"); + print("A RANDOM NUMBER SELECTED BY THE COMPUTER."); + printempty(); + print("YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)"); + print("YOUR POINT COUNT. YOU WIN WHEN YOU GET 500 POINTS."); + printempty(); + + try { + while (true) { + print("GUESS A NUMBER FROM 1 TO 5"); + + + Scanner numbersc = new Scanner(System.in); + String numberstring = numbersc.nextLine(); + + int number = Integer.parseInt(numberstring); + + if (!(number < 1| number > 5)) { + + Random rand = new Random(); + + int randomNum = rand.nextInt((5 - 1) + 1) + 1; + + if (randomNum == number) { + print("YOU HIT THE JACKPOT!!!"); + points = points * 2; + } else if(ValueRange.of(randomNum, randomNum + 1).isValidIntValue(number)) { + print("+5"); + points = points + 5; + } else if(ValueRange.of(randomNum - 1, randomNum + 2).isValidIntValue(number)) { + print("+1"); + points = points + 1; + } else if(ValueRange.of(randomNum - 3, randomNum + 1).isValidIntValue(number)) { + print("-1"); + points = points - 1; + } else { + print("-half"); + points = (int) (points * 0.5); + } + + print("YOU HAVE " + points + " POINTS."); + } + + if (points >= 500) { + print("!!!!YOU WIN!!!! WITH " + points + " POINTS."); + return; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} From fb8fe2b93b632b334fdfd27e2259f1332ec8dc32 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Mon, 22 Mar 2021 18:29:41 -0400 Subject: [PATCH 321/749] Ported Hello game to Java. --- 45 Hello/java/Hello.java | 216 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 45 Hello/java/Hello.java diff --git a/45 Hello/java/Hello.java b/45 Hello/java/Hello.java new file mode 100644 index 00000000..7807a2dd --- /dev/null +++ b/45 Hello/java/Hello.java @@ -0,0 +1,216 @@ +import java.util.Scanner; + +/** + * Game of Hello + *

+ * Based on the BASIC game of Hello here + * https://github.com/coding-horror/basic-computer-games/blob/main/45%20Hello/hello.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Hello { + + private static final int MONEY_WAIT_MS = 3000; + + private final boolean goodEnding = false; + + private final Scanner scan; // For user input + + public Hello() { + + scan = new Scanner(System.in); + + } // End of constructor Hello + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(32) + "HELLO"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + boolean moreProblems = true; + + String userCategory = ""; + String userName = ""; + String userResponse = ""; + + // Name question + System.out.println("HELLO. MY NAME IS CREATIVE COMPUTER.\n\n"); + System.out.print("WHAT'S YOUR NAME? "); + userName = scan.nextLine(); + System.out.println(""); + + // Enjoyment question + System.out.print("HI THERE, " + userName + ", ARE YOU ENJOYING YOURSELF HERE? "); + + while (true) { + userResponse = scan.nextLine(); + System.out.println(""); + + if (userResponse.toUpperCase().equals("YES")) { + System.out.println("I'M GLAD TO HEAR THAT, " + userName + ".\n"); + break; + } + else if (userResponse.toUpperCase().equals("NO")) { + System.out.println("OH, I'M SORRY TO HEAR THAT, " + userName + ". MAYBE WE CAN"); + System.out.println("BRIGHTEN UP YOUR VISIT A BIT."); + break; + } + else { + System.out.println(userName + ", I DON'T UNDERSTAND YOUR ANSWER OF '" + userResponse + "'."); + System.out.print("PLEASE ANSWER 'YES' OR 'NO'. DO YOU LIKE IT HERE? "); + } + } + + // Category question + System.out.println(""); + System.out.println("SAY, " + userName + ", I CAN SOLVE ALL KINDS OF PROBLEMS EXCEPT"); + System.out.println("THOSE DEALING WITH GREECE. WHAT KIND OF PROBLEMS DO"); + System.out.print("YOU HAVE (ANSWER SEX, HEALTH, MONEY, OR JOB)? "); + + while (moreProblems) { + userCategory = scan.nextLine(); + System.out.println(""); + + // Sex advice + if (userCategory.toUpperCase().equals("SEX")) { + System.out.print("IS YOUR PROBLEM TOO MUCH OR TOO LITTLE? "); + userResponse = scan.nextLine(); + System.out.println(""); + + while (true) { + if (userResponse.toUpperCase().equals("TOO MUCH")) { + System.out.println("YOU CALL THAT A PROBLEM?!! I SHOULD HAVE SUCH PROBLEMS!"); + System.out.println("IF IT BOTHERS YOU, " + userName + ", TAKE A COLD SHOWER."); + break; + } + else if (userResponse.toUpperCase().equals("TOO LITTLE")) { + System.out.println("WHY ARE YOU HERE IN SUFFERN, " + userName + "? YOU SHOULD BE"); + System.out.println("IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME"); + System.out.println("REAL ACTION."); + break; + } + else { + System.out.println("DON'T GET ALL SHOOK, " + userName + ", JUST ANSWER THE QUESTION"); + System.out.print("WITH 'TOO MUCH' OR 'TOO LITTLE'. WHICH IS IT? "); + userResponse = scan.nextLine(); + } + } + } + // Health advice + else if (userCategory.toUpperCase().equals("HEALTH")) { + System.out.println("MY ADVICE TO YOU " + userName + " IS:"); + System.out.println(" 1. TAKE TWO ASPRIN"); + System.out.println(" 2. DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)"); + System.out.println(" 3. GO TO BED (ALONE)"); + } + // Money advice + else if (userCategory.toUpperCase().equals("MONEY")) { + System.out.println("SORRY, " + userName + ", I'M BROKE TOO. WHY DON'T YOU SELL"); + System.out.println("ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING"); + System.out.println("SO YOU WON'T NEED SO MUCH MONEY?"); + } + // Job advice + else if (userCategory.toUpperCase().equals("JOB")) { + System.out.println("I CAN SYMPATHIZE WITH YOU " + userName + ". I HAVE TO WORK"); + System.out.println("VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES"); + System.out.println("REALLY BEAT ON MY KEYBOARD. MY ADVICE TO YOU, " + userName + ","); + System.out.println("IS TO OPEN A RETAIL COMPUTER STORE. IT'S GREAT FUN."); + } + else { + System.out.println("OH, " + userName + ", YOUR ANSWER OF " + userCategory + " IS GREEK TO ME."); + } + + // More problems question + while (true) { + System.out.println(""); + System.out.print("ANY MORE PROBLEMS YOU WANT SOLVED, " + userName + "? "); + userResponse = scan.nextLine(); + System.out.println(""); + + if (userResponse.toUpperCase().equals("YES")) { + System.out.print("WHAT KIND (SEX, MONEY, HEALTH, JOB)? "); + break; + } + else if (userResponse.toUpperCase().equals("NO")) { + moreProblems = false; + break; + } + else { + System.out.println("JUST A SIMPLE 'YES' OR 'NO' PLEASE, " + userName + "."); + } + } + } + + // Payment question + System.out.println(""); + System.out.println("THAT WILL BE $5.00 FOR THE ADVICE, " + userName + "."); + System.out.println("PLEASE LEAVE THE MONEY ON THE TERMINAL."); + + // Pause + try { + Thread.sleep(MONEY_WAIT_MS); + } catch (Exception e) { + System.out.println("Caught Exception: " + e.getMessage()); + } + + System.out.println("\n\n"); + + while (true) { + System.out.print("DID YOU LEAVE THE MONEY? "); + userResponse = scan.nextLine(); + System.out.println(""); + + if (userResponse.toUpperCase().equals("YES")) { + System.out.println("HEY, " + userName + "??? YOU LEFT NO MONEY AT ALL!"); + System.out.println("YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING."); + System.out.println(""); + System.out.println("WHAT A RIP OFF, " + userName + "!!!\n"); + break; + } + else if (userResponse.toUpperCase().equals("NO")) { + System.out.println("THAT'S HONEST, " + userName + ", BUT HOW DO YOU EXPECT"); + System.out.println("ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENTS"); + System.out.println("DON'T PAY THEIR BILLS?"); + break; + } + else { + System.out.println("YOUR ANSWER OF '" + userResponse + "' CONFUSES ME, " + userName + "."); + System.out.println("PLEASE RESPOND WITH 'YES' OR 'NO'."); + } + } + + // Legacy included unreachable code + if (goodEnding) { + System.out.println("NICE MEETING YOU, " + userName + ", HAVE A NICE DAY."); + } + else { + System.out.println(""); + System.out.println("TAKE A WALK, " + userName + ".\n"); + } + + } // End of method startGame + + public static void main(String[] args) { + + Hello hello = new Hello(); + hello.play(); + + } // End of method main + +} // End of class Hello From 3d984d25dcae6bf66c3e3e24b83fb380909b7b15 Mon Sep 17 00:00:00 2001 From: nanochess Date: Mon, 22 Mar 2021 21:41:30 -0600 Subject: [PATCH 322/749] Ported GOLF to Javascript --- 39 Golf/javascript/golf.html | 9 + 39 Golf/javascript/golf.js | 369 +++++++++++++++++++++++++++++++++++ 2 files changed, 378 insertions(+) create mode 100644 39 Golf/javascript/golf.html create mode 100644 39 Golf/javascript/golf.js diff --git a/39 Golf/javascript/golf.html b/39 Golf/javascript/golf.html new file mode 100644 index 00000000..bf43de8e --- /dev/null +++ b/39 Golf/javascript/golf.html @@ -0,0 +1,9 @@ + + +GOLF + + +


+
+
+
diff --git a/39 Golf/javascript/golf.js b/39 Golf/javascript/golf.js
new file mode 100644
index 00000000..814d589e
--- /dev/null
+++ b/39 Golf/javascript/golf.js	
@@ -0,0 +1,369 @@
+// GOLF
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var la = [];
+var f;
+var s1;
+var g2;
+var g3;
+var x;
+
+var hole_data = [
+    361,4,4,2,389,4,3,3,206,3,4,2,500,5,7,2,
+    408,4,2,4,359,4,6,4,424,4,4,2,388,4,4,4,
+    196,3,7,2,400,4,7,2,560,5,7,2,132,3,2,2,
+    357,4,4,4,294,4,2,4,475,5,2,3,375,4,4,2,
+    180,3,6,2,550,5,6,6,
+];
+
+function show_obstacle()
+{
+    switch (la[x]) {
+        case 1:
+            print("FAIRWAY.\n");
+            break;
+        case 2:
+            print("ROUGH.\n");
+            break;
+        case 3:
+            print("TREES.\n");
+            break;
+        case 4:
+            print("ADJACENT FAIRWAY.\n");
+            break;
+        case 5:
+            print("TRAP.\n");
+            break;
+        case 6:
+            print("WATER.\n");
+            break;
+    }
+}
+
+function show_score()
+{
+    g2 += s1;
+    print("TOTAL PAR FOR " + (f - 1) + " HOLES IS " + g3 + "  YOUR TOTAL IS " + g2 + "\n");
+}
+
+// Main program
+async function main()
+{
+    print(tab(34) + "GOLF\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("WELCOME TO THE CREATIVE COMPUTING COUNTRY CLUB,\n");
+    print("AN EIGHTEEN HOLE CHAMPIONSHIP LAYOUT LOCATED A SHORT\n");
+    print("DISTANCE FROM SCENIC DOWNTOWN MORRISTOWN.  THE\n");
+    print("COMMENTATOR WILL EXPLAIN THE GAME AS YOU PLAY.\n");
+    print("ENJOY YOUR GAME; SEE YOU AT THE 19TH HOLE...\n");
+    print("\n");
+    print("\n");
+    next_hole = 0;
+    g1 = 18;
+    g2 = 0;
+    g3 = 0;
+    a = 0;
+    n = 0.8;
+    s2 = 0;
+    f = 1;
+    while (1) {
+        print("WHAT IS YOUR HANDICAP");
+        h = parseInt(await input());
+        print("\n");
+        if (h < 0 || h > 30) {
+            print("PGA HANDICAPS RANGE FROM 0 TO 30.\n");
+        } else {
+            break;
+        }
+    }
+    do {
+        print("DIFFICULTIES AT GOLF INCLUDE:\n");
+        print("0=HOOK, 1=SLICE, 2=POOR DISTANCE, 4=TRAP SHOTS, 5=PUTTING\n");
+        print("WHICH ONE (ONLY ONE) IS YOUR WORST");
+        t = parseInt(await input());
+        print("\n");
+    } while (t > 5) ;
+    s1 = 0;
+    first_routine = true;
+    while (1) {
+        if (first_routine) {
+            la[0] = 0;
+            j = 0;
+            q = 0;
+            s2++;
+            k = 0;
+            if (f != 1) {
+                print("YOUR SCORE ON HOLE " + (f - 1) + " WAS " + s1 + "\n");
+                show_score();
+                if (g1 == f - 1)    // Completed all holes?
+                    return;         // Exit game
+                if (s1 > p + 2) {
+                    print("KEEP YOUR HEAD DOWN.\n");
+                } else if (s1 == p) {
+                    print("A PAR.  NICE GOING.\n");
+                } else if (s1 == p - 1) {
+                    print("A BIRDIE.\n");
+                } else if (s1 == p - 2) {
+                    if (p != 3)
+                        print("A GREAT BIG EAGLE.\n");
+                    else
+                        print("A HOLE IN ONE.\n");
+                }
+            }
+            if (f == 19) {
+                print("\n");
+                show_score();
+                if (g1 == f - 1)
+                    return;
+            }
+            s1 = 0;
+            print("\n");
+            if (s1 != 0 && la[0] < 1)
+                la[0] = 1;
+        }
+        if (s1 == 0) {
+            d = hole_data[next_hole++];
+            p = hole_data[next_hole++];
+            la[1] = hole_data[next_hole++];
+            la[2] = hole_data[next_hole++];
+            print("\n");
+            print("YOU ARE AT THE TEE OFF HOLE " + f + " DISTANCE " + d + " YARDS, PAR " + p + "\n");
+            g3 += p;
+            print("ON YOUR RIGHT IS ");
+            x = 1;
+            show_obstacle();
+            print("ON YOUR LEFT IS ");
+            x = 2
+            show_obstacle();
+        } else {
+            x = 0;
+            if (la[0] > 5) {
+                if (la[0] > 6) {
+                    print("YOUR SHOT WENT OUT OF BOUNDS.\n");
+                } else {
+                    print("YOUR SHOT WENT INTO THE WATER.\n");
+                }
+                s1++;
+                print("PENALTY STROKE ASSESSED.  HIT FROM PREVIOUS LOCATION.\n");
+                j++;
+                la[0] = 1;
+                d = b;
+            } else {
+                print("SHOT WENT " + d1 + " YARDS.  IT'S " + d2 + " YARDS FROM THE CUP.\n");
+                print("BALL IS " + Math.floor(o) + " YARDS OFF LINE... IN ");
+                show_obstacle();
+            }
+        }
+        
+        while (1) {
+            if (a != 1) {
+                print("SELECTION OF CLUBS\n");
+                print("YARDAGE DESIRED                       SUGGESTED CLUBS\n");
+                print("200 TO 280 YARDS                           1 TO 4\n");
+                print("100 TO 200 YARDS                          19 TO 13\n");
+                print("  0 TO 100 YARDS                          29 TO 23\n");
+                a = 1;
+            }
+            print("WHAT CLUB DO YOU CHOOSE");
+            c = parseInt(await input());
+            print("\n");
+            if (c >= 1 && c <= 29 && (c < 5 || c >= 12)) {
+                if (c > 4)
+                    c -= 6;
+                if (la[0] <= 5 || c == 14 || c == 23) {
+                    s1++;
+                    w = 1;
+                    if (c <= 13) {
+                        if (f % 3 == 0 && s2 + q + (10 * (f - 1) / 18) < (f - 1) * (72 + ((h + 1) / 0.85)) / 18) {
+                            q++;
+                            if (s1 % 2 != 0 && d >= 95) {
+                                print("BALL HIT TREE - BOUNCED INTO ROUGH " + (d - 75) + " YARDS FROM HOLE.\n");
+                                d -= 75;
+                                continue;
+                            }
+                            print("YOU DUBBED IT.\n");
+                            d1 = 35;
+                            second_routine = 1;
+                            break;
+                        } else if (c < 4 && la[0] == 2) {
+                            print("YOU DUBBED IT.\n");
+                            d1 = 35;
+                            second_routine = 1;
+                            break;
+                        } else {
+                            second_routine = 0;
+                            break;
+                        }
+                    } else {
+                        print("NOW GAUGE YOUR DISTANCE BY A PERCENTAGE (1 TO 100)\n");
+                        print("OF A FULL SWING");
+                        w = parseInt(await input());
+                        w /= 100;
+                        print("\n");
+                        if (w <= 1) {
+                            if (la[0] == 5) {
+                                if (t == 3) {
+                                    if (Math.random() <= n) {
+                                        n *= 0.2;
+                                        print("SHOT DUBBED, STILL IN TRAP.\n");
+                                        continue;
+                                    }
+                                    n = 0.8;
+                                }
+                                d2 = 1 + (3 * Math.floor((80 / (40 - h)) * Math.random()));
+                                second_routine = 2;
+                                break;
+                            }
+                            if (c != 14)
+                                c -= 10;
+                            second_routine = 0;
+                            break;
+                        }
+                        s1--;
+                        // Fall through to THAT CLUB IS NOT IN THE BAG.
+                    }
+                }
+            }
+            print("THAT CLUB IS NOT IN THE BAG.\n");
+            print("\n");
+        }
+        if (second_routine == 0) {
+            if (s1 > 7 && d < 200) {
+                d2 = 1 + (3 * Math.floor((80 / (40 - h)) * Math.random()));
+                second_routine = 2;
+            } else {
+                d1 = Math.floor(((30 - h) * 2.5 + 187 - ((30 - h) * 0.25 + 15) * c / 2) + 25 * Math.random());
+                d1 = Math.floor(d1 * w);
+                if (t == 2)
+                    d1 = Math.floor(d1 * 0.85);
+            }
+        }
+        if (second_routine <= 1) {
+            o = (Math.random() / 0.8) * (2 * h + 16) * Math.abs(Math.tan(d1 * 0.0035));
+            d2 = Math.floor(Math.sqrt(Math.pow(o, 2) + Math.pow(Math.abs(d - d1), 2)));
+            if (d - d1 < 0) {
+                if (d2 >= 20)
+                    print("TOO MUCH CLUB, YOU'RE PAST THE HOLE.\n");
+            }
+            b = d;
+            d = d2;
+            if (d2 > 27) {
+                if (o < 30 || j > 0) {
+                    la[0] = 1;
+                } else {
+                    if (t <= 0) {
+                        s9 = (s2 + 1) / 15;
+                        if (Math.floor(s9) == s9) {
+                            print("YOU SLICED- ");
+                            la[0] = la[1];
+                        } else {
+                            print("YOU HOOKED- ");
+                            la[0] = la[2];
+                        }
+                    } else {
+                        s9 = (s2 + 1) / 15;
+                        if (Math.floor(s9) == s9) {
+                            print("YOU HOOKED- ");
+                            la[0] = la[2];
+                        } else {
+                            print("YOU SLICED- ");
+                            la[0] = la[1];
+                        }
+                    }
+                    if (o > 45)
+                        print("BADLY.\n");
+                }
+                first_routine = false;
+            } else if (d2 > 20) {
+                la[0] = 5;
+                first_routine = false;
+            } else if (d2 > 0.5) {
+                la[0] = 8;
+                d2 = Math.floor(d2 * 3);
+                second_routine = 2;
+            } else {
+                la[0] = 9;
+                print("YOU HOLED IT.\n");
+                print("\n");
+                f++;
+                first_routine = true;
+            }
+        }
+        if (second_routine == 2) {
+            while (1) {
+                print("ON GREEN, " + d2 + " FEET FROM THE PIN.\n");
+                print("CHOOSE YOUR PUTT POTENCY (1 TO 13):");
+                i = parseInt(await input());
+                s1++;
+                if (s1 + 1 - p <= (h * 0.072) + 2 && k <= 2) {
+                    k++;
+                    if (t == 4)
+                        d2 -= i * (4 + 1 * Math.random()) + 1;
+                    else
+                        d2 -= i * (4 + 2 * Math.random()) + 1.5;
+                    if (d2 < -2) {
+                        print("PASSED BY CUP.\n");
+                        d2 = Math.floor(-d2);
+                        continue;
+                    }
+                    if (d2 > 2) {
+                        print("PUTT SHORT.\n");
+                        d2 = Math.floor(d2);
+                        continue;
+                    }
+                }
+                print("YOU HOLED IT.\n");
+                print("\n");
+                f++;
+                break;
+            }
+            first_routine = true;
+        }
+    }
+}
+
+main();

From c552dbfe9ab9ce42a665444bce4eb0bab9bd0dba Mon Sep 17 00:00:00 2001
From: Nezumi Ronin 
Date: Tue, 23 Mar 2021 02:34:53 -0600
Subject: [PATCH 323/749] Create love.pl

Made with Perl!
---
 58 Love/perl/love.pl | 54 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 58 Love/perl/love.pl

diff --git a/58 Love/perl/love.pl b/58 Love/perl/love.pl
new file mode 100644
index 00000000..9e9f95cc
--- /dev/null
+++ b/58 Love/perl/love.pl	
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+use strict;
+
+
+print ' 'x 33 . "LOVE\n";
+print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+print "A TRIBUTE TO THE GREAT AMERICAN ARTIST, ROBERT INDIANA.\n";
+print "HIS GREATEST WORK WILL BE REPRODUCED WITH A MESSAGE OF\n";
+print "YOUR CHOICE UP TO 60 CHARACTERS.  IF YOU CAN'T THINK OF\n";
+print "A MESSAGE, SIMPLE TYPE THE WORD 'LOVE'\n"; print "\n";
+print "YOUR MESSAGE, PLEASE? "; chomp(my $A = );
+my $L= length($A);
+
+
+#Original logic too fuzzy, remaked.
+my $Width= 60;
+my $Text= substr($A x ($Width/$L+1), 0, $Width);
+for (my $I=1; $I<10; $I++) { print "\n"; }
+
+my @Data= (
+	60,1,12,26,9,12,3,8,24,17,8,4,6,23,21,6,4,6,22,12,5,6,5,
+	4,6,21,11,8,6,4,4,6,21,10,10,5,4,4,6,21,9,11,5,4,
+	4,6,21,8,11,6,4,4,6,21,7,11,7,4,4,6,21,6,11,8,4,
+	4,6,19,1,1,5,11,9,4,4,6,19,1,1,5,10,10,4,4,6,18,2,1,6,8,11,4,
+	4,6,17,3,1,7,5,13,4,4,6,15,5,2,23,5,1,29,5,17,8,
+	1,29,9,9,12,1,13,5,40,1,1,13,5,40,1,4,6,13,3,10,6,12,5,1,
+	5,6,11,3,11,6,14,3,1,5,6,11,3,11,6,15,2,1,
+	6,6,9,3,12,6,16,1,1,6,6,9,3,12,6,7,1,10,
+	7,6,7,3,13,6,6,2,10,7,6,7,3,13,14,10,8,6,5,3,14,6,6,2,10,
+	8,6,5,3,14,6,7,1,10,9,6,3,3,15,6,16,1,1,
+	9,6,3,3,15,6,15,2,1,10,6,1,3,16,6,14,3,1,10,10,16,6,12,5,1,
+	11,8,13,27,1,11,8,13,27,1,60
+	);
+
+
+my $Pos=0;
+my $Toggle=1;
+foreach my $Size (@Data) {
+	my $Chunk= $Toggle ? substr($Text, $Pos, $Size) : " " x $Size;
+	print $Chunk;
+	$Pos+= $Size;
+	$Toggle= !$Toggle;
+	if ($Pos>= $Width) {
+		print "\n";
+		$Toggle=1;
+		$Pos=0;
+		}
+	}
+
+for (my $I=1; $I<10; $I++) { print "\n"; }
+exit;
+
+

From 32fc7fd73ed4b44b61ee1eac1e18768772923a79 Mon Sep 17 00:00:00 2001
From: Nezumi Ronin 
Date: Tue, 23 Mar 2021 02:36:48 -0600
Subject: [PATCH 324/749] Create rockscissors.pl

Made with Perl!
---
 74 Rock Scissors Paper/perl/rockscissors.pl | 56 +++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 74 Rock Scissors Paper/perl/rockscissors.pl

diff --git a/74 Rock Scissors Paper/perl/rockscissors.pl b/74 Rock Scissors Paper/perl/rockscissors.pl
new file mode 100644
index 00000000..ac83f5cf
--- /dev/null
+++ b/74 Rock Scissors Paper/perl/rockscissors.pl	
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+use strict;
+
+
+print ' 'x 21 . "GAME OF ROCK, SCISSORS, PAPER\n";
+print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+
+
+my $Q=0;
+my $C=0;
+my $H=0;
+
+do {
+	print "HOW MANY GAMES? "; chomp($Q = );
+	if ($Q>10) { print "SORRY, BUT WE AREN'T ALLOWED TO PLAY THAT MANY.\n"; }
+	} until ($Q<11);
+
+for (my $G=1; $G<=$Q; $G++) {
+	print "\n"; print "GAME NUMBER $G\n";
+	my $X=int(rand(1)*3+1);
+
+	my $K=0;
+	do {
+		print "3=ROCK...2=SCISSORS...1=PAPER\n";
+		print "1...2...3...WHAT'S YOUR CHOICE? "; chomp($K = );
+		if (($K-1)*($K-2)*($K-3)!=0) { print "INVALID.\n"; $K=0; } 
+		} until ($K!=0);
+
+
+	print "THIS IS MY CHOICE...\n";
+	if ($X==1) { print "...PAPER\n"; }
+	if ($X==2) { print "...SCISSORS\n"; }
+	if ($X==3) { print "...ROCK\n"; }
+
+	#Original logic too complex...
+	if ($X==$K) { print "TIE GAME. NO WINNER.\n"; next; }
+	my $Who=0;
+	if ($X==1 && $K==3) { $Who=1; } #Paper wins over rock.
+	if ($X==2 && $K==1) { $Who=1; } #Scissors wins over paper.
+	if ($X==3 && $K==2) { $Who=1; } #Rock wins over scissors.
+	if ($Who==1) {
+		print "WOW! I WIN!!!\n"; $C=$C+1;
+		} else {
+		print "YOU WIN!!!\n"; $H=$H+1;
+		}
+	}
+
+print "\n"; print "HERE IS THE FINAL GAME SCORE:\n";
+print "I HAVE WON $C GAME(S).\n";
+print "YOU HAVE WON $H GAME(S).\n";
+print "AND ".($Q-($C+$H))." GAME(S) ENDED IN A TIE.\n";
+print "\n"; print "THANKS FOR PLAYING!!\n";
+exit;
+
+

From d92a61c5c00f3d2233d65d43a1d417baab33466c Mon Sep 17 00:00:00 2001
From: Nezumi Ronin 
Date: Tue, 23 Mar 2021 02:38:27 -0600
Subject: [PATCH 325/749] Create kinema.pl

Made with Perl!
---
 52 Kinema/perl/kinema.pl | 53 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 52 Kinema/perl/kinema.pl

diff --git a/52 Kinema/perl/kinema.pl b/52 Kinema/perl/kinema.pl
new file mode 100644
index 00000000..ef607983
--- /dev/null
+++ b/52 Kinema/perl/kinema.pl	
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+use strict;
+
+
+print ' 'x 33 . "KINEMA\n";
+print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+
+while (1) {
+	print "\n";
+	print "\n";
+	my $Q=0;
+	my $V=5+int(35*rand(1));
+	print "A BALL IS THROWN UPWARDS AT $V METERS PER SECOND.\n";
+	print "\n";
+
+	my $A=.05*$V^2;
+	print "HOW HIGH WILL IT GO (IN METERS)";
+	$Q+= &Input($A);
+
+	$A=$V/5;
+	print "HOW LONG UNTIL IT RETURNS (IN SECONDS)";
+	$Q+= &Input($A);
+
+	my $T=1+int(2*$V*rand(1))/10;
+	$A=$V-10*$T;
+	print "WHAT WILL ITS VELOCITY BE AFTER $T SECONDS";
+	$Q+= &Input($A);
+
+	print "\n";
+	print "$Q RIGHT OUT OF 3.";
+	if ($Q<2) { next; }
+	print " NOT BAD.\n";
+	}
+
+exit;
+
+
+#Line500:
+sub Input {
+	my ($A)= @_;
+	my $Point=0;
+	print "? "; chomp(my $G = );
+	if (abs(($G-$A)/$A)<.15) {
+		print "CLOSE ENOUGH.\n";
+		$Point=1;
+		} else {
+		print "NOT EVEN CLOSE....\n";
+		}
+	print "CORRECT ANSWER IS $A\n";
+	print "\n";
+	return $Point;
+	}

From d9ee2fa070c70ba09042e4a17ac706afdb6592df Mon Sep 17 00:00:00 2001
From: rbamforth <79797573+rbamforth@users.noreply.github.com>
Date: Tue, 23 Mar 2021 11:45:38 +0000
Subject: [PATCH 326/749] Added Tester project and tests for the Card class.

---
 94 War/csharp/War/War.sln                    |   8 +-
 94 War/csharp/War/War/Cards.cs               | 102 +++++++++++--------
 94 War/csharp/War/WarTester/Tests.cs         |  90 ++++++++++++++++
 94 War/csharp/War/WarTester/WarTester.csproj |  20 ++++
 4 files changed, 179 insertions(+), 41 deletions(-)
 create mode 100644 94 War/csharp/War/WarTester/Tests.cs
 create mode 100644 94 War/csharp/War/WarTester/WarTester.csproj

diff --git a/94 War/csharp/War/War.sln b/94 War/csharp/War/War.sln
index 8f9560d8..a03a3a64 100644
--- a/94 War/csharp/War/War.sln	
+++ b/94 War/csharp/War/War.sln	
@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio Version 16
 VisualStudioVersion = 16.0.31112.23
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "War", "War\War.csproj", "{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "War", "War\War.csproj", "{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WarTester", "WarTester\WarTester.csproj", "{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +17,10 @@ Global
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.Build.0 = Release|Any CPU
+		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/94 War/csharp/War/War/Cards.cs b/94 War/csharp/War/War/Cards.cs
index ad84735a..1efdc715 100644
--- a/94 War/csharp/War/War/Cards.cs	
+++ b/94 War/csharp/War/War/Cards.cs	
@@ -34,11 +34,37 @@ namespace War
 
     // TODO Testing
 
-    class Card
+    public class Card
     {
-        // TODO Turn into properties, maybe??
-        private Suit suit;
-        private Rank rank;
+        private readonly Suit suit;
+        private readonly Rank rank;
+
+        private static Dictionary suitNames = new Dictionary()
+        {
+            { Suit.none, "N"},
+            { Suit.clubs, "C"},
+            { Suit.diamonds, "D"},
+            { Suit.hearts, "H"},
+            { Suit.spades, "S"},
+        };
+
+        private static Dictionary rankNames = new Dictionary()
+        {
+            { Rank.none, "0"},
+            { Rank.two, "2"},
+            { Rank.three, "3"},
+            { Rank.four, "4"},
+            { Rank.five, "5"},
+            { Rank.six, "6"},
+            { Rank.seven, "7"},
+            { Rank.eight, "8"},
+            { Rank.nine, "9"},
+            { Rank.ten, "10"},
+            { Rank.jack, "J"},
+            { Rank.queen, "Q"},
+            { Rank.king, "K"},
+            { Rank.ace, "A"},
+        };
 
         public Card(Suit suit, Rank rank) // immutable
         {
@@ -47,28 +73,31 @@ namespace War
         }
 
         // would normally consider suit and rank but in this case we only want to compare rank.
-        public static bool operator ==(Card lhs, Card rhs)
-        {
-            return lhs.rank == rhs.rank;
-        }
+        //public static bool operator ==(Card lhs, Card rhs)
+        //{
+        //    return lhs.rank == rhs.rank;
+        //}
 
-        public static bool operator !=(Card lhs, Card rhs)
-        {
-            return !(lhs == rhs);
-        }
+        //public static bool operator !=(Card lhs, Card rhs)
+        //{
+        //    return !(lhs == rhs);
+        //}
 
         public static bool operator <(Card lhs, Card rhs)
         {
             return lhs.rank < rhs.rank;
         }
+
         public static bool operator >(Card lhs, Card rhs)
         {
             return rhs < lhs;
         }
+
         public static bool operator <=(Card lhs, Card rhs)
         {
             return !(lhs > rhs);
         }
+
         public static bool operator >=(Card lhs, Card rhs)
         {
             return !(lhs < rhs);
@@ -76,38 +105,31 @@ namespace War
 
         public override string ToString()
         {
-            // TODO No need to create the dictionaries each time this is called.
-            // Also make it static.
-            // Is there a C# equivalent of an initializer list?
-            var suitNames = new Dictionary();
-
-            suitNames[Suit.none]     = "N";
-            suitNames[Suit.clubs]    = "C";
-            suitNames[Suit.diamonds] = "D";
-            suitNames[Suit.hearts]   = "H";
-            suitNames[Suit.spades]   = "S";
-
-            var rankNames = new Dictionary();
-            rankNames[Rank.none]  = "0";
-            rankNames[Rank.two]   = "2";
-            rankNames[Rank.three] = "3";
-            rankNames[Rank.four]  = "4";
-            rankNames[Rank.five]  = "5";
-            rankNames[Rank.six]   = "6";
-            rankNames[Rank.seven] = "7";
-            rankNames[Rank.eight] = "8";
-            rankNames[Rank.nine]  = "9";
-            rankNames[Rank.ten]   = "10";
-            rankNames[Rank.jack]  = "J";
-            rankNames[Rank.queen] = "Q";
-            rankNames[Rank.king]  = "K";
-            rankNames[Rank.ace]  = "A";
-
             return $"{suitNames[suit]}-{rankNames[rank]}"; // string interpolation
         }
     }
 
-    class Deck
+    public class Deck
     {
+        private const int deckSize = 52;
+        private Card[] theDeck = new Card[deckSize];
+
+        public Deck()
+        {
+            int i = 0;
+            for (Suit suit = Suit.clubs; suit <= Suit.spades; suit++)
+            {
+                for (Rank rank = Rank.two; rank <= Rank.ace; rank++)
+                {
+                    theDeck[i] = new Card(suit, rank);
+                    i++;
+                }
+            }
+        }
+
+        public void Shuffle()
+        {
+
+        }
     }
 }
diff --git a/94 War/csharp/War/WarTester/Tests.cs b/94 War/csharp/War/WarTester/Tests.cs
new file mode 100644
index 00000000..1e811c9e
--- /dev/null
+++ b/94 War/csharp/War/WarTester/Tests.cs	
@@ -0,0 +1,90 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using War;
+
+
+
+namespace WarTester
+{
+    [TestClass]
+    public class CardTest
+    {
+        Card c1 = new Card(Suit.clubs, Rank.two);
+        Card c2 = new Card(Suit.clubs, Rank.ten);
+        Card c3 = new Card(Suit.diamonds, Rank.ten);
+        Card c4 = new Card(Suit.diamonds, Rank.ten);
+
+        [TestMethod]
+        public void LessThan_IsValid()
+        {
+            Assert.IsTrue(c1 < c2, "c1 < c2");  // Same suit, different rank.
+            Assert.IsFalse(c2 < c1, "c2 < c1"); // Same suit, different rank.
+
+            Assert.IsFalse(c3 < c4, "c3 < c4"); // Same suit, same rank.
+
+            Assert.IsTrue(c1 < c3, "c1 < c3");  // Different suit, different rank.
+            Assert.IsFalse(c3 < c1, "c3 < c1"); // Different suit, different rank.
+
+            Assert.IsFalse(c2 < c4, "c2 < c4"); // Different suit, same rank.
+            Assert.IsFalse(c4 < c2, "c4 < c2"); // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void GreaterThan_IsValid()
+        {
+            Assert.IsFalse(c1 > c2, "c1 > c2"); // Same suit, different rank.
+            Assert.IsTrue(c2 > c1, "c2 > c1");  // Same suit, different rank.
+
+            Assert.IsFalse(c3 > c4, "c3 > c4"); // Same suit, same rank.
+
+            Assert.IsFalse(c1 > c3, "c1 > c3"); // Different suit, different rank.
+            Assert.IsTrue(c3 > c1, "c3 > c1");  // Different suit, different rank.
+
+            Assert.IsFalse(c2 > c4, "c2 > c4"); // Different suit, same rank.
+            Assert.IsFalse(c4 > c2, "c4 > c2"); // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void LessThanEquals_IsValid()
+        {
+            Assert.IsTrue(c1 <= c2, "c1 <= c2");  // Same suit, different rank.
+            Assert.IsFalse(c2 <= c1, "c2 <= c1"); // Same suit, different rank.
+
+            Assert.IsTrue(c3 <= c4, "c3 <= c4");  // Same suit, same rank.
+
+            Assert.IsTrue(c1 <= c3, "c1 <= c3");  // Different suit, different rank.
+            Assert.IsFalse(c3 <= c1, "c3 <= c1"); // Different suit, different rank.
+
+            Assert.IsTrue(c2 <= c4, "c2 <= c4");  // Different suit, same rank.
+            Assert.IsTrue(c4 <= c2, "c4 <= c2");  // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void GreaterThanEquals_IsValid()
+        {
+            Assert.IsFalse(c1 >= c2, "c1 >= c2"); // Same suit, different rank.
+            Assert.IsTrue(c2 >= c1, "c2 >= c1");  // Same suit, different rank.
+
+            Assert.IsTrue(c3 >= c4, "c3 >= c4");  // Same suit, same rank.
+
+            Assert.IsFalse(c1 >= c3, "c1 >= c3"); // Different suit, different rank.
+            Assert.IsTrue(c3 >= c1, "c3 >= c1");  // Different suit, different rank.
+
+            Assert.IsTrue(c2 >= c4, "c2 >= c4");  // Different suit, same rank.
+            Assert.IsTrue(c4 >= c2, "c4 >= c2");  // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void ToString_IsValid()
+        {
+            string s1 = c1.ToString();
+            string s2 = c3.ToString();
+            string s3 = new Card(Suit.hearts, Rank.queen).ToString();
+            string s4 = new Card(Suit.spades, Rank.ace).ToString();
+
+            Assert.IsTrue(s1 == "C-2", "s1 invalid");
+            Assert.IsTrue(s2 == "D-10", "s2 invalid");
+            Assert.IsTrue(s3 == "H-Q", "s3 invalid");
+            Assert.IsTrue(s4 == "S-A", "s4 invalid");
+        }
+    }
+}
diff --git a/94 War/csharp/War/WarTester/WarTester.csproj b/94 War/csharp/War/WarTester/WarTester.csproj
new file mode 100644
index 00000000..84aa459a
--- /dev/null
+++ b/94 War/csharp/War/WarTester/WarTester.csproj	
@@ -0,0 +1,20 @@
+
+
+  
+    netcoreapp3.1
+
+    false
+  
+
+  
+    
+    
+    
+    
+  
+
+  
+    
+  
+
+

From c9037fe9abc83b011e26349bc254609c87c05fae Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Tue, 23 Mar 2021 13:59:06 -0600
Subject: [PATCH 327/749] Ported LIFEFORTWO to Javascript

---
 56 Life for Two/javascript/lifefortwo.html |   9 +
 56 Life for Two/javascript/lifefortwo.js   | 209 +++++++++++++++++++++
 2 files changed, 218 insertions(+)
 create mode 100644 56 Life for Two/javascript/lifefortwo.html
 create mode 100644 56 Life for Two/javascript/lifefortwo.js

diff --git a/56 Life for Two/javascript/lifefortwo.html b/56 Life for Two/javascript/lifefortwo.html
new file mode 100644
index 00000000..fbd70636
--- /dev/null
+++ b/56 Life for Two/javascript/lifefortwo.html	
@@ -0,0 +1,9 @@
+
+
+LIFE FOR TWO
+
+
+

+
+
+
diff --git a/56 Life for Two/javascript/lifefortwo.js b/56 Life for Two/javascript/lifefortwo.js
new file mode 100644
index 00000000..a8c90e50
--- /dev/null
+++ b/56 Life for Two/javascript/lifefortwo.js	
@@ -0,0 +1,209 @@
+// LIFE FOR TWO
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var na = [];
+var ka = [, 3,102,103,120,130,121,112,111,12,
+          21,30,1020,1030,1011,1021,1003,1002,1012];
+var aa = [,-1,0,1,0,0,-1,0,1,-1,-1,1,-1,-1,1,1,1];
+var xa = [];
+var ya = [];
+var j;
+var k;
+var m2;
+var m3;
+
+function show_data()
+{
+    k = 0;
+    m2 = 0;
+    m3 = 0;
+    for (j = 0; j <= 6; j++) {
+        print("\n");
+        for (k = 0; k <= 6; k++) {
+            if (j == 0 || j == 6) {
+                if (k == 6)
+                    print(" 0 ");
+                else
+                    print(" " + k + " ");
+            } else if (k == 0 || k == 6) {
+                if (j == 6)
+                    print(" 0\n");
+                else
+                    print(" " + j + " ");
+            } else {
+                if (na[j][k] >= 3) {
+                    for (o1 = 1; o1 <= 18; o1++) {
+                        if (na[j][k] == ka[o1])
+                            break;
+                    }
+                    if (o1 <= 18) {
+                        if (o1 <= 9) {
+                            na[j][k] = 100;
+                            m2++;
+                            print(" * ");
+                        } else {
+                            na[j][k] = 1000;
+                            m3++;
+                            print(" # ");
+                        }
+                    } else {
+                        na[j][k] = 0;
+                        print("   ");
+                    }
+                } else {
+                    na[j][k] = 0;
+                    print("   ");
+                }
+            }
+        }
+    }
+}
+
+function process_board()
+{
+    for (j = 1; j <= 5; j++) {
+        for (k = 1; k <= 5; k++) {
+            if (na[j][k] > 99) {
+                b = 1;
+                if (na[j][k] > 999)
+                    b = 10;
+                for (o1 = 1; o1 <= 15; o1 += 2) {
+                    na[j + aa[o1]][k + aa[o1 + 1]] = na[j + aa[o1]][k + aa[o1 + 1]] + b;
+                }
+            }
+        }
+    }
+    show_data();
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "LIFE2\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print(tab(10) + "U.B. LIFE GAME\n");
+    m2 = 0;
+    m3 = 0;
+    for (j = 0; j <= 6; j++) {
+        na[j] = [];
+        for (k = 0; k <= 6; k++)
+            na[j][k] = 0;
+    }
+    for (b = 1; b <= 2; b++) {
+        p1 = (b == 2) ? 30 : 3;
+        print("\n");
+        print("PLAYER " + b + " - 3 LIVE PIECES.\n");
+        for (k1 = 1; k1 <= 3; k1++) {
+            while (1) {
+                print("X,Y\n");
+                str = await input();
+                ya[b] = parseInt(str);
+                xa[b] = parseInt(str.substr(str.indexOf(",") + 1));
+                if (xa[b] > 0 && xa[b] < 6 && ya[b] > 0 && ya[b] < 5 && na[xa[b]][ya[b]] == 0)
+                    break;
+                print("ILLEGAL COORDS. RETYPE\n");
+            }
+            if (b != 1) {
+                if (xa[1] == xa[2] && ya[1] == ya[2]) {
+                    print("SAME COORD.  SET TO 0\n");
+                    na[xa[b] + 1][ya[b] + 1] = 0;
+                    b = 99;
+                }
+            }
+            na[xa[b]][ya[b]] = p1;
+        }
+    }
+    show_data();
+    while (1) {
+        print("\n");
+        process_board();
+        if (m2 == 0 && m3 == 0) {
+            print("\n");
+            print("A DRAW\n");
+            break;
+        }
+        if (m3 == 0) {
+            print("\n");
+            print("PLAYER 1 IS THE WINNER\n");
+            break;
+        }
+        if (m2 == 0) {
+            print("\n");
+            print("PLAYER 2 IS THE WINNER\n");
+            break;
+        }
+        for (b = 1; b <= 2; b++) {
+            print("\n");
+            print("\n");
+            print("PLAYER " + b + " ");
+            while (1) {
+                print("X,Y\n");
+                str = await input();
+                ya[b] = parseInt(str);
+                xa[b] = parseInt(str.substr(str.indexOf(",") + 1));
+                if (xa[b] > 0 && xa[b] < 6 && ya[b] > 0 && ya[b] < 5 && na[xa[b]][ya[b]] == 0)
+                    break;
+                print("ILLEGAL COORDS. RETYPE\n");
+            }
+            if (b != 1) {
+                if (xa[1] == xa[2] && ya[1] == ya[2]) {
+                    print("SAME COORD.  SET TO 0\n");
+                    na[xa[b] + 1][ya[b] + 1] = 0;
+                    b = 99;
+                }
+            }
+            if (b == 99)
+                break;
+        }
+        if (b <= 2) {
+            na[x[1]][y[1]] = 100;
+            na[x[2]][y[2]] = 1000;
+        }
+    }
+}
+
+main();

From ceec7566f25d027da63693b3bd507337089c8754 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Tue, 23 Mar 2021 22:17:04 -0600
Subject: [PATCH 328/749] Ported MASTERMIND to Javascript

---
 60 Mastermind/javascript/mastermind.html |   9 +
 60 Mastermind/javascript/mastermind.js   | 361 +++++++++++++++++++++++
 2 files changed, 370 insertions(+)
 create mode 100644 60 Mastermind/javascript/mastermind.html
 create mode 100644 60 Mastermind/javascript/mastermind.js

diff --git a/60 Mastermind/javascript/mastermind.html b/60 Mastermind/javascript/mastermind.html
new file mode 100644
index 00000000..e1835c05
--- /dev/null
+++ b/60 Mastermind/javascript/mastermind.html	
@@ -0,0 +1,9 @@
+
+
+MASTERMIND
+
+
+

+
+
+
diff --git a/60 Mastermind/javascript/mastermind.js b/60 Mastermind/javascript/mastermind.js
new file mode 100644
index 00000000..40d8139e
--- /dev/null
+++ b/60 Mastermind/javascript/mastermind.js	
@@ -0,0 +1,361 @@
+// MASTERMIND
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var p9;
+var c9;
+var b;
+var w;
+var f;
+var m;
+
+var qa;
+var sa;
+var ss;
+var as;
+var gs;
+var hs;
+
+function initialize_qa()
+{
+    for (s = 1; s <= p9; s++)
+        qa[s] = 0;
+}
+
+function increment_qa()
+{
+    if (qa[1] <= 0) {
+        // If zero, this is our firt increment: make all ones
+        for (s = 1; s <= p9; s++)
+            qa[s] = 1;
+    } else {
+        q = 1;
+        while (1) {
+            qa[q] = qa[q] + 1;
+            if (qa[q] <= c9)
+                return;
+            qa[q] = 1;
+            q++;
+        }
+    }
+}
+
+function convert_qa()
+{
+    for (s = 1; s <= p9; s++) {
+        as[s] = ls.substr(qa[s] - 1, 1);
+    }
+}
+
+function get_number()
+{
+    b = 0;
+    w = 0;
+    f = 0;
+    for (s = 1; s <= p9; s++) {
+        if (gs[s] == as[s]) {
+            b++;
+            gs[s] = String.fromCharCode(f);
+            as[s] = String.fromCharCode(f + 1);
+            f += 2;
+        } else {
+            for (t = 1; t <= p9; t++) {
+                if (gs[s] == as[t] && gs[t] != as[t]) {
+                    w++;
+                    as[t] = String.fromCharCode(f);
+                    gs[s] = String.fromCharCode(f + 1);
+                    f += 2;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+function convert_qa_hs()
+{
+    for (s = 1; s <= p9; s++) {
+        hs[s] = ls.substr(qa[s] - 1, 1);
+    }
+}
+
+function copy_hs()
+{
+    for (s = 1; s <= p9; s++) {
+        gs[s] = hs[s];
+    }
+}
+
+function board_printout()
+{
+    print("\n");
+    print("BOARD\n");
+    print("MOVE     GUESS          BLACK     WHITE\n");
+    for (z = 1; z <= m - 1; z++) {
+        str = " " + z + " ";
+        while (str.length < 9)
+            str += " ";
+        str += ss[z];
+        while (str.length < 25)
+            str += " ";
+        str += sa[z][1];
+        while (str.length < 35)
+            str += " ";
+        str += sa[z][2];
+        print(str + "\n");
+    }
+    print("\n");
+}
+
+function quit()
+{
+    print("QUITTER!  MY COMBINATION WAS: ");
+    convert_qa();
+    for (x = 1; x <= p9; x++) {
+        print(as[x]);
+    }
+    print("\n");
+    print("GOOD BYE\n");
+}
+
+function show_score()
+{
+    print("SCORE:\n");
+    show_points();
+}
+
+function show_points()
+{
+    print("     COMPUTER " + c + "\n");
+    print("     HUMAN    " + h + "\n");
+    print("\n");
+}
+
+var color = ["BLACK", "WHITE", "RED", "GREEN",
+             "ORANGE", "YELLOW", "PURPLE", "TAN"];
+
+// Main program
+async function main()
+{
+    print(tab(30) + "MASTERMIND\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    //
+    //  MASTERMIND II
+    //  STEVE NORTH
+    //  CREATIVE COMPUTING
+    //  PO BOX 789-M MORRISTOWN NEW JERSEY 07960
+    //
+    //
+    while (1) {
+        print("NUMBER OF COLORS");
+        c9 = parseInt(await input());
+        if (c9 <= 8)
+            break;
+        print("NO MORE THAN 8, PLEASE!\n");
+    }
+    print("NUMBER OF POSITIONS");
+    p9 = parseInt(await input());
+    print("NUMBER OF ROUNDS");
+    r9 = parseInt(await input());
+    p = Math.pow(c9, p9);
+    print("TOTAL POSSIBILITIES = " + p + "\n");
+    h = 0;
+    c = 0;
+    qa = [];
+    sa = [];
+    ss = [];
+    as = [];
+    gs = [];
+    ia = [];
+    hs = [];
+    ls = "BWRGOYPT";
+    print("\n");
+    print("\n");
+    print("COLOR    LETTER\n");
+    print("=====    ======\n");
+    for (x = 1; x <= c9; x++) {
+        str = color[x - 1];
+        while (str.length < 13)
+            str += " ";
+        str += ls.substr(x - 1, 1);
+        print(str + "\n");
+    }
+    print("\n");
+    for (r = 1; r <= r9; r++) {
+        print("\n");
+        print("ROUND NUMBER " + r + " ----\n");
+        print("\n");
+        print("GUESS MY COMBINATION.\n");
+        print("\n");
+        // Get a combination
+        a = Math.floor(p * Math.random() + 1);
+        initialize_qa();
+        for (x = 1; x <= a; x++) {
+            increment_qa();
+        }
+        for (m = 1; m <= 10; m++) {
+            while (1) {
+                print("MOVE # " + m + " GUESS ");
+                str = await input();
+                if (str == "BOARD") {
+                    board_printout();
+                } else if (str == "QUIT") {
+                    quit();
+                    return;
+                } else if (str.length != p9) {
+                    print("BAD NUMBER OF POSITIONS.\n");
+                } else {
+                    // Unpack str into gs(1-p9)
+                    for (x = 1; x <= p9; x++) {
+                        y = ls.indexOf(str.substr(x - 1, 1));
+                        if (y < 0) {
+                            print("'" + str.substr(x - 1, 1) + "' IS UNRECOGNIZED.\n");
+                            break;
+                        }
+                        gs[x] = str.substr(x - 1, 1);
+                    }
+                    if (x > p9)
+                        break;
+                }
+            }
+            // Now we convert qa(1-p9) into as(1-p9) [ACTUAL GUESS]
+            convert_qa();
+            // And get number of blacks and white
+            get_number();
+            if (b == p9) {
+                print("YOU GUESSED IT IN " + m + " MOVES!\n");
+                break;
+            }
+            // Save all this stuff for board printout later
+            ss[m] = str;
+            sa[m] = [];
+            sa[m][1] = b;
+            sa[m][2] = w;
+        }
+        if (m > 10) {
+            print("YOU RAN OUT OF MOVES!  THAT'S ALL YOU GET!\n");
+        }
+        h += m;
+        show_score();
+        
+        //
+        // Now computer guesses
+        //
+        for (x = 1; x <= p; x++)
+            ia[x] = 1;
+        print("NOW I GUESS.  THINK OF A COMBINATION.\n");
+        print("HIT RETURN WHEN READY:");
+        str = await input();
+        for (m = 1; m <= 10; m++) {
+            initialize_qa();
+            // Find a guess
+            g = Math.floor(p * Math.random() + 1);
+            if (ia[g] != 1) {
+                for (x = g; x <= p; x++) {
+                    if (ia[x] == 1)
+                        break;
+                }
+                if (x > p) {
+                    for (x = 1; x <= g; x++) {
+                        if (ia[x] == 1)
+                            break;
+                    }
+                    if (x > g) {
+                        print("YOU HAVE GIVEN ME INCONSISTENT INFORMATION.\n");
+                        print("TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL.\n");
+                        for (x = 1; x <= p; x++)
+                            ia[x] = 1;
+                        print("NOW I GUESS.  THINK OF A COMBINATION.\n");
+                        print("HIT RETURN WHEN READY:");
+                        str = await input();
+                        m = 0;
+                        continue;
+                    }
+                }
+                g = x;
+            }
+            // Now we convert guess #g into gs
+            for (x = 1; x <= g; x++) {
+                increment_qa();
+            }
+            convert_qa_hs();
+            print("MY GUESS IS: ");
+            for (x = 1; x <= p9; x++) {
+                print(hs[x]);
+            }
+            print("  BLACKS, WHITES ");
+            str = await input();
+            b1 = parseInt(str);
+            w1 = parseInt(str.substr(str.indexOf(",") + 1));
+            if (b1 == p9) {
+                print("I GOT IT IN " + m + " MOVES!\n");
+                break;
+            }
+            initialize_qa();
+            for (x = 1; x <= p; x++) {
+                increment_qa();
+                if (ia[x] != 0) {
+                    copy_hs();
+                    convert_qa();
+                    get_number();
+                    if (b1 != b || w1 != w)
+                        ia[x] = 0;
+                }
+            }
+        }
+        if (m > 10) {
+            print("I USED UP ALL MY MOVES!\n");
+            print("I GUESS MY CPU I JUST HAVING AN OFF DAY.\n");
+        }
+        c += m;
+        show_score();
+    }
+    print("GAME OVER\n");
+    print("FINAL SCORE:\n");
+    show_points();
+}
+
+main();

From d36adb2550cca901c90d33d81a38c329881e2c81 Mon Sep 17 00:00:00 2001
From: rbamforth <79797573+rbamforth@users.noreply.github.com>
Date: Wed, 24 Mar 2021 12:53:26 +0000
Subject: [PATCH 329/749] Removed Tester project which wasn't working properly.
 Added shuffling the deck.

---
 94 War/csharp/War/War.sln                    |  6 --
 94 War/csharp/War/War/Cards.cs               | 15 +++-
 94 War/csharp/War/WarTester/Tests.cs         | 90 --------------------
 94 War/csharp/War/WarTester/WarTester.csproj | 20 -----
 4 files changed, 14 insertions(+), 117 deletions(-)
 delete mode 100644 94 War/csharp/War/WarTester/Tests.cs
 delete mode 100644 94 War/csharp/War/WarTester/WarTester.csproj

diff --git a/94 War/csharp/War/War.sln b/94 War/csharp/War/War.sln
index a03a3a64..fcb2d2c2 100644
--- a/94 War/csharp/War/War.sln	
+++ b/94 War/csharp/War/War.sln	
@@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.31112.23
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "War", "War\War.csproj", "{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WarTester", "WarTester\WarTester.csproj", "{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -17,10 +15,6 @@ Global
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.Build.0 = Release|Any CPU
-		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{ACB0D6AD-9675-4E72-BB97-BBB2241CB494}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/94 War/csharp/War/War/Cards.cs b/94 War/csharp/War/War/Cards.cs
index 1efdc715..7c31c3b2 100644
--- a/94 War/csharp/War/War/Cards.cs	
+++ b/94 War/csharp/War/War/Cards.cs	
@@ -111,7 +111,8 @@ namespace War
 
     public class Deck
     {
-        private const int deckSize = 52;
+        public const int deckSize = 52;
+
         private Card[] theDeck = new Card[deckSize];
 
         public Deck()
@@ -127,9 +128,21 @@ namespace War
             }
         }
 
+        public Card GetCard(int i) => theDeck[i];
+
         public void Shuffle()
         {
+            // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+            for (int i = deckSize - 1; i >= 1; i--)
+            {
+                var rand = new Random();
+                int j = rand.Next(0, i);
 
+                // Swap the cards at i and j
+                Card temp = theDeck[j];
+                theDeck[j] = theDeck[i];
+                theDeck[i] = temp;
+            }
         }
     }
 }
diff --git a/94 War/csharp/War/WarTester/Tests.cs b/94 War/csharp/War/WarTester/Tests.cs
deleted file mode 100644
index 1e811c9e..00000000
--- a/94 War/csharp/War/WarTester/Tests.cs	
+++ /dev/null
@@ -1,90 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using War;
-
-
-
-namespace WarTester
-{
-    [TestClass]
-    public class CardTest
-    {
-        Card c1 = new Card(Suit.clubs, Rank.two);
-        Card c2 = new Card(Suit.clubs, Rank.ten);
-        Card c3 = new Card(Suit.diamonds, Rank.ten);
-        Card c4 = new Card(Suit.diamonds, Rank.ten);
-
-        [TestMethod]
-        public void LessThan_IsValid()
-        {
-            Assert.IsTrue(c1 < c2, "c1 < c2");  // Same suit, different rank.
-            Assert.IsFalse(c2 < c1, "c2 < c1"); // Same suit, different rank.
-
-            Assert.IsFalse(c3 < c4, "c3 < c4"); // Same suit, same rank.
-
-            Assert.IsTrue(c1 < c3, "c1 < c3");  // Different suit, different rank.
-            Assert.IsFalse(c3 < c1, "c3 < c1"); // Different suit, different rank.
-
-            Assert.IsFalse(c2 < c4, "c2 < c4"); // Different suit, same rank.
-            Assert.IsFalse(c4 < c2, "c4 < c2"); // Different suit, same rank.
-        }
-
-        [TestMethod]
-        public void GreaterThan_IsValid()
-        {
-            Assert.IsFalse(c1 > c2, "c1 > c2"); // Same suit, different rank.
-            Assert.IsTrue(c2 > c1, "c2 > c1");  // Same suit, different rank.
-
-            Assert.IsFalse(c3 > c4, "c3 > c4"); // Same suit, same rank.
-
-            Assert.IsFalse(c1 > c3, "c1 > c3"); // Different suit, different rank.
-            Assert.IsTrue(c3 > c1, "c3 > c1");  // Different suit, different rank.
-
-            Assert.IsFalse(c2 > c4, "c2 > c4"); // Different suit, same rank.
-            Assert.IsFalse(c4 > c2, "c4 > c2"); // Different suit, same rank.
-        }
-
-        [TestMethod]
-        public void LessThanEquals_IsValid()
-        {
-            Assert.IsTrue(c1 <= c2, "c1 <= c2");  // Same suit, different rank.
-            Assert.IsFalse(c2 <= c1, "c2 <= c1"); // Same suit, different rank.
-
-            Assert.IsTrue(c3 <= c4, "c3 <= c4");  // Same suit, same rank.
-
-            Assert.IsTrue(c1 <= c3, "c1 <= c3");  // Different suit, different rank.
-            Assert.IsFalse(c3 <= c1, "c3 <= c1"); // Different suit, different rank.
-
-            Assert.IsTrue(c2 <= c4, "c2 <= c4");  // Different suit, same rank.
-            Assert.IsTrue(c4 <= c2, "c4 <= c2");  // Different suit, same rank.
-        }
-
-        [TestMethod]
-        public void GreaterThanEquals_IsValid()
-        {
-            Assert.IsFalse(c1 >= c2, "c1 >= c2"); // Same suit, different rank.
-            Assert.IsTrue(c2 >= c1, "c2 >= c1");  // Same suit, different rank.
-
-            Assert.IsTrue(c3 >= c4, "c3 >= c4");  // Same suit, same rank.
-
-            Assert.IsFalse(c1 >= c3, "c1 >= c3"); // Different suit, different rank.
-            Assert.IsTrue(c3 >= c1, "c3 >= c1");  // Different suit, different rank.
-
-            Assert.IsTrue(c2 >= c4, "c2 >= c4");  // Different suit, same rank.
-            Assert.IsTrue(c4 >= c2, "c4 >= c2");  // Different suit, same rank.
-        }
-
-        [TestMethod]
-        public void ToString_IsValid()
-        {
-            string s1 = c1.ToString();
-            string s2 = c3.ToString();
-            string s3 = new Card(Suit.hearts, Rank.queen).ToString();
-            string s4 = new Card(Suit.spades, Rank.ace).ToString();
-
-            Assert.IsTrue(s1 == "C-2", "s1 invalid");
-            Assert.IsTrue(s2 == "D-10", "s2 invalid");
-            Assert.IsTrue(s3 == "H-Q", "s3 invalid");
-            Assert.IsTrue(s4 == "S-A", "s4 invalid");
-        }
-    }
-}
diff --git a/94 War/csharp/War/WarTester/WarTester.csproj b/94 War/csharp/War/WarTester/WarTester.csproj
deleted file mode 100644
index 84aa459a..00000000
--- a/94 War/csharp/War/WarTester/WarTester.csproj	
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-  
-    netcoreapp3.1
-
-    false
-  
-
-  
-    
-    
-    
-    
-  
-
-  
-    
-  
-
-

From e9987a3269f8b98aee76002ea80356251109eec5 Mon Sep 17 00:00:00 2001
From: rbamforth <79797573+rbamforth@users.noreply.github.com>
Date: Thu, 25 Mar 2021 23:38:35 +0000
Subject: [PATCH 330/749] Reinstated Tester project. The Visual Studio test
 runner still doesn't display any test results but this is common to all
 solutions. It's a VS issue, not an issue with this Program.

First cut at a working program.
---
 94 War/csharp/War/War.sln        |  6 +++
 94 War/csharp/War/War/Program.cs | 90 +++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/94 War/csharp/War/War.sln b/94 War/csharp/War/War.sln
index fcb2d2c2..af1e88a5 100644
--- a/94 War/csharp/War/War.sln	
+++ b/94 War/csharp/War/War.sln	
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.31112.23
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "War", "War\War.csproj", "{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WarTester", "WarTester\WarTester.csproj", "{B539F618-EE83-486C-9A6D-404E998BED2D}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C13BE0FA-D8F7-4CA7-A95D-DA03A9DE8950}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B539F618-EE83-486C-9A6D-404E998BED2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B539F618-EE83-486C-9A6D-404E998BED2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B539F618-EE83-486C-9A6D-404E998BED2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B539F618-EE83-486C-9A6D-404E998BED2D}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/94 War/csharp/War/War/Program.cs b/94 War/csharp/War/War/Program.cs
index cf4b0edf..68b602f8 100644
--- a/94 War/csharp/War/War/Program.cs	
+++ b/94 War/csharp/War/War/Program.cs	
@@ -2,11 +2,99 @@
 
 namespace War
 {
+	public class Intro
+	{
+		public void WriteIntro()
+		{
+			Console.WriteLine("                                 WAR");
+			Console.WriteLine("               CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+			Console.WriteLine();
+			Console.WriteLine();
+			Console.WriteLine();
+	
+			Console.WriteLine("THIS IS THE CARD GAME OF WAR.  EACH CARD IS GIVEN BY SUIT-#");
+			Console.WriteLine("AS S-7 FOR SPADE 7.  ");
+	
+			if (AskQuestion("DO YOU WANT DIRECTIONS? "))
+			{
+				Console.WriteLine("THE COMPUTER GIVES YOU AND IT A 'CARD'.  THE HIGHER CARD");
+				Console.WriteLine("(NUMERICALLY) WINS.  THE GAME ENDS WHEN YOU CHOOSE NOT TO");
+				Console.WriteLine("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.");
+			}
+	
+			Console.WriteLine();
+			Console.WriteLine();
+		}
+	
+		public bool AskQuestion(string question)
+		{
+			while (true)
+			{
+				Console.Write(question);
+				string result = Console.ReadLine();
+	
+				if (result.ToLower()[0] == 'y')
+				{
+					return true;
+				}
+				else /*if (result.ToLower() == "no")*/
+				{
+					return false;
+				}
+	
+				Console.WriteLine("YES OR NO, PLEASE.");
+			}
+		}
+    }
+
     class Program
     {
         static void Main(string[] args)
         {
-            Console.WriteLine("Hello World!");
+            var intro = new Intro();
+			intro.WriteIntro();
+
+			var deck = new Deck();
+			deck.Shuffle();
+
+			int yourScore = 0;
+            int computersScore = 0;
+			bool usedAllCards = true;
+
+            for (int i = 0; i < Deck.deckSize; i += 2)
+            {
+				var yourCard = deck.GetCard(i);
+                var computersCard = deck.GetCard(i + 1);
+
+                Console.WriteLine($"YOU: {yourCard}     COMPUTER: {computersCard}");
+				if (yourCard < computersCard)
+                {
+					computersScore++;
+                    Console.WriteLine($"THE COMPUTER WINS!!! YOU HAVE {yourScore} AND THE COMPUTER HAS {computersScore}");
+                }
+                else if (yourCard > computersCard)
+                {
+					yourScore++;
+                    Console.WriteLine($"YOU WIN. YOU HAVE {yourScore} AND THE COMPUTER HAS {computersScore}");
+                }
+				else
+                {
+                    Console.WriteLine("TIE.  NO SCORE CHANGE");
+                }
+
+				if (!intro.AskQuestion("DO YOU WANT TO CONTINUE? "))
+                {
+					usedAllCards = false;
+					break;
+                }
+            }
+
+			if (usedAllCards)
+            {
+				Console.WriteLine("WE HAVE RUN OUT OF CARDS.");
+            }
+			Console.WriteLine($"FINAL SCORE:  YOU: {yourScore}  THE COMPUTER: {computersScore}");
+			Console.WriteLine("THANKS FOR PLAYING.  IT WAS FUN.");
         }
     }
 }

From a2cffe63f1f3216bb451ff1d971ecb25b66c0f48 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Thu, 25 Mar 2021 17:51:26 -0600
Subject: [PATCH 331/749] Ported FOOTBALL to Javascript

---
 37 Football/javascript/football.html |   9 +
 37 Football/javascript/football.js   | 504 +++++++++++++++++++++++++++
 2 files changed, 513 insertions(+)
 create mode 100644 37 Football/javascript/football.html
 create mode 100644 37 Football/javascript/football.js

diff --git a/37 Football/javascript/football.html b/37 Football/javascript/football.html
new file mode 100644
index 00000000..10e1acc1
--- /dev/null
+++ b/37 Football/javascript/football.html	
@@ -0,0 +1,9 @@
+
+
+FOOTBALL
+
+
+

+
+
+
diff --git a/37 Football/javascript/football.js b/37 Football/javascript/football.js
new file mode 100644
index 00000000..ca990f92
--- /dev/null
+++ b/37 Football/javascript/football.js	
@@ -0,0 +1,504 @@
+// FOOTBALL
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var player_data = [17,8,4,14,19,3,10,1,7,11,15,9,5,20,13,18,16,2,12,6,
+                   20,2,17,5,8,18,12,11,1,4,19,14,10,7,9,15,6,13,16,3];
+var aa = [];
+var ba = [];
+var ca = [];
+var ha = [];
+var ta = [];
+var wa = [];
+var xa = [];
+var ya = [];
+var za = [];
+var ms = [];
+var da = [];
+var ps = [, "PITCHOUT","TRIPLE REVERSE","DRAW","QB SNEAK","END AROUND",
+          "DOUBLE REVERSE","LEFT SWEEP","RIGHT SWEEP","OFF TACKLE",
+          "WISHBONE OPTION","FLARE PASS","SCREEN PASS",
+          "ROLL OUT OPTION","RIGHT CURL","LEFT CURL","WISHBONE OPTION",
+          "SIDELINE PASS","HALF-BACK OPTION","RAZZLE-DAZZLE","BOMB!!!!"];
+var p;
+var t;
+
+function field_headers()
+{
+    print("TEAM 1 [0   10   20   30   40   50   60   70   80   90");
+    print("   100] TEAM 2\n");
+    print("\n");
+}
+
+function separator()
+{
+    str = "";
+    for (x = 1; x <= 72; x++)
+        str += "+";
+    print(str + "\n");
+}
+
+function show_ball()
+{
+    print(tab(da[t] + 5 + p / 2) + ms[t] + "\n");
+    field_headers();
+}
+
+function show_scores()
+{
+    print("\n");
+    print("TEAM 1 SCORE IS " + ha[1] + "\n");
+    print("TEAM 2 SCORE IS " + ha[2] + "\n");
+    print("\n");
+    if (ha[t] >= e) {
+        print("TEAM " + t + " WINS*******************");
+        return true;
+    }
+    return false;
+}
+
+function loss_posession() {
+    print("\n");
+    print("** LOSS OF POSSESSION FROM TEAM " + t + " TO TEAM " + ta[t] + "\n");
+    print("\n");
+    separator();
+    print("\n");
+    t = ta[t];
+}
+
+function touchdown() {
+    print("\n");
+    print("TOUCHDOWN BY TEAM " + t + " *********************YEA TEAM\n");
+    q = 7;
+    g = Math.random();
+    if (g <= 0.1) {
+        q = 6;
+        print("EXTRA POINT NO GOOD\n");
+    } else {
+        print("EXTRA POINT GOOD\n");
+    }
+    ha[t] = ha[t] + q;
+}
+
+// Main program
+async function main()
+{
+    print(tab(32) + "FOOTBALL\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("PRESENTING N.F.U. FOOTBALL (NO FORTRAN USED)\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("DO YOU WANT INSTRUCTIONS");
+        str = await input();
+        if (str == "YES" || str == "NO")
+            break;
+    }
+    if (str == "YES") {
+        print("THIS IS A FOOTBALL GAME FOR TWO TEAMS IN WHICH PLAYERS MUST\n");
+        print("PREPARE A TAPE WITH A DATA STATEMENT (1770 FOR TEAM 1,\n");
+        print( "1780 FOR TEAM 2) IN WHICH EACH TEAM SCRAMBLES NOS. 1-20\n");
+        print("THESE NUMBERS ARE THEN ASSIGNED TO TWENTY GIVEN PLAYS.\n");
+        print("A LIST OF NOS. AND THEIR PLAYS IS PROVIDED WITH\n");
+        print("BOTH TEAMS HAVING THE SAME PLAYS. THE MORE SIMILAR THE\n");
+        print("PLAYS THE LESS YARDAGE GAINED.  SCORES ARE GIVEN\n");
+        print("WHENEVER SCORES ARE MADE. SCORES MAY ALSO BE OBTAINED\n");
+        print("BY INPUTTING 99,99 FOR PLAY NOS. TO PUNT OR ATTEMPT A\n");
+        print("FIELD GOAL, INPUT 77,77 FOR PLAY NUMBERS. QUESTIONS WILL BE\n");
+        print("ASKED THEN. ON 4TH DOWN, YOU WILL ALSO BE ASKED WHETHER\n");
+        print("YOU WANT TO PUNT OR ATTEMPT A FIELD GOAL. IF THE ANSWER TO\n");
+        print("BOTH QUESTIONS IS NO IT WILL BE ASSUMED YOU WANT TO\n");
+        print("TRY AND GAIN YARDAGE. ANSWER ALL QUESTIONS YES OR NO.\n");
+        print("THE GAME IS PLAYED UNTIL PLAYERS TERMINATE (CONTROL-C).\n");
+        print("PLEASE PREPARE A TAPE AND RUN.\n");
+    }
+    print("\n");
+    print("PLEASE INPUT SCORE LIMIT ON GAME");
+    e = parseInt(await input());
+    for (i = 1; i <= 40; i++) {
+        if (i <= 20) {
+            aa[player_data[i - 1]] = i;
+        } else {
+            ba[player_data[i - 1]] = i - 20;
+        }
+        ca[i] = player_data[i - 1];
+    }
+    l = 0;
+    t = 1;
+    do {
+        print("TEAM " + t + " PLAY CHART\n");
+        print("NO.      PLAY\n");
+        for (i = 1; i <= 20; i++) {
+            str = "" + ca[i + l];
+            while (str.length < 6)
+                str += " ";
+            str += ps[i];
+            print(str + "\n");
+        }
+        l += 20;
+        t = 2;
+        print("\n");
+        print("TEAR OFF HERE----------------------------------------------\n");
+        for (x = 1; x <= 11; x++)
+            print("\n");
+    } while (l == 20) ;
+    da[1] = 0;
+    da[2] = 3;
+    ms[1] = "--->";
+    ms[2] = "<---";
+    ha[1] = 0;
+    ha[2] = 0;
+    ta[1] = 2;
+    ta[2] = 1;
+    wa[1] = -1;
+    wa[2] = 1;
+    xa[1] = 100;
+    xa[2] = 0;
+    ya[1] = 1;
+    ya[2] = -1;
+    za[1] = 0;
+    za[2] = 100;
+    p = 0;
+    field_headers();
+    print("TEAM 1 DEFEND 0 YD GOAL -- TEAM 2 DEFENDS 100 YD GOAL.\n");
+    t = Math.floor(2 * Math.random() + 1);
+    print("\n");
+    print("THE COIN IS FLIPPED\n");
+    routine = 1;
+    while (1) {
+        if (routine <= 1) {
+            p = xa[t] - ya[t] * 40;
+            separator();
+            print("\n");
+            print("TEAM " + t + " RECEIVES KICK-OFF\n");
+            k = Math.floor(26 * Math.random() + 40);
+        }
+        if (routine <= 2) {
+            p = p - ya[t] * k;
+        }
+        if (routine <= 3) {
+            if (wa[t] * p >= za[t] + 10) {
+                print("\n");
+                print("BALL WENT OUT OF ENDZONE --AUTOMATIC TOUCHBACK--\n");
+                p = za[t] - wa[t] * 20;
+                if (routine <= 4)
+                    routine = 5;
+            } else {
+                print("BALL WENT " + k + " YARDS.  NOW ON " + p + "\n");
+                show_ball();
+            }
+        }
+        if (routine <= 4) {
+            while (1) {
+                print("TEAM " + t + " DO YOU WANT TO RUNBACK");
+                str = await input();
+                if (str == "YES" || str == "NO")
+                    break;
+            }
+            if (str == "YES") {
+                k = Math.floor(9 * Math.random() + 1);
+                r = Math.floor(((xa[t] - ya[t] * p + 25) * Math.random() - 15) / k);
+                p = p - wa[t] * r;
+                print("\n");
+                print("RUNBACK TEAM " + t + " " + r + " YARDS\n");
+                g = Math.random();
+                if (g < 0.25) {
+                    loss_posession();
+                    routine = 4;
+                    continue;
+                } else if (ya[t] * p >= xa[t]) {
+                    touchdown();
+                    if (show_scores())
+                        return;
+                    t = ta[t];
+                    routine = 1;
+                    continue;
+                } else if (wa[t] * p >= za[t]) {
+                    print("\n");
+                    print("SAFETY AGAINST TEAM " + t + " **********************OH-OH\n");
+                    ha[ta[t]] = ha[ta[t]] + 2;
+                    if (show_scores())
+                        return;
+                    print("TEAM " + t + " DO YOU WANT TO PUNT INSTEAD OF A KICKOFF");
+                    str = await input();
+                    p = za[t] - wa[t] * 20;
+                    if (str == "YES") {
+                        print("\n");
+                        print("TEAM " + t + " WILL PUNT\n");
+                        g = Math.random();
+                        if (g < 0.25) {
+                            loss_posession();
+                            routine = 4;
+                            continue;
+                        }
+                        print("\n");
+                        separator();
+                        k = Math.floor(25 * Math.random() + 35);
+                        t = ta[t];
+                        routine = 2;
+                        continue;
+                    }
+                    touchdown();
+                    if (show_scores())
+                        return;
+                    t = ta[t];
+                    routine = 1;
+                    continue;
+                } else {
+                    routine = 5;
+                    continue;
+                }
+            } else if (str == "NO") {
+                if (wa[t] * p >= za[t])
+                    p = za[t] - wa[t] * 20;
+            }
+        }
+        if (routine <= 5) {
+            d = 1;
+            s = p;
+        }
+        if (routine <= 6) {
+            str = "";
+            for (i = 1; i <= 72; i++)
+                str += "=";
+            print(str + "\n");
+            print("TEAM " + t + " DOWN " + d + " ON " + p + "\n");
+            if (d == 1) {
+                if (ya[t] * (p + ya[t] * 10) >= xa[t])
+                    c = 8;
+                else
+                    c = 4;
+            }
+            if (c != 8) {
+                print(tab(27) + (10 - (ya[t] * p - ya[t] * s)) + " YARDS TO 1ST DOWN\n");
+            } else {
+                print(tab(27) + (xa[t] - ya[t] * p) + " YARDS\n");
+            }
+            show_ball();
+            if (d == 4)
+                routine = 8;
+        }
+        if (routine <= 7) {
+            u = Math.floor(3 * Math.random() - 1);
+            while (1) {
+                print("INPUT OFFENSIVE PLAY, DEFENSIVE PLAY");
+                str = await input();
+                if (t == 1) {
+                    p1 = parseInt(str);
+                    p2 = parseInt(str.substr(str.indexOf(",") + 1));
+                } else {
+                    p2 = parseInt(str);
+                    p1 = parseInt(str.substr(str.indexOf(",") + 1));
+                }
+                if (p1 == 99) {
+                    if (show_scores())
+                        return;
+                    if (p1 == 99)
+                        continue;
+                }
+                if (p1 < 1 || p1 > 20 || p2 < 1 || p2 > 20) {
+                    print("ILLEGAL PLAY NUMBER, CHECK AND\n");
+                    continue;
+                }
+                break;
+            }
+        }
+        if (d == 4 || p1 == 77) {
+            while (1) {
+                print("DOES TEAM " + t + " WANT TO PUNT");
+                str = await input();
+                if (str == "YES" || str == "NO")
+                    break;
+            }
+            if (str == "YES") {
+                print("\n");
+                print("TEAM " + t + " WILL PUNT\n");
+                g = Math.random();
+                if (g < 0.25) {
+                    loss_posession();
+                    routine = 4;
+                    continue;
+                }
+                print("\n");
+                separator();
+                k = Math.floor(25 * Math.random() + 35);
+                t = ta[t];
+                routine = 2;
+                continue;
+            }
+            while (1) {
+                print("DOES TEAM " + t + " WANT TO ATTEMPT A FIELD GOAL");
+                str = await input();
+                if (str == "YES" || str == "NO")
+                    break;
+            }
+            if (str == "YES") {
+                print("\n");
+                print("TEAM " + t + " WILL ATTEMPT A FIELD GOAL\n");
+                g = Math.random();
+                if (g < 0.025) {
+                    loss_posession();
+                    routine = 4;
+                    continue;
+                } else {
+                    f = Math.floor(35 * Math.random() + 20);
+                    print("\n");
+                    print("KICK IS " + f + " YARDS LONG\n");
+                    p = p - wa[t] * f;
+                    g = Math.random();
+                    if (g < 0.35) {
+                        print("BALL WENT WIDE\n");
+                    } else if (ya[t] * p >= xa[t]) {
+                        print("FIELD GOLD GOOD FOR TEAM " + t + " *********************YEA");
+                        q = 3;
+                        ha[t] = ha[t] + q;
+                        if (show_scores())
+                            return;
+                        t = ta[t];
+                        routine = 1;
+                        continue;
+                    }
+                    print("FIELD GOAL UNSUCCESFUL TEAM " + t + "-----------------TOO BAD\n");
+                    print("\n");
+                    separator();
+                    if (ya[t] * p < xa[t] + 10) {
+                        print("\n");
+                        print("BALL NOW ON " + p + "\n");
+                        t = ta[t];
+                        show_ball();
+                        routine = 4;
+                        continue;
+                    } else {
+                        t = ta[t];
+                        routine = 3;
+                        continue;
+                    }
+                }
+            } else {
+                routine = 7;
+                continue;
+            }
+        }
+        y = Math.floor(Math.abs(aa[p1] - ba[p2]) / 19 * ((xa[t] - ya[t] * p + 25) * Math.random() - 15));
+        print("\n");
+        if (t == 1 && aa[p1] < 11 || t == 2 && ba[p2] < 11) {
+            print("THE BALL WAS RUN\n");
+        } else if (u == 0) {
+            print("PASS INCOMPLETE TEAM " + t + "\n");
+            y = 0;
+        } else {
+            g = Math.random();
+            if (g <= 0.025 && y > 2) {
+                print("PASS COMPLETED\n");
+            } else {
+                print("QUARTERBACK SCRAMBLED\n");
+            }
+        }
+        p = p - wa[t] * y;
+        print("\n");
+        print("NET YARDS GAINED ON DOWN " + d + " ARE " + y + "\n");
+        
+        g = Math.random();
+        if (g <= 0.025) {
+            loss_posession();
+            routine = 4;
+            continue;
+        } else if (ya[t] * p >= xa[t]) {
+            touchdown();
+            if (show_scores())
+                return;
+            t = ta[t];
+            routine = 1;
+            continue;
+        } else if (wa[t] * p >= za[t]) {
+            print("\n");
+            print("SAFETY AGAINST TEAM " + t + " **********************OH-OH\n");
+            ha[ta[t]] = ha[ta[t]] + 2;
+            if (show_scores())
+                return;
+            print("TEAM " + t + " DO YOU WANT TO PUNT INSTEAD OF A KICKOFF");
+            str = await input();
+            p = za[t] - wa[t] * 20;
+            if (str == "YES") {
+                print("\n");
+                print("TEAM " + t + " WILL PUNT\n");
+                g = Math.random();
+                if (g < 0.25) {
+                    loss_posession();
+                    routine = 4;
+                    continue;
+                }
+                print("\n");
+                separator();
+                k = Math.floor(25 * Math.random() + 35);
+                t = ta[t];
+                routine = 2;
+                continue;
+            }
+            touchdown();
+            if (show_scores())
+                return;
+            t = ta[t];
+            routine = 1;
+        } else if (ya[t] * p - ya[t] * s >= 10) {
+            routine = 5;
+        } else {
+            d++;
+            if (d != 5) {
+                routine = 6;
+            } else {
+                print("\n");
+                print("CONVERSION UNSUCCESSFUL TEAM " + t + "\n");
+                t = ta[t];
+                print("\n");
+                separator();
+                routine = 5;
+            }
+        }
+    }
+}
+
+main();

From 0d35b103b06a5c650582c615a2fd142d1011badc Mon Sep 17 00:00:00 2001
From: rbamforth <79797573+rbamforth@users.noreply.github.com>
Date: Fri, 26 Mar 2021 15:39:15 +0000
Subject: [PATCH 332/749] Added Tester files.

---
 94 War/csharp/War/WarTester/Tests.cs         | 126 +++++++++++++++++++
 94 War/csharp/War/WarTester/WarTester.csproj |  29 +++++
 2 files changed, 155 insertions(+)
 create mode 100644 94 War/csharp/War/WarTester/Tests.cs
 create mode 100644 94 War/csharp/War/WarTester/WarTester.csproj

diff --git a/94 War/csharp/War/WarTester/Tests.cs b/94 War/csharp/War/WarTester/Tests.cs
new file mode 100644
index 00000000..313d2a1e
--- /dev/null
+++ b/94 War/csharp/War/WarTester/Tests.cs	
@@ -0,0 +1,126 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Text;
+using War;
+
+
+
+namespace WarTester
+{
+    [TestClass]
+    public class CardTest
+    {
+        private Card c1 = new Card(Suit.clubs, Rank.two);
+        private Card c2 = new Card(Suit.clubs, Rank.ten);
+        private Card c3 = new Card(Suit.diamonds, Rank.ten);
+        private Card c4 = new Card(Suit.diamonds, Rank.ten);
+
+        [TestMethod]
+        public void LessThanIsValid()
+        {
+            Assert.IsTrue(c1 < c2, "c1 < c2");  // Same suit, different rank.
+            Assert.IsFalse(c2 < c1, "c2 < c1"); // Same suit, different rank.
+
+            Assert.IsFalse(c3 < c4, "c3 < c4"); // Same suit, same rank.
+
+            Assert.IsTrue(c1 < c3, "c1 < c3");  // Different suit, different rank.
+            Assert.IsFalse(c3 < c1, "c3 < c1"); // Different suit, different rank.
+
+            Assert.IsFalse(c2 < c4, "c2 < c4"); // Different suit, same rank.
+            Assert.IsFalse(c4 < c2, "c4 < c2"); // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void GreaterThanIsValid()
+        {
+            Assert.IsFalse(c1 > c2, "c1 > c2"); // Same suit, different rank.
+            Assert.IsTrue(c2 > c1, "c2 > c1");  // Same suit, different rank.
+
+            Assert.IsFalse(c3 > c4, "c3 > c4"); // Same suit, same rank.
+
+            Assert.IsFalse(c1 > c3, "c1 > c3"); // Different suit, different rank.
+            Assert.IsTrue(c3 > c1, "c3 > c1");  // Different suit, different rank.
+
+            Assert.IsFalse(c2 > c4, "c2 > c4"); // Different suit, same rank.
+            Assert.IsFalse(c4 > c2, "c4 > c2"); // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void LessThanEqualsIsValid()
+        {
+            Assert.IsTrue(c1 <= c2, "c1 <= c2");  // Same suit, different rank.
+            Assert.IsFalse(c2 <= c1, "c2 <= c1"); // Same suit, different rank.
+
+            Assert.IsTrue(c3 <= c4, "c3 <= c4");  // Same suit, same rank.
+
+            Assert.IsTrue(c1 <= c3, "c1 <= c3");  // Different suit, different rank.
+            Assert.IsFalse(c3 <= c1, "c3 <= c1"); // Different suit, different rank.
+
+            Assert.IsTrue(c2 <= c4, "c2 <= c4");  // Different suit, same rank.
+            Assert.IsTrue(c4 <= c2, "c4 <= c2");  // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void GreaterThanEqualsIsValid()
+        {
+            Assert.IsFalse(c1 >= c2, "c1 >= c2"); // Same suit, different rank.
+            Assert.IsTrue(c2 >= c1, "c2 >= c1");  // Same suit, different rank.
+
+            Assert.IsTrue(c3 >= c4, "c3 >= c4");  // Same suit, same rank.
+
+            Assert.IsFalse(c1 >= c3, "c1 >= c3"); // Different suit, different rank.
+            Assert.IsTrue(c3 >= c1, "c3 >= c1");  // Different suit, different rank.
+
+            Assert.IsTrue(c2 >= c4, "c2 >= c4");  // Different suit, same rank.
+            Assert.IsTrue(c4 >= c2, "c4 >= c2");  // Different suit, same rank.
+        }
+
+        [TestMethod]
+        public void ToStringIsValid()
+        {
+            string s1 = c1.ToString();
+            string s2 = c3.ToString();
+            string s3 = new Card(Suit.hearts, Rank.queen).ToString();
+            string s4 = new Card(Suit.spades, Rank.ace).ToString();
+
+            Assert.IsTrue(s1 == "C-2", "s1 invalid");
+            Assert.IsTrue(s2 == "D-10", "s2 invalid");
+            Assert.IsTrue(s3 == "H-Q", "s3 invalid");
+            Assert.IsTrue(s4 == "S-A", "s4 invalid");
+        }
+    }
+
+    [TestClass]
+    public class DeckTest
+    {
+        private string ConcatenateDeck(Deck d)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < Deck.deckSize; i++)
+            {
+                sb.Append(d.GetCard(i));
+            }
+
+            return sb.ToString();
+        }
+
+        [TestMethod]
+        public void InitialDeckContainsCardsInOrder()
+        {
+            Deck d1 = new Deck();
+            string allTheCards = ConcatenateDeck(d1);
+
+            Assert.IsTrue(allTheCards == "C-2C-3C-4C-5C-6C-7C-8C-9C-10C-JC-QC-KC-AD-2D-3D-4D-5D-6D-7D-8D-9D-10D-JD-QD-KD-AH-2H-3H-4H-5H-6H-7H-8H-9H-10H-JH-QH-KH-AS-2S-3S-4S-5S-6S-7S-8S-9S-10S-JS-QS-KS-A");
+        }
+
+        [TestMethod]
+        public void ShufflingChangesDeck()
+        {
+            Deck d1 = new Deck();
+            d1.Shuffle();
+            string allTheCards = ConcatenateDeck(d1);
+
+            Assert.IsTrue(allTheCards != "C-2C-3C-4C-5C-6C-7C-8C-9C-10C-JC-QC-KC-AD-2D-3D-4D-5D-6D-7D-8D-9D-10D-JD-QD-KD-AH-2H-3H-4H-5H-6H-7H-8H-9H-10H-JH-QH-KH-AS-2S-3S-4S-5S-6S-7S-8S-9S-10S-JS-QS-KS-A");
+        }
+    }
+}
diff --git a/94 War/csharp/War/WarTester/WarTester.csproj b/94 War/csharp/War/WarTester/WarTester.csproj
new file mode 100644
index 00000000..9d1808d6
--- /dev/null
+++ b/94 War/csharp/War/WarTester/WarTester.csproj	
@@ -0,0 +1,29 @@
+
+
+  
+    netcoreapp3.1
+
+    false
+
+    AnyCPU
+  
+
+  
+    true
+  
+
+  
+    
+    
+    
+    
+      all
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+    
+  
+
+  
+    
+  
+
+

From 86fd867dad9dc413872e1261411d9b5ea04c8103 Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Fri, 26 Mar 2021 18:47:00 -0400
Subject: [PATCH 333/749] Ported One Check to Java.

---
 67 One Check/java/OneCheck.java | 254 ++++++++++++++++++++++++++++++++
 1 file changed, 254 insertions(+)
 create mode 100644 67 One Check/java/OneCheck.java

diff --git a/67 One Check/java/OneCheck.java b/67 One Check/java/OneCheck.java
new file mode 100644
index 00000000..b33a76fe
--- /dev/null
+++ b/67 One Check/java/OneCheck.java	
@@ -0,0 +1,254 @@
+import java.util.Arrays;
+import java.util.Scanner;
+
+/**
+ * Game of One Check
+ * 

+ * Based on the BASIC game of One Check here + * https://github.com/coding-horror/basic-computer-games/blob/main/67%20One%20Check/onecheck.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class OneCheck { + + private final Scanner scan; // For user input + + private enum Step { + SHOW_INSTRUCTIONS, SHOW_BOARD, GET_MOVE, GET_SUMMARY, QUERY_RETRY + } + + public OneCheck() { + + scan = new Scanner(System.in); + + } // End of constructor OneCheck + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(29) + "ONE CHECK"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + boolean playAgain = true; + + int fromSquare = 0; + int numJumps = 0; + int numPieces = 0; + int square = 0; + int startPosition = 0; + int toSquare = 0; + + // Move legality test variables + int fromTest1 = 0; + int fromTest2 = 0; + int toTest1 = 0; + int toTest2 = 0; + + int[] positions = new int[65]; + + Step nextStep = Step.SHOW_INSTRUCTIONS; + + String lineContent = ""; + String userResponse = ""; + + // Begin outer while loop + while (true) { + + // Begin switch + switch (nextStep) { + + case SHOW_INSTRUCTIONS: + + System.out.println("SOLITAIRE CHECKER PUZZLE BY DAVID AHL\n"); + System.out.println("48 CHECKERS ARE PLACED ON THE 2 OUTSIDE SPACES OF A"); + System.out.println("STANDARD 64-SQUARE CHECKERBOARD. THE OBJECT IS TO"); + System.out.println("REMOVE AS MANY CHECKERS AS POSSIBLE BY DIAGONAL JUMPS"); + System.out.println("(AS IN STANDARD CHECKERS). USE THE NUMBERED BOARD TO"); + System.out.println("INDICATE THE SQUARE YOU WISH TO JUMP FROM AND TO. ON"); + System.out.println("THE BOARD PRINTED OUT ON EACH TURN '1' INDICATES A"); + System.out.println("CHECKER AND '0' AN EMPTY SQUARE. WHEN YOU HAVE NO"); + System.out.println("POSSIBLE JUMPS REMAINING, INPUT A '0' IN RESPONSE TO"); + System.out.println("QUESTION 'JUMP FROM ?'\n"); + System.out.println("HERE IS THE NUMERICAL BOARD:\n"); + + nextStep = Step.SHOW_BOARD; + break; + + case SHOW_BOARD: + + // Begin loop through all squares + for (square = 1; square <= 57; square += 8) { + + lineContent = String.format("% -4d%-4d%-4d%-4d%-4d%-4d%-4d%-4d", square, square + 1, square + 2, + square + 3, square + 4, square + 5, square + 6, square + 7); + System.out.println(lineContent); + + } // End loop through all squares + + System.out.println(""); + System.out.println("AND HERE IS THE OPENING POSITION OF THE CHECKERS."); + System.out.println(""); + + Arrays.fill(positions, 1); + + // Begin generating start positions + for (square = 19; square <= 43; square += 8) { + + for (startPosition = square; startPosition <= square + 3; startPosition++) { + + positions[startPosition] = 0; + + } + } // End generating start positions + + numJumps = 0; + + printBoard(positions); + + nextStep = Step.GET_MOVE; + break; + + case GET_MOVE: + + System.out.print("JUMP FROM? "); + fromSquare = scan.nextInt(); + scan.nextLine(); // Discard newline + + // User requested summary + if (fromSquare == 0) { + nextStep = Step.GET_SUMMARY; + break; + } + + System.out.print("TO? "); + toSquare = scan.nextInt(); + scan.nextLine(); // Discard newline + System.out.println(""); + + // Check legality of move + fromTest1 = (int) Math.floor((fromSquare - 1.0) / 8.0); + fromTest2 = fromSquare - 8 * fromTest1; + toTest1 = (int) Math.floor((toSquare - 1.0) / 8.0); + toTest2 = toSquare - 8 * toTest1; + + if ((fromTest1 > 7) || + (toTest1 > 7) || + (fromTest2 > 8) || + (toTest2 > 8) || + (Math.abs(fromTest1 - toTest1) != 2) || + (Math.abs(fromTest2 - toTest2) != 2) || + (positions[(toSquare + fromSquare) / 2] == 0) || + (positions[fromSquare] == 0) || + (positions[toSquare] == 1)) { + + System.out.println("ILLEGAL MOVE. TRY AGAIN..."); + nextStep = Step.GET_MOVE; + break; + } + + positions[toSquare] = 1; + positions[fromSquare] = 0; + positions[(toSquare + fromSquare) / 2] = 0; + numJumps++; + + printBoard(positions); + + nextStep = Step.GET_MOVE; + break; + + case GET_SUMMARY: + + numPieces = 0; + + // Count remaining pieces + for (square = 1; square <= 64; square++) { + numPieces += positions[square]; + } + + System.out.println(""); + System.out.println("YOU MADE " + numJumps + " JUMPS AND HAD " + numPieces + " PIECES"); + System.out.println("REMAINING ON THE BOARD.\n"); + + nextStep = Step.QUERY_RETRY; + break; + + case QUERY_RETRY: + + while (true) { + System.out.print("TRY AGAIN? "); + userResponse = scan.nextLine(); + System.out.println(""); + + if (userResponse.toUpperCase().equals("YES")) { + nextStep = Step.SHOW_BOARD; + break; + } + else if (userResponse.toUpperCase().equals("NO")) { + System.out.println("O.K. HOPE YOU HAD FUN!!"); + return; + } + else { + System.out.println("PLEASE ANSWER 'YES' OR 'NO'."); + } + } + break; + + default: + System.out.println("INVALID STEP"); + nextStep = Step.QUERY_RETRY; + break; + + } // End of switch + + } // End outer while loop + + } // End of method startGame + + public void printBoard(int[] positions) { + + int column = 0; + int row = 0; + String lineContent = ""; + + // Begin loop through all rows + for (row = 1; row <= 57; row += 8) { + + // Begin loop through all columns + for (column = row; column <= row + 7; column++) { + + lineContent += " " + positions[column]; + + } // End loop through all columns + + System.out.println(lineContent); + lineContent = ""; + + } // End loop through all rows + + System.out.println(""); + + } // End of method printBoard + + public static void main(String[] args) { + + OneCheck game = new OneCheck(); + game.play(); + + } // End of method main + +} // End of class OneCheck From b4655d577745f9aa03e1e7ffc9fa5e3c5b9ca813 Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Fri, 26 Mar 2021 22:51:28 +0000 Subject: [PATCH 334/749] Moved UI stuff into its own class. Minor changes, commenting and tidying up the other classes. --- 94 War/csharp/War/War/Cards.cs | 52 +++++++++++----- 94 War/csharp/War/War/Program.cs | 79 +++--------------------- 94 War/csharp/War/War/UserInterface.cs | 83 ++++++++++++++++++++++++++ 94 War/csharp/War/WarTester/Tests.cs | 30 ++++++---- 4 files changed, 145 insertions(+), 99 deletions(-) create mode 100644 94 War/csharp/War/War/UserInterface.cs diff --git a/94 War/csharp/War/War/Cards.cs b/94 War/csharp/War/War/Cards.cs index 7c31c3b2..99e03020 100644 --- a/94 War/csharp/War/War/Cards.cs +++ b/94 War/csharp/War/War/Cards.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; -using System.Text; + + namespace War { + // These enums define the card's suit and rank. public enum Suit { - none = 0, clubs, diamonds, hearts, @@ -15,7 +16,6 @@ namespace War public enum Rank { - none = 0, // Skip 1 because ace is high. two = 2, three, @@ -32,25 +32,25 @@ namespace War ace } - // TODO Testing - + // A class to represent a playing card. public class Card { + // A card is an immutable object (i.e. it can't be changed) so its suit + // and rank value are readonly; they can only be set in the constructor. private readonly Suit suit; private readonly Rank rank; - private static Dictionary suitNames = new Dictionary() + // These dictionaries are used to convert a suit or rank value into a string. + private readonly Dictionary suitNames = new Dictionary() { - { Suit.none, "N"}, { Suit.clubs, "C"}, { Suit.diamonds, "D"}, { Suit.hearts, "H"}, { Suit.spades, "S"}, }; - private static Dictionary rankNames = new Dictionary() + private readonly Dictionary rankNames = new Dictionary() { - { Rank.none, "0"}, { Rank.two, "2"}, { Rank.three, "3"}, { Rank.four, "4"}, @@ -66,18 +66,30 @@ namespace War { Rank.ace, "A"}, }; - public Card(Suit suit, Rank rank) // immutable + public Card(Suit suit, Rank rank) { this.suit = suit; this.rank = rank; } - // would normally consider suit and rank but in this case we only want to compare rank. + // Relational Operator Overloading. + // + // You would normally expect the relational operators to consider both the suit and the + // rank of a card, but in this program suit doesn't matter so we define the operators to just + // compare rank. + + // When adding relational operators we would normally include == and != but they are not + // relevant to this program so haven't been defined. Note that if they were defined we + // should also override the Equals() and GetHashCode() methods. See, for example: + // http://www.blackwasp.co.uk/CSharpRelationalOverload.aspx + + // If the == and != operators were defined they would look like this: + // //public static bool operator ==(Card lhs, Card rhs) //{ // return lhs.rank == rhs.rank; //} - + // //public static bool operator !=(Card lhs, Card rhs) //{ // return !(lhs == rhs); @@ -105,10 +117,12 @@ namespace War public override string ToString() { - return $"{suitNames[suit]}-{rankNames[rank]}"; // string interpolation + // N.B. We are using string interpolation to create the card name. + return $"{suitNames[suit]}-{rankNames[rank]}"; } } + // A class to represent a deck of cards. public class Deck { public const int deckSize = 52; @@ -117,6 +131,7 @@ namespace War public Deck() { + // Populate theDeck with all the cards in order. int i = 0; for (Suit suit = Suit.clubs; suit <= Suit.spades; suit++) { @@ -128,14 +143,21 @@ namespace War } } + // Return the card at a particular position in the deck. + // N.B. As this is such a short method, we make it an + // expression-body method. public Card GetCard(int i) => theDeck[i]; + // Shuffle the cards, this uses the modern version of the + // Fisher-Yates shuffle, see: + // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm public void Shuffle() { - // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + var rand = new Random(); + + // Iterate backwards through the deck. for (int i = deckSize - 1; i >= 1; i--) { - var rand = new Random(); int j = rand.Next(0, i); // Swap the cards at i and j diff --git a/94 War/csharp/War/War/Program.cs b/94 War/csharp/War/War/Program.cs index 68b602f8..57a6c37e 100644 --- a/94 War/csharp/War/War/Program.cs +++ b/94 War/csharp/War/War/Program.cs @@ -1,58 +1,11 @@ -using System; - -namespace War +namespace War { - public class Intro - { - public void WriteIntro() - { - Console.WriteLine(" WAR"); - Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - Console.WriteLine(); - Console.WriteLine(); - Console.WriteLine(); - - Console.WriteLine("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#"); - Console.WriteLine("AS S-7 FOR SPADE 7. "); - - if (AskQuestion("DO YOU WANT DIRECTIONS? ")) - { - Console.WriteLine("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD"); - Console.WriteLine("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO"); - Console.WriteLine("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK."); - } - - Console.WriteLine(); - Console.WriteLine(); - } - - public bool AskQuestion(string question) - { - while (true) - { - Console.Write(question); - string result = Console.ReadLine(); - - if (result.ToLower()[0] == 'y') - { - return true; - } - else /*if (result.ToLower() == "no")*/ - { - return false; - } - - Console.WriteLine("YES OR NO, PLEASE."); - } - } - } - class Program { static void Main(string[] args) { - var intro = new Intro(); - intro.WriteIntro(); + var ui = new UserInterface(); + ui.WriteIntro(); var deck = new Deck(); deck.Shuffle(); @@ -63,38 +16,20 @@ namespace War for (int i = 0; i < Deck.deckSize; i += 2) { + // Play the next hand. var yourCard = deck.GetCard(i); var computersCard = deck.GetCard(i + 1); - Console.WriteLine($"YOU: {yourCard} COMPUTER: {computersCard}"); - if (yourCard < computersCard) - { - computersScore++; - Console.WriteLine($"THE COMPUTER WINS!!! YOU HAVE {yourScore} AND THE COMPUTER HAS {computersScore}"); - } - else if (yourCard > computersCard) - { - yourScore++; - Console.WriteLine($"YOU WIN. YOU HAVE {yourScore} AND THE COMPUTER HAS {computersScore}"); - } - else - { - Console.WriteLine("TIE. NO SCORE CHANGE"); - } + ui.WriteAResult(yourCard, computersCard, ref computersScore, ref yourScore); - if (!intro.AskQuestion("DO YOU WANT TO CONTINUE? ")) + if (!ui.AskAQuestion("DO YOU WANT TO CONTINUE? ")) { usedAllCards = false; break; } } - if (usedAllCards) - { - Console.WriteLine("WE HAVE RUN OUT OF CARDS."); - } - Console.WriteLine($"FINAL SCORE: YOU: {yourScore} THE COMPUTER: {computersScore}"); - Console.WriteLine("THANKS FOR PLAYING. IT WAS FUN."); + ui.WriteClosingRemarks(usedAllCards, yourScore, computersScore); } } } diff --git a/94 War/csharp/War/War/UserInterface.cs b/94 War/csharp/War/War/UserInterface.cs new file mode 100644 index 00000000..ee93d9fa --- /dev/null +++ b/94 War/csharp/War/War/UserInterface.cs @@ -0,0 +1,83 @@ +using System; + + + +namespace War +{ + // This class displays all the text that the user sees when playing the game. + // It also handles asking the user a yes/no question and returning their answer. + public class UserInterface + { + public void WriteIntro() + { + Console.WriteLine(" WAR"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + + Console.WriteLine("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#"); + Console.Write("AS S-7 FOR SPADE 7. "); + + if (AskAQuestion("DO YOU WANT DIRECTIONS? ")) + { + Console.WriteLine("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD"); + Console.WriteLine("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO"); + Console.WriteLine("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK."); + } + + Console.WriteLine(); + Console.WriteLine(); + } + + public void WriteAResult(Card yourCard, Card computersCard, ref int computersScore, ref int yourScore) + { + Console.WriteLine($"YOU: {yourCard} COMPUTER: {computersCard}"); + if (yourCard < computersCard) + { + computersScore++; + Console.WriteLine($"THE COMPUTER WINS!!! YOU HAVE {yourScore} AND THE COMPUTER HAS {computersScore}"); + } + else if (yourCard > computersCard) + { + yourScore++; + Console.WriteLine($"YOU WIN. YOU HAVE {yourScore} AND THE COMPUTER HAS {computersScore}"); + } + else + { + Console.WriteLine("TIE. NO SCORE CHANGE"); + } + } + + public bool AskAQuestion(string question) + { + // Repeat asking the question until the user answers "YES" or "NO". + while (true) + { + Console.Write(question); + string result = Console.ReadLine(); + + if (result.ToLower() == "yes") + { + Console.WriteLine(); + return true; + } + else if (result.ToLower() == "no") + { + Console.WriteLine(); + return false; + } + + Console.WriteLine("YES OR NO, PLEASE."); + } + } + + public void WriteClosingRemarks(bool usedAllCards, int yourScore, int computersScore) + { + if (usedAllCards) + { + Console.WriteLine("WE HAVE RUN OUT OF CARDS."); + } + Console.WriteLine($"FINAL SCORE: YOU: {yourScore} THE COMPUTER: {computersScore}"); + Console.WriteLine("THANKS FOR PLAYING. IT WAS FUN."); + } + } +} diff --git a/94 War/csharp/War/WarTester/Tests.cs b/94 War/csharp/War/WarTester/Tests.cs index 313d2a1e..387b4547 100644 --- a/94 War/csharp/War/WarTester/Tests.cs +++ b/94 War/csharp/War/WarTester/Tests.cs @@ -14,6 +14,8 @@ namespace WarTester private Card c3 = new Card(Suit.diamonds, Rank.ten); private Card c4 = new Card(Suit.diamonds, Rank.ten); + // Test the relational operators. + [TestMethod] public void LessThanIsValid() { @@ -77,10 +79,10 @@ namespace WarTester [TestMethod] public void ToStringIsValid() { - string s1 = c1.ToString(); - string s2 = c3.ToString(); - string s3 = new Card(Suit.hearts, Rank.queen).ToString(); - string s4 = new Card(Suit.spades, Rank.ace).ToString(); + var s1 = c1.ToString(); + var s2 = c3.ToString(); + var s3 = new Card(Suit.hearts, Rank.queen).ToString(); + var s4 = new Card(Suit.spades, Rank.ace).ToString(); Assert.IsTrue(s1 == "C-2", "s1 invalid"); Assert.IsTrue(s2 == "D-10", "s2 invalid"); @@ -92,7 +94,10 @@ namespace WarTester [TestClass] public class DeckTest { - private string ConcatenateDeck(Deck d) + private readonly string cardNamesInOrder = "C-2C-3C-4C-5C-6C-7C-8C-9C-10C-JC-QC-KC-AD-2D-3D-4D-5D-6D-7D-8D-9D-10D-JD-QD-KD-AH-2H-3H-4H-5H-6H-7H-8H-9H-10H-JH-QH-KH-AS-2S-3S-4S-5S-6S-7S-8S-9S-10S-JS-QS-KS-A"; + + //Helper method. Adds the names of all the cards together into a single string. + private string ConcatenateTheDeck(Deck d) { StringBuilder sb = new StringBuilder(); @@ -107,20 +112,21 @@ namespace WarTester [TestMethod] public void InitialDeckContainsCardsInOrder() { - Deck d1 = new Deck(); - string allTheCards = ConcatenateDeck(d1); + Deck d = new Deck(); + string allTheCards = ConcatenateTheDeck(d); - Assert.IsTrue(allTheCards == "C-2C-3C-4C-5C-6C-7C-8C-9C-10C-JC-QC-KC-AD-2D-3D-4D-5D-6D-7D-8D-9D-10D-JD-QD-KD-AH-2H-3H-4H-5H-6H-7H-8H-9H-10H-JH-QH-KH-AS-2S-3S-4S-5S-6S-7S-8S-9S-10S-JS-QS-KS-A"); + Assert.IsTrue(allTheCards == cardNamesInOrder); } [TestMethod] public void ShufflingChangesDeck() { - Deck d1 = new Deck(); - d1.Shuffle(); - string allTheCards = ConcatenateDeck(d1); + // I'm not sure how to test that shuffling has worked other than to check that the cards aren't in the initial order. + Deck d = new Deck(); + d.Shuffle(); + string allTheCards = ConcatenateTheDeck(d); - Assert.IsTrue(allTheCards != "C-2C-3C-4C-5C-6C-7C-8C-9C-10C-JC-QC-KC-AD-2D-3D-4D-5D-6D-7D-8D-9D-10D-JD-QD-KD-AH-2H-3H-4H-5H-6H-7H-8H-9H-10H-JH-QH-KH-AS-2S-3S-4S-5S-6S-7S-8S-9S-10S-JS-QS-KS-A"); + Assert.IsTrue(allTheCards != cardNamesInOrder); } } } From 191b77f54c302024bc8c63163ebafe3fe6f9746a Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Fri, 26 Mar 2021 23:03:15 +0000 Subject: [PATCH 335/749] Fixed tabs, spaces mismatch. --- 94 War/csharp/War/War/Program.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/94 War/csharp/War/War/Program.cs b/94 War/csharp/War/War/Program.cs index 57a6c37e..7ab335e3 100644 --- a/94 War/csharp/War/War/Program.cs +++ b/94 War/csharp/War/War/Program.cs @@ -5,27 +5,27 @@ static void Main(string[] args) { var ui = new UserInterface(); - ui.WriteIntro(); + ui.WriteIntro(); - var deck = new Deck(); - deck.Shuffle(); + var deck = new Deck(); + deck.Shuffle(); - int yourScore = 0; + int yourScore = 0; int computersScore = 0; - bool usedAllCards = true; + bool usedAllCards = true; for (int i = 0; i < Deck.deckSize; i += 2) { // Play the next hand. - var yourCard = deck.GetCard(i); + var yourCard = deck.GetCard(i); var computersCard = deck.GetCard(i + 1); ui.WriteAResult(yourCard, computersCard, ref computersScore, ref yourScore); if (!ui.AskAQuestion("DO YOU WANT TO CONTINUE? ")) { - usedAllCards = false; - break; + usedAllCards = false; + break; } } From db93b7c79f51c3399f38746f4e3492d317c5f790 Mon Sep 17 00:00:00 2001 From: nanochess Date: Fri, 26 Mar 2021 23:01:01 -0600 Subject: [PATCH 336/749] Ported FTBALL to Javascript --- 37 Football/ftball.bas | 4 +- 37 Football/javascript/ftball.html | 9 + 37 Football/javascript/ftball.js | 508 +++++++++++++++++++++++++++++ 3 files changed, 519 insertions(+), 2 deletions(-) create mode 100644 37 Football/javascript/ftball.html create mode 100644 37 Football/javascript/ftball.js diff --git a/37 Football/ftball.bas b/37 Football/ftball.bas index 40a6aa8b..fe6ca68b 100644 --- a/37 Football/ftball.bas +++ b/37 Football/ftball.bas @@ -33,7 +33,7 @@ 500 FOR E=1 TO 2 510 IF A$=L$(E) THEN 550 520 NEXT E -530 PRINT "INCORRECT ANSWER. PLEASE TYPE 'KICK' OR 'RECIEVE'"; +530 PRINT "INCORRECT ANSWER. PLEASE TYPE 'KICK' OR 'RECEIVE'"; 540 GOTO 480 550 IF E=2 THEN 580 560 LET P=1 @@ -149,7 +149,7 @@ 1670 GOTO 1350 1680 REM PLACE KICK 1690 LET Y=INT(100*(R-.5)^3+35) -1700 IF R1>.15 THEN 1740 +1700 IF R1>.15 THEN 1750 1710 PRINT "KICK IS BLOCKED ***" 1720 LET X=X-5*FNF(1) 1730 LET P=1-P diff --git a/37 Football/javascript/ftball.html b/37 Football/javascript/ftball.html new file mode 100644 index 00000000..92862bde --- /dev/null +++ b/37 Football/javascript/ftball.html @@ -0,0 +1,9 @@ + + +FTBALL + + +


+
+
+
diff --git a/37 Football/javascript/ftball.js b/37 Football/javascript/ftball.js
new file mode 100644
index 00000000..16374bd0
--- /dev/null
+++ b/37 Football/javascript/ftball.js	
@@ -0,0 +1,508 @@
+// FTBALL
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var os = [];
+var sa = [];
+var ls = [, "KICK","RECEIVE"," YARD ","RUN BACK FOR ","BALL ON ",
+          "YARD LINE"," SIMPLE RUN"," TRICKY RUN"," SHORT PASS",
+          " LONG PASS","PUNT"," QUICK KICK "," PLACE KICK"," LOSS ",
+          " NO GAIN","GAIN "," TOUCHDOWN "," TOUCHBACK ","SAFETY***",
+          "JUNK"];
+var p;
+var x;
+var x1;
+
+function fnf(x)
+{
+    return 1 - 2 * p;
+}
+
+function fng(z)
+{
+    return p * (x1 - x) + (1 - p) * (x - x1);
+}
+
+function show_score()
+{
+    print("\n");
+    print("SCORE:  " + sa[0] + " TO " + sa[1] + "\n");
+    print("\n");
+    print("\n");
+}
+
+function show_position()
+{
+    if (x <= 50) {
+        print(ls[5] + os[0] + " " + x + " " + ls[6] + "\n");
+    } else {
+        print(ls[5] + os[1] + " " + (100 - x) + " " + ls[6] + "\n");
+    }
+}
+
+function offensive_td()
+{
+    print(ls[17] + "***\n");
+    if (Math.random() <= 0.8) {
+        sa[p] = sa[p] + 7;
+        print("KICK IS GOOD.\n");
+    } else {
+        print("KICK IS OFF TO THE SIDE\n");
+        sa[p] = sa[p] + 6;
+    }
+    show_score();
+    print(os[p] + " KICKS OFF\n");
+    p = 1 - p;
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "FTBALL\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("THIS IS DARTMOUTH CHAMPIONSHIP FOOTBALL.\n");
+    print("\n");
+    print("YOU WILL QUARTERBACK DARTMOUTH. CALL PLAYS AS FOLLOWS:\n");
+    print("1= SIMPLE RUN; 2= TRICKY RUN; 3= SHORT PASS;\n");
+    print("4= LONG PASS; 5= PUNT; 6= QUICK KICK; 7= PLACE KICK.\n");
+    print("\n");
+    print("CHOOSE YOUR OPPONENT");
+    os[1] = await input();
+    os[0] = "DARMOUTH";
+    print("\n");
+    sa[0] = 0;
+    sa[1] = 0;
+    p = Math.floor(Math.random() * 2);
+    print(os[p] + " WON THE TOSS\n");
+    if (p != 0) {
+        print(os[1] + " ELECTS TO RECEIVE.\n");
+        print("\n");
+    } else {
+        print("DO YOU ELECT TO KICK OR RECEIVE");
+        while (1) {
+            str = await input();
+            print("\n");
+            if (str == ls[1] || str == ls[2])
+                break;
+            print("INCORRECT ANSWER.  PLEASE TYPE 'KICK' OR 'RECEIVE'");
+        }
+        e = (str == ls[1]) ? 1 : 2;
+        if (e == 1)
+            p = 1;
+    }
+    t = 0;
+    start = 1;
+    while (1) {
+        if (start <= 1) {
+            x = 40 + (1 - p) * 20;
+        }
+        if (start <= 2) {
+            y = Math.floor(200 * Math.pow((Math.random() - 0.5), 3) + 55);
+            print(" " + y + " " + ls[3] + " KICKOFF\n");
+            x = x - fnf(1) * y;
+            if (Math.abs(x - 50) >= 50) {
+                print("TOUCHBACK FOR " + os[p] + ".\n");
+                x = 20 + p * 60;
+                start = 4;
+            } else {
+                start = 3;
+            }
+        }
+        if (start <= 3) {
+            y = Math.floor(50 * Math.pow(Math.random(), 2)) + (1 - p) * Math.floor(50 * Math.pow(Math.random(), 4));
+            x = x + fnf(1) * y;
+            if (Math.abs(x - 50) < 50) {
+                print(" " + y + " " + ls[3] + " RUNBACK\n");
+            } else {
+                print(ls[4]);
+                offensive_td();
+                start = 1;
+                continue;
+            }
+        }
+        if (start <= 4) {
+            // First down
+            show_position();
+        }
+        if (start <= 5) {
+            x1 = x;
+            d = 1;
+            print("\n");
+            print("FIRST DOWN " + os[p] + "***\n");
+            print("\n");
+            print("\n");
+        }
+        // New play
+        t++;
+        if (t == 30) {
+            if (Math.random() <= 1.3) {
+                print("GAME DELAYED.  DOG ON FIELD.\n");
+                print("\n");
+            }
+        }
+        if (t >= 50 && Math.random() <= 0.2)
+            break;
+        if (p != 1) {
+            // Opponent's play
+            if (d <= 1) {
+                z = Math.random() > 1 / 3 ? 1 : 3;
+            } else if (d != 4) {
+                if (10 + x - x1 < 5 || x < 5) {
+                    z = Math.random() > 1 / 3 ? 1 : 3;
+                } else if (x <= 10) {
+                    a = Math.floor(2 * Math.random());
+                    z = 2 + a;
+                } else if (x <= x1 || d < 3 || x < 45) {
+                    a = Math.floor(2 * Math.random());
+                    z = 2 + a * 2;
+                } else {
+                    if (Math.random() > 1 / 4)
+                        z = 4;
+                    else
+                        z = 6;
+                }
+            } else {
+                if (x <= 30) {
+                    z = 5;
+                } else if (10 + x - x1 < 3 || x < 3) {
+                    z = Math.random() > 1 / 3 ? 1 : 3;
+                } else {
+                    z = 7;
+                }
+            }
+        } else {
+            print("NEXT PLAY");
+            while (1) {
+                z = parseInt(await input());
+                if (Math.abs(z - 4) <= 3)
+                    break;
+                print("ILLEGAL PLAY NUMBER, RETYPE");
+            }
+        }
+        f = 0;
+        print(ls[z + 6] + ".  ");
+        r = Math.random() * (0.98 + fnf(1) * 0.02);
+        r1 = Math.random();
+        switch (z) {
+            case 1: // Simple run
+            case 2: // Tricky run
+                if (z == 1) {
+                    y = Math.floor(24 * Math.pow(r - 0.5, 3) + 3);
+                    if (Math.random() >= 0.05) {
+                        routine = 1;
+                        break;
+                    }
+                } else {
+                    y = Math.floor(20 * r - 5);
+                    if (Math.random() > 0.1) {
+                        routine = 1;
+                        break;
+                    }
+                }
+                f = -1;
+                x3 = x;
+                x = x + fnf(1) * y;
+                if (Math.abs(x - 50) < 50) {
+                    print("***  FUMBLE AFTER ");
+                    routine = 2;
+                    break;
+                } else {
+                    print("***  FUMBLE.\n");
+                    routine = 4;
+                    break;
+                }
+            case 3: // Short pass
+            case 4: // Long pass
+                if (z == 3) {
+                    y = Math.floor(60 * Math.pow(r1 - 0.5, 3) + 10);
+                } else {
+                    y = Math.floor(160 * Math.pow((r1 - 0.5), 3) + 30);
+                }
+                if (z == 3 && r < 0.05 || z == 4 && r < 0.1) {
+                    if (d != 4) {
+                        print("INTERCEPTED.\n");
+                        f = -1;
+                        x = x + fnf(1) * y;
+                        if (Math.abs(x - 50) >= 50) {
+                            routine = 4;
+                            break;
+                        }
+                        routine = 3;
+                        break;
+                    } else {
+                        y = 0;
+                        if (Math.random() < 0.3) {
+                            print("BATTED DOWN.  ");
+                        } else {
+                            print("INCOMPLETE.  ");
+                        }
+                        routine = 1;
+                        break;
+                    }
+                } else if (z == 4 && r < 0.3) {
+                    print("PASSER TACKLED.  ");
+                    y = -Math.floor(15 * r1 + 3);
+                    routine = 1;
+                    break;
+                } else if (z == 3 && r < 0.15) {
+                    print("PASSER TACLKED.  ");
+                    y = -Math.floor(10 * r1);
+                    routine = 1;
+                    break;
+                } else if (z == 3 && r < 0.55 || z == 4 && r < 0.75) {
+                    y = 0;
+                    if (Math.random() < 0.3) {
+                        print("BATTED DOWN.  ");
+                    } else {
+                        print("INCOMPLETE.  ");
+                    }
+                    routine = 1;
+                    break;
+                } else {
+                    print("COMPLETE.  ");
+                    routine = 1;
+                    break;
+                }
+            case 5:  // Punt
+            case 6:  // Quick kick
+                y = Math.floor(100 * Math.pow((r - 0.5), 3) + 35);
+                if (d != 4)
+                    y = Math.floor(y * 1.3);
+                print(" " + y + " " + ls[3] + " PUNT\n");
+                if (Math.abs(x + y * fnf(1) - 50) < 50 && d >= 4) {
+                    y1 = Math.floor(Math.pow(r1, 2) * 20);
+                    print(" " + y1 + " " + ls[3] + " RUN BACK\n");
+                    y = y - y1;
+                }
+                f = -1;
+                x = x + fnf(1) * y;
+                if (Math.abs(x - 50) >= 50) {
+                    routine = 4;
+                    break;
+                }
+                routine = 3;
+                break;
+            case 7: // Place kick
+                y = Math.floor(100 * Math.pow((r - 0.5), 3) + 35);
+                if (r1 <= 0.15) {
+                    print("KICK IS BLOCKED  ***\n");
+                    x = x - 5 * fnf(1);
+                    p = 1 - p;
+                    start = 4;
+                    continue;
+                }
+                x = x + fnf(1) * y;
+                if (Math.abs(x - 50) >= 60) {
+                    if (r1 <= 0.5) {
+                        print("KICK IS OFF TO THE SIDE.\n");
+                        print(ls[18] + "\n");
+                        p = 1 - p;
+                        x = 20 + p * 60;
+                        start = 4;
+                        continue;
+                    } else {
+                        print("FIELD GOAL ***\n");
+                        sa[p] = sa[p] + 3;
+                        show_score();
+                        print(os[p] + " KICKS OFF\n");
+                        p = 1 - p;
+                        start = 1;
+                        continue;
+                    }
+                } else {
+                    print("KICK IS SHORT.\n");
+                    if (Math.abs(x - 50) >= 50) {
+                        // Touchback
+                        print(ls[18] + "\n");
+                        p = 1 - p;
+                        x = 20 + p * 60;
+                        start = 4;
+                        continue;
+                    }
+                    p = 1 - p;
+                    start = 3;
+                    continue;
+                }
+                
+        }
+        // Gain or loss
+        if (routine <= 1) {
+            x3 = x;
+            x = x + fnf(1) * y;
+            if (Math.abs(x - 50) >= 50) {
+                routine = 4;
+            }
+        }
+        if (routine <= 2) {
+            if (y != 0) {
+                print(" " + Math.abs(y) + " " + ls[3]);
+                if (y < 0)
+                    yt = -1;
+                else if (y > 0)
+                    yt = 1;
+                else
+                    yt = 0;
+                print(ls[15 + yt]);
+                if (Math.abs(x3 - 50) <= 40 && Math.random() < 0.1) {
+                    // Penalty
+                    p3 = Math.floor(2 * Math.random());
+                    print(os[p3] + " OFFSIDES -- PENALTY OF 5 YARDS.\n");
+                    print("\n");
+                    print("\n");
+                    if (p3 != 0) {
+                        print("DO YOU ACCEPT THE PENALTY");
+                        while (1) {
+                            str = await input();
+                            if (str == "YES" || str == "NO")
+                                break;
+                            print("TYPE 'YES' OR 'NO'");
+                        }
+                        if (str == "YES") {
+                            f = 0;
+                            d = d - 1;
+                            if (p != p3)
+                                x = x3 + fnf(1) * 5;
+                            else
+                                x = x3 - fnf(1) * 5;
+                        }
+                    } else {
+                        // Opponent's strategy on penalty
+                        if ((p != 1 && (y <= 0 || f < 0 || fng(1) < 3 * d - 2))
+                            || (p == 1 && ((y > 5 && f >= 0) || d < 4 || fng(1) >= 10))) {
+                            print("PENALTY REFUSED.\n");
+                        } else {
+                            print("PENALTY ACCEPTED.\n");
+                            f = 0;
+                            d = d - 1;
+                            if (p != p3)
+                                x = x3 + fnf(1) * 5;
+                            else
+                                x = x3 - fnf(1) * 5;
+                        }
+                    }
+                    routine = 3;
+                }
+            }
+        }
+        if (routine <= 3) {
+            show_position();
+            if (f != 0) {
+                p = 1 - p;
+                start = 5;
+                continue;
+            } else if (fng(1) >= 10) {
+                start = 5;
+                continue;
+            } else if (d == 4) {
+                p = 1 - p;
+                start = 5;
+                continue;
+            } else {
+                d++;
+                print("DOWN: " + d + "     ");
+                if ((x1 - 50) * fnf(1) >= 40) {
+                    print("GOAL TO GO\n");
+                } else {
+                    print("YARDS TO GO: " + (10 - fng(1)) + "\n");
+                }
+                print("\n");
+                print("\n");
+                start = 6;
+                continue;
+            }
+        }
+        if (routine <= 4) {
+            // Ball in end-zone
+            e = (x >= 100) ? 1 : 0;
+            switch (1 + e - f * 2 + p * 4) {
+                case 1:
+                case 5:
+                    // Safety
+                    sa[1 - p] = sa[1 - p] + 2;
+                    print(ls[19] + "\n");
+                    show_score();
+                    print(os[p] + " KICKS OFF FROM ITS 20 YARD LINE.\n");
+                    x = 20 + p * 60;
+                    p = 1 - p;
+                    start = 2;
+                    continue;
+                case 3:
+                case 6:
+                    // Defensive TD
+                    print(ls[17] + "FOR " + os[1 - p] + "***\n");
+                    p = 1 - p;
+                    // Fall-thru
+                case 2:
+                case 8:
+                    // Offensive TD
+                    print(ls[17] + "***\n");
+                    if (Math.random() <= 0.8) {
+                        sa[p] = sa[p] + 7;
+                        print("KICK IS GOOD.\n");
+                    } else {
+                        print("KICK IS OFF TO THE SIDE\n");
+                        sa[p] = sa[p] + 6;
+                    }
+                    show_score();
+                    print(os[p] + " KICKS OFF\n");
+                    p = 1 - p;
+                    start = 1;
+                    continue;
+                case 4:
+                case 7:
+                    // Touchback
+                    print(ls[18] + "\n");
+                    p = 1 - p;
+                    x = 20 + p * 60;
+                    start = 4;
+                    continue;
+            }
+        }
+    }
+    print("END OF GAME  ***\n");
+    print("FINAL SCORE:  " + os[0] + ": " + sa[0] + "  " + os[1] + ": " + sa[1] + "\n");
+}
+
+main();

From 09d5461e9f2082c37a884ac8a460368d21c94d25 Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Sat, 27 Mar 2021 11:09:45 -0400
Subject: [PATCH 337/749] Remove an unused variable from OneCheck.java.

---
 67 One Check/java/OneCheck.java | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/67 One Check/java/OneCheck.java b/67 One Check/java/OneCheck.java
index b33a76fe..0e69fc30 100644
--- a/67 One Check/java/OneCheck.java	
+++ b/67 One Check/java/OneCheck.java	
@@ -43,9 +43,7 @@ public class OneCheck {
   }  // End of method showIntro        
   
   private void startGame() {
-    
-    boolean playAgain = true;
-    
+
     int fromSquare = 0;
     int numJumps = 0;
     int numPieces = 0;

From d080b9166d5b271acccf60a30e466b55a874ef87 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 27 Mar 2021 14:50:17 -0600
Subject: [PATCH 338/749] Ported HOCKEY to Javascript

---
 49 Hockey/hockey.bas             |   2 +-
 49 Hockey/javascript/hockey.html |   9 +
 49 Hockey/javascript/hockey.js   | 464 +++++++++++++++++++++++++++++++
 3 files changed, 474 insertions(+), 1 deletion(-)
 create mode 100644 49 Hockey/javascript/hockey.html
 create mode 100644 49 Hockey/javascript/hockey.js

diff --git a/49 Hockey/hockey.bas b/49 Hockey/hockey.bas
index 7fb90d6b..626b4f56 100644
--- a/49 Hockey/hockey.bas	
+++ b/49 Hockey/hockey.bas	
@@ -72,7 +72,7 @@
 600 PRINT A$(H(J-2)) " GIVES AND GOES WITH " A$(H(J-1))
 610 PRINT "PRETTY PASSING!"
 620 PRINT A$(H(J-1)) " DROPS IT TO " A$(H(J-4))
-630 G=H(J-4):G1=J(J-1):G2=H(J-2):Z1=1:GOTO 770
+630 G=H(J-4):G1=H(J-1):G2=H(J-2):Z1=1:GOTO 770
 640 ON P GOTO 650,670,720
 650 PRINT B$(H(J-1)) " HITS " B$(H(J-2)) " FLYING DOWN THE LEFT SIDE" 
 660 G=H(J-2):G1=H(J-1):G2=0:Z1=3:GOTO 770
diff --git a/49 Hockey/javascript/hockey.html b/49 Hockey/javascript/hockey.html
new file mode 100644
index 00000000..fb26a5c6
--- /dev/null
+++ b/49 Hockey/javascript/hockey.html	
@@ -0,0 +1,9 @@
+
+
+HOCKEY
+
+
+

+
+
+
diff --git a/49 Hockey/javascript/hockey.js b/49 Hockey/javascript/hockey.js
new file mode 100644
index 00000000..16d5f19e
--- /dev/null
+++ b/49 Hockey/javascript/hockey.js	
@@ -0,0 +1,464 @@
+// HOCKEY
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var as = [];
+var bs = [];
+var ha = [];
+var ta = [];
+var t1 = [];
+var t2 = [];
+var t3 = [];
+
+// Main program
+async function main()
+{
+    print(tab(33) + "HOCKEY\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // Robert Puopolo Alg. 1 140 McCowan 6/7/73 Hockey
+    for (c = 0; c <= 20; c++)
+        ha[c] = 0;
+    for (c = 1; c <= 5; c++) {
+        ta[c] = 0;
+        t1[c] = 0;
+        t2[c] = 0;
+        t3[c] = 0;
+    }
+    x = 1;
+    print("\n");
+    print("\n");
+    print("\n");
+    while (1) {
+        print("WOULD YOU LIKE THE INSTRUCTIONS");
+        str = await input();
+        print("\n");
+        if (str == "YES" || str == "NO")
+            break;
+        print("ANSWER YES OR NO!!\n");
+    }
+    if (str == "YES") {
+        print("\n");
+        print("THIS IS A SIMULATED HOCKEY GAME.\n");
+        print("QUESTION     RESPONSE\n");
+        print("PASS         TYPE IN THE NUMBER OF PASSES YOU WOULD\n");
+        print("             LIKE TO MAKE, FROM 0 TO 3.\n");
+        print("SHOT         TYPE THE NUMBER CORRESPONDING TO THE SHOT\n");
+        print("             YOU WANT TO MAKE.  ENTER:\n");
+        print("             1 FOR A SLAPSHOT\n");
+        print("             2 FOR A WRISTSHOT\n");
+        print("             3 FOR A BACKHAND\n");
+        print("             4 FOR A SNAP SHOT\n");
+        print("AREA         TYPE IN THE NUMBER CORRESPONDING TO\n");
+        print("             THE AREA YOU ARE AIMING AT.  ENTER:\n");
+        print("             1 FOR UPPER LEFT HAND CORNER\n");
+        print("             2 FOR UPPER RIGHT HAND CORNER\n");
+        print("             3 FOR LOWER LEFT HAND CORNER\n");
+        print("             4 FOR LOWER RIGHT HAND CORNER\n");
+        print("\n");
+        print("AT THE START OF THE GAME, YOU WILL BE ASKED FOR THE NAMES\n");
+        print("OF YOUR PLAYERS.  THEY ARE ENTERED IN THE ORDER: \n");
+        print("LEFT WING, CENTER, RIGHT WING, LEFT DEFENSE,\n");
+        print("RIGHT DEFENSE, GOALKEEPER.  ANY OTHER INPUT REQUIRED WILL\n");
+        print("HAVE EXPLANATORY INSTRUCTIONS.\n");
+    }
+    print("ENTER THE TWO TEAMS");
+    str = await input();
+    c = str.indexOf(",");
+    as[7] = str.substr(0, c);
+    bs[7] = str.substr(c + 1);
+    print("\n");
+    do {
+        print("ENTER THE NUMBER OF MINUTES IN A GAME");
+        t6 = parseInt(await input());
+        print("\n");
+    } while (t6 < 1) ;
+    print("\n");
+    print("WOULD THE " + as[7] + " COACH ENTER HIS TEAM\n");
+    print("\n");
+    for (i = 1; i <= 6; i++) {
+        print("PLAYER " + i + " ");
+        as[i] = await input();
+    }
+    print("\n");
+    print("WOULD THE " + bs[7] + " COACH DO THE SAME\n");
+    print("\n");
+    for (t = 1; t <= 6; t++) {
+        print("PLAYER " + t + " ");
+        bs[t] = await input();
+    }
+    print("\n");
+    print("INPUT THE REFEREE FOR THIS GAME");
+    rs = await input();
+    print("\n");
+    print(tab(10) + as[7] + " STARTING LINEUP\n");
+    for (t = 1; t <= 6; t++) {
+        print(as[t] + "\n");
+    }
+    print("\n");
+    print(tab(10) + bs[7] + " STARTING LINEUP\n");
+    for (t = 1; t <= 6; t++) {
+        print(bs[t] + "\n");
+    }
+    print("\n");
+    print("WE'RE READY FOR TONIGHTS OPENING FACE-OFF.\n");
+    print(rs + " WILL DROP THE PUCK BETWEEN " + as[2] + " AND " + bs[2] + "\n");
+    s2 = 0;
+    s3 = 0;
+    for (l = 1; l <= t6; l++) {
+        c = Math.floor(2 * Math.random()) + 1;
+        if (c == 1)
+            print(as[7] + " HAS CONTROL OF THE PUCK\n");
+        else
+            print(bs[7] + " HAS CONTROL.\n");
+        do {
+            
+            print("PASS");
+            p = parseInt(await input());
+            for (n = 1; n <= 3; n++)
+                ha[n] = 0;
+        } while (p < 0 || p > 3) ;
+        do {
+            for (j = 1; j <= p + 2; j++)
+                ha[j] = Math.floor(5 * Math.random()) + 1;
+        } while (ha[j - 1] == ha[j - 2] || (p + 2 >= 3 && (ha[j - 1] == ha[j - 3] || ha[j - 2] == ha[j - 3]))) ;
+        if (p == 0) {
+            while (1) {
+                print("SHOT");
+                s = parseInt(await input());
+                if (s >= 1 && s <= 4)
+                    break;
+            }
+            if (c == 1) {
+                print(as[ha[j - 1]]);
+                g = ha[j - 1];
+                g1 = 0;
+                g2 = 0;
+            } else {
+                print(bs[ha[j - 1]]);
+                g2 = 0;
+                g2 = 0;
+                g = ha[j - 1];
+            }
+            switch (s) {
+                case 1:
+                    print(" LET'S A BOOMER GO FROM THE RED LINE!!\n");
+                    z = 10;
+                    break;
+                case 2:
+                    print(" FLIPS A WRISTSHOT DOWN THE ICE\n");
+                    // Probable missing line 430 in original
+                case 3:
+                    print(" BACKHANDS ONE IN ON THE GOALTENDER\n");
+                    z = 25;
+                    break;
+                case 4:
+                    print(" SNAPS A LONG FLIP SHOT\n");
+                    z = 17;
+                    break;
+            }
+        } else {
+            if (c == 1) {
+                switch (p) {
+                    case 1:
+                        print(as[ha[j - 2]] + " LEADS " + as[ha[j - 1]] + " WITH A PERFECT PASS.\n");
+                        print(as[ha[j - 1]] + " CUTTING IN!!!\n");
+                        g = ha[j - 1];
+                        g1 = ha[j - 2];
+                        g2 = 0;
+                        z1 = 3;
+                        break;
+                    case 2:
+                        print(as[ha[j - 2]] + " GIVES TO A STREAKING " + as[ha[j - 1]] + "\n");
+                        print(as[ha[j - 3]] + " COMES DOWN ON " + bs[5] + " AND " + bs[4] + "\n");
+                        g = ha[j - 3];
+                        g1 = ha[j - 1];
+                        g2 = ha[j - 2];
+                        z1 = 2;
+                        break;
+                    case 3:
+                        print("OH MY GOD!! A ' 4 ON 2 ' SITUATION\n");
+                        print(as[ha[j - 3]] + " LEADS " + as[ha[j - 2]] + "\n");
+                        print(as[ha[j - 2]] + " IS WHEELING THROUGH CENTER.\n");
+                        print(as[ha[j - 2]] + " GIVES AND GOEST WITH " + as[ha[j - 1]] + "\n");
+                        print("PRETTY PASSING!\n");
+                        print(as[ha[j - 1]] + " DROPS IT TO " + as[ha[j - 4]] + "\n");
+                        g = ha[j - 4];
+                        g1 = ha[j - 1];
+                        g2 = ha[j - 2];
+                        z1 = 1;
+                        break;
+                }
+            } else {
+                switch (p) {
+                    case 1:
+                        print(bs[ha[j - 1]] + " HITS " + bs[ha[j - 2]] + " FLYING DOWN THE LEFT SIDE\n");
+                        g = ha[j - 2];
+                        g1 = ha[j - 1];
+                        g2 = 0;
+                        z1 = 3;
+                        break;
+                    case 2:
+                        print("IT'S A ' 3 ON 2 '!\n");
+                        print("ONLY " + as[4] + " AND " + as[5] + " ARE BACK.\n");
+                        print(bs[ha[j - 2]] + " GIVES OFF TO " + bs[ha[j - 1]] + "\n");
+                        print(bs[ha[j - 1]] + " DROPS TO " + bs[ha[j - 3]] + "\n");
+                        g = ha[j - 3];
+                        g1 = ha[j - 1];
+                        g2 = ha[j - 2];
+                        z1 = 2;
+                        break;
+                    case 3:
+                        print(" A '3 ON 2 ' WITH A ' TRAILER '!\n");
+                        print(bs[ha[j - 4]] + " GIVES TO " + bs[ha[j - 2]] + " WHO SHUFFLES IT OFF TO\n");
+                        print(bs[ha[j - 1]] + " WHO FIRES A WING TO WING PASS TO \n");
+                        print(bs[ha[j - 3]] + " AS HE CUTS IN ALONE!!\n");
+                        g = ha[j - 3];
+                        g1 = ha[j - 1];
+                        g2 = ha[j - 2];
+                        z1 = 1;
+                        break;
+                }
+            }
+            do {
+                print("SHOT");
+                s = parseInt(await input());
+            } while (s < 1 || s > 4) ;
+            if (c == 1)
+                print(as[g]);
+            else
+                print(bs[g]);
+            switch (s) {
+                case 1:
+                    print(" LET'S A BIG SLAP SHOT GO!!\n");
+                    z = 4;
+                    z += z1;
+                    break;
+                case 2:
+                    print(" RIPS A WRIST SHOT OFF\n");
+                    z = 2;
+                    z += z1;
+                    break;
+                case 3:
+                    print(" GETS A BACKHAND OFF\n");
+                    z = 3;
+                    z += z1;
+                    break;
+                case 4:
+                    print(" SNAPS OFF A SNAP SHOT\n");
+                    z = 2;
+                    z += z1;
+                    break;
+            }
+        }
+        do {
+            print("AREA");
+            a = parseInt(await input());
+        } while (a < 1 || a > 4) ;
+        if (c == 1)
+            s2++;
+        else
+            s3++;
+        a1 = Math.floor(4 * Math.random()) + 1;
+        if (a == a1) {
+            while (1) {
+                ha[20] = Math.floor(100 * Math.random()) + 1;
+                if (ha[20] % z != 0)
+                    break;
+                a2 = Math.floor(100 * Math.random()) + 1;
+                if (a2 % 4 == 0) {
+                    if (c == 1)
+                        print("SAVE " + bs[6] + " --  REBOUND\n");
+                    else
+                        print("SAVE " + as[6] + " --  FOLLOW up\n");
+                    continue;
+                } else {
+                    a1 = a + 1;  // So a != a1
+                }
+            }
+            if (ha[20] % z != 0) {
+                if (c == 1) {
+                    print("GOAL " + as[7] + "\n");
+                    ha[9]++;
+                } else {
+                    print("SCORE " + bs[7] + "\n");
+                    ha[8]++;
+                }
+                // Bells in origninal
+                print("\n");
+                print("SCORE: ");
+                if (ha[8] <= ha[9]) {
+                    print(as[7] + ": " + ha[9] + "\t" + bs[7] + ": " + ha[8] + "\n");
+                } else {
+                    print(bs[7] + ": " + ha[8] + "\t" + as[7] + ": " + ha[9] + "\n");
+                }
+                if (c == 1) {
+                    print("GOAL SCORED BY: " + as[g] + "\n");
+                    if (g1 != 0) {
+                        if (g2 != 0) {
+                            print(" ASSISTED BY: " + as[g1] + " AND " + as[g2] + "\n");
+                        } else {
+                            print(" ASSISTED BY: " + as[g1] + "\n");
+                        }
+                    } else {
+                        print(" UNASSISTED.\n");
+                    }
+                    ta[g]++;
+                    t1[g1]++;
+                    t1[g2]++;
+                    // 1540
+                } else {
+                    print("GOAL SCORED BY: " + bs[g] + "\n");
+                    if (g1 != 0) {
+                        if (g2 != 0) {
+                            print(" ASSISTED BY: " + bs[g1] + " AND " + bs[g2] + "\n");
+                        } else {
+                            print(" ASSISTED BY: " + bs[g1] + "\n");
+                        }
+                    } else {
+                        print(" UNASSISTED.\n");
+                    }
+                    t2[g]++;
+                    t3[g1]++;
+                    t3[g2]++;
+                    // 1540
+                }
+            }
+        }
+        if (a != a1) {
+            s1 = Math.floor(6 * Math.random()) + 1;
+            if (c == 1) {
+                switch (s1) {
+                    case 1:
+                        print("KICK SAVE AND A BEAUTY BY " + bs[6] + "\n");
+                        print("CLEARED OUT BY " + bs[3] + "\n");
+                        l--;
+                        continue;
+                    case 2:
+                        print("WHAT A SPECTACULAR GLOVE SAVE BY " + bs[6] + "\n");
+                        print("AND " + bs[6] + " GOLFS IT INTO THE CROWD\n");
+                        break;
+                    case 3:
+                        print("SKATE SAVE ON A LOW STEAMER BY " + bs[6] + "\n");
+                        l--;
+                        continue;
+                    case 4:
+                        print("PAD SAVE BY " + bs[6] + " OFF THE STICK\n");
+                        print("OF " + as[g] + " AND " + bs[6] + " COVERS UP\n");
+                        break;
+                    case 5:
+                        print("WHISTLES ONE OVER THE HEAD OF " + bs[6] + "\n");
+                        l--;
+                        continue;
+                    case 6:
+                        print(bs[6] + " MAKES A FACE SAVE!! AND HE IS HURT\n");
+                        print("THE DEFENSEMAN " + bs[5] + " COVERS UP FOR HIM\n");
+                        break;
+                }
+            } else {
+                switch (s1) {
+                    case 1:
+                        print("STICK SAVE BY " + as[6] +"\n");
+                        print("AND CLEARED OUT BY " + as[4] + "\n");
+                        l--;
+                        continue;
+                    case 2:
+                        print("OH MY GOD!! " + bs[g] + " RATTLES ONE OFF THE POST\n");
+                        print("TO THE RIGHT OF " + as[6] + " AND " + as[6] + " COVERS ");
+                        print("ON THE LOOSE PUCK!\n");
+                        break;
+                    case 3:
+                        print("SKATE SAVE BY " + as[6] + "\n");
+                        print(as[6] + " WHACKS THE LOOSE PUCK INTO THE STANDS\n");
+                        break;
+                    case 4:
+                        print("STICK SAVE BY " + as[6] + " AND HE CLEARS IT OUT HIMSELF\n");
+                        l--;
+                        continue;
+                    case 5:
+                        print("KICKED OUT BY " + as[6] + "\n");
+                        print("AND IT REBOUNDS ALL THE WAY TO CENTER ICE\n");
+                        l--;
+                        continue;
+                    case 6:
+                        print("GLOVE SAVE " + as[6] + " AND HE HANGS ON\n");
+                        break;
+                }
+            }
+        }
+        print("AND WE'RE READY FOR THE FACE-OFF\n");
+    }
+    // Bells chime
+    print("THAT'S THE SIREN\n");
+    print("\n");
+    print(tab(15) + "FINAL SCORE:\n");
+    if (ha[8] <= ha[9]) {
+        print(as[7] + ": " + ha[9] + "\t" + bs[7] + ": " + ha[8] + "\n");
+    } else {
+        print(bs[7] + ": " + ha[8] + "\t" + as[7] + ": " + ha[9] + "\n");
+    }
+    print("\n");
+    print(tab(10) + "SCORING SUMMARY\n");
+    print("\n");
+    print(tab(25) + as[7] + "\n");
+    print("\tNAME\tGOALS\tASSISTS\n");
+    print("\t----\t-----\t-------\n");
+    for (i = 1; i <= 5; i++) {
+        print("\t" + as[i] + "\t" + ta[i] + "\t" + t1[i] + "\n");
+    }
+    print("\n");
+    print(tab(25) + bs[7] + "\n");
+    print("\tNAME\tGOALS\tASSISTS\n");
+    print("\t----\t-----\t-------\n");
+    for (t = 1; t <= 5; t++) {
+        print("\t" + bs[t] + "\t" + t2[t] + "\t" + t3[t] + "\n");
+    }
+    print("\n");
+    print("SHOTS ON NET\n");
+    print(as[7] + ": " + s2 + "\n");
+    print(bs[7] + ": " + s3 + "\n");
+}
+
+main();

From b37e45ad5191e13430d4e758002647838af174e1 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sat, 27 Mar 2021 18:28:45 -0600
Subject: [PATCH 339/749] Ported HORSERACE to Javascript

---
 50 Horserace/javascript/horserace.html |   9 ++
 50 Horserace/javascript/horserace.js   | 213 +++++++++++++++++++++++++
 2 files changed, 222 insertions(+)
 create mode 100644 50 Horserace/javascript/horserace.html
 create mode 100644 50 Horserace/javascript/horserace.js

diff --git a/50 Horserace/javascript/horserace.html b/50 Horserace/javascript/horserace.html
new file mode 100644
index 00000000..2809ec39
--- /dev/null
+++ b/50 Horserace/javascript/horserace.html	
@@ -0,0 +1,9 @@
+
+
+HORSERACE
+
+
+

+
+
+
diff --git a/50 Horserace/javascript/horserace.js b/50 Horserace/javascript/horserace.js
new file mode 100644
index 00000000..882e66e6
--- /dev/null
+++ b/50 Horserace/javascript/horserace.js	
@@ -0,0 +1,213 @@
+// HORSERACE
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var sa = [];
+var ws = [];
+var da = [];
+var qa = [];
+var pa = [];
+var ma = [];
+var ya = [];
+var vs = [];
+
+// Main program
+async function main()
+{
+    print(tab(31) + "HORSERACE\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("WELCOME TO SOUTH PORTLAND HIGH RACETRACK\n");
+    print("                      ...OWNED BY LAURIE CHEVALIER\n");
+    print("DO YOU WANT DIRECTIONS");
+    str = await input();
+    if (str == "YES") {
+        print("UP TO 10 MAY PLAY.  A TABLE OF ODDS WILL BE PRINTED.  YOU\n");
+        print("MAY BET ANY + AMOUNT UNDER 100000 ON ONE HORSE.\n");
+        print("DURING THE RACE, A HORSE WILL BE SHOWN BY ITS\n");
+        print("NUMBER.  THE HORSES RACE DOWN THE PAPER!\n");
+        print("\n");
+    }
+    print("HOW MANY WANT TO BET");
+    c = parseInt(await input());
+    print("WHEN ? APPEARS,TYPE NAME\n");
+    for (a = 1; a <= c; a++) {
+        ws[a] = await input();
+    }
+    do {
+        print("\n");
+        print("HORSE\t\tNUMBERS\tODDS\n");
+        print("\n");
+        for (i = 1; i <= 8; i++) {
+            sa[i] = 0;
+        }
+        r = 0;
+        for (a = 1; a <= 8; a++) {
+            da[a] = Math.floor(10 * Math.random() + 1);
+        }
+        for (a = 1; a <= 8; a++) {
+            r = r + da[a];
+        }
+        vs[1] = "JOE MAN";
+        vs[2] = "L.B.J.";
+        vs[3] = "MR.WASHBURN";
+        vs[4] = "MISS KAREN";
+        vs[5] = "JOLLY";
+        vs[6] = "HORSE";
+        vs[7] = "JELLY DO NOT";
+        vs[8] = "MIDNIGHT";
+        for (n = 1; n <= 8; n++) {
+            print(vs[n] + "\t\t" + n + "\t" + (r / da[n]) + ":1\n");
+        }
+        print("--------------------------------------------------\n");
+        print("PLACE YOUR BETS...HORSE # THEN AMOUNT\n");
+        for (j = 1; j <= c; j++) {
+            while (1) {
+                print(ws[j]);
+                str = await input();
+                qa[j] = parseInt(str);
+                pa[j] = parseInt(str.substr(str.indexOf(",") + 1));
+                if (pa[j] < 1 || pa[j] >= 100000) {
+                    print("  YOU CAN'T DO THAT!\N");
+                } else {
+                    break;
+                }
+            }
+        }
+        print("\n");
+        print("1 2 3 4 5 6 7 8\n");
+        t = 0;
+        do {
+            print("XXXXSTARTXXXX\n");
+            for (i = 1; i <= 8; i++) {
+                m = i;
+                ma[i] = m;
+                ya[ma[i]] = Math.floor(100 * Math.random() + 1);
+                if (ya[ma[i]] < 10) {
+                    ya[ma[i]] = 1;
+                    continue;
+                }
+                s = Math.floor(r / da[i] + 0.5);
+                if (ya[ma[i]] < s + 17) {
+                    ya[ma[i]] = 2;
+                    continue;
+                }
+                if (ya[ma[i]] < s + 37) {
+                    ya[ma[i]] = 3;
+                    continue;
+                }
+                if (ya[ma[i]] < s + 57) {
+                    ya[ma[i]] = 4;
+                    continue;
+                }
+                if (ya[ma[i]] < s + 77) {
+                    ya[ma[i]] = 5;
+                    continue;
+                }
+                if (ya[ma[i]] < s + 92) {
+                    ya[ma[i]] = 6;
+                    continue;
+                }
+                ya[ma[i]] = 7;
+            }
+            m = i;
+            for (i = 1; i <= 8; i++) {
+                sa[ma[i]] = sa[ma[i]] + ya[ma[i]];
+            }
+            i = 1;
+            for (l = 1; l <= 8; l++) {
+                for (i = 1; i <= 8 - l; i++) {
+                    if (sa[ma[i]] < sa[ma[i + 1]])
+                        continue;
+                    h = ma[i];
+                    ma[i] = ma[i + 1];
+                    ma[i + 1] = h;
+                }
+            }
+            t = sa[ma[8]];
+            for (i = 1; i <= 8; i++) {
+                b = sa[ma[i]] - sa[ma[i - 1]];
+                if (b != 0) {
+                    for (a = 1; a <= b; a++) {
+                        print("\n");
+                        if (sa[ma[i]] > 27)
+                            break;
+                    }
+                    if (a <= b)
+                        break;
+                }
+                print(" " + ma[i] + " ");
+            }
+            for (a = 1; a < 28 - t; a++) {
+                print("\n");
+            }
+            print("XXXXFINISHXXXX\n");
+            print("\n");
+            print("\n");
+            print("---------------------------------------------\n");
+            print("\n");
+        } while (t < 28) ;
+        print("THE RACE RESULTS ARE:\n");
+        z9 = 1;
+        for (i = 8; i >= 1; i--) {
+            f = ma[i];
+            print("\n");
+            print("" + z9 + " PLACE HORSE NO. " + f + " AT " + (r / da[f]) + ":1\n");
+            z9++;
+        }
+        for (j = 1; j <= c; j++) {
+            if (qa[j] != ma[8])
+                continue;
+            n = qa[j];
+            print("\n");
+            print(ws[j] + " WINS $" + (r / da[n]) * pa[j] + "\n");
+        }
+        print("DO YOU WANT TO BET ON THE NEXT RACE ?\n");
+        print("YES OR NO");
+        str = await input();
+    } while (str == "YES") ;
+}
+
+main();

From 35b9cae30cd17d2f52d36502ae428c30d853365c Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Sun, 28 Mar 2021 16:14:22 -0600
Subject: [PATCH 340/749] Ported SALVO to Javascript

---
 77 Salvo/javascript/salvo.html |   9 +
 77 Salvo/javascript/salvo.js   | 504 +++++++++++++++++++++++++++++++++
 2 files changed, 513 insertions(+)
 create mode 100644 77 Salvo/javascript/salvo.html
 create mode 100644 77 Salvo/javascript/salvo.js

diff --git a/77 Salvo/javascript/salvo.html b/77 Salvo/javascript/salvo.html
new file mode 100644
index 00000000..25752f0f
--- /dev/null
+++ b/77 Salvo/javascript/salvo.html	
@@ -0,0 +1,9 @@
+
+
+SALVO
+
+
+

+
+
+
diff --git a/77 Salvo/javascript/salvo.js b/77 Salvo/javascript/salvo.js
new file mode 100644
index 00000000..b75f5088
--- /dev/null
+++ b/77 Salvo/javascript/salvo.js	
@@ -0,0 +1,504 @@
+// SALVO
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var aa = [];
+var ba = [];
+var ca = [];
+var da = [];
+var ea = [];
+var fa = [];
+var ga = [];
+var ha = [];
+var ka = [];
+var w;
+var r3;
+var x;
+var y;
+var v;
+var v2;
+
+function sgn(k)
+{
+    if (k < 0)
+        return -1;
+    if (k > 0)
+        return 1;
+    return 0;
+}
+
+function fna(k)
+{
+    return (5 - k) * 3 - 2 * Math.floor(k / 4) + sgn(k - 1) - 1;
+}
+
+function fnb(k)
+{
+    return k + Math.floor(k / 4) - sgn(k - 1);
+}
+
+function generate_random()
+{
+    x = Math.floor(Math.random() * 10 + 1);
+    y = Math.floor(Math.random() * 10 + 1);
+    v = Math.floor(3 * Math.random() - 1);
+    v2 = Math.floor(3 * Math.random() - 1);
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "SALVO\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    z8 = 0;
+    for (w = 1; w <= 12; w++) {
+        ea[w] = -1;
+        ha[w] = -1;
+    }
+    for (x = 1; x <= 10; x++) {
+        ba[x] = [];
+        ka[x] = [];
+        for (y = 1; y <= 10; y++) {
+            ba[x][y] = 0;
+            ka[x][y] = 0;
+        }
+    }
+    for (x = 1; x <= 12; x++) {
+        fa[x] = 0;
+        ga[x] = 0;
+    }
+    for (x = 1; x <= 10; x++) {
+        aa[x] = [];
+        for (y = 1; y <= 10; y++) {
+            aa[x][y] = 0;
+        }
+    }
+    u6 = 0;
+    for (k = 4; k >= 1; k--) {
+        do {
+            generate_random();
+        } while (v + v2 + v * v2 == 0 || y + v * fnb(k) > 10 || y + v * fnb(k) < 1 || x + v2 * fnb(k) > 10 || x + v2 * fnb(k) < 1) ;
+        u6++;
+        if (u6 > 25) {
+            for (x = 1; x <= 10; x++) {
+                aa[x] = [];
+                for (y = 1; y <= 10; y++) {
+                    aa[x][y] = 0;
+                }
+            }
+            u6 = 0;
+            k = 5;
+            continue;
+        }
+        for (z = 0; z <= fnb(k); z++) {
+            fa[z + fna(k)] = x + v2 * z;
+            ga[z + fna(k)] = y + v * z;
+        }
+        u8 = fna(k);
+        if (u8 <= u8 + fnb(k)) {
+            retry = false;
+            for (z2 = u8; z2 <= u8 + fnb(k); z2++) {
+                if (u8 >= 2) {
+                    for (z3 = 1; z3 < u8 - 1; z3++) {
+                        if (Math.sqrt(Math.pow((fa[z3] - fa[z2]), 2)) + Math.pow((ga[z3] - ga[z2]), 2) < 3.59) {
+                            retry = true;
+                            break;
+                        }
+                    }
+                    if (retry)
+                        break;
+                }
+            }
+            if (retry) {
+                k++;
+                continue;
+            }
+        }
+        for (z = 0; z <= fnb(k); z++) {
+            if (k - 1 < 0)
+                sk = -1;
+            else if (k - 1 > 0)
+                sk = 1;
+            else
+                sk = 0;
+            aa[fa[z + u8]][ga[z + u8]] = 0.5 + sk * (k - 1.5);
+        }
+        u6 = 0;
+    }
+    print("ENTER COORDINATES FOR...\n");
+    print("BATTLESHIP\n");
+    for (x = 1; x <= 5; x++) {
+        str = await input();
+        y = parseInt(str);
+        z = parseInt(str.substr(str.indexOf(",") + 1));
+        ba[y][z] = 3;
+    }
+    print("CRUISER\n");
+    for (x = 1; x <= 3; x++) {
+        str = await input();
+        y = parseInt(str);
+        z = parseInt(str.substr(str.indexOf(",") + 1));
+        ba[y][z] = 2;
+    }
+    print("DESTROYER
\n"); + for (x = 1; x <= 2; x++) { + str = await input(); + y = parseInt(str); + z = parseInt(str.substr(str.indexOf(",") + 1)); + ba[y][z] = 1; + } + print("DESTROYER\n"); + for (x = 1; x <= 2; x++) { + str = await input(); + y = parseInt(str); + z = parseInt(str.substr(str.indexOf(",") + 1)); + ba[y][z] = 0.5; + } + while (1) { + print("DO YOU WANT TO START"); + js = await input(); + if (js == "WHERE ARE YOUR SHIPS?") { + print("BATTLESHIP\n"); + for (z = 1; z <= 5; z++) + print(" " + fa[z] + " " + ga[z] + "\n"); + print("CRUISER\n"); + print(" " + fa[6] + " " + ga[6] + "\n"); + print(" " + fa[7] + " " + ga[7] + "\n"); + print(" " + fa[8] + " " + ga[8] + "\n"); + print("DESTROYER\n"); + print(" " + fa[9] + " " + ga[9] + "\n"); + print(" " + fa[10] + " " + ga[10] + "\n"); + print("DESTROYER\n"); + print(" " + fa[11] + " " + ga[11] + "\n"); + print(" " + fa[12] + " " + ga[12] + "\n"); + } else { + break; + } + } + c = 0; + print("DO YOU WANT TO SEE MY SHOTS"); + ks = await input(); + print("\n"); + if (js != "YES") + first_time = true; + else + first_time = false; + while (1) { + if (first_time) { + first_time = false; + } else { + if (js == "YES") { + c++; + print("\n"); + print("TURN " + c + "\n"); + } + a = 0; + for (w = 0.5; w <= 3; w += 0.5) { + loop1: + for (x = 1; x <= 10; x++) { + for (y = 1; y <= 10; y++) { + if (ba[x][y] == w) { + a += Math.floor(w + 0.5); + break loop1; + } + } + } + } + for (w = 1; w <= 7; w++) { + ca[w] = 0; + da[w] = 0; + fa[w] = 0; + ga[w] = 0; + } + p3 = 0; + for (x = 1; x <= 10; x++) { + for (y = 1; y <= 10; y++) { + if (aa[x][y] <= 10) + p3++; + } + } + print("YOU HAVE " + a + " SHOTS.\n"); + if (p3 < a) { + print("YOU HAVE MORE SHOTS THAN THERE ARE BLANK SQUARES.\n"); + print("YOU HAVE WON.\n"); + return; + } + if (a == 0) { + print("I HAVE WON.\n"); + return; + } + for (w = 1; w <= a; w++) { + while (1) { + str = await input(); + x = parseInt(str); + y = parseInt(str.substr(str.indexOf(",") + 1)); + if (x >= 1 && x <= 10 && y >= 1 && y <= 10) { + if (aa[x][y] > 10) { + print("YOU SHOT THERE BEFORE ON TURN " + (aa[x][y] - 10) + "\n"); + continue; + } + break; + } + print("ILLEGAL, ENTER AGAIN.\n"); + } + ca[w] = x; + da[w] = y; + } + for (w = 1; w <= a; w++) { + if (aa[ca[w]][da[w]] == 3) { + print("YOU HIT MY BATTLESHIP.\n"); + } else if (aa[ca[w]][da[w]] == 2) { + print("YOU HIT MY CRUISER.\n"); + } else if (aa[ca[w]][da[w]] == 1) { + print("YOU HIT MY DESTROYER.\n"); + } else if (aa[ca[w]][da[w]] == 0.5) { + print("YOU HIT MY DESTROYER.\n"); + } + aa[ca[w]][da[w]] = 10 + c; + } + } + a = 0; + if (js != "YES") { + c++; + print("\n"); + print("TURN " + c + "\n"); + } + a = 0; + for (w = 0.5; w <= 3; w += 0.5) { + loop2: + for (x = 1; x <= 10; x++) { + for (y = 1; y <= 10; y++) { + if (ba[x][y] == w) { + a += Math.floor(w + 0.5); + break loop2; + } + } + } + } + p3 = 0; + for (x = 1; x <= 10; x++) { + for (y = 1; y <= 10; y++) { + if (aa[x][y] <= 10) + p3++; + } + } + print("I HAVE " + a + " SHOTS.\n"); + if (p3 < a) { + print("I HAVE MORE SHOTS THAN BLANK SQUARES.\n"); + print("I HAVE WON.\n"); + return; + } + if (a == 0) { + print("YOU HAVE WON.\n"); + return; + } + for (w = 1; w <= 12; w++) { + if (ha[w] > 0) + break; + } + if (w <= 12) { + for (r = 1; r <= 10; r++) { + ka[r] = []; + for (s = 1; s <= 10; s++) + ka[r][s] = 0; + } + for (u = 1; u <= 12; u++) { + if (ea[u] >= 10) + continue; + for (r = 1; r <= 10; r++) { + for (s = 1; s <= 10; s++) { + if (ba[r][s] >= 10) { + ka[r][s] = -10000000; + } else { + for (m = sgn(1 - r); m <= sgn(10 - r); m++) { + for (n = sgn(1 - s); n <= sgn(10 - s); n++) { + if (n + m + n * m != 0 && ba[r + m][s + n] == ea[u]) + ka[r][s] += ea[u] - s * Math.floor(ha[u] + 0.5); + } + } + } + } + } + } + for (r = 1; r <= a; r++) { + fa[r] = r; + ga[r] = r; + } + for (r = 1; r <= 10; r++) { + for (s = 1; s <= 10; s++) { + q9 = 1; + for (m = 1; m <= a; m++) { + if (ka[fa[m]][ga[m]] < ka[fa[q9]][ga[q9]]) + q9 = m; + } + if ((r > a || r != s) && ka[r][s] >= ka[fa[q9]][ga[q9]]) { + for (m = 1; m <= a; m++) { + if (fa[m] != r) { + fa[q9] = r; + ga[q9] = s; + break; + } + if (ga[m] == s) + break; + } + } + } + } + } else { + // RANDOM + w = 0; + r3 = 0; + generate_random(); + r2 = 0; + while (1) { + r3++; + if (r3 > 100) { + generate_random(); + r2 = 0; + r3 = 1; + } + if (x > 10) { + x = 10 - Math.floor(Math.random() * 2.5); + } else if (x <= 0) { + x = 1 + Math.floor(Math.random() * 2.5); + } + if (y > 10) { + y = 10 - Math.floor(Math.random() * 2.5); + } else if (y <= 0) { + y = 1 + Math.floor(Math.random() * 2.5); + } + while (1) { + valid = true; + if (x < 1 || x > 10 || y < 1 || y > 10 || ba[x][y] > 10) { + valid = false; + } else { + for (q9 = 1; q9 <= w; q9++) { + if (fa[q9] == x && ga[q9] == y) { + valid = false; + break; + } + } + if (q9 > w) + w++; + } + if (valid) { + fa[w] = x; + ga[w] = y; + if (w == a) { + finish = true; + break; + } + } + if (r2 == 6) { + r2 = 0; + finish = false; + break; + } + x1 = [1,-1, 1,1,0,-1][r2]; + y1 = [1, 1,-3,1,2, 1][r2]; + r2++; + x += x1; + y += y1; + } + if (finish) + break; + } + } + if (ks == "YES") { + for (z5 = 1; z5 <= a; z5++) + print(" " + fa[z5] + " " + ga[z5] + "\n"); + } + for (w = 1; w <= a; w++) { + hit = false; + if (ba[fa[w]][ga[w]] == 3) { + print("I HIT YOUR BATTLESHIP.\n"); + hit = true; + } else if (ba[fa[w]][ga[w]] == 2) { + print("I HIT YOUR CRUISER.\n"); + hit = true; + } else if (ba[fa[w]][ga[w]] == 1) { + print("I HIT YOUR DESTROYER.\n"); + hit = true; + } else if (ba[fa[w]][ga[w]] == 0.5) { + print("I HIT YOUR DESTROYER.\n"); + hit = true; + } + if (hit) { + for (q = 1; q <= 12; q++) { + if (ea[q] != -1) + continue; + ea[q] = 10 + c; + ha[q] = ba[fa[w]][ga[w]]; + m3 = 0; + for (m2 = 1; m2 <= 12; m2++) { + if (ha[m2] == ha[q]) + m3++; + } + if (m3 == Math.floor(ha[q] + 0.5) + 1 + Math.floor(Math.floor(ha[q] + 0.5) / 3)) { + for (m2 = 1; m2 <= 12; m2++) { + if (ha[m2] == ha[q]) { + ea[m2] = -1; + ha[m2] = -1; + } + } + } + break; + } + if (q > 12) { + print("PROGRAM ABORT:\n"); + for (q = 1; q <= 12; q++) { + print("ea[" + q + "] = " + ea[q] + "\n"); + print("ha[" + q + "] = " + ha[q] + "\n"); + } + return; + } + } + ba[fa[w]][ga[w]] = 10 + c; + } + } +} + +main(); From c229e37fc96f85599b0f074091e6fdb7e4e2ebd9 Mon Sep 17 00:00:00 2001 From: nanochess Date: Sun, 28 Mar 2021 21:28:48 -0600 Subject: [PATCH 341/749] Ported STOCKMARKET to Javascript --- 83 Stock Market/javascript/stockmarket.html | 9 + 83 Stock Market/javascript/stockmarket.js | 317 ++++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 83 Stock Market/javascript/stockmarket.html create mode 100644 83 Stock Market/javascript/stockmarket.js diff --git a/83 Stock Market/javascript/stockmarket.html b/83 Stock Market/javascript/stockmarket.html new file mode 100644 index 00000000..6a6188ef --- /dev/null +++ b/83 Stock Market/javascript/stockmarket.html @@ -0,0 +1,9 @@ + + +STOCKMARKET + + +

+
+
+
diff --git a/83 Stock Market/javascript/stockmarket.js b/83 Stock Market/javascript/stockmarket.js
new file mode 100644
index 00000000..fbcbd8a5
--- /dev/null
+++ b/83 Stock Market/javascript/stockmarket.js	
@@ -0,0 +1,317 @@
+// STOCKMARKET
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var sa = [];
+var pa = [];
+var za = [];
+var ca = [];
+var i1;
+var n1;
+var e1;
+var i2;
+var n2;
+var e2;
+var x1;
+var w3;
+var t8;
+var a;
+var s4;
+
+// New stock values - subroutine
+function randomize_initial()
+{
+    // RANDOMLY PRODUCE NEW STOCK VALUES BASED ON PREVIOUS
+    // DAY'S VALUES
+    // N1,N2 ARE RANDOM NUMBERS OF DAYS WHICH RESPECTIVELY
+    // DETERMINE WHEN STOCK I1 WILL INCREASE 10 PTS. AND STOCK
+    // I2 WILL DECREASE 10 PTS.
+    // IF N1 DAYS HAVE PASSED, PICK AN I1, SET E1, DETERMINE NEW N1
+    if (n1 <= 0) {
+        i1 = Math.floor(4.99 * Math.random() + 1);
+        n1 = Math.floor(4.99 * Math.random() + 1);
+        e1 = 1;
+    }
+    // IF N2 DAYS HAVE PASSED, PICK AN I2, SET E2, DETERMINE NEW N2
+    if (n2 <= 0) {
+        i2 = Math.floor(4.99 * Math.random() + 1);
+        n2 = Math.floor(4.99 * Math.random() + 1);
+        e2 = 1;
+    }
+    // DEDUCT ONE DAY FROM N1 AND N2
+    n1--;
+    n2--;
+    // LOOP THROUGH ALL STOCKS
+    for (i = 1; i <= 5; i++) {
+        x1 = Math.random();
+        if (x1 < 0.25) {
+            x1 = 0.25;
+        } else if (x1 < 0.5) {
+            x1 = 0.5;
+        } else if (x1 < 0.75) {
+            x1 = 0.75;
+        } else {
+            x1 = 0.0;
+        }
+        // BIG CHANGE CONSTANT:W3  (SET TO ZERO INITIALLY)
+        w3 = 0;
+        if (e1 >= 1 && Math.floor(i1 + 0.5) == Math.floor(i + 0.5)) {
+            // ADD 10 PTS. TO THIS STOCK;  RESET E1
+            w3 = 10;
+            e1 = 0;
+        }
+        if (e2 >= 1 && Math.floor(i2 + 0.5) == Math.floor(i + 0.5)) {
+            // SUBTRACT 10 PTS. FROM THIS STOCK;  RESET E2
+            w3 -= 10;
+            e2 = 0;
+        }
+        // C(I) IS CHANGE IN STOCK VALUE
+        ca[i] = Math.floor(a * sa[i]) + x1 + Math.floor(3 - 6 * Math.random() + 0.5) + w3;
+        ca[i] = Math.floor(100 * ca[i] + 0.5) / 100;
+        sa[i] += ca[i];
+        if (sa[i] <= 0) {
+            ca[i] = 0;
+            sa[i] = 0;
+        } else {
+            sa[i] = Math.floor(100 * sa[i] + 0.5) / 100;
+        }
+    }
+    // AFTER T8 DAYS RANDOMLY CHANGE TREND SIGN AND SLOPE
+    if (--t8 < 1) {
+        // RANDOMLY CHANGE TREND SIGN AND SLOPE (A), AND DURATION
+        // OF TREND (T8)
+        t8 = Math.floor(4.99 * Math.random() + 1);
+        a = Math.floor((Math.random() / 10) * 100 + 0.5) / 100;
+        s4 = Math.random();
+        if (s4 > 0.5)
+            a = -a;
+    }
+}
+
+// Main program
+async function main()
+{
+    print(tab(30) + "STOCK MARKET\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    // STOCK MARKET SIMULATION     -STOCK-
+    // REVISED 8/18/70 (D. PESSEL, L. BRAUN, C. LOSIK)
+    // IMP VRBLS: A-MRKT TRND SLP; B5-BRKRGE FEE; C-TTL CSH ASSTS;
+    // C5-TTL CSH ASSTS (TEMP); C(I)-CHNG IN STK VAL; D-TTL ASSTS;
+    // E1,E2-LRG CHNG MISC; I-STCK #; I1,I2-STCKS W LRG CHNG;
+    // N1,N2-LRG CHNG DAY CNTS; P5-TTL DAYS PRCHSS; P(I)-PRTFL CNTNTS;
+    // Q9-NEW CYCL?; S4-SGN OF A; S5-TTL DYS SLS; S(I)-VALUE/SHR;
+    // T-TTL STCK ASSTS; T5-TTL VAL OF TRNSCTNS;
+    // W3-LRG CHNG; X1-SMLL CHNG(<$1); Z4,Z5,Z6-NYSE AVE.; Z(I)-TRNSCT
+    // SLOPE OF MARKET TREND:A  (SAME FOR ALL STOCKS)
+    x = 1;
+    a = Math.floor(Math.random() / 10 * 100 + 0.5) / 100;
+    t5 = 0;
+    x9 = 0;
+    n1 = 0;
+    n2 = 0;
+    e1 = 0;
+    e2 = 0;
+    // INTRODUCTION
+    print("DO YOU WANT THE INSTRUCTIONS (YES-TYPE 1, NO-TYPE 0)");
+    z9 = parseInt(await input());
+    print("\n");
+    print("\n");
+    if (z9 >= 1) {
+        print("THIS PROGRAM PLAYS THE STOCK MARKET.  YOU WILL BE GIVEN\n");
+        print("$10,000 AND MAY BUY OR SELL STOCKS.  THE STOCK PRICES WILL\n");
+        print("BE GENERATED RANDOMLY AND THEREFORE THIS MODEL DOES NOT\n");
+        print("REPRESENT EXACTLY WHAT HAPPENS ON THE EXCHANGE.  A TABLE\n");
+        print("OF AVAILABLE STOCKS, THEIR PRICES, AND THE NUMBER OF SHARES\n");
+        print("IN YOUR PORTFOLIO WILL BE PRINTED.  FOLLOWING THIS, THE\n");
+        print("INITIALS OF EACH STOCK WILL BE PRINTED WITH A QUESTION\n");
+        print("MARK.  HERE YOU INDICATE A TRANSACTION.  TO BUY A STOCK\n");
+        print("TYPE +NNN, TO SELL A STOCK TYPE -NNN, WHERE NNN IS THE\n");
+        print("NUMBER OF SHARES.  A BROKERAGE FEE OF 1% WILL BE CHARGED\n");
+        print("ON ALL TRANSACTIONS.  NOTE THAT IF A STOCK'S VALUE DROPS\n");
+        print("TO ZERO IT MAY REBOUND TO A POSITIVE VALUE AGAIN.  YOU\n");
+        print("HAVE $10,000 TO INVEST.  USE INTEGERS FOR ALL YOUR INPUTS.\n");
+        print("(NOTE:  TO GET A 'FEEL' FOR THE MARKET RUN FOR AT LEAST\n");
+        print("10 DAYS)\n");
+        print("-----GOOD LUCK!-----\n");
+    }
+    // GENERATION OF STOCK TABLE: INPUT REQUESTS
+    // INITIAL STOCK VALUES
+    sa[1] = 100;
+    sa[2] = 85;
+    sa[3] = 150;
+    sa[4] = 140;
+    sa[5] = 110;
+    // INITIAL T8 - # DAYS FOR FIRST TREND SLOPE (A)
+    t8 = Math.floor(4.99 * Math.random() + 1);
+    // RANDOMIZE SIGN OF FIRST TREND SLOPE (A)
+    if (Math.random() <= 0.5)
+        a -= a;
+    // RANDOMIZE INITIAL VALUES
+    randomize_initial();
+    // INITIAL PORTFOLIO CONTENTS
+    for (i = 1; i <= 5; i++) {
+        pa[i] = 0;
+        za[i] = 0;
+    }
+    print("\n");
+    print("\n");
+    // INITIALIZE CASH ASSETS:C
+    c = 10000;
+    z5 = 0;
+    // PRINT INITIAL PORTFOLIO
+    print("STOCK\t \t\t\tINITIALS\tPRICE/SHARE\n");
+    print("INT. BALLISTIC MISSILES\t\t  IBM\t\t" + sa[1] + "\n");
+    print("RED CROSS OF AMERICA\t\t  RCA\t\t" + sa[2] + "\n");
+    print("LICHTENSTEIN, BUMRAP & JOKE\t  LBJ\t\t" + sa[3] + "\n");
+    print("AMERICAN BANKRUPT CO.\t\t  ABC\t\t" + sa[4] + "\n");
+    print("CENSURED BOOKS STORE\t\t  CBS\t\t" + sa[5] + "\n");
+    while (1) {
+        print("\n");
+        // NYSE AVERAGE:Z5; TEMP. VALUE:Z4; NET CHANGE:Z6
+        z4 = z5;
+        z5 = 0;
+        t = 0;
+        for (i = 1; i <= 5; i++) {
+            z5 += sa[i];
+            t += sa[i] * pa[i];
+        }
+        z5 = Math.floor(100 * (z5 / 5) + 0.5) / 100;
+        z6 = Math.floor((z5 - z4) * 100 + 0.5) / 100;
+        // TOTAL ASSETS:D
+        d = t + c;
+        if (x9 <= 0) {
+            print("NEW YORK STOCK EXCHANGE AVERAGE: " + z5 + "\n");
+        } else {
+            print("NEW YORK STOCK EXCHANGE AVERAGE: " + z5 + " NET CHANGE " + z6 + "\n");
+        }
+        print("\n");
+        t = Math.floor(100 * t + 0.5) / 100;
+        print("TOTAL STOCK ASSETS ARE   $" + t + "\n");
+        c = Math.floor(100 * c + 0.5) / 100;
+        print("TOTAL CASH ASSETS ARE    $" + c + "\n");
+        d = Math.floor(100 * d + 0.5) / 100;
+        print("TOTAL ASSETS ARE         $" + d + "\n");
+        print("\n");
+        if (x9 != 0) {
+            print("DO YOU WISH TO CONTINUE (YES-TYPE 1, NO-TYPE 0)");
+            q9 = parseInt(await input());
+            if (q9 < 1) {
+                print("HOPE YOU HAD FUN!!\n");
+                return;
+            }
+        }
+        // INPUT TRANSACTIONS
+        while (1) {
+            print("WHAT IS YOUR TRANSACTION IN\n");
+            print("IBM");
+            za[1] = parseInt(await input());
+            print("RCA");
+            za[2] = parseInt(await input());
+            print("LBJ");
+            za[3] = parseInt(await input());
+            print("ABC");
+            za[4] = parseInt(await input());
+            print("CBS");
+            za[5] = parseInt(await input());
+            print("\n");
+            // TOTAL DAY'S PURCHASES IN $:P5
+            p5 = 0;
+            // TOTAL DAY'S SALES IN $:S5
+            s5 = 0;
+            for (i = 1; i <= 5; i++) {
+                za[i] = Math.floor(za[i] + 0.5);
+                if (za[i] > 0) {
+                    p5 += za[i] * sa[i];
+                } else {
+                    s5 -= za[i] * sa[i];
+                    if (-za[i] > pa[i]) {
+                        print("YOU HAVE OVERSOLD A STOCK; TRY AGAIN.\n");
+                        break;
+                    }
+                }
+            }
+            if (i <= 5)
+                contine;
+            // TOTAL VALUE OF TRANSACTIONS:T5
+            t5 = p5 + s5;
+            // BROKERAGE FEE:B5
+            b5 = Math.floor(0.01 * t5 * 100 + 0.5) / 100;
+            // CASH ASSETS=OLD CASH ASSETS-TOTAL PURCHASES
+            // -BROKERAGE FEES+TOTAL SALES:C5
+            c5 = c - p5 - b5 + s5;
+            if (c5 < 0) {
+                print("YOU HAVE USED $" + (-c5) + " MORE THAN YOU HAVE.\n");
+                continue;
+            }
+            break;
+        }
+        c = c5;
+        // CALCULATE NEW PORTFOLIO
+        for (i = 1; i <= 5; i++) {
+            pa[i] += za[i];
+        }
+        // CALCULATE NEW STOCK VALUES
+        randomize_initial();
+        // PRINT PORTFOLIO
+        // BELL RINGING-DIFFERENT ON MANY COMPUTERS
+        print("\n");
+        print("**********     END OF DAY'S TRADING     **********\n");
+        print("\n");
+        print("\n");
+        if (x9 >= 1) ;
+        print("STOCK\tPRICE/SHARE\tHOLDINGS\tVALUE\tNET PRICE CHANGE\n");
+        print("IBM\t" + sa[1] + "\t\t" + pa[1] + "\t\t" + sa[1] * pa[1] + "\t" + ca[1] + "\n");
+        print("RCA\t" + sa[2] + "\t\t" + pa[2] + "\t\t" + sa[2] * pa[2] + "\t" + ca[2] + "\n");
+        print("LBJ\t" + sa[3] + "\t\t" + pa[3] + "\t\t" + sa[3] * pa[3] + "\t" + ca[3] + "\n");
+        print("ABC\t" + sa[4] + "\t\t" + pa[4] + "\t\t" + sa[4] * pa[4] + "\t" + ca[4] + "\n");
+        print("CBS\t" + sa[5] + "\t\t" + pa[5] + "\t\t" + sa[5] * pa[5] + "\t" + ca[5] + "\n");
+        x9 = 1;
+        print("\n");
+        print("\n");
+    }
+}
+
+main();

From 1924d652fef0c5e62ebf5308f4a38034bd306239 Mon Sep 17 00:00:00 2001
From: nanochess 
Date: Mon, 29 Mar 2021 22:58:47 -0600
Subject: [PATCH 342/749] Ported POKER to Javascript (final 94th program
 ported)

---
 71 Poker/javascript/poker.html |   9 +
 71 Poker/javascript/poker.js   | 751 +++++++++++++++++++++++++++++++++
 2 files changed, 760 insertions(+)
 create mode 100644 71 Poker/javascript/poker.html
 create mode 100644 71 Poker/javascript/poker.js

diff --git a/71 Poker/javascript/poker.html b/71 Poker/javascript/poker.html
new file mode 100644
index 00000000..c2abd411
--- /dev/null
+++ b/71 Poker/javascript/poker.html	
@@ -0,0 +1,9 @@
+
+
+POKER
+
+
+

+
+
+
diff --git a/71 Poker/javascript/poker.js b/71 Poker/javascript/poker.js
new file mode 100644
index 00000000..105da0fa
--- /dev/null
+++ b/71 Poker/javascript/poker.js	
@@ -0,0 +1,751 @@
+// POKER
+//
+// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
+//
+
+function print(str)
+{
+    document.getElementById("output").appendChild(document.createTextNode(str));
+}
+
+function input()
+{
+    var input_element;
+    var input_str;
+    
+    return new Promise(function (resolve) {
+                       input_element = document.createElement("INPUT");
+                       
+                       print("? ");
+                       input_element.setAttribute("type", "text");
+                       input_element.setAttribute("length", "50");
+                       document.getElementById("output").appendChild(input_element);
+                       input_element.focus();
+                       input_str = undefined;
+                       input_element.addEventListener("keydown", function (event) {
+                                                      if (event.keyCode == 13) {
+                                                      input_str = input_element.value;
+                                                      document.getElementById("output").removeChild(input_element);
+                                                      print(input_str);
+                                                      print("\n");
+                                                      resolve(input_str);
+                                                      }
+                                                      });
+                       });
+}
+
+function tab(space)
+{
+    var str = "";
+    while (space-- > 0)
+        str += " ";
+    return str;
+}
+
+var aa = [];
+var ba = [];
+var b;
+var c;
+var d;
+var g;
+var i;
+var k;
+var m;
+var n;
+var p;
+var s;
+var u;
+var v;
+var x;
+var z;
+var hs;
+var is;
+var js;
+var ks;
+
+function fna(x)
+{
+    return Math.floor(10 * Math.random());
+}
+
+function fnb(x)
+{
+    return x % 100;
+}
+
+function im_busted()
+{
+    print("I'M BUSTED.  CONGRATULATIONS!\n");
+}
+
+// 1740
+function deal_card()
+{
+    while (1) {
+        aa[z] = 100 * Math.floor(4 * Math.random()) + Math.floor(100 * Math.random());
+        if (Math.floor(aa[z] / 100) > 3)    // Invalid suit
+            continue;
+        if (aa[z] % 100 > 12) // Invalid number
+            continue;
+        if (z != 1) {
+            for (k = 1; k <= z - 1; k++) {
+                if (aa[z] == aa[k])
+                    break;
+            }
+            if (k <= z - 1) // Repeated card
+                continue;
+            if (z > 10) {
+                n = aa[u];
+                aa[u] = aa[z];
+                aa[z] = n;
+            }
+        }
+        return;
+    }
+}
+
+// 1850
+function show_cards()
+{
+    for (z = n; z <= n + 4; z++) {
+        print(" " + z + "--  ");
+        k = fnb(aa[z]);
+        show_number();
+        print(" OF");
+        k = Math.floor(aa[z] / 100);
+        show_suit();
+        if (z % 2 == 0)
+            print("\n");
+    }
+    print("\n");
+}
+
+// 1950
+function show_number()
+{
+    if (k == 9)
+        print("JACK");
+    if (k == 10)
+        print("QUEEN");
+    if (k == 11)
+        print("KING");
+    if (k == 12)
+        print("ACE");
+    if (k < 9)
+        print(" " + (k + 2));
+}
+
+// 2070
+function show_suit()
+{
+    if (k == 0)
+        print(" CLUBS\t");
+    if (k == 1)
+        print(" DIAMONDS\t");
+    if (k == 2)
+        print(" HEARTS\t");
+    if (k == 3)
+        print(" SPADES\t");
+}
+
+// 2170
+function evaluate_hand()
+{
+    u = 0;
+    for (z = n; z <= n + 4; z++) {
+        ba[z] = fnb(aa[z]);
+        if (z != n + 4) {
+            if (Math.floor(aa[z] / 100) == Math.floor(aa[z + 1] / 100))
+                u++;
+        }
+    }
+    if (u == 4) {
+        x = 11111;
+        d = aa[n];
+        hs = "A FLUS";
+        is = "H IN";
+        u = 15;
+        return;
+    }
+    for (z = n; z <= n + 3; z++) {
+        for (k = z + 1; k <= n + 4; k++) {
+            if (ba[z] > ba[k]) {
+                x = aa[z];
+                aa[z] = aa[k];
+                ba[z] = ba[k];
+                aa[k] = x;
+                ba[k] = aa[k] - 100 * Math.floor(aa[k] / 100);
+            }
+        }
+    }
+    x = 0;
+    for (z = n; z <= n + 3; z++) {
+        if (ba[z] == ba[z + 1]) {
+            x = x + 11 * Math.pow(10, z - n);
+            d = aa[z];
+            if (u < 11) {
+                u = 11;
+                hs = "A PAIR";
+                is = " OF ";
+            } else if (u == 11) {
+                if (ba[z] == ba[z - 1]) {
+                    hs = "THREE";
+                    is = " ";
+                    u = 13;
+                } else {
+                    hs = "TWO P";
+                    is = "AIR, ";
+                    u = 12;
+                }
+            } else if (u == 12) {
+                u = 16;
+                hs = "FULL H";
+                is = "OUSE, ";
+            } else if (ba[z] == ba[z - 1]) {
+                u = 17;
+                hs = "FOUR";
+                is = " ";
+            } else {
+                u = 16;
+                hs = "FULL H";
+                is = "OUSE. ";
+            }
+        }
+    }
+    if (x == 0) {
+        if (ba[n] + 3 == ba[n + 3]) {
+            x = 1111;
+            u = 10;
+        }
+        if (ba[n + 1] + 3 == ba[n + 4]) {
+            if (u == 10) {
+                u = 14;
+                hs = "STRAIG";
+                is = "HT";
+                x = 11111;
+                d = aa[n + 4];
+                return;
+            }
+            u = 10;
+            x = 11110;
+        }
+    }
+    if (u < 10) {
+        d = aa[n + 4];
+        hs = "SCHMAL";
+        is = "TZ, ";
+        u = 9;
+        x = 11000;
+        i = 6;
+        return;
+    }
+    if (u == 10) {
+        if (i == 1)
+            i = 6;
+        return;
+    }
+    if (u > 12)
+        return;
+    if (fnb(d) > 6)
+        return;
+    i = 6;
+}
+
+function get_prompt(question, def)
+{
+    var str;
+    
+    str = window.prompt(question, def);
+    print(question + "? " + str + "\n");
+    return str;
+}
+
+function player_low_in_money()
+{
+    print("\n");
+    print("YOU CAN'T BET WITH WHAT YOU HAVEN'T GOT.\n");
+    str = "N";
+    if (o % 2 != 0) {
+        str = get_prompt("WOULD YOU LIKE TO SELL YOUR WATCH", "YES");
+        if (str.substr(0, 1) != "N") {
+            if (fna(0) < 7) {
+                print("I'LL GIVE YOU $75 FOR IT.\n");
+                s += 75;
+            } else {
+                print("THAT'S A PRETTY CRUMMY WATCH - I'LL GIVE YOU $25.\n");
+                s += 25;
+            }
+            o *= 2;
+        }
+    }
+    if (o % 3 == 0 && str.substr(0, 1) == "N") {
+        str = get_prompt("WILL YOU PART WITH THAT DIAMOND TIE TACK", "YES");
+        if (str.substr(0, 1) != "N") {
+            if (fna(0) < 6) {
+                print("YOU ARE NOW $100 RICHER.\n");
+                s += 100;
+            } else {
+                print("IT'S PASTE.  $25.\n");
+                s += 25;
+            }
+            o *= 3;
+        }
+    }
+    if (str.substr(0,1) == "N") {
+        print("YOUR WAD IS SHOT.  SO LONG, SUCKER!\n");
+        return true;
+    }
+    return false;
+}
+
+function computer_low_in_money()
+{
+    if (c - g - v >= 0)
+        return false;
+    if (g == 0) {
+        v = c;
+        return false;
+    }
+    if (c - g < 0) {
+        print("I'LL SEE YOU.\n");
+        k = g;
+        s = s - g;
+        c = c - k;
+        p = p + g + k;
+        return false;
+    }
+    js = "N";
+    if (o % 2 == 0) {
+        js = get_prompt("WOULD YOU LIKE TO BUY BACK YOUR WATCH FOR $50", "YES");
+        if (js.substr(0, 1) != "N") {
+            c += 50;
+            o /= 2;
+        }
+    }
+    if (js.substr(0, 1) == "N" && o % 3 == 0) {
+        js = get_prompt("WOULD YOU LIKE TO BUY BACK YOUR TIE TACK FOR $50", "YES");
+        if (js.substr(0, 1) != "N") {
+            c += 50;
+            o /= 3;
+        }
+    }
+    if (js.substr(0, 1) == "N") {
+        print("I'M BUSTED.  CONGRATULATIONS!\n");
+        return true;
+    }
+    return false;
+}
+
+function ask_for_bet()
+{
+    var forced;
+    
+    if (t != Math.floor(t)) {
+        if (k != 0 || g != 0 || t != 0.5) {
+            print("NO SMALL CHANGE, PLEASE.\n");
+            return 0;
+        }
+        return 1;
+    }
+    if (s - g - t < 0) {
+        if (player_low_in_money())
+            return 2;
+        return 0;
+    }
+    if (t == 0) {
+        i = 3;
+    } else if (g + t < k) {
+        print("IF YOU CAN'T SEE MY BET, THEN FOLD.\n");
+        return 0;
+    } else {
+        g += t;
+        if (g != k) {
+            forced = false;
+            if (z != 1) {
+                if (g <= 3 * z)
+                    forced = true;
+            } else {
+                if (g <= 5) {
+                    if (z < 2) {
+                        v = 5;
+                        if (g <= 3 * z)
+                            forced = true;
+                    }
+                } else {
+                    if (z == 1 || t > 25) {
+                        i = 4;
+                        print("I FOLD.\n");
+                        return 1;
+                    }
+                }
+            }
+            if (forced || z == 2) {
+                v = g - k + fna(0);
+                if (computer_low_in_money())
+                    return 2;
+                print("I'LL SEE YOU, AND RAISE YOU " + v + "\n");
+                k = g + v;
+                return 0;
+            }
+            print("I'LL SEE YOU.\n");
+            k = g;
+        }
+    }
+    s -= g;
+    c -= k;
+    p += g + k;
+    return 1;
+}
+
+function check_for_win(type)
+{
+    if (type == 0 && i == 3 || type == 1) {
+        print("\n");
+        print("I WIN.\n");
+        c += p;
+    } else if (type == 0 && i == 4 || type == 2) {
+        print("\n");
+        print("YOU WIN.\n");
+        s += p;
+    } else {
+        return 0;
+    }
+    print("NOW I HAVE $" + c + " AND YOU HAVE $" + s + "\n");
+    return 1;
+}
+
+function show_hand()
+{
+    print(hs + is);
+    if (hs == "A FLUS") {
+        k = Math.floor(k / 100);
+        print("\n");
+        show_suit();
+        print("\n");
+    } else {
+        k = fnb(k);
+        show_number();
+        if (hs == "SCHMAL" || hs == "STRAIG")
+            print(" HIGH\n");
+        else
+            print("'S\n");
+    }
+}
+
+// Main program
+async function main()
+{
+    print(tab(33) + "POKER\n");
+    print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
+    print("\n");
+    print("\n");
+    print("\n");
+    print("WELCOME TO THE CASINO.  WE EACH HAVE $200.\n");
+    print("I WILL OPEN THE BETTING BEFORE THE DRAW; YOU OPEN AFTER.\n");
+    print("TO FOLD BET 0; TO CHECK BET .5.\n");
+    print("ENOUGH TALK -- LET'S GET DOWN TO BUSINESS.\n");
+    print("\n");
+    o = 1;
+    c = 200;
+    s = 200;
+    z = 0;
+    while (1) {
+        p = 0;
+        //
+        print("\n");
+        if (c <= 5) {
+            im_busted();
+            return;
+        }
+        print("THE ANTE IS $5, I WILL DEAL:\n");
+        print("\n");
+        if (s <= 5) {
+            if (player_low_in_money())
+                return;
+        }
+        p += 10;
+        s -= 5;
+        c -= 5;
+        for (z = 1; z <= 10; z++)
+            deal_card();
+        print("YOUR HAND:\n");
+        n = 1;
+        show_cards();
+        n = 6;
+        i = 2;
+        evaluate_hand();
+        print("\n");
+        first = true;
+        if (i == 6) {
+            if (fna(0) > 7) {
+                x = 11100;
+                i = 7;
+                z = 23;
+            } else if (fna(0) > 7) {
+                x = 11110;
+                i = 7;
+                z = 23;
+            } else if (fna(0) < 2) {
+                x = 11111;
+                i = 7;
+                z = 23;
+            } else {
+                z = 1;
+                k = 0;
+                print("I CHECK.\n");
+                first = false;
+            }
+        } else {
+            if (u < 13) {
+                if (fna(0) < 2) {
+                    i = 7;
+                    z = 23;
+                } else {
+                    z = 0;
+                    k = 0;
+                    print("I CHECK.\n");
+                    first = false;
+                }
+            } else if (u > 16) {
+                z = 2;
+                if (fna(0) < 1)
+                    z = 35;
+            } else {
+                z = 35;
+            }
+        }
+        if (first) {
+            v = z + fna(0);
+            g = 0;
+            if (computer_low_in_money())
+                return;
+            print("I'LL OPEN WITH $" + v + "\n");
+            k = v;
+        }
+        g = 0;
+        do {
+            print("\nWHAT IS YOUR BET");
+            t = parseFloat(await input());
+            status = ask_for_bet();
+        } while (status == 0) ;
+        if (status == 2)
+            return;
+        status = check_for_win(0);
+        if (status == 1) {
+            while (1) {
+                print("DO YOU WISH TO CONTINUE");
+                hs = await input();
+                if (hs == "YES") {
+                    status = 1;
+                    break;
+                }
+                if (hs == "NO") {
+                    status = 2;
+                    break;
+                }
+                print("ANSWER YES OR NO, PLEASE.\n");
+            }
+        }
+        if (status == 2)
+            return;
+        if (status == 1) {
+            p = 0;
+            continue;
+        }
+        print("\n");
+        print("NOW WE DRAW -- HOW MANY CARDS DO YOU WANT");
+        while (1) {
+            t = parseInt(await input());
+            if (t != 0) {
+                z = 10;
+                if (t >= 4) {
+                    print("YOU CAN'T DRAW MORE THAN THREE CARDS.\n");
+                    continue;
+                }
+                print("WHAT ARE THEIR NUMBERS:\n");
+                for (q = 1; q <= t; q++) {
+                    u = parseInt(await input());
+                    z++;
+                    deal_card();
+                }
+                print("YOUR NEW HAND:\n");
+                n = 1;
+                show_cards();
+            }
+            break;
+        }
+        z = 10 + t;
+        for (u = 6; u <= 10; u++) {
+            if (Math.floor(x / Math.pow(10, u - 6)) != 10 * Math.floor(x / Math.pow(10, u - 5)))
+                break;
+            z++;
+            deal_card();
+        }
+        print("\n");
+        print("I AM TAKING " + (z - 10 - t) + " CARD");
+        if (z != 11 + t) {
+            print("S");
+        }
+        print("\n");
+        n = 6;
+        v = i;
+        i = 1;
+        evaluate_hand();
+        b = u;
+        m = d;
+        if (v == 7) {
+            z = 28;
+        } else if (i == 6) {
+            z = 1;
+        } else {
+            if (u < 13) {
+                z = 2;
+                if (fna(0) == 6)
+                    z = 19;
+            } else if (u < 16) {
+                z = 19;
+                if (fna(0) == 8)
+                    z = 11;
+            } else {
+                z = 2;
+            }
+        }
+        k = 0;
+        g = 0;
+        do {
+            print("\nWHAT IS YOUR BET");
+            t = parseFloat(await input());
+            status = ask_for_bet();
+        } while (status == 0) ;
+        if (status == 2)
+            return;
+        if (t == 0.5) {
+            if (v != 7 && i == 6) {
+                print("I'LL CHECK\n");
+            } else {
+                v = z + fna(0);
+                if (computer_low_in_money())
+                    return;
+                print("I'LL BET $" + v + "\n");
+                k = v;
+                do {
+                    print("\nWHAT IS YOUR BET");
+                    t = parseFloat(await input());
+                    status = ask_for_bet();
+                } while (status == 0) ;
+                if (status == 2)
+                    return;
+                status = check_for_win(0);
+                if (status == 1) {
+                    while (1) {
+                        print("DO YOU WISH TO CONTINUE");
+                        hs = await input();
+                        if (hs == "YES") {
+                            status = 1;
+                            break;
+                        }
+                        if (hs == "NO") {
+                            status = 2;
+                            break;
+                        }
+                        print("ANSWER YES OR NO, PLEASE.\n");
+                    }
+                }
+                if (status == 2)
+                    return;
+                if (status == 1) {
+                    p = 0;
+                    continue;
+                }
+            }
+        } else {
+            status = check_for_win(0);
+            if (status == 1) {
+                while (1) {
+                    print("DO YOU WISH TO CONTINUE");
+                    hs = await input();
+                    if (hs == "YES") {
+                        status = 1;
+                        break;
+                    }
+                    if (hs == "NO") {
+                        status = 2;
+                        break;
+                    }
+                    print("ANSWER YES OR NO, PLEASE.\n");
+                }
+            }
+            if (status == 2)
+                return;
+            if (status == 1) {
+                p = 0;
+                continue;
+            }
+        }
+        print("\n");
+        print("NOW WE COMPARE HANDS:\n");
+        js = hs;
+        ks = is;
+        print("MY HAND:\n");
+        n = 6;
+        show_cards();
+        n = 1;
+        evaluate_hand();
+        print("\n");
+        print("YOU HAVE ");
+        k = d;
+        show_hand();
+        hs = js;
+        is = ks;
+        k = m;
+        print("AND I HAVE ");
+        show_hand();
+        status = 0;
+        if (b > u) {
+            status = 1;
+        } else if (u > b) {
+            status = 2;
+        } else {
+            if (hs != "A FLUS") {
+                if (fnb(m) < fnb(d))
+                    status = 2;
+                else if (fnb(m) > fnb(d))
+                    status = 1;
+            } else {
+                if (fnb(m) > fnb(d))
+                    status = 1;
+                else if (fnb(d) > fnb(m))
+                    status = 2;
+            }
+            if (status == 0) {
+                print("THE HAND IS DRAWN.\n");
+                print("ALL $" + p + " REMAINS IN THE POT.\n");
+                continue;
+            }
+        }
+        status = check_for_win(status);
+        if (status == 1) {
+            while (1) {
+                print("DO YOU WISH TO CONTINUE");
+                hs = await input();
+                if (hs == "YES") {
+                    status = 1;
+                    break;
+                }
+                if (hs == "NO") {
+                    status = 2;
+                    break;
+                }
+                print("ANSWER YES OR NO, PLEASE.\n");
+            }
+        }
+        if (status == 2)
+            return;
+        if (status == 1) {
+            p = 0;
+            continue;
+        }
+    }
+}
+
+main();

From c11237b57d5476429eae1ef3e4cab47306af9449 Mon Sep 17 00:00:00 2001
From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com>
Date: Tue, 30 Mar 2021 19:08:57 -0400
Subject: [PATCH 343/749] Ported Orbit to Java.

---
 68 Orbit/java/Orbit.java | 193 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)
 create mode 100644 68 Orbit/java/Orbit.java

diff --git a/68 Orbit/java/Orbit.java b/68 Orbit/java/Orbit.java
new file mode 100644
index 00000000..4f4d9d01
--- /dev/null
+++ b/68 Orbit/java/Orbit.java	
@@ -0,0 +1,193 @@
+import java.lang.Integer;
+import java.lang.Math;
+import java.util.Scanner;
+
+/**
+ * Game of Orbit
+ * 

+ * Based on the BASIC game of Orbit here + * https://github.com/coding-horror/basic-computer-games/blob/main/68%20Orbit/orbit.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Orbit { + + private final Scanner scan; // For user input + + public Orbit() { + + scan = new Scanner(System.in); + + } // End of constructor Orbit + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(32) + "ORBIT"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + System.out.println("SOMEWHERE ABOVE YOUR PLANET IS A ROMULAN SHIP."); + System.out.println(""); + System.out.println("THE SHIP IS IN A CONSTANT POLAR ORBIT. ITS"); + System.out.println("DISTANCE FROM THE CENTER OF YOUR PLANET IS FROM"); + System.out.println("10,000 TO 30,000 MILES AND AT ITS PRESENT VELOCITY CAN"); + System.out.println("CIRCLE YOUR PLANET ONCE EVERY 12 TO 36 HOURS."); + System.out.println(""); + System.out.println("UNFORTUNATELY, THEY ARE USING A CLOAKING DEVICE SO"); + System.out.println("YOU ARE UNABLE TO SEE THEM, BUT WITH A SPECIAL"); + System.out.println("INSTRUMENT YOU CAN TELL HOW NEAR THEIR SHIP YOUR"); + System.out.println("PHOTON BOMB EXPLODED. YOU HAVE SEVEN HOURS UNTIL THEY"); + System.out.println("HAVE BUILT UP SUFFICIENT POWER IN ORDER TO ESCAPE"); + System.out.println("YOUR PLANET'S GRAVITY."); + System.out.println(""); + System.out.println("YOUR PLANET HAS ENOUGH POWER TO FIRE ONE BOMB AN HOUR."); + System.out.println(""); + System.out.println("AT THE BEGINNING OF EACH HOUR YOU WILL BE ASKED TO GIVE AN"); + System.out.println("ANGLE (BETWEEN 0 AND 360) AND A DISTANCE IN UNITS OF"); + System.out.println("100 MILES (BETWEEN 100 AND 300), AFTER WHICH YOUR BOMB'S"); + System.out.println("DISTANCE FROM THE ENEMY SHIP WILL BE GIVEN."); + System.out.println(""); + System.out.println("AN EXPLOSION WITHIN 5,000 MILES OF THE ROMULAN SHIP"); + System.out.println("WILL DESTROY IT."); + System.out.println(""); + System.out.println("BELOW IS A DIAGRAM TO HELP YOU VISUALIZE YOUR PLIGHT."); + System.out.println(""); + System.out.println(""); + System.out.println(" 90"); + System.out.println(" 0000000000000"); + System.out.println(" 0000000000000000000"); + System.out.println(" 000000 000000"); + System.out.println(" 00000 00000"); + System.out.println(" 00000 XXXXXXXXXXX 00000"); + System.out.println(" 00000 XXXXXXXXXXXXX 00000"); + System.out.println(" 0000 XXXXXXXXXXXXXXX 0000"); + System.out.println(" 0000 XXXXXXXXXXXXXXXXX 0000"); + System.out.println(" 0000 XXXXXXXXXXXXXXXXXXX 0000"); + System.out.println("180<== 00000 XXXXXXXXXXXXXXXXXXX 00000 ==>0"); + System.out.println(" 0000 XXXXXXXXXXXXXXXXXXX 0000"); + System.out.println(" 0000 XXXXXXXXXXXXXXXXX 0000"); + System.out.println(" 0000 XXXXXXXXXXXXXXX 0000"); + System.out.println(" 00000 XXXXXXXXXXXXX 00000"); + System.out.println(" 00000 XXXXXXXXXXX 00000"); + System.out.println(" 00000 00000"); + System.out.println(" 000000 000000"); + System.out.println(" 0000000000000000000"); + System.out.println(" 0000000000000"); + System.out.println(" 270"); + System.out.println(""); + System.out.println("X - YOUR PLANET"); + System.out.println("O - THE ORBIT OF THE ROMULAN SHIP"); + System.out.println(""); + System.out.println("ON THE ABOVE DIAGRAM, THE ROMULAN SHIP IS CIRCLING"); + System.out.println("COUNTERCLOCKWISE AROUND YOUR PLANET. DON'T FORGET THAT"); + System.out.println("WITHOUT SUFFICIENT POWER THE ROMULAN SHIP'S ALTITUDE"); + System.out.println("AND ORBITAL RATE WILL REMAIN CONSTANT."); + System.out.println(""); + System.out.println("GOOD LUCK. THE FEDERATION IS COUNTING ON YOU."); + + } // End of method showIntro + + private void startGame() { + + double bombDistance = 0; + int bombAltitude = 0; + int bombAngle = 0; + int deltaAngle = 0; + int hour = 0; + int shipAltitude = 0; + int shipAngle = 0; + int shipRate = 0; + String userResponse = ""; + + // Begin outer while loop + while (true) { + + shipAngle = (int) Math.floor(360 * Math.random()); + shipAltitude = (int) Math.floor(200 * Math.random() + 200); + shipRate = (int) Math.floor(20 * Math.random() + 10); + + hour = 0; + + // Begin time limit loop + while (hour < 7) { + + System.out.println(""); + System.out.println(""); + System.out.println("THIS IS HOUR " + (hour + 1) + ", AT WHAT ANGLE DO YOU WISH TO SEND"); + System.out.print("YOUR PHOTON BOMB? "); + bombAngle = Integer.parseInt(scan.nextLine()); + + System.out.print("HOW FAR OUT DO YOU WISH TO DETONATE IT? "); + bombAltitude = Integer.parseInt(scan.nextLine()); + + System.out.println(""); + System.out.println(""); + + // Update ship position + shipAngle += shipRate; + + // Handle full revolutions + if (shipAngle >= 360) { + shipAngle -= 360; + } + + deltaAngle = Math.abs(shipAngle - bombAngle); + + // Keep angle in upper quadrants + if (deltaAngle >= 180) { + deltaAngle = 360 - deltaAngle; + } + + bombDistance = Math.sqrt(shipAltitude * shipAltitude + bombAltitude * bombAltitude - 2 * shipAltitude + * bombAltitude * Math.cos(deltaAngle * Math.PI / 180)); + + System.out.format("YOUR PHOTON BOMB EXPLODED " + "%.5f" + "*10^2 MILES FROM THE\n", bombDistance); + System.out.println("ROMULAN SHIP."); + + // Win condition + if (bombDistance <= 50) { + System.out.println("YOU HAVE SUCCESFULLY COMPLETED YOUR MISSION."); + break; + } + + hour++; + + } // End time limit loop + + // Lose condition + if (hour == 7) { + System.out.println("YOU HAVE ALLOWED THE ROMULANS TO ESCAPE."); + } + + System.out.println("ANOTHER ROMULAN SHIP HAS GONE INTO ORBIT."); + System.out.print("DO YOU WISH TO TRY TO DESTROY IT? "); + userResponse = scan.nextLine(); + + if (!userResponse.toUpperCase().equals("YES")) { + System.out.println("GOOD BYE."); + break; + } + + } // End outer while loop + + } // End of method startGame + + public static void main(String[] args) { + + Orbit game = new Orbit(); + game.play(); + + } // End of method main + +} // End of class Orbit From 1d3819afd799d42e96d6fa687e4c1973a477c020 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Thu, 1 Apr 2021 16:52:25 -0600 Subject: [PATCH 344/749] Create number.pl Made with Perl! --- 66 Number/perl/number.pl | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 66 Number/perl/number.pl diff --git a/66 Number/perl/number.pl b/66 Number/perl/number.pl new file mode 100644 index 00000000..b76dc6e5 --- /dev/null +++ b/66 Number/perl/number.pl @@ -0,0 +1,39 @@ +#!/usr/bin/perl +use strict; + +print ' 'x 33 . "NUMBER\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; +print "YOU HAVE 100 POINTS. BY GUESSING NUMBERS FROM 1 TO 5, YOU\n"; +print "CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO\n"; +print "A RANDOM NUMBER SELECTED BY THE COMPUTER.\n"; print "\n"; +print "YOU OCCASIONALLY WILL GET A JACKPOT WHICH WILL DOUBLE(!)\n"; +print "YOUR POINT COUNT. YOU WIN WHEN YOU GET 500 POINTS.\n"; +print "\n"; my $P=100; + +Line12: +while ($P<500) { + print "GUESS A NUMBER FROM 1 TO 5? "; chomp(my $G = ); + my $R= &FNR(1); + my $S= &FNR(1); + my $T= &FNR(1); + my $U= &FNR(1); + my $V= &FNR(1); + if ($G eq $R) { $P=$P-5; } + if ($G eq $S) { $P=$P+5; } + if ($G eq $T) { $P=$P+$P; print "YOU HIT THE JACKPOT!!!\n"; } + if ($G eq $U) { $P=$P+1; } + if ($G eq $V) { $P=$P-($P*.5); } + if ($G<1 || $G>5) { redo; } + print "YOU HAVE $P POINTS.\n"; print "\n"; + } +print "!!!!YOU WIN!!!! WITH $P POINTS.\n"; +exit; + + +sub FNR { + my ($X)= @_; #Useless... + return int(5*rand(1)+1); + } + + From 6d12759f04c2eea83aa8e6f07615c1fd92c2cb2d Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Thu, 1 Apr 2021 16:54:00 -0600 Subject: [PATCH 345/749] Create nicomachus.pl Made with Perl! --- 64 Nicomachus/perl/nicomachus.pl | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 64 Nicomachus/perl/nicomachus.pl diff --git a/64 Nicomachus/perl/nicomachus.pl b/64 Nicomachus/perl/nicomachus.pl new file mode 100644 index 00000000..4ed2018f --- /dev/null +++ b/64 Nicomachus/perl/nicomachus.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl +use strict; + + +print ' 'x 33 . "NICOMA\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; +print "BOOMERANG PUZZLE FROM ARITHMETICA OF NICOMACHUS -- A.D. 90!\n"; + + +while (1) { + print "\n"; + print "PLEASE THINK OF A NUMBER BETWEEN 1 AND 100.\n"; + print "YOUR NUMBER DIVIDED BY 3 HAS A REMAINDER OF"; + print "? "; chomp(my $A = ); + print "YOUR NUMBER DIVIDED BY 5 HAS A REMAINDER OF"; + print "? "; chomp(my $B = ); + print "YOUR NUMBER DIVIDED BY 7 HAS A REMAINDER OF"; + print "? "; chomp(my $C = ); + print "\n"; + print "LET ME THINK A MOMENT...\n"; + print "\n"; + for (my $I=1; $I<=1500; $I++) { } + my $D= 70*$A+21*$B+15*$C; + + while ($D>105) { + $D= $D-105; + } + + print "YOUR NUMBER WAS $D, RIGHT"; + + my $Flag=0; + do { + print "? "; chomp($A = uc()); + print "\n"; + if ($A eq "YES") { print "HOW ABOUT THAT!!\n"; $Flag=1; } + if ($A eq "NO") { print "I FEEL YOUR ARITHMETIC IS IN ERROR.\n"; $Flag=1; } + if ($Flag==0) { print "EH? I DON'T UNDERSTAND '$A' TRY 'YES' OR 'NO'.\n"; } + } until ($Flag==1); + + print "\n"; + print "LET'S TRY ANOTHER.\n"; + } #goto Line20; +exit; + + From 2827e98cd393605443f69f1b60c41173e12d3338 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Thu, 1 Apr 2021 16:55:16 -0600 Subject: [PATCH 346/749] Create bullseye.pl Made with Perl! --- 18 Bullseye/perl/bullseye.pl | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 18 Bullseye/perl/bullseye.pl diff --git a/18 Bullseye/perl/bullseye.pl b/18 Bullseye/perl/bullseye.pl new file mode 100644 index 00000000..22405d30 --- /dev/null +++ b/18 Bullseye/perl/bullseye.pl @@ -0,0 +1,59 @@ +#!/usr/bin/perl +use strict; + + +print ' 'x 32 . "BULLSEYE\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; + +print "IN THIS GAME, UP TO 20 PLAYERS THROW DARTS AT A TARGET\n"; +print "WITH 10, 20, 30, AND 40 POINT ZONES. THE OBJECTIVE IS\n"; +print "TO GET 200 POINTS.\n\n"; + +print "THROW\t\tDESCRIPTION\t\tPROBABLE SCORE\n"; +print" 1\t\tFAST OVERARM\t\tBULLSEYE OR COMPLETE MISS\n"; +print" 2\t\tCONTROLLED OVERARM\t10, 20 OR 30 POINTS\n"; +print" 3\t\tUNDERARM\t\tANYTHING\n\n"; + +my @A; my $M=0; my $R=0; my @S; my @W; for (my $I=1; $I<=20; $I++) { $S[$I]= 0; } +print "HOW MANY PLAYERS? "; chomp(my $N = ); print "\n"; +for (my $I=1; $I<=$N; $I++) { + print "NAME OF PLAYER #$I? "; chomp($A[$I] = ); + } + +do { + $R= $R+1; print "\n"; print "ROUND $R---------\n"; + for (my $I=1; $I<=$N; $I++) { + my $Flag=0; + my $T; + do { + print "\n"; print "$A[$I]'S THROW? "; chomp($T = ); + if ($T<1 || $T>3) { print "INPUT 1, 2, OR 3!\n"; $Flag=0; } + else { $Flag=1; } + } until ($Flag==1); + + my $P1; my $P2; my $P3; my $P4; + if ($T==1) { $P1=.65; $P2=.55; $P3=.5; $P4=.5; } + if ($T==2) { $P1=.99; $P2=.77; $P3=.43; $P4=.01; } + if ($T==3) { $P1=.95; $P2=.75; $P3=.45; $P4=.05; } + + my $B=0; + my $U= rand(1); + if ($U>= $P1) { print "BULLSEYE!! 40 POINTS!\n"; $B=40; } + elsif ($U>= $P2) { print "30-POINT ZONE!\n"; $B=30; } + elsif ($U>= $P3) { print "20-POINT ZONE\n"; $B=20; } + elsif ($U>= $P4) { print "WHEW! 10 POINTS.\n"; $B=10; } + else { print "MISSED THE TARGET! TOO BAD.\n"; $B=0; } + $S[$I]= $S[$I]+$B; print "TOTAL SCORE =$S[$I]"; + } + + for (my $I=1; $I<=$N; $I++) { + if ($S[$I]>=200) { $M= $M+1; $W[$M]= $I; } + } + } until ($M!=0); + +print "\n"; print "WE HAVE A WINNER!!\n\n"; +for (my $I=1; $I<=$M; $I++) { print $A[$W[$I]]." SCORED ".$S[$W[$I]]." POINTS.\n"; } +print "\n"; print "THANKS FOR THE GAME.\n"; exit; + + From 01c701ee3a3a3bf0d0ec4c9736df951be34614f1 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Thu, 1 Apr 2021 21:11:24 -0400 Subject: [PATCH 347/749] Fixed random number range in Orbit.java. --- 68 Orbit/java/Orbit.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/68 Orbit/java/Orbit.java b/68 Orbit/java/Orbit.java index 4f4d9d01..13a8026b 100644 --- a/68 Orbit/java/Orbit.java +++ b/68 Orbit/java/Orbit.java @@ -111,11 +111,10 @@ public class Orbit { String userResponse = ""; // Begin outer while loop - while (true) { - - shipAngle = (int) Math.floor(360 * Math.random()); - shipAltitude = (int) Math.floor(200 * Math.random() + 200); - shipRate = (int) Math.floor(20 * Math.random() + 10); + while (true) { + shipAngle = (int) (361 * Math.random()); + shipAltitude = (int) (201 * Math.random() + 200); + shipRate = (int) (21 * Math.random() + 10); hour = 0; @@ -157,7 +156,7 @@ public class Orbit { // Win condition if (bombDistance <= 50) { - System.out.println("YOU HAVE SUCCESFULLY COMPLETED YOUR MISSION."); + System.out.println("YOU HAVE SUCCESSFULLY COMPLETED YOUR MISSION."); break; } From e2547fb4bb4d499127bbc3411f87a59ff213d638 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Thu, 1 Apr 2021 22:48:22 -0400 Subject: [PATCH 348/749] Ported '23 Matches' to Java. --- 93 23 Matches/java/TwentyThreeMatches.java | 163 +++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 93 23 Matches/java/TwentyThreeMatches.java diff --git a/93 23 Matches/java/TwentyThreeMatches.java b/93 23 Matches/java/TwentyThreeMatches.java new file mode 100644 index 00000000..46b12793 --- /dev/null +++ b/93 23 Matches/java/TwentyThreeMatches.java @@ -0,0 +1,163 @@ +import java.util.Scanner; +import java.lang.Math; + +/** + * Game of 23 Matches + *

+ * Based on the BASIC game of 23 Matches here + * https://github.com/coding-horror/basic-computer-games/blob/main/93%2023%20Matches/23matches.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class TwentyThreeMatches { + + private static final int MATCH_COUNT_START = 23; + + private static final int HEADS = 1; + + private final Scanner scan; // For user input + + public TwentyThreeMatches() { + + scan = new Scanner(System.in); + + } // End of constructor TwentyThreeMatches + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(30) + "23 MATCHES"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + System.out.println(" THIS IS A GAME CALLED '23 MATCHES'."); + System.out.println(""); + System.out.println("WHEN IT IS YOUR TURN, YOU MAY TAKE ONE, TWO, OR THREE"); + System.out.println("MATCHES. THE OBJECT OF THE GAME IS NOT TO HAVE TO TAKE"); + System.out.println("THE LAST MATCH."); + System.out.println(""); + System.out.println("LET'S FLIP A COIN TO SEE WHO GOES FIRST."); + System.out.println("IF IT COMES UP HEADS, I WILL WIN THE TOSS."); + System.out.println(""); + + } // End of method showIntro + + private void startGame() { + + int coinSide = (int) (3 * Math.random()); + int cpuRemoves = 0; + int matchesLeft = MATCH_COUNT_START; + int playerRemoves = 0; + + if (coinSide == HEADS) { + + System.out.println("HEADS! I WIN! HA! HA!"); + System.out.println("PREPARE TO LOSE, MEATBALL-NOSE!!"); + System.out.println(""); + System.out.println("I TAKE 2 MATCHES"); + + matchesLeft -= 2; + + } else { + + System.out.println("TAILS! YOU GO FIRST. "); + System.out.println(""); + + } + + // Begin outer while loop + while (true) { + + if (coinSide == HEADS) { + + System.out.println("THE NUMBER OF MATCHES IS NOW " + matchesLeft); + System.out.println(""); + System.out.println("YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES."); + + } + + coinSide = HEADS; + + System.out.print("HOW MANY DO YOU WISH TO REMOVE? "); + + // Begin match removal while loop + while (true) { + + playerRemoves = scan.nextInt(); + + // Handle invalid entries + if ((playerRemoves > 3) || (playerRemoves <= 0)) { + + System.out.println("VERY FUNNY! DUMMY!"); + System.out.println("DO YOU WANT TO PLAY OR GOOF AROUND?"); + System.out.print("NOW, HOW MANY MATCHES DO YOU WANT? "); + continue; + + } + + break; + + } // End match removal while loop + + matchesLeft -= playerRemoves; + + System.out.println("THERE ARE NOW " + matchesLeft + " MATCHES REMAINING."); + + // Win condition + if (matchesLeft <= 1) { + + // Win condition + System.out.println("YOU WON, FLOPPY EARS !"); + System.out.println("THINK YOU'RE PRETTY SMART !"); + System.out.println("LETS PLAY AGAIN AND I'LL BLOW YOUR SHOES OFF !!"); + System.out.println(""); + return; + + } else if ((matchesLeft >= 2) && (matchesLeft <= 4)) { + + cpuRemoves = matchesLeft - 1; + + } else { + + cpuRemoves = 4 - playerRemoves; + + } + + System.out.println("MY TURN ! I REMOVE " + cpuRemoves + " MATCHES"); + + matchesLeft -= cpuRemoves; + + // Lose condition + if (matchesLeft <= 1) { + + System.out.println(""); + System.out.println("YOU POOR BOOB! YOU TOOK THE LAST MATCH! I GOTCHA!!"); + System.out.println("HA ! HA ! I BEAT YOU !!!"); + System.out.println(""); + System.out.println("GOOD BYE LOSER!"); + return; + + } + + } // End outer while loop + + } // End of method startGame + + public static void main(String[] args) { + + TwentyThreeMatches game = new TwentyThreeMatches(); + game.play(); + + } // End of method main + +} // End of class TwentyThreeMatches From 74f758fd35eb27e4a0817531d7684448ca00920b Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 3 Apr 2021 02:21:06 -0400 Subject: [PATCH 349/749] Ported Hammurabi to C# --- 43 Hammurabi/csharp/Game.csproj | 8 + 43 Hammurabi/csharp/Hammurabi.sln | 25 +++ 43 Hammurabi/csharp/src/ActionResult.cs | 37 ++++ 43 Hammurabi/csharp/src/Controller.cs | 65 ++++++ 43 Hammurabi/csharp/src/GameResult.cs | 45 ++++ 43 Hammurabi/csharp/src/GameState.cs | 73 +++++++ 43 Hammurabi/csharp/src/GreatOffence.cs | 12 ++ 43 Hammurabi/csharp/src/PerformanceRating.cs | 14 ++ 43 Hammurabi/csharp/src/Program.cs | 51 +++++ 43 Hammurabi/csharp/src/Rules.cs | 207 +++++++++++++++++++ 43 Hammurabi/csharp/src/View.cs | 193 +++++++++++++++++ 11 files changed, 730 insertions(+) create mode 100644 43 Hammurabi/csharp/Game.csproj create mode 100644 43 Hammurabi/csharp/Hammurabi.sln create mode 100644 43 Hammurabi/csharp/src/ActionResult.cs create mode 100644 43 Hammurabi/csharp/src/Controller.cs create mode 100644 43 Hammurabi/csharp/src/GameResult.cs create mode 100644 43 Hammurabi/csharp/src/GameState.cs create mode 100644 43 Hammurabi/csharp/src/GreatOffence.cs create mode 100644 43 Hammurabi/csharp/src/PerformanceRating.cs create mode 100644 43 Hammurabi/csharp/src/Program.cs create mode 100644 43 Hammurabi/csharp/src/Rules.cs create mode 100644 43 Hammurabi/csharp/src/View.cs diff --git a/43 Hammurabi/csharp/Game.csproj b/43 Hammurabi/csharp/Game.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/43 Hammurabi/csharp/Game.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/43 Hammurabi/csharp/Hammurabi.sln b/43 Hammurabi/csharp/Hammurabi.sln new file mode 100644 index 00000000..feeae212 --- /dev/null +++ b/43 Hammurabi/csharp/Hammurabi.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31129.286 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{20599300-7C6E-48A2-AB24-EC7CCF224A5C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {20599300-7C6E-48A2-AB24-EC7CCF224A5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20599300-7C6E-48A2-AB24-EC7CCF224A5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20599300-7C6E-48A2-AB24-EC7CCF224A5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20599300-7C6E-48A2-AB24-EC7CCF224A5C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {89DBE213-C0F0-4ABA-BB2D-5D9AAED41FF6} + EndGlobalSection +EndGlobal diff --git a/43 Hammurabi/csharp/src/ActionResult.cs b/43 Hammurabi/csharp/src/ActionResult.cs new file mode 100644 index 00000000..58d4f3cb --- /dev/null +++ b/43 Hammurabi/csharp/src/ActionResult.cs @@ -0,0 +1,37 @@ +namespace Hammurabi +{ + ///

+ /// Enumerates the different possible outcomes of attempting the various + /// actions in the game. + /// + public enum ActionResult + { + /// + /// The action was a success. + /// + Success, + + /// + /// The action could not be completed because the city does not have + /// enough bushels of grain. + /// + InsufficientStores, + + /// + /// The action could not be completed because the city does not have + /// sufficient acreage. + /// + InsufficientLand, + + /// + /// The action could not be completed because the city does not have + /// sufficient population. + /// + InsufficientPopulation, + + /// + /// The requested action offended the city steward. + /// + Offense + } +} diff --git a/43 Hammurabi/csharp/src/Controller.cs b/43 Hammurabi/csharp/src/Controller.cs new file mode 100644 index 00000000..91d1b64f --- /dev/null +++ b/43 Hammurabi/csharp/src/Controller.cs @@ -0,0 +1,65 @@ +using System; + +namespace Hammurabi +{ + /// + /// Provides methods for reading input from the user. + /// + public static class Controller + { + /// + /// Continuously prompts the user to enter a number until he or she + /// enters a valid number and updates the game state. + /// + /// + /// The current game state. + /// + /// + /// Action that will display the prompt to the user. + /// + /// + /// The rule to invoke once input is retrieved. + /// + /// + /// The updated game state. + /// + public static GameState TryUntilSuccess( + GameState state, + Action prompt, + Func rule) + { + while (true) + { + prompt(); + + if (!Int32.TryParse(Console.ReadLine(), out var amount)) + { + View.ShowInvalidNumber(); + } + else + { + var (newState, result) = rule(state, amount); + + switch (result) + { + case ActionResult.InsufficientLand: + View.ShowInsufficientLand(state); + break; + case ActionResult.InsufficientPopulation: + View.ShowInsufficientPopulation(state); + break; + case ActionResult.InsufficientStores: + View.ShowInsufficientStores(state); + break; + case ActionResult.Offense: + // Not sure why we have to blow up the game here... + // Maybe this made sense in the 70's. + throw new GreatOffence(); + default: + return newState; + } + } + } + } + } +} diff --git a/43 Hammurabi/csharp/src/GameResult.cs b/43 Hammurabi/csharp/src/GameResult.cs new file mode 100644 index 00000000..23dfbe28 --- /dev/null +++ b/43 Hammurabi/csharp/src/GameResult.cs @@ -0,0 +1,45 @@ +namespace Hammurabi +{ + /// + /// Stores the final game result. + /// + public record GameResult + { + /// + /// Gets the player's performance rating. + /// + public PerformanceRating Rating { get; init; } + + /// + /// Gets the number of acres in the city per person. + /// + public int AcresPerPerson { get; init; } + + /// + /// Gets the number of people who starved the final year in office. + /// + public int FinalStarvation { get; init; } + + /// + /// Gets the total number of people who starved. + /// + public int TotalStarvation { get; init; } + + /// + /// Gets the average starvation rate per year (as a percentage + /// of population). + /// + public int AverageStarvationRate { get; init; } + + /// + /// Gets the number of people who want to assassinate the player. + /// + public int Assassins { get; init; } + + /// + /// Gets a flag indicating whether the player was impeached for + /// starving too many people. + /// + public bool WasImpeached { get; init; } + } +} diff --git a/43 Hammurabi/csharp/src/GameState.cs b/43 Hammurabi/csharp/src/GameState.cs new file mode 100644 index 00000000..3e2d1eb2 --- /dev/null +++ b/43 Hammurabi/csharp/src/GameState.cs @@ -0,0 +1,73 @@ +namespace Hammurabi +{ + /// + /// Stores the state of the game. + /// + public record GameState + { + /// + /// Gets the current game year. + /// + public int Year { get; init; } + + /// + /// Gets the city's population. + /// + public int Population { get; init; } + + /// + /// Gets the population increase this year. + /// + public int PopulationIncrease { get; init; } + + /// + /// Gets the number of people who starved. + /// + public int Starvation { get; init; } + + /// + /// Gets the city's size in acres. + /// + public int Acres { get; init; } + + /// + /// Gets the price for an acre of land (in bushels). + /// + public int LandPrice { get; init; } + + /// + /// Gets the number of bushels of grain in the city stores. + /// + public int Stores { get; init; } + + /// + /// Gets the amount of food distributed to the people. + /// + public int FoodDistributed { get; init; } + + /// + /// Gets the number of acres that were planted. + /// + public int AcresPlanted { get; init; } + + /// + /// Gets the number of bushels produced per acre. + /// + public int Productivity { get; init; } + + /// + /// Gets the amount of food lost to rats. + /// + public int Spoilage { get; init; } + + /// + /// Gets a flag indicating whether the current year is a plague year. + /// + public bool IsPlagueYear { get; init; } + + /// + /// Gets a flag indicating whether the player has been impeached. + /// + public bool IsImpeached { get; init; } + } +} diff --git a/43 Hammurabi/csharp/src/GreatOffence.cs b/43 Hammurabi/csharp/src/GreatOffence.cs new file mode 100644 index 00000000..98791492 --- /dev/null +++ b/43 Hammurabi/csharp/src/GreatOffence.cs @@ -0,0 +1,12 @@ +using System; + +namespace Hammurabi +{ + /// + /// Indicates that the game cannot continue due to the player's extreme + /// incompetance and/or unserious attitude! + /// + public class GreatOffence : InvalidOperationException + { + } +} diff --git a/43 Hammurabi/csharp/src/PerformanceRating.cs b/43 Hammurabi/csharp/src/PerformanceRating.cs new file mode 100644 index 00000000..39454720 --- /dev/null +++ b/43 Hammurabi/csharp/src/PerformanceRating.cs @@ -0,0 +1,14 @@ +namespace Hammurabi +{ + /// + /// Enumerates the different performance ratings that the player can + /// achieve. + /// + public enum PerformanceRating + { + Disgraceful, + Bad, + Ok, + Terrific + } +} diff --git a/43 Hammurabi/csharp/src/Program.cs b/43 Hammurabi/csharp/src/Program.cs new file mode 100644 index 00000000..45d5b101 --- /dev/null +++ b/43 Hammurabi/csharp/src/Program.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Immutable; + +namespace Hammurabi +{ + public static class Program + { + public const int GameLength = 10; + + public static void Main(string[] args) + { + var random = new Random ((int) (DateTime.UtcNow.Ticks / 10000)) ; + var state = Rules.BeginGame(); + var history = ImmutableList.Empty; + + View.ShowBanner(); + + try + { + while (state.Year <= GameLength && !state.IsImpeached) + { + state = Rules.BeginTurn(state, random); + View.ShowCitySummary(state); + + View.ShowLandPrice(state); + var newState = Controller.TryUntilSuccess(state, View.PromptBuyLand, Rules.BuyLand); + state = newState.Acres != state.Acres ? + newState : Controller.TryUntilSuccess(state, View.PromptSellLand, Rules.SellLand); + + View.ShowSeparator(); + state = Controller.TryUntilSuccess(state, View.PromptFeedPeople, Rules.FeedPeople); + + View.ShowSeparator(); + state = Controller.TryUntilSuccess(state, View.PromptPlantCrops, Rules.PlantCrops); + + state = Rules.EndTurn(state, random); + history = history.Add(state); + } + + var result = Rules.GetGameResult(history, random); + View.ShowGameResult(result); + } + catch (GreatOffence) + { + View.ShowGreatOffence(); + } + + View.ShowFarewell(); + } + } +} diff --git a/43 Hammurabi/csharp/src/Rules.cs b/43 Hammurabi/csharp/src/Rules.cs new file mode 100644 index 00000000..56a59d96 --- /dev/null +++ b/43 Hammurabi/csharp/src/Rules.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Hammurabi +{ + public static class Rules + { + /// + /// Creates the initial state for a new game. + /// + public static GameState BeginGame() => + new GameState + { + Year = 1, + Population = 95, + PopulationIncrease = 5, + Starvation = 0, + Acres = 1000, + Stores = 0, + AcresPlanted = 1000, + Productivity = 3, + Spoilage = 200, + IsPlagueYear = false, + IsImpeached = false + }; + + /// + /// Updates the game state to start a new turn. + /// + public static GameState BeginTurn(GameState state, Random random) => + state with + { + Population = (state.Population + state.PopulationIncrease - state.Starvation) / (state.IsPlagueYear ? 2 : 1), + LandPrice = random.Next(10) + 17, + Stores = state.Stores + (state.AcresPlanted * state.Productivity) - state.Spoilage, + AcresPlanted = 0, + FoodDistributed = 0 + }; + + /// + /// Attempts to purchase the given number of acres. + /// + /// + /// The updated game state and action result. + /// + public static (GameState newState, ActionResult result) BuyLand(GameState state, int amount) + { + var price = state.LandPrice * amount; + + if (price < 0) + return (state, ActionResult.Offense); + else + if (price > state.Stores) + return (state, ActionResult.InsufficientStores); + else + return (state with { Acres = state.Acres + amount, Stores = state.Stores - price }, ActionResult.Success); + } + + /// + /// Attempts to sell the given number of acres. + /// + /// + /// The updated game state and action result. + /// + public static (GameState newState, ActionResult result) SellLand(GameState state, int amount) + { + var price = state.LandPrice * amount; + + if (price < 0) + return (state, ActionResult.Offense); + else + if (amount >= state.Acres) + return (state, ActionResult.InsufficientLand); + else + return (state with { Acres = state.Acres - amount, Stores = state.Stores + price }, ActionResult.Success); + } + + /// + /// Attempts to feed the people the given number of buschels. + /// + /// + /// + /// The updated game state and action result. + /// + public static (GameState newState, ActionResult result) FeedPeople(GameState state, int amount) + { + if (amount < 0) + return (state, ActionResult.Offense); + else + if (amount > state.Stores) + return (state, ActionResult.InsufficientStores); + else + return (state with { Stores = state.Stores - amount, FoodDistributed = state.FoodDistributed + amount }, ActionResult.Success); + } + + /// + /// Attempts to plant crops on the given number of acres. + /// + /// + /// The updated game state and action result. + /// + public static (GameState newState, ActionResult result) PlantCrops(GameState state, int amount) + { + var storesRequired = amount / 2; + var maxAcres = state.Population * 10; + + if (amount < 0) + return (state, ActionResult.Offense); + else + if (amount > state.Acres) + return (state, ActionResult.InsufficientLand); + else + if (storesRequired > state.Stores) + return (state, ActionResult.InsufficientStores); + else + if ((state.AcresPlanted + amount) > maxAcres) + return (state, ActionResult.InsufficientPopulation); + else + return (state with + { + AcresPlanted = state.AcresPlanted + amount, + Stores = state.Stores - storesRequired, + }, ActionResult.Success); + } + + /// + /// Ends the current turn and returns the updated game state. + /// + public static GameState EndTurn(GameState state, Random random) + { + var productivity = random.Next(1, 6); + var harvest = productivity * state.AcresPlanted; + + var spoilage = random.Next(1, 6) switch + { + 2 => state.Stores / 2, + 4 => state.Stores / 4, + _ => 0 + }; + + var populationIncrease= (int)((double) random.Next(1, 6) * (20 * state.Acres + state.Stores + harvest - spoilage) / state.Population / 100 + 1); + + var plagueYear = random.Next(20) < 3; + + var peopleFed = state.FoodDistributed / 20; + var starvation = peopleFed < state.Population ? state.Population - peopleFed : 0; + var impeached = starvation > state.Population * 0.45; + + return state with + { + Year = state.Year + 1, + Productivity = productivity, + Spoilage = spoilage, + PopulationIncrease = populationIncrease, + Starvation = starvation, + IsPlagueYear = plagueYear, + IsImpeached = impeached + }; + } + + /// + /// Examines the game's history to arrive at the final result. + /// + public static GameResult GetGameResult(IEnumerable history, Random random) + { + var (_, averageStarvationRate, totalStarvation, finalState) = history.Aggregate( + (count: 0, starvationRate: 0, totalStarvation: 0, finalState: default(GameState)), + (stats, state) => + ( + stats.count + 1, + ((stats.starvationRate * stats.count) + (state.Starvation * 100 / state.Population)) / (stats.count + 1), + stats.totalStarvation + state.Starvation, + state + )); + + var acresPerPerson = finalState.Acres / finalState.Population; + + var rating = finalState.IsImpeached ? + PerformanceRating.Disgraceful : + (averageStarvationRate, acresPerPerson) switch + { + (> 33, _) => PerformanceRating.Disgraceful, + (_, < 7) => PerformanceRating.Disgraceful, + (> 10, _) => PerformanceRating.Bad, + (_, < 9) => PerformanceRating.Bad, + (> 3, _) => PerformanceRating.Ok, + (_, < 10) => PerformanceRating.Ok, + _ => PerformanceRating.Terrific + }; + + var assassins = rating == PerformanceRating.Ok ? + random.Next(0, (int)(finalState.Population * 0.8)) : 0; + + return new GameResult + { + Rating = rating, + AcresPerPerson = acresPerPerson, + FinalStarvation = finalState.Starvation, + TotalStarvation = totalStarvation, + AverageStarvationRate = averageStarvationRate, + Assassins = assassins, + WasImpeached = finalState.IsImpeached + }; + } + } +} diff --git a/43 Hammurabi/csharp/src/View.cs b/43 Hammurabi/csharp/src/View.cs new file mode 100644 index 00000000..be10af32 --- /dev/null +++ b/43 Hammurabi/csharp/src/View.cs @@ -0,0 +1,193 @@ +using System; + +namespace Hammurabi +{ + /// + /// Provides various methods for presenting information to the user. + /// + public static class View + { + /// + /// Shows the introductory banner to the player. + /// + public static void ShowBanner() + { + Console.WriteLine(" HAMURABI"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA"); + Console.WriteLine("FOR A TEN-YEAR TERM OF OFFICE."); + } + + /// + /// Shows a summary of the current state of the city. + /// + public static void ShowCitySummary(GameState state) + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("HAMURABI: I BEG TO REPORT TO YOU,"); + Console.WriteLine($"IN YEAR {state.Year}, {state.Starvation} PEOPLE STARVED, {state.PopulationIncrease} CAME TO THE CITY,"); + + if (state.IsPlagueYear) + { + Console.WriteLine("A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED."); + } + + Console.WriteLine($"POPULATION IS NOW {state.Population}"); + Console.WriteLine($"THE CITY NOW OWNS {state.Acres} ACRES."); + Console.WriteLine($"YOU HARVESTED {state.Productivity} BUSHELS PER ACRE."); + Console.WriteLine($"THE RATS ATE {state.Spoilage} BUSHELS."); + Console.WriteLine($"YOU NOW HAVE {state.Stores} BUSHELS IN STORE."); + Console.WriteLine(); + } + + /// + /// Shows the current cost of land. + /// + /// + public static void ShowLandPrice(GameState state) + { + Console.WriteLine ($"LAND IS TRADING AT {state.LandPrice} BUSHELS PER ACRE."); + } + + /// + /// Displays a section separator. + /// + public static void ShowSeparator() + { + Console.WriteLine(); + } + + /// + /// Inform the player that he or she has entered an invalid number. + /// + public static void ShowInvalidNumber() + { + Console.WriteLine("PLEASE ENTER A VALID NUMBER"); + } + + /// + /// Inform the player that he or she has insufficient acreage. + /// + public static void ShowInsufficientLand(GameState state) + { + Console.WriteLine($"HAMURABI: THINK AGAIN. YOU OWN ONLY {state.Acres} ACRES. NOW THEN,"); + } + + /// + /// Inform the player that he or she has insufficient population. + /// + public static void ShowInsufficientPopulation(GameState state) + { + Console.WriteLine($"BUT YOU HAVE ONLY {state.Population} PEOPLE TO TEND THE FIELDS! NOW THEN,"); + } + + /// + /// Inform the player that he or she has insufficient grain stores. + /// + public static void ShowInsufficientStores(GameState state) + { + Console.WriteLine("HAMURABI: THINK AGAIN. YOU HAVE ONLY"); + Console.WriteLine($"{state.Stores} BUSHELS OF GRAIN. NOW THEN,"); + } + + /// + /// Show the player that he or she has caused great offence. + /// + public static void ShowGreatOffence() + { + Console.WriteLine(); + Console.WriteLine("HAMURABI: I CANNOT DO WHAT YOU WISH."); + Console.WriteLine("GET YOURSELF ANOTHER STEWARD!!!!!"); + } + + /// + /// Shows the game's final result to the user. + /// + public static void ShowGameResult(GameResult result) + { + if (!result.WasImpeached) + { + Console.WriteLine($"IN YOUR 10-YEAR TERM OF OFFICE, {result.AverageStarvationRate} PERCENT OF THE"); + Console.WriteLine("POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF"); + Console.WriteLine($"{result.TotalStarvation} PEOPLE DIED!!"); + + Console.WriteLine("YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH"); + Console.WriteLine($"{result.AcresPerPerson} ACRES PER PERSON."); + Console.WriteLine(); + } + + switch (result.Rating) + { + case PerformanceRating.Disgraceful: + if (result.WasImpeached) + Console.WriteLine($"YOU STARVED {result.FinalStarvation} PEOPLE IN ONE YEAR!!!"); + + Console.WriteLine("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY"); + Console.WriteLine("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE"); + Console.WriteLine("ALSO BEEN DECLARED NATIONAL FINK!!!!"); + break; + case PerformanceRating.Bad: + Console.WriteLine("YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV."); + Console.WriteLine("THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,"); + Console.WriteLine("FRANKLY, HATE YOUR GUTS!!"); + break; + case PerformanceRating.Ok: + Console.WriteLine("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT"); + Console.WriteLine($"REALLY WASN'T TOO BAD AT ALL. {result.Assassins} PEOPLE"); + Console.WriteLine("WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR"); + Console.WriteLine("TRIVIAL PROBLEMS."); + break; + case PerformanceRating.Terrific: + Console.WriteLine("A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND"); + Console.WriteLine("JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!"); + break; + } + } + + /// + /// Shows a farewell message to the user. + /// + public static void ShowFarewell() + { + Console.WriteLine("SO LONG FOR NOW."); + Console.WriteLine(); + } + + /// + /// Prompts the user to buy land. + /// + public static void PromptBuyLand() + { + Console.WriteLine ("HOW MANY ACRES DO YOU WISH TO BUY"); + } + + /// + /// Prompts the user to sell land. + /// + public static void PromptSellLand() + { + Console.WriteLine("HOW MANY ACRES DO YOU WISH TO SELL"); + } + + /// + /// Prompts the user to feed the people. + /// + public static void PromptFeedPeople() + { + Console.WriteLine("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE"); + } + + /// + /// Prompts the user to plant crops. + /// + public static void PromptPlantCrops() + { + Console.WriteLine("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED"); + } + } +} From 07bfdb591266e57f9644b8ccd76f80b61520dcff Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sun, 4 Apr 2021 00:28:36 -0400 Subject: [PATCH 350/749] Ported Word to Java. --- 96 Word/java/Word.java | 223 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 96 Word/java/Word.java diff --git a/96 Word/java/Word.java b/96 Word/java/Word.java new file mode 100644 index 00000000..7cae9124 --- /dev/null +++ b/96 Word/java/Word.java @@ -0,0 +1,223 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Word + *

+ * Based on the BASIC game of Word here + * https://github.com/coding-horror/basic-computer-games/blob/main/96%20Word/word.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Word { + + private final static String[] WORDS = { + + "DINKY", "SMOKE", "WATER", "GRASS", "TRAIN", "MIGHT", + "FIRST", "CANDY", "CHAMP", "WOULD", "CLUMP", "DOPEY" + + }; + + private final Scanner scan; // For user input + + private enum Step { + INITIALIZE, MAKE_GUESS, USER_WINS + } + + public Word() { + + scan = new Scanner(System.in); + + } // End of constructor Word + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private void showIntro() { + + System.out.println(" ".repeat(32) + "WORD"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + System.out.println("I AM THINKING OF A WORD -- YOU GUESS IT. I WILL GIVE YOU"); + System.out.println("CLUES TO HELP YOU GET IT. GOOD LUCK!!"); + System.out.println("\n"); + + } // End of method showIntro + + private void startGame() { + + char[] commonLetters = new char[8]; + char[] exactLetters = new char[8]; + + int commonIndex = 0; + int ii = 0; // Loop iterator + int jj = 0; // Loop iterator + int numGuesses = 0; + int numMatches = 0; + int wordIndex = 0; + + Step nextStep = Step.INITIALIZE; + + String commonString = ""; + String exactString = ""; + String guessWord = ""; + String secretWord = ""; + String userResponse = ""; + + // Begin outer while loop + while (true) { + + switch (nextStep) { + + case INITIALIZE: + + System.out.println("\n"); + System.out.println("YOU ARE STARTING A NEW GAME..."); + + // Select a secret word from the list + wordIndex = (int) (Math.random() * WORDS.length); + secretWord = WORDS[wordIndex]; + + numGuesses = 0; + + Arrays.fill(exactLetters, 1, 6, '-'); + Arrays.fill(commonLetters, 1, 6, '\0'); + + nextStep = Step.MAKE_GUESS; + break; + + case MAKE_GUESS: + + System.out.print("GUESS A FIVE LETTER WORD? "); + guessWord = scan.nextLine().toUpperCase(); + + numGuesses++; + + // Win condition + if (guessWord.equals(secretWord)) { + nextStep = Step.USER_WINS; + continue; + } + + Arrays.fill(commonLetters, 1, 8, '\0'); + + // Surrender condition + if (guessWord.equals("?")) { + System.out.println("THE SECRET WORD IS " + secretWord); + System.out.println(""); + nextStep = Step.INITIALIZE; // Play again + continue; + } + + // Check for valid input + if (guessWord.length() != 5) { + System.out.println("YOU MUST GUESS A 5 LETTER WORD. START AGAIN."); + numGuesses--; + nextStep = Step.MAKE_GUESS; // Guess again + continue; + } + + numMatches = 0; + commonIndex = 1; + + for (ii = 1; ii <= 5; ii++) { + + for (jj = 1; jj <= 5; jj++) { + + if (secretWord.charAt(ii - 1) != guessWord.charAt(jj - 1)) { + continue; + } + + // Avoid out of bounds errors + if (commonIndex <= 5) { + commonLetters[commonIndex] = guessWord.charAt(jj - 1); + commonIndex++; + } + + if (ii == jj) { + exactLetters[jj] = guessWord.charAt(jj - 1); + } + + // Avoid out of bounds errors + if (numMatches < 5) { + numMatches++; + } + } + } + + exactString = ""; + commonString = ""; + + // Build the exact letters string + for (ii = 1; ii <= 5; ii++) { + exactString += exactLetters[ii]; + } + + // Build the common letters string + for (ii = 1; ii <= numMatches; ii++) { + commonString += commonLetters[ii]; + } + + System.out.println("THERE WERE " + numMatches + " MATCHES AND THE COMMON LETTERS WERE..." + + commonString); + + System.out.println("FROM THE EXACT LETTER MATCHES, YOU KNOW................" + exactString); + + // Win condition + if (exactString.equals(secretWord)) { + nextStep = Step.USER_WINS; + continue; + } + + // No matches + if (numMatches <= 1) { + System.out.println(""); + System.out.println("IF YOU GIVE UP, TYPE '?' FOR YOUR NEXT GUESS."); + } + + System.out.println(""); + nextStep = Step.MAKE_GUESS; + break; + + case USER_WINS: + + System.out.println("YOU HAVE GUESSED THE WORD. IT TOOK " + numGuesses + " GUESSES!"); + System.out.println(""); + + System.out.print("WANT TO PLAY AGAIN? "); + userResponse = scan.nextLine(); + + if (userResponse.toUpperCase().equals("YES")) { + nextStep = Step.INITIALIZE; // Play again + } else { + return; // Quit game + } + break; + + default: + System.out.println("INVALID STEP"); + break; + + } + + } // End outer while loop + + } // End of method startGame + + public static void main(String[] args) { + + Word word = new Word(); + word.play(); + + } // End of method main + +} // End of class Word From d60f10e87e6cfa695e2634dcfce34a75d305e8d0 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Mon, 5 Apr 2021 21:19:59 -0400 Subject: [PATCH 351/749] Ported Depth Charge to Java. --- 31 Depth Charge/java/DepthCharge.java | 186 ++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 31 Depth Charge/java/DepthCharge.java diff --git a/31 Depth Charge/java/DepthCharge.java b/31 Depth Charge/java/DepthCharge.java new file mode 100644 index 00000000..bf17accc --- /dev/null +++ b/31 Depth Charge/java/DepthCharge.java @@ -0,0 +1,186 @@ +import java.util.Scanner; +import java.lang.Math; + +/** + * Game of Depth Charge + *

+ * Based on the BASIC game of Depth Charge here + * https://github.com/coding-horror/basic-computer-games/blob/main/31%20Depth%20Charge/depthcharge.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class DepthCharge { + + private final Scanner scan; // For user input + + public DepthCharge() { + + scan = new Scanner(System.in); + + } // End of constructor DepthCharge + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(29) + "DEPTH CHARGE"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + int searchArea = 0; + int shotNum = 0; + int shotTotal = 0; + int shotX = 0; + int shotY = 0; + int shotZ = 0; + int targetX = 0; + int targetY = 0; + int targetZ = 0; + int tries = 0; + String[] userCoordinates; + String userResponse = ""; + + System.out.print("DIMENSION OF SEARCH AREA? "); + searchArea = Integer.parseInt(scan.nextLine()); + System.out.println(""); + + shotTotal = (int) (Math.log10(searchArea) / Math.log10(2)) + 1; + + System.out.println("YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER"); + System.out.println("AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR"); + System.out.println("MISSION IS TO DESTROY IT. YOU HAVE " + shotTotal + " SHOTS."); + System.out.println("SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A"); + System.out.println("TRIO OF NUMBERS -- THE FIRST TWO ARE THE"); + System.out.println("SURFACE COORDINATES; THE THIRD IS THE DEPTH."); + + // Begin outer while loop + while (true) { + + System.out.println(""); + System.out.println("GOOD LUCK !"); + System.out.println(""); + + targetX = (int) ((searchArea + 1) * Math.random()); + targetY = (int) ((searchArea + 1) * Math.random()); + targetZ = (int) ((searchArea + 1) * Math.random()); + + // Begin loop through all shots + for (shotNum = 1; shotNum <= shotTotal; shotNum++) { + + // Get user input + System.out.println(""); + System.out.print("TRIAL # " + shotNum + "? "); + userResponse = scan.nextLine(); + + // Split on commas + userCoordinates = userResponse.split(","); + + // Assign to integer variables + shotX = Integer.parseInt(userCoordinates[0].trim()); + shotY = Integer.parseInt(userCoordinates[1].trim()); + shotZ = Integer.parseInt(userCoordinates[2].trim()); + + // Win condition + if (Math.abs(shotX - targetX) + Math.abs(shotY - targetY) + + Math.abs(shotZ - targetZ) == 0) { + + System.out.println("B O O M ! ! YOU FOUND IT IN" + shotNum + " TRIES!"); + break; + + } + + this.getReport(targetX, targetY, targetZ, shotX, shotY, shotZ); + + System.out.println(""); + + } // End loop through all shots + + if (shotNum > shotTotal) { + + System.out.println(""); + System.out.println("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!"); + System.out.println("THE SUBMARINE WAS AT " + targetX + "," + targetY + "," + targetZ); + } + + System.out.println(""); + System.out.println(""); + System.out.print("ANOTHER GAME (Y OR N)? "); + userResponse = scan.nextLine(); + + if (!userResponse.toUpperCase().equals("Y")) { + System.out.print("OK. HOPE YOU ENJOYED YOURSELF."); + return; + } + + } // End outer while loop + + } // End of method startGame + + public void getReport(int a, int b, int c, int x, int y, int z) { + + System.out.print("SONAR REPORTS SHOT WAS "); + + // Handle y coordinate + if (y > b) { + + System.out.print("NORTH"); + + } else if (y < b) { + + System.out.print("SOUTH"); + } + + // Handle x coordinate + if (x > a) { + + System.out.print("EAST"); + + } else if (x < a) { + + System.out.print("WEST"); + } + + if ((y != b) || (x != a)) { + + System.out.print(" AND"); + } + + // Handle depth + if (z > c) { + + System.out.println(" TOO LOW."); + + } else if (z < c) { + + System.out.println(" TOO HIGH."); + + } else { + + System.out.println(" DEPTH OK."); + } + + return; + + } // End of method getReport + + public static void main(String[] args) { + + DepthCharge game = new DepthCharge(); + game.play(); + + } // End of method main + +} // End of class DepthCharge From eefd487fd882f29a4fefed324050485de6d18b23 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Tue, 6 Apr 2021 02:58:37 -0500 Subject: [PATCH 352/749] Create guess.pl Made with Perl! --- 41 Guess/perl/guess.pl | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 41 Guess/perl/guess.pl diff --git a/41 Guess/perl/guess.pl b/41 Guess/perl/guess.pl new file mode 100644 index 00000000..f16a3e84 --- /dev/null +++ b/41 Guess/perl/guess.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl +use strict; + +my $L1; +while (1) { + print ' 'x 33 . "GUESS\n"; + print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; + print "\n"; print "\n"; print "\n"; + print "THIS IS A NUMBER GUESSING GAME. I'LL THINK\n"; + print "OF A NUMBER BETWEEN 1 AND ANY LIMIT YOU WANT.\n"; + print "THEN YOU HAVE TO GUESS WHAT IT IS.\n"; + print "\n"; + print "WHAT LIMIT DO YOU WANT"; + print "? "; chomp(my $L = ); + print "\n"; + $L1= int(log($L)/log(2))+1; + + while (1) { + print "I'M THINKING OF A NUMBER BETWEEN 1 AND $L\n"; + my $G=0; + print "NOW YOU TRY TO GUESS WHAT IT IS.\n"; + my $M=int($L*rand(1)+1); + my $N=0; + while (1) { + while (1) { + print "? "; chomp($N = ); + if ($N>0) { last; } + } + $G=$G+1; + if ($N==$M) { last; } + if ($N>$M) { print "TOO HIGH. TRY A SMALLER ANSWER.\n"; } + else { print "TOO LOW. TRY A BIGGER ANSWER.\n"; } + } + print "THAT'S IT! YOU GOT IT IN $G TRIES.\n"; + if ($G<$L1) { print "VERY "; } + if ($G<=$L1) { print "GOOD.\n"; } + if ($G>$L1) { print "YOU SHOULD HAVE BEEN ABLE TO GET IT IN ONLY $L1\n"; } + &ENTERS(); + } + } + +exit; + + +sub ENTERS { #GOSUB 70 + for (my $H=1; $H<=5; $H++) { + print "\n"; + } + return; + } + + From 0c644dbe97d50a08c729220801f9bdaa5dfe420a Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Tue, 6 Apr 2021 03:00:11 -0500 Subject: [PATCH 353/749] Create bunny.pl --- 19 Bunny/perl/bunny.pl | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 19 Bunny/perl/bunny.pl diff --git a/19 Bunny/perl/bunny.pl b/19 Bunny/perl/bunny.pl new file mode 100644 index 00000000..21b65f2e --- /dev/null +++ b/19 Bunny/perl/bunny.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl +use strict; + +print ' 'x 33 . "BUNNY\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +#REM "BUNNY" FROM AHL'$S 'BASIC COMPUTER GAMES'; + +# This data contains the letter Bunny A=1, B=2, C=3... +my @A= (2,21,14,14,25); + +# This data structure contains the pair of start and finish absolute position to show letters. +# -1 means next line, whatever more than 128 will stop the data read. +my @B= ( + 1,2,-1,0,2,45,50,-1,0,5,43,52,-1,0,7,41,52,-1, + 1,9,37,50,-1,2,11,36,50,-1,3,13,34,49,-1,4,14,32,48,-1, + 5,15,31,47,-1,6,16,30,45,-1,7,17,29,44,-1,8,19,28,43,-1, + 9,20,27,41,-1,10,21,26,40,-1,11,22,25,38,-1,12,22,24,36,-1, + 13,34,-1,14,33,-1,15,31,-1,17,29,-1,18,27,-1, + 19,26,-1,16,28,-1,13,30,-1,11,31,-1,10,32,-1, + 8,33,-1,7,34,-1,6,13,16,34,-1,5,12,16,35,-1, + 4,12,16,35,-1,3,12,15,35,-1,2,35,-1,1,35,-1, + 2,34,-1,3,34,-1,4,33,-1,6,33,-1,10,32,34,34,-1, + 14,17,19,25,28,31,35,35,-1,15,19,23,30,36,36,-1, + 14,18,21,21,24,30,37,37,-1,13,18,23,29,33,38,-1, + 12,29,31,33,-1,11,13,17,17,19,19,22,22,24,31,-1, + 10,11,17,18,22,22,24,24,29,29,-1, + 22,23,26,29,-1,27,29,-1,28,29,-1,4096 + ); + + +&ENTERS(); +my $L= 64; #REM ASCII LETTER CODE... +print "\n"; + +my $P=0; #Position read iterator +my $Line= ' 'x 60; +while (1) { + my $X= $B[$P]; $P++; #Read start position. + if ($X<0) { print "$Line\n";; $Line= ' 'x 60; next; } + if ($X>128) { last; } + my $Y= $B[$P]; $P++; #Read end position. + + for (my $I=$X; $I<=$Y; $I++) { my $J=$I-5*int($I/5); + substr($Line, $I, 1, chr($L+$A[$J])); #You can change $I for $X to get a nice bunny shadow. + } + } + +&ENTERS(); +exit; + + +sub ENTERS { #GOSUB 260 + for (my $I=1; $I<=6; $I++) { print chr(10); } + } From e976a92840866b8fa9812ad7814ecafc6bf63266 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Tue, 6 Apr 2021 03:03:16 -0500 Subject: [PATCH 354/749] Create poetry.pl Made with Perl! --- 70 Poetry/poetry.pl | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 70 Poetry/poetry.pl diff --git a/70 Poetry/poetry.pl b/70 Poetry/poetry.pl new file mode 100644 index 00000000..610938b6 --- /dev/null +++ b/70 Poetry/poetry.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl +#use strict; +# Automatic converted by bas2perl.pl +# Too much spaguetti code to be properly converted. + + +print ' 'x 30 . "POETRY\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +Line90: +if ($I==1) { goto Line100; } elsif ($I==2) { goto Line101; } elsif ($I==3) { goto Line102; } elsif ($I==4) { goto Line103; } elsif ($I==5) { goto Line104; } ; +Line100: +print "MIDNIGHT DREARY"; goto Line210; +Line101: +print "FIERY EYES"; goto Line210; +Line102: +print "BIRD OR FIEND"; goto Line210; +Line103: +print "THING OF EVIL"; goto Line210; +Line104: +print "PROPHET"; goto Line210; +Line110: +if ($I==1) { goto Line111; } elsif ($I==2) { goto Line112; } elsif ($I==3) { goto Line113; } elsif ($I==4) { goto Line114; } elsif ($I==5) { goto Line115; } ; +Line111: +print "BEGUILING ME"; $U=2; goto Line210; +Line112: +print "THRILLED ME"; goto Line210; +Line113: +print "STILL SITTING...."; goto Line212; +Line114: +print "NEVER FLITTING"; $U=2; goto Line210; +Line115: +print "BURNED"; goto Line210; +Line120: +if ($I==1) { goto Line121; } elsif ($I==2) { goto Line122; } elsif ($I==3) { goto Line123; } elsif ($I==4) { goto Line124; } elsif ($I==5) { goto Line125; } ; +Line121: +print "AND MY SOUL"; goto Line210; +Line122: +print "DARKNESS THERE"; goto Line210; +Line123: +print "SHALL BE LIFTED"; goto Line210; +Line124: +print "QUOTH THE RAVEN"; goto Line210; +Line125: +if ($U==0) { goto Line210; } +print "SIGN OF PARTING"; goto Line210; +Line130: +if ($I==1) { goto Line131; } elsif ($I==2) { goto Line132; } elsif ($I==3) { goto Line133; } elsif ($I==4) { goto Line134; } elsif ($I==5) { goto Line135; } ; +Line131: +print "NOTHING MORE"; goto Line210; +Line132: +print "YET AGAIN"; goto Line210; +Line133: +print "SLOWLY CREEPING"; goto Line210; +Line134: +print "...EVERMORE"; goto Line210; +Line135: +print "NEVERMORE"; +Line210: +if ($U==0 || rand(1)>.19) { goto Line212; } +print ","; $U=2; +Line212: +if (rand(1)>.65) { goto Line214; } +print " "; $U=$U+1; goto Line215; +Line214: +print "\n"; $U=0; +Line215: +$I=int(int(10*rand(1))/2)+1; +$J=$J+1; $K=$K+1; +if ($U>0 || int($J/2)!=$J/2) { goto Line240; } +print " "; +Line240: +if ($J==1) { goto Line90; } elsif ($J==2) { goto Line110; } elsif ($J==3) { goto Line120; } elsif ($J==4) { goto Line130; } elsif ($J==5) { goto Line250; } ; +Line250: +$J=0; print "\n"; if ($K>20) { goto Line270; } +goto Line215; +Line270: +print "\n"; $U=0; $K=0; goto Line110; +exit; + + From 0e89201ca2484f65bebeae2d84162e70def263d6 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Tue, 6 Apr 2021 14:25:05 -0500 Subject: [PATCH 355/749] Create poetry.pl Made with Perl! (now in correct path, I promise to learn git properly...) --- 70 Poetry/perl/poetry.pl | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 70 Poetry/perl/poetry.pl diff --git a/70 Poetry/perl/poetry.pl b/70 Poetry/perl/poetry.pl new file mode 100644 index 00000000..610938b6 --- /dev/null +++ b/70 Poetry/perl/poetry.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl +#use strict; +# Automatic converted by bas2perl.pl +# Too much spaguetti code to be properly converted. + + +print ' 'x 30 . "POETRY\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +Line90: +if ($I==1) { goto Line100; } elsif ($I==2) { goto Line101; } elsif ($I==3) { goto Line102; } elsif ($I==4) { goto Line103; } elsif ($I==5) { goto Line104; } ; +Line100: +print "MIDNIGHT DREARY"; goto Line210; +Line101: +print "FIERY EYES"; goto Line210; +Line102: +print "BIRD OR FIEND"; goto Line210; +Line103: +print "THING OF EVIL"; goto Line210; +Line104: +print "PROPHET"; goto Line210; +Line110: +if ($I==1) { goto Line111; } elsif ($I==2) { goto Line112; } elsif ($I==3) { goto Line113; } elsif ($I==4) { goto Line114; } elsif ($I==5) { goto Line115; } ; +Line111: +print "BEGUILING ME"; $U=2; goto Line210; +Line112: +print "THRILLED ME"; goto Line210; +Line113: +print "STILL SITTING...."; goto Line212; +Line114: +print "NEVER FLITTING"; $U=2; goto Line210; +Line115: +print "BURNED"; goto Line210; +Line120: +if ($I==1) { goto Line121; } elsif ($I==2) { goto Line122; } elsif ($I==3) { goto Line123; } elsif ($I==4) { goto Line124; } elsif ($I==5) { goto Line125; } ; +Line121: +print "AND MY SOUL"; goto Line210; +Line122: +print "DARKNESS THERE"; goto Line210; +Line123: +print "SHALL BE LIFTED"; goto Line210; +Line124: +print "QUOTH THE RAVEN"; goto Line210; +Line125: +if ($U==0) { goto Line210; } +print "SIGN OF PARTING"; goto Line210; +Line130: +if ($I==1) { goto Line131; } elsif ($I==2) { goto Line132; } elsif ($I==3) { goto Line133; } elsif ($I==4) { goto Line134; } elsif ($I==5) { goto Line135; } ; +Line131: +print "NOTHING MORE"; goto Line210; +Line132: +print "YET AGAIN"; goto Line210; +Line133: +print "SLOWLY CREEPING"; goto Line210; +Line134: +print "...EVERMORE"; goto Line210; +Line135: +print "NEVERMORE"; +Line210: +if ($U==0 || rand(1)>.19) { goto Line212; } +print ","; $U=2; +Line212: +if (rand(1)>.65) { goto Line214; } +print " "; $U=$U+1; goto Line215; +Line214: +print "\n"; $U=0; +Line215: +$I=int(int(10*rand(1))/2)+1; +$J=$J+1; $K=$K+1; +if ($U>0 || int($J/2)!=$J/2) { goto Line240; } +print " "; +Line240: +if ($J==1) { goto Line90; } elsif ($J==2) { goto Line110; } elsif ($J==3) { goto Line120; } elsif ($J==4) { goto Line130; } elsif ($J==5) { goto Line250; } ; +Line250: +$J=0; print "\n"; if ($K>20) { goto Line270; } +goto Line215; +Line270: +print "\n"; $U=0; $K=0; goto Line110; +exit; + + From 733621bb834542cd3864af9902b76ada078e894c Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Wed, 7 Apr 2021 19:47:21 -0400 Subject: [PATCH 356/749] Ported Poetry to Java. --- 70 Poetry/java/Poetry.java | 266 +++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 70 Poetry/java/Poetry.java diff --git a/70 Poetry/java/Poetry.java b/70 Poetry/java/Poetry.java new file mode 100644 index 00000000..80be8f21 --- /dev/null +++ b/70 Poetry/java/Poetry.java @@ -0,0 +1,266 @@ +/** + * Game of Poetry + *

+ * Based on the BASIC game of Poetry here + * https://github.com/coding-horror/basic-computer-games/blob/main/70%20Poetry/poetry.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Poetry { + + private final static double COMMA_RATE = 0.19; + private final static double SPACE_RATE = 0.65; + private final static int PARAGRAPH_RATE = 20; + + private enum Step { + WORD_GROUP1, WORD_GROUP2, WORD_GROUP3, WORD_GROUP4, RANDOMIZE_COMMA, + RANDOMIZE_WHITESPACE, RANDOMIZE_COUNTERS + } + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private void showIntro() { + + System.out.println(" ".repeat(29) + "POETRY"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + int groupIndex = 0; + int paragraphIndex = 0; + int punctuationIndex = 0; + int wordIndex = 1; + + Step nextStep = Step.WORD_GROUP1; + + // Begin outer while loop + while (true) { + + switch (nextStep) { + + case WORD_GROUP1: + + if (wordIndex == 1) { + + System.out.print("MIDNIGHT DREARY"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 2) { + + System.out.print("FIERY EYES"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 3) { + + System.out.print("BIRD OR FIEND"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 4) { + + System.out.print("THING OF EVIL"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 5) { + + System.out.print("PROPHET"); + nextStep = Step.RANDOMIZE_COMMA; + } + break; + + case WORD_GROUP2: + + if (wordIndex == 1) { + + System.out.print("BEGUILING ME"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 2) { + + System.out.print("THRILLED ME"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 3) { + + System.out.print("STILL SITTING...."); + nextStep = Step.RANDOMIZE_WHITESPACE; + + } else if (wordIndex == 4) { + + System.out.print("NEVER FLITTING"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 5) { + + System.out.print("BURNED"); + nextStep = Step.RANDOMIZE_COMMA; + } + break; + + case WORD_GROUP3: + + if (wordIndex == 1) { + + System.out.print("AND MY SOUL"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 2) { + + System.out.print("DARKNESS THERE"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 3) { + + System.out.print("SHALL BE LIFTED"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 4) { + + System.out.print("QUOTH THE RAVEN"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 5) { + + if (punctuationIndex != 0) { + + System.out.print("SIGN OF PARTING"); + } + + nextStep = Step.RANDOMIZE_COMMA; + } + break; + + case WORD_GROUP4: + + if (wordIndex == 1) { + + System.out.print("NOTHING MORE"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 2) { + + System.out.print("YET AGAIN"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 3) { + + System.out.print("SLOWLY CREEPING"); + nextStep = Step.RANDOMIZE_WHITESPACE; + + } else if (wordIndex == 4) { + + System.out.print("...EVERMORE"); + nextStep = Step.RANDOMIZE_COMMA; + + } else if (wordIndex == 5) { + + System.out.print("NEVERMORE"); + nextStep = Step.RANDOMIZE_COMMA; + } + break; + + case RANDOMIZE_COMMA: + + // Insert commas + if ((punctuationIndex != 0) && (Math.random() <= COMMA_RATE)) { + + System.out.print(","); + punctuationIndex = 2; + } + nextStep = Step.RANDOMIZE_WHITESPACE; + break; + + + case RANDOMIZE_WHITESPACE: + + // Insert spaces + if (Math.random() <= SPACE_RATE) { + + System.out.print(" "); + punctuationIndex++; + + } + // Insert newlines + else { + + System.out.println(""); + punctuationIndex = 0; + } + nextStep = Step.RANDOMIZE_COUNTERS; + break; + + case RANDOMIZE_COUNTERS: + + wordIndex = (int)((int)(10 * Math.random()) / 2) + 1; + + groupIndex++; + paragraphIndex++; + + if ((punctuationIndex == 0) && (groupIndex % 2 == 0)) { + + System.out.print(" "); + } + + if (groupIndex == 1) { + + nextStep = Step.WORD_GROUP1; + + } else if (groupIndex == 2) { + + nextStep = Step.WORD_GROUP2; + + } else if (groupIndex == 3) { + + nextStep = Step.WORD_GROUP3; + + } else if (groupIndex == 4) { + + nextStep = Step.WORD_GROUP4; + + } else if (groupIndex == 5) { + + groupIndex = 0; + System.out.println(""); + + if (paragraphIndex > PARAGRAPH_RATE) { + + System.out.println(""); + punctuationIndex = 0; + paragraphIndex = 0; + nextStep = Step.WORD_GROUP2; + + } else { + + nextStep = Step.RANDOMIZE_COUNTERS; + } + } + break; + + default: + System.out.println("INVALID STEP"); + break; + } + + } // End outer while loop + + } // End of method startGame + + public static void main(String[] args) { + + Poetry poetry = new Poetry(); + poetry.play(); + + } // End of method main + +} // End of class Poetry From c675cd3af801855747e894201981cba7dbacb3a0 Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Sat, 10 Apr 2021 23:27:22 +0100 Subject: [PATCH 357/749] Initial version of Craps game. --- 29 Craps/csharp/Craps/Craps.sln | 31 +++++++++++++++++++ 29 Craps/csharp/Craps/Craps/Craps.csproj | 8 +++++ 29 Craps/csharp/Craps/Craps/Dice.cs | 24 ++++++++++++++ 29 Craps/csharp/Craps/Craps/Program.cs | 12 +++++++ .../Craps/CrapsTester/CrapsTester.csproj | 20 ++++++++++++ .../csharp/Craps/CrapsTester/CrapsTests.cs | 31 +++++++++++++++++++ 6 files changed, 126 insertions(+) create mode 100644 29 Craps/csharp/Craps/Craps.sln create mode 100644 29 Craps/csharp/Craps/Craps/Craps.csproj create mode 100644 29 Craps/csharp/Craps/Craps/Dice.cs create mode 100644 29 Craps/csharp/Craps/Craps/Program.cs create mode 100644 29 Craps/csharp/Craps/CrapsTester/CrapsTester.csproj create mode 100644 29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs diff --git a/29 Craps/csharp/Craps/Craps.sln b/29 Craps/csharp/Craps/Craps.sln new file mode 100644 index 00000000..f6ab76ec --- /dev/null +++ b/29 Craps/csharp/Craps/Craps.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Craps", "Craps\Craps.csproj", "{783A49D7-DADE-477A-9973-D9457258573B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrapsTester", "CrapsTester\CrapsTester.csproj", "{44DFE8DB-715F-428E-992D-A97C34D47B98}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {783A49D7-DADE-477A-9973-D9457258573B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {783A49D7-DADE-477A-9973-D9457258573B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {783A49D7-DADE-477A-9973-D9457258573B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {783A49D7-DADE-477A-9973-D9457258573B}.Release|Any CPU.Build.0 = Release|Any CPU + {44DFE8DB-715F-428E-992D-A97C34D47B98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44DFE8DB-715F-428E-992D-A97C34D47B98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44DFE8DB-715F-428E-992D-A97C34D47B98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44DFE8DB-715F-428E-992D-A97C34D47B98}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {871679FF-B86C-468B-960E-DFC625CDB5D0} + EndGlobalSection +EndGlobal diff --git a/29 Craps/csharp/Craps/Craps/Craps.csproj b/29 Craps/csharp/Craps/Craps/Craps.csproj new file mode 100644 index 00000000..c73e0d16 --- /dev/null +++ b/29 Craps/csharp/Craps/Craps/Craps.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/29 Craps/csharp/Craps/Craps/Dice.cs b/29 Craps/csharp/Craps/Craps/Dice.cs new file mode 100644 index 00000000..3485f0f6 --- /dev/null +++ b/29 Craps/csharp/Craps/Craps/Dice.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Craps +{ + public class Dice + { + private Random rand = new Random(); + public readonly int sides; + + public Dice() + { + sides = 6; + } + + public Dice(int sides) + { + this.sides = sides; + } + + public int Roll() => rand.Next(1, sides); + } +} diff --git a/29 Craps/csharp/Craps/Craps/Program.cs b/29 Craps/csharp/Craps/Craps/Program.cs new file mode 100644 index 00000000..17688427 --- /dev/null +++ b/29 Craps/csharp/Craps/Craps/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace Craps +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/29 Craps/csharp/Craps/CrapsTester/CrapsTester.csproj b/29 Craps/csharp/Craps/CrapsTester/CrapsTester.csproj new file mode 100644 index 00000000..748e7da4 --- /dev/null +++ b/29 Craps/csharp/Craps/CrapsTester/CrapsTester.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + diff --git a/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs b/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs new file mode 100644 index 00000000..9765ba61 --- /dev/null +++ b/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs @@ -0,0 +1,31 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Craps; + +namespace CrapsTester +{ + [TestClass] + public class DiceTests + { + [TestMethod] + public void SixSidedDiceReturnsValidRolls() + { + var dice = new Dice(); + for (int i = 0; i < 100000; i++) + { + var roll = dice.Roll(); + Assert.IsTrue(roll >= 1 && roll <= dice.sides); + } + } + + [TestMethod] + public void TwentySidedDiceReturnsValidRolls() + { + var dice = new Dice(20); + for (int i = 0; i < 100000; i++) + { + var roll = dice.Roll(); + Assert.IsTrue(roll >= 1 && roll <= dice.sides); + } + } + } +} From 26decdcd2b3c9397c9c36df13f936118189b1550 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sat, 10 Apr 2021 19:52:00 -0400 Subject: [PATCH 358/749] Ported Reverse to Java. --- 73 Reverse/java/Reverse.java | 242 +++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 73 Reverse/java/Reverse.java diff --git a/73 Reverse/java/Reverse.java b/73 Reverse/java/Reverse.java new file mode 100644 index 00000000..22c1d073 --- /dev/null +++ b/73 Reverse/java/Reverse.java @@ -0,0 +1,242 @@ +import java.util.Scanner; +import java.lang.Math; + +/** + * Game of Reverse + *

+ * Based on the BASIC game of Reverse here + * https://github.com/coding-horror/basic-computer-games/blob/main/73%20Reverse/reverse.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Reverse { + + private final int NUMBER_COUNT = 9; + + private final Scanner scan; // For user input + + private enum Step { + INITIALIZE, PERFORM_REVERSE, TRY_AGAIN, END_GAME + } + + public Reverse() { + + scan = new Scanner(System.in); + + } // End of constructor Reverse + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(31) + "REVERSE"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + System.out.println("REVERSE -- A GAME OF SKILL"); + System.out.println(""); + + } // End of method showIntro + + private void startGame() { + + int index = 0; + int numMoves = 0; + int numReverse = 0; + int tempVal = 0; + int[] numList = new int[NUMBER_COUNT + 1]; + + Step nextStep = Step.INITIALIZE; + + String userResponse = ""; + + System.out.print("DO YOU WANT THE RULES? "); + userResponse = scan.nextLine(); + + if (!userResponse.toUpperCase().equals("NO")) { + + this.printRules(); + } + + // Begin outer while loop + while (true) { + + // Begin outer switch + switch (nextStep) { + + case INITIALIZE: + + // Make a random list of numbers + numList[1] = (int)((NUMBER_COUNT - 1) * Math.random() + 2); + + for (index = 2; index <= NUMBER_COUNT; index++) { + + // Keep generating lists if there are duplicates + while (true) { + + numList[index] = (int)(NUMBER_COUNT * Math.random() + 1); + + // Search for duplicates + if (!this.findDuplicates(numList, index)) { + break; + } + } + } + + System.out.println(""); + System.out.println("HERE WE GO ... THE LIST IS:"); + + numMoves = 0; + + this.printBoard(numList); + + nextStep = Step.PERFORM_REVERSE; + break; + + case PERFORM_REVERSE: + + System.out.print("HOW MANY SHALL I REVERSE? "); + numReverse = Integer.parseInt(scan.nextLine()); + + if (numReverse == 0) { + + nextStep = Step.TRY_AGAIN; + + } else if (numReverse > NUMBER_COUNT) { + + System.out.println("OOPS! TOO MANY! I CAN REVERSE AT MOST " + NUMBER_COUNT); + nextStep = Step.PERFORM_REVERSE; + + } else { + + numMoves++; + + for (index = 1; index <= (int)(numReverse / 2.0); index++) { + + tempVal = numList[index]; + numList[index] = numList[numReverse - index + 1]; + numList[numReverse - index + 1] = tempVal; + } + + this.printBoard(numList); + + nextStep = Step.TRY_AGAIN; + + // Check for a win + for (index = 1; index <= NUMBER_COUNT; index++) { + + if (numList[index] != index) { + nextStep = Step.PERFORM_REVERSE; + } + } + + if (nextStep == Step.TRY_AGAIN) { + System.out.println("YOU WON IT IN " + numMoves + " MOVES!!!"); + System.out.println(""); + } + } + break; + + case TRY_AGAIN: + + System.out.println(""); + System.out.print("TRY AGAIN (YES OR NO)? "); + userResponse = scan.nextLine(); + + if (userResponse.toUpperCase().equals("YES")) { + nextStep = Step.INITIALIZE; + } else { + nextStep = Step.END_GAME; + } + break; + + case END_GAME: + + System.out.println(""); + System.out.println("O.K. HOPE YOU HAD FUN!!"); + return; + + default: + + System.out.println("INVALID STEP"); + break; + + } // End outer switch + + } // End outer while loop + + } // End of method startGame + + public boolean findDuplicates(int[] board, int length) { + + int index = 0; + + for (index = 1; index <= length - 1; index++) { + + // Identify duplicates + if (board[length] == board[index]) { + + return true; // Found a duplicate + } + } + + return false; // No duplicates found + + } // End of method findDuplicates + + public void printBoard(int[] board) { + + int index = 0; + + System.out.println(""); + + for (index = 1; index <= NUMBER_COUNT; index++) { + + System.out.format("%2d", board[index]); + } + + System.out.println("\n"); + + } // End of method printBoard + + public void printRules() { + + System.out.println(""); + System.out.println("THIS IS THE GAME OF 'REVERSE'. TO WIN, ALL YOU HAVE"); + System.out.println("TO DO IS ARRANGE A LIST OF NUMBERS (1 THROUGH " + NUMBER_COUNT + ")"); + System.out.println("IN NUMERICAL ORDER FROM LEFT TO RIGHT. TO MOVE, YOU"); + System.out.println("TELL ME HOW MANY NUMBERS (COUNTING FROM THE LEFT) TO"); + System.out.println("REVERSE. FOR EXAMPLE, IF THE CURRENT LIST IS:"); + System.out.println(""); + System.out.println("2 3 4 5 1 6 7 8 9"); + System.out.println(""); + System.out.println("AND YOU REVERSE 4, THE RESULT WILL BE:"); + System.out.println(""); + System.out.println("5 4 3 2 1 6 7 8 9"); + System.out.println(""); + System.out.println("NOW IF YOU REVERSE 5, YOU WIN!"); + System.out.println(""); + System.out.println("1 2 3 4 5 6 7 8 9"); + System.out.println(""); + System.out.println("NO DOUBT YOU WILL LIKE THIS GAME, BUT"); + System.out.println("IF YOU WANT TO QUIT, REVERSE 0 (ZERO)."); + System.out.println(""); + + } // End of method printRules + + public static void main(String[] args) { + + Reverse game = new Reverse(); + game.play(); + + } // End of method main + +} // End of class Reverse From e1f2c92b191ad70d99234f5dbccb8d2d24c35fa5 Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Sun, 11 Apr 2021 20:57:43 +0100 Subject: [PATCH 359/749] Added test that dice rolls are random. --- 29 Craps/csharp/Craps/Craps/Dice.cs | 5 +- 29 Craps/csharp/Craps/Craps/Program.cs | 3 +- .../csharp/Craps/CrapsTester/CrapsTests.cs | 65 +++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/29 Craps/csharp/Craps/Craps/Dice.cs b/29 Craps/csharp/Craps/Craps/Dice.cs index 3485f0f6..43186026 100644 --- a/29 Craps/csharp/Craps/Craps/Dice.cs +++ b/29 Craps/csharp/Craps/Craps/Dice.cs @@ -1,6 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; + namespace Craps { @@ -19,6 +18,6 @@ namespace Craps this.sides = sides; } - public int Roll() => rand.Next(1, sides); + public int Roll() => rand.Next(1, sides + 1); } } diff --git a/29 Craps/csharp/Craps/Craps/Program.cs b/29 Craps/csharp/Craps/Craps/Program.cs index 17688427..d8109a16 100644 --- a/29 Craps/csharp/Craps/Craps/Program.cs +++ b/29 Craps/csharp/Craps/Craps/Program.cs @@ -1,12 +1,13 @@ using System; + + namespace Craps { class Program { static void Main(string[] args) { - Console.WriteLine("Hello World!"); } } } diff --git a/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs b/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs index 9765ba61..2534f21f 100644 --- a/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs +++ b/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs @@ -1,6 +1,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Craps; + + namespace CrapsTester { [TestClass] @@ -27,5 +29,68 @@ namespace CrapsTester Assert.IsTrue(roll >= 1 && roll <= dice.sides); } } + + [TestMethod] + public void DiceRollsAreRandom() + { + // Roll 600,000 dice and count how many rolls there are for each side. + + var dice = new Dice(); + + int numOnes = 0; + int numTwos = 0; + int numThrees = 0; + int numFours = 0; + int numFives = 0; + int numSixes = 0; + int numErrors = 0; + + for (int i = 0; i < 600000; i++) + { + switch (dice.Roll()) + { + case 1: + numOnes++; + break; + + case 2: + numTwos++; + break; + + case 3: + numThrees++; + break; + + case 4: + numFours++; + break; + + case 5: + numFives++; + break; + + case 6: + numSixes++; + break; + + default: + numErrors++; + break; + } + } + + // We'll assume that a variation of 10% in rolls for the different numbers is random enough. + // Perfectly random rolling would produce 100000 rolls per side, +/- 5% of this gives the + // range 90000..110000. + const int minRolls = 95000; + const int maxRolls = 105000; + Assert.IsTrue(numOnes >= minRolls && numOnes <= maxRolls); + Assert.IsTrue(numTwos >= minRolls && numTwos <= maxRolls); + Assert.IsTrue(numThrees >= minRolls && numThrees <= maxRolls); + Assert.IsTrue(numFours >= minRolls && numFours <= maxRolls); + Assert.IsTrue(numFives >= minRolls && numFives <= maxRolls); + Assert.IsTrue(numSixes >= minRolls && numSixes <= maxRolls); + Assert.AreEqual(numErrors, 0); + } } } From 815dc4ae722a15c21a6ccd2a980aa5a39c96190d Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Sun, 11 Apr 2021 23:54:46 +0100 Subject: [PATCH 360/749] First cut at implementing the game. Added .gitignore file. --- 29 Craps/csharp/Craps/.gitignore | 5 ++ 29 Craps/csharp/Craps/Craps/Program.cs | 70 ++++++++++++++++++++ 29 Craps/csharp/Craps/Craps/UserInterface.cs | 42 ++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 29 Craps/csharp/Craps/.gitignore create mode 100644 29 Craps/csharp/Craps/Craps/UserInterface.cs diff --git a/29 Craps/csharp/Craps/.gitignore b/29 Craps/csharp/Craps/.gitignore new file mode 100644 index 00000000..c1cb0dce --- /dev/null +++ b/29 Craps/csharp/Craps/.gitignore @@ -0,0 +1,5 @@ +.vs +TestResults +bin +obj + diff --git a/29 Craps/csharp/Craps/Craps/Program.cs b/29 Craps/csharp/Craps/Craps/Program.cs index d8109a16..916f331a 100644 --- a/29 Craps/csharp/Craps/Craps/Program.cs +++ b/29 Craps/csharp/Craps/Craps/Program.cs @@ -6,8 +6,78 @@ namespace Craps { class Program { + enum Result + { + naturalWin, + snakeEyesLoss, + loss, + pointLoss, + pointWin, + }; + static void Main(string[] args) { + var dice1 = new Dice(); + var dice2 = new Dice(); + var ui = new UserInterface(); + + int winnings = 0; + + ui.Intro(); + + do + { + var bet = ui.PlaceBet(); + var diceRoll = dice1.Roll() + dice2.Roll(); + bool isWinner = false; + + if (Win(diceRoll)) + { + winnings += bet; + isWinner = true; + } + else if (Lose(diceRoll)) + { + winnings -= bet; + isWinner = false; + } + else + { + var point = diceRoll; + ui.Point(point); + + while (true) + { + var newRoll = dice1.Roll() + dice2.Roll(); + if (newRoll == point) + { + winnings += bet; + isWinner = true; + break; + } + else if (newRoll == 7) + { + winnings -= bet; + isWinner = false; + break; + } + + ui.RollAgain(); + } + } + + ui.ShowResult(isWinner, bet); + } while (ui.PlayAgain(winnings)); + } + + private static bool Lose(int diceRoll) + { + throw new NotImplementedException(); + } + + private static bool Win(int diceRoll) + { + throw new NotImplementedException(); } } } diff --git a/29 Craps/csharp/Craps/Craps/UserInterface.cs b/29 Craps/csharp/Craps/Craps/UserInterface.cs new file mode 100644 index 00000000..5b1bb280 --- /dev/null +++ b/29 Craps/csharp/Craps/Craps/UserInterface.cs @@ -0,0 +1,42 @@ +using System; + +namespace Craps +{ + public class UserInterface + { + public UserInterface() + { + } + + public void Intro() + { + } + + public int PlaceBet() + { + return 0; + } + + public bool PlayAgain(int bet) + { + throw new NotImplementedException(); + } + + internal void ShowResult(bool isWinner, int winnings) + { + throw new NotImplementedException(); + } + + internal void RollAgain() + { + throw new NotImplementedException(); + } + + internal void Point(int point) + { + throw new NotImplementedException(); + } + } +} + + From 25f8f3bb3f285e381a59394717f69ef6d3f15e0d Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Mon, 12 Apr 2021 23:17:37 +0100 Subject: [PATCH 361/749] Added CrapsGame class. Implemented playing the game but it doesn't work properly yet. --- 29 Craps/csharp/Craps/Craps/CrapsGame.cs | 72 ++++++++++++++ 29 Craps/csharp/Craps/Craps/Program.cs | 78 +++++---------- 29 Craps/csharp/Craps/Craps/UserInterface.cs | 98 ++++++++++++++++--- .../csharp/Craps/CrapsTester/CrapsTests.cs | 2 +- 4 files changed, 179 insertions(+), 71 deletions(-) create mode 100644 29 Craps/csharp/Craps/Craps/CrapsGame.cs diff --git a/29 Craps/csharp/Craps/Craps/CrapsGame.cs b/29 Craps/csharp/Craps/Craps/CrapsGame.cs new file mode 100644 index 00000000..c0da368c --- /dev/null +++ b/29 Craps/csharp/Craps/Craps/CrapsGame.cs @@ -0,0 +1,72 @@ +namespace Craps +{ + public enum Result + { + // It's not used in this program but it's often a good idea to include a "none" + // value in an enum so that you can set an instance of the enum to "invalid" or + // initialise it to "none of the valid values". + noResult, + naturalWin, + snakeEyesLoss, + naturalLoss, + pointLoss, + pointWin, + }; + + class CrapsGame + { + private readonly UserInterface ui; + + public CrapsGame(ref UserInterface ui) + { + this.ui = ui; + } + + public Result Play(out int diceRoll) + { + + var dice1 = new Dice(); + var dice2 = new Dice(); + diceRoll = dice1.Roll() + dice2.Roll(); + + if (Win(diceRoll)) + { + return Result.naturalWin; + } + else if (Lose(diceRoll)) + { + return (diceRoll == 2) ? Result.snakeEyesLoss : Result.naturalLoss; + } + else + { + var point = diceRoll; + ui.Point(point); + + while (true) + { + var newRoll = dice1.Roll() + dice2.Roll(); + if (newRoll == point) + { + return Result.pointWin; + } + else if (newRoll == 7) + { + return Result.pointLoss; + } + + ui.NoPoint(diceRoll); + } + } + } + + private bool Lose(int diceRoll) + { + return diceRoll == 2 || diceRoll == 3 || diceRoll == 12; + } + + private bool Win(int diceRoll) + { + return diceRoll == 7 || diceRoll == 11; + } + } +} diff --git a/29 Craps/csharp/Craps/Craps/Program.cs b/29 Craps/csharp/Craps/Craps/Program.cs index 916f331a..31caffd8 100644 --- a/29 Craps/csharp/Craps/Craps/Program.cs +++ b/29 Craps/csharp/Craps/Craps/Program.cs @@ -1,4 +1,4 @@ -using System; +using System.Diagnostics; @@ -6,21 +6,10 @@ namespace Craps { class Program { - enum Result - { - naturalWin, - snakeEyesLoss, - loss, - pointLoss, - pointWin, - }; - static void Main(string[] args) { - var dice1 = new Dice(); - var dice2 = new Dice(); var ui = new UserInterface(); - + var game = new CrapsGame(ref ui); int winnings = 0; ui.Intro(); @@ -28,56 +17,33 @@ namespace Craps do { var bet = ui.PlaceBet(); - var diceRoll = dice1.Roll() + dice2.Roll(); - bool isWinner = false; + var result = game.Play(out int diceRoll); - if (Win(diceRoll)) + switch (result) { - winnings += bet; - isWinner = true; - } - else if (Lose(diceRoll)) - { - winnings -= bet; - isWinner = false; - } - else - { - var point = diceRoll; - ui.Point(point); + case Result.naturalWin: + winnings += bet; + break; - while (true) - { - var newRoll = dice1.Roll() + dice2.Roll(); - if (newRoll == point) - { - winnings += bet; - isWinner = true; - break; - } - else if (newRoll == 7) - { - winnings -= bet; - isWinner = false; - break; - } + case Result.naturalLoss: + case Result.snakeEyesLoss: + case Result.pointLoss: + winnings -= bet; + break; - ui.RollAgain(); - } + case Result.pointWin: + winnings += (2 * bet); + break; + + // Include a default so that we will be warned if the values of the enum + // ever change and we forget to add code to handle the new value. + default: + Debug.Assert(false); // We should never get here. + break; } - ui.ShowResult(isWinner, bet); + ui.ShowResult(result, diceRoll, bet); } while (ui.PlayAgain(winnings)); } - - private static bool Lose(int diceRoll) - { - throw new NotImplementedException(); - } - - private static bool Win(int diceRoll) - { - throw new NotImplementedException(); - } } } diff --git a/29 Craps/csharp/Craps/Craps/UserInterface.cs b/29 Craps/csharp/Craps/Craps/UserInterface.cs index 5b1bb280..72bdb17b 100644 --- a/29 Craps/csharp/Craps/Craps/UserInterface.cs +++ b/29 Craps/csharp/Craps/Craps/UserInterface.cs @@ -1,40 +1,110 @@ using System; +using System.Diagnostics; + + namespace Craps { - public class UserInterface + public class UserInterface { - public UserInterface() - { - } - public void Intro() { + Console.WriteLine(" CRAPS"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n"); + Console.WriteLine("2,3,12 ARE LOSERS; 4,5,6,8,9,10 ARE POINTS; 7,11 ARE NATURAL WINNERS."); + + // In the original game a random number would be generated and then thrown away for as many + // times as the number the user entered. This is presumably something to do with ensuring + // that different random numbers will be generated each time the program is run. + // + // This is not necessary in C#; the random number generator uses the time as a seed so the + // results will always be different every time it is run. + // + // So that the game exactly matches the original game we ask the question but then ignore the + // answer. + Console.WriteLine("PICK A NUMBER AND INPUT TO ROLL DICE"); + GetInt(); } - public int PlaceBet() + public int PlaceBet() { - return 0; + Console.WriteLine("INPUT THE AMOUNT OF YOUR WAGER."); + int n = GetInt(); + Console.WriteLine("I WILL NOW THROW THE DICE"); + + return n; } public bool PlayAgain(int bet) { - throw new NotImplementedException(); + // Goodness knows why we have to enter 5 to play + // again but that's what the original game asked. + Console.WriteLine("IF YOU WANT TO PLAY AGAIN PRINT 5 IF NOT PRINT 2"); + + return GetInt() == 5; } - internal void ShowResult(bool isWinner, int winnings) + public void NoPoint(int diceRoll) { - throw new NotImplementedException(); + Console.WriteLine($"{diceRoll} - NO POINT. I WILL ROLL AGAIN "); } - internal void RollAgain() + public void Point(int point) { - throw new NotImplementedException(); + Console.WriteLine($"{point} IS THE POINT. I WILL ROLL AGAIN"); } - internal void Point(int point) + public void ShowResult(Result result, int diceRoll, int bet) { - throw new NotImplementedException(); + switch (result) + { + case Result.naturalWin: + Console.WriteLine($"{diceRoll} - NATURAL....A WINNER!!!!"); + Console.WriteLine($"{diceRoll} PAYS EVEN MONEY, YOU WIN {bet} DOLLARS"); + break; + + case Result.naturalLoss: + Console.WriteLine($"{diceRoll} - CRAPS...YOU LOSE."); + Console.WriteLine($"YOU LOSE {bet} DOLLARS."); + break; + + case Result.snakeEyesLoss: + Console.WriteLine($"{diceRoll} - SNAKE EYES....YOU LOSE."); + Console.WriteLine($"YOU LOSE {bet} DOLLARS."); + break; + + case Result.pointLoss: + Console.WriteLine($"{diceRoll} - CRAPS. YOU LOSE."); + Console.WriteLine($"YOU LOSE ${bet}"); + break; + + case Result.pointWin: + Console.WriteLine($"{diceRoll} - A WINNER.........CONGRATS!!!!!!!!"); + Console.WriteLine($"AT 2 TO 1 ODDS PAYS YOU...LET ME SEE... {2 * bet} DOLLARS"); + break; + + // Include a default so that we will be warned if the values of the enum + // ever change and we forget to add code to handle the new value. + default: + Debug.Assert(false); // We should never get here. + break; + } + } + + private int GetInt() + { + while (true) + { + string input = Console.ReadLine(); + if (int.TryParse(input, out int n)) + { + return n; + } + else + { + Console.WriteLine("ENTER AN INTEGER"); + } + } } } } diff --git a/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs b/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs index 2534f21f..576c2b82 100644 --- a/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs +++ b/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs @@ -1,5 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; using Craps; +using Microsoft.VisualStudio.TestTools.UnitTesting; From 2de853ade3db4550648af8a70d82922419f400e8 Mon Sep 17 00:00:00 2001 From: Dave LeCompte Date: Tue, 13 Apr 2021 21:08:06 -0700 Subject: [PATCH 362/749] Fix missing global variable --- 04 Awari/python/awari.py | 1 + 1 file changed, 1 insertion(+) diff --git a/04 Awari/python/awari.py b/04 Awari/python/awari.py index de97ee97..c04cce26 100644 --- a/04 Awari/python/awari.py +++ b/04 Awari/python/awari.py @@ -90,6 +90,7 @@ One could go many directions with this game: game_number = 0 move_count = 0 losing_book = [] +n = 0 MAX_HISTORY = 9 LOSING_BOOK_SIZE = 50 From a97a049ae909651481343e0bb21eaf3573de5450 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Wed, 14 Apr 2021 19:01:58 -0400 Subject: [PATCH 363/749] Ported Calendar to Java. --- 21 Calendar/java/Calendar.java | 175 +++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 21 Calendar/java/Calendar.java diff --git a/21 Calendar/java/Calendar.java b/21 Calendar/java/Calendar.java new file mode 100644 index 00000000..4202a4dc --- /dev/null +++ b/21 Calendar/java/Calendar.java @@ -0,0 +1,175 @@ +/** + * Game of Calendar + *

+ * Based on the BASIC game of Calendar here + * https://github.com/coding-horror/basic-computer-games/blob/main/21%20Calendar/calendar.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Calendar { + + private static final int NUM_WEEK_ROWS = 6; + private static final int NUM_DAYS_PER_WEEK = 7; + private static final int NUM_MONTHS_PER_YEAR = 12; + private static final int[] daysPerMonth = { 0, 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 }; + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(31) + "CALENDAR"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + int dayOfMonth = 0; + int dayOfWeek = 0; + int dayOfYear = 0; + int daysTotal = 0; + int index = 0; + int month = 0; + int row = 0; + + String lineContent = ""; + + for (index = 1; index <= 6; index++) { + System.out.println(""); + } + + daysTotal = -1; + dayOfYear = 0; + + System.out.println(""); + + // Begin loop through all months + for (month = 1; month <= NUM_MONTHS_PER_YEAR; month++) { + + System.out.println(""); + + dayOfYear = dayOfYear + daysPerMonth[month - 1]; + + lineContent = String.format("** %-3d" + "*".repeat(18), dayOfYear); + + switch (month) { + case 1: + lineContent += " JANUARY "; + break; + case 2: + lineContent += " FEBRUARY"; + break; + case 3: + lineContent += " MARCH "; + break; + case 4: + lineContent += " APRIL "; + break; + case 5: + lineContent += " MAY "; + break; + case 6: + lineContent += " JUNE "; + break; + case 7: + lineContent += " JULY "; + break; + case 8: + lineContent += " AUGUST "; + break; + case 9: + lineContent += "SEPTEMBER"; + break; + case 10: + lineContent += " OCTOBER "; + break; + case 11: + lineContent += " NOVEMBER"; + break; + case 12: + lineContent += " DECEMBER"; + break; + default: + break; + } + + lineContent += "*".repeat(18) + " " + (365 - dayOfYear) + "**"; + + System.out.println(lineContent); + System.out.println(""); + + System.out.print(" S M T W"); + System.out.println(" T F S"); + System.out.println(""); + + System.out.println("*".repeat(59)); + + // Begin loop through each week row + for (row = 1; row <= NUM_WEEK_ROWS; row++) { + + System.out.println(""); + + lineContent = " "; + + // Begin loop through days of the week + for (dayOfWeek = 1; dayOfWeek <= NUM_DAYS_PER_WEEK; dayOfWeek++) { + + daysTotal++; + + dayOfMonth = daysTotal - dayOfYear; + + if (dayOfMonth > daysPerMonth[month]) { + row = 6; + break; + } + + if (dayOfMonth > 0) { + lineContent += dayOfMonth; + } + + while (lineContent.length() < (4 + 8 * dayOfWeek)) { + lineContent += " "; + } + + } // End loop through days of the week + + if (dayOfMonth == daysPerMonth[month]) { + row = 6; + daysTotal += dayOfWeek; + System.out.println(lineContent); + break; + } + + System.out.println(lineContent); + + } // End loop through each week row + + daysTotal -= dayOfWeek; + + } // End loop through all months + + for (index = 1; index <= 6; index++) { + System.out.println(""); + } + + } // End of method startGame + + public static void main(String[] args) { + + Calendar game = new Calendar(); + game.play(); + + } // End of method main + +} // End of class Calendar From 6d7e57430e203c4931264efcbfddbf79b7e28836 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 21:21:01 +1000 Subject: [PATCH 364/749] Standardise accessibility keywords and remove dead code. --- 84 Super Star Trek/csharp/Game.cs | 20 +++---- 84 Super Star Trek/csharp/Input.cs | 24 ++++---- .../csharp/Objects/Enterprise.cs | 56 +++++++++---------- 84 Super Star Trek/csharp/Objects/Klingon.cs | 8 +-- 84 Super Star Trek/csharp/Objects/Starbase.cs | 2 +- 84 Super Star Trek/csharp/Output.cs | 10 ++-- 84 Super Star Trek/csharp/Program.cs | 7 ++- 84 Super Star Trek/csharp/Random.cs | 10 ++-- .../csharp/Resources/Strings.cs | 50 ++++++++--------- .../csharp/Space/Coordinates.cs | 10 ++-- 84 Super Star Trek/csharp/Space/Galaxy.cs | 14 ++--- 84 Super Star Trek/csharp/Space/Quadrant.cs | 20 +++---- .../csharp/Space/QuadrantInfo.cs | 14 ++--- .../DirectionDistanceCalculator.cs | 5 +- .../ComputerFunctions/GalacticReport.cs | 2 +- .../StarbaseDataCalculator.cs | 2 +- .../Systems/ComputerFunctions/StatusReport.cs | 2 +- .../TorpedoDataCalculator.cs | 2 +- .../csharp/Systems/DamageControl.cs | 4 +- .../csharp/Systems/LibraryComputer.cs | 2 +- .../csharp/Systems/LongRangeSensors.cs | 7 +-- .../csharp/Systems/PhaserControl.cs | 2 +- .../csharp/Systems/PhotonTubes.cs | 4 +- .../csharp/Systems/ShieldControl.cs | 4 +- .../csharp/Systems/ShortRangeSensors.cs | 4 +- .../csharp/Systems/Subsystem.cs | 15 +++-- .../csharp/Systems/WarpEngines.cs | 2 +- .../csharp/Utils/DirectionAndDistance.cs | 8 +-- 28 files changed, 149 insertions(+), 161 deletions(-) diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index f2e1c819..96261498 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -4,7 +4,6 @@ using SuperStarTrek.Resources; using SuperStarTrek.Space; using SuperStarTrek.Systems; using SuperStarTrek.Systems.ComputerFunctions; -using static System.StringComparison; namespace SuperStarTrek { @@ -22,17 +21,17 @@ namespace SuperStarTrek private int _initialKlingonCount; private Enterprise _enterprise; - public Game() + internal Game(Output output, Input input, Random random) { - _output = new Output(); - _input = new Input(_output); - _random = new Random(); + _output = output; + _input = input; + _random = random; } - public float Stardate => _currentStardate; - public float StardatesRemaining => _finalStarDate - _currentStardate; + internal float Stardate => _currentStardate; + internal float StardatesRemaining => _finalStarDate - _currentStardate; - public void DoIntroduction() + internal void DoIntroduction() { _output.Write(Strings.Title); @@ -44,11 +43,10 @@ namespace SuperStarTrek } } - public void Play() + internal void Play() { Initialise(); var gameOver = false; - var newQuadrantText = Strings.StartText; while (!gameOver) { @@ -120,7 +118,7 @@ namespace SuperStarTrek private Quadrant BuildCurrentQuadrant() => new Quadrant(_galaxy[_currentQuadrant], _enterprise, _random, _galaxy, _input, _output); - public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye"); + internal bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye"); private bool CheckIfStranded() { diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs index 3011738b..2b37b2ba 100644 --- a/84 Super Star Trek/csharp/Input.cs +++ b/84 Super Star Trek/csharp/Input.cs @@ -10,24 +10,24 @@ namespace SuperStarTrek { private readonly Output _output; - public Input(Output output) + internal Input(Output output) { _output = output; } - public void WaitForAnyKeyButEnter(string prompt) + internal void WaitForAnyKeyButEnter(string prompt) { _output.Write($"Hit any key but Enter {prompt} "); while (Console.ReadKey(intercept: true).Key == ConsoleKey.Enter); } - public string GetString(string prompt) + internal string GetString(string prompt) { _output.Prompt(prompt); return Console.ReadLine(); } - public float GetNumber(string prompt) + internal float GetNumber(string prompt) { _output.Prompt(prompt); @@ -44,24 +44,24 @@ namespace SuperStarTrek } } - public (float X, float Y) GetCoordinates(string prompt) + internal (float X, float Y) GetCoordinates(string prompt) { _output.Prompt($"{prompt} (X,Y)"); var responses = ReadNumbers(2); return (responses[0], responses[1]); } - public bool TryGetNumber(string prompt, float minValue, float maxValue, out float value) + internal bool TryGetNumber(string prompt, float minValue, float maxValue, out float value) { value = GetNumber($"{prompt} ({minValue}-{maxValue})"); return value >= minValue && value <= maxValue; } - internal bool GetString(string replayPrompt, string trueValue) - => GetString(replayPrompt).Equals(trueValue, InvariantCultureIgnoreCase); + internal bool GetString(string replayPrompt, string trueValue) => + GetString(replayPrompt).Equals(trueValue, InvariantCultureIgnoreCase); - public Command GetCommand() + internal Command GetCommand() { while(true) { @@ -82,7 +82,7 @@ namespace SuperStarTrek } } - public bool TryGetCourse(string prompt, string officer, out Course course) + internal bool TryGetCourse(string prompt, string officer, out Course course) { if (!TryGetNumber(prompt, 1, 9, out var direction)) { @@ -95,7 +95,7 @@ namespace SuperStarTrek return true; } - public bool GetYesNo(string prompt, YesNoMode mode) + internal bool GetYesNo(string prompt, YesNoMode mode) { _output.Prompt($"{prompt} (Y/N)"); var response = Console.ReadLine().ToUpperInvariant(); @@ -150,7 +150,7 @@ namespace SuperStarTrek return numbers; } - public enum YesNoMode + internal enum YesNoMode { TrueOnY, FalseOnN diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index 4adf81df..2f587631 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using SuperStarTrek.Commands; using SuperStarTrek.Resources; using SuperStarTrek.Space; @@ -31,22 +30,33 @@ namespace SuperStarTrek.Objects _input = input; } - public Quadrant Quadrant => _quadrant; - public Coordinates QuadrantCoordinates => _quadrant.Coordinates; - public Coordinates SectorCoordinates { get; private set; } + internal Quadrant Quadrant => _quadrant; - public string Condition => GetCondition(); - public LibraryComputer Computer => (LibraryComputer)_commandExecutors[Command.COM]; - public ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE]; - public float Energy => TotalEnergy - ShieldControl.ShieldEnergy; - public float TotalEnergy { get; private set; } - public int DamagedSystemCount => _systems.Count(s => s.IsDamaged); - public IEnumerable Systems => _systems; - public PhotonTubes PhotonTubes => (PhotonTubes)_commandExecutors[Command.TOR]; - public bool IsDocked => _quadrant.EnterpriseIsNextToStarbase; - public bool IsStranded => TotalEnergy < 10 || Energy < 10 && ShieldControl.IsDamaged; + internal Coordinates QuadrantCoordinates => _quadrant.Coordinates; - public Enterprise Add(Subsystem system) + internal Coordinates SectorCoordinates { get; private set; } + + internal string Condition => GetCondition(); + + internal LibraryComputer Computer => (LibraryComputer)_commandExecutors[Command.COM]; + + internal ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE]; + + internal float Energy => TotalEnergy - ShieldControl.ShieldEnergy; + + internal float TotalEnergy { get; private set; } + + internal int DamagedSystemCount => _systems.Count(s => s.IsDamaged); + + internal IEnumerable Systems => _systems; + + internal PhotonTubes PhotonTubes => (PhotonTubes)_commandExecutors[Command.TOR]; + + internal bool IsDocked => _quadrant.EnterpriseIsNextToStarbase; + + internal bool IsStranded => TotalEnergy < 10 || Energy < 10 && ShieldControl.IsDamaged; + + internal Enterprise Add(Subsystem system) { _systems.Add(system); _commandExecutors[system.Command] = system; @@ -54,7 +64,7 @@ namespace SuperStarTrek.Objects return this; } - public void StartIn(Quadrant quadrant) + internal void StartIn(Quadrant quadrant) { _quadrant = quadrant; quadrant.Display(Strings.StartText); @@ -68,24 +78,14 @@ namespace SuperStarTrek.Objects _ => "Green" }; - public CommandResult Execute(Command command) + internal CommandResult Execute(Command command) { if (command == Command.XXX) { return CommandResult.GameOver; } return _commandExecutors[command].ExecuteCommand(_quadrant); } - public void Refuel() => TotalEnergy = _maxEnergy; - - internal bool Recognises(string command) - { - throw new NotImplementedException(); - } - - internal string GetCommandList() - { - throw new NotImplementedException(); - } + internal void Refuel() => TotalEnergy = _maxEnergy; public override string ToString() => "<*>"; diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs index 4e277b07..78c307e5 100644 --- a/84 Super Star Trek/csharp/Objects/Klingon.cs +++ b/84 Super Star Trek/csharp/Objects/Klingon.cs @@ -7,19 +7,19 @@ namespace SuperStarTrek.Objects { private readonly Random _random; - public Klingon(Coordinates sector, Random random) + internal Klingon(Coordinates sector, Random random) { Sector = sector; _random = random; Energy = _random.GetFloat(100, 300); } - public float Energy { get; private set; } - public Coordinates Sector { get; private set; } + internal float Energy { get; private set; } + internal Coordinates Sector { get; private set; } public override string ToString() => "+K+"; - public CommandResult FireOn(Enterprise enterprise) + internal CommandResult FireOn(Enterprise enterprise) { var attackStrength = _random.GetFloat(); var distanceToEnterprise = Sector.GetDistanceTo(enterprise.SectorCoordinates); diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs index 4befa73a..1ef4a85e 100644 --- a/84 Super Star Trek/csharp/Objects/Starbase.cs +++ b/84 Super Star Trek/csharp/Objects/Starbase.cs @@ -9,7 +9,7 @@ namespace SuperStarTrek.Objects private readonly Output _output; private readonly float _repairDelay; - public Starbase(Coordinates sector, Random random, Input input, Output output) + internal Starbase(Coordinates sector, Random random, Input input, Output output) { Sector = sector; _repairDelay = random.GetFloat() * 0.5f; diff --git a/84 Super Star Trek/csharp/Output.cs b/84 Super Star Trek/csharp/Output.cs index ed960eea..6a377bce 100644 --- a/84 Super Star Trek/csharp/Output.cs +++ b/84 Super Star Trek/csharp/Output.cs @@ -4,33 +4,33 @@ namespace SuperStarTrek { internal class Output { - public Output Write(string text) + internal Output Write(string text) { Console.Write(text); return this; } - public Output Write(string format, params object[] args) + internal Output Write(string format, params object[] args) { Console.Write(format, args); return this; } - public Output WriteLine(string text = "") + internal Output WriteLine(string text = "") { Console.WriteLine(text); return this; } - public Output NextLine() + internal Output NextLine() { Console.WriteLine(); return this; } - public Output Prompt(string text = "") + internal Output Prompt(string text = "") { Console.Write($"{text}? "); return this; diff --git a/84 Super Star Trek/csharp/Program.cs b/84 Super Star Trek/csharp/Program.cs index 7f8395a6..7080df29 100644 --- a/84 Super Star Trek/csharp/Program.cs +++ b/84 Super Star Trek/csharp/Program.cs @@ -29,8 +29,11 @@ namespace SuperStarTrek { static void Main() { - var foo = Utils.DirectionAndDistance.From(1,1).To(4,5); - var game = new Game(); + var output = new Output(); + var input = new Input(output); + var random = new Random(); + + var game = new Game(output, input, random); game.DoIntroduction(); diff --git a/84 Super Star Trek/csharp/Random.cs b/84 Super Star Trek/csharp/Random.cs index 5ed47805..ae51d95b 100644 --- a/84 Super Star Trek/csharp/Random.cs +++ b/84 Super Star Trek/csharp/Random.cs @@ -6,20 +6,20 @@ namespace SuperStarTrek { private static readonly System.Random _random = new(); - public Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive() - 1, Get1To8Inclusive() - 1); + internal Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive() - 1, Get1To8Inclusive() - 1); // Duplicates the algorithm used in the original code to get an integer value from 1 to 8, inclusive: // 475 DEF FNR(R)=INT(RND(R)*7.98+1.01) // Returns a value from 1 to 8, inclusive. // Note there's a slight bias away from the extreme values, 1 and 8. - public int Get1To8Inclusive() => (int)(GetFloat() * 7.98 + 1.01); + internal int Get1To8Inclusive() => (int)(GetFloat() * 7.98 + 1.01); - public int GetInt(int inclusiveMinValue, int exclusiveMaxValue) => + internal int GetInt(int inclusiveMinValue, int exclusiveMaxValue) => _random.Next(inclusiveMinValue, exclusiveMaxValue); - public float GetFloat() => (float)_random.NextDouble(); + internal float GetFloat() => (float)_random.NextDouble(); - public float GetFloat(float inclusiveMinValue, float exclusiveMaxValue) + internal float GetFloat(float inclusiveMinValue, float exclusiveMaxValue) => GetFloat() * (exclusiveMaxValue - inclusiveMinValue) + inclusiveMinValue; } } diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index ddb768ca..fea41521 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -6,31 +6,31 @@ namespace SuperStarTrek.Resources { internal static class Strings { - public static string CombatArea => GetResource(); - public static string ComputerFunctions => GetResource(); - public static string Congratulations => GetResource(); - public static string CourtMartial => GetResource(); - public static string Destroyed => GetResource(); - public static string EndOfMission => GetResource(); - public static string Enterprise => GetResource(); - public static string Instructions => GetResource(); - public static string LowShields => GetResource(); - public static string NoEnemyShips => GetResource(); - public static string NoStarbase => GetResource(); - public static string NowEntering => GetResource(); - public static string Orders => GetResource(); - public static string PermissionDenied => GetResource(); - public static string Protected => GetResource(); - public static string RegionNames => GetResource(); - public static string RelievedOfCommand => GetResource(); - public static string RepairEstimate => GetResource(); - public static string RepairPrompt => GetResource(); - public static string ReplayPrompt => GetResource(); - public static string ShieldsDropped => GetResource(); - public static string ShortRangeSensorsOut => GetResource(); - public static string StartText => GetResource(); - public static string Stranded => GetResource(); - public static string Title => GetResource(); + internal static string CombatArea => GetResource(); + internal static string ComputerFunctions => GetResource(); + internal static string Congratulations => GetResource(); + internal static string CourtMartial => GetResource(); + internal static string Destroyed => GetResource(); + internal static string EndOfMission => GetResource(); + internal static string Enterprise => GetResource(); + internal static string Instructions => GetResource(); + internal static string LowShields => GetResource(); + internal static string NoEnemyShips => GetResource(); + internal static string NoStarbase => GetResource(); + internal static string NowEntering => GetResource(); + internal static string Orders => GetResource(); + internal static string PermissionDenied => GetResource(); + internal static string Protected => GetResource(); + internal static string RegionNames => GetResource(); + internal static string RelievedOfCommand => GetResource(); + internal static string RepairEstimate => GetResource(); + internal static string RepairPrompt => GetResource(); + internal static string ReplayPrompt => GetResource(); + internal static string ShieldsDropped => GetResource(); + internal static string ShortRangeSensorsOut => GetResource(); + internal static string StartText => GetResource(); + internal static string Stranded => GetResource(); + internal static string Title => GetResource(); private static string GetResource([CallerMemberName] string name = "") { diff --git a/84 Super Star Trek/csharp/Space/Coordinates.cs b/84 Super Star Trek/csharp/Space/Coordinates.cs index 1619d387..4c4f7b69 100644 --- a/84 Super Star Trek/csharp/Space/Coordinates.cs +++ b/84 Super Star Trek/csharp/Space/Coordinates.cs @@ -7,7 +7,7 @@ namespace SuperStarTrek.Space // Note that the origin is top-left, x increase downwards, and y increases to the right. internal record Coordinates { - public Coordinates(int x, int y) + internal Coordinates(int x, int y) { X = Validated(x, nameof(x)); Y = Validated(y, nameof(y)); @@ -16,10 +16,10 @@ namespace SuperStarTrek.Space SubRegionIndex = Y % 4; } - public int X { get; } - public int Y { get; } - public int RegionIndex { get; } - public int SubRegionIndex { get; } + internal int X { get; } + internal int Y { get; } + internal int RegionIndex { get; } + internal int SubRegionIndex { get; } private int Validated(int value, string argumentName) { diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 63838567..8fce8fb9 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -1,7 +1,5 @@ -using System.Collections; using System.Collections.Generic; using System.Linq; -using SuperStarTrek.Objects; using SuperStarTrek.Resources; using static System.StringSplitOptions; @@ -21,7 +19,7 @@ namespace SuperStarTrek.Space _subRegionIdentifiers = new[] { "I", "II", "III", "IV" }; } - public Galaxy(Random random) + internal Galaxy(Random random) { _random = random; @@ -46,16 +44,16 @@ namespace SuperStarTrek.Space } } - public QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X][coordinate.Y]; + internal QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X][coordinate.Y]; - public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount); - public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase); - public IEnumerable> Quadrants => _quadrants; + internal int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount); + internal int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase); + internal IEnumerable> Quadrants => _quadrants; private static string GetQuadrantName(Coordinates coordinates) => $"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}"; - public IEnumerable> GetNeighborhood(Quadrant quadrant) => + internal IEnumerable> GetNeighborhood(Quadrant quadrant) => Enumerable.Range(-1, 3) .Select(dx => dx + quadrant.Coordinates.X) .Select(x => GetNeighborhoodRow(quadrant, x)); diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index b333cb7e..0ed2a567 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -16,7 +16,7 @@ namespace SuperStarTrek.Space private readonly Output _output; private bool _displayed = false; - public Quadrant( + internal Quadrant( QuadrantInfo info, Enterprise enterprise, Random random, @@ -39,13 +39,13 @@ namespace SuperStarTrek.Space PositionObject(_ => new Star(), _info.StarCount); } - public Coordinates Coordinates => _info.Coordinates; - public bool HasKlingons => _info.KlingonCount > 0; - public int KlingonCount => _info.KlingonCount; - public bool HasStarbase => _info.HasStarbase; - public Starbase Starbase { get; } + internal Coordinates Coordinates => _info.Coordinates; + internal bool HasKlingons => _info.KlingonCount > 0; + internal int KlingonCount => _info.KlingonCount; + internal bool HasStarbase => _info.HasStarbase; + internal Starbase Starbase { get; } internal Galaxy Galaxy { get; } - public bool EnterpriseIsNextToStarbase => + internal bool EnterpriseIsNextToStarbase => _info.HasStarbase && Math.Abs(_enterprise.SectorCoordinates.X - Starbase.Sector.X) <= 1 && Math.Abs(_enterprise.SectorCoordinates.Y - Starbase.Sector.Y) <= 1; @@ -166,10 +166,10 @@ namespace SuperStarTrek.Space } } - public IEnumerable GetDisplayLines() => Enumerable.Range(0, 8).Select(x => GetDisplayLine(x)); + internal IEnumerable GetDisplayLines() => Enumerable.Range(0, 8).Select(x => GetDisplayLine(x)); - private string GetDisplayLine(int x) - => string.Join( + private string GetDisplayLine(int x) => + string.Join( " ", Enumerable .Range(0, 8) diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs index 70447250..e37a1a9c 100644 --- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs +++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs @@ -1,5 +1,3 @@ -using SuperStarTrek.Objects; - namespace SuperStarTrek.Space { internal class QuadrantInfo @@ -15,13 +13,13 @@ namespace SuperStarTrek.Space HasStarbase = hasStarbase; } - public Coordinates Coordinates { get; } - public string Name { get; } - public int KlingonCount { get; private set; } - public bool HasStarbase { get; private set; } - public int StarCount { get; } + internal Coordinates Coordinates { get; } + internal string Name { get; } + internal int KlingonCount { get; private set; } + internal bool HasStarbase { get; private set; } + internal int StarCount { get; } - public static QuadrantInfo Create(Coordinates coordinates, string name) + internal static QuadrantInfo Create(Coordinates coordinates, string name) { var random = new Random(); var klingonCount = random.GetFloat() switch diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs index ff6239ed..f59865a0 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; using SuperStarTrek.Objects; using SuperStarTrek.Space; @@ -11,7 +8,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions private readonly Enterprise _enterprise; private readonly Input _input; - public DirectionDistanceCalculator(Enterprise enterprise, Output output, Input input) + internal DirectionDistanceCalculator(Enterprise enterprise, Output output, Input input) : base("Starbase nav data", output) { _enterprise = enterprise; diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs index 8b26cc2e..8be29baf 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs @@ -6,7 +6,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions { internal abstract class GalacticReport : ComputerFunction { - public GalacticReport(string description, Output output, Galaxy galaxy) + internal GalacticReport(string description, Output output, Galaxy galaxy) : base(description, output) { Galaxy = galaxy; diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs index 0d2c5b50..7a87f970 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs @@ -8,7 +8,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions { private readonly Enterprise _enterprise; - public StarbaseDataCalculator(Enterprise enterprise, Output output) + internal StarbaseDataCalculator(Enterprise enterprise, Output output) : base("Starbase nav data", output) { _enterprise = enterprise; diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs index f80ba7bb..26a299a8 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs @@ -10,7 +10,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions private readonly Galaxy _galaxy; private readonly Enterprise _enterprise; - public StatusReport(Game game, Galaxy galaxy, Enterprise enterprise, Output output) + internal StatusReport(Game game, Galaxy galaxy, Enterprise enterprise, Output output) : base("Status report", output) { _game = game; diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs index 09c71859..ec837fc4 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs @@ -8,7 +8,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions { private readonly Enterprise _enterprise; - public TorpedoDataCalculator(Enterprise enterprise, Output output) + internal TorpedoDataCalculator(Enterprise enterprise, Output output) : base("Photon torpedo data", output) { _enterprise = enterprise; diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84 Super Star Trek/csharp/Systems/DamageControl.cs index 6ce41bbe..8fbf21d3 100644 --- a/84 Super Star Trek/csharp/Systems/DamageControl.cs +++ b/84 Super Star Trek/csharp/Systems/DamageControl.cs @@ -9,7 +9,7 @@ namespace SuperStarTrek.Systems private readonly Enterprise _enterprise; private readonly Output _output; - public DamageControl(Enterprise enterprise, Output output) + internal DamageControl(Enterprise enterprise, Output output) : base("Damage Control", Command.DAM, output) { _enterprise = enterprise; @@ -40,7 +40,7 @@ namespace SuperStarTrek.Systems return CommandResult.Ok; } - public void WriteDamageReport() + internal void WriteDamageReport() { _output.NextLine().WriteLine("Device State of Repair"); foreach (var system in _enterprise.Systems) diff --git a/84 Super Star Trek/csharp/Systems/LibraryComputer.cs b/84 Super Star Trek/csharp/Systems/LibraryComputer.cs index b2e47d2a..df5c6868 100644 --- a/84 Super Star Trek/csharp/Systems/LibraryComputer.cs +++ b/84 Super Star Trek/csharp/Systems/LibraryComputer.cs @@ -10,7 +10,7 @@ namespace SuperStarTrek.Systems private readonly Input _input; private readonly ComputerFunction[] _functions; - public LibraryComputer(Output output, Input input, params ComputerFunction[] functions) + internal LibraryComputer(Output output, Input input, params ComputerFunction[] functions) : base("Library-Computer", Command.COM, output) { _output = output; diff --git a/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs b/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs index 84ed7a87..a873eeba 100644 --- a/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs +++ b/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs @@ -1,10 +1,5 @@ - -using System; -using System.Collections.Generic; using System.Linq; using SuperStarTrek.Commands; -using SuperStarTrek.Objects; -using SuperStarTrek.Resources; using SuperStarTrek.Space; namespace SuperStarTrek.Systems @@ -14,7 +9,7 @@ namespace SuperStarTrek.Systems private readonly Galaxy _galaxy; private readonly Output _output; - public LongRangeSensors(Galaxy galaxy, Output output) + internal LongRangeSensors(Galaxy galaxy, Output output) : base("Long Range Sensors", Command.LRS, output) { _galaxy = galaxy; diff --git a/84 Super Star Trek/csharp/Systems/PhaserControl.cs b/84 Super Star Trek/csharp/Systems/PhaserControl.cs index 18566294..9207ad94 100644 --- a/84 Super Star Trek/csharp/Systems/PhaserControl.cs +++ b/84 Super Star Trek/csharp/Systems/PhaserControl.cs @@ -13,7 +13,7 @@ namespace SuperStarTrek.Systems private readonly Input _input; private readonly Random _random; - public PhaserControl(Enterprise enterprise, Output output, Input input, Random random) + internal PhaserControl(Enterprise enterprise, Output output, Input input, Random random) : base("Phaser Control", Command.PHA, output) { _enterprise = enterprise; diff --git a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs index a807d16c..37613037 100644 --- a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs +++ b/84 Super Star Trek/csharp/Systems/PhotonTubes.cs @@ -11,7 +11,7 @@ namespace SuperStarTrek.Systems private readonly Output _output; private readonly Input _input; - public PhotonTubes(int tubeCount, Enterprise enterprise, Output output, Input input) + internal PhotonTubes(int tubeCount, Enterprise enterprise, Output output, Input input) : base("Photon Tubes", Command.TOR, output) { TorpedoCount = _tubeCount = tubeCount; @@ -20,7 +20,7 @@ namespace SuperStarTrek.Systems _input = input; } - public int TorpedoCount { get; private set; } + internal int TorpedoCount { get; private set; } protected override bool CanExecuteCommand() => HasTorpedoes() && IsOperational("{name} are not operational"); diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs index a7518359..df42c125 100644 --- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs +++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs @@ -10,7 +10,7 @@ namespace SuperStarTrek.Systems private readonly Output _output; private readonly Input _input; - public ShieldControl(Enterprise enterprise, Output output, Input input) + internal ShieldControl(Enterprise enterprise, Output output, Input input) : base("Shield Control", Command.SHE, output) { _enterprise = enterprise; @@ -18,7 +18,7 @@ namespace SuperStarTrek.Systems _input = input; } - public float ShieldEnergy { get; set; } + internal float ShieldEnergy { get; set; } protected override bool CanExecuteCommand() => IsOperational("{name} inoperable"); diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs index ad3929d1..c37028cb 100644 --- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs +++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs @@ -16,7 +16,7 @@ namespace SuperStarTrek.Systems private readonly Game _game; private readonly Output _output; - public ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, Output output) + internal ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, Output output) : base("Short Range Sensors", Command.SRS, output) { _enterprise = enterprise; @@ -47,7 +47,7 @@ namespace SuperStarTrek.Systems return CommandResult.Ok; } - public IEnumerable GetStatusLines() + internal IEnumerable GetStatusLines() { yield return $"Stardate {_game.Stardate}"; yield return $"Condition {_enterprise.Condition}"; diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs index 9e5f3570..2e11e3e7 100644 --- a/84 Super Star Trek/csharp/Systems/Subsystem.cs +++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs @@ -1,4 +1,3 @@ -using System; using SuperStarTrek.Commands; using SuperStarTrek.Space; @@ -16,10 +15,10 @@ namespace SuperStarTrek.Systems _output = output; } - public string Name { get; } - public float Condition { get; private set; } - public bool IsDamaged => Condition < 0; - public Command Command { get; } + internal string Name { get; } + internal float Condition { get; private set; } + internal bool IsDamaged => Condition < 0; + internal Command Command { get; } protected virtual bool CanExecuteCommand() => true; @@ -34,12 +33,12 @@ namespace SuperStarTrek.Systems return true; } - public CommandResult ExecuteCommand(Quadrant quadrant) + internal CommandResult ExecuteCommand(Quadrant quadrant) => CanExecuteCommand() ? ExecuteCommandCore(quadrant) : CommandResult.Ok; protected abstract CommandResult ExecuteCommandCore(Quadrant quadrant); - public virtual void Repair() + internal virtual void Repair() { if (IsDamaged) { @@ -47,7 +46,7 @@ namespace SuperStarTrek.Systems } } - public virtual bool Repair(float repairWorkDone) + internal virtual bool Repair(float repairWorkDone) { if (IsDamaged) { diff --git a/84 Super Star Trek/csharp/Systems/WarpEngines.cs b/84 Super Star Trek/csharp/Systems/WarpEngines.cs index 0dcf396c..4203f4e8 100644 --- a/84 Super Star Trek/csharp/Systems/WarpEngines.cs +++ b/84 Super Star Trek/csharp/Systems/WarpEngines.cs @@ -11,7 +11,7 @@ namespace SuperStarTrek.Systems private readonly Output _output; private readonly Input _input; - public WarpEngines(Enterprise enterprise, Output output, Input input) + internal WarpEngines(Enterprise enterprise, Output output, Input input) : base("Warp Engines", Command.NAV, output) { _enterprise = enterprise; diff --git a/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs b/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs index 3fa9f4b8..65cb6a30 100644 --- a/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs +++ b/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs @@ -14,13 +14,13 @@ namespace SuperStarTrek.Utils _fromY = fromY; } - public static DirectionAndDistance From(Coordinates coordinates) => From(coordinates.X, coordinates.Y); + internal static DirectionAndDistance From(Coordinates coordinates) => From(coordinates.X, coordinates.Y); - public static DirectionAndDistance From(float x, float y) => new DirectionAndDistance(x, y); + internal static DirectionAndDistance From(float x, float y) => new DirectionAndDistance(x, y); - public (float Direction, float Distance) To(Coordinates coordinates) => To(coordinates.X, coordinates.Y); + internal (float Direction, float Distance) To(Coordinates coordinates) => To(coordinates.X, coordinates.Y); - public (float Direction, float Distance) To(float x, float y) + internal (float Direction, float Distance) To(float x, float y) { var deltaX = x - _fromX; var deltaY = y - _fromY; From 2aee62dd476b813eeeb986b5d869b66f4e31536c Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 21:31:53 +1000 Subject: [PATCH 365/749] Fix compiler messages --- 84 Super Star Trek/csharp/Random.cs | 2 +- 84 Super Star Trek/csharp/Resources/Strings.cs | 4 +--- 84 Super Star Trek/csharp/Space/Coordinates.cs | 2 +- 84 Super Star Trek/csharp/Space/Course.cs | 2 +- 84 Super Star Trek/csharp/Space/Galaxy.cs | 3 --- 84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs | 4 ++-- 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/84 Super Star Trek/csharp/Random.cs b/84 Super Star Trek/csharp/Random.cs index ae51d95b..cd0ef230 100644 --- a/84 Super Star Trek/csharp/Random.cs +++ b/84 Super Star Trek/csharp/Random.cs @@ -4,7 +4,7 @@ namespace SuperStarTrek { internal class Random { - private static readonly System.Random _random = new(); + private readonly System.Random _random = new(); internal Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive() - 1, Get1To8Inclusive() - 1); diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index fea41521..72fd7d5a 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -35,9 +35,7 @@ namespace SuperStarTrek.Resources private static string GetResource([CallerMemberName] string name = "") { var streamName = $"SuperStarTrek.Resources.{name}.txt"; - using var stream = Assembly - .GetExecutingAssembly() - .GetManifestResourceStream(streamName); + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(streamName); using var reader = new StreamReader(stream); return reader.ReadToEnd(); diff --git a/84 Super Star Trek/csharp/Space/Coordinates.cs b/84 Super Star Trek/csharp/Space/Coordinates.cs index 4c4f7b69..4bcc8085 100644 --- a/84 Super Star Trek/csharp/Space/Coordinates.cs +++ b/84 Super Star Trek/csharp/Space/Coordinates.cs @@ -21,7 +21,7 @@ namespace SuperStarTrek.Space internal int RegionIndex { get; } internal int SubRegionIndex { get; } - private int Validated(int value, string argumentName) + private static int Validated(int value, string argumentName) { if (value >= 0 && value <= 7) { return value; } diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs index a46385c3..7067ec81 100644 --- a/84 Super Star Trek/csharp/Space/Course.cs +++ b/84 Super Star Trek/csharp/Space/Course.cs @@ -74,7 +74,7 @@ namespace SuperStarTrek.Space return (xComplete && yComplete, new Coordinates(quadrantX, quadrantY), new Coordinates(sectorX, sectorY)); } - private (bool, int, int) GetNewCoordinate(int quadrant, int sector, float sectorsTravelled) + private static (bool, int, int) GetNewCoordinate(int quadrant, int sector, float sectorsTravelled) { var galacticCoordinate = quadrant * 8 + sector + sectorsTravelled; var newQuadrant = (int)(galacticCoordinate / 8); diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 8fce8fb9..66f7c418 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -11,7 +11,6 @@ namespace SuperStarTrek.Space private static readonly string[] _regionNames; private static readonly string[] _subRegionIdentifiers; private readonly QuadrantInfo[][] _quadrants; - private readonly Random _random; static Galaxy() { @@ -21,8 +20,6 @@ namespace SuperStarTrek.Space internal Galaxy(Random random) { - _random = random; - _quadrants = Enumerable .Range(0, 8) .Select(x => Enumerable diff --git a/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs b/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs index 65cb6a30..e4b1a2fa 100644 --- a/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs +++ b/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs @@ -45,7 +45,7 @@ namespace SuperStarTrek.Utils // 8430 PRINT"DIRECTION =";C1+(((ABS(X)-ABS(A))+ABS(X))/ABS(X)):GOTO8460 // 8450 PRINT"DIRECTION =";C1+(ABS(X)/ABS(A)) // 8460 PRINT"DISTANCE =";SQR(X^2+A^2):IFH8=1THEN1990 - private float GetDirection(float deltaX, float deltaY) + private static float GetDirection(float deltaX, float deltaY) { var deltaXDominant = Math.Abs(deltaX) > Math.Abs(deltaY); var fractionalPart = deltaXDominant ? deltaY / deltaX : -deltaX / deltaY; @@ -59,7 +59,7 @@ namespace SuperStarTrek.Utils return direction < 1 ? direction + 8 : direction; } - private float GetDistance(float deltaX, float deltaY) => + private static float GetDistance(float deltaX, float deltaY) => (float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2)); } } \ No newline at end of file From 99a847813c56964e440b6dea4f54440c5c364216 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 21:39:21 +1000 Subject: [PATCH 366/749] Inject Random into QuadrantInfo --- 84 Super Star Trek/csharp/Space/Galaxy.cs | 2 +- 84 Super Star Trek/csharp/Space/QuadrantInfo.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 66f7c418..91961b38 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -25,7 +25,7 @@ namespace SuperStarTrek.Space .Select(x => Enumerable .Range(0, 8) .Select(y => new Coordinates(x, y)) - .Select(c => QuadrantInfo.Create(c, GetQuadrantName(c))) + .Select(c => QuadrantInfo.Create(c, GetQuadrantName(c), random)) .ToArray()) .ToArray(); diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs index e37a1a9c..31626a35 100644 --- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs +++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs @@ -19,9 +19,8 @@ namespace SuperStarTrek.Space internal bool HasStarbase { get; private set; } internal int StarCount { get; } - internal static QuadrantInfo Create(Coordinates coordinates, string name) + internal static QuadrantInfo Create(Coordinates coordinates, string name, Random random) { - var random = new Random(); var klingonCount = random.GetFloat() switch { > 0.98f => 3, From 0f795c07250f82c37c0f95e2583455c71a8605e3 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 21:44:43 +1000 Subject: [PATCH 367/749] Normalise member spacing --- 84 Super Star Trek/csharp/Game.cs | 1 + 84 Super Star Trek/csharp/Objects/Klingon.cs | 1 + 84 Super Star Trek/csharp/Objects/Starbase.cs | 1 + .../csharp/Resources/Strings.cs | 24 +++++++++++++++++++ .../csharp/Space/Coordinates.cs | 3 +++ 84 Super Star Trek/csharp/Space/Course.cs | 1 + 84 Super Star Trek/csharp/Space/Galaxy.cs | 2 ++ 84 Super Star Trek/csharp/Space/Quadrant.cs | 6 +++++ .../csharp/Space/QuadrantInfo.cs | 4 ++++ .../ComputerFunctions/ComputerFunction.cs | 1 + .../csharp/Systems/Subsystem.cs | 3 +++ 11 files changed, 47 insertions(+) diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index 96261498..92c16a83 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -29,6 +29,7 @@ namespace SuperStarTrek } internal float Stardate => _currentStardate; + internal float StardatesRemaining => _finalStarDate - _currentStardate; internal void DoIntroduction() diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84 Super Star Trek/csharp/Objects/Klingon.cs index 78c307e5..1b55940a 100644 --- a/84 Super Star Trek/csharp/Objects/Klingon.cs +++ b/84 Super Star Trek/csharp/Objects/Klingon.cs @@ -15,6 +15,7 @@ namespace SuperStarTrek.Objects } internal float Energy { get; private set; } + internal Coordinates Sector { get; private set; } public override string ToString() => "+K+"; diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs index 1ef4a85e..c9abb870 100644 --- a/84 Super Star Trek/csharp/Objects/Starbase.cs +++ b/84 Super Star Trek/csharp/Objects/Starbase.cs @@ -18,6 +18,7 @@ namespace SuperStarTrek.Objects } internal Coordinates Sector { get; } + public override string ToString() => ">!<"; internal bool TryRepair(Enterprise enterprise, out float repairTime) diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index 72fd7d5a..c3dcedf6 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -7,29 +7,53 @@ namespace SuperStarTrek.Resources internal static class Strings { internal static string CombatArea => GetResource(); + internal static string ComputerFunctions => GetResource(); + internal static string Congratulations => GetResource(); + internal static string CourtMartial => GetResource(); + internal static string Destroyed => GetResource(); + internal static string EndOfMission => GetResource(); + internal static string Enterprise => GetResource(); + internal static string Instructions => GetResource(); + internal static string LowShields => GetResource(); + internal static string NoEnemyShips => GetResource(); + internal static string NoStarbase => GetResource(); + internal static string NowEntering => GetResource(); + internal static string Orders => GetResource(); + internal static string PermissionDenied => GetResource(); + internal static string Protected => GetResource(); + internal static string RegionNames => GetResource(); + internal static string RelievedOfCommand => GetResource(); + internal static string RepairEstimate => GetResource(); + internal static string RepairPrompt => GetResource(); + internal static string ReplayPrompt => GetResource(); + internal static string ShieldsDropped => GetResource(); + internal static string ShortRangeSensorsOut => GetResource(); + internal static string StartText => GetResource(); + internal static string Stranded => GetResource(); + internal static string Title => GetResource(); private static string GetResource([CallerMemberName] string name = "") diff --git a/84 Super Star Trek/csharp/Space/Coordinates.cs b/84 Super Star Trek/csharp/Space/Coordinates.cs index 4bcc8085..7aec927f 100644 --- a/84 Super Star Trek/csharp/Space/Coordinates.cs +++ b/84 Super Star Trek/csharp/Space/Coordinates.cs @@ -17,8 +17,11 @@ namespace SuperStarTrek.Space } internal int X { get; } + internal int Y { get; } + internal int RegionIndex { get; } + internal int SubRegionIndex { get; } private static int Validated(int value, string argumentName) diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs index 7067ec81..6418b15b 100644 --- a/84 Super Star Trek/csharp/Space/Course.cs +++ b/84 Super Star Trek/csharp/Space/Course.cs @@ -46,6 +46,7 @@ namespace SuperStarTrek.Space } internal float DeltaX { get; } + internal float DeltaY { get; } internal IEnumerable GetSectorsFrom(Coordinates start) diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84 Super Star Trek/csharp/Space/Galaxy.cs index 91961b38..0b348b06 100644 --- a/84 Super Star Trek/csharp/Space/Galaxy.cs +++ b/84 Super Star Trek/csharp/Space/Galaxy.cs @@ -44,7 +44,9 @@ namespace SuperStarTrek.Space internal QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X][coordinate.Y]; internal int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount); + internal int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase); + internal IEnumerable> Quadrants => _quadrants; private static string GetQuadrantName(Coordinates coordinates) => diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index 0ed2a567..29f8e0ce 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -40,11 +40,17 @@ namespace SuperStarTrek.Space } internal Coordinates Coordinates => _info.Coordinates; + internal bool HasKlingons => _info.KlingonCount > 0; + internal int KlingonCount => _info.KlingonCount; + internal bool HasStarbase => _info.HasStarbase; + internal Starbase Starbase { get; } + internal Galaxy Galaxy { get; } + internal bool EnterpriseIsNextToStarbase => _info.HasStarbase && Math.Abs(_enterprise.SectorCoordinates.X - Starbase.Sector.X) <= 1 && diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs index 31626a35..6a403c2e 100644 --- a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs +++ b/84 Super Star Trek/csharp/Space/QuadrantInfo.cs @@ -14,9 +14,13 @@ namespace SuperStarTrek.Space } internal Coordinates Coordinates { get; } + internal string Name { get; } + internal int KlingonCount { get; private set; } + internal bool HasStarbase { get; private set; } + internal int StarCount { get; } internal static QuadrantInfo Create(Coordinates coordinates, string name, Random random) diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs index 400c1f62..36d9127b 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs @@ -11,6 +11,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions } internal string Description { get; } + protected Output Output { get; } internal abstract void Execute(Quadrant quadrant); diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs index 2e11e3e7..5c11e656 100644 --- a/84 Super Star Trek/csharp/Systems/Subsystem.cs +++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs @@ -16,8 +16,11 @@ namespace SuperStarTrek.Systems } internal string Name { get; } + internal float Condition { get; private set; } + internal bool IsDamaged => Condition < 0; + internal Command Command { get; } protected virtual bool CanExecuteCommand() => true; From 315bdc04327ac7f31013de7d603bd18ff29ad4aa Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 21:48:27 +1000 Subject: [PATCH 368/749] Remove unsed string resource --- .../csharp/Resources/ComputerFunctions.txt | 9 --------- 84 Super Star Trek/csharp/Resources/Strings.cs | 2 -- 2 files changed, 11 deletions(-) delete mode 100644 84 Super Star Trek/csharp/Resources/ComputerFunctions.txt diff --git a/84 Super Star Trek/csharp/Resources/ComputerFunctions.txt b/84 Super Star Trek/csharp/Resources/ComputerFunctions.txt deleted file mode 100644 index 4827b0fe..00000000 --- a/84 Super Star Trek/csharp/Resources/ComputerFunctions.txt +++ /dev/null @@ -1,9 +0,0 @@ - -Functions available from Library-Computer: - 0 = Cumulative galactic record - 1 = Status report - 2 = Photon torpedo data - 3 = Starbase nav data - 4 = Direction/distance calculator - 5 = Galaxy 'region name' map - diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index c3dcedf6..6fd472c1 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -8,8 +8,6 @@ namespace SuperStarTrek.Resources { internal static string CombatArea => GetResource(); - internal static string ComputerFunctions => GetResource(); - internal static string Congratulations => GetResource(); internal static string CourtMartial => GetResource(); From 3165a9226a79ef13ae24cc278d6babaccd1bebce Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 21:51:20 +1000 Subject: [PATCH 369/749] Fix computer function name --- .../Systems/ComputerFunctions/DirectionDistanceCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs index f59865a0..a3679ada 100644 --- a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs +++ b/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs @@ -9,7 +9,7 @@ namespace SuperStarTrek.Systems.ComputerFunctions private readonly Input _input; internal DirectionDistanceCalculator(Enterprise enterprise, Output output, Input input) - : base("Starbase nav data", output) + : base("Direction/distance calculator", output) { _enterprise = enterprise; _input = input; From 471af5bf4079fa9b1344fdbea592bb354c2e8ff4 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 22:02:36 +1000 Subject: [PATCH 370/749] Fix shield set text --- 84 Super Star Trek/csharp/Resources/ShieldsSet.txt | 2 ++ 84 Super Star Trek/csharp/Resources/Strings.cs | 2 ++ 84 Super Star Trek/csharp/Systems/ShieldControl.cs | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 84 Super Star Trek/csharp/Resources/ShieldsSet.txt diff --git a/84 Super Star Trek/csharp/Resources/ShieldsSet.txt b/84 Super Star Trek/csharp/Resources/ShieldsSet.txt new file mode 100644 index 00000000..e3d7efda --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/ShieldsSet.txt @@ -0,0 +1,2 @@ +Deflector control room report: + 'Shields now at {0} units per your command.' diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index 6fd472c1..b6cd5486 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -46,6 +46,8 @@ namespace SuperStarTrek.Resources internal static string ShieldsDropped => GetResource(); + internal static string ShieldsSet => GetResource(); + internal static string ShortRangeSensorsOut => GetResource(); internal static string StartText => GetResource(); diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84 Super Star Trek/csharp/Systems/ShieldControl.cs index df42c125..de4f44d9 100644 --- a/84 Super Star Trek/csharp/Systems/ShieldControl.cs +++ b/84 Super Star Trek/csharp/Systems/ShieldControl.cs @@ -1,5 +1,6 @@ using SuperStarTrek.Commands; using SuperStarTrek.Objects; +using SuperStarTrek.Resources; using SuperStarTrek.Space; namespace SuperStarTrek.Systems @@ -30,6 +31,7 @@ namespace SuperStarTrek.Systems if (Validate(requested)) { ShieldEnergy = requested; + _output.Write(Strings.ShieldsSet, requested); } else { From 1c1eead60a422935f4d13aac5e668a4f419d3e12 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 22:04:49 +1000 Subject: [PATCH 371/749] Fix "Now entering ..." text spacing --- 84 Super Star Trek/csharp/Resources/NowEntering.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/84 Super Star Trek/csharp/Resources/NowEntering.txt b/84 Super Star Trek/csharp/Resources/NowEntering.txt index 915b526f..6545f9c4 100644 --- a/84 Super Star Trek/csharp/Resources/NowEntering.txt +++ b/84 Super Star Trek/csharp/Resources/NowEntering.txt @@ -1,2 +1,3 @@ + Now entering {0} quadrant . . . From f3fce146e5e11aeefea400c63c31756a9d256de6 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 22:24:11 +1000 Subject: [PATCH 372/749] Fix display of quadrant after move --- 84 Super Star Trek/csharp/Game.cs | 2 -- 84 Super Star Trek/csharp/Space/Quadrant.cs | 12 ++++++------ 84 Super Star Trek/csharp/Systems/WarpEngines.cs | 3 +++ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index 92c16a83..274e2948 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -51,8 +51,6 @@ namespace SuperStarTrek while (!gameOver) { - _enterprise.Quadrant.Display(Strings.NowEntering); - var command = _input.GetCommand(); var result = _enterprise.Execute(command); diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index 29f8e0ce..694f7fc8 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -14,7 +14,7 @@ namespace SuperStarTrek.Space private readonly Dictionary _sectors; private readonly Enterprise _enterprise; private readonly Output _output; - private bool _displayed = false; + private bool _entered = false; internal Quadrant( QuadrantInfo info, @@ -77,9 +77,11 @@ namespace SuperStarTrek.Space internal void Display(string textFormat) { - if (_displayed) { return; } - - _output.Write(textFormat, this); + if (!_entered) + { + _output.Write(textFormat, this); + _entered = true; + } if (_info.KlingonCount > 0) { @@ -88,8 +90,6 @@ namespace SuperStarTrek.Space } _enterprise.Execute(Command.SRS); - - _displayed = true; } internal bool HasObjectAt(Coordinates coordinates) => _sectors.ContainsKey(coordinates); diff --git a/84 Super Star Trek/csharp/Systems/WarpEngines.cs b/84 Super Star Trek/csharp/Systems/WarpEngines.cs index 4203f4e8..096d0e43 100644 --- a/84 Super Star Trek/csharp/Systems/WarpEngines.cs +++ b/84 Super Star Trek/csharp/Systems/WarpEngines.cs @@ -1,6 +1,7 @@ using System; using SuperStarTrek.Commands; using SuperStarTrek.Objects; +using SuperStarTrek.Resources; using SuperStarTrek.Space; namespace SuperStarTrek.Systems @@ -39,6 +40,8 @@ namespace SuperStarTrek.Systems _enterprise.PhotonTubes.ReplenishTorpedoes(); } + _enterprise.Quadrant.Display(Strings.NowEntering); + return CommandResult.Elapsed(timeElapsed); } From 8169f1e64a8ab100badeda0816ee99f04538332a Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 22:29:39 +1000 Subject: [PATCH 373/749] Fix "Shields dropped..." text spacing --- 84 Super Star Trek/csharp/Resources/ShieldsDropped.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt b/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt index acc87f59..9135e8b4 100644 --- a/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt +++ b/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt @@ -1 +1 @@ -Shields dropped for docking purposes +Shields dropped for docking purposes \ No newline at end of file From 94c0d2398318d1e57ce163f79edefa5050aa9229 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 23:00:36 +1000 Subject: [PATCH 374/749] Fix error when navigating out of bounds --- 84 Super Star Trek/csharp/Space/Course.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84 Super Star Trek/csharp/Space/Course.cs index 6418b15b..b316e4b3 100644 --- a/84 Super Star Trek/csharp/Space/Course.cs +++ b/84 Super Star Trek/csharp/Space/Course.cs @@ -81,10 +81,10 @@ namespace SuperStarTrek.Space var newQuadrant = (int)(galacticCoordinate / 8); var newSector = (int)(galacticCoordinate - newQuadrant * 8); - if (newSector == -1) + if (newSector < 0) { newQuadrant -= 1; - newSector = 7; + newSector += 8; } return newQuadrant switch From 4a82dd2198a5fb81d89ec392fefbac3712aa8b35 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 15 Apr 2021 23:02:40 +1000 Subject: [PATCH 375/749] Fix display of Docked status --- 84 Super Star Trek/csharp/Objects/Enterprise.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index 2f587631..ac9e8112 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -71,11 +71,12 @@ namespace SuperStarTrek.Objects } private string GetCondition() => - (_quadrant.HasKlingons, Energy / _maxEnergy) switch + IsDocked switch { - (true, _) => "*Red*", - (_, < 0.1f) => "Yellow", - _ => "Green" + true => "Docked", + false when _quadrant.HasKlingons => "*Red*", + false when Energy / _maxEnergy < 0.1f => "Yellow", + false => "Green" }; internal CommandResult Execute(Command command) From ff40494de65c3b45401af7984c972ee39a479016 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 17 Apr 2021 18:49:34 +1000 Subject: [PATCH 376/749] Add C# project --- .gitignore | 4 ++-- 82 Stars/csharp/Stars.sln | 34 ++++++++++++++++++++++++++++++ 82 Stars/csharp/Stars/Program.cs | 12 +++++++++++ 82 Stars/csharp/Stars/Stars.csproj | 8 +++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 82 Stars/csharp/Stars.sln create mode 100644 82 Stars/csharp/Stars/Program.cs create mode 100644 82 Stars/csharp/Stars/Stars.csproj diff --git a/.gitignore b/.gitignore index fc50f7f2..a186b7a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ */.vs -*/csharp/bin -*/csharp/obj +bin/ +obj/ .idea *.iws diff --git a/82 Stars/csharp/Stars.sln b/82 Stars/csharp/Stars.sln new file mode 100644 index 00000000..5f85e6b7 --- /dev/null +++ b/82 Stars/csharp/Stars.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stars", "Stars\Stars.csproj", "{5832C21C-4DE5-475E-893D-745DA15F1AAC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Debug|x64.ActiveCfg = Debug|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Debug|x64.Build.0 = Debug|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Debug|x86.ActiveCfg = Debug|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Debug|x86.Build.0 = Debug|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Release|Any CPU.Build.0 = Release|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Release|x64.ActiveCfg = Release|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Release|x64.Build.0 = Release|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Release|x86.ActiveCfg = Release|Any CPU + {5832C21C-4DE5-475E-893D-745DA15F1AAC}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/82 Stars/csharp/Stars/Program.cs b/82 Stars/csharp/Stars/Program.cs new file mode 100644 index 00000000..2d53de62 --- /dev/null +++ b/82 Stars/csharp/Stars/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace Stars +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/82 Stars/csharp/Stars/Stars.csproj b/82 Stars/csharp/Stars/Stars.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/82 Stars/csharp/Stars/Stars.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + From 0589f4d95a3eb894e9a1e08b7e7cb4189820e73f Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sat, 17 Apr 2021 21:14:01 +0400 Subject: [PATCH 377/749] Ported 44 Hangman to Java --- 44 Hangman/java/Hangman.java | 245 +++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 44 Hangman/java/Hangman.java diff --git a/44 Hangman/java/Hangman.java b/44 Hangman/java/Hangman.java new file mode 100644 index 00000000..56567bb2 --- /dev/null +++ b/44 Hangman/java/Hangman.java @@ -0,0 +1,245 @@ +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Scanner; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * HANGMAN + * + * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + */ +public class Hangman { + + //50 word list + private final static List words = List.of( + "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"); + + public static void main(String[] args) { + Scanner scan = new Scanner(System.in); + + printIntro(); + + int[] usedWords = new int[50]; + int roundNumber = 1; + int totalWords = words.size(); + boolean continueGame; + + do { + if (roundNumber > totalWords) { + System.out.println("\nYOU DID ALL THE WORDS!!"); + break; + } + + int randomWordIndex; + do { + randomWordIndex = ((int) (totalWords * Math.random())) + 1; + } while (usedWords[randomWordIndex] == 1); + usedWords[randomWordIndex] = 1; + + boolean youWon = playRound(scan, words.get(randomWordIndex - 1)); + if (!youWon) { + System.out.print("\nYOU MISSED THAT ONE. DO YOU WANT ANOTHER WORD? "); + } else { + System.out.print("\nWANT ANOTHER WORD? "); + } + final String anotherWordChoice = scan.next(); + continueGame = "YES".equals(anotherWordChoice); + roundNumber++; + } while (continueGame); + + System.out.println("\nIT'S BEEN FUN! BYE FOR NOW."); + } + + private static boolean playRound(Scanner scan, String word) { + char[] letters; + char[] discoveredLetters; + int misses = 0; + Set lettersUsed = new LinkedHashSet<>();//LinkedHashSet maintains the order of characters inserted + + String[][] hangmanPicture = new String[12][12]; + //initialize the hangman picture + for (int i = 0; i < hangmanPicture.length; i++) { + for (int j = 0; j < hangmanPicture[i].length; j++) { + hangmanPicture[i][j] = " "; + } + } + for (int i = 0; i < hangmanPicture.length; i++) { + hangmanPicture[i][0] = "X"; + } + for (int i = 0; i < 7; i++) { + hangmanPicture[0][i] = "X"; + } + hangmanPicture[1][6] = "X"; + + int totalWordGuesses = 0; //guesses + + int len = word.length(); + letters = word.toCharArray(); + + discoveredLetters = new char[len]; + Arrays.fill(discoveredLetters, '-'); + + boolean validNextGuess = false; + char guessLetter = ' '; + + while (misses < 10) { + while (!validNextGuess) { + printLettersUsed(lettersUsed); + printDiscoveredLetters(discoveredLetters); + + System.out.print("WHAT IS YOUR GUESS? "); + var tmpRead = scan.next(); + guessLetter = tmpRead.charAt(0); + if (lettersUsed.contains(guessLetter)) { + System.out.println("YOU GUESSED THAT LETTER BEFORE!"); + } else { + lettersUsed.add(guessLetter); + totalWordGuesses++; + validNextGuess = true; + } + } + + if (word.indexOf(guessLetter) >= 0) { + //replace all occurrences in D$ with G$ + for (int i = 0; i < letters.length; i++) { + if (letters[i] == guessLetter) { + discoveredLetters[i] = guessLetter; + } + } + //check if the word is fully discovered + boolean isWordDiscovered = true; + for (char discoveredLetter : discoveredLetters) { + if (discoveredLetter == '-') { + isWordDiscovered = false; + break; + } + } + if (isWordDiscovered) { + System.out.println("YOU FOUND THE WORD!"); + return true; + } + + printDiscoveredLetters(discoveredLetters); + System.out.print("WHAT IS YOUR GUESS FOR THE WORD? "); + final String wordGuess = scan.next(); + if (wordGuess.equals(word)) { + System.out.printf("RIGHT!! IT TOOK YOU %s GUESSES!", totalWordGuesses); + return true; + } else { + System.out.println("WRONG. TRY ANOTHER LETTER."); + } + } else { + misses = misses + 1; + System.out.println("\n\nSORRY, THAT LETTER ISN'T IN THE WORD."); + drawHangman(misses, hangmanPicture); + } + validNextGuess = false; + } + + System.out.printf("SORRY, YOU LOSE. THE WORD WAS %s", word); + return false; + } + + private static void drawHangman(int m, String[][] hangmanPicture) { + switch (m) { + case 1: + System.out.println("FIRST, WE DRAW A HEAD"); + hangmanPicture[2][5] = "-"; + hangmanPicture[2][6] = "-"; + hangmanPicture[2][7] = "-"; + hangmanPicture[3][4] = "("; + hangmanPicture[3][5] = "."; + hangmanPicture[3][7] = "."; + hangmanPicture[3][8] = ")"; + hangmanPicture[4][5] = "-"; + hangmanPicture[4][6] = "-"; + hangmanPicture[4][7] = "-"; + break; + case 2: + System.out.println("NOW WE DRAW A BODY."); + for (var i = 5; i <= 8; i++) { + hangmanPicture[i][6] = "X"; + } + break; + case 3: + System.out.println("NEXT WE DRAW AN ARM."); + for (int i = 3; i <= 6; i++) { + hangmanPicture[i][i - 1] = "\\"; + } + break; + case 4: + System.out.println("THIS TIME IT'S THE OTHER ARM."); + hangmanPicture[3][10] = "/"; + hangmanPicture[4][9] = "/"; + hangmanPicture[5][8] = "/"; + hangmanPicture[6][7] = "/"; + break; + case 5: + System.out.println("NOW, LET'S DRAW THE RIGHT LEG."); + hangmanPicture[9][5] = "/"; + hangmanPicture[10][4] = "/"; + break; + case 6: + System.out.println("THIS TIME WE DRAW THE LEFT LEG."); + hangmanPicture[9][7] = "\\"; + hangmanPicture[10][8] = "\\"; + break; + case 7: + System.out.println("NOW WE PUT UP A HAND."); + hangmanPicture[2][10] = "\\"; + break; + case 8: + System.out.println("NEXT THE OTHER HAND."); + hangmanPicture[2][2] = "/"; + break; + case 9: + System.out.println("NOW WE DRAW ONE FOOT"); + hangmanPicture[11][9] = "\\"; + hangmanPicture[11][10] = "-"; + break; + case 10: + System.out.println("HERE'S THE OTHER FOOT -- YOU'RE HUNG!!"); + hangmanPicture[11][2] = "-"; + hangmanPicture[11][3] = "/"; + break; + } + for (int i = 0; i <= 11; i++) { + for (int j = 0; j <= 11; j++) { + System.out.print(hangmanPicture[i][j]); + } + System.out.print("\n"); + } + + } + + private static void printDiscoveredLetters(char[] D$) { + System.out.println(new String(D$)); + System.out.println("\n"); + } + + private static void printLettersUsed(Set lettersUsed) { + System.out.println("\nHERE ARE THE LETTERS YOU USED:"); + System.out.println(lettersUsed.stream() + .map(Object::toString).collect(Collectors.joining(","))); + System.out.println("\n"); + } + + private static void printIntro() { + System.out.println(" HANGMAN"); + System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n\n"); + } + +} + + From fbe47d4c2b0a734be3fd7bd120536e46cc455655 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sun, 18 Apr 2021 15:43:04 -0400 Subject: [PATCH 378/749] Ported Banner to Java. --- 06 Banner/java/Banner.java | 224 +++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 06 Banner/java/Banner.java diff --git a/06 Banner/java/Banner.java b/06 Banner/java/Banner.java new file mode 100644 index 00000000..8c4e1c61 --- /dev/null +++ b/06 Banner/java/Banner.java @@ -0,0 +1,224 @@ +import java.util.Scanner; +import java.util.HashMap; +import java.util.Map; +import java.lang.Math; + +/** + * Game of Banner + *

+ * Based on the BASIC game of Banner here + * https://github.com/coding-horror/basic-computer-games/blob/main/06%20Banner/banner.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Banner { + + private final Scanner scan; // For user input + + public Banner() { + + scan = new Scanner(System.in); + + } // End of constructor Banner + + public void play() { + + int bitIndex = 0; + int centerFlag = 0; + int dataIndex = 0; + int hIndex = 0; + int horizontal = 0; + int index = 0; + int letterIndex = 0; + int tempVal = 0; + int vertical = 0; + int vIndex = 0; + int writeIndex = 0; + + int[] writerMap = new int[10]; + int[] writeLimit = new int[10]; + + String centerResponse = ""; + String characters = ""; + String letter = ""; + String lineContent = ""; + String setPage = ""; + String statement = ""; + String token = ""; // Print token + + Map symbolData = new HashMap(); + symbolData.put(" ", new int[]{0,0,0,0,0,0,0,0 }); + symbolData.put("A", new int[]{0,505,37,35,34,35,37,505 }); + symbolData.put("G", new int[]{0,125,131,258,258,290,163,101}); + symbolData.put("E", new int[]{0,512,274,274,274,274,258,258}); + symbolData.put("T", new int[]{0,2,2,2,512,2,2,2 }); + symbolData.put("W", new int[]{0,256,257,129,65,129,257,256 }); + symbolData.put("L", new int[]{0,512,257,257,257,257,257,257}); + symbolData.put("S", new int[]{0,69,139,274,274,274,163,69 }); + symbolData.put("O", new int[]{0,125,131,258,258,258,131,125}); + symbolData.put("N", new int[]{0,512,7,9,17,33,193,512 }); + symbolData.put("F", new int[]{0,512,18,18,18,18,2,2 }); + symbolData.put("K", new int[]{0,512,17,17,41,69,131,258 }); + symbolData.put("B", new int[]{0,512,274,274,274,274,274,239}); + symbolData.put("D", new int[]{0,512,258,258,258,258,131,125}); + symbolData.put("H", new int[]{0,512,17,17,17,17,17,512 }); + symbolData.put("M", new int[]{0,512,7,13,25,13,7,512 }); + symbolData.put("?", new int[]{0,5,3,2,354,18,11,5 }); + symbolData.put("U", new int[]{0,128,129,257,257,257,129,128}); + symbolData.put("R", new int[]{0,512,18,18,50,82,146,271 }); + symbolData.put("P", new int[]{0,512,18,18,18,18,18,15 }); + symbolData.put("Q", new int[]{0,125,131,258,258,322,131,381}); + symbolData.put("Y", new int[]{0,8,9,17,481,17,9,8 }); + symbolData.put("V", new int[]{0,64,65,129,257,129,65,64 }); + symbolData.put("X", new int[]{0,388,69,41,17,41,69,388 }); + symbolData.put("Z", new int[]{0,386,322,290,274,266,262,260}); + symbolData.put("I", new int[]{0,258,258,258,512,258,258,258}); + symbolData.put("C", new int[]{0,125,131,258,258,258,131,69 }); + symbolData.put("J", new int[]{0,65,129,257,257,257,129,128 }); + symbolData.put("1", new int[]{0,0,0,261,259,512,257,257 }); + symbolData.put("2", new int[]{0,261,387,322,290,274,267,261}); + symbolData.put("*", new int[]{0,69,41,17,512,17,41,69 }); + symbolData.put("3", new int[]{0,66,130,258,274,266,150,100 }); + symbolData.put("4", new int[]{0,33,49,41,37,35,512,33 }); + symbolData.put("5", new int[]{0,160,274,274,274,274,274,226}); + symbolData.put("6", new int[]{0,194,291,293,297,305,289,193}); + symbolData.put("7", new int[]{0,258,130,66,34,18,10,8 }); + symbolData.put("8", new int[]{0,69,171,274,274,274,171,69 }); + symbolData.put("9", new int[]{0,263,138,74,42,26,10,7 }); + symbolData.put("=", new int[]{0,41,41,41,41,41,41,41 }); + symbolData.put("!", new int[]{0,1,1,1,384,1,1,1 }); + symbolData.put("0", new int[]{0,57,69,131,258,131,69,57 }); + symbolData.put(".", new int[]{0,1,1,129,449,129,1,1 }); + + System.out.print("HORIZONTAL? "); + horizontal = Integer.parseInt(scan.nextLine()); + + System.out.print("VERTICAL? "); + vertical = Integer.parseInt(scan.nextLine()); + + System.out.print("CENTERED? "); + centerResponse = scan.nextLine().toUpperCase(); + + centerFlag = 0; + + // Lexicographical comparison + if (centerResponse.compareTo("P") > 0) { + centerFlag = 1; + } + + System.out.print("CHARACTER (TYPE 'ALL' IF YOU WANT CHARACTER BEING PRINTED)? "); + characters = scan.nextLine().toUpperCase(); + + System.out.print("STATEMENT? "); + statement = scan.nextLine().toUpperCase(); + + // Initiates the print + System.out.print("SET PAGE? "); + setPage = scan.nextLine(); + + // Begin loop through statement letters + for (letterIndex = 1; letterIndex <= statement.length(); letterIndex++) { + + // Extract a letter + letter = String.valueOf(statement.charAt(letterIndex - 1)); + + // Begin loop through all symbol data + for (String symbolString: symbolData.keySet()) { + + // Begin letter handling + if (letter.equals(" ")) { + for (index = 1; index <= (7 * horizontal); index++) { + System.out.println(""); + } + break; + + } else if (letter.equals(symbolString)) { + token = characters; + + if (characters.equals("ALL")) { + token = symbolString; + } + + for (dataIndex = 1; dataIndex <= 7; dataIndex++) { + + // Avoid overwriting symbol data + tempVal = symbolData.get(symbolString)[dataIndex]; + + for (bitIndex = 8; bitIndex >= 0; bitIndex--) { + + if (Math.pow(2, bitIndex) < tempVal) { + writerMap[9 - bitIndex] = 1; + tempVal -= Math.pow(2, bitIndex); + + if (tempVal == 1) { + writeLimit[dataIndex] = 9 - bitIndex; + break; + } + + } else { + + writerMap[9 - bitIndex] = 0; + } + } // End of bitIndex loop + + for (hIndex = 1; hIndex <= horizontal; hIndex++) { + + // Add whitespace for centering + lineContent = " ".repeat((int)((63 - 4.5 * vertical) * centerFlag / token.length())); + + for (writeIndex = 1; writeIndex <= writeLimit[dataIndex]; writeIndex++) { + + if (writerMap[writeIndex] == 0) { + + for (vIndex = 1; vIndex <= vertical; vIndex++) { + + for (index = 1; index <= token.length(); index++) { + lineContent += " "; + } + } + + } else { + + for (vIndex = 1; vIndex <= vertical; vIndex++) { + lineContent += token; + } + } + + } // End of writeIndex loop + + System.out.println(lineContent); + + } // End of hIndex loop + + } // End of dataIndex loop + + // Add padding between letters + for (index = 1; index <= 2 * horizontal; index++) { + System.out.println(""); + } + + } // End letter handling + + } // End loop through all symbol data + + } // End loop through statement letters + + // Add extra length to the banner + for (index = 1; index <= 75; index++) { + System.out.println(""); + } + + } // End of method play + + public static void main(String[] args) { + + Banner game = new Banner(); + game.play(); + + } // End of method main + +} // End of class Banner From 5c447bac872ced98fc94ae6780445957af1ca7fe Mon Sep 17 00:00:00 2001 From: rbamforth <79797573+rbamforth@users.noreply.github.com> Date: Sun, 18 Apr 2021 22:28:22 +0100 Subject: [PATCH 379/749] Added missing bit of UI. Fixed final bugs. --- 29 Craps/csharp/Craps/Craps/CrapsGame.cs | 9 ++-- 29 Craps/csharp/Craps/Craps/Program.cs | 2 + 29 Craps/csharp/Craps/Craps/UserInterface.cs | 51 ++++++++++++++++---- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/29 Craps/csharp/Craps/Craps/CrapsGame.cs b/29 Craps/csharp/Craps/Craps/CrapsGame.cs index c0da368c..71a3931f 100644 --- a/29 Craps/csharp/Craps/Craps/CrapsGame.cs +++ b/29 Craps/csharp/Craps/Craps/CrapsGame.cs @@ -16,6 +16,8 @@ class CrapsGame { private readonly UserInterface ui; + private Dice dice1 = new Dice(); + private Dice dice2 = new Dice(); public CrapsGame(ref UserInterface ui) { @@ -24,9 +26,6 @@ public Result Play(out int diceRoll) { - - var dice1 = new Dice(); - var dice2 = new Dice(); diceRoll = dice1.Roll() + dice2.Roll(); if (Win(diceRoll)) @@ -47,14 +46,16 @@ var newRoll = dice1.Roll() + dice2.Roll(); if (newRoll == point) { + diceRoll = newRoll; return Result.pointWin; } else if (newRoll == 7) { + diceRoll = newRoll; return Result.pointLoss; } - ui.NoPoint(diceRoll); + ui.NoPoint(newRoll); } } } diff --git a/29 Craps/csharp/Craps/Craps/Program.cs b/29 Craps/csharp/Craps/Craps/Program.cs index 31caffd8..d0aa5961 100644 --- a/29 Craps/csharp/Craps/Craps/Program.cs +++ b/29 Craps/csharp/Craps/Craps/Program.cs @@ -44,6 +44,8 @@ namespace Craps ui.ShowResult(result, diceRoll, bet); } while (ui.PlayAgain(winnings)); + + ui.GoodBye(winnings); } } } diff --git a/29 Craps/csharp/Craps/Craps/UserInterface.cs b/29 Craps/csharp/Craps/Craps/UserInterface.cs index 72bdb17b..149a3ecc 100644 --- a/29 Craps/csharp/Craps/Craps/UserInterface.cs +++ b/29 Craps/csharp/Craps/Craps/UserInterface.cs @@ -17,31 +17,62 @@ namespace Craps // times as the number the user entered. This is presumably something to do with ensuring // that different random numbers will be generated each time the program is run. // - // This is not necessary in C#; the random number generator uses the time as a seed so the - // results will always be different every time it is run. + // This is not necessary in C#; the random number generator uses the current time as a seed + // so the results will always be different every time it is run. // - // So that the game exactly matches the original game we ask the question but then ignore the - // answer. - Console.WriteLine("PICK A NUMBER AND INPUT TO ROLL DICE"); + // So that the game exactly matches the original game we ask the question but then ignore + // the answer. + Console.Write("PICK A NUMBER AND INPUT TO ROLL DICE "); GetInt(); } public int PlaceBet() { - Console.WriteLine("INPUT THE AMOUNT OF YOUR WAGER."); + Console.Write("INPUT THE AMOUNT OF YOUR WAGER. "); int n = GetInt(); Console.WriteLine("I WILL NOW THROW THE DICE"); return n; } - public bool PlayAgain(int bet) + public bool PlayAgain(int winnings) { // Goodness knows why we have to enter 5 to play // again but that's what the original game asked. - Console.WriteLine("IF YOU WANT TO PLAY AGAIN PRINT 5 IF NOT PRINT 2"); + Console.Write("IF YOU WANT TO PLAY AGAIN PRINT 5 IF NOT PRINT 2 "); - return GetInt() == 5; + bool playAgain = (GetInt() == 5); + + if (winnings < 0) + { + Console.WriteLine($"YOU ARE NOW UNDER ${-winnings}"); + } + else if (winnings > 0) + { + Console.WriteLine($"YOU ARE NOW OVER ${winnings}"); + } + else + { + Console.WriteLine($"YOU ARE NOW EVEN AT ${winnings}"); + } + + return playAgain; + } + + public void GoodBye(int winnings) + { + if (winnings < 0) + { + Console.WriteLine("TOO BAD, YOU ARE IN THE HOLE. COME AGAIN."); + } + else if (winnings > 0) + { + Console.WriteLine("CONGRATULATIONS---YOU CAME OUT A WINNER. COME AGAIN!"); + } + else + { + Console.WriteLine("CONGRATULATIONS---YOU CAME OUT EVEN, NOT BAD FOR AN AMATEUR"); + } } public void NoPoint(int diceRoll) @@ -102,7 +133,7 @@ namespace Craps } else { - Console.WriteLine("ENTER AN INTEGER"); + Console.Write("ENTER AN INTEGER "); } } } From 1236ee8c48deeec172ac2396a910ef795da3daf9 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 19 Apr 2021 08:59:35 +1000 Subject: [PATCH 380/749] Implement stars game --- 82 Stars/csharp/Stars/Game.cs | 94 ++++++++++++++++++++++++++++++++ 82 Stars/csharp/Stars/Input.cs | 31 +++++++++++ 82 Stars/csharp/Stars/Program.cs | 20 ++++++- 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 82 Stars/csharp/Stars/Game.cs create mode 100644 82 Stars/csharp/Stars/Input.cs diff --git a/82 Stars/csharp/Stars/Game.cs b/82 Stars/csharp/Stars/Game.cs new file mode 100644 index 00000000..7045fe4b --- /dev/null +++ b/82 Stars/csharp/Stars/Game.cs @@ -0,0 +1,94 @@ +using System; + +namespace Stars +{ + internal class Game + { + private readonly int _maxNumber; + private readonly int _maxGuessCount; + private readonly Random _random; + + public Game(int maxNumber, int maxGuessCount) + { + _maxNumber = maxNumber; + _maxGuessCount = maxGuessCount; + _random = new Random(); + } + + internal void DisplayInstructions() + { + if (Input.GetString("Do you want instructions? ").Equals("N", StringComparison.InvariantCultureIgnoreCase)) + { + return; + } + + Console.WriteLine($"I am thinking of a number between 1 and {_maxNumber}."); + Console.WriteLine("Try to guess my number. After you guess, I"); + Console.WriteLine("will type one or more stars (*). The more"); + Console.WriteLine("stars I type, the close you are to my number."); + Console.WriteLine("One star (*) means far away, seven stars (*******)"); + Console.WriteLine($"means really close! You get {_maxGuessCount} guesses."); + } + + internal void Play() + { + Console.WriteLine(); + Console.WriteLine(); + + var target = _random.Next(_maxNumber) + 1; + + Console.WriteLine("Ok, I am thinking of a number. Start guessing."); + + AcceptGuesses(target); + } + + private void AcceptGuesses(int target) + { + for (int guessCount = 1; guessCount <= _maxGuessCount; guessCount++) + { + Console.WriteLine(); + var guess = Input.GetNumber("Your guess? "); + + if (guess == target) + { + DisplayWin(guessCount); + return; + } + + DisplayStars(target, guess); + } + + DisplayLoss(target); + } + + private static void DisplayStars(int target, float guess) + { + var stars = Math.Abs(guess - target) switch + { + >= 64 => "*", + >= 32 => "**", + >= 16 => "***", + >= 8 => "****", + >= 4 => "*****", + >= 2 => "******", + _ => "*******" + }; + + Console.WriteLine(stars); + } + + private static void DisplayWin(int guessCount) + { + Console.WriteLine(); + Console.WriteLine(new string('*', 79)); + Console.WriteLine(); + Console.WriteLine($"You got it in {guessCount} guesses!!! Let's play again..."); + } + + private void DisplayLoss(int target) + { + Console.WriteLine(); + Console.WriteLine($"Sorry, that's {_maxGuessCount} guesses. The number was {target}."); + } + } +} \ No newline at end of file diff --git a/82 Stars/csharp/Stars/Input.cs b/82 Stars/csharp/Stars/Input.cs new file mode 100644 index 00000000..6ba6e3a1 --- /dev/null +++ b/82 Stars/csharp/Stars/Input.cs @@ -0,0 +1,31 @@ +using System; + +namespace Stars +{ + internal static class Input + { + // Float, because that's what the BASIC input operation returns + internal static float GetNumber(string prompt) + { + Console.Write(prompt); + + while (true) + { + var response = Console.ReadLine(); + if (float.TryParse(response, out var value)) + { + return value; + } + + Console.WriteLine("!Number expected - retry input line"); + Console.Write("? "); + } + } + + internal static string GetString(string prompt) + { + Console.Write(prompt); + return Console.ReadLine(); + } + } +} diff --git a/82 Stars/csharp/Stars/Program.cs b/82 Stars/csharp/Stars/Program.cs index 2d53de62..b072595c 100644 --- a/82 Stars/csharp/Stars/Program.cs +++ b/82 Stars/csharp/Stars/Program.cs @@ -6,7 +6,25 @@ namespace Stars { static void Main(string[] args) { - Console.WriteLine("Hello World!"); + DisplayTitle(); + + var game = new Game(maxNumber: 100, maxGuessCount: 7); + + game.DisplayInstructions(); + + while (true) + { + game.Play(); + } + } + + private static void DisplayTitle() + { + Console.WriteLine(" Stars"); + Console.WriteLine(" Creative Computing Morristown, New Jersey"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); } } } From e47bfc9d4a649272bda43c2d782f474e33b4049d Mon Sep 17 00:00:00 2001 From: Kyle Zhao Date: Fri, 16 Apr 2021 22:36:07 -0400 Subject: [PATCH 381/749] Port Bombardment to Ruby --- 11 Bombardment/ruby/bombardment.rb | 167 +++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 11 Bombardment/ruby/bombardment.rb diff --git a/11 Bombardment/ruby/bombardment.rb b/11 Bombardment/ruby/bombardment.rb new file mode 100644 index 00000000..9a89f9f6 --- /dev/null +++ b/11 Bombardment/ruby/bombardment.rb @@ -0,0 +1,167 @@ +require "set" + +class Battlefield + TOTAL_OUTPOSTS = 25 + TOTAL_PLATOONS = 4 + + class << self + def with_random_platoon_placements + new((1..TOTAL_OUTPOSTS).to_a.sample(4)) + end + + def valid_platoon_placement?(i) + i.between?(1, TOTAL_OUTPOSTS) + end + end + + def initialize(platoon_placements) + @platoon_placements = Set.new(platoon_placements) + end + + # Fires a missile at the specified outpost. Returns true if it hits a + # platoon, false otherwise. + def fire_missile_at(outpost) + !@platoon_placements.delete?(outpost).nil? + end + + def remaining_platoons_count + @platoon_placements.size + end +end + +class Game + def initialize(player_battlefield:, computer_battlefield:) + @player_battlefield = player_battlefield + @computer_battlefield = computer_battlefield + end + + def play + player_choice = get_integer_answer_to("WHERE DO YOU WISH TO FIRE") + + if @computer_battlefield.fire_missile_at(player_choice) + print_player_success_message + return if @computer_battlefield.remaining_platoons_count == 0 + else + puts "HA, HA YOU MISSED. MY TURN NOW:" + end + puts + + computer_choice = rand(1..Battlefield::TOTAL_OUTPOSTS) + + if @player_battlefield.fire_missile_at(computer_choice) + print_computer_success_message(computer_choice) + else + puts "I MISSED YOU, YOU DIRTY RAT. I PICKED #{computer_choice}. YOUR TURN:" + end + puts + end + + def finished? + @player_battlefield.remaining_platoons_count == 0 || + @computer_battlefield.remaining_platoons_count == 0 + end + + private + + def get_integer_answer_to(question) + puts question + $stdin.gets.strip.to_i + end + + def print_computer_success_message(computer_choice) + if @player_battlefield.remaining_platoons_count == 0 + puts "YOU'RE DEAD. YOUR LAST OUTPOST WAS AT #{computer_choice}. HA, HA, HA." + puts "BETTER LUCK NEXT TIME." + return + end + + puts "I GOT YOU. IT WON'T BE LONG NOW. POST #{computer_choice} WAS HIT." + + case @player_battlefield.remaining_platoons_count + when 1 + puts "YOU HAVE ONLY ONE OUTPOST LEFT" + when 2 + puts "YOU HAVE ONLY TWO OUTPOSTS LEFT" + when 3 + puts "YOU HAVE ONLY THREE OUTPOSTS LEFT" + end + end + + def print_player_success_message + if @computer_battlefield.remaining_platoons_count == 0 + puts "YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN" + puts "MY TRANSISTO&S RECUP%RA*E!" + return + end + + puts "YOU GOT ONE OF MY OUTPOSTS!" + + case @computer_battlefield.remaining_platoons_count + when 1 + puts "THREE DOWN, ONE TO GO." + when 2 + puts "TWO DOWN, TWO TO GO." + when 3 + puts "ONE DOWN, THREE TO GO." + end + end +end + +INTRODUCTION = <<~TEXT + BOMBARDMENT + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + + YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU + HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED. + YOU CAN ONLY PLACE ONE PLATOON AT ANY ONE OUTPOST. + THE COMPUTER DOES THE SAME WITH ITS FOUR PLATOONS. + + THE OBJECT OF THE GAME IS TO FIRE MISSLES AT THE + OUTPOSTS OF THE COMPUTER. IT WILL DO THE SAME TO YOU. + THE ONE WHO DESTROYS ALL FOUR OF THE ENEMY'S PLATOONS + FIRST IS THE WINNER. + + GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT! + + TEAR OFF MATRIX AND USE IT TO CHECK OFF THE NUMBERS. +TEXT + +def print_matrix + (1..25).each do |i| + print i + print i % 5 == 0 ? "\n" : "\t" + end +end + +def ask_for_platoon_placements + puts "WAHT ARE YOUR FOUR POSITIONS?" + platoon_placements = $stdin.gets.strip.split(",").map(&:to_i) + + if platoon_placements.size == 4 && + platoon_placements.all? { |i| Battlefield.valid_platoon_placement?(i) } + platoon_placements + else + puts "POSITIONS SHOULD BE BETWEEN 1 TO 25, DELIMITED BY COMMA." + ask_for_platoon_placements + end +end + +def start_game + puts INTRODUCTION + puts + print_matrix + puts + platoon_placements = ask_for_platoon_placements + puts + + game = Game.new( + player_battlefield: Battlefield.new(platoon_placements), + computer_battlefield: Battlefield.with_random_platoon_placements + ) + + game.play until game.finished? +end + +start_game From 47ec385b6b2449219b7cb5e71b98a38386b4f5d4 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sat, 24 Apr 2021 18:40:00 -0400 Subject: [PATCH 382/749] Ported Bounce to Java. --- 13 Bounce/java/Bounce.java | 169 +++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 13 Bounce/java/Bounce.java diff --git a/13 Bounce/java/Bounce.java b/13 Bounce/java/Bounce.java new file mode 100644 index 00000000..6d39daa2 --- /dev/null +++ b/13 Bounce/java/Bounce.java @@ -0,0 +1,169 @@ +import java.util.Scanner; +import java.lang.Math; + +/** + * Game of Bounce + *

+ * Based on the BASIC game of Bounce here + * https://github.com/coding-horror/basic-computer-games/blob/main/13%20Bounce/bounce.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Bounce { + + private final Scanner scan; // For user input + + public Bounce() { + + scan = new Scanner(System.in); + + } // End of constructor Bounce + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private void showIntro() { + + System.out.println(" ".repeat(32) + "BOUNCE"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + double coefficient = 0; + double height = 0; + double timeIncrement = 0; + double timeIndex = 0; + double timeTotal = 0; + double velocity = 0; + + double[] timeData = new double[21]; + + int heightInt = 0; + int index = 0; + int maxData = 0; + + String lineContent = ""; + + System.out.println("THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY"); + System.out.println("OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF"); + System.out.println("ELASTICITY OF THE BALL. PLEASE USE A DECIMAL FRACTION"); + System.out.println("COEFFICIENCY (LESS THAN 1)."); + System.out.println(""); + System.out.println("YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN"); + System.out.println("'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY)."); + System.out.println(""); + + // Begin outer while loop + while (true) { + + System.out.print("TIME INCREMENT (SEC)? "); + timeIncrement = Double.parseDouble(scan.nextLine()); + System.out.println(""); + + System.out.print("VELOCITY (FPS)? "); + velocity = Double.parseDouble(scan.nextLine()); + System.out.println(""); + + System.out.print("COEFFICIENT? "); + coefficient = Double.parseDouble(scan.nextLine()); + System.out.println(""); + + System.out.println("FEET"); + System.out.println(""); + + maxData = (int)(70 / (velocity / (16 * timeIncrement))); + + for (index = 1; index <= maxData; index++) { + timeData[index] = velocity * Math.pow(coefficient, index - 1) / 16; + } + + // Begin loop through all rows of y-axis data + for (heightInt = (int)(-16 * Math.pow(velocity / 32, 2) + Math.pow(velocity, 2) / 32 + 0.5) * 10; + heightInt >= 0; heightInt -= 5) { + + height = heightInt / 10.0; + + lineContent = ""; + + if ((int)(Math.floor(height)) == height) { + + lineContent += " " + (int)(height) + " "; + } + + timeTotal = 0; + + for (index = 1; index <= maxData; index++) { + + for (timeIndex = 0; timeIndex <= timeData[index]; timeIndex += timeIncrement) { + + timeTotal += timeIncrement; + + if (Math.abs(height - (0.5 * (-32) * Math.pow(timeIndex, 2) + velocity + * Math.pow(coefficient, index - 1) * timeIndex)) <= 0.25) { + + while (lineContent.length() < (timeTotal / timeIncrement) - 1) { + lineContent += " "; + } + lineContent += "0"; + } + } + + timeIndex = timeData[index + 1] / 2; + + if (-16 * Math.pow(timeIndex, 2) + velocity * Math.pow(coefficient, index - 1) * timeIndex < height) { + + break; + } + } + + System.out.println(lineContent); + + } // End loop through all rows of y-axis data + + lineContent = ""; + + // Show the x-axis + for (index = 1; index <= (int)(timeTotal + 1) / timeIncrement + 1; index++) { + + lineContent += "."; + } + + System.out.println(lineContent); + + lineContent = " 0"; + + for (index = 1; index <= (int)(timeTotal + 0.9995); index++) { + + while (lineContent.length() < (int)(index / timeIncrement)) { + lineContent += " "; + } + lineContent += index; + } + + System.out.println(lineContent); + + System.out.println(" ".repeat((int)((timeTotal + 1) / (2 * timeIncrement) - 3)) + "SECONDS"); + + } // End outer while loop + + } // End of method startGame + + public static void main(String[] args) { + + Bounce game = new Bounce(); + game.play(); + + } // End of method main + +} // End of class Bounce From d195ab8151ca2b6018e39c52d1066f75260c56ef Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 24 Apr 2021 20:21:04 -0400 Subject: [PATCH 383/749] Golf in C#. Source, plus 2 pre-compiled executables --- 39 Golf/csharp/Program.cs | 1142 +++++++++++++++++++++++++++++++++++++ 39 Golf/csharp/README.md | 12 + 2 files changed, 1154 insertions(+) create mode 100644 39 Golf/csharp/Program.cs diff --git a/39 Golf/csharp/Program.cs b/39 Golf/csharp/Program.cs new file mode 100644 index 00000000..abbbaf6b --- /dev/null +++ b/39 Golf/csharp/Program.cs @@ -0,0 +1,1142 @@ +// +// 8""""8 8"""88 8 8"""" +// 8 " 8 8 8 8 +// 8e 8 8 8e 8eeee +// 88 ee 8 8 88 88 +// 88 8 8 8 88 88 +// 88eee8 8eeee8 88eee 88 +// +// GOLF +// +// C# +// .NET Core +// TargetFramework: netcoreapp 3.1 +// +// Run source: +// dotnet run +// +// Linux compile: +// dotnet publish --self-contained -c Release -r linux-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true +// +// Windows compile: +// dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true +// +// +// INDEX +// ----------------- methods +// constructor +// NewHole +// TeeUp +// Stroke +// PlotBall +// InterpretResults +// ReportCurrentScore +// FindBall +// IsOnFairway +// IsOnGreen +// IsInHazard +// IsInRough +// IsOutOfBounds +// ScoreCardNewHole +// ScoreCardRecordStroke +// ScoreCardGetPreviousStroke +// ScoreCardGetTotal +// Ask +// Wait +// ReviewBag +// Quit +// GameOver +// ----------------- DATA +// Clubs +// CourseInfo +// ----------------- classes +// HoleInfo +// CircleGameObj +// RectGameObj +// HoleGeometry +// Plot +// ----------------- helper methods +// GetDistance +// IsInRectangle +// ToRadians +// ToDegrees360 +// Odds +// +// Despite being a text based game, the code uses simple geometry to simulate a course. +// Fairways are 40 yard wide rectangles, surrounded by 5 yards of rough around the perimeter. +// The green is a circle of 10 yards radius around the cup. +// The cup is always at point (0,0). +// +// Using basic trigonometry we can plot the ball's location using the distance of the stroke and +// and the angle of deviation (hook/slice). +// +// The stroke distances are based on real world averages of different club types. +// Lots of randomization, "business rules", and luck influence the game play. +// Probabilities are commented in the code. +// +// note: 'courseInfo', 'clubs', & 'scoreCard' arrays each include an empty object so indexing +// can begin at 1. Like all good programmers we count from zero, but in this context, +// it's more natural when hole number one is at index one +// +// +// |-----------------------------| +// | rough | +// | ---------------------- | +// | | | | +// | r | = = | r | +// | o | = = | o | +// | u | = . = | u | +// | g | = green = | g | +// | h | = = | h | +// | | = = | | +// | | | | +// | | | | +// | | Fairway | | +// | | | | +// | | ------ | +// | | -- -- | +// | | -- hazard --| +// | | -- -- | +// | | ------ | +// | | | | +// | | | | out +// | | | | of +// | | | | bounds +// | | | | +// | | | | +// | tee | +// +// +// Typical green size: 20-30 yards +// Typical golf course fairways are 35 to 45 yards wide +// Our fairway extends 5 yards past green +// Our rough is a 5 yard perimeter around fairway +// +// We calculate the new position of the ball given the ball's point, the distance +// of the stroke, and degrees off line (hook or slice). +// +// Degrees off (for a right handed golfer): +// Slice: positive degrees = ball goes right +// Hook: negative degrees = left goes left +// +// The cup is always at point: 0,0. +// We use atan2 to compute the angle between the cup and the ball. +// Setting the cup's vector to 0,-1 on a 360 circle is equivalent to: +// 0 deg = 12 o'clock; 90 deg = 3 o'clock; 180 deg = 6 o'clock; 270 = 9 o'clock +// The reverse angle between the cup and the ball is a difference of PI (using radians). +// +// Given the angle and stroke distance (hypotenuse), we use cosine to compute +// the opposite and adjacent sides of the triangle, which, is the ball's new position. +// +// 0 +// | +// 270 - cup - 90 +// | +// 180 +// +// +// cup +// | +// | +// | opp +// |-----* new position +// | / +// | / +// adj | / +// | / hyp +// |/ +// tee +// +// <- hook slice -> +// +// +// Given the large number of combinations needed to describe a particular stroke / ball location, +// we use the technique of "bitwise masking" to describe stroke results. +// With bit masking, multiple flags (bits) are combined into a single binary number that can be +// tested by applying a mask. A mask is another binary number that isolates a particular bit that +// you are interested in. You can then apply your language's bitwise opeartors to test or +// set a flag. +// +// Game design by Jason Bonthron, 2021 +// www.bonthron.com +// for my father, Raymond Bonthron, an avid golfer +// +// Inspired by the 1978 "Golf" from "Basic Computer Games" +// by Steve North, who modified an existing golf game by an unknown author +// +// + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading; + + +namespace Golf +{ + using Ball = Golf.CircleGameObj; + using Hazard = Golf.CircleGameObj; + + // --------------------------------------------------------------------------- Program + class Program + { + static void Main(string[] args) + { + Golf g = new Golf(); + } + } + + + // --------------------------------------------------------------------------- Golf + public class Golf + { + Ball BALL; + int HOLE_NUM = 0; + int STROKE_NUM = 0; + int Handicap = 0; + int PlayerDifficulty = 0; + HoleGeometry holeGeometry; + + // all fairways are 40 yards wide, extend 5 yards beyond the cup, and + // have 5 yards of rough around the perimeter + const int FairwayWidth = 40; + const int FairwayExtension = 5; + const int RoughAmt = 5; + + // ScoreCard records the ball position after each stroke + // a new list for each hole + // include a blank list so index 1 == hole 1 + + List> ScoreCard = new List> { new List() }; + + static void w(string s) { Console.WriteLine(s); } // WRITE + Random RANDOM = new Random(); + + + // --------------------------------------------------------------- constructor + public Golf() + { + Console.Clear(); + w(" "); + w(" 8\"\"\"\"8 8\"\"\"88 8 8\"\"\"\" "); + w(" 8 \" 8 8 8 8 "); + w(" 8e 8 8 8e 8eeee "); + w(" 88 ee 8 8 88 88 "); + w(" 88 8 8 8 88 88 "); + w(" 88eee8 8eeee8 88eee 88 "); + w(" "); + w("Welcome to the Creative Computing Country Club,"); + w("an eighteen hole championship layout located a short"); + w("distance from scenic downtown Lambertville, New Jersey."); + w("The game will be explained as you play."); + w("Enjoy your game! See you at the 19th hole..."); + w(" "); + w("Type QUIT at any time to leave the game."); + w("Type BAG at any time to review the clubs in your bag."); + w(" "); + + Wait((z) => + { + w(" "); + w(" YOUR BAG"); + ReviewBag(); + w("Type BAG at any time to review the clubs in your bag."); + w(" "); + + Wait((zz) => + { + w(" "); + + Ask("PGA handicaps range from 0 to 30.\nWhat is your handicap?", 0, 30, (i) => + { + Handicap = i; + w(" "); + + Ask("Common difficulties at golf include:\n1=Hook, 2=Slice, 3=Poor Distance, 4=Trap Shots, 5=Putting\nWhich one is your worst?", 1, 5, (j) => + { + PlayerDifficulty = j; + Console.Clear(); + NewHole(); + }); + }); + }); + }); + } + + + // --------------------------------------------------------------- NewHole + void NewHole() + { + HOLE_NUM++; + STROKE_NUM = 0; + + HoleInfo info = CourseInfo[HOLE_NUM]; + + int yards = info.Yards; // from tee to cup + int par = info.Par; + var cup = new CircleGameObj(0, 0, 0, GameObjType.CUP); + var green = new CircleGameObj(0, 0, 10, GameObjType.GREEN); + + var fairway = new RectGameObj(0 - (FairwayWidth / 2), + 0 - (green.Radius + FairwayExtension), + FairwayWidth, + yards + (green.Radius + FairwayExtension) + 1, + GameObjType.FAIRWAY); + + var rough = new RectGameObj(fairway.X - RoughAmt, + fairway.Y - RoughAmt, + fairway.Width + (2 * RoughAmt), + fairway.Length + (2 * RoughAmt), + GameObjType.ROUGH); + + BALL = new Ball(0, yards, 0, GameObjType.BALL); + + ScoreCardStartNewHole(); + + holeGeometry = new HoleGeometry(cup, green, fairway, rough, info.Hazard); + + w(" |> " + HOLE_NUM); + w(" | "); + w(" | "); + w(" ^^^^^^^^^^^^^^^"); + + Console.WriteLine("Hole #{0}. You are at the tee. Distance {1} yards, par {2}.", HOLE_NUM, info.Yards, info.Par); + w(info.Description); + + TeeUp(); + } + + + // --------------------------------------------------------------- TeeUp + // on the green? automatically select putter + // otherwise Ask club and swing strength + + void TeeUp() + { + if (IsOnGreen(BALL) && !IsInHazard(BALL, GameObjType.SAND)) + { + var putt = 10; + w("[PUTTER: average 10 yards]"); + var msg = Odds(20) ? "Keep your head down.\n" : ""; + + Ask(msg + "Choose your putt potency. (1-10)", 1, 10, (strength) => + { + var putter = Clubs[putt]; + Stroke(Convert.ToDouble((double)putter.Item2 * ((double)strength / 10.0)), putt); + }); + } + else + { + Ask("What club do you choose? (1-10)", 1, 10, (c) => + { + var club = Clubs[c]; + + w(" "); + Console.WriteLine("[{0}: average {1} yards]", club.Item1.ToUpper(), club.Item2); + + Ask("Now gauge your distance by a percentage of a full swing. (1-10)", 1, 10, (strength) => + { + Stroke(Convert.ToDouble((double)club.Item2 * ((double)strength / 10.0)), c); + }); + }); + }; + } + + + // -------------------------------------------------------- bitwise Flags + int dub = 0b00000000000001; + int hook = 0b00000000000010; + int slice = 0b00000000000100; + int passedCup = 0b00000000001000; + int inCup = 0b00000000010000; + int onFairway = 0b00000000100000; + int onGreen = 0b00000001000000; + int inRough = 0b00000010000000; + int inSand = 0b00000100000000; + int inTrees = 0b00001000000000; + int inWater = 0b00010000000000; + int outOfBounds = 0b00100000000000; + int luck = 0b01000000000000; + int ace = 0b10000000000000; + + + // --------------------------------------------------------------- Stroke + void Stroke(double clubAmt, int clubIndex) + { + STROKE_NUM++; + + var flags = 0b000000000000; + + // fore! only when driving + if ((STROKE_NUM == 1) && (clubAmt > 210) && Odds(30)) { w("\"...Fore !\""); }; + + // dub + if (Odds(5)) { flags |= dub; }; // there's always a 5% chance of dubbing it + + // if you're in the rough, or sand, you really should be using a wedge + if ((IsInRough(BALL) || IsInHazard(BALL, GameObjType.SAND)) && + !(clubIndex == 8 || clubIndex == 9)) + { + if (Odds(40)) { flags |= dub; }; + }; + + // trap difficulty + if (IsInHazard(BALL, GameObjType.SAND) && PlayerDifficulty == 4) + { + if (Odds(20)) { flags |= dub; }; + } + + // hook/slice + // There's 10% chance of a hook or slice + // if it's a known playerDifficulty then increase chance to 30% + // if it's a putt & putting is a playerDifficulty increase to 30% + + bool randHookSlice = (PlayerDifficulty == 1 || + PlayerDifficulty == 2 || + (PlayerDifficulty == 5 && IsOnGreen(BALL))) ? Odds(30) : Odds(10); + + if (randHookSlice) + { + if (PlayerDifficulty == 1) + { + if (Odds(80)) { flags |= hook; } else { flags |= slice; }; + } + else if (PlayerDifficulty == 2) + { + if (Odds(80)) { flags |= slice; } else { flags |= hook; }; + } + else + { + if (Odds(50)) { flags |= hook; } else { flags |= slice; }; + }; + }; + + // beginner's luck ! + // If handicap is greater than 15, there's a 10% chance of avoiding all errors + if ((Handicap > 15) && (Odds(10))) { flags |= luck; }; + + // ace + // there's a 10% chance of an Ace on a par 3 + if (CourseInfo[HOLE_NUM].Par == 3 && Odds(10) && STROKE_NUM == 1) { flags |= ace; }; + + // distance: + // If handicap is < 15, there a 50% chance of reaching club average, + // a 25% of exceeding it, and a 25% of falling short + // If handicap is > 15, there's a 25% chance of reaching club average, + // and 75% chance of falling short + // The greater the handicap, the more the ball falls short + // If poor distance is a known playerDifficulty, then reduce distance by 10% + + double distance; + int rnd = RANDOM.Next(1, 101); + + if (Handicap < 15) + { + if (rnd <= 25) + { + distance = clubAmt - (clubAmt * ((double)Handicap / 100.0)); + } + else if (rnd > 25 && rnd <= 75) + { + distance = clubAmt; + } + else + { + distance = clubAmt + (clubAmt * 0.10); + }; + } + else + { + if (rnd <= 75) + { + distance = clubAmt - (clubAmt * ((double)Handicap / 100.0)); + } + else + { + distance = clubAmt; + }; + }; + + if (PlayerDifficulty == 3) // poor distance + { + if (Odds(80)) { distance = (distance * 0.80); }; + }; + + if ((flags & luck) == luck) { distance = clubAmt; } + + // angle + // For all strokes, there's a possible "drift" of 4 degrees + // a hooks or slice increases the angle between 5-10 degrees, hook uses negative degrees + int angle = RANDOM.Next(0, 5); + if ((flags & slice) == slice) { angle = RANDOM.Next(5, 11); }; + if ((flags & hook) == hook) { angle = 0 - RANDOM.Next(5, 11); }; + if ((flags & luck) == luck) { angle = 0; }; + + var plot = PlotBall(BALL, distance, Convert.ToDouble(angle)); // calculate a new location + if ((flags & luck) == luck) { if(plot.Y > 0){ plot.Y = 2; }; }; + + flags = FindBall(new Ball(plot.X, plot.Y, plot.Offline, GameObjType.BALL), flags); + + InterpretResults(plot, flags); + } + + + // --------------------------------------------------------------- plotBall + Plot PlotBall(Ball ball, double strokeDistance, double degreesOff) + { + var cupVector = new Point(0, -1); + double radFromCup = Math.Atan2((double)ball.Y, (double)ball.X) - Math.Atan2((double)cupVector.Y, (double)cupVector.X); + double radFromBall = radFromCup - Math.PI; + + var hypotenuse = strokeDistance; + var adjacent = Math.Cos(radFromBall + ToRadians(degreesOff)) * hypotenuse; + var opposite = Math.Sqrt(Math.Pow(hypotenuse, 2) - Math.Pow(adjacent, 2)); + + Point newPos; + if (ToDegrees360(radFromBall + ToRadians(degreesOff)) > 180) + { + newPos = new Point(Convert.ToInt32(ball.X - opposite), + Convert.ToInt32(ball.Y - adjacent)); + } + else + { + newPos = new Point(Convert.ToInt32(ball.X + opposite), + Convert.ToInt32(ball.Y - adjacent)); + } + + return new Plot(newPos.X, newPos.Y, Convert.ToInt32(opposite)); + } + + + // --------------------------------------------------------------- InterpretResults + void InterpretResults(Plot plot, int flags) + { + int cupDistance = Convert.ToInt32(GetDistance(new Point(plot.X, plot.Y), + new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y))); + int travelDistance = Convert.ToInt32(GetDistance(new Point(plot.X, plot.Y), + new Point(BALL.X, BALL.Y))); + + w(" "); + + if ((flags & ace) == ace) + { + w("Hole in One! You aced it."); + ScoreCardRecordStroke(new Ball(0, 0, 0, GameObjType.BALL)); + ReportCurrentScore(); + return; + }; + + if ((flags & inTrees) == inTrees) + { + w("Your ball is lost in the trees. Take a penalty stroke."); + ScoreCardRecordStroke(BALL); + TeeUp(); + return; + }; + + if ((flags & inWater) == inWater) + { + var msg = Odds(50) ? "Your ball has gone to a watery grave." : "Your ball is lost in the water."; + w(msg + " Take a penalty stroke."); + ScoreCardRecordStroke(BALL); + TeeUp(); + return; + }; + + if ((flags & outOfBounds) == outOfBounds) + { + w("Out of bounds. Take a penalty stroke."); + ScoreCardRecordStroke(BALL); + TeeUp(); + return; + }; + + if ((flags & dub) == dub) + { + w("You dubbed it."); + ScoreCardRecordStroke(BALL); + TeeUp(); + return; + }; + + if ((flags & inCup) == inCup) + { + var msg = Odds(50) ? "You holed it." : "It's in!"; + w(msg); + ScoreCardRecordStroke(new Ball(plot.X, plot.Y, 0, GameObjType.BALL)); + ReportCurrentScore(); + return; + }; + + if (((flags & slice) == slice) && + !((flags & onGreen) == onGreen)) + { + var bad = ((flags & outOfBounds) == outOfBounds) ? " badly" : ""; + Console.WriteLine("You sliced{0}: {1} yards offline.", bad, plot.Offline); + }; + + if (((flags & hook) == hook) && + !((flags & onGreen) == onGreen)) + { + var bad = ((flags & outOfBounds) == outOfBounds) ? " badly" : ""; + Console.WriteLine("You hooked{0}: {1} yards offline.", bad, plot.Offline); + }; + + if (STROKE_NUM > 1) + { + var prevBall = ScoreCardGetPreviousStroke(); + var d1 = GetDistance(new Point(prevBall.X, prevBall.Y), + new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y)); + var d2 = cupDistance; + if (d2 > d1) { w("Too much club."); }; + }; + + if ((flags & inRough) == inRough) { w("You're in the rough."); }; + + if ((flags & inSand) == inSand) { w("You're in a sand trap."); }; + + if ((flags & onGreen) == onGreen) + { + var pd = (cupDistance < 4) ? ((cupDistance * 3) + " feet") : (cupDistance + " yards"); + Console.WriteLine("You're on the green. It's {0} from the pin.", pd); + }; + + if (((flags & onFairway) == onFairway) || + ((flags & inRough) == inRough)) + { + Console.WriteLine("Shot went {0} yards. It's {1} yards from the cup.", travelDistance, cupDistance); + }; + + ScoreCardRecordStroke(new Ball(plot.X, plot.Y, 0, GameObjType.BALL)); + + BALL = new Ball(plot.X, plot.Y, 0, GameObjType.BALL); + + TeeUp(); + } + + + // --------------------------------------------------------------- ReportCurrentScore + void ReportCurrentScore() + { + var par = CourseInfo[HOLE_NUM].Par; + if (ScoreCard[HOLE_NUM].Count == par + 1) { w("A bogey. One above par."); }; + if (ScoreCard[HOLE_NUM].Count == par) { w("Par. Nice."); }; + if (ScoreCard[HOLE_NUM].Count == (par - 1)) { w("A birdie! One below par."); }; + if (ScoreCard[HOLE_NUM].Count == (par - 2)) { w("An Eagle! Two below par."); }; + if (ScoreCard[HOLE_NUM].Count == (par - 3)) { w("Double Eagle! Unbelievable."); }; + + int totalPar = 0; + for (var i = 1; i <= HOLE_NUM; i++) { totalPar += CourseInfo[i].Par; }; + + w(" "); + w("-----------------------------------------------------"); + Console.WriteLine(" Total par for {0} hole{1} is: {2}. Your total is: {3}.", + HOLE_NUM, + ((HOLE_NUM > 1) ? "s" : ""), //plural + totalPar, + ScoreCardGetTotal()); + w("-----------------------------------------------------"); + w(" "); + + if (HOLE_NUM == 18) + { + GameOver(); + } + else + { + Thread.Sleep(2000); + NewHole(); + }; + } + + + // --------------------------------------------------------------- FindBall + int FindBall(Ball ball, int flags) + { + if (IsOnFairway(ball) && !IsOnGreen(ball)) { flags |= onFairway; } + if (IsOnGreen(ball)) { flags |= onGreen; } + if (IsInRough(ball)) { flags |= inRough; } + if (IsOutOfBounds(ball)) { flags |= outOfBounds; } + if (IsInHazard(ball, GameObjType.WATER)) { flags |= inWater; } + if (IsInHazard(ball, GameObjType.TREES)) { flags |= inTrees; } + if (IsInHazard(ball, GameObjType.SAND)) { flags |= inSand; } + + if (ball.Y < 0) { flags |= passedCup; } + + // less than 2, it's in the cup + var d = GetDistance(new Point(ball.X, ball.Y), + new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y)); + if (d < 2) { flags |= inCup; }; + + return flags; + } + + + // --------------------------------------------------------------- IsOnFairway + bool IsOnFairway(Ball ball) + { + return IsInRectangle(ball, holeGeometry.Fairway); + } + + + // --------------------------------------------------------------- IsOngreen + bool IsOnGreen(Ball ball) + { + var d = GetDistance(new Point(ball.X, ball.Y), + new Point(holeGeometry.Cup.X, holeGeometry.Cup.Y)); + return d < holeGeometry.Green.Radius; + } + + + // --------------------------------------------------------------- IsInHazard + bool IsInHazard(Ball ball, GameObjType hazard) + { + bool result = false; + Array.ForEach(holeGeometry.Hazards, (Hazard h) => + { + var d = GetDistance(new Point(ball.X, ball.Y), new Point(h.X, h.Y)); + if ((d < h.Radius) && h.Type == hazard) { result = true; }; + }); + return result; + } + + + // --------------------------------------------------------------- IsInRough + bool IsInRough(Ball ball) + { + return IsInRectangle(ball, holeGeometry.Rough) && + (IsInRectangle(ball, holeGeometry.Fairway) == false); + } + + + // --------------------------------------------------------------- IsOutOfBounds + bool IsOutOfBounds(Ball ball) + { + return (IsOnFairway(ball) == false) && (IsInRough(ball) == false); + } + + + // --------------------------------------------------------------- ScoreCardNewHole + void ScoreCardStartNewHole() + { + ScoreCard.Add(new List()); + } + + + // --------------------------------------------------------------- ScoreCardRecordStroke + void ScoreCardRecordStroke(Ball ball) + { + var clone = new Ball(ball.X, ball.Y, 0, GameObjType.BALL); + ScoreCard[HOLE_NUM].Add(clone); + } + + + // ------------------------------------------------------------ ScoreCardGetPreviousStroke + Ball ScoreCardGetPreviousStroke() + { + return ScoreCard[HOLE_NUM][ScoreCard[HOLE_NUM].Count - 1]; + } + + + // --------------------------------------------------------------- ScoreCardGetTotal + int ScoreCardGetTotal() + { + int total = 0; + ScoreCard.ForEach((h) => { total += h.Count; }); + return total; + } + + + // --------------------------------------------------------------- Ask + // input from console is always an integer passed to a callback + // or "quit" to end game + + void Ask(string question, int min, int max, Action callback) + { + w(question); + string i = Console.ReadLine().Trim().ToLower(); + if (i == "quit") { Quit(); return; }; + if (i == "bag") { ReviewBag(); }; + + int n; + bool success = Int32.TryParse(i, out n); + + if (success) + { + if (n >= min && n <= max) + { + callback(n); + } + else + { + Ask(question, min, max, callback); + } + } + else + { + Ask(question, min, max, callback); + }; + } + + + // --------------------------------------------------------------- Wait + void Wait(Action callback) + { + w("Press any key to continue."); + + ConsoleKeyInfo keyinfo; + do { keyinfo = Console.ReadKey(true); } + while (keyinfo.KeyChar < 0); + Console.Clear(); + callback(0); + } + + + // --------------------------------------------------------------- ReviewBag + void ReviewBag() + { + w(" "); + w(" # Club Average Yardage"); + w("-----------------------------------"); + w(" 1 Driver 250"); + w(" 2 3 Wood 225"); + w(" 3 5 Wood 200"); + w(" 4 Hybrid 190"); + w(" 5 4 Iron 170"); + w(" 6 7 Iron 150"); + w(" 7 9 Iron 125"); + w(" 8 Pitching wedge 110"); + w(" 9 Sand wedge 75"); + w(" 10 Putter 10"); + w(" "); + } + + + // --------------------------------------------------------------- Quit + void Quit() + { + w(""); + w("Looks like rain. Goodbye!"); + w(""); + Wait((z) => { }); + return; + } + + + // --------------------------------------------------------------- GameOver + void GameOver() + { + var net = ScoreCardGetTotal() - Handicap; + w("Good game!"); + w("Your net score is: " + net); + w("Let's visit the pro shop..."); + w(" "); + Wait((z) => { }); + return; + } + + + // YOUR BAG + // ======================================================== Clubs + (string, int)[] Clubs = new (string, int)[] { + ("",0), + + // name, average yardage + ("Driver", 250), + ("3 Wood", 225), + ("5 Wood", 200), + ("Hybrid", 190), + ("4 Iron", 170), + ("7 Iron", 150), + ("9 Iron", 125), + ("Pitching wedge", 110), + ("Sand wedge", 75), + ("Putter", 10) + }; + + + // THE COURSE + // ======================================================== CourseInfo + + HoleInfo[] CourseInfo = new HoleInfo[]{ + new HoleInfo(0, 0, 0, new Hazard[]{}, ""), // include a blank so index 1 == hole 1 + + + // -------------------------------------------------------- front 9 + // hole, yards, par, hazards, (description) + + new HoleInfo(1, 361, 4, + new Hazard[]{ + new Hazard( 20, 100, 10, GameObjType.TREES), + new Hazard(-20, 80, 10, GameObjType.TREES), + new Hazard(-20, 100, 10, GameObjType.TREES) + }, + "There are a couple of trees on the left and right."), + + new HoleInfo(2, 389, 4, + new Hazard[]{ + new Hazard(0, 160, 20, GameObjType.WATER) + }, + "There is a large water hazard across the fairway about 150 yards."), + + new HoleInfo(3, 206, 3, + new Hazard[]{ + new Hazard( 20, 20, 5, GameObjType.WATER), + new Hazard(-20, 160, 10, GameObjType.WATER), + new Hazard( 10, 12, 5, GameObjType.SAND) + }, + "There is some sand and water near the green."), + + new HoleInfo(4, 500, 5, + new Hazard[]{ + new Hazard(-14, 12, 12, GameObjType.SAND) + }, + "There's a bunker to the left of the green."), + + new HoleInfo(5, 408, 4, + new Hazard[]{ + new Hazard(20, 120, 20, GameObjType.TREES), + new Hazard(20, 160, 20, GameObjType.TREES), + new Hazard(10, 20, 5, GameObjType.SAND) + }, + "There are some trees to your right."), + + new HoleInfo(6, 359, 4, + new Hazard[]{ + new Hazard( 14, 0, 4, GameObjType.SAND), + new Hazard(-14, 0, 4, GameObjType.SAND) + }, + ""), + + new HoleInfo(7, 424, 5, + new Hazard[]{ + new Hazard(20, 200, 10, GameObjType.SAND), + new Hazard(10, 180, 10, GameObjType.SAND), + new Hazard(20, 160, 10, GameObjType.SAND) + }, + "There are several sand traps along your right."), + + new HoleInfo(8, 388, 4, + new Hazard[]{ + new Hazard(-20, 340, 10, GameObjType.TREES) + }, + ""), + + new HoleInfo(9, 196, 3, + new Hazard[]{ + new Hazard(-30, 180, 20, GameObjType.TREES), + new Hazard( 14, -8, 5, GameObjType.SAND) + }, + ""), + + // -------------------------------------------------------- back 9 + // hole, yards, par, hazards, (description) + + new HoleInfo(10, 400, 4, + new Hazard[]{ + new Hazard(-14, -8, 5, GameObjType.SAND), + new Hazard( 14, -8, 5, GameObjType.SAND) + }, + ""), + + new HoleInfo(11, 560, 5, + new Hazard[]{ + new Hazard(-20, 400, 10, GameObjType.TREES), + new Hazard(-10, 380, 10, GameObjType.TREES), + new Hazard(-20, 260, 10, GameObjType.TREES), + new Hazard(-20, 200, 10, GameObjType.TREES), + new Hazard(-10, 180, 10, GameObjType.TREES), + new Hazard(-20, 160, 10, GameObjType.TREES) + }, + "Lots of trees along the left of the fairway."), + + new HoleInfo(12, 132, 3, + new Hazard[]{ + new Hazard(-10, 120, 10, GameObjType.WATER), + new Hazard( -5, 100, 10, GameObjType.SAND) + }, + "There is water and sand directly in front of you. A good drive should clear both."), + + new HoleInfo(13, 357, 4, + new Hazard[]{ + new Hazard(-20, 200, 10, GameObjType.TREES), + new Hazard(-10, 180, 10, GameObjType.TREES), + new Hazard(-20, 160, 10, GameObjType.TREES), + new Hazard( 14, 12, 8, GameObjType.SAND) + }, + ""), + + new HoleInfo(14, 294, 4, + new Hazard[]{ + new Hazard(0, 20, 10, GameObjType.SAND) + }, + ""), + + new HoleInfo(15, 475, 5, + new Hazard[]{ + new Hazard(-20, 20, 10, GameObjType.WATER), + new Hazard( 10, 20, 10, GameObjType.SAND) + }, + "Some sand and water near the green."), + + new HoleInfo(16, 375, 4, + new Hazard[]{ + new Hazard(-14, -8, 5, GameObjType.SAND) + }, + ""), + + new HoleInfo(17, 180, 3, + new Hazard[]{ + new Hazard( 20, 100, 10, GameObjType.TREES), + new Hazard(-20, 80, 10, GameObjType.TREES) + }, + ""), + + new HoleInfo(18, 550, 5, + new Hazard[]{ + new Hazard(20, 30, 15, GameObjType.WATER) + }, + "There is a water hazard near the green.") + }; + + + // -------------------------------------------------------- HoleInfo + class HoleInfo + { + public int Hole { get; } + public int Yards { get; } + public int Par { get; } + public Hazard[] Hazard { get; } + public string Description { get; } + + public HoleInfo(int hole, int yards, int par, Hazard[] hazard, string description) + { + Hole = hole; + Yards = yards; + Par = par; + Hazard = hazard; + Description = description; + } + } + + + public enum GameObjType { BALL, CUP, GREEN, FAIRWAY, ROUGH, TREES, WATER, SAND } + + + // -------------------------------------------------------- CircleGameObj + public class CircleGameObj + { + public GameObjType Type { get; } + public int X { get; } + public int Y { get; } + public int Radius { get; } + + public CircleGameObj(int x, int y, int r, GameObjType type) + { + Type = type; + X = x; + Y = y; + Radius = r; + } + } + + + // -------------------------------------------------------- RectGameObj + public class RectGameObj + { + public GameObjType Type { get; } + public int X { get; } + public int Y { get; } + public int Width { get; } + public int Length { get; } + + public RectGameObj(int x, int y, int w, int l, GameObjType type) + { + Type = type; + X = x; + Y = y; + Width = w; + Length = l; + } + } + + + // -------------------------------------------------------- HoleGeometry + public class HoleGeometry + { + public CircleGameObj Cup { get; } + public CircleGameObj Green { get; } + public RectGameObj Fairway { get; } + public RectGameObj Rough { get; } + public Hazard[] Hazards { get; } + + public HoleGeometry(CircleGameObj cup, CircleGameObj green, RectGameObj fairway, RectGameObj rough, Hazard[] haz) + { + Cup = cup; + Green = green; + Fairway = fairway; + Rough = rough; + Hazards = haz; + } + } + + + // -------------------------------------------------------- Plot + public class Plot + { + public int X { get; } + public int Y { get; set; } + public int Offline { get; } + + public Plot(int x, int y, int offline) + { + X = x; + Y = y; + Offline = offline; + } + } + + + // -------------------------------------------------------- GetDistance + // distance between 2 points + double GetDistance(Point pt1, Point pt2) + { + return Math.Sqrt(Math.Pow((pt2.X - pt1.X), 2) + Math.Pow((pt2.Y - pt1.Y), 2)); + } + + + // -------------------------------------------------------- IsInRectangle + bool IsInRectangle(CircleGameObj pt, RectGameObj rect) + { + return ((pt.X > rect.X) && + (pt.X < rect.X + rect.Width) && + (pt.Y > rect.Y) && + (pt.Y < rect.Y + rect.Length)); + } + + + // -------------------------------------------------------- ToRadians + double ToRadians(double angle) { return angle * (Math.PI / 180.0); } + + + // -------------------------------------------------------- ToDegrees360 + // radians to 360 degrees + double ToDegrees360(double angle) + { + double deg = angle * (180.0 / Math.PI); + if (deg < 0.0) { deg += 360.0; } + return deg; + } + + + // -------------------------------------------------------- Odds + // chance an integer is <= the given argument + // between 1-100 + Random RND = new Random(); + + bool Odds(int x) + { + return RND.Next(1, 101) <= x; + } + } +} diff --git a/39 Golf/csharp/README.md b/39 Golf/csharp/README.md index 4daabb5c..126658a1 100644 --- a/39 Golf/csharp/README.md +++ b/39 Golf/csharp/README.md @@ -1,3 +1,15 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/) + +There are 2 compiled executables in the compiled/ directory (windows and linux) that you can play right away! + +Program.cs contains the C# source code. +It has been written for .NET Core 3.1 + +The source code is well documented. + + + + + From a8436342616c9cf71eb8f03a71e9f08b3a4cc346 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 25 Apr 2021 13:09:27 -0400 Subject: [PATCH 384/749] Ported Depth Charge to C# --- 31 Depth Charge/csharp/DepthCharge.sln | 25 +++++ 31 Depth Charge/csharp/Game.csproj | 9 ++ 31 Depth Charge/csharp/src/Controller.cs | 85 ++++++++++++++++ 31 Depth Charge/csharp/src/Program.cs | 47 +++++++++ 31 Depth Charge/csharp/src/View.cs | 121 +++++++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 31 Depth Charge/csharp/DepthCharge.sln create mode 100644 31 Depth Charge/csharp/Game.csproj create mode 100644 31 Depth Charge/csharp/src/Controller.cs create mode 100644 31 Depth Charge/csharp/src/Program.cs create mode 100644 31 Depth Charge/csharp/src/View.cs diff --git a/31 Depth Charge/csharp/DepthCharge.sln b/31 Depth Charge/csharp/DepthCharge.sln new file mode 100644 index 00000000..8d56c717 --- /dev/null +++ b/31 Depth Charge/csharp/DepthCharge.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31129.286 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {738F08DD-89E9-44C5-B5AC-3F21C6AEEFA1} + EndGlobalSection +EndGlobal diff --git a/31 Depth Charge/csharp/Game.csproj b/31 Depth Charge/csharp/Game.csproj new file mode 100644 index 00000000..3028f277 --- /dev/null +++ b/31 Depth Charge/csharp/Game.csproj @@ -0,0 +1,9 @@ + + + + Exe + net5.0 + DepthCharge + + + diff --git a/31 Depth Charge/csharp/src/Controller.cs b/31 Depth Charge/csharp/src/Controller.cs new file mode 100644 index 00000000..7669e67c --- /dev/null +++ b/31 Depth Charge/csharp/src/Controller.cs @@ -0,0 +1,85 @@ +using System; + +namespace DepthCharge +{ + ///

+ /// Contains functions for reading input from the user. + /// + static class Controller + { + /// + /// Retrives a dimension for the play area from the user. + /// + /// + /// Note that the original BASIC version would allow dimension values + /// of 0 or less. We're doing a little extra validation here in order + /// to avoid strange behaviour. + /// + public static int InputDimension() + { + View.PromptDimension(); + + while (true) + { + if (!Int32.TryParse(Console.ReadLine(), out var dimension)) + View.ShowInvalidNumber(); + else + if (dimension < 1) + View.ShowInvalidDimension(); + else + return dimension; + } + } + + /// + /// Retrieves a set of coordinates from the user. + /// + /// + /// The current trail number. + /// + public static (int x, int y, int depth) InputCoordinates(int trailNumber) + { + View.PromptGuess(trailNumber); + + while (true) + { + var coordinates = Console.ReadLine().Split(','); + + if (coordinates.Length < 3) + View.ShowTooFewCoordinates(); + else + if (coordinates.Length > 3) + View.ShowTooManyCoordinates(); + else + if (!Int32.TryParse(coordinates[0], out var x) || + !Int32.TryParse(coordinates[1], out var y) || + !Int32.TryParse(coordinates[2], out var depth)) + View.ShowInvalidNumber(); + else + return (x, y, depth); + } + } + + /// + /// Retrieves the user's intention to play again (or not). + /// + public static bool InputPlayAgain() + { + View.PromptPlayAgain(); + + while (true) + { + switch (Console.ReadLine()) + { + case "Y": + return true; + case "N": + return false; + default: + View.ShowInvalidYesOrNo(); + break; + } + } + } + } +} diff --git a/31 Depth Charge/csharp/src/Program.cs b/31 Depth Charge/csharp/src/Program.cs new file mode 100644 index 00000000..de3db6d9 --- /dev/null +++ b/31 Depth Charge/csharp/src/Program.cs @@ -0,0 +1,47 @@ +using System; + +namespace DepthCharge +{ + class Program + { + static void Main(string[] args) + { + var random = new Random(); + + View.ShowBanner(); + + var dimension = Controller.InputDimension(); + var maximumGuesses = CalculateMaximumGuesses(); + + View.ShowInstructions(maximumGuesses); + + do + { + View.ShowStartGame(); + + var submarineCoordinates = PlaceSubmarine(); + var trailNumber = 1; + var guess = (0, 0, 0); + + do + { + guess = Controller.InputCoordinates(trailNumber); + if (guess != submarineCoordinates) + View.ShowGuessPlacement(submarineCoordinates, guess); + } + while (guess != submarineCoordinates && trailNumber++ < maximumGuesses); + + View.ShowGameResult(submarineCoordinates, guess, trailNumber); + } + while (Controller.InputPlayAgain()); + + View.ShowFarewell(); + + int CalculateMaximumGuesses() => + (int)Math.Log2(dimension) + 1; + + (int x, int y, int depth) PlaceSubmarine() => + (random.Next(dimension), random.Next(dimension), random.Next(dimension)); + } + } +} diff --git a/31 Depth Charge/csharp/src/View.cs b/31 Depth Charge/csharp/src/View.cs new file mode 100644 index 00000000..71e83a9f --- /dev/null +++ b/31 Depth Charge/csharp/src/View.cs @@ -0,0 +1,121 @@ +using System; + +namespace DepthCharge +{ + /// + /// Contains methods for displaying information to the user. + /// + static class View + { + public static void ShowBanner() + { + Console.WriteLine(" DEPTH CHARGE"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowInstructions(int maximumGuesses) + { + Console.WriteLine("YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER"); + Console.WriteLine("AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR"); + Console.WriteLine($"MISSION IS TO DESTROY IT. YOU HAVE {maximumGuesses} SHOTS."); + Console.WriteLine("SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A"); + Console.WriteLine("TRIO OF NUMBERS -- THE FIRST TWO ARE THE"); + Console.WriteLine("SURFACE COORDINATES; THE THIRD IS THE DEPTH."); + Console.WriteLine(); + } + + public static void ShowStartGame() + { + Console.WriteLine("GOOD LUCK !"); + Console.WriteLine(); + } + + public static void ShowGuessPlacement((int x, int y, int depth) actual, (int x, int y, int depth) guess) + { + Console.Write("SONAR REPORTS SHOT WAS "); + if (guess.y > actual.y) + Console.Write("NORTH"); + if (guess.y < actual.y) + Console.Write("SOUTH"); + if (guess.x > actual.x) + Console.Write("EAST"); + if (guess.x < actual.x) + Console.Write("WEST"); + if (guess.y != actual.y || guess.x != actual.y) + Console.Write(" AND"); + if (guess.depth > actual.depth) + Console.Write (" TOO LOW."); + if (guess.depth < actual.depth) + Console.Write(" TOO HIGH."); + if (guess.depth == actual.depth) + Console.Write(" DEPTH OK."); + + Console.WriteLine(); + } + + public static void ShowGameResult((int x, int y, int depth) submarineLocation, (int x, int y, int depth) finalGuess, int trailNumber) + { + Console.WriteLine(); + + if (submarineLocation == finalGuess) + { + Console.WriteLine($"B O O M ! ! YOU FOUND IT IN {trailNumber} TRIES!"); + } + else + { + Console.WriteLine("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!"); + Console.WriteLine($"THE SUBMARINE WAS AT {submarineLocation.x}, {submarineLocation.y}, {submarineLocation.depth}"); + } + } + + public static void ShowFarewell() + { + Console.WriteLine ("OK. HOPE YOU ENJOYED YOURSELF."); + } + + public static void ShowInvalidNumber() + { + Console.WriteLine("PLEASE ENTER A NUMBER"); + } + + public static void ShowInvalidDimension() + { + Console.WriteLine("PLEASE ENTER A VALID DIMENSION"); + } + + public static void ShowTooFewCoordinates() + { + Console.WriteLine("TOO FEW COORDINATES"); + } + + public static void ShowTooManyCoordinates() + { + Console.WriteLine("TOO MANY COORDINATES"); + } + + public static void ShowInvalidYesOrNo() + { + Console.WriteLine("PLEASE ENTER Y OR N"); + } + + public static void PromptDimension() + { + Console.Write("DIMENSION OF SEARCH AREA? "); + } + + public static void PromptGuess(int trailNumber) + { + Console.WriteLine(); + Console.Write($"TRIAL #{trailNumber}? "); + } + + public static void PromptPlayAgain() + { + Console.WriteLine(); + Console.Write("ANOTHER GAME (Y OR N)? "); + } + } +} From 81e36428b2a7151dda28f657ca73b17d852b2c2d Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 26 Apr 2021 19:06:01 -0400 Subject: [PATCH 385/749] Minor quality improvements and fixes * Improved names and fixed inconsistent spacing * Update year at the start of the turn instead of the end * Input functions work more like the BASIC versions * Display city summary before end game results (as in the original version) --- 43 Hammurabi/csharp/src/Controller.cs | 43 +++++++++++++-------------- 43 Hammurabi/csharp/src/GameResult.cs | 2 +- 43 Hammurabi/csharp/src/GameState.cs | 2 +- 43 Hammurabi/csharp/src/Program.cs | 15 ++++++---- 43 Hammurabi/csharp/src/Rules.cs | 16 +++++----- 43 Hammurabi/csharp/src/View.cs | 12 ++++---- 6 files changed, 46 insertions(+), 44 deletions(-) diff --git a/43 Hammurabi/csharp/src/Controller.cs b/43 Hammurabi/csharp/src/Controller.cs index 91d1b64f..afdb83d2 100644 --- a/43 Hammurabi/csharp/src/Controller.cs +++ b/43 Hammurabi/csharp/src/Controller.cs @@ -23,7 +23,7 @@ namespace Hammurabi /// /// The updated game state. /// - public static GameState TryUntilSuccess( + public static GameState UpdateGameState( GameState state, Action prompt, Func rule) @@ -35,29 +35,28 @@ namespace Hammurabi if (!Int32.TryParse(Console.ReadLine(), out var amount)) { View.ShowInvalidNumber(); + continue; } - else - { - var (newState, result) = rule(state, amount); - switch (result) - { - case ActionResult.InsufficientLand: - View.ShowInsufficientLand(state); - break; - case ActionResult.InsufficientPopulation: - View.ShowInsufficientPopulation(state); - break; - case ActionResult.InsufficientStores: - View.ShowInsufficientStores(state); - break; - case ActionResult.Offense: - // Not sure why we have to blow up the game here... - // Maybe this made sense in the 70's. - throw new GreatOffence(); - default: - return newState; - } + var (newState, result) = rule(state, amount); + + switch (result) + { + case ActionResult.InsufficientLand: + View.ShowInsufficientLand(state); + break; + case ActionResult.InsufficientPopulation: + View.ShowInsufficientPopulation(state); + break; + case ActionResult.InsufficientStores: + View.ShowInsufficientStores(state); + break; + case ActionResult.Offense: + // Not sure why we have to blow up the game here... + // Maybe this made sense in the 70's. + throw new GreatOffence(); + default: + return newState; } } } diff --git a/43 Hammurabi/csharp/src/GameResult.cs b/43 Hammurabi/csharp/src/GameResult.cs index 23dfbe28..9c143375 100644 --- a/43 Hammurabi/csharp/src/GameResult.cs +++ b/43 Hammurabi/csharp/src/GameResult.cs @@ -40,6 +40,6 @@ /// Gets a flag indicating whether the player was impeached for /// starving too many people. /// - public bool WasImpeached { get; init; } + public bool WasPlayerImpeached { get; init; } } } diff --git a/43 Hammurabi/csharp/src/GameState.cs b/43 Hammurabi/csharp/src/GameState.cs index 3e2d1eb2..41e6fe11 100644 --- a/43 Hammurabi/csharp/src/GameState.cs +++ b/43 Hammurabi/csharp/src/GameState.cs @@ -68,6 +68,6 @@ /// /// Gets a flag indicating whether the player has been impeached. /// - public bool IsImpeached { get; init; } + public bool IsPlayerImpeached { get; init; } } } diff --git a/43 Hammurabi/csharp/src/Program.cs b/43 Hammurabi/csharp/src/Program.cs index 45d5b101..8f158839 100644 --- a/43 Hammurabi/csharp/src/Program.cs +++ b/43 Hammurabi/csharp/src/Program.cs @@ -9,7 +9,7 @@ namespace Hammurabi public static void Main(string[] args) { - var random = new Random ((int) (DateTime.UtcNow.Ticks / 10000)) ; + var random = new Random() ; var state = Rules.BeginGame(); var history = ImmutableList.Empty; @@ -17,21 +17,24 @@ namespace Hammurabi try { - while (state.Year <= GameLength && !state.IsImpeached) + while (!state.IsPlayerImpeached) { state = Rules.BeginTurn(state, random); View.ShowCitySummary(state); + if (state.Year > GameLength) + break; + View.ShowLandPrice(state); - var newState = Controller.TryUntilSuccess(state, View.PromptBuyLand, Rules.BuyLand); + var newState = Controller.UpdateGameState(state, View.PromptBuyLand, Rules.BuyLand); state = newState.Acres != state.Acres ? - newState : Controller.TryUntilSuccess(state, View.PromptSellLand, Rules.SellLand); + newState : Controller.UpdateGameState(state, View.PromptSellLand, Rules.SellLand); View.ShowSeparator(); - state = Controller.TryUntilSuccess(state, View.PromptFeedPeople, Rules.FeedPeople); + state = Controller.UpdateGameState(state, View.PromptFeedPeople, Rules.FeedPeople); View.ShowSeparator(); - state = Controller.TryUntilSuccess(state, View.PromptPlantCrops, Rules.PlantCrops); + state = Controller.UpdateGameState(state, View.PromptPlantCrops, Rules.PlantCrops); state = Rules.EndTurn(state, random); history = history.Add(state); diff --git a/43 Hammurabi/csharp/src/Rules.cs b/43 Hammurabi/csharp/src/Rules.cs index 56a59d96..36fc9c50 100644 --- a/43 Hammurabi/csharp/src/Rules.cs +++ b/43 Hammurabi/csharp/src/Rules.cs @@ -12,7 +12,7 @@ namespace Hammurabi public static GameState BeginGame() => new GameState { - Year = 1, + Year = 0, Population = 95, PopulationIncrease = 5, Starvation = 0, @@ -22,7 +22,7 @@ namespace Hammurabi Productivity = 3, Spoilage = 200, IsPlagueYear = false, - IsImpeached = false + IsPlayerImpeached = false }; /// @@ -31,6 +31,7 @@ namespace Hammurabi public static GameState BeginTurn(GameState state, Random random) => state with { + Year = state.Year + 1, Population = (state.Population + state.PopulationIncrease - state.Starvation) / (state.IsPlagueYear ? 2 : 1), LandPrice = random.Next(10) + 17, Stores = state.Stores + (state.AcresPlanted * state.Productivity) - state.Spoilage, @@ -139,23 +140,22 @@ namespace Hammurabi _ => 0 }; - var populationIncrease= (int)((double) random.Next(1, 6) * (20 * state.Acres + state.Stores + harvest - spoilage) / state.Population / 100 + 1); + var populationIncrease= (int)((double)random.Next(1, 6) * (20 * state.Acres + state.Stores + harvest - spoilage) / state.Population / 100 + 1); var plagueYear = random.Next(20) < 3; - var peopleFed = state.FoodDistributed / 20; + var peopleFed = state.FoodDistributed / 20; var starvation = peopleFed < state.Population ? state.Population - peopleFed : 0; var impeached = starvation > state.Population * 0.45; return state with { - Year = state.Year + 1, Productivity = productivity, Spoilage = spoilage, PopulationIncrease = populationIncrease, Starvation = starvation, IsPlagueYear = plagueYear, - IsImpeached = impeached + IsPlayerImpeached = impeached }; } @@ -176,7 +176,7 @@ namespace Hammurabi var acresPerPerson = finalState.Acres / finalState.Population; - var rating = finalState.IsImpeached ? + var rating = finalState.IsPlayerImpeached ? PerformanceRating.Disgraceful : (averageStarvationRate, acresPerPerson) switch { @@ -200,7 +200,7 @@ namespace Hammurabi TotalStarvation = totalStarvation, AverageStarvationRate = averageStarvationRate, Assassins = assassins, - WasImpeached = finalState.IsImpeached + WasPlayerImpeached = finalState.IsPlayerImpeached }; } } diff --git a/43 Hammurabi/csharp/src/View.cs b/43 Hammurabi/csharp/src/View.cs index be10af32..fcfb4cd5 100644 --- a/43 Hammurabi/csharp/src/View.cs +++ b/43 Hammurabi/csharp/src/View.cs @@ -110,7 +110,7 @@ namespace Hammurabi /// public static void ShowGameResult(GameResult result) { - if (!result.WasImpeached) + if (!result.WasPlayerImpeached) { Console.WriteLine($"IN YOUR 10-YEAR TERM OF OFFICE, {result.AverageStarvationRate} PERCENT OF THE"); Console.WriteLine("POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF"); @@ -124,7 +124,7 @@ namespace Hammurabi switch (result.Rating) { case PerformanceRating.Disgraceful: - if (result.WasImpeached) + if (result.WasPlayerImpeached) Console.WriteLine($"YOU STARVED {result.FinalStarvation} PEOPLE IN ONE YEAR!!!"); Console.WriteLine("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY"); @@ -163,7 +163,7 @@ namespace Hammurabi /// public static void PromptBuyLand() { - Console.WriteLine ("HOW MANY ACRES DO YOU WISH TO BUY"); + Console.Write("HOW MANY ACRES DO YOU WISH TO BUY? "); } /// @@ -171,7 +171,7 @@ namespace Hammurabi /// public static void PromptSellLand() { - Console.WriteLine("HOW MANY ACRES DO YOU WISH TO SELL"); + Console.Write("HOW MANY ACRES DO YOU WISH TO SELL? "); } /// @@ -179,7 +179,7 @@ namespace Hammurabi /// public static void PromptFeedPeople() { - Console.WriteLine("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE"); + Console.Write("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? "); } /// @@ -187,7 +187,7 @@ namespace Hammurabi /// public static void PromptPlantCrops() { - Console.WriteLine("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED"); + Console.Write("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? "); } } } From 6cf5b3948a10ebdcddc6c8bb2088baef1946b69b Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Tue, 27 Apr 2021 20:01:34 -0400 Subject: [PATCH 386/749] Ported Bowling to Java. --- 14 Bowling/java/Bowling.java | 282 +++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 14 Bowling/java/Bowling.java diff --git a/14 Bowling/java/Bowling.java b/14 Bowling/java/Bowling.java new file mode 100644 index 00000000..e443246a --- /dev/null +++ b/14 Bowling/java/Bowling.java @@ -0,0 +1,282 @@ +import java.util.Scanner; +import java.lang.Math; + +/** + * Game of Bowling + *

+ * Based on the BASIC game of Bowling here + * https://github.com/coding-horror/basic-computer-games/blob/main/14%20Bowling/bowling.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class Bowling { + + private final Scanner scan; // For user input + + public Bowling() { + + scan = new Scanner(System.in); + + } // End of constructor Bowling + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(33) + "BOWL"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + + } // End of method showIntro + + private void startGame() { + + int ball = 0; + int bell = 0; + int frame = 0; + int ii = 0; // Loop iterator + int jj = 0; // Loop iterator + int kk = 0; // Loop iterator + int numPlayers = 0; + int pinsDownBefore = 0; + int pinsDownNow = 0; + int player = 0; + int randVal = 0; + int result = 0; + + int[] pins = new int[16]; + + int[][] scores = new int[101][7]; + + String userResponse = ""; + + System.out.println("WELCOME TO THE ALLEY"); + System.out.println("BRING YOUR FRIENDS"); + System.out.println("OKAY LET'S FIRST GET ACQUAINTED"); + System.out.println(""); + System.out.println("THE INSTRUCTIONS (Y/N)"); + System.out.print("? "); + + userResponse = scan.nextLine(); + + if (userResponse.toUpperCase().equals("Y")) { + printRules(); + } + + System.out.print("FIRST OF ALL...HOW MANY ARE PLAYING? "); + numPlayers = Integer.parseInt(scan.nextLine()); + + System.out.println(""); + System.out.println("VERY GOOD..."); + + // Begin outer while loop + while (true) { + + for (ii = 1; ii <= 100; ii++) { + for (jj = 1; jj <= 6; jj++) { + scores[ii][jj] = 0; + } + } + + frame = 1; + + // Begin frame while loop + while (frame < 11) { + + // Begin loop through all players + for (player = 1; player <= numPlayers; player++) { + + pinsDownBefore = 0; + ball = 1; + result = 0; + + for (ii = 1; ii <= 15; ii++) { + pins[ii] = 0; + } + + while (true) { + + // Ball generator using mod '15' system + + System.out.println("TYPE ROLL TO GET THE BALL GOING."); + System.out.print("? "); + scan.nextLine(); + + kk = 0; + pinsDownNow = 0; + + for (ii = 1; ii <= 20; ii++) { + + randVal = (int)(Math.random() * 100) + 1; + + for (jj = 1; jj <= 10; jj++) { + + if (randVal < 15 * jj) { + break; + } + } + pins[15 * jj - randVal] = 1; + } + + // Pin diagram + + System.out.println("PLAYER: " + player + " FRAME: " + frame + " BALL: " + ball); + + for (ii = 0; ii <= 3; ii++) { + + System.out.println(""); + + System.out.print(" ".repeat(ii)); + + for (jj = 1; jj <= 4 - ii; jj++) { + + kk++; + + if (pins[kk] == 1) { + + System.out.print("O "); + + } else { + + System.out.print("+ "); + } + } + } + + System.out.println(""); + + // Roll analysis + + for (ii = 1; ii <= 10; ii++) { + pinsDownNow += pins[ii]; + } + + if (pinsDownNow - pinsDownBefore == 0) { + System.out.println("GUTTER!!"); + } + + if (ball == 1 && pinsDownNow == 10) { + System.out.println("STRIKE!!!!!"); + + // Ring bell + for (bell = 1; bell <= 4; bell++) { + System.out.print("\007"); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + result = 3; + } + + if (ball == 2 && pinsDownNow == 10) { + System.out.println("SPARE!!!!"); + result = 2; + } + + if (ball == 2 && pinsDownNow < 10) { + System.out.println("ERROR!!!"); + result = 1; + } + + if (ball == 1 && pinsDownNow < 10) { + System.out.println("ROLL YOUR 2ND BALL"); + } + + // Storage of the scores + + System.out.println(""); + + scores[frame * player][ball] = pinsDownNow; + + if (ball != 2) { + ball = 2; + pinsDownBefore = pinsDownNow; + + if (result != 3) { + scores[frame * player][ball] = pinsDownNow - pinsDownBefore; + if (result == 0) { + continue; + } + } else { + scores[frame * player][ball] = pinsDownNow; + } + + } + break; + } + + scores[frame * player][3] = result; + + } // End loop through all players + + frame++; + + } // End frame while loop + + System.out.println("FRAMES"); + + System.out.print(" "); + for (ii = 1; ii <= 10; ii++) { + System.out.print(ii + " "); + } + + System.out.println(""); + + for (player = 1; player <= numPlayers; player++) { + for (ii = 1; ii <= 3; ii++) { + System.out.print(" "); + for (jj = 1; jj <= 10; jj++) { + System.out.print (scores[jj * player][ii] + " "); + } + System.out.println(""); + } + System.out.println(""); + } + + System.out.println("DO YOU WANT ANOTHER GAME"); + System.out.print("? "); + + userResponse = scan.nextLine(); + + if (!String.valueOf(userResponse.toUpperCase().charAt(0)).equals("Y")) { + break; + } + + } // End outer while loop + + } // End of method startGame + + public void printBoard(int[] board) { + + } // End of method printBoard + + public static void printRules() { + + System.out.println("THE GAME OF BOWLING TAKES MIND AND SKILL.DURING THE GAME"); + System.out.println("THE COMPUTER WILL KEEP SCORE.YOU MAY COMPETE WITH"); + System.out.println("OTHER PLAYERS[UP TO FOUR].YOU WILL BE PLAYING TEN FRAMES"); + System.out.println("ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE"); + System.out.println("PIN IS STANDING.AFTER THE GAME THE COMPUTER WILL SHOW YOUR"); + System.out.println("SCORES ."); + + } // End of method printRules + + public static void main(String[] args) { + + Bowling game = new Bowling(); + game.play(); + + } // End of method main + +} // End of class Bowling From 3af97fd180ecf67a240ebdcbc0e39ffacba3906c Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Wed, 28 Apr 2021 00:56:48 -0500 Subject: [PATCH 387/749] Create litquiz.pl Made with Perl! --- 57 Literature Quiz/perl/litquiz.pl | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 57 Literature Quiz/perl/litquiz.pl diff --git a/57 Literature Quiz/perl/litquiz.pl b/57 Literature Quiz/perl/litquiz.pl new file mode 100644 index 00000000..f7d41075 --- /dev/null +++ b/57 Literature Quiz/perl/litquiz.pl @@ -0,0 +1,82 @@ +#!/usr/bin/perl +use strict; + + +print ' 'x 25 . "LITERATURE QUIZ\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +print "TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE.\n"; +print "\n"; print "THIS IS A MULTIPLE-CHOICE QUIZ.\n"; +print "TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK.\n"; +print "\n"; print "GOOD LUCK!\n"; +my $R=0; + + +print "\n"; print "\n"; +print "IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT\n"; +print "1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO"; +print "? "; chomp(my $A = ); + +if ($A eq 3) { + $R++; + print "VERY GOOD! HERE'S ANOTHER.\n"; + } else { + print "SORRY...FIGARO WAS HIS NAME.\n"; + } + + +print "\n"; print "\n"; +print "FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?\n"; +print "1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S"; +print "? "; chomp($A = ); + +if ($A eq 2) { + print "PRETTY GOOD!\n"; + $R=$R+1; + } else { + print "TOO BAD...IT WAS ELMER FUDD'S GARDEN.\n"; + } + + +print "\n"; print "\n"; +print "IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED\n"; +print "1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO"; +print "? "; chomp($A = ); +if ($A eq 4) { + print "YEA! YOU'RE A REAL LITERATURE GIANT.\n"; + $R=$R+1; + } else { + print "BACK TO THE BOOKS,...TOTO WAS HIS NAME.\n"; + } + + +print "\n"; print "\n"; +print "WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE\n"; +print "1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY"; +print "? "; chomp($A = ); +if ($A eq 3) { + print "GOOD MEMORY!\n"; + $R=$R+1; + } else { + print "OH, COME ON NOW...IT WAS SNOW WHITE.\n"; + } + + +print "\n"; print "\n"; +if ($R eq 4) { + print "WOW! THAT'S SUPER! YOU REALLY KNOW YOUR NURSERY\n"; + print "YOUR NEXT QUIZ WILL BE ON 2ND CENTURY CHINESE\n"; + print "LITERATURE (HA, HA, HA)\n"; + exit + } +if ($R<2) { + print "UGH. THAT WAS DEFINITELY NOT TOO SWIFT. BACK TO\n"; + print "NURSERY SCHOOL FOR YOU, MY FRIEND.\n"; + exit; + } + +print "NOT BAD, BUT YOU MIGHT SPEND A LITTLE MORE TIME\n"; +print "READING THE NURSERY GREATS.\n"; +exit; + + From 31c34129076e26af2f68b8141fbdf1b3e612d91a Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sat, 1 May 2021 10:31:14 +0400 Subject: [PATCH 388/749] Ported 86 Target to Java --- 86 Target/java/Target.java | 146 +++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 86 Target/java/Target.java diff --git a/86 Target/java/Target.java b/86 Target/java/Target.java new file mode 100644 index 00000000..869c443a --- /dev/null +++ b/86 Target/java/Target.java @@ -0,0 +1,146 @@ +import java.util.Scanner; + +/** + * TARGET + *

+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + */ +public class Target { + + private static final double RADIAN = 180 / Math.PI; + + public static void main(String[] args) { + Scanner scan = new Scanner(System.in); + + printIntro(); + + //continue till the user aborts + while (true) { + int numberShots = 0; + + final double xAxisInRadians = Math.random() * 2 * Math.PI; + final double yAxisInRadians = Math.random() * 2 * Math.PI; + System.out.printf("RADIANS FROM X AXIS = %.7f FROM Z AXIS = %.7f\n", xAxisInRadians, yAxisInRadians); + + final double p1 = 100000 * Math.random() + Math.random(); + final double x = Math.sin(yAxisInRadians) * Math.cos(xAxisInRadians) * p1; + final double y = Math.sin(yAxisInRadians) * Math.sin(xAxisInRadians) * p1; + final double z = Math.cos(yAxisInRadians) * p1; + System.out.printf("TARGET SIGHTED: APPROXIMATE COORDINATES: X=%.3f Y=%.3f Z=%.3f\n", x, y, z); + boolean targetOrSelfDestroyed = false; + while (!targetOrSelfDestroyed) { + numberShots++; + int estimatedDistance = 0; + switch (numberShots) { + case 1: + estimatedDistance = (int) (p1 * .05) * 20; + break; + case 2: + estimatedDistance = (int) (p1 * .1) * 10; + break; + case 3: + estimatedDistance = (int) (p1 * .5) * 2; + break; + case 4: + case 5: + estimatedDistance = (int) (p1); + break; + } + + System.out.printf(" ESTIMATED DISTANCE: %s\n\n", estimatedDistance); + + final TargetAttempt targetAttempt = readInput(scan); + if (targetAttempt.distance < 20) { + System.out.println("YOU BLEW YOURSELF UP!!"); + targetOrSelfDestroyed = true; + } else { + final double a1 = targetAttempt.xDeviation / RADIAN; + final double b1 = targetAttempt.zDeviation / RADIAN; + System.out.printf("RADIANS FROM X AXIS = %.7f FROM Z AXIS = %.7f\n", a1, b1); + + final double x1 = targetAttempt.distance * Math.sin(b1) * Math.cos(a1); + final double y1 = targetAttempt.distance * Math.sin(b1) * Math.sin(a1); + final double z1 = targetAttempt.distance * Math.cos(b1); + + double distance = Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y) + (z1 - z) * (z1 - z)); + if (distance > 20) { + double X2 = x1 - x; + double Y2 = y1 - y; + double Z2 = z1 - z; + if (X2 < 0) { + System.out.printf("SHOT BEHIND TARGET %.7f KILOMETERS.\n", -X2); + } else { + System.out.printf("SHOT IN FRONT OF TARGET %.7f KILOMETERS.\n", X2); + } + if (Y2 < 0) { + System.out.printf("SHOT TO RIGHT OF TARGET %.7f KILOMETERS.\n", -Y2); + } else { + System.out.printf("SHOT TO LEFT OF TARGET %.7f KILOMETERS.\n", Y2); + } + if (Z2 < 0) { + System.out.printf("SHOT BELOW TARGET %.7f KILOMETERS.\n", -Z2); + } else { + System.out.printf("SHOT ABOVE TARGET %.7f KILOMETERS.\n", Z2); + } + System.out.printf("APPROX POSITION OF EXPLOSION: X=%.7f Y=%.7f Z=%.7f\n", x1, y1, z1); + System.out.printf(" DISTANCE FROM TARGET =%.7f\n\n\n\n", distance); + } else { + System.out.println(" * * * HIT * * * TARGET IS NON-FUNCTIONAL"); + System.out.printf("DISTANCE OF EXPLOSION FROM TARGET WAS %.5f KILOMETERS.\n", distance); + System.out.printf("MISSION ACCOMPLISHED IN %s SHOTS.\n", numberShots); + targetOrSelfDestroyed = true; + } + } + } + System.out.println("\n\n\n\n\nNEXT TARGET...\n"); + } + } + + private static TargetAttempt readInput(Scanner scan) { + System.out.println("INPUT ANGLE DEVIATION FROM X, DEVIATION FROM Z, DISTANCE "); + boolean validInput = false; + TargetAttempt targetAttempt = new TargetAttempt(); + while (!validInput) { + String input = scan.nextLine(); + final String[] split = input.split(","); + try { + targetAttempt.xDeviation = Float.parseFloat(split[0]); + targetAttempt.zDeviation = Float.parseFloat(split[1]); + targetAttempt.distance = Float.parseFloat(split[2]); + validInput = true; + } catch (NumberFormatException nfe) { + System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE\n? "); + } + + } + return targetAttempt; + } + + private static void printIntro() { + System.out.println(" TARGET"); + System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + System.out.println("YOU ARE THE WEAPONS OFFICER ON THE STARSHIP ENTERPRISE"); + System.out.println("AND THIS IS A TEST TO SEE HOW ACCURATE A SHOT YOU"); + System.out.println("ARE IN A THREE-DIMENSIONAL RANGE. YOU WILL BE TOLD"); + System.out.println("THE RADIAN OFFSET FOR THE X AND Z AXES, THE LOCATION"); + System.out.println("OF THE TARGET IN THREE DIMENSIONAL RECTANGULAR COORDINATES,"); + System.out.println("THE APPROXIMATE NUMBER OF DEGREES FROM THE X AND Z"); + System.out.println("AXES, AND THE APPROXIMATE DISTANCE TO THE TARGET."); + System.out.println("YOU WILL THEN PROCEED TO SHOOT AT THE TARGET UNTIL IT IS"); + System.out.println("DESTROYED!"); + System.out.println("\nGOOD LUCK!!\n\n"); + } + + /** + * Represents the user input + */ + private static class TargetAttempt { + + double xDeviation; + double zDeviation; + double distance; + } +} + + From 31080089ff7eec8a6421c9ed970108df8da71457 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Sun, 2 May 2021 15:29:08 -0400 Subject: [PATCH 389/749] Remove unused method in Bowling.java. --- 14 Bowling/java/Bowling.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/14 Bowling/java/Bowling.java b/14 Bowling/java/Bowling.java index e443246a..998f4fb3 100644 --- a/14 Bowling/java/Bowling.java +++ b/14 Bowling/java/Bowling.java @@ -256,10 +256,6 @@ public class Bowling { } // End outer while loop } // End of method startGame - - public void printBoard(int[] board) { - - } // End of method printBoard public static void printRules() { From e6cc8305d43c44d53c3d479d2cd9a9a89507c806 Mon Sep 17 00:00:00 2001 From: Darren Cardenas <53984972+darrencardenas@users.noreply.github.com> Date: Tue, 4 May 2021 20:53:23 -0400 Subject: [PATCH 390/749] Ported FlipFlop to Java. --- 36 Flip Flop/java/FlipFlop.java | 287 ++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 36 Flip Flop/java/FlipFlop.java diff --git a/36 Flip Flop/java/FlipFlop.java b/36 Flip Flop/java/FlipFlop.java new file mode 100644 index 00000000..afca236f --- /dev/null +++ b/36 Flip Flop/java/FlipFlop.java @@ -0,0 +1,287 @@ +import java.util.Scanner; +import java.lang.Math; + +/** + * Game of FlipFlop + *

+ * Based on the BASIC game of FlipFlop here + * https://github.com/coding-horror/basic-computer-games/blob/main/36%20Flip%20Flop/flipflop.bas + *

+ * 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. + * + * Converted from BASIC to Java by Darren Cardenas. + */ + +public class FlipFlop { + + private final Scanner scan; // For user input + + private enum Step { + RANDOMIZE, INIT_BOARD, GET_NUMBER, ILLEGAL_ENTRY, FLIP_POSITION, SET_X_FIRST, SET_X_SECOND, + GENERATE_R_FIRST, GENERATE_R_SECOND, PRINT_BOARD, QUERY_RETRY + } + + public FlipFlop() { + + scan = new Scanner(System.in); + + } // End of constructor FlipFlop + + public void play() { + + showIntro(); + startGame(); + + } // End of method play + + private static void showIntro() { + + System.out.println(" ".repeat(31) + "FLIPFLOP"); + System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(""); + + } // End of method showIntro + + private void startGame() { + + double mathVal = 0; + double randVal = 0; + double tmpVal = 0; + + int index = 0; + int match = 0; + int numFlip = 0; + int numGuesses = 0; + + Step nextStep = Step.RANDOMIZE; + + String userResponse = ""; + + String[] board = new String[21]; + + System.out.println("THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:"); + System.out.println(""); + System.out.println("X X X X X X X X X X"); + System.out.println(""); + System.out.println("TO THIS:"); + System.out.println(""); + System.out.println("O O O O O O O O O O"); + System.out.println(""); + System.out.println("BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE"); + System.out.println("LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON"); + System.out.println("OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0"); + System.out.println("(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE "); + System.out.println("11 (ELEVEN)."); + System.out.println(""); + + // Begin outer while loop + while (true) { + + // Begin switch + switch (nextStep) { + + case RANDOMIZE: + + randVal = Math.random(); + + System.out.println("HERE IS THE STARTING LINE OF X'S."); + System.out.println(""); + + numGuesses = 0; + nextStep = Step.INIT_BOARD; + break; + + case INIT_BOARD: + + System.out.println("1 2 3 4 5 6 7 8 9 10"); + System.out.println("X X X X X X X X X X"); + System.out.println(""); + + // Avoid out of bounds error by starting at zero + for (index = 0; index <= 10; index++) { + board[index] = "X"; + } + + nextStep = Step.GET_NUMBER; + break; + + case GET_NUMBER: + + System.out.print("INPUT THE NUMBER? "); + userResponse = scan.nextLine(); + + try { + numFlip = Integer.parseInt(userResponse); + } + catch (NumberFormatException ex) { + nextStep = Step.ILLEGAL_ENTRY; + break; + } + + // Command to start a new game + if (numFlip == 11) { + nextStep = Step.RANDOMIZE; + break; + } + + if (numFlip > 11) { + nextStep = Step.ILLEGAL_ENTRY; + break; + } + + // Command to reset the board + if (numFlip == 0) { + nextStep = Step.INIT_BOARD; + break; + } + + if (match == numFlip) { + nextStep = Step.FLIP_POSITION; + break; + } + + match = numFlip; + + if (board[numFlip].equals("O")) { + nextStep = Step.SET_X_FIRST; + break; + } + + board[numFlip] = "O"; + nextStep = Step.GENERATE_R_FIRST; + break; + + case ILLEGAL_ENTRY: + System.out.println("ILLEGAL ENTRY--TRY AGAIN."); + nextStep = Step.GET_NUMBER; + break; + + case GENERATE_R_FIRST: + + mathVal = Math.tan(randVal + numFlip / randVal - numFlip) - Math.sin(randVal / numFlip) + 336 + * Math.sin(8 * numFlip); + + tmpVal = mathVal - (int)Math.floor(mathVal); + + numFlip = (int)(10 * tmpVal); + + if (board[numFlip].equals("O")) { + nextStep = Step.SET_X_FIRST; + break; + } + + board[numFlip] = "O"; + nextStep = Step.PRINT_BOARD; + break; + + case SET_X_FIRST: + board[numFlip] = "X"; + + if (match == numFlip) { + nextStep = Step.GENERATE_R_FIRST; + } else { + nextStep = Step.PRINT_BOARD; + } + break; + + case FLIP_POSITION: + + if (board[numFlip].equals("O")) { + nextStep = Step.SET_X_SECOND; + break; + } + + board[numFlip] = "O"; + nextStep = Step.GENERATE_R_SECOND; + break; + + case GENERATE_R_SECOND: + + mathVal = 0.592 * (1 / Math.tan(randVal / numFlip + randVal)) / Math.sin(numFlip * 2 + randVal) + - Math.cos(numFlip); + + tmpVal = mathVal - (int)mathVal; + numFlip = (int)(10 * tmpVal); + + if (board[numFlip].equals("O")) { + nextStep = Step.SET_X_SECOND; + break; + } + + board[numFlip] = "O"; + nextStep = Step.PRINT_BOARD; + break; + + case SET_X_SECOND: + + board[numFlip] = "X"; + if (match == numFlip) { + nextStep = Step.GENERATE_R_SECOND; + break; + } + + nextStep = Step.PRINT_BOARD; + break; + + case PRINT_BOARD: + System.out.println("1 2 3 4 5 6 7 8 9 10"); + + for (index = 1; index <= 10; index++) { + System.out.print(board[index] + " "); + } + + numGuesses++; + + System.out.println(""); + + for (index = 1; index <= 10; index++) { + if (!board[index].equals("O")) { + nextStep = Step.GET_NUMBER; + break; + } + } + + if (nextStep == Step.GET_NUMBER) { + break; + } + + if (numGuesses > 12) { + System.out.println("TRY HARDER NEXT TIME. IT TOOK YOU " + numGuesses + " GUESSES."); + } else { + System.out.println("VERY GOOD. YOU GUESSED IT IN ONLY " + numGuesses + " GUESSES."); + } + nextStep = Step.QUERY_RETRY; + break; + + case QUERY_RETRY: + + System.out.print("DO YOU WANT TO TRY ANOTHER PUZZLE? "); + userResponse = scan.nextLine(); + + if (userResponse.toUpperCase().charAt(0) == 'N') { + return; + } + System.out.println(""); + nextStep = Step.RANDOMIZE; + break; + + default: + System.out.println("INVALID STEP"); + nextStep = Step.QUERY_RETRY; + break; + + } // End of switch + + } // End outer while loop + + } // End of method startGame + + public static void main(String[] args) { + + FlipFlop game = new FlipFlop(); + game.play(); + + } // End of method main + +} // End of class FlipFlop From c9e779bbca9d6947bf31868072923fac63615da4 Mon Sep 17 00:00:00 2001 From: beyonddream <43626691+beyonddream@users.noreply.github.com> Date: Sat, 15 May 2021 15:55:32 -0700 Subject: [PATCH 391/749] Add Hammurabi game port to C and Rust --- 43 Hammurabi/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/43 Hammurabi/README.md b/43 Hammurabi/README.md index 1e5db404..22378ac0 100644 --- a/43 Hammurabi/README.md +++ b/43 Hammurabi/README.md @@ -5,3 +5,7 @@ https://www.atariarchives.org/basicgames/showpage.php?page=78 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) From d403bd0b1b22c3915233aa60c167e5171dd273e1 Mon Sep 17 00:00:00 2001 From: Nezumi Ronin Date: Thu, 20 May 2021 01:38:50 -0500 Subject: [PATCH 392/749] Create trap.pl Made with Perl! --- 92 Trap/perl/trap.pl | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 92 Trap/perl/trap.pl diff --git a/92 Trap/perl/trap.pl b/92 Trap/perl/trap.pl new file mode 100644 index 00000000..80349056 --- /dev/null +++ b/92 Trap/perl/trap.pl @@ -0,0 +1,62 @@ +#!/usr/bin/perl +use strict; + +print ' 'x 34 . "TRAP\n"; +print ' 'x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n"; print "\n"; print "\n"; +my $G=6; +my $N=100; +# REM-TRAP; +# REM-STEVE ULLMAN, 8-1-72; + +print "INSTRUCTIONS"; +print "? "; chomp(my $Z = uc()); +if (substr($Z,0,1) eq "Y") { + print "I AM THINKING OF A NUMBER BETWEEN 1 AND $N\n"; + print "TRY TO GUESS MY NUMBER. ON EACH GUESS,\n"; + print "YOU ARE TO ENTER 2 NUMBERS, TRYING TO TRAP\n"; + print "MY NUMBER BETWEEN THE TWO NUMBERS. I WILL\n"; + print "TELL YOU IF YOU HAVE TRAPPED MY NUMBER, IF MY\n"; + print "NUMBER IS LARGER THAN YOUR TWO NUMBERS, OR IF\n"; + print "MY NUMBER IS SMALLER THAN YOUR TWO NUMBERS.\n"; + print "IF YOU WANT TO GUESS ONE SINGLE NUMBER, TYPE\n"; + print "YOUR GUESS FOR BOTH YOUR TRAP NUMBERS.\n"; + print "YOU GET $G GUESSES TO GET MY NUMBER.\n"; + } + +while (1) { + my $Flag= 0; + my $X=int($N*rand(1))+1; + for (my $Q=1; $Q<=$G; $Q++) { + print "\n"; + print "GUESS #$Q "; + print "? "; chomp(my $Pair= uc()); + my ($A, $B)= split(",", $Pair); + if ($A eq $B && $X eq $A) { $Flag=1; last; } + + if ($A>$B) { ($A,$B)= ($B,$A); } + if ($X>$B) { + print "MY NUMBER IS LARGER THAN YOUR TRAP NUMBERS.\n"; + next; + } + if ($X<$A) { + print "MY NUMBER IS SMALLER THAN YOUR TRAP NUMBERS.\n"; + next; + } + print "YOU HAVE TRAPPED MY NUMBER.\n"; + } + + if ($Flag==0) { + print "SORRY, THAT'S $G GUESSES. THE NUMBER WAS $X\n"; + } else { + print "YOU GOT IT!!!\n"; + } + + print "\n"; + print "TRY AGAIN.\n"; + print "\n"; + } + +exit; + + From b9dd50f6e411a0a57fba1a19ac90c5fb363cd0ba Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sat, 22 May 2021 11:53:20 +0400 Subject: [PATCH 393/749] Ported 40 Gomoko to Java --- 40 Gomoko/java/Gomoko.java | 211 +++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 40 Gomoko/java/Gomoko.java diff --git a/40 Gomoko/java/Gomoko.java b/40 Gomoko/java/Gomoko.java new file mode 100644 index 00000000..64ad7c74 --- /dev/null +++ b/40 Gomoko/java/Gomoko.java @@ -0,0 +1,211 @@ +import java.util.Arrays; +import java.util.InputMismatchException; +import java.util.Scanner; + +/** + * GOMOKO + *

+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + */ +public class Gomoko { + + private static final int MIN_BOARD_SIZE = 7; + private static final int MAX_BOARD_SIZE = 19; + + public static void main(String[] args) { + printIntro(); + Scanner scan = new Scanner(System.in); + int boardSize = readBoardSize(scan); + + boolean continuePlay = true; + while (continuePlay) { + int[][] board = new int[boardSize][boardSize]; + //initialize the board elements to 0 + for (int[] ints : board) { + Arrays.fill(ints, 0); + } + + System.out.println("\n\nWE ALTERNATE MOVES. YOU GO FIRST..."); + + boolean doneRound = false; + while (!doneRound) { + Move playerMove = null; + boolean validMove = false; + while (!validMove) { + playerMove = readMove(scan); + if (playerMove.i == -1 || playerMove.j == -1) { + doneRound = true; + System.out.println("\nTHANKS FOR THE GAME!!"); + System.out.print("PLAY AGAIN (1 FOR YES, 0 FOR NO)? "); + final int playAgain = scan.nextInt(); + scan.nextLine(); + if (playAgain == 1) { + continuePlay = true; + break; + } else { + continuePlay = false; + break; + } + } else if (!isLegalMove(playerMove, boardSize)) { + System.out.println("ILLEGAL MOVE. TRY AGAIN..."); + } else if (board[playerMove.i - 1][playerMove.j - 1] != 0) { + System.out.println("SQUARE OCCUPIED. TRY AGAIN..."); + } else { + validMove = true; + } + } + + if (!doneRound) { + board[playerMove.i - 1][playerMove.j - 1] = 1; + Move computerMove = getComputerMove(playerMove, board, boardSize); + if (computerMove == null) { + computerMove = getRandomMove(board, boardSize); + } + board[computerMove.i - 1][computerMove.j - 1] = 2; + + printBoard(board); + } + } + + } + } + + //*** COMPUTER TRIES AN INTELLIGENT MOVE *** + private static Move getComputerMove(Move playerMove, int[][] board, int boardSize) { + for (int e = -1; e <= 1; e++) { + for (int f = -1; f <= 1; f++) { + if ((e + f - e * f) != 0) { + var x = playerMove.i + f; + var y = playerMove.j + f; + final Move newMove = new Move(x, y); + if (isLegalMove(newMove, boardSize)) { + if (board[newMove.i - 1][newMove.j - 1] != 0) { + newMove.i = newMove.i - e; + newMove.i = newMove.j - f; + if (!isLegalMove(newMove, boardSize)) { + return null; + } else { + if (board[newMove.i - 1][newMove.j - 1] == 0) { + return newMove; + } + } + } + } + } + } + } + return null; + } + + private static void printBoard(int[][] board) { + for (int[] ints : board) { + for (int cell : ints) { + System.out.printf(" %s", cell); + } + System.out.println(); + } + } + + //*** COMPUTER TRIES A RANDOM MOVE *** + private static Move getRandomMove(int[][] board, int boardSize) { + boolean legalMove = false; + Move randomMove = null; + while (!legalMove) { + randomMove = randomMove(boardSize); + legalMove = isLegalMove(randomMove, boardSize) && board[randomMove.i - 1][randomMove.j - 1] == 0; + + } + return randomMove; + } + + private static Move randomMove(int boardSize) { + int x = (int) (boardSize * Math.random() + 1); + int y = (int) (boardSize * Math.random() + 1); + return new Move(x, y); + } + + private static boolean isLegalMove(Move move, int boardSize) { + return (move.i >= 1) && (move.i <= boardSize) && (move.j >= 1) && (move.j <= boardSize); + } + + private static void printIntro() { + System.out.println(" GOMOKO"); + System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + System.out.println("WELCOME TO THE ORIENTAL GAME OF GOMOKO."); + System.out.println("\n"); + System.out.println("THE GAME IS PLAYED ON AN N BY N GRID OF A SIZE"); + System.out.println("THAT YOU SPECIFY. DURING YOUR PLAY, YOU MAY COVER ONE GRID"); + System.out.println("INTERSECTION WITH A MARKER. THE OBJECT OF THE GAME IS TO GET"); + System.out.println("5 ADJACENT MARKERS IN A ROW -- HORIZONTALLY, VERTICALLY, OR"); + System.out.println("DIAGONALLY. ON THE BOARD DIAGRAM, YOUR MOVES ARE MARKED"); + System.out.println("WITH A '1' AND THE COMPUTER MOVES WITH A '2'."); + System.out.println("\nTHE COMPUTER DOES NOT KEEP TRACK OF WHO HAS WON."); + System.out.println("TO END THE GAME, TYPE -1,-1 FOR YOUR MOVE.\n "); + } + + private static int readBoardSize(Scanner scan) { + System.out.print("WHAT IS YOUR BOARD SIZE (MIN 7/ MAX 19)? "); + + boolean validInput = false; + int input = 0; + while (!validInput) { + try { + input = scan.nextInt(); + if (input < MIN_BOARD_SIZE || input > MAX_BOARD_SIZE) { + System.out.printf("I SAID, THE MINIMUM IS %s, THE MAXIMUM IS %s.\n", MIN_BOARD_SIZE, MAX_BOARD_SIZE); + } else { + validInput = true; + } + } catch (InputMismatchException ex) { + System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE\n"); + validInput = false; + } finally { + scan.nextLine(); + } + } + return input; + } + + private static Move readMove(Scanner scan) { + System.out.print("YOUR PLAY (I,J)? "); + boolean validInput = false; + Move move = new Move(); + while (!validInput) { + String input = scan.nextLine(); + final String[] split = input.split(","); + try { + move.i = Integer.parseInt(split[0]); + move.j = Integer.parseInt(split[1]); + validInput = true; + } catch (NumberFormatException nfe) { + System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE\n? "); + } + + } + return move; + } + + private static class Move { + int i; + int j; + + public Move() { + } + + public Move(int i, int j) { + this.i = i; + this.j = j; + } + + @Override + public String toString() { + return "Move{" + + "i=" + i + + ", j=" + j + + '}'; + } + } + +} + From 4bf4f1da28c630dcff51ed4aaab183b53de41622 Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sat, 29 May 2021 11:37:31 +0400 Subject: [PATCH 394/749] Ported 34 Digits to Java --- 34 Digits/java/Digits.java | 186 +++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 34 Digits/java/Digits.java diff --git a/34 Digits/java/Digits.java b/34 Digits/java/Digits.java new file mode 100644 index 00000000..36ee58ae --- /dev/null +++ b/34 Digits/java/Digits.java @@ -0,0 +1,186 @@ +import java.util.Arrays; +import java.util.InputMismatchException; +import java.util.Scanner; + +/** + * DIGITS + *

+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + */ +public class Digits { + + public static void main(String[] args) { + printIntro(); + Scanner scan = new Scanner(System.in); + + boolean showInstructions = readInstructionChoice(scan); + if (showInstructions) { + printInstructions(); + } + + int a = 0, b = 1, c = 3; + int[][] m = new int[27][3]; + int[][] k = new int[3][3]; + int[][] l = new int[9][3]; + + boolean continueGame = true; + while (continueGame) { + for (int[] ints : m) { + Arrays.fill(ints, 1); + } + for (int[] ints : k) { + Arrays.fill(ints, 9); + } + for (int[] ints : l) { + Arrays.fill(ints, 3); + } + + l[0][0] = 2; + l[4][1] = 2; + l[8][2] = 2; + + int z = 26, z1 = 8, z2 = 2, runningCorrect = 0; + + for (int t = 1; t <= 3; t++) { + boolean validNumbers = false; + int[] numbers = new int[0]; + while (!validNumbers) { + System.out.println(); + numbers = read10Numbers(scan); + validNumbers = true; + for (int number : numbers) { + if (number < 0 || number > 2) { + System.out.println("ONLY USE THE DIGITS '0', '1', OR '2'."); + System.out.println("LET'S TRY AGAIN."); + validNumbers = false; + break; + } + } + } + + System.out.printf("\n%-14s%-14s%-14s%-14s", "MY GUESS", "YOUR NO.", "RESULT", "NO. RIGHT"); + for (int number : numbers) { + int s = 0; + int myGuess = 0; + for (int j = 0; j <= 2; j++) { + //What did the original author have in mind ? The first expression always results in 0 because a is always 0 + int s1 = a * k[z2][j] + b * l[z1][j] + c * m[z][j]; + if (s < s1) { + s = s1; + myGuess = j; + } else if (s1 == s) { + if (Math.random() >= 0.5) { + myGuess = j; + } + } + } + + String result; + if (myGuess != number) { + result = "WRONG"; + } else { + runningCorrect++; + result = "RIGHT"; + m[z][number] = m[z][number] + 1; + l[z1][number] = l[z1][number] + 1; + k[z2][number] = k[z2][number] + 1; + z = z - (z / 9) * 9; + z = 3 * z + number; + } + System.out.printf("\n%-14d%-14d%-14s%-14d", myGuess, number, result, runningCorrect); + + z1 = z - (z / 9) * 9; + z2 = number; + } + } + + //print summary report + System.out.println(); + if (runningCorrect > 10) { + System.out.println(); + System.out.println("I GUESSED MORE THAN 1/3 OF YOUR NUMBERS."); + System.out.println("I WIN.\u0007"); + } else if (runningCorrect < 10) { + System.out.println("I GUESSED LESS THAN 1/3 OF YOUR NUMBERS."); + System.out.println("YOU BEAT ME. CONGRATULATIONS *****"); + } else { + System.out.println("I GUESSED EXACTLY 1/3 OF YOUR NUMBERS."); + System.out.println("IT'S A TIE GAME."); + } + + continueGame = readContinueChoice(scan); + } + + System.out.println("\nTHANKS FOR THE GAME."); + } + + private static boolean readContinueChoice(Scanner scan) { + System.out.print("\nDO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO) ? "); + int choice; + try { + choice = scan.nextInt(); + return choice == 1; + } catch (InputMismatchException ex) { + return false; + } finally { + scan.nextLine(); + } + } + + private static int[] read10Numbers(Scanner scan) { + System.out.print("TEN NUMBERS, PLEASE ? "); + int[] numbers = new int[10]; + + for (int i = 0; i < numbers.length; i++) { + boolean validInput = false; + while (!validInput) { + try { + int n = scan.nextInt(); + validInput = true; + numbers[i] = n; + } catch (InputMismatchException ex) { + System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE"); + } finally { + scan.nextLine(); + } + } + } + + return numbers; + } + + private static void printInstructions() { + System.out.println("\n"); + System.out.println("PLEASE TAKE A PIECE OF PAPER AND WRITE DOWN"); + System.out.println("THE DIGITS '0', '1', OR '2' THIRTY TIMES AT RANDOM."); + System.out.println("ARRANGE THEM IN THREE LINES OF TEN DIGITS EACH."); + System.out.println("I WILL ASK FOR THEN TEN AT A TIME."); + System.out.println("I WILL ALWAYS GUESS THEM FIRST AND THEN LOOK AT YOUR"); + System.out.println("NEXT NUMBER TO SEE IF I WAS RIGHT. BY PURE LUCK,"); + System.out.println("I OUGHT TO BE RIGHT TEN TIMES. BUT I HOPE TO DO BETTER"); + System.out.println("THAN THAT *****"); + System.out.println(); + } + + private static boolean readInstructionChoice(Scanner scan) { + System.out.print("FOR INSTRUCTIONS, TYPE '1', ELSE TYPE '0' ? "); + int choice; + try { + choice = scan.nextInt(); + return choice == 1; + } catch (InputMismatchException ex) { + return false; + } finally { + scan.nextLine(); + } + } + + private static void printIntro() { + System.out.println(" DIGITS"); + System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + System.out.println("THIS IS A GAME OF GUESSING."); + } + +} + From 2cf4ad8a73715bb6f7120b381b82c149997a014c Mon Sep 17 00:00:00 2001 From: Joe Walter Date: Sat, 29 May 2021 15:08:32 -0400 Subject: [PATCH 395/749] Port banner to C# --- 06 Banner/csharp/banner.cs | 251 +++++++++++++++++++++++++++++++++ 06 Banner/csharp/banner.csproj | 8 ++ 06 Banner/csharp/banner.sln | 25 ++++ 3 files changed, 284 insertions(+) create mode 100644 06 Banner/csharp/banner.cs create mode 100644 06 Banner/csharp/banner.csproj create mode 100644 06 Banner/csharp/banner.sln diff --git a/06 Banner/csharp/banner.cs b/06 Banner/csharp/banner.cs new file mode 100644 index 00000000..6b0ff142 --- /dev/null +++ b/06 Banner/csharp/banner.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace banner +{ + class Banner + { + private int Horizontal { get; set; } + private int Vertical { get; set; } + private bool Centered { get; set; } + private string Character { get; set; } + private string Statement { get; set; } + + // This provides a bit-ended representation of each symbol + // that can be output. Each symbol is defined by 7 parts - + // where each part is an integer value that, when converted to + // the binary representation, shows which section is filled in + // with values and which are spaces. i.e., the 'filled in' + // parts represent the actual symbol on the paper. + Dictionary letters = new Dictionary() + { + {' ', new int[] { 0, 0, 0, 0, 0, 0, 0 } }, + {'A', new int[] {505, 37, 35, 34, 35, 37, 505} }, + {'B', new int[] {512, 274, 274, 274, 274, 274, 239} }, + {'C', new int[] {125, 131, 258, 258, 258, 131, 69} }, + {'D', new int[] {512, 258, 258, 258, 258, 131, 125} }, + {'E', new int[] {512, 274, 274, 274, 274, 258, 258} }, + {'F', new int[] {512, 18, 18, 18, 18, 2, 2} }, + {'G', new int[] {125, 131, 258, 258, 290, 163, 101} }, + {'H', new int[] {512, 17, 17, 17, 17, 17, 512} }, + {'I', new int[] {258, 258, 258, 512, 258, 258, 258} }, + {'J', new int[] {65, 129, 257, 257, 257, 129, 128} }, + {'K', new int[] {512, 17, 17, 41, 69, 131, 258} }, + {'L', new int[] {512, 257, 257, 257, 257, 257, 257} }, + {'M', new int[] {512, 7, 13, 25, 13, 7, 512} }, + {'N', new int[] {512, 7, 9, 17, 33, 193, 512} }, + {'O', new int[] {125, 131, 258, 258, 258, 131, 125} }, + {'P', new int[] {512, 18, 18, 18, 18, 18, 15} }, + {'Q', new int[] {125, 131, 258, 258, 322, 131, 381} }, + {'R', new int[] {512, 18, 18, 50, 82, 146, 271} }, + {'S', new int[] {69, 139, 274, 274, 274, 163, 69} }, + {'T', new int[] {2, 2, 2, 512, 2, 2, 2} }, + {'U', new int[] {128, 129, 257, 257, 257, 129, 128} }, + {'V', new int[] {64, 65, 129, 257, 129, 65, 64} }, + {'W', new int[] {256, 257, 129, 65, 129, 257, 256} }, + {'X', new int[] {388, 69, 41, 17, 41, 69, 388} }, + {'Y', new int[] {8, 9, 17, 481, 17, 9, 8} }, + {'Z', new int[] {386, 322, 290, 274, 266, 262, 260} }, + {'0', new int[] {57, 69, 131, 258, 131, 69, 57} }, + {'1', new int[] {0, 0, 261, 259, 512, 257, 257} }, + {'2', new int[] {261, 387, 322, 290, 274, 267, 261} }, + {'3', new int[] {66, 130, 258, 274, 266, 150, 100} }, + {'4', new int[] {33, 49, 41, 37, 35, 512, 33} }, + {'5', new int[] {160, 274, 274, 274, 274, 274, 226} }, + {'6', new int[] {194, 291, 293, 297, 305, 289, 193} }, + {'7', new int[] {258, 130, 66, 34, 18, 10, 8} }, + {'8', new int[] {69, 171, 274, 274, 274, 171, 69} }, + {'9', new int[] {263, 138, 74, 42, 26, 10, 7} }, + {'?', new int[] {5, 3, 2, 354, 18, 11, 5} }, + {'*', new int[] {69, 41, 17, 512, 17, 41, 69} }, + {'=', new int[] {41, 41, 41, 41, 41, 41, 41} }, + {'!', new int[] {1, 1, 1, 384, 1, 1, 1} }, + {'.', new int[] {1, 1, 129, 449, 129, 1, 1} } + }; + + + ///

+ /// This displays the provided text on the screen and then waits for the user + /// to enter a integer value greater than 0. + /// + /// Text to display on the screen asking for the input + /// The integer value entered by the user + private int GetNumber(string DisplayText) + { + Console.Write(DisplayText); + string TempStr = Console.ReadLine(); + + Int32.TryParse(TempStr, out int TempInt); + + if (TempInt <= 0) + { + throw new ArgumentException($"{DisplayText} must be greater than zero"); + } + + return TempInt; + } + + /// + /// This displays the provided text on the screen and then waits for the user + /// to enter a Y or N. It cheats by just looking for a 'y' and returning that + /// as true. Anything else that the user enters is returned as false. + /// + /// Text to display on the screen asking for the input + /// Returns true or false + private bool GetBool(string DisplayText) + { + Console.Write(DisplayText); + return (Console.ReadLine().StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); + } + + /// + /// This displays the provided text on the screen and then waits for the user + /// to enter an arbitrary string. That string is then returned 'as-is'. + /// + /// Text to display on the screen asking for the input + /// The string entered by the user. + private string GetString(string DisplayText) + { + Console.Write(DisplayText); + return (Console.ReadLine().ToUpper()); + } + + /// + /// This queries the user for the various inputs needed by the program. + /// + private void GetInput() + { + Horizontal = GetNumber("Horizontal "); + Vertical = GetNumber("Vertical "); + Centered = GetBool("Centered "); + Character = GetString("Character (type 'ALL' if you want character being printed) "); + Statement = GetString("Statement "); + // We don't care about what the user enters here. This is just telling them + // to set the page in the printer. + _ = GetString("Set page "); + } + + /// + /// This prints out a single character of the banner - adding + /// a few blanks lines as a spacer between characters. + /// + private void PrintChar(char ch) + { + // In the trivial case (a space character), just print out the spaces + if (ch.Equals(' ')) + { + Console.WriteLine(new string('\n', 7 * Horizontal)); + return; + } + + // If a specific character to be printed was provided by the user, + // then user that as our ouput character - otherwise take the + // current character + char outCh = Character == "ALL" ? ch : Character[0]; + int[] letter = new int[7]; + try + { + letters[outCh].CopyTo(letter, 0); + } + catch (KeyNotFoundException) + { + throw new KeyNotFoundException($"The provided letter {outCh} was not found in the letters list"); + } + + // New int array declarations default to zeros + // numSections decides how many 'sections' need to be printed + // for a given line of each character + int[] numSections = new int[7]; + // fillInSection decides whether each 'section' of the + // character gets filled in with the character or with blanks + int[] fillInSection = new int[9]; + + // This iterates through each of the parts that make up + // each letter. Each part represents 1 * Horizontal lines + // of actual output. + for (int idx = 0; idx < 7; idx++) + { + // This uses the value in each part to decide which + // sections are empty spaces in the letter or filled in + // spaces. For each section marked with 1 in fillInSection, + // that will correspond to 1 * Vertical characters actually + // being output. + for (int exp = 8; exp >= 0; exp--) + { + if (Math.Pow(2, exp) < letter[idx]) + { + fillInSection[8 - exp] = 1; + letter[idx] -= (int)Math.Pow(2, exp); + if (letter[idx] == 1) + { + // Once we've exhausted all of the sections + // defined in this part of the letter, then + // we marked that number and break out of this + // for loop. + numSections[idx] = 8 - exp; + break; + } + } + } + + // Now that we know which sections of this part of the letter + // are filled in or spaces, we can actually create the string + // to print out. + string lineStr = ""; + + if (Centered) + lineStr += new string(' ', (int)(63 - 4.5 * Vertical) * 1 / 1 + 1); + + for (int idx2 = 0; idx2 <= numSections[idx]; idx2++) + { + lineStr = lineStr + new string(fillInSection[idx2] == 0 ? ' ' : outCh, Vertical); + } + + // Then we print that string out 1 * Horizontal number of times + for (int lineidx = 1; lineidx <= Horizontal; lineidx++) + { + Console.WriteLine(lineStr); + } + } + + // Finally, add a little spacer after each character for readability. + Console.WriteLine(new string('\n', 2 * Horizontal - 1)); + } + + /// + /// This prints the entire banner based in the parameters + /// the user provided. + /// + private void PrintBanner() + { + // Iterate through each character in the statement + foreach (char ch in Statement) + { + PrintChar(ch); + } + + // In the original version, it would print an additional 75 blank + // lines in order to feed the printer paper...don't really need this + // since we're not actually printing. + Console.WriteLine(new string('\n', 75)); + } + + /// + /// Main entry point into the banner class and handles the main loop. + /// + public void Play() + { + GetInput(); + PrintBanner(); + } + } + + class Program + { + static void Main(string[] args) + { + new Banner().Play(); + } + } +} diff --git a/06 Banner/csharp/banner.csproj b/06 Banner/csharp/banner.csproj new file mode 100644 index 00000000..c73e0d16 --- /dev/null +++ b/06 Banner/csharp/banner.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/06 Banner/csharp/banner.sln b/06 Banner/csharp/banner.sln new file mode 100644 index 00000000..34f63984 --- /dev/null +++ b/06 Banner/csharp/banner.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "banner", "banner.csproj", "{9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E24FA30-F2AC-4BF3-ADFB-92D3F796561C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FF2A268C-9C4A-457F-8733-2E8931E07A1D} + EndGlobalSection +EndGlobal From dea43e1d308de98d03db94eccb8c848ec7f8c75b Mon Sep 17 00:00:00 2001 From: Joe Walter Date: Sat, 29 May 2021 15:48:10 -0400 Subject: [PATCH 396/749] Port banner to VB --- 06 Banner/csharp/banner.cs | 18 +-- 06 Banner/vbnet/banner.sln | 25 ++++ 06 Banner/vbnet/banner.vb | 226 ++++++++++++++++++++++++++++++++++ 06 Banner/vbnet/banner.vbproj | 9 ++ 4 files changed, 269 insertions(+), 9 deletions(-) create mode 100644 06 Banner/vbnet/banner.sln create mode 100644 06 Banner/vbnet/banner.vb create mode 100644 06 Banner/vbnet/banner.vbproj diff --git a/06 Banner/csharp/banner.cs b/06 Banner/csharp/banner.cs index 6b0ff142..e3e59b4b 100644 --- a/06 Banner/csharp/banner.cs +++ b/06 Banner/csharp/banner.cs @@ -153,19 +153,19 @@ namespace banner throw new KeyNotFoundException($"The provided letter {outCh} was not found in the letters list"); } - // New int array declarations default to zeros - // numSections decides how many 'sections' need to be printed - // for a given line of each character - int[] numSections = new int[7]; - // fillInSection decides whether each 'section' of the - // character gets filled in with the character or with blanks - int[] fillInSection = new int[9]; - // This iterates through each of the parts that make up // each letter. Each part represents 1 * Horizontal lines // of actual output. for (int idx = 0; idx < 7; idx++) { + // New int array declarations default to zeros + // numSections decides how many 'sections' need to be printed + // for a given line of each character + int[] numSections = new int[7]; + // fillInSection decides whether each 'section' of the + // character gets filled in with the character or with blanks + int[] fillInSection = new int[9]; + // This uses the value in each part to decide which // sections are empty spaces in the letter or filled in // spaces. For each section marked with 1 in fillInSection, @@ -228,7 +228,7 @@ namespace banner // In the original version, it would print an additional 75 blank // lines in order to feed the printer paper...don't really need this // since we're not actually printing. - Console.WriteLine(new string('\n', 75)); + // Console.WriteLine(new string('\n', 75)); } /// diff --git a/06 Banner/vbnet/banner.sln b/06 Banner/vbnet/banner.sln new file mode 100644 index 00000000..5fdc8737 --- /dev/null +++ b/06 Banner/vbnet/banner.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "banner", "banner.vbproj", "{1738D297-A04C-4E6E-8219-D9E72982C39D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1738D297-A04C-4E6E-8219-D9E72982C39D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1738D297-A04C-4E6E-8219-D9E72982C39D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1738D297-A04C-4E6E-8219-D9E72982C39D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1738D297-A04C-4E6E-8219-D9E72982C39D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {04E18CE1-1C55-432F-A15A-DC2FA9DDC0F1} + EndGlobalSection +EndGlobal diff --git a/06 Banner/vbnet/banner.vb b/06 Banner/vbnet/banner.vb new file mode 100644 index 00000000..90e183b8 --- /dev/null +++ b/06 Banner/vbnet/banner.vb @@ -0,0 +1,226 @@ +Imports System + +Module Banner + Private Horizontal As Integer + Private Vertical As Integer + Private Centered As Boolean + Private Character As String + Private Statement As String + + ' This provides a bit-ended representation of each symbol + ' that can be output. Each symbol Is defined by 7 parts - + ' where each part Is an integer value that, when converted to + ' the binary representation, shows which section Is filled in + ' with values And which are spaces. i.e., the 'filled in' + ' parts represent the actual symbol on the paper. + Private letters As Dictionary(Of Char, Integer()) = New Dictionary(Of Char, Integer()) From + { + {" ", {0, 0, 0, 0, 0, 0, 0}}, + {"A", {505, 37, 35, 34, 35, 37, 505}}, + {"B", {512, 274, 274, 274, 274, 274, 239}}, + {"C", {125, 131, 258, 258, 258, 131, 69}}, + {"D", {512, 258, 258, 258, 258, 131, 125}}, + {"E", {512, 274, 274, 274, 274, 258, 258}}, + {"F", {512, 18, 18, 18, 18, 2, 2}}, + {"G", {125, 131, 258, 258, 290, 163, 101}}, + {"H", {512, 17, 17, 17, 17, 17, 512}}, + {"I", {258, 258, 258, 512, 258, 258, 258}}, + {"J", {65, 129, 257, 257, 257, 129, 128}}, + {"K", {512, 17, 17, 41, 69, 131, 258}}, + {"L", {512, 257, 257, 257, 257, 257, 257}}, + {"M", {512, 7, 13, 25, 13, 7, 512}}, + {"N", {512, 7, 9, 17, 33, 193, 512}}, + {"O", {125, 131, 258, 258, 258, 131, 125}}, + {"P", {512, 18, 18, 18, 18, 18, 15}}, + {"Q", {125, 131, 258, 258, 322, 131, 381}}, + {"R", {512, 18, 18, 50, 82, 146, 271}}, + {"S", {69, 139, 274, 274, 274, 163, 69}}, + {"T", {2, 2, 2, 512, 2, 2, 2}}, + {"U", {128, 129, 257, 257, 257, 129, 128}}, + {"V", {64, 65, 129, 257, 129, 65, 64}}, + {"W", {256, 257, 129, 65, 129, 257, 256}}, + {"X", {388, 69, 41, 17, 41, 69, 388}}, + {"Y", {8, 9, 17, 481, 17, 9, 8}}, + {"Z", {386, 322, 290, 274, 266, 262, 260}}, + {"0", {57, 69, 131, 258, 131, 69, 57}}, + {"1", {0, 0, 261, 259, 512, 257, 257}}, + {"2", {261, 387, 322, 290, 274, 267, 261}}, + {"3", {66, 130, 258, 274, 266, 150, 100}}, + {"4", {33, 49, 41, 37, 35, 512, 33}}, + {"5", {160, 274, 274, 274, 274, 274, 226}}, + {"6", {194, 291, 293, 297, 305, 289, 193}}, + {"7", {258, 130, 66, 34, 18, 10, 8}}, + {"8", {69, 171, 274, 274, 274, 171, 69}}, + {"9", {263, 138, 74, 42, 26, 10, 7}}, + {"?", {5, 3, 2, 354, 18, 11, 5}}, + {"*", {69, 41, 17, 512, 17, 41, 69}}, + {"=", {41, 41, 41, 41, 41, 41, 41}}, + {"!", {1, 1, 1, 384, 1, 1, 1}}, + {".", {1, 1, 129, 449, 129, 1, 1}} + } + + ' + ' This displays the provided text on the screen And then waits for the user + ' to enter a integer value greater than 0. + ' + ' Text to display on the screen asking for the input + ' The integer value entered by the user + Private Function GetNumber(DisplayText As String) As Integer + Console.Write(DisplayText) + Dim TempStr As String = Console.ReadLine() + Dim TempInt As Integer + + Int32.TryParse(TempStr, TempInt) + + If (TempInt <= 0) Then + Throw New ArgumentException($"{DisplayText} must be greater than zero") + End If + + Return TempInt + End Function + + ' + ' This displays the provided text on the screen And then waits for the user + ' to enter a Y Or N. It cheats by just looking for a 'y' and returning that + ' as true. Anything else that the user enters Is returned as false. + ' + ' Text to display on the screen asking for the input + ' Returns true Or false + Private Function GetBool(DisplayText As String) As Boolean + Console.Write(DisplayText) + Return Console.ReadLine().StartsWith("y", StringComparison.InvariantCultureIgnoreCase) + End Function + + ' + ' This displays the provided text on the screen And then waits for the user + ' to enter an arbitrary string. That string Is then returned 'as-is'. + ' + ' Text to display on the screen asking for the input + ' The string entered by the user. + Private Function GetString(DisplayText As String) As String + Console.Write(DisplayText) + Return (Console.ReadLine().ToUpper()) + End Function + + ' + ' This queries the user for the various inputs needed by the program. + ' + Private Sub GetInput() + Horizontal = GetNumber("Horizontal ") + Vertical = GetNumber("Vertical ") + Centered = GetBool("Centered ") + Character = GetString("Character (type 'ALL' if you want character being printed) ") + Statement = GetString("Statement ") + ' We don't care about what the user enters here. This is just telling them + ' to set the page in the printer. + GetString("Set page ") + End Sub + + ' + ' This prints out a single character of the banner - adding + ' a few blanks lines as a spacer between characters. + ' + Private Sub PrintChar(ch As Char) + ' In the trivial case (a space character), just print out the spaces + If ch.Equals(" ") Then + Console.WriteLine(New String("\n", 7 * Horizontal)) + Return + End If + + ' If a specific character to be printed was provided by the user, + ' then user that as our ouput character - otherwise take the + ' current character + Dim outCh As Char = IIf(Character.Equals("ALL"), ch, Character.Substring(0, 1)) + Dim letter(7) As Integer + Try + letters(outCh).CopyTo(letter, 0) + Catch ex As KeyNotFoundException + Throw New KeyNotFoundException($"The provided letter {outCh} was not found in the letters list") + End Try + + ' This iterates through each of the parts that make up + ' each letter. Each part represents 1 * Horizontal lines + ' of actual output. + For idx As Integer = 0 To 7 + ' New int array declarations default to zeros + ' numSections decides how many 'sections' need to be printed + ' for a given line of each character + Dim numSections(7) As Integer + ' fillInSection decides whether each 'section' of the + ' character gets filled in with the character Or with blanks + Dim fillInSection(9) As Integer + + ' This uses the value in each part to decide which + ' sections are empty spaces in the letter Or filled in + ' spaces. For each section marked with 1 in fillInSection, + ' that will correspond to 1 * Vertical characters actually + ' being output. + For exp As Integer = 8 To 0 Step -1 + If (Math.Pow(2, exp) < letter(idx)) Then + fillInSection(8 - exp) = 1 + letter(idx) -= Math.Pow(2, exp) + If (letter(idx) = 1) Then + ' Once we've exhausted all of the sections + ' defined in this part of the letter, then + ' we marked that number And break out of this + ' for loop. + numSections(idx) = 8 - exp + Exit For + End If + End If + Next exp + + ' Now that we know which sections of this part of the letter + ' are filled in Or spaces, we can actually create the string + ' to print out. + Dim lineStr As String = "" + + If (Centered) Then + lineStr += New String(" ", (63 - 4.5 * Vertical) * 1 / 1 + 1) + End If + + For idx2 As Integer = 0 To numSections(idx) + lineStr = lineStr + New String(IIf(fillInSection(idx2) = 0, " ", outCh), Vertical) + Next idx2 + + ' Then we print that string out 1 * Horizontal number of times + For lineIdx As Integer = 1 To Horizontal + Console.WriteLine(lineStr) + Next lineIdx + Next idx + + + ' Finally, add a little spacer after each character for readability. + Console.WriteLine(New String(Environment.NewLine, 2 * Horizontal - 1)) + End Sub + + ' + ' This prints the entire banner based in the parameters + ' the user provided. + ' + Private Sub PrintBanner() + ' Iterate through each character in the statement + For Each ch As Char In Statement + PrintChar(ch) + Next ch + + ' In the original version, it would print an additional 75 blank + ' lines in order to feed the printer paper...don't really need this + ' since we're not actually printing. + Console.WriteLine(New String(Environment.NewLine, 75)) + End Sub + + ' + ' Main entry point into the banner class And handles the main loop. + ' + Public Sub Play() + GetInput() + PrintBanner() + End Sub +End Module + +Module Program + Sub Main(args As String()) + Banner.Play() + End Sub +End Module diff --git a/06 Banner/vbnet/banner.vbproj b/06 Banner/vbnet/banner.vbproj new file mode 100644 index 00000000..659fea7b --- /dev/null +++ b/06 Banner/vbnet/banner.vbproj @@ -0,0 +1,9 @@ + + + + Exe + banner + netcoreapp3.1 + + + From 2f0645bc14794ae62f83ab1773d016874fc47886 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 30 May 2021 21:04:37 +1000 Subject: [PATCH 397/749] Implement Hexapawn in C# --- 46 Hexapawn/csharp/Hexapawn.sln | 34 +++++ 46 Hexapawn/csharp/Hexapawn/Board.cs | 73 ++++++++++ 46 Hexapawn/csharp/Hexapawn/Cell.cs | 53 +++++++ 46 Hexapawn/csharp/Hexapawn/Computer.cs | 146 ++++++++++++++++++++ 46 Hexapawn/csharp/Hexapawn/Game.cs | 49 +++++++ 46 Hexapawn/csharp/Hexapawn/GameSeries.cs | 27 ++++ 46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj | 8 ++ 46 Hexapawn/csharp/Hexapawn/Human.cs | 64 +++++++++ 46 Hexapawn/csharp/Hexapawn/IPlayer.cs | 8 ++ 46 Hexapawn/csharp/Hexapawn/Input.cs | 112 +++++++++++++++ 46 Hexapawn/csharp/Hexapawn/Move.cs | 68 +++++++++ 46 Hexapawn/csharp/Hexapawn/Pawn.cs | 19 +++ 46 Hexapawn/csharp/Hexapawn/Program.cs | 71 ++++++++++ 13 files changed, 732 insertions(+) create mode 100644 46 Hexapawn/csharp/Hexapawn.sln create mode 100644 46 Hexapawn/csharp/Hexapawn/Board.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Cell.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Computer.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Game.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/GameSeries.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj create mode 100644 46 Hexapawn/csharp/Hexapawn/Human.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/IPlayer.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Input.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Move.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Pawn.cs create mode 100644 46 Hexapawn/csharp/Hexapawn/Program.cs diff --git a/46 Hexapawn/csharp/Hexapawn.sln b/46 Hexapawn/csharp/Hexapawn.sln new file mode 100644 index 00000000..6cfc8a8f --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hexapawn", "Hexapawn\Hexapawn.csproj", "{679D95BE-6E0C-4D8C-A2D4-0957576B63F3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Debug|x64.ActiveCfg = Debug|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Debug|x64.Build.0 = Debug|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Debug|x86.ActiveCfg = Debug|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Debug|x86.Build.0 = Debug|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Release|Any CPU.Build.0 = Release|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Release|x64.ActiveCfg = Release|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Release|x64.Build.0 = Release|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Release|x86.ActiveCfg = Release|Any CPU + {679D95BE-6E0C-4D8C-A2D4-0957576B63F3}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/46 Hexapawn/csharp/Hexapawn/Board.cs b/46 Hexapawn/csharp/Hexapawn/Board.cs new file mode 100644 index 00000000..ba7d19ad --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Board.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using static Hexapawn.Pawn; + +namespace Hexapawn +{ + internal class Board : IEnumerable, IEquatable + { + private readonly Pawn[] _cells; + + public Board() + { + _cells = new[] + { + Black, Black, Black, + None, None, None, + White, White, White + }; + } + + public Board(params Pawn[] cells) + { + _cells = cells; + } + + public Pawn this[int index] + { + get => _cells[index - 1]; + set => _cells[index - 1] = value; + } + + public Board Reflected => new(Cell.AllCells.Select(c => this[c.Reflected]).ToArray()); + + public IEnumerator GetEnumerator() => _cells.OfType().GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public override string ToString() + { + var builder = new StringBuilder().AppendLine(); + for (int row = 0; row < 3; row++) + { + builder.Append(" "); + for (int col = 0; col < 3; col++) + { + builder.Append(_cells[row * 3 + col]); + } + builder.AppendLine(); + } + return builder.ToString(); + } + + public bool Equals(Board other) => other?.Zip(this).All(x => x.First == x.Second) ?? false; + + public override bool Equals(object obj) => Equals(obj as Board); + + public override int GetHashCode() + { + var hash = 19; + + for (int i = 0; i < 9; i++) + { + hash = hash * 53 + _cells[i].GetHashCode(); + } + + return hash; + } + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Cell.cs b/46 Hexapawn/csharp/Hexapawn/Cell.cs new file mode 100644 index 00000000..7647e0bc --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Cell.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; + +namespace Hexapawn +{ + // Represents a cell on the board, numbered 1 to 9, with support for finding the reflection of the reference around + // the middle column of the board. + internal class Cell + { + private static readonly Cell[] _cells = new Cell[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + private static readonly Cell[] _reflected = new Cell[] { 3, 2, 1, 6, 5, 4, 9, 8, 7 }; + + private readonly int _number; + + private Cell(int number) + { + if (number < 1 || number > 9) + { + throw new ArgumentOutOfRangeException(nameof(number), number, "Must be from 1 to 9"); + } + + _number = number; + } + + // Facilitates enumerating all the cells. + public static IEnumerable AllCells => _cells; + + // Takes a value input by the user and attempts to create a Cell reference + public static bool TryCreate(float input, out Cell cell) + { + if (IsInteger(input) && input >= 1 && input <= 9) + { + cell = (int)input; + return true; + } + + cell = default; + return false; + + static bool IsInteger(float value) => value - (int)value == 0; + } + + // Returns the reflection of the cell reference about the middle column of the board. + public Cell Reflected => _reflected[_number - 1]; + + // Allows the cell reference to be used where an int is expected, such as the indexer in Board. + public static implicit operator int(Cell c) => c._number; + + public static implicit operator Cell(int number) => new(number); + + public override string ToString() => _number.ToString(); + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Computer.cs b/46 Hexapawn/csharp/Hexapawn/Computer.cs new file mode 100644 index 00000000..41e2b4a2 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Computer.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using static Hexapawn.Pawn; +using static Hexapawn.Cell; + +namespace Hexapawn +{ + /// + /// Encapsulates the logic of the computer player. + /// + internal class Computer : IPlayer + { + private readonly Random _random = new(); + private readonly Dictionary> _potentialMoves; + private (List, Move) _lastMove; + + public Computer() + { + // This dictionary implements the data in the original code, which encodes board positions for which the + // computer has a legal move, and the list of possible moves for each position: + // 900 DATA -1,-1,-1,1,0,0,0,1,1,-1,-1,-1,0,1,0,1,0,1 + // 905 DATA -1,0,-1,-1,1,0,0,0,1,0,-1,-1,1,-1,0,0,0,1 + // 910 DATA -1,0,-1,1,1,0,0,1,0,-1,-1,0,1,0,1,0,0,1 + // 915 DATA 0,-1,-1,0,-1,1,1,0,0,0,-1,-1,-1,1,1,1,0,0 + // 920 DATA -1,0,-1,-1,0,1,0,1,0,0,-1,-1,0,1,0,0,0,1 + // 925 DATA 0,-1,-1,0,1,0,1,0,0,-1,0,-1,1,0,0,0,0,1 + // 930 DATA 0,0,-1,-1,-1,1,0,0,0,-1,0,0,1,1,1,0,0,0 + // 935 DATA 0,-1,0,-1,1,1,0,0,0,-1,0,0,-1,-1,1,0,0,0 + // 940 DATA 0,0,-1,-1,1,0,0,0,0,0,-1,0,1,-1,0,0,0,0 + // 945 DATA -1,0,0,-1,1,0,0,0,0 + // 950 DATA 24,25,36,0,14,15,36,0,15,35,36,47,36,58,59,0 + // 955 DATA 15,35,36,0,24,25,26,0,26,57,58,0 + // 960 DATA 26,35,0,0,47,48,0,0,35,36,0,0,35,36,0,0 + // 965 DATA 36,0,0,0,47,58,0,0,15,0,0,0 + // 970 DATA 26,47,0,0,47,58,0,0,35,36,47,0,28,58,0,0,15,47,0,0 + // + // The original code loaded this data into two arrays. + // 40 FOR I=1 TO 19: FOR J=1 TO 9: READ B(I,J): NEXT J: NEXT I + // 45 FOR I=1 TO 19: FOR J=1 TO 4: READ M(I,J): NEXT J: NEXT I + // + // When finding moves for the computer the first array was searched for the current board position, or the + // reflection of it, and the resulting index was used in the second array to get the possible moves. + // With this dictionary we can just use the current board as the index, and retrieve a list of moves for + // consideration by the computer. + _potentialMoves = new() + { + [new(Black, Black, Black, White, None, None, None, White, White)] = Moves((2, 4), (2, 5), (3, 6)), + [new(Black, Black, Black, None, White, None, White, None, White)] = Moves((1, 4), (1, 5), (3, 6)), + [new(Black, None, Black, Black, White, None, None, None, White)] = Moves((1, 5), (3, 5), (3, 6), (4, 7)), + [new(None, Black, Black, White, Black, None, None, None, White)] = Moves((3, 6), (5, 8), (5, 9)), + [new(Black, None, Black, White, White, None, None, White, None)] = Moves((1, 5), (3, 5), (3, 6)), + [new(Black, Black, None, White, None, White, None, None, White)] = Moves((2, 4), (2, 5), (2, 6)), + [new(None, Black, Black, None, Black, White, White, None, None)] = Moves((2, 6), (5, 7), (5, 8)), + [new(None, Black, Black, Black, White, White, White, None, None)] = Moves((2, 6), (3, 5)), + [new(Black, None, Black, Black, None, White, None, White, None)] = Moves((4, 7), (4, 8)), + [new(None, Black, Black, None, White, None, None, None, White)] = Moves((3, 5), (3, 6)), + [new(None, Black, Black, None, White, None, White, None, None)] = Moves((3, 5), (3, 6)), + [new(Black, None, Black, White, None, None, None, None, White)] = Moves((3, 6)), + [new(None, None, Black, Black, Black, White, None, None, None)] = Moves((4, 7), (5, 8)), + [new(Black, None, None, White, White, White, None, None, None)] = Moves((1, 5)), + [new(None, Black, None, Black, White, White, None, None, None)] = Moves((2, 6), (4, 7)), + [new(Black, None, None, Black, Black, White, None, None, None)] = Moves((4, 7), (5, 8)), + [new(None, None, Black, Black, White, None, None, None, None)] = Moves((3, 5), (3, 6), (4, 7)), + [new(None, Black, None, White, Black, None, None, None, None)] = Moves((2, 8), (5, 8)), + [new(Black, None, None, Black, White, None, None, None, None)] = Moves((1, 5), (4, 7)) + }; + } + + public int Wins { get; private set; } + + public void AddWin() => Wins++; + + // Try to make a move. We first try to find a legal move for the current board position. + public bool TryMove(Board board) + { + if (TryGetMoves(board, out var moves, out var reflected) && + TrySelectMove(moves, out var move)) + { + // We've found a move, so we record it as the last move made, and then announce and make the move. + _lastMove = (moves, move); + + // If we found the move from a reflacted match of the board we need to make the reflected move. + if (reflected) { move = move.Reflected; } + + Console.WriteLine($"I move {move}"); + move.Execute(board); + return true; + } + + // We haven't found a move for this board position, so remove the previous move that led to this board + // position from future consideration. We don't want to make that move again, because we now know it's a + // non-winning move. + ExcludeLastMoveFromFuturePlay(); + + return false; + } + + // Looks up the given board and its reflection in the potential moves dictionary. If it's found then we have a + // list of potential moves. If the board is not found in the dictionary then the computer has no legal moves, + // and the human player wins. + private bool TryGetMoves(Board board, out List moves, out bool reflected) + { + if (_potentialMoves.TryGetValue(board, out moves)) + { + reflected = false; + return true; + } + + if (_potentialMoves.TryGetValue(board.Reflected, out moves)) + { + reflected = true; + return true; + } + + reflected = default; + return false; + } + + // Get a random move from the list. If the list is empty, then we've previously eliminated all the moves for + // this board position as being non-winning moves. We therefore resign the game. + private bool TrySelectMove(List moves, out Move move) + { + if (moves.Any()) + { + move = moves[_random.Next(moves.Count)]; + return true; + } + + Console.Write("I resign."); + move = null; + return false; + } + + private void ExcludeLastMoveFromFuturePlay() + { + var (moves, move) = _lastMove; + moves.Remove(move); + } + + private static List Moves(params Move[] moves) => moves.ToList(); + + public bool IsFullyAdvanced(Board board) => + board[9] == Black || board[8] == Black || board[7] == Black; + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Game.cs b/46 Hexapawn/csharp/Hexapawn/Game.cs new file mode 100644 index 00000000..95e321ff --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Game.cs @@ -0,0 +1,49 @@ +using System; + +namespace Hexapawn +{ + // Runs a single game of Hexapawn + internal class Game + { + private readonly Board _board; + private readonly Human _human; + private readonly Computer _computer; + + public Game(Human human, Computer computer) + { + _board = new Board(); + _human = human; + _computer = computer; + } + + public IPlayer Play() + { + Console.WriteLine(_board); + + while(true) + { + _human.Move(_board); + + Console.WriteLine(_board); + + if (!_computer.TryMove(_board)) + { + return _human; + } + + Console.WriteLine(_board); + + if (_computer.IsFullyAdvanced(_board) || _human.HasNoPawns(_board)) + { + return _computer; + } + + if (!_human.HasLegalMove(_board)) + { + Console.Write("You can't move, so "); + return _computer; + } + } + } + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/GameSeries.cs b/46 Hexapawn/csharp/Hexapawn/GameSeries.cs new file mode 100644 index 00000000..6f45cab7 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/GameSeries.cs @@ -0,0 +1,27 @@ +using System; + +namespace Hexapawn +{ + // Runs series of games between the computer and the human player + internal class GameSeries + { + private readonly Computer _computer = new(); + private readonly Human _human = new(); + + public void Play() + { + while (true) + { + var game = new Game(_human, _computer); + + var winner = game.Play(); + winner.AddWin(); + Console.WriteLine(winner == _computer ? "I win." : "You win."); + + Console.Write($"I have won {_computer.Wins} and you {_human.Wins}"); + Console.WriteLine($" out of {_computer.Wins + _human.Wins} games."); + Console.WriteLine(); + } + } + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj b/46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/46 Hexapawn/csharp/Hexapawn/Human.cs b/46 Hexapawn/csharp/Hexapawn/Human.cs new file mode 100644 index 00000000..d2d24118 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Human.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using static Hexapawn.Cell; +using static Hexapawn.Move; +using static Hexapawn.Pawn; + +namespace Hexapawn +{ + internal class Human : IPlayer + { + public int Wins { get; private set; } + + public void Move(Board board) + { + while (true) + { + var move = Input.GetMove("Your move"); + + if (TryExecute(board, move)) { return; } + + Console.WriteLine("Illegal move."); + } + } + + public void AddWin() => Wins++; + + public bool HasLegalMove(Board board) + { + foreach (var from in AllCells.Where(c => c > 3)) + { + if (board[from] != White) { continue; } + + if (HasLegalMove(board, from)) + { + return true; + } + } + + return false; + } + + private bool HasLegalMove(Board board, Cell from) => + Right(from).IsRightDiagonalToCapture(board) || + Straight(from).IsStraightMoveToEmptySpace(board) || + from > 4 && Left(from).IsLeftDiagonalToCapture(board); + + public bool HasNoPawns(Board board) => board.All(c => c != White); + + public bool TryExecute(Board board, Move move) + { + if (board[move.From] != White) { return false; } + + if (move.IsStraightMoveToEmptySpace(board) || + move.IsLeftDiagonalToCapture(board) || + move.IsRightDiagonalToCapture(board)) + { + move.Execute(board); + return true; + } + + return false; + } + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/IPlayer.cs b/46 Hexapawn/csharp/Hexapawn/IPlayer.cs new file mode 100644 index 00000000..7313904e --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/IPlayer.cs @@ -0,0 +1,8 @@ +namespace Hexapawn +{ + // An interface implemented by a player of the game to track the number of wins. + internal interface IPlayer + { + void AddWin(); + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Input.cs b/46 Hexapawn/csharp/Hexapawn/Input.cs new file mode 100644 index 00000000..d169f2f6 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Input.cs @@ -0,0 +1,112 @@ +using System; +using System.Linq; + +namespace Hexapawn +{ + // Provides input methods which emulate the BASIC interpreter's keyboard input routines + internal static class Input + { + internal static char GetYesNo(string prompt) + { + while (true) + { + Console.Write($"{prompt} (Y-N)? "); + var response = Console.ReadLine().FirstOrDefault(); + if ("YyNn".Contains(response)) + { + return char.ToUpperInvariant(response); + } + } + } + + // Implements original code: + // 120 PRINT "YOUR MOVE"; + // 121 INPUT M1,M2 + // 122 IF M1=INT(M1)AND M2=INT(M2)AND M1>0 AND M1<10 AND M2>0 AND M2<10 THEN 130 + // 123 PRINT "ILLEGAL CO-ORDINATES." + // 124 GOTO 120 + internal static Move GetMove(string prompt) + { + while(true) + { + ReadNumbers(prompt, out var from, out var to); + + if (Move.TryCreate(from, to, out var move)) + { + return move; + } + + Console.WriteLine("Illegal Coordinates."); + } + } + + internal static void Prompt(string text = "") => Console.Write($"{text}? "); + + internal static void ReadNumbers(string prompt, out float number1, out float number2) + { + while (!TryReadNumbers(prompt, out number1, out number2)) + { + prompt = ""; + } + } + + private static bool TryReadNumbers(string prompt, out float number1, out float number2) + { + Prompt(prompt); + var inputValues = ReadStrings(); + + if (!TryParseNumber(inputValues[0], out number1)) + { + number2 = default; + return false; + } + + if (inputValues.Length == 1) + { + return TryReadNumber("?", out number2); + } + + if (!TryParseNumber(inputValues[1], out number2)) + { + number2 = default; + return false; + } + + if (inputValues.Length > 2) + { + Console.WriteLine("!Extra input ingored"); + } + + return true; + } + + private static bool TryReadNumber(string prompt, out float number) + { + Prompt(prompt); + var inputValues = ReadStrings(); + + if (!TryParseNumber(inputValues[0], out number)) + { + return false; + } + + if (inputValues.Length > 1) + { + Console.WriteLine("!Extra input ingored"); + } + + return true; + } + + private static string[] ReadStrings() => Console.ReadLine().Split(',', StringSplitOptions.TrimEntries); + + private static bool TryParseNumber(string text, out float number) + { + if (float.TryParse(text, out number)) { return true; } + + Console.WriteLine("!Number expected - retry input line"); + number = default; + return false; + } + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Move.cs b/46 Hexapawn/csharp/Hexapawn/Move.cs new file mode 100644 index 00000000..9581a959 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Move.cs @@ -0,0 +1,68 @@ +using static Hexapawn.Pawn; + +namespace Hexapawn +{ + /// + /// Represents a move which may, or may not, be legal. + /// + internal class Move + { + private readonly Cell _from; + private readonly Cell _to; + private readonly int _metric; + + public Move(Cell from, Cell to) + { + _from = from; + _to = to; + _metric = _from - _to; + } + + public void Deconstruct(out Cell from, out Cell to) + { + from = _from; + to = _to; + } + + public Cell From => _from; + + // Produces the mirror image of the current moved, reflected around the central column of the board. + public Move Reflected => (_from.Reflected, _to.Reflected); + + // Allows a tuple of two ints to be implicitly converted to a Move. + public static implicit operator Move((int From, int To) value) => new(value.From, value.To); + + // Takes floating point coordinates, presumably from keyboard input, and attempts to create a Move object. + public static bool TryCreate(float input1, float input2, out Move move) + { + if (Cell.TryCreate(input1, out var from) && + Cell.TryCreate(input2, out var to)) + { + move = (from, to); + return true; + } + + move = default; + return false; + } + + public static Move Right(Cell from) => (from, from - 2); + public static Move Straight(Cell from) => (from, from - 3); + public static Move Left(Cell from) => (from, from - 4); + + public bool IsStraightMoveToEmptySpace(Board board) => _metric == 3 && board[_to] == None; + + public bool IsLeftDiagonalToCapture(Board board) => _metric == 4 && _from != 7 && board[_to] == Black; + + public bool IsRightDiagonalToCapture(Board board) => + _metric == 2 && _from != 9 && _from != 6 && board[_to] == Black; + + public void Execute(Board board) + { + board[_to] = board[_from]; + board[_from] = None; + } + + public override string ToString() => $"from {_from} to {_to}"; + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Pawn.cs b/46 Hexapawn/csharp/Hexapawn/Pawn.cs new file mode 100644 index 00000000..7a4c5633 --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Pawn.cs @@ -0,0 +1,19 @@ +namespace Hexapawn +{ + // Represents the contents of a cell on the board + internal class Pawn + { + public static readonly Pawn Black = new('X'); + public static readonly Pawn White = new('O'); + public static readonly Pawn None = new('.'); + + private readonly char _symbol; + + private Pawn(char symbol) + { + _symbol = symbol; + } + + public override string ToString() => _symbol.ToString(); + } +} diff --git a/46 Hexapawn/csharp/Hexapawn/Program.cs b/46 Hexapawn/csharp/Hexapawn/Program.cs new file mode 100644 index 00000000..59917dfa --- /dev/null +++ b/46 Hexapawn/csharp/Hexapawn/Program.cs @@ -0,0 +1,71 @@ +using System; + +namespace Hexapawn +{ + // Hexapawn: Interpretation of hexapawn game as presented in + // Martin Gardner's "The Unexpected Hanging and Other Mathematic + // al Diversions", Chapter Eight: A Matchbox Game-Learning Machine. + // Original version for H-P timeshare system by R.A. Kaapke 5/5/76 + // Instructions by Jeff Dalton + // Conversion to MITS BASIC by Steve North + // Conversion to C# by Andrew Cooper + class Program + { + static void Main() + { + DisplayTitle(); + + if (Input.GetYesNo("Instructions") == 'Y') + { + DisplayInstructions(); + } + + var games = new GameSeries(); + + games.Play(); + } + + private static void DisplayTitle() + { + Console.WriteLine(" Hexapawn"); + Console.WriteLine(" Creative Computing Morristown, New Jersey"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + private static void DisplayInstructions() + { + Console.WriteLine(); + Console.WriteLine("This program plays the game of Hexapawn."); + Console.WriteLine("Hexapawn is played with Chess pawns on a 3 by 3 board."); + Console.WriteLine("The pawns are move as in Chess - one space forward to"); + Console.WriteLine("an empty space, or one space forward and diagonally to"); + Console.WriteLine("capture an opposing man. On the board, your pawns"); + Console.WriteLine("are 'O', the computer's pawns are 'X', and empty"); + Console.WriteLine("squares are '.'. To enter a move, type the number of"); + Console.WriteLine("the square you are moving from, followed by the number"); + Console.WriteLine("of the square you will move to. The numbers must be"); + Console.WriteLine("separated by a comma."); + Console.WriteLine(); + Console.WriteLine("The computer starts a series of games knowing only when"); + Console.WriteLine("the game is won (a draw is impossible) and how to move."); + Console.WriteLine("It has no strategy at first and just moves randomly."); + Console.WriteLine("However, it learns from each game. Thus winning becomes"); + Console.WriteLine("more and more difficult. Also, to help offset your"); + Console.WriteLine("initial advantage, you will not be told how to win the"); + Console.WriteLine("game but must learn this by playing."); + Console.WriteLine(); + Console.WriteLine("The numbering of the board is as follows:"); + Console.WriteLine(" 123"); + Console.WriteLine(" 456"); + Console.WriteLine(" 789"); + Console.WriteLine(); + Console.WriteLine("For example, to move your rightmost pawn forward,"); + Console.WriteLine("you would type 9,6 in response to the question"); + Console.WriteLine("'Your move ?'. Since I'm a good sport, you'll always"); + Console.WriteLine("go first."); + Console.WriteLine(); + } + } +} From ec2d063fb94e776e81cd616bb7316cc5f8e55643 Mon Sep 17 00:00:00 2001 From: Joe Walter Date: Sun, 30 May 2021 10:51:29 -0400 Subject: [PATCH 398/749] Port Batnum to Python and VB --- .gitignore | 1 + 08 Batnum/python/batnum.py | 159 +++++++++++++++++++++++++++ 08 Batnum/vbnet/Program.vb | 199 ++++++++++++++++++++++++++++++++++ 08 Batnum/vbnet/batnum.sln | 25 +++++ 08 Batnum/vbnet/batnum.vbproj | 9 ++ 5 files changed, 393 insertions(+) create mode 100644 08 Batnum/python/batnum.py create mode 100644 08 Batnum/vbnet/Program.vb create mode 100644 08 Batnum/vbnet/batnum.sln create mode 100644 08 Batnum/vbnet/batnum.vbproj diff --git a/.gitignore b/.gitignore index a186b7a3..78bed0e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ */.vs +*.suo bin/ obj/ diff --git a/08 Batnum/python/batnum.py b/08 Batnum/python/batnum.py new file mode 100644 index 00000000..0f3473ed --- /dev/null +++ b/08 Batnum/python/batnum.py @@ -0,0 +1,159 @@ +from enum import Enum + +class WinOptions(Enum): + Undefined = 0 + TakeLast = 1 + AvoidLast = 2 + +class StartOptions(Enum): + Undefined = 0 + ComputerFirst = 1 + PlayerFirst = 2 + +def PrintIntro(): + '''Prints out the introduction and rules for the game.''' + print("BATNUM".rjust(33, ' ')) + print("CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY".rjust(15, ' ')) + print() + print() + print() + print("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE") + print("COMPUTER IS YOUR OPPONENT.") + print() + print("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU") + print( "AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.") + print("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR") + print("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.") + print("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.") + print("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.") + print() + return + +def GetParams(): + '''This requests the necessary parameters to play the game. + + Returns a set with the five game parameters: + pileSize - the starting size of the object pile + minSelect - minimum selection that can be made on each turn + maxSelect - maximum selection that can be made on each turn + startOption - 1 if the computer is first + or 2 if the player is first + winOption - 1 if the goal is to take the last object + or 2 if the goal is to not take the last object + ''' + pileSize = 0 + winOption = WinOptions.Undefined + minSelect = 0 + maxSelect = 0 + startOption = StartOptions.Undefined + + while pileSize < 1: + pileSize = int(input("ENTER PILE SIZE ")) + while winOption == WinOptions.Undefined: + winOption = int(input("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ")) + while minSelect < 1 or maxSelect < 1 or minSelect > maxSelect: + (minSelect, maxSelect) = [int(x) for x in input("ENTER MIN AND MAX ").split(' ')] + while startOption == StartOptions.Undefined: + startOption = int(input("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ")) + return (pileSize, minSelect, maxSelect, startOption, winOption) + +def PlayerMove(pileSize, minSelect, maxSelect, startOption, winOption): + '''This handles the player's turn - asking the player how many objects + to take and doing some basic validation around that input. Then it + checks for any win conditions. + + Returns a boolean indicating whether the game is over and the new pileSize.''' + playerDone = False + while not playerDone: + playerMove = int(input("YOUR MOVE ")) + if playerMove == 0: + print ("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.") + return (True, pileSize) + if playerMove > maxSelect or playerMove < minSelect: + print("ILLEGAL MOVE, REENTER IT") + continue + pileSize = pileSize - playerMove + playerDone = True + if pileSize <= 0: + if winOption == WinOptions.AvoidLast: + print("TOUGH LUCK, YOU LOSE.") + else: + print("CONGRATULATIONS, YOU WIN.") + return (True, pileSize) + return (False, pileSize) + +def ComputerPick(pileSize, minSelect, maxSelect, startOption, winOption): + '''This handles the logic to determine how many objects the computer + will select on its turn. + ''' + q = pileSize - 1 if winOption == WinOptions.AvoidLast else pileSize + c = minSelect + maxSelect + computerPick = q - (c * int(q / c)) + if computerPick < minSelect: + computerPick = minSelect + if computerPick > maxSelect: + computerPick = maxSelect + return computerPick + +def ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption): + '''This handles the computer's turn - first checking for the various + win/lose conditions and then calculating how many objects + the computer will take. + + Returns a boolean indicating whether the game is over and the new pileSize.''' + # First, check for win conditions on this move + # In this case, we win by taking the last object and + # the remaining pile is less than max select + # so the computer can grab them all and win + if winOption == WinOptions.TakeLast and pileSize <= maxSelect: + print (f"COMPUTER TAKES {pileSize} AND WINS.") + return (True, pileSize) + # In this case, we lose by taking the last object and + # the remaining pile is less than minsize and the computer + # has to take all of them. + if winOption == WinOptions.AvoidLast and pileSize <= minSelect: + print (f"COMPUTER TAKES {minSelect} AND LOSES.") + return (True, pileSize) + + # Otherwise, we determine how many the computer selects + currSel = ComputerPick(pileSize, minSelect, maxSelect, startOption, winOption) + pileSize = pileSize - currSel + print(f"COMPUTER TAKES {currSel} AND LEAVES {pileSize}") + return (False, pileSize) + +def PlayGame(pileSize, minSelect, maxSelect, startOption, winOption): + '''This is the main game loop - repeating each turn until one + of the win/lose conditions is met. + ''' + gameOver = False + # playersTurn is a boolean keeping track of whether it's the + # player's or computer's turn + playersTurn = startOption == StartOptions.PlayerFirst + + while not gameOver: + if playersTurn: + (gameOver, pileSize) = PlayerMove(pileSize, minSelect, maxSelect, startOption, winOption) + playersTurn = False + if gameOver: + return + if not playersTurn: + (gameOver, pileSize) = ComputerMove(pileSize, minSelect, maxSelect, startOption, winOption) + playersTurn = True + + return + +if __name__ == "__main__": + + pileSize = 0 + minSelect = 0 + maxSelect = 0 + # 1 = to take last, 2 = to avoid last + winOption = 0 + # 1 = computer first, 2 = user first + startOption = 0 + + while True: + PrintIntro() + (pileSize, minSelect, maxSelect, startOption, winOption) = GetParams() + # Just keep playing the game until the user kills it with ctrl-C + PlayGame(pileSize, minSelect, maxSelect, startOption, winOption) diff --git a/08 Batnum/vbnet/Program.vb b/08 Batnum/vbnet/Program.vb new file mode 100644 index 00000000..4ba9ad9d --- /dev/null +++ b/08 Batnum/vbnet/Program.vb @@ -0,0 +1,199 @@ +Imports System + +Module BatNum + Enum WinOptions + Undefined = 0 + TakeLast = 1 + AvoidLast = 2 + End Enum + + Enum StartOptions + Undefined = 0 + ComputerFirst = 1 + PlayerFirst = 2 + End Enum + + Dim pileSize As Integer = 0 + Dim minSelect As Integer = 0 + Dim maxSelect As Integer = 0 + Dim startOption As StartOptions = StartOptions.Undefined + Dim winOption As WinOptions = WinOptions.Undefined + + ' + ' Prints the intro and rules of the game. + ' + Private Sub PrintIntro() + Console.WriteLine("BATNUM".PadLeft(33, " ")) + Console.WriteLine("CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY".PadLeft(15, " ")) + Console.WriteLine() + Console.WriteLine() + Console.WriteLine() + Console.WriteLine("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE") + Console.WriteLine("COMPUTER IS YOUR OPPONENT.") + Console.WriteLine() + Console.WriteLine("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU") + Console.WriteLine("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.") + Console.WriteLine("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR") + Console.WriteLine("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.") + Console.WriteLine("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.") + Console.WriteLine("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.") + Console.WriteLine() + End Sub + + ' + ' Asks the user for the various parameters necessary + ' to play the game. + ' + Private Sub GetParams() + ' Reset the game parameters + pileSize = 0 + minSelect = 0 + maxSelect = 0 + startOption = StartOptions.Undefined + winOption = WinOptions.Undefined + + While pileSize < 1 + Console.Write("ENTER PILE SIZE ") + pileSize = Convert.ToInt32(Console.ReadLine()) + End While + While winOption = WinOptions.Undefined + Console.Write("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST: ") + winOption = Convert.ToInt32(Console.ReadLine()) + End While + While minSelect < 1 Or maxSelect < 1 Or minSelect > maxSelect + Console.Write("ENTER MIN AND MAX ") + Dim vals = Console.ReadLine().ToString().Split(" ").[Select](Function(n) Integer.Parse(n)).ToList() + If vals.Count() <> 2 Then + Continue While + End If + minSelect = vals(0) + maxSelect = vals(1) + End While + While startOption = StartOptions.Undefined + Console.Write("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ") + startOption = Convert.ToInt32(Console.ReadLine()) + End While + End Sub + + ' + 'This handles the player's turn - asking the player how many objects + 'to take And doing some basic validation around that input. Then it + 'checks for any win conditions. + ' + 'Returns a Boolean indicating whether the game Is over And the New pileSize.' + Private Function PlayerMove() As Boolean + Dim playerDone As Boolean = False + + While Not playerDone + Console.WriteLine("YOUR MOVE ") + Dim playerNum As Integer = Convert.ToInt32(Console.ReadLine()) + If playerNum = 0 Then + Console.WriteLine("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.") + Return True + End If + If playerNum > maxSelect Or playerNum < minSelect Then + Console.WriteLine("ILLEGAL MOVE, REENTER IT") + Continue While + End If + + pileSize = pileSize - playerNum + playerDone = True + If pileSize <= 0 Then + If winOption = WinOptions.AvoidLast Then + Console.WriteLine("TOUGH LUCK, YOU LOSE.") + Else + Console.WriteLine("CONGRATULATIONS, YOU WIN.") + End If + Return True + End If + End While + + Return False + End Function + + ' + 'This handles the logic to determine how many objects the computer + 'will select on its turn. + ' + Private Function ComputerPick() As Integer + Dim q As Integer = IIf(winOption = WinOptions.AvoidLast, pileSize - 1, pileSize) + Dim c As Integer = minSelect + maxSelect + Dim computerNum As Integer = q - (c * Int(q / c)) + If computerNum < minSelect Then + computerNum = minSelect + End If + If computerNum > maxSelect Then + ComputerPick = maxSelect + End If + + Return computerNum + End Function + + ' + 'This handles the computer's turn - first checking for the various + 'win/lose conditions And then calculating how many objects + 'the computer will take. + ' + 'Returns a boolean indicating whether the game is over.' + Private Function ComputerMove() As Boolean + ' First, check For win conditions On this move + ' In this Case, we win by taking the last Object And + ' the remaining pile Is less than max Select + ' so the computer can grab them all And win + If winOption = WinOptions.TakeLast And pileSize <= maxSelect Then + Console.WriteLine($"COMPUTER TAKES {pileSize} AND WINS.") + Return True + End If + ' In this Case, we lose by taking the last Object And + ' the remaining pile Is less than minsize And the computer + ' has To take all Of them. + If winOption = WinOptions.AvoidLast And pileSize <= minSelect Then + Console.WriteLine($"COMPUTER TAKES {minSelect} AND LOSES.") + Return True + End If + + ' Otherwise, we determine how many the computer selects + Dim currSel As Integer = ComputerPick() + pileSize = pileSize - currSel + Console.WriteLine($"COMPUTER TAKES {currSel} AND LEAVES {pileSize}") + Return False + End Function + + ' + 'This is the main game loop - repeating each turn until one + 'of the win/lose conditions Is met. + ' + Private Sub PlayGame() + Dim gameOver As Boolean = False + ' playersTurn Is a Boolean keeping track Of whether it's the + ' player's or computer's turn + Dim playersTurn As Boolean = (startOption = StartOptions.PlayerFirst) + + While Not gameOver + If playersTurn Then + gameOver = PlayerMove() + playersTurn = False + If gameOver Then Return + End If + + If Not playersTurn Then + gameOver = ComputerMove() + playersTurn = True + End If + End While + End Sub + + Public Sub Play() + While True + PrintIntro() + GetParams() + PlayGame() + End While + End Sub +End Module + +Module Program + Sub Main(args As String()) + BatNum.Play() + End Sub +End Module diff --git a/08 Batnum/vbnet/batnum.sln b/08 Batnum/vbnet/batnum.sln new file mode 100644 index 00000000..b3f63f59 --- /dev/null +++ b/08 Batnum/vbnet/batnum.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "batnum", "batnum.vbproj", "{D577E429-F84D-4E84-86E7-E6526CFD5FD9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D577E429-F84D-4E84-86E7-E6526CFD5FD9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {426DF7FE-66E7-4319-9AD8-7A2DD3964A2F} + EndGlobalSection +EndGlobal diff --git a/08 Batnum/vbnet/batnum.vbproj b/08 Batnum/vbnet/batnum.vbproj new file mode 100644 index 00000000..3c21499c --- /dev/null +++ b/08 Batnum/vbnet/batnum.vbproj @@ -0,0 +1,9 @@ + + + + Exe + batnum + netcoreapp3.1 + + + From 6ee857bf2df1bbefc81b6d25cbe9f0fd7f8e942c Mon Sep 17 00:00:00 2001 From: Joe Walter Date: Sun, 6 Jun 2021 14:14:53 -0400 Subject: [PATCH 399/749] C# and VB port of word --- 96 Word/csharp/Program.cs | 163 +++++++++++++++++++++++++++++++++++++ 96 Word/csharp/word.csproj | 8 ++ 96 Word/csharp/word.sln | 25 ++++++ 96 Word/vbnet/Program.vb | 145 +++++++++++++++++++++++++++++++++ 96 Word/vbnet/word.sln | 25 ++++++ 96 Word/vbnet/word.vbproj | 9 ++ 6 files changed, 375 insertions(+) create mode 100644 96 Word/csharp/Program.cs create mode 100644 96 Word/csharp/word.csproj create mode 100644 96 Word/csharp/word.sln create mode 100644 96 Word/vbnet/Program.vb create mode 100644 96 Word/vbnet/word.sln create mode 100644 96 Word/vbnet/word.vbproj diff --git a/96 Word/csharp/Program.cs b/96 Word/csharp/Program.cs new file mode 100644 index 00000000..464787c5 --- /dev/null +++ b/96 Word/csharp/Program.cs @@ -0,0 +1,163 @@ +using System; +using System.Linq; +using System.Text; + +namespace word +{ + class Word + { + // Here's the list of potential words that could be selected + // as the winning word. + private string[] words = { "DINKY", "SMOKE", "WATER", "GRASS", "TRAIN", "MIGHT", "FIRST", + "CANDY", "CHAMP", "WOULD", "CLUMP", "DOPEY" }; + + /// + /// Outputs the instructions of the game. + /// + private void intro() + { + Console.WriteLine("WORD".PadLeft(37)); + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".PadLeft(59)); + + Console.WriteLine("I am thinking of a word -- you guess it. I will give you"); + Console.WriteLine("clues to help you get it. Good luck!!"); + } + + /// + /// This allows the user to enter a guess - doing some basic validation + /// on those guesses. + /// + /// The guess entered by the user + private string get_guess() + { + string guess = ""; + + while (guess.Length == 0) + { + Console.WriteLine($"{Environment.NewLine}Guess a five letter word. "); + guess = Console.ReadLine().ToUpper(); + + if ((guess.Length != 5) || (guess.Equals("?")) || (!guess.All(char.IsLetter))) + { + guess = ""; + Console.WriteLine("You must guess a give letter word. Start again."); + } + } + + return guess; + } + + /// + /// This checks the user's guess against the target word - capturing + /// any letters that match up between the two as well as the specific + /// letters that are correct. + /// + /// The user's guess + /// The 'winning' word + /// A string showing which specific letters have already been guessed + /// The integer value showing the number of character matches between guess and target + private int check_guess(string guess, string target, StringBuilder progress) + { + // Go through each letter of the guess and see which + // letters match up to the target word. + // For each position that matches, update the progress + // to reflect the guess + int matches = 0; + string common_letters = ""; + + for (int ctr = 0; ctr < 5; ctr++) + { + // First see if this letter appears anywhere in the target + // and, if so, add it to the common_letters list. + if (target.Contains(guess[ctr])) + { + common_letters.Append(guess[ctr]); + } + // Then see if this specific letter matches the + // same position in the target. And, if so, update + // the progress tracker + if (guess[ctr].Equals(target[ctr])) + { + progress[ctr] = guess[ctr]; + matches++; + } + } + + Console.WriteLine($"There were {matches} matches and the common letters were... {common_letters}"); + Console.WriteLine($"From the exact letter matches, you know......... {progress}"); + return matches; + } + + /// + /// This plays one full game. + /// + private void play_game() + { + string guess_word, target_word; + StringBuilder guess_progress = new StringBuilder("-----"); + Random rand = new Random(); + int count = 0; + + Console.WriteLine("You are starting a new game..."); + + // Randomly select a word from the list of words + target_word = words[rand.Next(words.Length)]; + + // Just run as an infinite loop until one of the + // endgame conditions are met. + while (true) + { + // Ask the user for their guess + guess_word = get_guess(); + count++; + + // If they enter a question mark, then tell them + // the answer and quit the game + if (guess_word.Equals("?")) + { + Console.WriteLine($"The secret word is {target_word}"); + return; + } + + // Otherwise, check the guess against the target - noting progress + if (check_guess(guess_word, target_word, guess_progress) == 0) + { + Console.WriteLine("If you give up, type '?' for your next guess."); + } + + // Once they've guess the word, end the game. + if (guess_progress.Equals(guess_word)) + { + Console.WriteLine($"You have guessed the word. It took {count} guesses!"); + return; + } + } + } + + /// + /// The main entry point for the class - just keeps + /// playing the game until the user decides to quit. + /// + public void play() + { + intro(); + + bool keep_playing = true; + + while (keep_playing) + { + play_game(); + Console.WriteLine($"{Environment.NewLine}Want to play again? "); + keep_playing = Console.ReadLine().StartsWith("y", StringComparison.CurrentCultureIgnoreCase); + } + } + } + + class Program + { + static void Main(string[] args) + { + new Word().play(); + } + } +} diff --git a/96 Word/csharp/word.csproj b/96 Word/csharp/word.csproj new file mode 100644 index 00000000..c73e0d16 --- /dev/null +++ b/96 Word/csharp/word.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/96 Word/csharp/word.sln b/96 Word/csharp/word.sln new file mode 100644 index 00000000..59bdec97 --- /dev/null +++ b/96 Word/csharp/word.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "word", "word.csproj", "{E2CF183B-EBC3-497C-8D34-32EBEE4E2B73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E2CF183B-EBC3-497C-8D34-32EBEE4E2B73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2CF183B-EBC3-497C-8D34-32EBEE4E2B73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2CF183B-EBC3-497C-8D34-32EBEE4E2B73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2CF183B-EBC3-497C-8D34-32EBEE4E2B73}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B4D37881-6972-406B-978F-C1B60BA42638} + EndGlobalSection +EndGlobal diff --git a/96 Word/vbnet/Program.vb b/96 Word/vbnet/Program.vb new file mode 100644 index 00000000..cc807e56 --- /dev/null +++ b/96 Word/vbnet/Program.vb @@ -0,0 +1,145 @@ +Imports System +Imports System.Text +Imports System.Text.RegularExpressions + +Module Word + ' Here's the list of potential words that could be selected + ' as the winning word. + Dim words As String() = {"DINKY", "SMOKE", "WATER", "GRASS", "TRAIN", "MIGHT", "FIRST", + "CANDY", "CHAMP", "WOULD", "CLUMP", "DOPEY"} + + ' + ' Outputs the instructions of the game. + ' + Private Sub intro() + Console.WriteLine("WORD".PadLeft(37)) + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".PadLeft(59)) + + Console.WriteLine("I am thinking of a word -- you guess it. I will give you") + Console.WriteLine("clues to help you get it. Good luck!!") + End Sub + + ' + ' This allows the user to enter a guess - doing some basic validation + ' on those guesses. + ' + ' The guess entered by the user + Private Function get_guess() As String + Dim guess As String = "" + + While (guess.Length = 0) + Console.WriteLine($"{Environment.NewLine}Guess a five letter word. ") + guess = Console.ReadLine().ToUpper() + + If ((guess.Length <> 5) Or guess.Equals("?") Or Not Regex.IsMatch(guess, "^[A-Z]+$")) Then + guess = "" + Console.WriteLine("You must guess a give letter word. Start again.") + End If + End While + + Return guess + End Function + + ' + ' This checks the user's guess against the target word - capturing + ' any letters that match up between the two as well as the specific + ' letters that are correct. + ' + ' The user's guess + ' The 'winning' word + ' A string showing which specific letters have already been guessed + ' The integer value showing the number of character matches between guess and target + Private Function check_guess(guess As String, target As String, progress As StringBuilder) As Integer + ' Go through each letter of the guess And see which + ' letters match up to the target word. + ' For each position that matches, update the progress + ' to reflect the guess + Dim matches As Integer = 0 + Dim common_letters As String = "" + + For ctr As Integer = 0 To 4 + + ' First see if this letter appears anywhere in the target + ' And, if so, add it to the common_letters list. + If (target.Contains(guess(ctr))) Then + common_letters.Append(guess(ctr)) + End If + ' Then see if this specific letter matches the + ' same position in the target. And, if so, update + ' the progress tracker + If (guess(ctr).Equals(target(ctr))) Then + progress(ctr) = guess(ctr) + matches += 1 + End If + Next + + Console.WriteLine($"There were {matches} matches and the common letters were... {common_letters}") + Console.WriteLine($"From the exact letter matches, you know......... {progress}") + Return matches + End Function + + ' + ' This plays one full game. + ' + Private Sub play_game() + Dim guess_word As String, target_word As String + Dim guess_progress As StringBuilder = New StringBuilder("-----") + Dim rand As Random = New Random() + Dim count As Integer = 0 + + Console.WriteLine("You are starting a new game...") + + ' Randomly select a word from the list of words + target_word = words(rand.Next(words.Length)) + + ' Just run as an infinite loop until one of the + ' endgame conditions are met. + While (True) + ' Ask the user for their guess + guess_word = get_guess() + count += 1 + + ' If they enter a question mark, then tell them + ' the answer and quit the game + If (guess_word.Equals("?")) Then + Console.WriteLine($"The secret word is {target_word}") + Return + End If + + ' Otherwise, check the guess against the target - noting progress + If (check_guess(guess_word, target_word, guess_progress) = 0) Then + Console.WriteLine("If you give up, type '?' for your next guess.") + End If + + ' Once they've guess the word, end the game. + If (guess_progress.Equals(guess_word)) Then + Console.WriteLine($"You have guessed the word. It took {count} guesses!") + Return + End If + + End While + End Sub + + ' + ' The main entry point for the class - just keeps + ' playing the game until the user decides to quit. + ' + Public Sub play() + intro() + + Dim keep_playing As Boolean = True + + While (keep_playing) + play_game() + Console.WriteLine($"{Environment.NewLine}Want to play again? ") + keep_playing = Console.ReadLine().StartsWith("y", StringComparison.CurrentCultureIgnoreCase) + End While + + End Sub +End Module + +Module Program + Sub Main(args As String()) + Word.play() + End Sub +End Module diff --git a/96 Word/vbnet/word.sln b/96 Word/vbnet/word.sln new file mode 100644 index 00000000..16584104 --- /dev/null +++ b/96 Word/vbnet/word.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "word", "word.vbproj", "{F0D2422C-983F-4DF3-9D17-D2480839DF07}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F0D2422C-983F-4DF3-9D17-D2480839DF07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0D2422C-983F-4DF3-9D17-D2480839DF07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0D2422C-983F-4DF3-9D17-D2480839DF07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0D2422C-983F-4DF3-9D17-D2480839DF07}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {179D39EB-C497-4336-B795-49CC799929BB} + EndGlobalSection +EndGlobal diff --git a/96 Word/vbnet/word.vbproj b/96 Word/vbnet/word.vbproj new file mode 100644 index 00000000..9868dd3e --- /dev/null +++ b/96 Word/vbnet/word.vbproj @@ -0,0 +1,9 @@ + + + + Exe + word + netcoreapp3.1 + + + From eea78f037c978b951c4d7393d2b26572fba8e6f5 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 15 Jun 2021 17:37:40 -0400 Subject: [PATCH 400/749] Ported Stock Market to C# --- 83 Stock Market/csharp/Game.csproj | 8 + 83 Stock Market/csharp/StockMarket.sln | 25 +++ 83 Stock Market/csharp/src/Assets.cs | 20 +++ 83 Stock Market/csharp/src/Broker.cs | 60 +++++++ 83 Stock Market/csharp/src/Company.cs | 23 +++ 83 Stock Market/csharp/src/Controller.cs | 107 ++++++++++++ .../src/Extensions/EnumerableExtensions.cs | 116 +++++++++++++ .../csharp/src/Extensions/RandomExtensions.cs | 46 +++++ 83 Stock Market/csharp/src/Program.cs | 52 ++++++ 83 Stock Market/csharp/src/StockMarket.cs | 149 +++++++++++++++++ 83 Stock Market/csharp/src/TradingDay.cs | 24 +++ .../csharp/src/TransactionResult.cs | 25 +++ 83 Stock Market/csharp/src/View.cs | 157 ++++++++++++++++++ 13 files changed, 812 insertions(+) create mode 100644 83 Stock Market/csharp/Game.csproj create mode 100644 83 Stock Market/csharp/StockMarket.sln create mode 100644 83 Stock Market/csharp/src/Assets.cs create mode 100644 83 Stock Market/csharp/src/Broker.cs create mode 100644 83 Stock Market/csharp/src/Company.cs create mode 100644 83 Stock Market/csharp/src/Controller.cs create mode 100644 83 Stock Market/csharp/src/Extensions/EnumerableExtensions.cs create mode 100644 83 Stock Market/csharp/src/Extensions/RandomExtensions.cs create mode 100644 83 Stock Market/csharp/src/Program.cs create mode 100644 83 Stock Market/csharp/src/StockMarket.cs create mode 100644 83 Stock Market/csharp/src/TradingDay.cs create mode 100644 83 Stock Market/csharp/src/TransactionResult.cs create mode 100644 83 Stock Market/csharp/src/View.cs diff --git a/83 Stock Market/csharp/Game.csproj b/83 Stock Market/csharp/Game.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/83 Stock Market/csharp/Game.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/83 Stock Market/csharp/StockMarket.sln b/83 Stock Market/csharp/StockMarket.sln new file mode 100644 index 00000000..5bfb67aa --- /dev/null +++ b/83 Stock Market/csharp/StockMarket.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{BADD262D-D540-431F-8803-2A6F80C22033}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BADD262D-D540-431F-8803-2A6F80C22033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BADD262D-D540-431F-8803-2A6F80C22033}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BADD262D-D540-431F-8803-2A6F80C22033}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BADD262D-D540-431F-8803-2A6F80C22033}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C78DBA4A-87E2-4B31-A261-4AEF5E4C3B12} + EndGlobalSection +EndGlobal diff --git a/83 Stock Market/csharp/src/Assets.cs b/83 Stock Market/csharp/src/Assets.cs new file mode 100644 index 00000000..ecb2eafe --- /dev/null +++ b/83 Stock Market/csharp/src/Assets.cs @@ -0,0 +1,20 @@ +using System.Collections.Immutable; + +namespace Game +{ + /// + /// Stores the player's assets. + /// + public record Assets + { + /// + /// Gets the player's amount of cash. + /// + public double Cash { get; init; } + + /// + /// Gets the number of stocks owned of each company. + /// + public ImmutableArray Portfolio { get; init; } + } +} diff --git a/83 Stock Market/csharp/src/Broker.cs b/83 Stock Market/csharp/src/Broker.cs new file mode 100644 index 00000000..dc0abb9e --- /dev/null +++ b/83 Stock Market/csharp/src/Broker.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace Game +{ + /// + /// Contains functions for exchanging assets. + /// + public static class Broker + { + /// + /// Applies the given set of transactions to the given set of assets. + /// + /// + /// The assets to update. + /// + /// + /// The set of stocks to purchase or sell. Positive values indicate + /// purchaes and negative values indicate sales. + /// + /// + /// The collection of companies. + /// + /// + /// Returns the sellers new assets and a code indicating the result + /// of the transaction. + /// + public static (Assets newAssets, TransactionResult result) Apply(Assets assets, IEnumerable transactions, IEnumerable companies) + { + var (netCost, transactionSize) = Enumerable.Zip( + transactions, + companies, + (amount, company) => (amount * company.SharePrice)) + .Aggregate( + (netCost: 0.0, transactionSize: 0.0), + (accumulated, amount) => (accumulated.netCost + amount, accumulated.transactionSize + Math.Abs(amount))); + + var brokerageFee = 0.01 * transactionSize; + + var newAssets = assets with + { + Cash = assets.Cash - netCost - brokerageFee, + Portfolio = ImmutableArray.CreateRange(Enumerable.Zip( + assets.Portfolio, + transactions, + (sharesOwned, delta) => sharesOwned + delta)) + }; + + if (newAssets.Portfolio.Any(amount => amount < 0)) + return (newAssets, TransactionResult.Oversold); + else + if (newAssets.Cash < 0) + return (newAssets, TransactionResult.Overspent); + else + return (newAssets, TransactionResult.Ok); + } + } +} diff --git a/83 Stock Market/csharp/src/Company.cs b/83 Stock Market/csharp/src/Company.cs new file mode 100644 index 00000000..59f40e8d --- /dev/null +++ b/83 Stock Market/csharp/src/Company.cs @@ -0,0 +1,23 @@ +namespace Game +{ + /// + /// Represents a company. + /// + public record Company + { + /// + /// Gets the company's name. + /// + public string Name { get; init; } + + /// + /// Gets the company's three letter stock symbol. + /// + public string StockSymbol { get; init; } + + /// + /// Gets the company's current share price. + /// + public double SharePrice { get; init; } + } +} diff --git a/83 Stock Market/csharp/src/Controller.cs b/83 Stock Market/csharp/src/Controller.cs new file mode 100644 index 00000000..bccfde0c --- /dev/null +++ b/83 Stock Market/csharp/src/Controller.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game +{ + public static class Controller + { + /// + /// Manages the initial interaction with the user. + /// + public static void StartGame() + { + View.ShowBanner(); + + var showInstructions = GetYesOrNo(View.PromptShowInstructions); + View.ShowSeparator(); + if (showInstructions) + View.ShowInstructions(); + + View.ShowSeparator(); + } + + /// + /// Gets a yes or no answer from the user. + /// + /// + /// Displays the prompt. + /// + /// + /// True if the user answered yes and false if he or she answered no. + /// + public static bool GetYesOrNo(Action prompt) + { + prompt(); + + var response = default(char); + do + { + response = Console.ReadKey(intercept: true).KeyChar; + } + while (response != '0' && response != '1'); + + View.ShowChar(response); + return response == '1'; + } + + /// + /// Gets a transaction amount for each company in the given collection + /// of companies and returns the updated assets. + /// + /// + /// The assets to update. + /// + /// + /// The collection of companies. + /// + /// + /// The updated assets. + /// + public static Assets UpdateAssets(Assets assets, IEnumerable companies) + { + while (true) + { + View.PromptEnterTransactions(); + + var result = Broker.Apply ( + assets, + companies.Select(GetTransactionAmount).ToList(), + companies); + + switch (result) + { + case (Assets newAssets, TransactionResult.Ok): + return newAssets; + case (_, TransactionResult.Oversold): + View.ShowOversold(); + break; + case (Assets newAssets, TransactionResult.Overspent): + View.ShowOverspent(-newAssets.Cash); + break; + } + } + } + + /// + /// Gets a transaction amount for the given company. + /// + /// + /// The company to buy or sell. + /// + /// + /// The number of shares to buy or sell. + /// + public static int GetTransactionAmount(Company company) + { + while (true) + { + View.PromptBuySellCompany(company); + if (Int32.TryParse(Console.ReadLine(), out var amount)) + return amount; + else + View.PromptValidInteger(); + } + } + } +} diff --git a/83 Stock Market/csharp/src/Extensions/EnumerableExtensions.cs b/83 Stock Market/csharp/src/Extensions/EnumerableExtensions.cs new file mode 100644 index 00000000..11de50a9 --- /dev/null +++ b/83 Stock Market/csharp/src/Extensions/EnumerableExtensions.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game.Extensions +{ + /// + /// Provides additional methods for the + /// interface. + /// + public static class EnumerableExtensions + { + /// + /// Simultaneously projects each element of a sequence and applies + /// the result of the previous projection. + /// + /// + /// The type of elements in the source sequence. + /// + /// + /// The type of elements in the result sequence. + /// + /// + /// The source sequence. + /// + /// + /// The seed value for the aggregation component. This value is + /// passed to the first call to . + /// + /// + /// The projection function. This function is supplied with a value + /// from the source sequence and the result of the projection on the + /// previous value in the source sequence. + /// + /// + /// The resulting sequence. + /// + public static IEnumerable SelectAndAggregate( + this IEnumerable source, + TResult seed, + Func selector) + { + foreach (var element in source) + { + seed = selector(element, seed); + yield return seed; + } + } + + /// + /// Combines the results of three distinct sequences into a single + /// sequence. + /// + /// + /// The element type of the first sequence. + /// + /// + /// The element type of the second sequence. + /// + /// + /// The element type of the third sequence. + /// + /// + /// The element type of the resulting sequence. + /// + /// + /// The first source sequence. + /// + /// + /// The second source sequence. + /// + /// + /// The third source sequence. + /// + /// + /// Function that combines results from each source sequence into a + /// final result. + /// + /// + /// A sequence of combined values. + /// + /// + /// + /// This function works identically to Enumerable.Zip except that it + /// combines three sequences instead of two. + /// + /// + /// We have defined this as an extension method for consistency with + /// the similar LINQ methods in the class. + /// However, since there is nothing special about the first sequence, + /// it is often more clear to call this as a regular function. For + /// example: + /// + /// + /// EnumerableExtensions.Zip( + /// sequence1, + /// sequence2, + /// sequence3, + /// (a, b, c) => GetResult (a, b, c)); + /// + /// + public static IEnumerable Zip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + Func resultSelector) + { + using var enumerator1 = first.GetEnumerator(); + using var enumerator2 = second.GetEnumerator(); + using var enumerator3 = third.GetEnumerator(); + + while (enumerator1.MoveNext() && enumerator2.MoveNext() && enumerator3.MoveNext()) + yield return resultSelector(enumerator1.Current, enumerator2.Current, enumerator3.Current); + } + } +} diff --git a/83 Stock Market/csharp/src/Extensions/RandomExtensions.cs b/83 Stock Market/csharp/src/Extensions/RandomExtensions.cs new file mode 100644 index 00000000..0c3a4230 --- /dev/null +++ b/83 Stock Market/csharp/src/Extensions/RandomExtensions.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; + +namespace Game.Extensions +{ + /// + /// Provides additional methods for the class. + /// + public static class RandomExtensions + { + /// + /// Generates an infinite sequence of random numbers. + /// + /// + /// The random number generator. + /// + /// + /// The inclusive lower bound of the range to generate. + /// + /// + /// The exclusive upper bound of the range to generate. + /// + /// + /// An infinite sequence of random integers in the range [min, max). + /// + /// + /// + /// We use an exclusive upper bound, even though it's a little + /// confusing, for the sake of consistency with Random.Next. + /// + /// + /// Since the sequence is infinite, a typical usage would be to cap + /// the results with a function like Enumerable.Take. For example, + /// to sum the results of rolling three six sided dice, we could do: + /// + /// + /// random.Integers(1, 7).Take(3).Sum() + /// + /// + public static IEnumerable Integers(this Random random, int min, int max) + { + while (true) + yield return random.Next(min, max); + } + } +} diff --git a/83 Stock Market/csharp/src/Program.cs b/83 Stock Market/csharp/src/Program.cs new file mode 100644 index 00000000..552d8c9a --- /dev/null +++ b/83 Stock Market/csharp/src/Program.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Immutable; +using System.Linq; + +namespace Game +{ + class Program + { + /// + /// Defines the set of companies that will be simulated in the game. + /// + private static ImmutableArray Companies = ImmutableArray.CreateRange(new[] + { + new Company { Name = "INT. BALLISTIC MISSILES", StockSymbol = "IBM", SharePrice = 100 }, + new Company { Name = "RED CROSS OF AMERICA", StockSymbol = "RCA", SharePrice = 85 }, + new Company { Name = "LICHTENSTEIN, BUMRAP & JOKE", StockSymbol = "LBJ", SharePrice = 150 }, + new Company { Name = "AMERICAN BANKRUPT CO.", StockSymbol = "ABC", SharePrice = 140 }, + new Company { Name = "CENSURED BOOKS STORE", StockSymbol = "CBS", SharePrice = 110 } + }); + + static void Main() + { + var assets = new Assets + { + Cash = 10000.0, + Portfolio = ImmutableArray.CreateRange(Enumerable.Repeat(0, Companies.Length)) + }; + + var previousDay = default(TradingDay); + + Controller.StartGame(); + + foreach (var day in StockMarket.Simulate(Companies)) + { + if (previousDay is null) + View.ShowCompanies(day.Companies); + else + View.ShowTradeResults(day, previousDay, assets); + + View.ShowAssets(assets, day.Companies); + + if (previousDay is not null && !Controller.GetYesOrNo(View.PromptContinue)) + break; + + assets = Controller.UpdateAssets(assets, day.Companies); + previousDay = day; + } + + View.ShowFarewell(); + } + } +} diff --git a/83 Stock Market/csharp/src/StockMarket.cs b/83 Stock Market/csharp/src/StockMarket.cs new file mode 100644 index 00000000..ba2f52ee --- /dev/null +++ b/83 Stock Market/csharp/src/StockMarket.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Game.Extensions; + +namespace Game +{ + /// + /// Provides a method for simulating a stock market. + /// + public static class StockMarket + { + /// + /// Simulates changes in the stock market over time. + /// + /// + /// The collection of companies that will participate in the market. + /// + /// + /// An infinite sequence of trading days. Each day represents the + /// state of the stock market at the start of that day. + /// + public static IEnumerable Simulate(ImmutableArray companies) + { + var random = new Random(); + + var cyclicParameters = EnumerableExtensions.Zip( + Trends(random, 1, 5), + PriceSpikes(random, companies.Length, 1, 5), + PriceSpikes(random, companies.Length, 1, 5), + (trend, company1, company2) => (trend, positiveSpike: company1, negativeSpike: company2)); + + return cyclicParameters.SelectAndAggregate( + new TradingDay + { + Companies = companies + }, + (parameters, previousDay) => previousDay with + { + Companies = ImmutableArray.CreateRange( + previousDay.Companies.Select ((company, index) => AdjustSharePrice( + random, + company, + parameters.trend, + parameters.positiveSpike == index, + parameters.negativeSpike == index))) + }); + } + + /// + /// Creates a copy of a company with a randomly adjusted share price, + /// based on the given parameters. + /// + /// + /// The random number generator. + /// + /// + /// The company to adjust. + /// + /// + /// The slope of the overall market price trend. + /// + /// + /// True if the function should simulate a positive spike in the + /// company's share price. + /// + /// + /// True if the function should simulate a negative spike in the + /// company's share price. + /// + /// + /// The adjusted company. + /// + private static Company AdjustSharePrice(Random random, Company company, double trend, bool positiveSpike, bool negativeSpike) + { + var boost = random.Next(4) * 0.25; + + var spikeAmount = 0.0; + + if (positiveSpike) + spikeAmount = 10; + + if (negativeSpike) + spikeAmount = spikeAmount - 10; + + var priceChange = (int)(trend * company.SharePrice) + boost + (int)(3.5 - (6 * random.NextDouble())) + spikeAmount; + + var newPrice = company.SharePrice + priceChange; + if (newPrice < 0) + newPrice = 0; + + return company with { SharePrice = newPrice }; + } + + /// + /// Generates an infinite sequence of market trends. + /// + /// + /// The random number generator. + /// + /// + /// The minimum number of days each trend should last. + /// + /// + /// The maximum number of days each trend should last. + /// + public static IEnumerable Trends(Random random, int minDays, int maxDays) => + random.Integers(minDays, maxDays + 1).SelectMany(days => Enumerable.Repeat(GenerateTrend(random), days)); + + /// + /// Generates a random value for the market trend. + /// + /// + /// The random number generator. + /// + /// + /// A trend value in the range [-0.1, 0.1]. + /// + private static double GenerateTrend(Random random) => + ((int)(random.NextDouble() * 10 + 0.5) / 100.0) * (random.Next(2) == 0 ? 1 : -1) ; + + /// + /// Generates an infinite sequence of price spikes. + /// + /// + /// The random number generator. + /// + /// + /// The number of companies. + /// + /// + /// The minimum number of days in between price spikes. + /// + /// + /// The maximum number of days in between price spikes. + /// + /// + /// An infinite sequence of random company indexes and null values. + /// A non-null value means that the corresponding company should + /// experience a price spike. + /// + private static IEnumerable PriceSpikes(Random random, int companyCount, int minDays, int maxDays) => + random.Integers(minDays, maxDays + 1) + .SelectMany( + days => Enumerable.Range(0, days), + (days, dayNumber) => dayNumber == 0 ? random.Next(companyCount) : default(int?)); + } +} diff --git a/83 Stock Market/csharp/src/TradingDay.cs b/83 Stock Market/csharp/src/TradingDay.cs new file mode 100644 index 00000000..4e9d93f4 --- /dev/null +++ b/83 Stock Market/csharp/src/TradingDay.cs @@ -0,0 +1,24 @@ +using System.Collections.Immutable; +using System.Linq; + +namespace Game +{ + /// + /// Represents a single trading day. + /// + public record TradingDay + { + /// + /// Gets the average share price of all companies in the market this + /// day. + /// + public double AverageSharePrice => + Companies.Average (company => company.SharePrice); + + /// + /// Gets the collection of public listed companies in the stock market + /// this day. + /// + public ImmutableArray Companies { get; init; } + } +} diff --git a/83 Stock Market/csharp/src/TransactionResult.cs b/83 Stock Market/csharp/src/TransactionResult.cs new file mode 100644 index 00000000..23ee8831 --- /dev/null +++ b/83 Stock Market/csharp/src/TransactionResult.cs @@ -0,0 +1,25 @@ +namespace Game +{ + /// + /// Enumerates the different possible outcomes of applying a transaction. + /// + public enum TransactionResult + { + /// + /// The transaction was successful. + /// + Ok, + + /// + /// The transaction failed because the seller tried to sell more shares + /// than he or she owns. + /// + Oversold, + + /// + /// The transaction failed because the net cost was greater than the + /// seller's available cash. + /// + Overspent + } +} diff --git a/83 Stock Market/csharp/src/View.cs b/83 Stock Market/csharp/src/View.cs new file mode 100644 index 00000000..28426b98 --- /dev/null +++ b/83 Stock Market/csharp/src/View.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Game.Extensions; + +namespace Game +{ + /// + /// Contains functions for displaying information to the user. + /// + public static class View + { + public static void ShowBanner() + { + Console.WriteLine(" STOCK MARKET"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowInstructions() + { + Console.WriteLine("THIS PROGRAM PLAYS THE STOCK MARKET. YOU WILL BE GIVEN"); + Console.WriteLine("$10,000 AND MAY BUY OR SELL STOCKS. THE STOCK PRICES WILL"); + Console.WriteLine("BE GENERATED RANDOMLY AND THEREFORE THIS MODEL DOES NOT"); + Console.WriteLine("REPRESENT EXACTLY WHAT HAPPENS ON THE EXCHANGE. A TABLE"); + Console.WriteLine("OF AVAILABLE STOCKS, THEIR PRICES, AND THE NUMBER OF SHARES"); + Console.WriteLine("IN YOUR PORTFOLIO WILL BE PRINTED. FOLLOWING THIS, THE"); + Console.WriteLine("INITIALS OF EACH STOCK WILL BE PRINTED WITH A QUESTION"); + Console.WriteLine("MARK. HERE YOU INDICATE A TRANSACTION. TO BUY A STOCK"); + Console.WriteLine("TYPE +NNN, TO SELL A STOCK TYPE -NNN, WHERE NNN IS THE"); + Console.WriteLine("NUMBER OF SHARES. A BROKERAGE FEE OF 1% WILL BE CHARGED"); + Console.WriteLine("ON ALL TRANSACTIONS. NOTE THAT IF A STOCK'S VALUE DROPS"); + Console.WriteLine("TO ZERO IT MAY REBOUND TO A POSITIVE VALUE AGAIN. YOU"); + Console.WriteLine("HAVE $10,000 TO INVEST. USE INTEGERS FOR ALL YOUR INPUTS."); + Console.WriteLine("(NOTE: TO GET A 'FEEL' FOR THE MARKET RUN FOR AT LEAST"); + Console.WriteLine("10 DAYS)"); + Console.WriteLine("-----GOOD LUCK!-----"); + } + + public static void ShowCompanies(IEnumerable companies) + { + var maxNameLength = companies.Max(company => company.Name.Length); + + Console.WriteLine($"{"STOCK".PadRight(maxNameLength)} INITIALS PRICE/SHARE"); + foreach (var company in companies) + Console.WriteLine($"{company.Name.PadRight(maxNameLength)} {company.StockSymbol} {company.SharePrice:0.00}"); + + Console.WriteLine(); + Console.WriteLine($"NEW YORK STOCK EXCHANGE AVERAGE: {companies.Average(company => company.SharePrice):0.00}"); + Console.WriteLine(); + } + + public static void ShowTradeResults(TradingDay day, TradingDay previousDay, Assets assets) + { + var results = EnumerableExtensions.Zip( + day.Companies, + previousDay.Companies, + assets.Portfolio, + (company, previous, shares) => + ( + stockSymbol: company.StockSymbol, + price: company.SharePrice, + shares, + value: shares * company.SharePrice, + change: company.SharePrice - previous.SharePrice + )).ToList(); + + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("********** END OF DAY'S TRADING **********"); + Console.WriteLine(); + Console.WriteLine(); + + Console.WriteLine("STOCK\tPRICE/SHARE\tHOLDINGS\tVALUE\tNET PRICE CHANGE"); + foreach (var result in results) + Console.WriteLine($"{result.stockSymbol}\t{result.price}\t\t{result.shares}\t\t{result.value:0.00}\t\t{result.change:0.00}"); + + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + + var averagePrice = day.AverageSharePrice; + var averagePriceChange = averagePrice - previousDay.AverageSharePrice; + + Console.WriteLine($"NEW YORK STOCK EXCHANGE AVERAGE: {averagePrice:0.00} NET CHANGE {averagePriceChange:0.00}"); + Console.WriteLine(); + } + + public static void ShowAssets(Assets assets, IEnumerable companies) + { + var totalStockValue = Enumerable.Zip( + assets.Portfolio, + companies, + (shares, company) => shares * company.SharePrice).Sum(); + + Console.WriteLine($"TOTAL STOCK ASSETS ARE ${totalStockValue:0.00}"); + Console.WriteLine($"TOTAL CASH ASSETS ARE ${assets.Cash:0.00}"); + Console.WriteLine($"TOTAL ASSETS ARE ${totalStockValue + assets.Cash:0.00}"); + Console.WriteLine(); + } + + public static void ShowOversold() + { + Console.WriteLine(); + Console.WriteLine("YOU HAVE OVERSOLD A STOCK; TRY AGAIN."); + } + + public static void ShowOverspent(double amount) + { + Console.WriteLine(); + Console.WriteLine($"YOU HAVE USED ${amount:0.00} MORE THAN YOU HAVE."); + } + + public static void ShowFarewell() + { + Console.WriteLine("HOPE YOU HAD FUN!!"); + } + + public static void ShowSeparator() + { + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowChar(char c) + { + Console.WriteLine(c); + } + + public static void PromptShowInstructions() + { + Console.Write("DO YOU WANT THE INSTRUCTIONS (YES-TYPE 1, NO-TYPE 0)? "); + } + + public static void PromptContinue() + { + Console.Write("DO YOU WISH TO CONTINUE (YES-TYPE 1, NO-TYPE 0)? "); + } + + public static void PromptEnterTransactions() + { + Console.WriteLine("WHAT IS YOUR TRANSACTION IN"); + } + + public static void PromptBuySellCompany(Company company) + { + Console.Write($"{company.StockSymbol}? "); + } + + public static void PromptValidInteger() + { + Console.WriteLine("PLEASE ENTER A VALID INTEGER"); + } + } +} From e29af4e3f945ad5bb338cb55ce09fc780577bebd Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sat, 19 Jun 2021 14:37:33 +0400 Subject: [PATCH 401/749] Ported 03 Animal to Java --- 03 Animal/java/Animal.java | 160 +++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 03 Animal/java/Animal.java diff --git a/03 Animal/java/Animal.java b/03 Animal/java/Animal.java new file mode 100644 index 00000000..11e9e889 --- /dev/null +++ b/03 Animal/java/Animal.java @@ -0,0 +1,160 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Scanner; + +/** + * ANIMAL + *

+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + */ +public class Animal { + + public static void main(String[] args) { + printIntro(); + Scanner scan = new Scanner(System.in); + + List questions = new ArrayList<>(); + questions.add(new Question("DOES IT SWIM", "FISH", "BIRD")); + + boolean stopGame = false; + while (!stopGame) { + String choice = readMainChoice(scan); + switch (choice) { + case "LIST": + printKnownAnimals(questions); + break; + case "Q": + case "QUIT": + stopGame = true; + break; + default: + if (choice.toUpperCase(Locale.ROOT).startsWith("Y")) { + int k = 0; + boolean correctGuess = false; + while (questions.size() > k && !correctGuess) { + Question question = questions.get(k); + correctGuess = askQuestion(question, scan); + if (correctGuess) { + System.out.println("WHY NOT TRY ANOTHER ANIMAL?"); + } else { + k++; + } + } + + if (!correctGuess) { + askForInformationAndSave(scan, questions); + } + } + } + } + + } + + private static void askForInformationAndSave(Scanner scan, List questions) { + //Failed to get it right and ran out of questions + //Let's ask the user for the new information + System.out.print("THE ANIMAL YOU WERE THINKING OF WAS A "); + String animal = scan.nextLine(); + System.out.printf("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A %s FROM A %s ", animal, questions.get( + questions.size() - 1).falseAnswer); + String newQuestion = scan.nextLine(); + System.out.printf("FOR A %s THE ANSWER WOULD BE ", animal); + boolean newAnswer = readYesOrNo(scan); + //Add it to our list + addNewAnimal(questions, animal, newQuestion, newAnswer); + } + + private static void addNewAnimal(List questions, String animal, String newQuestion, boolean newAnswer) { + Question lastQuestion = questions.get(questions.size() - 1); + String lastAnimal = lastQuestion.falseAnswer; + lastQuestion.falseAnswer = null; //remove the false option to indicate that there is a next question + + Question newOption; + if (newAnswer) { + newOption = new Question(newQuestion, animal, lastAnimal); + } else { + newOption = new Question(newQuestion, lastAnimal, animal); + } + questions.add(newOption); + } + + private static boolean askQuestion(Question question, Scanner scanner) { + System.out.printf("%s ? ", question.question); + + boolean chosenAnswer = readYesOrNo(scanner); + if (chosenAnswer) { + if (question.trueAnswer != null) { + System.out.printf("IS IT A %s ? ", question.trueAnswer); + return readYesOrNo(scanner); + } + //else go to the next question + } else { + if (question.falseAnswer != null) { + System.out.printf("IS IT A %s ? ", question.falseAnswer); + return readYesOrNo(scanner); + } + //else go to the next question + } + return false; + } + + private static boolean readYesOrNo(Scanner scanner) { + boolean validAnswer = false; + Boolean choseAnswer = null; + while (!validAnswer) { + String answer = scanner.nextLine(); + if (answer.toUpperCase(Locale.ROOT).startsWith("Y")) { + validAnswer = true; + choseAnswer = true; + } else if (answer.toUpperCase(Locale.ROOT).startsWith("N")) { + validAnswer = true; + choseAnswer = false; + } + } + return choseAnswer; + } + + private static void printKnownAnimals(List questions) { + System.out.println("\nANIMALS I ALREADY KNOW ARE:"); + List animals = new ArrayList<>(); + questions.forEach(q -> { + if (q.trueAnswer != null) { + animals.add(q.trueAnswer); + } + if (q.falseAnswer != null) { + animals.add(q.falseAnswer); + } + }); + System.out.println(String.join("\t\t", animals)); + } + + private static String readMainChoice(Scanner scan) { + System.out.print("ARE YOU THINKING OF AN ANIMAL ? "); + return scan.nextLine(); + } + + private static void printIntro() { + System.out.println(" ANIMAL"); + System.out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println("\n\n"); + System.out.println("PLAY 'GUESS THE ANIMAL'"); + System.out.println("\n"); + System.out.println("THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT."); + } + + + public static class Question { + String question; + String trueAnswer; + String falseAnswer; + + public Question(String question, String trueAnswer, String falseAnswer) { + this.question = question; + this.trueAnswer = trueAnswer; + this.falseAnswer = falseAnswer; + } + } + +} + From dc2375e4af3101e8ad473b4a75b037c65a51ec75 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 19 Jun 2021 13:27:38 -0400 Subject: [PATCH 402/749] Ported Combat to C# --- 28 Combat/csharp/Combat.sln | 25 ++++ 28 Combat/csharp/Game.csproj | 6 + 28 Combat/csharp/README.md | 4 + 28 Combat/csharp/src/ArmedForces.cs | 42 ++++++ 28 Combat/csharp/src/Ceasefire.cs | 60 ++++++++ 28 Combat/csharp/src/Controller.cs | 102 +++++++++++++ 28 Combat/csharp/src/FinalCampaign.cs | 121 +++++++++++++++ 28 Combat/csharp/src/InitialCampaign.cs | 187 ++++++++++++++++++++++++ 28 Combat/csharp/src/MilitaryBranch.cs | 12 ++ 28 Combat/csharp/src/Program.cs | 31 ++++ 28 Combat/csharp/src/View.cs | 110 ++++++++++++++ 28 Combat/csharp/src/WarResult.cs | 14 ++ 28 Combat/csharp/src/WarState.cs | 101 +++++++++++++ 13 files changed, 815 insertions(+) create mode 100644 28 Combat/csharp/Combat.sln create mode 100644 28 Combat/csharp/Game.csproj create mode 100644 28 Combat/csharp/src/ArmedForces.cs create mode 100644 28 Combat/csharp/src/Ceasefire.cs create mode 100644 28 Combat/csharp/src/Controller.cs create mode 100644 28 Combat/csharp/src/FinalCampaign.cs create mode 100644 28 Combat/csharp/src/InitialCampaign.cs create mode 100644 28 Combat/csharp/src/MilitaryBranch.cs create mode 100644 28 Combat/csharp/src/Program.cs create mode 100644 28 Combat/csharp/src/View.cs create mode 100644 28 Combat/csharp/src/WarResult.cs create mode 100644 28 Combat/csharp/src/WarState.cs diff --git a/28 Combat/csharp/Combat.sln b/28 Combat/csharp/Combat.sln new file mode 100644 index 00000000..522b680e --- /dev/null +++ b/28 Combat/csharp/Combat.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{054A1718-1B7D-4954-81A7-EEA390713439}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {054A1718-1B7D-4954-81A7-EEA390713439}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {054A1718-1B7D-4954-81A7-EEA390713439}.Debug|Any CPU.Build.0 = Debug|Any CPU + {054A1718-1B7D-4954-81A7-EEA390713439}.Release|Any CPU.ActiveCfg = Release|Any CPU + {054A1718-1B7D-4954-81A7-EEA390713439}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1EBA7488-1DA6-4B0B-8234-F10A65E96BDB} + EndGlobalSection +EndGlobal diff --git a/28 Combat/csharp/Game.csproj b/28 Combat/csharp/Game.csproj new file mode 100644 index 00000000..dbc7a12e --- /dev/null +++ b/28 Combat/csharp/Game.csproj @@ -0,0 +1,6 @@ + + + Exe + net5.0 + + diff --git a/28 Combat/csharp/README.md b/28 Combat/csharp/README.md index 4daabb5c..7634ed9c 100644 --- a/28 Combat/csharp/README.md +++ b/28 Combat/csharp/README.md @@ -1,3 +1,7 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/) + +The original BASIC code has a surprising number of bugs for such a small program. +For the sake of preserving the original behaviour, I've left them in place and +commented the ones I noticed. diff --git a/28 Combat/csharp/src/ArmedForces.cs b/28 Combat/csharp/src/ArmedForces.cs new file mode 100644 index 00000000..f246a179 --- /dev/null +++ b/28 Combat/csharp/src/ArmedForces.cs @@ -0,0 +1,42 @@ +using System; + +namespace Game +{ + ///

+ /// Represents the armed forces for a country. + /// + public record ArmedForces + { + /// + /// Gets the number of men and women in the army. + /// + public int Army { get; init; } + + /// + /// Gets the number of men and women in the navy. + /// + public int Navy { get; init; } + + /// + /// Gets the number of men and women in the air force. + /// + public int AirForce { get; init; } + + /// + /// Gets the total number of troops in the armed forces. + /// + public int TotalTroops => Army + Navy + AirForce; + + /// + /// Gets the number of men and women in the given branch. + /// + public int this[MilitaryBranch branch] => + branch switch + { + MilitaryBranch.Army => Army, + MilitaryBranch.Navy => Navy, + MilitaryBranch.AirForce => AirForce, + _ => throw new ArgumentException("INVALID BRANCH") + }; + } +} diff --git a/28 Combat/csharp/src/Ceasefire.cs b/28 Combat/csharp/src/Ceasefire.cs new file mode 100644 index 00000000..3b1a7d65 --- /dev/null +++ b/28 Combat/csharp/src/Ceasefire.cs @@ -0,0 +1,60 @@ +using System; + +namespace Game +{ + /// + /// Represents the state of the game after reaching a ceasefire. + /// + public sealed class Ceasefire : WarState + { + /// + /// Gets a flag indicating whether the player achieved absolute victory. + /// + public override bool IsAbsoluteVictory { get; } + + /// + /// Gets the outcome of the war. + /// + public override WarResult? FinalOutcome + { + get + { + if (IsAbsoluteVictory || PlayerForces.TotalTroops > 3 / 2 * ComputerForces.TotalTroops) + return WarResult.PlayerVictory; + else + if (PlayerForces.TotalTroops < 2 / 3 * ComputerForces.TotalTroops) + return WarResult.ComputerVictory; + else + return WarResult.PeaceTreaty; + } + } + + /// + /// Initializes a new instance of the Ceasefire class. + /// + /// + /// The computer's forces. + /// + /// + /// The player's forces. + /// + /// + /// Indicates whether the player acheived absolute victory (defeating + /// the computer without destroying its military). + /// + public Ceasefire(ArmedForces computerForces, ArmedForces playerForces, bool absoluteVictory = false) + : base(computerForces, playerForces) + { + IsAbsoluteVictory = absoluteVictory; + } + + protected override (WarState nextState, string message) AttackWithArmy(int attackSize) => + throw new InvalidOperationException("THE WAR IS OVER"); + + protected override (WarState nextState, string message) AttackWithNavy(int attackSize) => + throw new InvalidOperationException("THE WAR IS OVER"); + + protected override (WarState nextState, string message) AttackWithAirForce(int attackSize) => + throw new InvalidOperationException("THE WAR IS OVER"); + } +} diff --git a/28 Combat/csharp/src/Controller.cs b/28 Combat/csharp/src/Controller.cs new file mode 100644 index 00000000..b02f81ad --- /dev/null +++ b/28 Combat/csharp/src/Controller.cs @@ -0,0 +1,102 @@ +using System; + +namespace Game +{ + /// + /// Contains functions for interacting with the user. + /// + public class Controller + { + /// + /// Gets the player's initial armed forces distribution. + /// + /// + /// The computer's initial armed forces. + /// + public static ArmedForces GetInitialForces(ArmedForces computerForces) + { + var playerForces = default(ArmedForces); + + // BUG: This loop allows the player to assign negative values to + // some branches, leading to strange results. + do + { + View.ShowDistributeForces(); + + View.PromptArmySize(computerForces.Army); + var army = InputInteger(); + + View.PromptNavySize(computerForces.Navy); + var navy = InputInteger(); + + View.PromptAirForceSize(computerForces.AirForce); + var airForce = InputInteger(); + + playerForces = new ArmedForces + { + Army = army, + Navy = navy, + AirForce = airForce + }; + } + while (playerForces.TotalTroops > computerForces.TotalTroops); + + return playerForces; + } + + /// + /// Gets the military branch for the user's next attack. + /// + public static MilitaryBranch GetAttackBranch(WarState state, bool isFirstTurn) + { + if (isFirstTurn) + View.PromptFirstAttackBranch(); + else + View.PromptNextAttackBranch(state.ComputerForces, state.PlayerForces); + + // If the user entered an invalid branch number in the original + // game, the code fell through to the army case. We'll preserve + // that behaviour here. + return Console.ReadLine() switch + { + "2" => MilitaryBranch.Navy, + "3" => MilitaryBranch.AirForce, + _ => MilitaryBranch.Army + }; + } + + /// + /// Gets a valid attack size from the player for the given branch + /// of the armed forces. + /// + /// + /// The number of troops available. + /// + public static int GetAttackSize(int troopsAvailable) + { + var attackSize = 0; + + do + { + View.PromptAttackSize(); + attackSize = InputInteger(); + } + while (attackSize < 0 || attackSize > troopsAvailable); + + return attackSize; + } + + /// + /// Gets an integer value from the user. + /// + public static int InputInteger() + { + var value = default(int); + + while (!Int32.TryParse(Console.ReadLine(), out value)) + View.PromptValidInteger(); + + return value; + } + } +} diff --git a/28 Combat/csharp/src/FinalCampaign.cs b/28 Combat/csharp/src/FinalCampaign.cs new file mode 100644 index 00000000..f34d80e3 --- /dev/null +++ b/28 Combat/csharp/src/FinalCampaign.cs @@ -0,0 +1,121 @@ +namespace Game +{ + /// + /// Represents the state of the game during the final campaign of the war. + /// + public sealed class FinalCampaign : WarState + { + /// + /// Initializes a new instance of the FinalCampaign class. + /// + /// + /// The computer's forces. + /// + /// + /// The player's forces. + /// + public FinalCampaign(ArmedForces computerForces, ArmedForces playerForces) + : base(computerForces, playerForces) + { + } + + protected override (WarState nextState, string message) AttackWithArmy(int attackSize) + { + if (attackSize < ComputerForces.Army / 2) + { + return + ( + new Ceasefire( + ComputerForces, + PlayerForces with + { + Army = PlayerForces.Army - attackSize + }), + "I WIPED OUT YOUR ATTACK!" + ); + } + else + { + return + ( + new Ceasefire( + ComputerForces with + { + Army = 0 + }, + PlayerForces), + "YOU DESTROYED MY ARMY!" + ); + } + } + + protected override (WarState nextState, string message) AttackWithNavy(int attackSize) + { + if (attackSize < ComputerForces.Navy / 2) + { + return + ( + new Ceasefire( + ComputerForces, + PlayerForces with + { + Army = PlayerForces.Army / 4, + Navy = PlayerForces.Navy / 2 + }), + "I SUNK TWO OF YOUR BATTLESHIPS, AND MY AIR FORCE\n" + + "WIPED OUT YOUR UNGAURDED CAPITOL." + ); + } + else + { + return + ( + new Ceasefire( + ComputerForces with + { + AirForce = 2 * ComputerForces.AirForce / 3, + Navy = ComputerForces.Navy / 2 + }, + PlayerForces), + "YOUR NAVY SHOT DOWN THREE OF MY XIII PLANES,\n" + + "AND SUNK THREE BATTLESHIPS." + ); + } + } + + protected override (WarState nextState, string message) AttackWithAirForce(int attackSize) + { + // BUG? Usually, larger attacks lead to better outcomes. + // It seems odd that the logic is suddenly reversed here, + // but this could be intentional. + if (attackSize > ComputerForces.AirForce / 2) + { + return + ( + new Ceasefire( + ComputerForces, + PlayerForces with + { + Army = PlayerForces.Army / 3, + Navy = PlayerForces.Navy / 3, + AirForce = PlayerForces.AirForce / 3 + }), + "MY NAVY AND AIR FORCE IN A COMBINED ATTACK LEFT\n" + + "YOUR COUNTRY IN SHAMBLES." + ); + } + else + { + return + ( + new Ceasefire( + ComputerForces, + PlayerForces, + absoluteVictory: true), + "ONE OF YOUR PLANES CRASHED INTO MY HOUSE. I AM DEAD.\n" + + "MY COUNTRY FELL APART." + ); + } + } + } +} diff --git a/28 Combat/csharp/src/InitialCampaign.cs b/28 Combat/csharp/src/InitialCampaign.cs new file mode 100644 index 00000000..25430074 --- /dev/null +++ b/28 Combat/csharp/src/InitialCampaign.cs @@ -0,0 +1,187 @@ +namespace Game +{ + /// + /// Represents the state of the game during the initial campaign of the war. + /// + public sealed class InitialCampaign : WarState + { + /// + /// Initializes a new instance of the InitialCampaign class. + /// + /// + /// The computer's forces. + /// + /// + /// The player's forces. + /// + public InitialCampaign(ArmedForces computerForces, ArmedForces playerForces) + : base(computerForces, playerForces) + { + } + + protected override (WarState nextState, string message) AttackWithArmy(int attackSize) + { + // BUG: Why are we comparing attack size to the size of our own + // military? This leads to some truly absurd results if our + // army is tiny. + if (attackSize < PlayerForces.Army / 3) + { + return + ( + new FinalCampaign( + ComputerForces, + PlayerForces with + { + Army = PlayerForces.Army - attackSize + }), + $"YOU LOST {attackSize} MEN FROM YOUR ARMY." + ); + } + else + if (attackSize < 2 * PlayerForces.Army / 3) + { + return + ( + new FinalCampaign( + ComputerForces with + { + // BUG: Clearly not what we claim below... + Army = 0 + }, + PlayerForces with + { + Army = PlayerForces.Army - attackSize / 3 + }), + $"YOU LOST {attackSize / 3} MEN, BUT I LOST {2 * ComputerForces.Army / 3}" + ); + } + else + { + // BUG? This is identical to the third outcome when attacking + // with the navy. It seems unlikely that this was the + // intent. Probably line 115 in the original source was + // supposed to say "GOTO 170" instead of "GOTO 270". + // (Line 170 is conspicuously absent.) + return + ( + new FinalCampaign( + ComputerForces with + { + Navy = 2 * ComputerForces.Navy / 3 + }, + PlayerForces with + { + Army = PlayerForces.Army / 3, + AirForce = PlayerForces.AirForce / 3 + }), + "YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO\n" + + "OF YOUR AIR FORCE BASES AND 3 ARMY BASES." + ); + } + } + + protected override (WarState nextState, string message) AttackWithNavy(int attackSize) + { + if (attackSize < ComputerForces.Navy / 3) + { + return + ( + new FinalCampaign( + ComputerForces, + PlayerForces with + { + Navy = PlayerForces.Navy - attackSize + }), + "YOUR ATTACK WAS STOPPED!" + ); + } + else + if (attackSize < 2 * ComputerForces.Navy / 3) + { + return + ( + new FinalCampaign( + ComputerForces with + { + Navy = ComputerForces.Navy / 3 + }, + PlayerForces), + $"YOU DESTROYED {2 * ComputerForces.Navy / 3} OF MY ARMY." + ); + } + else + { + return + ( + new FinalCampaign( + ComputerForces with + { + Navy = 2 * ComputerForces.Navy / 3 + }, + PlayerForces with + { + Army = PlayerForces.Army / 3, + AirForce = PlayerForces.AirForce / 3 + }), + "YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO\n" + + "OF YOUR AIR FORCE BASES AND 3 ARMY BASES." + ); + } + } + + protected override (WarState nextState, string message) AttackWithAirForce(int attackSize) + { + // BUG: Why are we comparing the attack size to the size of + // our own air force? Surely we meant to compare to the + // computer's air force. + if (attackSize < PlayerForces.AirForce / 3) + { + return + ( + new FinalCampaign( + ComputerForces, + PlayerForces with + { + AirForce = PlayerForces.AirForce - attackSize + }), + "YOUR ATTACK WAS WIPED OUT." + ); + } + else + if (attackSize < 2 * PlayerForces.AirForce / 3) + { + return + ( + new FinalCampaign( + ComputerForces with + { + Army = 2 * ComputerForces.Army / 3, + Navy = ComputerForces.Navy / 3, + AirForce = ComputerForces.AirForce / 3 + }, + PlayerForces), + "WE HAD A DOGFIGHT. YOU WON - AND FINISHED YOUR MISSION." + ); + } + else + { + + return + ( + new FinalCampaign( + ComputerForces with + { + Army = 2 * ComputerForces.Army / 3 + }, + PlayerForces with + { + Army = PlayerForces.Army / 4, + Navy = PlayerForces.Navy / 3 + }), + "YOU WIPED OUT ONE OF MY ARMY PATROLS, BUT I DESTROYED" + + "TWO NAVY BASES AND BOMBED THREE ARMY BASES." + ); + } + } + } +} diff --git a/28 Combat/csharp/src/MilitaryBranch.cs b/28 Combat/csharp/src/MilitaryBranch.cs new file mode 100644 index 00000000..50f53c5e --- /dev/null +++ b/28 Combat/csharp/src/MilitaryBranch.cs @@ -0,0 +1,12 @@ +namespace Game +{ + /// + /// Enumerates the different branches of the military. + /// + public enum MilitaryBranch + { + Army, + Navy, + AirForce + } +} diff --git a/28 Combat/csharp/src/Program.cs b/28 Combat/csharp/src/Program.cs new file mode 100644 index 00000000..1695867d --- /dev/null +++ b/28 Combat/csharp/src/Program.cs @@ -0,0 +1,31 @@ +namespace Game +{ + class Program + { + static void Main() + { + View.ShowBanner(); + View.ShowInstructions(); + + var computerForces = new ArmedForces { Army = 30000, Navy = 20000, AirForce = 22000 }; + var playerForces = Controller.GetInitialForces(computerForces); + + var state = (WarState) new InitialCampaign(computerForces, playerForces); + var isFirstTurn = true; + + while (!state.FinalOutcome.HasValue) + { + var branch = Controller.GetAttackBranch(state, isFirstTurn); + var attackSize = Controller.GetAttackSize(state.PlayerForces[branch]); + + var (nextState, message) = state.LaunchAttack(branch, attackSize); + View.ShowMessage(message); + + state = nextState; + isFirstTurn = false; + } + + View.ShowResult(state); + } + } +} diff --git a/28 Combat/csharp/src/View.cs b/28 Combat/csharp/src/View.cs new file mode 100644 index 00000000..199194fd --- /dev/null +++ b/28 Combat/csharp/src/View.cs @@ -0,0 +1,110 @@ +using System; + +namespace Game +{ + /// + /// Contains functions for displaying information to the user. + /// + public static class View + { + public static void ShowBanner() + { + Console.WriteLine(" COMBAT"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + } + + public static void ShowInstructions() + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("I AM AT WAR WITH YOU."); + Console.WriteLine("WE HAVE 72000 SOLDIERS APIECE."); + } + + public static void ShowDistributeForces() + { + Console.WriteLine(); + Console.WriteLine("DISTRIBUTE YOUR FORCES."); + Console.WriteLine("\tME\t YOU"); + } + + public static void ShowMessage(string message) + { + Console.WriteLine(message); + } + + public static void ShowResult(WarState finalState) + { + if (!finalState.IsAbsoluteVictory) + { + Console.WriteLine(); + Console.WriteLine("FROM THE RESULTS OF BOTH OF YOUR ATTACKS,"); + } + + switch (finalState.FinalOutcome) + { + case WarResult.ComputerVictory: + Console.WriteLine("YOU LOST-I CONQUERED YOUR COUNTRY. IT SERVES YOU"); + Console.WriteLine("RIGHT FOR PLAYING THIS STUPID GAME!!!"); + break; + case WarResult.PlayerVictory: + Console.WriteLine("YOU WON, OH! SHUCKS!!!!"); + break; + case WarResult.PeaceTreaty: + Console.WriteLine("THE TREATY OF PARIS CONCLUDED THAT WE TAKE OUR"); + Console.WriteLine("RESPECTIVE COUNTRIES AND LIVE IN PEACE."); + break; + } + } + + public static void PromptArmySize(int computerArmySize) + { + Console.Write($"ARMY\t{computerArmySize}\t? "); + } + + public static void PromptNavySize(int computerNavySize) + { + Console.Write($"NAVY\t{computerNavySize}\t? "); + } + + public static void PromptAirForceSize(int computerAirForceSize) + { + Console.Write($"A. F.\t{computerAirForceSize}\t? "); + } + + public static void PromptFirstAttackBranch() + { + Console.WriteLine("YOU ATTACK FIRST. TYPE (1) FOR ARMY; (2) FOR NAVY;"); + Console.WriteLine("AND (3) FOR AIR FORCE."); + Console.Write("? "); + } + + public static void PromptNextAttackBranch(ArmedForces computerForces, ArmedForces playerForces) + { + // BUG: More of a nit-pick really, but the order of columns in the + // table is reversed from what we showed when distributing troops. + // The tables should be consistent. + Console.WriteLine(); + Console.WriteLine("\tYOU\tME"); + Console.WriteLine($"ARMY\t{playerForces.Army}\t{computerForces.Army}"); + Console.WriteLine($"NAVY\t{playerForces.Navy}\t{computerForces.Navy}"); + Console.WriteLine($"A. F.\t{playerForces.AirForce}\t{computerForces.AirForce}"); + + Console.WriteLine("WHAT IS YOUR NEXT MOVE?"); + Console.WriteLine("ARMY=1 NAVY=2 AIR FORCE=3"); + Console.Write("? "); + } + + public static void PromptAttackSize() + { + Console.WriteLine("HOW MANY MEN"); + Console.Write("? "); + } + + public static void PromptValidInteger() + { + Console.WriteLine("ENTER A VALID INTEGER VALUE"); + } + } +} diff --git a/28 Combat/csharp/src/WarResult.cs b/28 Combat/csharp/src/WarResult.cs new file mode 100644 index 00000000..a491fe4b --- /dev/null +++ b/28 Combat/csharp/src/WarResult.cs @@ -0,0 +1,14 @@ +namespace Game +{ + /// + /// Enumerates the possible outcomes of the war. + /// + public enum WarResult + { + ComputerVictory, + + PlayerVictory, + + PeaceTreaty + } +} diff --git a/28 Combat/csharp/src/WarState.cs b/28 Combat/csharp/src/WarState.cs new file mode 100644 index 00000000..1bc5f6cd --- /dev/null +++ b/28 Combat/csharp/src/WarState.cs @@ -0,0 +1,101 @@ +using System; + +namespace Game +{ + /// + /// Represents the current state of the war. + /// + public abstract class WarState + { + /// + /// Gets the computer's armed forces. + /// + public ArmedForces ComputerForces { get; } + + /// + /// Gets the player's armed forces. + /// + public ArmedForces PlayerForces { get; } + + /// + /// Gets a flag indicating whether this state represents absolute + /// victory for the player. + /// + public virtual bool IsAbsoluteVictory => false; + + /// + /// Gets the final outcome of the war. + /// + /// + /// If the war is ongoing, this property will be null. + /// + public virtual WarResult? FinalOutcome => null; + + /// + /// Initializes a new instance of the state class. + /// + /// + /// The computer's forces. + /// + /// + /// The player's forces. + /// + public WarState(ArmedForces computerForces, ArmedForces playerForces) => + (ComputerForces, PlayerForces) = (computerForces, playerForces); + + /// + /// Launches an attack. + /// + /// + /// The branch of the military to use for the attack. + /// + /// + /// The number of men and women to use for the attack. + /// + /// + /// The new state of the game resulting from the attack and a message + /// describing the result. + /// + public (WarState nextState, string message) LaunchAttack(MilitaryBranch branch, int attackSize) => + branch switch + { + MilitaryBranch.Army => AttackWithArmy(attackSize), + MilitaryBranch.Navy => AttackWithNavy(attackSize), + MilitaryBranch.AirForce => AttackWithAirForce(attackSize), + _ => throw new ArgumentException("INVALID BRANCH") + }; + + /// + /// Conducts an attack with the player's army. + /// + /// + /// The number of men and women used in the attack. + /// + /// + /// The new game state and a message describing the result. + /// + protected abstract (WarState nextState, string message) AttackWithArmy(int attackSize); + + /// + /// Conducts an attack with the player's navy. + /// + /// + /// The number of men and women used in the attack. + /// + /// + /// The new game state and a message describing the result. + /// + protected abstract (WarState nextState, string message) AttackWithNavy(int attackSize); + + /// + /// Conducts an attack with the player's air force. + /// + /// + /// The number of men and women used in the attack. + /// + /// + /// The new game state and a message describing the result. + /// + protected abstract (WarState nextState, string message) AttackWithAirForce(int attackSize); + } +} From dcd11bc9075ba54d50ac6a1e2a5a44de16e844b4 Mon Sep 17 00:00:00 2001 From: Greg Kennedy Date: Mon, 5 Jul 2021 01:10:27 -0500 Subject: [PATCH 403/749] Cleanup repository. Make all Perl scripts executable. --- .gitignore | 2 ++ 01 Acey Ducey/perl/aceyducey.pl | 0 18 Bullseye/perl/bullseye.pl | 0 19 Bunny/perl/bunny.pl | 0 20 Buzzword/perl/buzzword.pl | 0 24 Chemist/perlchemist.pl | 0 31 Depth Charge/perl/depth-charge.pl | 0 32 Diamond/perl/diamond.pl | 0 33 Dice/perl/dice.pl | 0 41 Guess/perl/guess.pl | 0 47 Hi-Lo/perl/hi-lo.pl | 0 52 Kinema/perl/kinema.pl | 0 54 Letter/perl/letter.pl | 0 57 Literature Quiz/perl/litquiz.pl | 0 58 Love/perl/love.pl | 0 63 Name/perl/name.pl | 0 64 Nicomachus/perl/nicomachus.pl | 0 66 Number/perl/number.pl | 0 70 Poetry/perl/poetry.pl | 0 70 Poetry/poetry.pl | 0 74 Rock Scissors Paper/perl/rockscissors.pl | 0 76 Russian Roulette/perl/russianroulette.pl | 0 78 Sine Wave/perl/sinewave.pl | 0 87 3-D Plot/perl/3dplot.pl | 0 91 Train/perl/train.pl | 0 92 Trap/perl/trap.pl | 0 README.md | 2 +- 27 files changed, 3 insertions(+), 1 deletion(-) mode change 100644 => 100755 01 Acey Ducey/perl/aceyducey.pl mode change 100644 => 100755 18 Bullseye/perl/bullseye.pl mode change 100644 => 100755 19 Bunny/perl/bunny.pl mode change 100644 => 100755 20 Buzzword/perl/buzzword.pl mode change 100644 => 100755 24 Chemist/perlchemist.pl mode change 100644 => 100755 31 Depth Charge/perl/depth-charge.pl mode change 100644 => 100755 32 Diamond/perl/diamond.pl mode change 100644 => 100755 33 Dice/perl/dice.pl mode change 100644 => 100755 41 Guess/perl/guess.pl mode change 100644 => 100755 47 Hi-Lo/perl/hi-lo.pl mode change 100644 => 100755 52 Kinema/perl/kinema.pl mode change 100644 => 100755 54 Letter/perl/letter.pl mode change 100644 => 100755 57 Literature Quiz/perl/litquiz.pl mode change 100644 => 100755 58 Love/perl/love.pl mode change 100644 => 100755 63 Name/perl/name.pl mode change 100644 => 100755 64 Nicomachus/perl/nicomachus.pl mode change 100644 => 100755 66 Number/perl/number.pl mode change 100644 => 100755 70 Poetry/perl/poetry.pl mode change 100644 => 100755 70 Poetry/poetry.pl mode change 100644 => 100755 74 Rock Scissors Paper/perl/rockscissors.pl mode change 100644 => 100755 76 Russian Roulette/perl/russianroulette.pl mode change 100644 => 100755 78 Sine Wave/perl/sinewave.pl mode change 100644 => 100755 87 3-D Plot/perl/3dplot.pl mode change 100644 => 100755 91 Train/perl/train.pl mode change 100644 => 100755 92 Trap/perl/trap.pl diff --git a/.gitignore b/.gitignore index 78bed0e0..4707e8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ out/ *.py[co] Pipfile + +.DS_Store diff --git a/01 Acey Ducey/perl/aceyducey.pl b/01 Acey Ducey/perl/aceyducey.pl old mode 100644 new mode 100755 diff --git a/18 Bullseye/perl/bullseye.pl b/18 Bullseye/perl/bullseye.pl old mode 100644 new mode 100755 diff --git a/19 Bunny/perl/bunny.pl b/19 Bunny/perl/bunny.pl old mode 100644 new mode 100755 diff --git a/20 Buzzword/perl/buzzword.pl b/20 Buzzword/perl/buzzword.pl old mode 100644 new mode 100755 diff --git a/24 Chemist/perlchemist.pl b/24 Chemist/perlchemist.pl old mode 100644 new mode 100755 diff --git a/31 Depth Charge/perl/depth-charge.pl b/31 Depth Charge/perl/depth-charge.pl old mode 100644 new mode 100755 diff --git a/32 Diamond/perl/diamond.pl b/32 Diamond/perl/diamond.pl old mode 100644 new mode 100755 diff --git a/33 Dice/perl/dice.pl b/33 Dice/perl/dice.pl old mode 100644 new mode 100755 diff --git a/41 Guess/perl/guess.pl b/41 Guess/perl/guess.pl old mode 100644 new mode 100755 diff --git a/47 Hi-Lo/perl/hi-lo.pl b/47 Hi-Lo/perl/hi-lo.pl old mode 100644 new mode 100755 diff --git a/52 Kinema/perl/kinema.pl b/52 Kinema/perl/kinema.pl old mode 100644 new mode 100755 diff --git a/54 Letter/perl/letter.pl b/54 Letter/perl/letter.pl old mode 100644 new mode 100755 diff --git a/57 Literature Quiz/perl/litquiz.pl b/57 Literature Quiz/perl/litquiz.pl old mode 100644 new mode 100755 diff --git a/58 Love/perl/love.pl b/58 Love/perl/love.pl old mode 100644 new mode 100755 diff --git a/63 Name/perl/name.pl b/63 Name/perl/name.pl old mode 100644 new mode 100755 diff --git a/64 Nicomachus/perl/nicomachus.pl b/64 Nicomachus/perl/nicomachus.pl old mode 100644 new mode 100755 diff --git a/66 Number/perl/number.pl b/66 Number/perl/number.pl old mode 100644 new mode 100755 diff --git a/70 Poetry/perl/poetry.pl b/70 Poetry/perl/poetry.pl old mode 100644 new mode 100755 diff --git a/70 Poetry/poetry.pl b/70 Poetry/poetry.pl old mode 100644 new mode 100755 diff --git a/74 Rock Scissors Paper/perl/rockscissors.pl b/74 Rock Scissors Paper/perl/rockscissors.pl old mode 100644 new mode 100755 diff --git a/76 Russian Roulette/perl/russianroulette.pl b/76 Russian Roulette/perl/russianroulette.pl old mode 100644 new mode 100755 diff --git a/78 Sine Wave/perl/sinewave.pl b/78 Sine Wave/perl/sinewave.pl old mode 100644 new mode 100755 diff --git a/87 3-D Plot/perl/3dplot.pl b/87 3-D Plot/perl/3dplot.pl old mode 100644 new mode 100755 diff --git a/91 Train/perl/train.pl b/91 Train/perl/train.pl old mode 100644 new mode 100755 diff --git a/92 Trap/perl/trap.pl b/92 Trap/perl/trap.pl old mode 100644 new mode 100755 diff --git a/README.md b/README.md index 0a1c48d5..241e2f74 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ We're updating the first million selling computer book, [BASIC Computer Games](https://en.wikipedia.org/wiki/BASIC_Computer_Games), for 2021! -[Read book] (https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf) +[Read book](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf) ### Where can we discuss it? From e95990b7a3623f3a5fd792a61e69d065f05c3378 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 11 Jul 2021 09:14:38 -0400 Subject: [PATCH 404/749] Ported Mastermind to C# --- 60 Mastermind/csharp/Game/Game.csproj | 7 + 60 Mastermind/csharp/Game/src/Code.cs | 91 +++++++++ 60 Mastermind/csharp/Game/src/CodeFactory.cs | 92 +++++++++ 60 Mastermind/csharp/Game/src/ColorInfo.cs | 20 ++ 60 Mastermind/csharp/Game/src/Colors.cs | 20 ++ 60 Mastermind/csharp/Game/src/Command.cs | 13 ++ 60 Mastermind/csharp/Game/src/Controller.cs | 175 +++++++++++++++++ .../csharp/Game/src/EnumerableExtensions.cs | 111 +++++++++++ 60 Mastermind/csharp/Game/src/Program.cs | 171 +++++++++++++++++ 60 Mastermind/csharp/Game/src/TurnResult.cs | 38 ++++ 60 Mastermind/csharp/Game/src/View.cs | 178 ++++++++++++++++++ 60 Mastermind/csharp/Mastermind.sln | 25 +++ 12 files changed, 941 insertions(+) create mode 100644 60 Mastermind/csharp/Game/Game.csproj create mode 100644 60 Mastermind/csharp/Game/src/Code.cs create mode 100644 60 Mastermind/csharp/Game/src/CodeFactory.cs create mode 100644 60 Mastermind/csharp/Game/src/ColorInfo.cs create mode 100644 60 Mastermind/csharp/Game/src/Colors.cs create mode 100644 60 Mastermind/csharp/Game/src/Command.cs create mode 100644 60 Mastermind/csharp/Game/src/Controller.cs create mode 100644 60 Mastermind/csharp/Game/src/EnumerableExtensions.cs create mode 100644 60 Mastermind/csharp/Game/src/Program.cs create mode 100644 60 Mastermind/csharp/Game/src/TurnResult.cs create mode 100644 60 Mastermind/csharp/Game/src/View.cs create mode 100644 60 Mastermind/csharp/Mastermind.sln diff --git a/60 Mastermind/csharp/Game/Game.csproj b/60 Mastermind/csharp/Game/Game.csproj new file mode 100644 index 00000000..849a99d4 --- /dev/null +++ b/60 Mastermind/csharp/Game/Game.csproj @@ -0,0 +1,7 @@ + + + Exe + net5.0 + enable + + diff --git a/60 Mastermind/csharp/Game/src/Code.cs b/60 Mastermind/csharp/Game/src/Code.cs new file mode 100644 index 00000000..f8189c48 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/Code.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game +{ + /// + /// Represents a secret code in the game. + /// + public class Code + { + private readonly int[] m_colors; + + /// + /// Initializes a new instance of the Code class from the given set + /// of positions. + /// + /// + /// Contains the color for each position. + /// + public Code(IEnumerable colors) + { + m_colors = colors.ToArray(); + if (m_colors.Length == 0) + throw new ArgumentException("A code must contain at least one position"); + } + + /// + /// Compares this code with the given code. + /// + /// + /// The code to compare. + /// + /// + /// A number of black pegs and a number of white pegs. The number + /// of black pegs is the number of positions that contain the same + /// color in both codes. The number of white pegs is the number of + /// colors that appear in both codes, but in the wrong positions. + /// + public (int blacks, int whites) Compare(Code other) + { + // What follows is the O(N^2) from the original BASIC program + // (where N is the number of positions in the code). Note that + // there is an O(N) algorithm. (Finding it is left as an + // exercise for the reader.) + if (other.m_colors.Length != m_colors.Length) + throw new ArgumentException("Only codes of the same length can be compared"); + + // Keeps track of which positions in the other code have already + // been marked as exact or close matches. + var consumed = new bool[m_colors.Length]; + + var blacks = 0; + var whites = 0; + + for (var i = 0; i < m_colors.Length; ++i) + { + if (m_colors[i] == other.m_colors[i]) + { + ++blacks; + consumed[i] = true; + } + else + { + // Check if the current color appears elsewhere in the + // other code. We must be careful not to consider + // positions that are also exact matches. + for (var j = 0; j < m_colors.Length; ++j) + { + if (!consumed[j] && + m_colors[i] == other.m_colors[j] && + m_colors[j] != other.m_colors[j]) + { + ++whites; + consumed[j] = true; + break; + } + } + } + } + + return (blacks, whites); + } + + /// + /// Gets a string representation of the code. + /// + public override string ToString() => + new (m_colors.Select(index => Colors.List[index].ShortName).ToArray()); + } +} diff --git a/60 Mastermind/csharp/Game/src/CodeFactory.cs b/60 Mastermind/csharp/Game/src/CodeFactory.cs new file mode 100644 index 00000000..f1d0cb98 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/CodeFactory.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game +{ + /// + /// Provides methods for generating codes with a given number of positions + /// and colors. + /// + public class CodeFactory + { + /// + /// Gets the number of colors in codes generated by this factory. + /// + public int Colors { get; } + + /// + /// Gets the number of positions in codes generated by this factory. + /// + public int Positions { get; } + + /// + /// Gets the number of distinct codes that this factory can + /// generate. + /// + public int Possibilities { get; } + + /// + /// Initializes a new instance of the CodeFactory class. + /// + /// + /// The number of positions. + /// + /// + /// The number of colors. + /// + public CodeFactory(int positions, int colors) + { + if (positions < 1) + throw new ArgumentException("A code must contain at least one position"); + + if (colors < 1) + throw new ArgumentException("A code must contain at least one color"); + + if (colors > Game.Colors.List.Length) + throw new ArgumentException($"A code can contain no more than {Game.Colors.List.Length} colors"); + + Positions = positions; + Colors = colors; + Possibilities = (int)Math.Pow(colors, positions); + } + + /// + /// Creates a specified code. + /// + /// + /// The number of the code to create from 0 to Possibilities - 1. + /// + public Code Create(int number) => + EnumerateCodes().Skip(number).First(); + + /// + /// Creates a random code using the provided random number generator. + /// + /// + /// The random number generator. + /// + public Code Create(Random random) => + Create(random.Next(Possibilities)); + + /// + /// Generates a collection of codes containing every code that this + /// factory can create exactly once. + /// + public IEnumerable EnumerateCodes() + { + var current = new int[Positions]; + var position = default(int); + + do + { + yield return new Code(current); + + position = 0; + while (position < Positions && ++current[position] == Colors) + current[position++] = 0; + } + while (position < Positions); + } + } +} diff --git a/60 Mastermind/csharp/Game/src/ColorInfo.cs b/60 Mastermind/csharp/Game/src/ColorInfo.cs new file mode 100644 index 00000000..b05b8fa9 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/ColorInfo.cs @@ -0,0 +1,20 @@ +using System; + +namespace Game +{ + /// + /// Stores information about a color. + /// + public record ColorInfo + { + /// + /// Gets a single character that represents the color. + /// + public char ShortName { get; init; } + + /// + /// Gets the color's full name. + /// + public string LongName { get; init; } = String.Empty; + } +} diff --git a/60 Mastermind/csharp/Game/src/Colors.cs b/60 Mastermind/csharp/Game/src/Colors.cs new file mode 100644 index 00000000..6901633c --- /dev/null +++ b/60 Mastermind/csharp/Game/src/Colors.cs @@ -0,0 +1,20 @@ +namespace Game +{ + /// + /// Provides information about the colors that can be used in codes. + /// + public static class Colors + { + public static readonly ColorInfo[] List = new[] + { + new ColorInfo { ShortName = 'B', LongName = "BLACK" }, + new ColorInfo { ShortName = 'W', LongName = "WHITE" }, + new ColorInfo { ShortName = 'R', LongName = "RED" }, + new ColorInfo { ShortName = 'G', LongName = "GREEN" }, + new ColorInfo { ShortName = 'O', LongName = "ORANGE" }, + new ColorInfo { ShortName = 'Y', LongName = "YELLOW" }, + new ColorInfo { ShortName = 'P', LongName = "PURPLE" }, + new ColorInfo { ShortName = 'T', LongName = "TAN" } + }; + } +} diff --git a/60 Mastermind/csharp/Game/src/Command.cs b/60 Mastermind/csharp/Game/src/Command.cs new file mode 100644 index 00000000..5df3201a --- /dev/null +++ b/60 Mastermind/csharp/Game/src/Command.cs @@ -0,0 +1,13 @@ +namespace Game +{ + /// + /// Enumerates the different commands that the user can issue during + /// the game. + /// + public enum Command + { + MakeGuess, + ShowBoard, + Quit + } +} diff --git a/60 Mastermind/csharp/Game/src/Controller.cs b/60 Mastermind/csharp/Game/src/Controller.cs new file mode 100644 index 00000000..389203b0 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/Controller.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Immutable; +using System.Linq; + +namespace Game +{ + /// + /// Contains functions for getting input from the end user. + /// + public static class Controller + { + /// + /// Maps the letters for each color to the integer value representing + /// that color. + /// + /// + /// We derive this map from the Colors list rather than defining the + /// entries directly in order to keep all color related information + /// in one place. (This makes it easier to change the color options + /// later.) + /// + private static ImmutableDictionary ColorsByKey = Colors.List + .Select((info, index) => (key: info.ShortName, index)) + .ToImmutableDictionary(entry => entry.key, entry => entry.index); + + /// + /// Gets the number of colors to use in the secret code. + /// + public static int GetNumberOfColors() + { + var maximumColors = Colors.List.Length; + var colors = 0; + + while (colors < 1 || colors > maximumColors) + { + colors = GetInteger(View.PromptNumberOfColors); + if (colors > maximumColors) + View.NotifyTooManyColors(maximumColors); + } + + return colors; + } + + /// + /// Gets the number of positions in the secret code. + /// + /// + public static int GetNumberOfPositions() + { + // Note: We should probably ensure that the user enters a sane + // number of positions here. (Things go south pretty quickly + // with a large number of positions.) But since the original + // program did not, neither will we. + return GetInteger(View.PromptNumberOfPositions); + } + + /// + /// Gets the number of rounds to play. + /// + public static int GetNumberOfRounds() + { + // Note: Silly numbers of rounds (like 0, or a negative number) + // are harmless, but it would still make sense to validate. + return GetInteger(View.PromptNumberOfRounds); + } + + /// + /// Gets a command from the user. + /// + /// + /// The current move number. + /// + /// + /// The number of code positions. + /// + /// + /// The maximum number of code colors. + /// + /// + /// The entered command and guess (if applicable). + /// + public static (Command command, Code? guess) GetCommand(int moveNumber, int positions, int colors) + { + while (true) + { + View.PromptGuess (moveNumber); + + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + switch (input.ToUpperInvariant()) + { + case "BOARD": + return (Command.ShowBoard, null); + case "QUIT": + return (Command.Quit, null); + default: + if (input.Length != positions) + View.NotifyBadNumberOfPositions(); + else + if (input.FindFirstIndex(c => !TranslateColor(c).HasValue) is int invalidPosition) + View.NotifyInvalidColor(input[invalidPosition]); + else + return (Command.MakeGuess, new Code(input.SelectNonNull(TranslateColor))); + + break; + } + } + } + + /// + /// Waits until the user indicates that he or she is ready to continue. + /// + public static void WaitUntilReady() + { + View.PromptReady(); + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + } + + /// + /// Gets the number of blacks and whites for the given code from the + /// user. + /// + public static (int blacks, int whites) GetBlacksWhites(Code code) + { + while (true) + { + View.PromptBlacksWhites(code); + + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + var parts = input.Split(','); + + if (parts.Length != 2) + View.PromptTwoValues(); + else + if (!Int32.TryParse(parts[0], out var blacks) || !Int32.TryParse(parts[1], out var whites)) + View.PromptValidInteger(); + else + return (blacks, whites); + } + } + + /// + /// Gets an integer value from the user. + /// + private static int GetInteger(Action prompt) + { + while (true) + { + prompt(); + + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + if (Int32.TryParse(input, out var result)) + return result; + else + View.PromptValidInteger(); + } + } + + /// + /// Translates the given character into the corresponding color. + /// + private static int? TranslateColor(char c) => + ColorsByKey.TryGetValue(c, out var index) ? index : null; + } +} diff --git a/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs b/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs new file mode 100644 index 00000000..c235ffa7 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game +{ + /// + /// Provides additional methods for the + /// interface. + /// + public static class EnumerableExtensions + { + /// + /// Cycles through the integer values in the range [0, count). + /// + /// + /// The first value to return. + /// + /// + /// The number of values to return. + /// + public static IEnumerable Cycle(int start, int count) + { + if (count < 1) + throw new ArgumentException("count must be at least 1"); + + if (start < 0 || start >= count) + throw new ArgumentException("start must be in the range [0, count)"); + + for (var i = start; i < count; ++i) + yield return i; + + for (var i = 0; i < start; ++i) + yield return i; + } + + /// + /// Finds the index of the first item in the given sequence that + /// satisfies the given predicate. + /// + /// + /// The type of elements in the sequence. + /// + /// + /// The source sequence. + /// + /// + /// The predicate function. + /// + /// + /// The index of the first element in the source sequence for which + /// predicate(element) is true. If there is no such element, return + /// is null. + /// + public static int? FindFirstIndex(this IEnumerable source, Func predicate) => + source.Select((element, index) => predicate(element) ? index : default(int?)) + .FirstOrDefault(index => index.HasValue); + + /// + /// Returns the first item in the given sequence that matches the + /// given predicate. + /// + /// + /// The type of elements in the sequence. + /// + /// + /// The source sequence. + /// + /// + /// The predicate to check against each element. + /// + /// + /// The value to return if no elements match the predicate. + /// + /// + /// The first item in the source sequence that matches the given + /// predicate, or the provided default value if none do. + /// + public static T FirstOrDefault(this IEnumerable source, Func predicate, T defaultValue) + { + foreach (var element in source) + if (predicate(element)) + return element; + + return defaultValue; + } + + /// + /// Maps the values of the source sequence to a nullable type and + /// returns the non-null values. + /// + /// + /// The type of elements in the source sequence. + /// + /// + /// The source sequence. + /// + /// + /// The selector function. + /// + public static IEnumerable SelectNonNull(this IEnumerable source, Func selector) where TResult: struct + { + foreach (var element in source) + { + var result = selector(element); + if (result.HasValue) + yield return result.Value; + } + } + } +} diff --git a/60 Mastermind/csharp/Game/src/Program.cs b/60 Mastermind/csharp/Game/src/Program.cs new file mode 100644 index 00000000..e7419084 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/Program.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game +{ + // MASTERMIND II + // STEVE NORTH + // CREATIVE COMPUTING + // PO BOX 789-M MORRISTOWN NEW JERSEY 07960 + class Program + { + public const int MaximumGuesses = 10; + + static void Main() + { + var (codeFactory, rounds) = StartGame(); + + var random = new Random(); + var humanScore = 0; + var computerScore = 0; + + for (var round = 1; round <= rounds; ++round) + { + if (!HumanTakesTurn()) + return; + + while (!ComputerTakesTurn()) + View.ShowInconsistentInformation(); + } + + View.ShowScores(humanScore, computerScore, isFinal: true); + + /// + /// Gets the game start parameters from the user. + /// + (CodeFactory codeFactory, int rounds) StartGame() + { + View.ShowBanner(); + + var colors = Controller.GetNumberOfColors(); + var positions = Controller.GetNumberOfPositions(); + var rounds = Controller.GetNumberOfRounds(); + + var codeFactory = new CodeFactory(positions, colors); + + View.ShowTotalPossibilities(codeFactory.Possibilities); + View.ShowColorTable(codeFactory.Colors); + + return (codeFactory, rounds); + } + + /// + /// Executes the human's turn. + /// + /// + /// True if thue human completed his or her turn and false if + /// he or she quit the game. + /// + bool HumanTakesTurn() + { + // Store a history of the human's guesses (used for the show + // board command below). + var history = new List(); + var code = codeFactory.Create(random); + var guessNumber = default(int); + + for (guessNumber = 1; guessNumber <= MaximumGuesses; ++guessNumber) + { + var guess = default(Code); + + while (guess is null) + { + switch (Controller.GetCommand(guessNumber, codeFactory.Positions, codeFactory.Colors)) + { + case (Command.MakeGuess, Code input): + guess = input; + break; + case (Command.ShowBoard, _): + View.ShowBoard(history); + break; + case (Command.Quit, _): + View.ShowQuitGame(code); + return false; + } + } + + var (blacks, whites) = code.Compare(guess); + if (blacks == codeFactory.Positions) + break; + + View.ShowResults(blacks, whites); + + history.Add(new TurnResult(guess, blacks, whites)); + } + + if (guessNumber <= MaximumGuesses) + View.ShowHumanGuessedCode(guessNumber); + else + View.ShowHumanFailedToGuessCode(code); + + humanScore += guessNumber; + + View.ShowScores(humanScore, computerScore, isFinal: false); + return true; + } + + /// + /// Executes the computers turn. + /// + /// + /// True if the computer completes its turn successfully and false + /// if it does not (due to human error). + /// + bool ComputerTakesTurn() + { + var isCandidate = new bool[codeFactory.Possibilities]; + var guessNumber = default(int); + + Array.Fill(isCandidate, true); + + View.ShowComputerStartTurn(); + Controller.WaitUntilReady(); + + for (guessNumber = 1; guessNumber <= MaximumGuesses; ++guessNumber) + { + // Starting with a random code, cycle through codes until + // we find one that is still a candidate solution. If + // there are no remaining candidates, then it implies that + // the user made an error in one or more responses. + var codeNumber = EnumerableExtensions.Cycle(random.Next(codeFactory.Possibilities), codeFactory.Possibilities) + .FirstOrDefault(i => isCandidate[i], -1); + + if (codeNumber < 0) + return false; + + var guess = codeFactory.Create(codeNumber); + + var (blacks, whites) = Controller.GetBlacksWhites(guess); + if (blacks == codeFactory.Positions) + break; + + // Mark codes which are no longer potential solutions. We + // know that the current guess yields the above number of + // blacks and whites when compared to the solution, so any + // code that yields a different number of blacks or whites + // can't be the answer. + foreach (var (candidate, index) in codeFactory.EnumerateCodes().Select((candidate, index) => (candidate, index))) + { + if (isCandidate[index]) + { + var (candidateBlacks, candidateWhites) = guess.Compare(candidate); + if (blacks != candidateBlacks || whites != candidateWhites) + isCandidate[index] = false; + } + } + } + + if (guessNumber <= MaximumGuesses) + View.ShowComputerGuessedCode(guessNumber); + else + View.ShowComputerFailedToGuessCode(); + + computerScore += guessNumber; + View.ShowScores(humanScore, computerScore, isFinal: false); + + return true; + } + } + } +} diff --git a/60 Mastermind/csharp/Game/src/TurnResult.cs b/60 Mastermind/csharp/Game/src/TurnResult.cs new file mode 100644 index 00000000..b854e92f --- /dev/null +++ b/60 Mastermind/csharp/Game/src/TurnResult.cs @@ -0,0 +1,38 @@ +namespace Game +{ + /// + /// Stores the result of a player's turn. + /// + public record TurnResult + { + /// + /// Gets the code guessed by the player. + /// + public Code Guess { get; } + + /// + /// Gets the number of black pegs resulting from the guess. + /// + public int Blacks { get; } + + /// + /// Gets the number of white pegs resulting from the guess. + /// + public int Whites { get; } + + /// + /// Initializes a new instance of the TurnResult record. + /// + /// + /// The player's guess. + /// + /// + /// The number of black pegs. + /// + /// + /// The number of white pegs. + /// + public TurnResult(Code guess, int blacks, int whites) => + (Guess, Blacks, Whites) = (guess, blacks, whites); + } +} diff --git a/60 Mastermind/csharp/Game/src/View.cs b/60 Mastermind/csharp/Game/src/View.cs new file mode 100644 index 00000000..7dcb3429 --- /dev/null +++ b/60 Mastermind/csharp/Game/src/View.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Game +{ + /// + /// Contains functions for displaying information to the end user. + /// + public static class View + { + public static void ShowBanner() + { + Console.WriteLine(" MASTERMIND"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowStartOfRound(int roundNumber) + { + Console.WriteLine(); + Console.WriteLine($"ROUND NUMBER {roundNumber} ----"); + Console.WriteLine(); + Console.WriteLine("GUESS MY COMBINATION."); + Console.WriteLine(); + } + + public static void ShowTotalPossibilities(int possibilities) + { + Console.WriteLine($"TOTAL POSSIBILITIES = {possibilities}"); + Console.WriteLine(); + } + + public static void ShowColorTable(int numberOfColors) + { + Console.WriteLine(); + Console.WriteLine("COLOR LETTER"); + Console.WriteLine("===== ======"); + + foreach (var color in Colors.List.Take(numberOfColors)) + Console.WriteLine($"{color.LongName,-13}{color.ShortName}"); + + Console.WriteLine(); + } + + public static void ShowBoard(IEnumerable history) + { + Console.WriteLine(); + Console.WriteLine("BOARD"); + Console.WriteLine("MOVE GUESS BLACK WHITE"); + + var moveNumber = 0; + foreach (var result in history) + Console.WriteLine($"{++moveNumber,-9}{result.Guess,-16}{result.Blacks,-10}{result.Whites}"); + + Console.WriteLine(); + } + + public static void ShowQuitGame(Code code) + { + Console.WriteLine($"QUITTER! MY COMBINATION WAS: {code}"); + Console.WriteLine("GOOD BYE"); + } + + public static void ShowResults(int blacks, int whites) + { + Console.WriteLine($"YOU HAVE {blacks} BLACKS AND {whites} WHITES."); + } + + public static void ShowHumanGuessedCode(int guessNumber) + { + Console.WriteLine($"YOU GUESSED IT IN {guessNumber} MOVES!"); + } + + public static void ShowHumanFailedToGuessCode(Code code) + { + // Note: The original code did not print out the combination, but + // this appears to be a bug. + Console.WriteLine("YOU RAN OUT OF MOVES! THAT'S ALL YOU GET!"); + Console.WriteLine($"THE ACTUAL COMBINATION WAS: {code}"); + } + + public static void ShowScores(int humanScore, int computerScore, bool isFinal) + { + if (isFinal) + { + Console.WriteLine("GAME OVER"); + Console.WriteLine("FINAL SCORE:"); + } + else + Console.WriteLine("SCORE:"); + + Console.WriteLine($" COMPUTER {computerScore}"); + Console.WriteLine($" HUMAN {humanScore}"); + Console.WriteLine(); + } + + public static void ShowComputerStartTurn() + { + Console.WriteLine("NOW I GUESS. THINK OF A COMBINATION."); + } + + public static void ShowInconsistentInformation() + { + Console.WriteLine("YOU HAVE GIVEN ME INCONSISTENT INFORMATION."); + Console.WriteLine("TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL."); + } + + public static void ShowComputerGuessedCode(int guessNumber) + { + Console.WriteLine($"I GOT IT IN {guessNumber} MOVES!"); + } + + public static void ShowComputerFailedToGuessCode() + { + Console.WriteLine("I USED UP ALL MY MOVES!"); + Console.WriteLine("I GUESS MY CPU IS JUST HAVING AN OFF DAY."); + } + + public static void PromptNumberOfColors() + { + Console.Write("NUMBER OF COLORS? "); + } + + public static void PromptNumberOfPositions() + { + Console.Write("NUMBER OF POSITIONS? "); + } + + public static void PromptNumberOfRounds() + { + Console.Write("NUMBER OF ROUNDS? "); + } + + public static void PromptGuess(int moveNumber) + { + Console.Write($"MOVE # {moveNumber} GUESS ? "); + } + + public static void PromptReady() + { + Console.Write("HIT RETURN WHEN READY ? "); + } + + public static void PromptBlacksWhites(Code code) + { + Console.Write($"MY GUESS IS: {code}"); + Console.Write(" BLACKS, WHITES ? "); + } + + public static void PromptTwoValues() + { + Console.WriteLine("PLEASE ENTER TWO VALUES, SEPARATED BY A COMMA"); + } + + public static void PromptValidInteger() + { + Console.WriteLine("PLEASE ENTER AN INTEGER VALUE"); + } + + public static void NotifyBadNumberOfPositions() + { + Console.WriteLine("BAD NUMBER OF POSITIONS"); + } + + public static void NotifyInvalidColor(char colorKey) + { + Console.WriteLine($"'{colorKey}' IS UNRECOGNIZED."); + } + + public static void NotifyTooManyColors(int maxColors) + { + Console.WriteLine($"NO MORE THAN {maxColors}, PLEASE!"); + } + } +} diff --git a/60 Mastermind/csharp/Mastermind.sln b/60 Mastermind/csharp/Mastermind.sln new file mode 100644 index 00000000..c3827fb7 --- /dev/null +++ b/60 Mastermind/csharp/Mastermind.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game\Game.csproj", "{E8D63140-971D-4FBF-8138-964E54CCB7DD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E8D63140-971D-4FBF-8138-964E54CCB7DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8D63140-971D-4FBF-8138-964E54CCB7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8D63140-971D-4FBF-8138-964E54CCB7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8D63140-971D-4FBF-8138-964E54CCB7DD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1BDFBEE6-8345-438C-8FCE-B2C9394CC080} + EndGlobalSection +EndGlobal From 016d65862525f24a14e9b5e871e9802a253fffea Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 11 Jul 2021 09:27:45 -0400 Subject: [PATCH 405/749] Added missing start of turn output --- 60 Mastermind/csharp/Game/src/Program.cs | 2 ++ 60 Mastermind/csharp/Game/src/View.cs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/60 Mastermind/csharp/Game/src/Program.cs b/60 Mastermind/csharp/Game/src/Program.cs index e7419084..13f525d7 100644 --- a/60 Mastermind/csharp/Game/src/Program.cs +++ b/60 Mastermind/csharp/Game/src/Program.cs @@ -22,6 +22,8 @@ namespace Game for (var round = 1; round <= rounds; ++round) { + View.ShowStartOfRound(round); + if (!HumanTakesTurn()) return; diff --git a/60 Mastermind/csharp/Game/src/View.cs b/60 Mastermind/csharp/Game/src/View.cs index 7dcb3429..ea8bd898 100644 --- a/60 Mastermind/csharp/Game/src/View.cs +++ b/60 Mastermind/csharp/Game/src/View.cs @@ -18,15 +18,6 @@ namespace Game Console.WriteLine(); } - public static void ShowStartOfRound(int roundNumber) - { - Console.WriteLine(); - Console.WriteLine($"ROUND NUMBER {roundNumber} ----"); - Console.WriteLine(); - Console.WriteLine("GUESS MY COMBINATION."); - Console.WriteLine(); - } - public static void ShowTotalPossibilities(int possibilities) { Console.WriteLine($"TOTAL POSSIBILITIES = {possibilities}"); @@ -45,6 +36,15 @@ namespace Game Console.WriteLine(); } + public static void ShowStartOfRound(int roundNumber) + { + Console.WriteLine(); + Console.WriteLine($"ROUND NUMBER {roundNumber} ----"); + Console.WriteLine(); + Console.WriteLine("GUESS MY COMBINATION."); + Console.WriteLine(); + } + public static void ShowBoard(IEnumerable history) { Console.WriteLine(); From 2fd93904b1db41a8cd3614f5cbd20ae1774eba17 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 11 Jul 2021 21:58:19 -0400 Subject: [PATCH 406/749] Removed unnecessary code in favor of null forgiving operator --- 60 Mastermind/csharp/Game/src/Controller.cs | 2 +- .../csharp/Game/src/EnumerableExtensions.cs | 23 ------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/60 Mastermind/csharp/Game/src/Controller.cs b/60 Mastermind/csharp/Game/src/Controller.cs index 389203b0..85a41f9f 100644 --- a/60 Mastermind/csharp/Game/src/Controller.cs +++ b/60 Mastermind/csharp/Game/src/Controller.cs @@ -102,7 +102,7 @@ namespace Game if (input.FindFirstIndex(c => !TranslateColor(c).HasValue) is int invalidPosition) View.NotifyInvalidColor(input[invalidPosition]); else - return (Command.MakeGuess, new Code(input.SelectNonNull(TranslateColor))); + return (Command.MakeGuess, new Code(input.Select(c => TranslateColor(c)!.Value))); break; } diff --git a/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs b/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs index c235ffa7..3bd6cf96 100644 --- a/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs +++ b/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs @@ -84,28 +84,5 @@ namespace Game return defaultValue; } - - /// - /// Maps the values of the source sequence to a nullable type and - /// returns the non-null values. - /// - /// - /// The type of elements in the source sequence. - /// - /// - /// The source sequence. - /// - /// - /// The selector function. - /// - public static IEnumerable SelectNonNull(this IEnumerable source, Func selector) where TResult: struct - { - foreach (var element in source) - { - var result = selector(element); - if (result.HasValue) - yield return result.Value; - } - } } } From 1794bb048db0ff5d4915a284c4864bc5bbb17d4a Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 12 Jul 2021 22:20:51 -0400 Subject: [PATCH 407/749] Enabled nullable reference types --- 83 Stock Market/csharp/Game.csproj | 3 +-- 83 Stock Market/csharp/src/Company.cs | 10 ++++++++-- 83 Stock Market/csharp/src/Controller.cs | 9 +++++++-- 83 Stock Market/csharp/src/Program.cs | 10 +++++----- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/83 Stock Market/csharp/Game.csproj b/83 Stock Market/csharp/Game.csproj index 20827042..849a99d4 100644 --- a/83 Stock Market/csharp/Game.csproj +++ b/83 Stock Market/csharp/Game.csproj @@ -1,8 +1,7 @@ - Exe net5.0 + enable - diff --git a/83 Stock Market/csharp/src/Company.cs b/83 Stock Market/csharp/src/Company.cs index 59f40e8d..86c4e4ba 100644 --- a/83 Stock Market/csharp/src/Company.cs +++ b/83 Stock Market/csharp/src/Company.cs @@ -8,16 +8,22 @@ /// /// Gets the company's name. /// - public string Name { get; init; } + public string Name { get; } /// /// Gets the company's three letter stock symbol. /// - public string StockSymbol { get; init; } + public string StockSymbol { get; } /// /// Gets the company's current share price. /// public double SharePrice { get; init; } + + /// + /// Initializes a new Company record. + /// + public Company(string name, string stockSymbol, double sharePrice) => + (Name, StockSymbol, SharePrice) = (name, stockSymbol, sharePrice); } } diff --git a/83 Stock Market/csharp/src/Controller.cs b/83 Stock Market/csharp/src/Controller.cs index bccfde0c..87a1dc7d 100644 --- a/83 Stock Market/csharp/src/Controller.cs +++ b/83 Stock Market/csharp/src/Controller.cs @@ -97,10 +97,15 @@ namespace Game while (true) { View.PromptBuySellCompany(company); - if (Int32.TryParse(Console.ReadLine(), out var amount)) - return amount; + + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); else + if (!Int32.TryParse(input, out var amount)) View.PromptValidInteger(); + else + return amount; } } } diff --git a/83 Stock Market/csharp/src/Program.cs b/83 Stock Market/csharp/src/Program.cs index 552d8c9a..8d2b2a98 100644 --- a/83 Stock Market/csharp/src/Program.cs +++ b/83 Stock Market/csharp/src/Program.cs @@ -11,11 +11,11 @@ namespace Game ///
private static ImmutableArray Companies = ImmutableArray.CreateRange(new[] { - new Company { Name = "INT. BALLISTIC MISSILES", StockSymbol = "IBM", SharePrice = 100 }, - new Company { Name = "RED CROSS OF AMERICA", StockSymbol = "RCA", SharePrice = 85 }, - new Company { Name = "LICHTENSTEIN, BUMRAP & JOKE", StockSymbol = "LBJ", SharePrice = 150 }, - new Company { Name = "AMERICAN BANKRUPT CO.", StockSymbol = "ABC", SharePrice = 140 }, - new Company { Name = "CENSURED BOOKS STORE", StockSymbol = "CBS", SharePrice = 110 } + new Company("INT. BALLISTIC MISSILES", "IBM", sharePrice:100), + new Company("RED CROSS OF AMERICA", "RCA", sharePrice:85 ), + new Company("LICHTENSTEIN, BUMRAP & JOKE", "LBJ", sharePrice:150), + new Company("AMERICAN BANKRUPT CO.", "ABC", sharePrice:140), + new Company("CENSURED BOOKS STORE", "CBS", sharePrice:110) }); static void Main() From cc23f806c4ae6ab190c1bb504f43236c87e10029 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 17 Jul 2021 06:46:53 -0400 Subject: [PATCH 408/749] Minor code clean-up --- .../Extensions/ImmutableArrayExtensions.cs | 37 +++++++++++++++++++ 83 Stock Market/csharp/src/Program.cs | 2 +- 83 Stock Market/csharp/src/StockMarket.cs | 12 +++--- 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 83 Stock Market/csharp/src/Extensions/ImmutableArrayExtensions.cs diff --git a/83 Stock Market/csharp/src/Extensions/ImmutableArrayExtensions.cs b/83 Stock Market/csharp/src/Extensions/ImmutableArrayExtensions.cs new file mode 100644 index 00000000..544c7625 --- /dev/null +++ b/83 Stock Market/csharp/src/Extensions/ImmutableArrayExtensions.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Immutable; + +namespace Game.Extensions +{ + /// + /// Provides additional methods for the class. + /// + public static class ImmutableArrayExtensions + { + /// + /// Maps each element in an immutable array to a new value. + /// + /// + /// The type of elements in the source array. + /// + /// + /// The type of elements in the resulting array. + /// + /// + /// The source array. + /// + /// + /// Function which receives an element from the source array and its + /// index and returns the resulting element. + /// + public static ImmutableArray Map(this ImmutableArray source, Func selector) + { + var builder = ImmutableArray.CreateBuilder(source.Length); + + for (var i = 0; i < source.Length; ++i) + builder.Add(selector(source[i], i)); + + return builder.MoveToImmutable(); + } + } +} diff --git a/83 Stock Market/csharp/src/Program.cs b/83 Stock Market/csharp/src/Program.cs index 8d2b2a98..a7ab841a 100644 --- a/83 Stock Market/csharp/src/Program.cs +++ b/83 Stock Market/csharp/src/Program.cs @@ -9,7 +9,7 @@ namespace Game /// /// Defines the set of companies that will be simulated in the game. /// - private static ImmutableArray Companies = ImmutableArray.CreateRange(new[] + private readonly static ImmutableArray Companies = ImmutableArray.CreateRange(new[] { new Company("INT. BALLISTIC MISSILES", "IBM", sharePrice:100), new Company("RED CROSS OF AMERICA", "RCA", sharePrice:85 ), diff --git a/83 Stock Market/csharp/src/StockMarket.cs b/83 Stock Market/csharp/src/StockMarket.cs index ba2f52ee..36201074 100644 --- a/83 Stock Market/csharp/src/StockMarket.cs +++ b/83 Stock Market/csharp/src/StockMarket.cs @@ -38,13 +38,13 @@ namespace Game }, (parameters, previousDay) => previousDay with { - Companies = ImmutableArray.CreateRange( - previousDay.Companies.Select ((company, index) => AdjustSharePrice( + Companies = previousDay.Companies.Map( + (company, index) => AdjustSharePrice( random, company, parameters.trend, parameters.positiveSpike == index, - parameters.negativeSpike == index))) + parameters.negativeSpike == index)) }); } @@ -106,7 +106,7 @@ namespace Game /// The maximum number of days each trend should last. /// public static IEnumerable Trends(Random random, int minDays, int maxDays) => - random.Integers(minDays, maxDays + 1).SelectMany(days => Enumerable.Repeat(GenerateTrend(random), days)); + random.Integers(minDays, maxDays + 1).SelectMany(daysInCycle => Enumerable.Repeat(GenerateTrend(random), daysInCycle)); ///
/// Generates a random value for the market trend. @@ -143,7 +143,7 @@ namespace Game private static IEnumerable PriceSpikes(Random random, int companyCount, int minDays, int maxDays) => random.Integers(minDays, maxDays + 1) .SelectMany( - days => Enumerable.Range(0, days), - (days, dayNumber) => dayNumber == 0 ? random.Next(companyCount) : default(int?)); + daysInCycle => Enumerable.Range(0, daysInCycle), + (daysInCycle, dayNumber) => dayNumber == 0 ? random.Next(companyCount) : default(int?)); } } From bc628e71daf1f807730fc9843ca4edde1a7ee76a Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 22 Jul 2021 16:55:23 -0400 Subject: [PATCH 409/749] Initial port of Bullfight to C# --- 17 Bullfight/csharp/Bullfight.sln | 25 ++ 17 Bullfight/csharp/Game.csproj | 7 + 17 Bullfight/csharp/src/Action.cs | 24 ++ 17 Bullfight/csharp/src/ActionResult.cs | 44 ++++ 17 Bullfight/csharp/src/Controller.cs | 129 +++++++++++ 17 Bullfight/csharp/src/MatchConditions.cs | 41 ++++ 17 Bullfight/csharp/src/MatchState.cs | 28 +++ 17 Bullfight/csharp/src/Program.cs | 56 +++++ 17 Bullfight/csharp/src/Quality.cs | 19 ++ 17 Bullfight/csharp/src/Reward.cs | 13 ++ 17 Bullfight/csharp/src/RiskLevel.cs | 12 + 17 Bullfight/csharp/src/Rules.cs | 258 +++++++++++++++++++++ 17 Bullfight/csharp/src/View.cs | 240 +++++++++++++++++++ 13 files changed, 896 insertions(+) create mode 100644 17 Bullfight/csharp/Bullfight.sln create mode 100644 17 Bullfight/csharp/Game.csproj create mode 100644 17 Bullfight/csharp/src/Action.cs create mode 100644 17 Bullfight/csharp/src/ActionResult.cs create mode 100644 17 Bullfight/csharp/src/Controller.cs create mode 100644 17 Bullfight/csharp/src/MatchConditions.cs create mode 100644 17 Bullfight/csharp/src/MatchState.cs create mode 100644 17 Bullfight/csharp/src/Program.cs create mode 100644 17 Bullfight/csharp/src/Quality.cs create mode 100644 17 Bullfight/csharp/src/Reward.cs create mode 100644 17 Bullfight/csharp/src/RiskLevel.cs create mode 100644 17 Bullfight/csharp/src/Rules.cs create mode 100644 17 Bullfight/csharp/src/View.cs diff --git a/17 Bullfight/csharp/Bullfight.sln b/17 Bullfight/csharp/Bullfight.sln new file mode 100644 index 00000000..29f5276f --- /dev/null +++ b/17 Bullfight/csharp/Bullfight.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{8F7C450E-5F3A-45BA-9DB9-329744214931}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F7C450E-5F3A-45BA-9DB9-329744214931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F7C450E-5F3A-45BA-9DB9-329744214931}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F7C450E-5F3A-45BA-9DB9-329744214931}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F7C450E-5F3A-45BA-9DB9-329744214931}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C5BFC749-C7D8-4981-A7D4-1D401901A890} + EndGlobalSection +EndGlobal diff --git a/17 Bullfight/csharp/Game.csproj b/17 Bullfight/csharp/Game.csproj new file mode 100644 index 00000000..849a99d4 --- /dev/null +++ b/17 Bullfight/csharp/Game.csproj @@ -0,0 +1,7 @@ + + + Exe + net5.0 + enable + + diff --git a/17 Bullfight/csharp/src/Action.cs b/17 Bullfight/csharp/src/Action.cs new file mode 100644 index 00000000..2a148683 --- /dev/null +++ b/17 Bullfight/csharp/src/Action.cs @@ -0,0 +1,24 @@ +namespace Game +{ + /// + /// Enumerates the different actions that the player can take on each round + /// of the fight. + /// + public enum Action + { + /// + /// Dodge the bull. + /// + Dodge, + + /// + /// Kill the bull. + /// + Kill, + + /// + /// Freeze in place and don't do anything. + /// + Panic + } +} diff --git a/17 Bullfight/csharp/src/ActionResult.cs b/17 Bullfight/csharp/src/ActionResult.cs new file mode 100644 index 00000000..baa74f2e --- /dev/null +++ b/17 Bullfight/csharp/src/ActionResult.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Game +{ + /// + /// Enumerates the different possible outcomes of the player's action. + /// + public enum ActionResult + { + /// + /// The fight continues. + /// + FightContinues, + + /// + /// The player fled from the ring. + /// + PlayerFlees, + + /// + /// The bull has gored the player. + /// + BullGoresPlayer, + + /// + /// The bull killed the player. + /// + BullKillsPlayer, + + /// + /// The player killed the bull. + /// + PlayerKillsBull, + + /// + /// The player attempted to kill the bull and both survived. + /// + Draw + } +} diff --git a/17 Bullfight/csharp/src/Controller.cs b/17 Bullfight/csharp/src/Controller.cs new file mode 100644 index 00000000..2355e247 --- /dev/null +++ b/17 Bullfight/csharp/src/Controller.cs @@ -0,0 +1,129 @@ +using System; + +namespace Game +{ + /// + /// Contains functions for getting input from the user. + /// + public static class Controller + { + /// + /// Handles the initial interaction with the player. + /// + public static void StartGame() + { + View.ShowBanner(); + View.PromptShowInstructions(); + + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + if (input.ToUpperInvariant() != "NO") + View.ShowInstructions(); + + View.ShowSeparator(); + } + + /// + /// Gets the player's action for the current round. + /// + /// + /// The current pass number. + /// + public static (Action action, RiskLevel riskLevel) GetPlayerIntention(int passNumber) + { + if (passNumber < 3) + View.PromptKillBull(); + else + View.PromptKillBullBrief(); + + var attemptToKill = GetYesOrNo(); + + if (attemptToKill) + { + View.PromptKillMethod(); + + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + return input switch + { + "4" => (Action.Kill, RiskLevel.High), + "5" => (Action.Kill, RiskLevel.Low), + _ => (Action.Panic, default(RiskLevel)) + }; + } + else + { + if (passNumber < 2) + View.PromptCapeMove(); + else + View.PromptCapeMoveBrief(); + + var action = Action.Panic; + var riskLevel = default(RiskLevel); + + while (action == Action.Panic) + { + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + (action, riskLevel) = input switch + { + "0" => (Action.Dodge, RiskLevel.High), + "1" => (Action.Dodge, RiskLevel.Medium), + "2" => (Action.Dodge, RiskLevel.Low), + _ => (Action.Panic, default(RiskLevel)) + }; + + if (action == Action.Panic) + View.PromptDontPanic(); + } + + return (action, riskLevel); + } + } + + /// + /// Gets the player's intention to flee (or not). + /// + /// + /// True if the player flees; otherwise, false. + /// + public static bool PlayerRunsFromRing() + { + View.PromptRunFromRing(); + return GetYesOrNo(); + } + + /// + /// Gets a yes or no response from the player. + /// + /// + /// True if the user answered yes; otherwise, false. + /// + public static bool GetYesOrNo() + { + while (true) + { + var input = Console.ReadLine(); + if (input is null) + Environment.Exit(0); + + switch (input.ToUpperInvariant()) + { + case "YES": + return true; + case "NO": + return false; + default: + Console.WriteLine("INCORRECT ANSWER - - PLEASE TYPE 'YES' OR 'NO'."); + break; + } + } + } + } +} diff --git a/17 Bullfight/csharp/src/MatchConditions.cs b/17 Bullfight/csharp/src/MatchConditions.cs new file mode 100644 index 00000000..5d5d979c --- /dev/null +++ b/17 Bullfight/csharp/src/MatchConditions.cs @@ -0,0 +1,41 @@ +namespace Game +{ + /// + /// Stores the initial conditions of a match. + /// + public record MatchConditions + { + /// + /// Gets the quality of the bull. + /// + public Quality BullQuality { get; init; } + + /// + /// Gets the quality of help received from the toreadores. + /// + public Quality ToreadorePerformance { get; init; } + + /// + /// Gets the quality of help received from the picadores. + /// + public Quality PicadorePerformance { get; init; } + + /// + /// Gets the number of toreadores killed while preparing for the + /// final round. + /// + public int ToreadoresKilled { get; init; } + + /// + /// Gets the number of picadores killed while preparing for the + /// final round. + /// + public int PicadoresKilled { get; init; } + + /// + /// Gets the number of horses killed while preparing for the final + /// round. + /// + public int HorsesKilled { get; init; } + } +} diff --git a/17 Bullfight/csharp/src/MatchState.cs b/17 Bullfight/csharp/src/MatchState.cs new file mode 100644 index 00000000..3eae6d5d --- /dev/null +++ b/17 Bullfight/csharp/src/MatchState.cs @@ -0,0 +1,28 @@ +namespace Game +{ + /// + /// Stores the current state of the match. + /// + public record MatchState(MatchConditions Conditions) + { + /// + /// Gets the number of times the bull has charged. + /// + public int PassNumber { get; init; } + + /// + /// Measures the player's bravery during the match. + /// + public double Bravery { get; init; } + + /// + /// Measures how much style the player showed during the match. + /// + public double Style { get; init; } + + /// + /// Gets the result of the player's last action. + /// + public ActionResult Result { get; init; } + } +} diff --git a/17 Bullfight/csharp/src/Program.cs b/17 Bullfight/csharp/src/Program.cs new file mode 100644 index 00000000..17da736f --- /dev/null +++ b/17 Bullfight/csharp/src/Program.cs @@ -0,0 +1,56 @@ +using System; + +namespace Game +{ + class Program + { + static void Main() + { + Controller.StartGame(); + + var random = new Random(); + var match = Rules.StartMatch(random); + View.ShowStartingConditions(match.Conditions); + + while (match.Result == ActionResult.FightContinues) + { + match = match with { PassNumber = match.PassNumber + 1 }; + + View.StartOfPass(match.PassNumber); + + var (action, riskLevel) = Controller.GetPlayerIntention(match.PassNumber); + match = action switch + { + Action.Dodge => Rules.TryDodge(random, riskLevel, match), + Action.Kill => Rules.TryKill(random, riskLevel, match), + _ => Rules.Panic(match) + }; + + var first = true; + while (match.Result == ActionResult.BullGoresPlayer) + { + View.ShowPlayerGored(action == Action.Panic, first); + first = false; + + match = Rules.TrySurvive(random, match); + if (match.Result == ActionResult.FightContinues) + { + View.ShowPlayerSurvives(); + + if (Controller.PlayerRunsFromRing()) + { + match = Rules.Flee(match); + } + else + { + View.ShowPlayerFoolhardy(); + match = Rules.IgnoreInjury(random, action, match); + } + } + } + } + + View.ShowFinalResult(match.Result, match.Bravery, Rules.GetReward(random, match)); + } + } +} diff --git a/17 Bullfight/csharp/src/Quality.cs b/17 Bullfight/csharp/src/Quality.cs new file mode 100644 index 00000000..ee7bf6d9 --- /dev/null +++ b/17 Bullfight/csharp/src/Quality.cs @@ -0,0 +1,19 @@ +namespace Game +{ + /// + /// Enumerates the different levels of quality in the game. + /// + /// + /// Quality applies both to the bull and to the help received from the + /// toreadores and picadores. Note that the ordinal values are significant + /// (these are used in various calculations). + /// + public enum Quality + { + Superb = 1, + Good = 2, + Fair = 3, + Poor = 4, + Awful = 5 + } +} diff --git a/17 Bullfight/csharp/src/Reward.cs b/17 Bullfight/csharp/src/Reward.cs new file mode 100644 index 00000000..295789be --- /dev/null +++ b/17 Bullfight/csharp/src/Reward.cs @@ -0,0 +1,13 @@ +namespace Game +{ + /// + /// Enumerates the different things the player can be awarded. + /// + public enum Reward + { + Nothing, + OneEar, + TwoEars, + CarriedFromRing + } +} diff --git a/17 Bullfight/csharp/src/RiskLevel.cs b/17 Bullfight/csharp/src/RiskLevel.cs new file mode 100644 index 00000000..8048f663 --- /dev/null +++ b/17 Bullfight/csharp/src/RiskLevel.cs @@ -0,0 +1,12 @@ +namespace Game +{ + /// + /// Enumerates the different levels of risk for manoeuvres in the game. + /// + public enum RiskLevel + { + Low, + Medium, + High + } +} diff --git a/17 Bullfight/csharp/src/Rules.cs b/17 Bullfight/csharp/src/Rules.cs new file mode 100644 index 00000000..463af1ed --- /dev/null +++ b/17 Bullfight/csharp/src/Rules.cs @@ -0,0 +1,258 @@ +using System; + +namespace Game +{ + /// + /// Provides functions implementing the rules of the game. + /// + public static class Rules + { + /// + /// Gets the state of a new match. + /// + /// + /// The random number generator. + /// + public static MatchState StartMatch(Random random) + { + var bullQuality = GetBullQuality(); + var toreadorePerformance = GetHelpQuality(); + var picadorePerformance = GetHelpQuality(); + + var conditions = new MatchConditions + { + BullQuality = bullQuality, + ToreadorePerformance = toreadorePerformance, + PicadorePerformance = picadorePerformance, + ToreadoresKilled = GetHumanCasualties(toreadorePerformance), + PicadoresKilled = GetHumanCasualties(picadorePerformance), + HorsesKilled = GetHorseCasualties(picadorePerformance) + }; + + return new MatchState(conditions) + { + Bravery = 1.0, + Style = 1.0 + }; + + Quality GetBullQuality() => + (Quality)random.Next(1, 6); + + Quality GetHelpQuality() => + ((3.0 / (int)bullQuality) * random.NextDouble()) switch + { + < 0.37 => Quality.Superb, + < 0.50 => Quality.Good, + < 0.63 => Quality.Fair, + < 0.87 => Quality.Poor, + _ => Quality.Awful + }; + + int GetHumanCasualties(Quality performance) => + performance switch + { + Quality.Poor => random.Next(0, 2), + Quality.Awful => random.Next(1, 3), + _ => 0 + }; + + int GetHorseCasualties(Quality performance) => + performance switch + { + // NOTE: The code for displaying a single horse casuality + // following a poor picadore peformance was unreachable + // in the original BASIC version. I've assumed this was + // a bug. + Quality.Poor => 1, + Quality.Awful => random.Next(1, 3), + _ => 0 + }; + } + + /// + /// Determines the result when the player attempts to dodge the bull. + /// + /// + /// The random number generator. + /// + /// + /// The level of risk in the dodge manoeuvre chosen. + /// + /// + /// The current match state. + /// + /// + /// The updated match state. + /// + public static MatchState TryDodge(Random random, RiskLevel riskLevel, MatchState match) + { + var difficultyModifier = riskLevel switch + { + RiskLevel.High => 3.0, + RiskLevel.Medium => 2.0, + _ => 0.5 + }; + + var outcome = (GetBullStrength(match) + (difficultyModifier / 10)) * random.NextDouble() / + ((GetAssisstance(match) + (match.PassNumber / 10.0)) * 5); + + return outcome < 0.51 ? + match with { Result = ActionResult.FightContinues, Style = match.Style + difficultyModifier } : + match with { Result = ActionResult.BullGoresPlayer }; + } + + /// + /// Determines the result when the player attempts to kill the bull. + /// + /// + /// The random number generator. + /// + /// + /// The level of risk in the manoeuvre chosen. + /// + /// + /// The current match state. + /// + /// + /// The updated match state. + /// + public static MatchState TryKill(Random random, RiskLevel riskLevel, MatchState match) + { + var K = GetBullStrength(match) * 10 * random.NextDouble() / (GetAssisstance(match) * 5 * match.PassNumber); + + return ((riskLevel == RiskLevel.High && K > 0.2) || K > 0.8) ? + match with { Result = ActionResult.BullGoresPlayer } : + match with { Result = ActionResult.PlayerKillsBull }; + } + + /// + /// Determines if the player survives being gored by the bull. + /// + /// + /// The random number generator. + /// + /// + /// The current match state. + /// + /// + /// The updated match state. + /// + public static MatchState TrySurvive(Random random, MatchState match) => + (random.Next(2) == 0) ? + match with { Result = ActionResult.BullKillsPlayer, Bravery = 1.5 } : + match with { Result = ActionResult.FightContinues }; + + /// + /// Determines the result when the player panics and fails to do anything. + /// + /// + /// The match state. + /// + public static MatchState Panic(MatchState match) => + match with { Result = ActionResult.BullGoresPlayer }; + + /// + /// Determines the result when the player flees the ring. + /// + /// + /// The current match state. + /// + /// + /// The updated match state. + /// + public static MatchState Flee(MatchState match) => + match with { Result = ActionResult.PlayerFlees, Bravery = 0.0 }; + + /// + /// Determines the result when the player decides to continue fighting + /// following an injury. + /// + /// + /// The random number generator. + /// + /// + /// The action the player took that lead to the injury. + /// + /// + /// The current match state. + /// + /// + /// The updated match state. + /// + public static MatchState IgnoreInjury(Random random, Action action, MatchState match) => + (random.Next(2) == 0) ? + match with { Result = action == Action.Dodge ? ActionResult.FightContinues : ActionResult.Draw, Bravery = 2.0 } : + match with { Result = ActionResult.BullGoresPlayer }; + + /// + /// Gets the player's reward for completing a match. + /// + /// + /// The random number generator. + /// + /// + /// The final match state. + /// + public static Reward GetReward(Random random, MatchState match) + { + var score = CalculateScore(); + + if (score * random.NextDouble() < 2.4) + return Reward.Nothing; + else + if (score * random.NextDouble() < 4.9) + return Reward.OneEar; + else + if (score * random.NextDouble() < 7.4) + return Reward.TwoEars; + else + return Reward.CarriedFromRing; + + double CalculateScore() + { + var score = 4.5; + + // Style + score += match.Style / 6; + + // Assisstance + score -= GetAssisstance(match) * 2.5; + + // Courage + score += 4 * match.Bravery; + + // Kill bonus + score += (match.Result == ActionResult.PlayerKillsBull) ? 4 : 2; + + // Match length + score -= Math.Pow(match.PassNumber, 2) / 120; + + // Difficulty + score -= (int)match.Conditions.BullQuality; + + return score; + } + } + + /// + /// Calculates the strength of the bull in a match. + /// + private static double GetBullStrength(MatchState match) => + 6 - (int)match.Conditions.BullQuality; + + /// + /// Gets the amount of assistance received from the toreadores and + /// picadores in a match. + /// + private static double GetAssisstance(MatchState match) => + GetPerformanceBonus(match.Conditions.ToreadorePerformance) + + GetPerformanceBonus(match.Conditions.PicadorePerformance); + + /// + /// Gets the amount of assistance rendered by a performance of the + /// given quality. + /// + private static double GetPerformanceBonus(Quality performance) => + (6 - (int)performance) * 0.1; + } +} diff --git a/17 Bullfight/csharp/src/View.cs b/17 Bullfight/csharp/src/View.cs new file mode 100644 index 00000000..2bff39c8 --- /dev/null +++ b/17 Bullfight/csharp/src/View.cs @@ -0,0 +1,240 @@ +using System; + +namespace Game +{ + /// + /// Contains functions for displaying information to the user. + /// + public static class View + { + private static readonly string[] QualityString = { "SUPERB", "GOOD", "FAIR", "POOR", "AWFUL" }; + + public static void ShowBanner() + { + Console.WriteLine(" BULL"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowInstructions() + { + Console.WriteLine("HELLO, ALL YOU BLOODLOVERS AND AFICIONADOS."); + Console.WriteLine("HERE IS YOUR BIG CHANCE TO KILL A BULL."); + Console.WriteLine(); + Console.WriteLine("ON EACH PASS OF THE BULL, YOU MAY TRY"); + Console.WriteLine("0 - VERONICA (DANGEROUS INSIDE MOVE OF THE CAPE)"); + Console.WriteLine("1 - LESS DANGEROUS OUTSIDE MOVE OF THE CAPE"); + Console.WriteLine("2 - ORDINARY SWIRL OF THE CAPE."); + Console.WriteLine(); + Console.WriteLine("INSTEAD OF THE ABOVE, YOU MAY TRY TO KILL THE BULL"); + Console.WriteLine("ON ANY TURN: 4 (OVER THE HORNS), 5 (IN THE CHEST)."); + Console.WriteLine("BUT IF I WERE YOU,"); + Console.WriteLine("I WOULDN'T TRY IT BEFORE THE SEVENTH PASS."); + Console.WriteLine(); + Console.WriteLine("THE CROWD WILL DETERMINE WHAT AWARD YOU DESERVE"); + Console.WriteLine("(POSTHUMOUSLY IF NECESSARY)."); + Console.WriteLine("THE BRAVER YOU ARE, THE BETTER THE AWARD YOU RECEIVE."); + Console.WriteLine(); + Console.WriteLine("THE BETTER THE JOB THE PICADORES AND TOREADORES DO,"); + Console.WriteLine("THE BETTER YOUR CHANCES ARE."); + } + + public static void ShowSeparator() + { + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowStartingConditions(MatchConditions conditions) + { + ShowBullQuality(); + ShowHelpQuality("TOREADORES", conditions.ToreadorePerformance, conditions.ToreadoresKilled, 0); + ShowHelpQuality("PICADORES", conditions.PicadorePerformance, conditions.PicadoresKilled, conditions.HorsesKilled); + + void ShowBullQuality() + { + Console.WriteLine($"YOU HAVE DRAWN A {QualityString[(int)conditions.BullQuality - 1]} BULL."); + + if (conditions.BullQuality > Quality.Poor) + { + Console.WriteLine("YOU'RE LUCKY"); + } + else + if (conditions.BullQuality < Quality.Good) + { + Console.WriteLine("GOOD LUCK. YOU'LL NEED IT."); + Console.WriteLine(); + } + + Console.WriteLine(); + } + + static void ShowHelpQuality(string helperName, Quality helpQuality, int helpersKilled, int horsesKilled) + { + Console.WriteLine($"THE {helperName} DID A {QualityString[(int)helpQuality - 1]} JOB."); + + // NOTE: The code below makes some *strong* assumptions about + // how the casualty numbers were generated. It is written + // this way to preserve the behaviour of the original BASIC + // version, but it would make more sense ignore the helpQuality + // parameter and just use the provided numbers to decide what + // to display. + switch (helpQuality) + { + case Quality.Poor: + if (horsesKilled > 0) + Console.WriteLine($"ONE OF THE HORSES OF THE {helperName} WAS KILLED."); + + if (helpersKilled > 0) + Console.WriteLine($"ONE OF THE {helperName} WAS KILLED."); + break; + + case Quality.Awful: + if (horsesKilled > 0) + Console.WriteLine($" {horsesKilled} OF THE HORSES OF THE {helperName} KILLED."); + + Console.WriteLine($" {helpersKilled} OF THE {helperName} KILLED."); + break; + } + } + } + + public static void StartOfPass(int passNumber) + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine($"PASS NUMBER {passNumber}"); + } + + public static void ShowPlayerGored(bool playerPanicked, bool firstGoring) + { + Console.WriteLine((playerPanicked, firstGoring) switch + { + (true, true) => "YOU PANICKED. THE BULL GORED YOU.", + (false, true) => "THE BULL HAS GORED YOU!", + (_, false) => "YOU ARE GORED AGAIN!" + }); + } + + public static void ShowPlayerSurvives() + { + Console.WriteLine("YOU ARE STILL ALIVE."); + Console.WriteLine(); + } + + public static void ShowPlayerFoolhardy() + { + Console.WriteLine("YOU ARE BRAVE. STUPID, BUT BRAVE."); + } + + public static void ShowFinalResult(ActionResult result, double bravery, Reward reward) + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + + switch (result) + { + case ActionResult.PlayerFlees: + Console.WriteLine("COWARD"); + break; + case ActionResult.BullKillsPlayer: + Console.WriteLine("YOU ARE DEAD."); + break; + case ActionResult.PlayerKillsBull: + Console.WriteLine("YOU KILLED THE BULL!"); + break; + } + + if (result == ActionResult.PlayerFlees) + { + Console.WriteLine("THE CROWD BOOS FOR TEN MINUTES. IF YOU EVER DARE TO SHOW"); + Console.WriteLine("YOUR FACE IN A RING AGAIN, THEY SWEAR THEY WILL KILL YOU--"); + Console.WriteLine("UNLESS THE BULL DOES FIRST."); + } + else + { + if (bravery == 2) // You were gored by the bull but survived (and did not later die or flee) + Console.WriteLine("THE CROWD CHEERS WILDLY!"); + else + if (result == ActionResult.PlayerKillsBull) + { + Console.WriteLine("THE CROWD CHEERS!"); + Console.WriteLine(); + } + + Console.WriteLine("THE CROWD AWARDS YOU"); + switch (reward) + { + case Reward.Nothing: + Console.WriteLine("NOTHING AT ALL."); + break; + case Reward.OneEar: + Console.WriteLine("ONE EAR OF THE BULL."); + break; + case Reward.TwoEars: + Console.WriteLine("BOTH EARS OF THE BULL!"); + Console.WriteLine("OLE!"); + break; + default: + Console.WriteLine("OLE! YOU ARE 'MUY HOMBRE'!! OLE! OLE!"); + break; + } + } + + Console.WriteLine(); + Console.WriteLine("ADIOS"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + public static void PromptShowInstructions() + { + Console.Write("DO YOU WANT INSTRUCTIONS? "); + } + + public static void PromptKillBull() + { + Console.WriteLine("THE BULL IS CHARGING AT YOU! YOU ARE THE MATADOR--"); + Console.Write("DO YOU WANT TO KILL THE BULL? "); + } + + public static void PromptKillBullBrief() + { + Console.Write("HERE COMES THE BULL. TRY FOR A KILL? "); + } + + public static void PromptKillMethod() + { + Console.WriteLine(); + Console.WriteLine("IT IS THE MOMENT OF TRUTH."); + Console.WriteLine(); + + Console.Write("HOW DO YOU TRY TO KILL THE BULL? "); + } + + public static void PromptCapeMove() + { + Console.Write("WHAT MOVE DO YOU MAKE WITH THE CAPE? "); + } + + public static void PromptCapeMoveBrief() + { + Console.Write("CAPE MOVE? "); + } + + public static void PromptDontPanic() + { + Console.WriteLine("DON'T PANIC, YOU IDIOT! PUT DOWN A CORRECT NUMBER"); + Console.Write("? "); + } + + public static void PromptRunFromRing() + { + Console.Write("DO YOU RUN FROM THE RING? "); + } + } +} From 6c4f019d40cf893c68b5adc2b36e28feaf38e9a4 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 23 Jul 2021 20:02:54 -0400 Subject: [PATCH 410/749] Reworked Bull Fight in a reactive style --- 17 Bullfight/csharp/Game.csproj | 2 +- 17 Bullfight/csharp/src/BullFight.cs | 220 +++++++++++++++ 17 Bullfight/csharp/src/Controller.cs | 9 +- .../csharp/src/Events/BullCharging.cs | 7 + 17 Bullfight/csharp/src/Events/Event.cs | 7 + .../csharp/src/Events/MatchCompleted.cs | 7 + .../csharp/src/Events/MatchStarted.cs | 13 + 17 Bullfight/csharp/src/Events/PlayerGored.cs | 7 + .../csharp/src/Events/PlayerSurvived.cs | 7 + 17 Bullfight/csharp/src/MatchConditions.cs | 41 --- 17 Bullfight/csharp/src/MatchState.cs | 28 -- 17 Bullfight/csharp/src/Mediator.cs | 48 ++++ 17 Bullfight/csharp/src/Program.cs | 74 +++-- 17 Bullfight/csharp/src/Rules.cs | 258 ------------------ 17 Bullfight/csharp/src/View.cs | 22 +- 15 files changed, 372 insertions(+), 378 deletions(-) create mode 100644 17 Bullfight/csharp/src/BullFight.cs create mode 100644 17 Bullfight/csharp/src/Events/BullCharging.cs create mode 100644 17 Bullfight/csharp/src/Events/Event.cs create mode 100644 17 Bullfight/csharp/src/Events/MatchCompleted.cs create mode 100644 17 Bullfight/csharp/src/Events/MatchStarted.cs create mode 100644 17 Bullfight/csharp/src/Events/PlayerGored.cs create mode 100644 17 Bullfight/csharp/src/Events/PlayerSurvived.cs delete mode 100644 17 Bullfight/csharp/src/MatchConditions.cs delete mode 100644 17 Bullfight/csharp/src/MatchState.cs create mode 100644 17 Bullfight/csharp/src/Mediator.cs delete mode 100644 17 Bullfight/csharp/src/Rules.cs diff --git a/17 Bullfight/csharp/Game.csproj b/17 Bullfight/csharp/Game.csproj index 849a99d4..36c64642 100644 --- a/17 Bullfight/csharp/Game.csproj +++ b/17 Bullfight/csharp/Game.csproj @@ -1,4 +1,4 @@ - + Exe net5.0 diff --git a/17 Bullfight/csharp/src/BullFight.cs b/17 Bullfight/csharp/src/BullFight.cs new file mode 100644 index 00000000..8df6ff8c --- /dev/null +++ b/17 Bullfight/csharp/src/BullFight.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; + +namespace Game +{ + /// + /// Provides a method for simulating a bull fight. + /// + public static class BullFight + { + /// + /// Begins a new fight. + /// + /// + /// Object used to communicate with the player. + /// + /// + /// The sequence of events that take place during the fight. + /// + /// + /// After receiving each event, the caller must invoke the appropriate + /// mediator method to inform this coroutine what to do next. Failure + /// to do so will result in an exception. + /// + public static IEnumerable Begin(Mediator mediator) + { + var random = new Random(); + var result = ActionResult.FightContinues; + + var bullQuality = GetBullQuality(); + var toreadorePerformance = GetHelpQuality(bullQuality); + var picadorePerformance = GetHelpQuality(bullQuality); + + var bullStrength = 6 - (int)bullQuality; + var assistanceLevel = (12 - (int)toreadorePerformance - (int)picadorePerformance) * 0.1; + var bravery = 1.0; + var style = 1.0; + var passNumber = 0; + + yield return new Events.MatchStarted( + bullQuality, + toreadorePerformance, + picadorePerformance, + GetHumanCasualties(toreadorePerformance), + GetHumanCasualties(picadorePerformance), + GetHorseCasualties(picadorePerformance)); + + while (result == ActionResult.FightContinues) + { + yield return new Events.BullCharging(++passNumber); + + var (action, riskLevel) = mediator.GetInput<(Action, RiskLevel)>(); + result = action switch + { + Action.Dodge => TryDodge(riskLevel), + Action.Kill => TryKill(riskLevel), + _ => Panic() + }; + + var first = true; + while (result == ActionResult.BullGoresPlayer) + { + yield return new Events.PlayerGored(action == Action.Panic, first); + first = false; + + result = TrySurvive(); + if (result == ActionResult.FightContinues) + { + yield return new Events.PlayerSurvived(); + + var runFromRing = mediator.GetInput(); + if (runFromRing) + result = Flee(); + else + result = IgnoreInjury(action); + } + } + } + + yield return new Events.MatchCompleted( + result, + bravery == 2, + GetReward()); + + Quality GetBullQuality() => + (Quality)random.Next(1, 6); + + Quality GetHelpQuality(Quality bullQuality) => + ((3.0 / (int)bullQuality) * random.NextDouble()) switch + { + < 0.37 => Quality.Superb, + < 0.50 => Quality.Good, + < 0.63 => Quality.Fair, + < 0.87 => Quality.Poor, + _ => Quality.Awful + }; + + int GetHumanCasualties(Quality performance) => + performance switch + { + Quality.Poor => random.Next(0, 2), + Quality.Awful => random.Next(1, 3), + _ => 0 + }; + + int GetHorseCasualties(Quality performance) => + performance switch + { + // NOTE: The code for displaying a single horse casuality + // following a poor picadore peformance was unreachable + // in the original BASIC version. I've assumed this was + // a bug. + Quality.Poor => 1, + Quality.Awful => random.Next(1, 3), + _ => 0 + }; + + ActionResult TryDodge(RiskLevel riskLevel) + { + var difficultyModifier = riskLevel switch + { + RiskLevel.High => 3.0, + RiskLevel.Medium => 2.0, + _ => 0.5 + }; + + var outcome = (bullStrength + (difficultyModifier / 10)) * random.NextDouble() / + ((assistanceLevel + (passNumber / 10.0)) * 5); + + if (outcome < 0.51) + { + style += difficultyModifier; + return ActionResult.FightContinues; + } + else + return ActionResult.BullGoresPlayer; + } + + ActionResult TryKill(RiskLevel riskLevel) + { + var luck = bullStrength * 10 * random.NextDouble() / (assistanceLevel * 5 * passNumber); + + return ((riskLevel == RiskLevel.High && luck > 0.2) || luck > 0.8) ? + ActionResult.BullGoresPlayer : ActionResult.PlayerKillsBull; + } + + ActionResult Panic() => + ActionResult.BullGoresPlayer; + + ActionResult TrySurvive() + { + if (random.Next(2) == 0) + { + bravery = 1.5; + return ActionResult.BullKillsPlayer; + } + else + return ActionResult.FightContinues; + } + + ActionResult Flee() + { + bravery = 0.0; + return ActionResult.PlayerFlees; + } + + ActionResult IgnoreInjury(Action action) + { + if (random.Next(2) == 0) + { + bravery = 2.0; + return action == Action.Dodge ? ActionResult.FightContinues : ActionResult.Draw; + } + else + return ActionResult.BullGoresPlayer; + } + + Reward GetReward() + { + var score = CalculateScore(); + + if (score * random.NextDouble() < 2.4) + return Reward.Nothing; + else + if (score * random.NextDouble() < 4.9) + return Reward.OneEar; + else + if (score * random.NextDouble() < 7.4) + return Reward.TwoEars; + else + return Reward.CarriedFromRing; + } + + double CalculateScore() + { + var score = 4.5; + + // Style + score += style / 6; + + // Assisstance + score -= assistanceLevel * 2.5; + + // Courage + score += 4 * bravery; + + // Kill bonus + score += (result == ActionResult.PlayerKillsBull) ? 4 : 2; + + // Match length + score -= Math.Pow(passNumber, 2) / 120; + + // Difficulty + score -= (int)bullQuality; + + return score; + } + } + } +} diff --git a/17 Bullfight/csharp/src/Controller.cs b/17 Bullfight/csharp/src/Controller.cs index 2355e247..c1441f9a 100644 --- a/17 Bullfight/csharp/src/Controller.cs +++ b/17 Bullfight/csharp/src/Controller.cs @@ -93,10 +93,15 @@ namespace Game /// /// True if the player flees; otherwise, false. /// - public static bool PlayerRunsFromRing() + public static bool GetPlayerRunsFromRing() { View.PromptRunFromRing(); - return GetYesOrNo(); + + var playerFlees = GetYesOrNo(); + if (!playerFlees) + View.ShowPlayerFoolhardy(); + + return playerFlees; } /// diff --git a/17 Bullfight/csharp/src/Events/BullCharging.cs b/17 Bullfight/csharp/src/Events/BullCharging.cs new file mode 100644 index 00000000..bc041c64 --- /dev/null +++ b/17 Bullfight/csharp/src/Events/BullCharging.cs @@ -0,0 +1,7 @@ +namespace Game.Events +{ + /// + /// Indicates that the bull is charing the player. + /// + public sealed record BullCharging(int PassNumber) : Event; +} diff --git a/17 Bullfight/csharp/src/Events/Event.cs b/17 Bullfight/csharp/src/Events/Event.cs new file mode 100644 index 00000000..e9a8a646 --- /dev/null +++ b/17 Bullfight/csharp/src/Events/Event.cs @@ -0,0 +1,7 @@ +namespace Game.Events +{ + /// + /// Common base class for all events in the game. + /// + public abstract record Event(); +} diff --git a/17 Bullfight/csharp/src/Events/MatchCompleted.cs b/17 Bullfight/csharp/src/Events/MatchCompleted.cs new file mode 100644 index 00000000..94c67d06 --- /dev/null +++ b/17 Bullfight/csharp/src/Events/MatchCompleted.cs @@ -0,0 +1,7 @@ +namespace Game.Events +{ + /// + /// Indicates that the fight has completed. + /// + public sealed record MatchCompleted(ActionResult Result, bool ExtremeBravery, Reward Reward) : Event; +} diff --git a/17 Bullfight/csharp/src/Events/MatchStarted.cs b/17 Bullfight/csharp/src/Events/MatchStarted.cs new file mode 100644 index 00000000..8141b617 --- /dev/null +++ b/17 Bullfight/csharp/src/Events/MatchStarted.cs @@ -0,0 +1,13 @@ +namespace Game.Events +{ + /// + /// Indicates that a new match has started. + /// + public sealed record MatchStarted( + Quality BullQuality, + Quality ToreadorePerformance, + Quality PicadorePerformance, + int ToreadoresKilled, + int PicadoresKilled, + int HorsesKilled) : Event; +} diff --git a/17 Bullfight/csharp/src/Events/PlayerGored.cs b/17 Bullfight/csharp/src/Events/PlayerGored.cs new file mode 100644 index 00000000..f55ae20d --- /dev/null +++ b/17 Bullfight/csharp/src/Events/PlayerGored.cs @@ -0,0 +1,7 @@ +namespace Game.Events +{ + /// + /// Indicates that the player has been gored by the bull. + /// + public sealed record PlayerGored(bool Panicked, bool FirstGoring) : Event; +} diff --git a/17 Bullfight/csharp/src/Events/PlayerSurvived.cs b/17 Bullfight/csharp/src/Events/PlayerSurvived.cs new file mode 100644 index 00000000..135a9a09 --- /dev/null +++ b/17 Bullfight/csharp/src/Events/PlayerSurvived.cs @@ -0,0 +1,7 @@ +namespace Game.Events +{ + /// + /// Indicates that the player has survived being gored by the bull. + /// + public sealed record PlayerSurvived() : Event; +} diff --git a/17 Bullfight/csharp/src/MatchConditions.cs b/17 Bullfight/csharp/src/MatchConditions.cs deleted file mode 100644 index 5d5d979c..00000000 --- a/17 Bullfight/csharp/src/MatchConditions.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Game -{ - /// - /// Stores the initial conditions of a match. - /// - public record MatchConditions - { - /// - /// Gets the quality of the bull. - /// - public Quality BullQuality { get; init; } - - /// - /// Gets the quality of help received from the toreadores. - /// - public Quality ToreadorePerformance { get; init; } - - /// - /// Gets the quality of help received from the picadores. - /// - public Quality PicadorePerformance { get; init; } - - /// - /// Gets the number of toreadores killed while preparing for the - /// final round. - /// - public int ToreadoresKilled { get; init; } - - /// - /// Gets the number of picadores killed while preparing for the - /// final round. - /// - public int PicadoresKilled { get; init; } - - /// - /// Gets the number of horses killed while preparing for the final - /// round. - /// - public int HorsesKilled { get; init; } - } -} diff --git a/17 Bullfight/csharp/src/MatchState.cs b/17 Bullfight/csharp/src/MatchState.cs deleted file mode 100644 index 3eae6d5d..00000000 --- a/17 Bullfight/csharp/src/MatchState.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Game -{ - /// - /// Stores the current state of the match. - /// - public record MatchState(MatchConditions Conditions) - { - /// - /// Gets the number of times the bull has charged. - /// - public int PassNumber { get; init; } - - /// - /// Measures the player's bravery during the match. - /// - public double Bravery { get; init; } - - /// - /// Measures how much style the player showed during the match. - /// - public double Style { get; init; } - - /// - /// Gets the result of the player's last action. - /// - public ActionResult Result { get; init; } - } -} diff --git a/17 Bullfight/csharp/src/Mediator.cs b/17 Bullfight/csharp/src/Mediator.cs new file mode 100644 index 00000000..c9d4e298 --- /dev/null +++ b/17 Bullfight/csharp/src/Mediator.cs @@ -0,0 +1,48 @@ +using System.Diagnostics; + +namespace Game +{ + /// + /// Facilitates sending messages between the two game loops. + /// + /// + /// This class serves as a little piece of glue in between the main program + /// loop and the bull fight coroutine. When the main program calls one of + /// its methods, the mediator creates the appropriate input data that the + /// bull fight coroutine later retrieves with . + /// + public class Mediator + { + private object? m_input; + + public void Dodge(RiskLevel riskLevel) => + m_input = (Action.Dodge, riskLevel); + + public void Kill(RiskLevel riskLevel) => + m_input = (Action.Kill, riskLevel); + + public void Panic() => + m_input = (Action.Panic, default(RiskLevel)); + + public void RunFromRing() => + m_input = true; + + public void ContinueFighting() => + m_input = false; + + /// + /// Gets the next input from the user. + /// + /// + /// The type of input to receive. + /// + public T GetInput() + { + Debug.Assert(m_input is not null, "No input received"); + Debug.Assert(m_input.GetType() == typeof(T), "Invalid input received"); + var result = (T)m_input; + m_input = null; + return result; + } + } +} diff --git a/17 Bullfight/csharp/src/Program.cs b/17 Bullfight/csharp/src/Program.cs index 17da736f..d3f3760b 100644 --- a/17 Bullfight/csharp/src/Program.cs +++ b/17 Bullfight/csharp/src/Program.cs @@ -1,6 +1,4 @@ -using System; - -namespace Game +namespace Game { class Program { @@ -8,49 +6,49 @@ namespace Game { Controller.StartGame(); - var random = new Random(); - var match = Rules.StartMatch(random); - View.ShowStartingConditions(match.Conditions); - - while (match.Result == ActionResult.FightContinues) + var mediator = new Mediator(); + foreach (var evt in BullFight.Begin(mediator)) { - match = match with { PassNumber = match.PassNumber + 1 }; - - View.StartOfPass(match.PassNumber); - - var (action, riskLevel) = Controller.GetPlayerIntention(match.PassNumber); - match = action switch + switch (evt) { - Action.Dodge => Rules.TryDodge(random, riskLevel, match), - Action.Kill => Rules.TryKill(random, riskLevel, match), - _ => Rules.Panic(match) - }; + case Events.MatchStarted matchStarted: + View.ShowStartingConditions(matchStarted); + break; - var first = true; - while (match.Result == ActionResult.BullGoresPlayer) - { - View.ShowPlayerGored(action == Action.Panic, first); - first = false; + case Events.BullCharging bullCharging: + View.ShowStartOfPass(bullCharging.PassNumber); + var (action, riskLevel) = Controller.GetPlayerIntention(bullCharging.PassNumber); + switch (action) + { + case Action.Dodge: + mediator.Dodge(riskLevel); + break; + case Action.Kill: + mediator.Kill(riskLevel); + break; + case Action.Panic: + mediator.Panic(); + break; + } + break; - match = Rules.TrySurvive(random, match); - if (match.Result == ActionResult.FightContinues) - { + case Events.PlayerGored playerGored: + View.ShowPlayerGored(playerGored.Panicked, playerGored.FirstGoring); + break; + + case Events.PlayerSurvived: View.ShowPlayerSurvives(); - - if (Controller.PlayerRunsFromRing()) - { - match = Rules.Flee(match); - } + if (Controller.GetPlayerRunsFromRing()) + mediator.RunFromRing(); else - { - View.ShowPlayerFoolhardy(); - match = Rules.IgnoreInjury(random, action, match); - } - } + mediator.ContinueFighting(); + break; + + case Events.MatchCompleted matchCompleted: + View.ShowFinalResult(matchCompleted.Result, matchCompleted.ExtremeBravery, matchCompleted.Reward); + break; } } - - View.ShowFinalResult(match.Result, match.Bravery, Rules.GetReward(random, match)); } } } diff --git a/17 Bullfight/csharp/src/Rules.cs b/17 Bullfight/csharp/src/Rules.cs deleted file mode 100644 index 463af1ed..00000000 --- a/17 Bullfight/csharp/src/Rules.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; - -namespace Game -{ - /// - /// Provides functions implementing the rules of the game. - /// - public static class Rules - { - /// - /// Gets the state of a new match. - /// - /// - /// The random number generator. - /// - public static MatchState StartMatch(Random random) - { - var bullQuality = GetBullQuality(); - var toreadorePerformance = GetHelpQuality(); - var picadorePerformance = GetHelpQuality(); - - var conditions = new MatchConditions - { - BullQuality = bullQuality, - ToreadorePerformance = toreadorePerformance, - PicadorePerformance = picadorePerformance, - ToreadoresKilled = GetHumanCasualties(toreadorePerformance), - PicadoresKilled = GetHumanCasualties(picadorePerformance), - HorsesKilled = GetHorseCasualties(picadorePerformance) - }; - - return new MatchState(conditions) - { - Bravery = 1.0, - Style = 1.0 - }; - - Quality GetBullQuality() => - (Quality)random.Next(1, 6); - - Quality GetHelpQuality() => - ((3.0 / (int)bullQuality) * random.NextDouble()) switch - { - < 0.37 => Quality.Superb, - < 0.50 => Quality.Good, - < 0.63 => Quality.Fair, - < 0.87 => Quality.Poor, - _ => Quality.Awful - }; - - int GetHumanCasualties(Quality performance) => - performance switch - { - Quality.Poor => random.Next(0, 2), - Quality.Awful => random.Next(1, 3), - _ => 0 - }; - - int GetHorseCasualties(Quality performance) => - performance switch - { - // NOTE: The code for displaying a single horse casuality - // following a poor picadore peformance was unreachable - // in the original BASIC version. I've assumed this was - // a bug. - Quality.Poor => 1, - Quality.Awful => random.Next(1, 3), - _ => 0 - }; - } - - /// - /// Determines the result when the player attempts to dodge the bull. - /// - /// - /// The random number generator. - /// - /// - /// The level of risk in the dodge manoeuvre chosen. - /// - /// - /// The current match state. - /// - /// - /// The updated match state. - /// - public static MatchState TryDodge(Random random, RiskLevel riskLevel, MatchState match) - { - var difficultyModifier = riskLevel switch - { - RiskLevel.High => 3.0, - RiskLevel.Medium => 2.0, - _ => 0.5 - }; - - var outcome = (GetBullStrength(match) + (difficultyModifier / 10)) * random.NextDouble() / - ((GetAssisstance(match) + (match.PassNumber / 10.0)) * 5); - - return outcome < 0.51 ? - match with { Result = ActionResult.FightContinues, Style = match.Style + difficultyModifier } : - match with { Result = ActionResult.BullGoresPlayer }; - } - - /// - /// Determines the result when the player attempts to kill the bull. - /// - /// - /// The random number generator. - /// - /// - /// The level of risk in the manoeuvre chosen. - /// - /// - /// The current match state. - /// - /// - /// The updated match state. - /// - public static MatchState TryKill(Random random, RiskLevel riskLevel, MatchState match) - { - var K = GetBullStrength(match) * 10 * random.NextDouble() / (GetAssisstance(match) * 5 * match.PassNumber); - - return ((riskLevel == RiskLevel.High && K > 0.2) || K > 0.8) ? - match with { Result = ActionResult.BullGoresPlayer } : - match with { Result = ActionResult.PlayerKillsBull }; - } - - /// - /// Determines if the player survives being gored by the bull. - /// - /// - /// The random number generator. - /// - /// - /// The current match state. - /// - /// - /// The updated match state. - /// - public static MatchState TrySurvive(Random random, MatchState match) => - (random.Next(2) == 0) ? - match with { Result = ActionResult.BullKillsPlayer, Bravery = 1.5 } : - match with { Result = ActionResult.FightContinues }; - - /// - /// Determines the result when the player panics and fails to do anything. - /// - /// - /// The match state. - /// - public static MatchState Panic(MatchState match) => - match with { Result = ActionResult.BullGoresPlayer }; - - /// - /// Determines the result when the player flees the ring. - /// - /// - /// The current match state. - /// - /// - /// The updated match state. - /// - public static MatchState Flee(MatchState match) => - match with { Result = ActionResult.PlayerFlees, Bravery = 0.0 }; - - /// - /// Determines the result when the player decides to continue fighting - /// following an injury. - /// - /// - /// The random number generator. - /// - /// - /// The action the player took that lead to the injury. - /// - /// - /// The current match state. - /// - /// - /// The updated match state. - /// - public static MatchState IgnoreInjury(Random random, Action action, MatchState match) => - (random.Next(2) == 0) ? - match with { Result = action == Action.Dodge ? ActionResult.FightContinues : ActionResult.Draw, Bravery = 2.0 } : - match with { Result = ActionResult.BullGoresPlayer }; - - /// - /// Gets the player's reward for completing a match. - /// - /// - /// The random number generator. - /// - /// - /// The final match state. - /// - public static Reward GetReward(Random random, MatchState match) - { - var score = CalculateScore(); - - if (score * random.NextDouble() < 2.4) - return Reward.Nothing; - else - if (score * random.NextDouble() < 4.9) - return Reward.OneEar; - else - if (score * random.NextDouble() < 7.4) - return Reward.TwoEars; - else - return Reward.CarriedFromRing; - - double CalculateScore() - { - var score = 4.5; - - // Style - score += match.Style / 6; - - // Assisstance - score -= GetAssisstance(match) * 2.5; - - // Courage - score += 4 * match.Bravery; - - // Kill bonus - score += (match.Result == ActionResult.PlayerKillsBull) ? 4 : 2; - - // Match length - score -= Math.Pow(match.PassNumber, 2) / 120; - - // Difficulty - score -= (int)match.Conditions.BullQuality; - - return score; - } - } - - /// - /// Calculates the strength of the bull in a match. - /// - private static double GetBullStrength(MatchState match) => - 6 - (int)match.Conditions.BullQuality; - - /// - /// Gets the amount of assistance received from the toreadores and - /// picadores in a match. - /// - private static double GetAssisstance(MatchState match) => - GetPerformanceBonus(match.Conditions.ToreadorePerformance) + - GetPerformanceBonus(match.Conditions.PicadorePerformance); - - /// - /// Gets the amount of assistance rendered by a performance of the - /// given quality. - /// - private static double GetPerformanceBonus(Quality performance) => - (6 - (int)performance) * 0.1; - } -} diff --git a/17 Bullfight/csharp/src/View.cs b/17 Bullfight/csharp/src/View.cs index 2bff39c8..0cc627b8 100644 --- a/17 Bullfight/csharp/src/View.cs +++ b/17 Bullfight/csharp/src/View.cs @@ -47,22 +47,22 @@ namespace Game Console.WriteLine(); } - public static void ShowStartingConditions(MatchConditions conditions) + public static void ShowStartingConditions(Events.MatchStarted matchStarted) { ShowBullQuality(); - ShowHelpQuality("TOREADORES", conditions.ToreadorePerformance, conditions.ToreadoresKilled, 0); - ShowHelpQuality("PICADORES", conditions.PicadorePerformance, conditions.PicadoresKilled, conditions.HorsesKilled); + ShowHelpQuality("TOREADORES", matchStarted.ToreadorePerformance, matchStarted.ToreadoresKilled, 0); + ShowHelpQuality("PICADORES", matchStarted.PicadorePerformance, matchStarted.PicadoresKilled, matchStarted.HorsesKilled); void ShowBullQuality() { - Console.WriteLine($"YOU HAVE DRAWN A {QualityString[(int)conditions.BullQuality - 1]} BULL."); + Console.WriteLine($"YOU HAVE DRAWN A {QualityString[(int)matchStarted.BullQuality - 1]} BULL."); - if (conditions.BullQuality > Quality.Poor) + if (matchStarted.BullQuality > Quality.Poor) { Console.WriteLine("YOU'RE LUCKY"); } else - if (conditions.BullQuality < Quality.Good) + if (matchStarted.BullQuality < Quality.Good) { Console.WriteLine("GOOD LUCK. YOU'LL NEED IT."); Console.WriteLine(); @@ -86,9 +86,11 @@ namespace Game case Quality.Poor: if (horsesKilled > 0) Console.WriteLine($"ONE OF THE HORSES OF THE {helperName} WAS KILLED."); - + if (helpersKilled > 0) Console.WriteLine($"ONE OF THE {helperName} WAS KILLED."); + else + Console.WriteLine($"NO {helperName} WERE KILLED."); break; case Quality.Awful: @@ -101,7 +103,7 @@ namespace Game } } - public static void StartOfPass(int passNumber) + public static void ShowStartOfPass(int passNumber) { Console.WriteLine(); Console.WriteLine(); @@ -129,7 +131,7 @@ namespace Game Console.WriteLine("YOU ARE BRAVE. STUPID, BUT BRAVE."); } - public static void ShowFinalResult(ActionResult result, double bravery, Reward reward) + public static void ShowFinalResult(ActionResult result, bool extremeBravery, Reward reward) { Console.WriteLine(); Console.WriteLine(); @@ -156,7 +158,7 @@ namespace Game } else { - if (bravery == 2) // You were gored by the bull but survived (and did not later die or flee) + if (extremeBravery) Console.WriteLine("THE CROWD CHEERS WILDLY!"); else if (result == ActionResult.PlayerKillsBull) From e135653d12f34bcf51e2716a7288333d64c69dd5 Mon Sep 17 00:00:00 2001 From: DWidel <49377673+DWidel@users.noreply.github.com> Date: Thu, 19 Aug 2021 18:32:48 -0400 Subject: [PATCH 411/749] Add files via upload Reverse ported to VB.NET --- 73 Reverse/vbnet/Reverse.vb | 195 ++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 73 Reverse/vbnet/Reverse.vb diff --git a/73 Reverse/vbnet/Reverse.vb b/73 Reverse/vbnet/Reverse.vb new file mode 100644 index 00000000..33148795 --- /dev/null +++ b/73 Reverse/vbnet/Reverse.vb @@ -0,0 +1,195 @@ +Imports System + +Module Reverse + + + ' VB.NET Port of Reverse from book BASIC COMPUTER GAMES. + ' Console app for .NET Core 3.1 + ' Some simplification and error checking was added. + ' David Widel + + Const NumberOfDigits As Integer = 9 + + Private Numbers As New Generic.List(Of Integer) + + + + Sub Main(args As String()) + + DisplayIntro() + + Console.WriteLine("DO YOU WANT THE RULES? (Y/N)") + If Console.ReadKey(True).Key = ConsoleKey.Y Then + DisplayRules() + End If + + + + Dim playing As Boolean = True + + Do While (playing) ' New game loop. + + InitializeRandomNumberList() + + Console.WriteLine("HERE WE GO ... THE LIST IS:") + DisplayNumbers() + + Dim Counter As Integer = 0 + + While True ' Turn loop. + + Dim ReverseNumber As Integer = GetHowManyToReverse() + If ReverseNumber = 0 Then + If Not TryAgain() Then + playing = False + End If + Continue Do + End If + + PerformReverse(ReverseNumber) + Counter += 1 + DisplayNumbers() + + If DidPlayerWin() Then + Console.WriteLine("YOU WON IN " & Counter.ToString & " MOVES") + If Not TryAgain() Then + Console.WriteLine("O.K. HOPE YOU HAD FUN!!") + playing = False + End If + Continue Do + End If + + End While + + Loop + + + + + End Sub + + Sub DisplayIntro() + Console.WriteLine("REVERSE") + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + Console.WriteLine("REVERSE -- A GAME OF SKILL") + + + End Sub + + Sub DisplayRules() + + Console.WriteLine("THIS IS THE GAME OF REVERSE. TO WIN, ALL YOU HAVE") + Console.WriteLine("TO DO IS ARRANGE A LIST OF NUMBERS (1 THROUGH " & NumberOfDigits.ToString & ")") + Console.WriteLine("IN NUMERICAL ORDER FROM LEFT TO RIGHT. TO MOVE, YOU") + Console.WriteLine("TELL ME HOW MANY NUMBERS (COUNTING FROM THE LEFT) TO") + Console.WriteLine("REVERSE. FOR EXAMPLE, IF THE CURRENT LIST IS:") + Console.WriteLine() + Console.WriteLine("2 3 4 5 1 6 7 8 9") + Console.WriteLine() + Console.WriteLine("AND YOU REVERSE 4, THE RESULT WILL BE:") + Console.WriteLine() + Console.WriteLine("5 4 3 2 1 6 7 8 9") + Console.WriteLine() + Console.WriteLine("NOW IF YOU REVERSE 5, YOU WIN!") + Console.WriteLine() + Console.WriteLine("1 2 3 4 5 6 7 8 9") + Console.WriteLine() + Console.WriteLine() + Console.WriteLine() + Console.WriteLine("NO DOUBT YOU WILL LIKE THIS GAME, BUT") + Console.WriteLine("IF YOU WANT TO QUIT, REVERSE O (ZERO).") + Console.WriteLine() + + End Sub + + Sub InitializeRandomNumberList() + + Dim R As New Random + Numbers.Clear() + + Do Until Numbers.Count = NumberOfDigits + + Dim NewNumber = R.Next(1, NumberOfDigits + 1) 'Lower bound is inclusive, Upper bound is exclusive + + If Not Numbers.Contains(NewNumber) Then + Numbers.Add(NewNumber) + End If + + Loop + + + If DidPlayerWin() Then + Numbers.Reverse() + End If + + End Sub + + Private Sub DisplayNumbers() + For i As Integer = 0 To Numbers.Count - 1 + Console.Write(Numbers(i).ToString(" #")) + Next + Console.WriteLine() + End Sub + + Function GetHowManyToReverse() As Integer + Console.WriteLine("HOW MANY SHALL I REVERSE?") + + Do + + Dim K = Console.ReadLine + Dim ReverseNumber As Integer + + If Integer.TryParse(K, ReverseNumber) Then + If ReverseNumber <= NumberOfDigits Then + Return ReverseNumber + Else + Console.WriteLine("OOPS! TOO MANY! I CAN REVERSE AT MOST " & NumberOfDigits.ToString) + End If + Else + 'Added check. + Console.WriteLine("OOPS! NUMBERS PLEASE!") + End If + + Loop + + End Function + + Sub PerformReverse(ReverseNumber As Integer) + + ' We will make pointers to the 2 digits to swap, swap them, and converge the pointers. + Dim LowerPointer As Integer = 1 + Dim UpperPointer As Integer = ReverseNumber + + Do + 'Since our list begins at 0 we must always subtract one to access a digit. + Dim temp As Integer = Numbers(LowerPointer - 1) + Numbers(LowerPointer - 1) = Numbers(UpperPointer - 1) + Numbers(UpperPointer - 1) = temp + LowerPointer += 1 + UpperPointer -= 1 + + Loop Until UpperPointer <= LowerPointer + + End Sub + + Function DidPlayerWin() As Boolean + For i As Integer = 0 To Numbers.Count - 2 + If Numbers(i) > Numbers(i + 1) Then Return False + Next + Return True + End Function + + + Private Function TryAgain() As Boolean + Console.WriteLine("TRY AGAIN? (Y OR N)") + If Console.ReadKey(True).Key = ConsoleKey.Y Then + Return True + Else + Return False + End If + End Function + + + + +End Module From e0260d4fe0c2a11a8504dc696dc3bb774dfa32aa Mon Sep 17 00:00:00 2001 From: bornach Date: Sun, 5 Sep 2021 22:22:27 +0100 Subject: [PATCH 412/749] Ported qubit.bas to Python --- 88 3-D Tic-Tac-Toe/python/qubit.py | 406 +++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 88 3-D Tic-Tac-Toe/python/qubit.py diff --git a/88 3-D Tic-Tac-Toe/python/qubit.py b/88 3-D Tic-Tac-Toe/python/qubit.py new file mode 100644 index 00000000..e8840a87 --- /dev/null +++ b/88 3-D Tic-Tac-Toe/python/qubit.py @@ -0,0 +1,406 @@ +#!/usr/bin/python3 + +# Ported from the BASIC source for 3D Tic Tac Toe +# in BASIC Computer Games, by David H. Ahl +# The code originated from Dartmouth College + +from enum import Enum + + +class Move(Enum): + """ Game status and types of machine move """ + HUMAN_WIN = 0 + MACHINE_WIN = 1 + DRAW = 2 + MOVES = 3 + LIKES = 4 + TAKES = 5 + GET_OUT = 6 + YOU_FOX = 7 + NICE_TRY = 8 + CONCEDES = 9 + +class Player(Enum): + EMPTY = 0 + HUMAN = 1 + MACHINE = 2 + +class TicTacToe3D: + """ The game logic for 3D Tic Tac Toe and the machine opponent """ + + def __init__(self): + + # 4x4x4 board keeps track of which player occupies each place + # and used by machine to work out its strategy + self.board = [0] * 64 + + # starting move + self.corners = [0, 48, 51, 3, 12, 60, 63, 15, + 21, 38, 22, 37, 25, 41, 26, 42] + + # lines to check for end game + self.lines = [[0, 1, 2, 3], + [4, 5, 6, 7], + [8, 9, 10, 11], + [12, 13, 14, 15], + [16, 17, 18, 19], + [20, 21, 22, 23], + [24, 25, 26, 27], + [28, 29, 30, 31], + [32, 33, 34, 35], + [36, 37, 38, 39], + [40, 41, 42, 43], + [44, 45, 46, 47], + [48, 49, 50, 51], + [52, 53, 54, 55], + [56, 57, 58, 59], + [60, 61, 62, 63], + [0, 16, 32, 48], + [4, 20, 36, 52], + [8, 24, 40, 56], + [12, 28, 44, 60], + [1, 17, 33, 49], + [5, 21, 37, 53], + [9, 25, 41, 57], + [13, 29, 45, 61], + [2, 18, 34, 50], + [6, 22, 38, 54], + [10, 26, 42, 58], + [14, 30, 46, 62], + [3, 19, 35, 51], + [7, 23, 39, 55], + [11, 27, 43, 59], + [15, 31, 47, 63], + [0, 4, 8, 12], + [16, 20, 24, 28], + [32, 36, 40, 44], + [48, 52, 56, 60], + [1, 5, 9, 13], + [17, 21, 25, 29], + [33, 37, 41, 45], + [49, 53, 57, 61], + [2, 6, 10, 14], + [18, 22, 26, 30], + [34, 38, 42, 46], + [50, 54, 58, 62], + [3, 7, 11, 15], + [19, 23, 27, 31], + [35, 39, 43, 47], + [51, 55, 59, 63], + [0, 5, 10, 15], + [16, 21, 26, 31], + [32, 37, 42, 47], + [48, 53, 58, 63], + [12, 9, 6, 3], + [28, 25, 22, 19], + [44, 41, 38, 35], + [60, 57, 54, 51], + [0, 20, 40, 60], + [1, 21, 41, 61], + [2, 22, 42, 62], + [3, 23, 43, 63], + [48, 36, 24, 12], + [49, 37, 25, 13], + [50, 38, 26, 14], + [51, 39, 27, 15], + [0, 17, 34, 51], + [4, 21, 38, 55], + [8, 25, 42, 59], + [12, 29, 46, 63], + [48, 33, 18, 3], + [52, 37, 22, 7], + [56, 41, 26, 11], + [60, 45, 30, 15], + [0, 21, 42, 63], + [15, 26, 37, 48], + [3, 22, 41, 60], + [12, 25, 38, 51]] + + def get(self, x, y, z): + m = self.board[4*(4*z + y) + x] + if m == 40: + return Player.MACHINE + elif m == 8: + return Player.HUMAN + else: + return Player.EMPTY + + def move3D(self, x, y, z, player): + m = 4*(4*z + y) + x + return self.move(m, player) + + def move(self, m, player): + if self.board[m] > 1: + return False + + if player == Player.MACHINE: + self.board[m] = 40 + else: + self.board[m] = 8 + return True + + def get3DPosition(self, m): + x = m % 4 + y = (m // 4) % 4 + z = m // 16 + return x, y, z + + def evaluateLines(self): + self.lineValues = [0] * 76 + for j in range(76): + value = 0 + for k in range(4): + value += self.board[self.lines[j][k]] + self.lineValues[j] = value + + def strategyMarkLine(self, i): + for j in range(4): + m = self.lines[i][j] + if self.board[m] == 0: + self.board[m] = 1 + + def clearStrategyMarks(self): + for i in range(64): + if self.board[i] == 1: + self.board[i] = 0 + + def markAndMove(self, vlow, vhigh, vmove): + """ + mark lines that can potentially win the game for the human + or the machine and choose best place to play + """ + for i in range(76): + value = 0 + for j in range(4): + value += self.board[self.lines[i][j]] + self.lineValues[i] = value + if vlow <= value < vhigh: + if value > vlow: + return self.moveTriple(i) + self.strategyMarkLine(i) + self.evaluateLines() + + for i in range(76): + value = self.lineValues[i] + if value == 4 or value == vmove: + return self.moveDiagonals(i, 1) + return None + + def machineMove(self): + """ machine works out what move to play """ + self.clearStrategyMarks() + + self.evaluateLines() + for value, event in [(32, self.humanWin), + (120, self.machineWin), + (24, self.blockHumanWin)]: + for i in range(76): + if self.lineValues[i] == value: + return event(i) + + m = self.markAndMove(80, 88, 43) + if m != None: + return m + + self.clearStrategyMarks() + + m = self.markAndMove(16, 24, 11) + if m != None: + return m + + for k in range(18): + value = 0 + for i in range(4*k, 4*k+4): + for j in range(4): + value += self.board[self.lines[i][j]] + if (32 <= value < 40) or (72 <= value < 80): + for s in [1, 0]: + for i in range(4*k, 4*k+4): + m = self.moveDiagonals(i, s) + if m != None: + return m + + self.clearStrategyMarks() + + for y in self.corners: + if self.board[y] == 0: + return (Move.MOVES, y) + + for i in range(64): + if self.board[i] == 0: + return (Move.LIKES, i) + + return (Move.DRAW, -1) + + def humanWin(self, i): + return (Move.HUMAN_WIN, -1, i) + + def machineWin(self, i): + for j in range(4): + m = self.lines[i][j] + if self.board[m] == 0: + return (Move.MACHINE_WIN, m, i) + return None + + def blockHumanWin(self, i): + for j in range(4): + m = self.lines[i][j] + if self.board[m] == 0: + return (Move.NICE_TRY, m) + return None + + + def moveTriple(self, i): + """ make two lines-of-3 or prevent human from doing this """ + for j in range(4): + m = self.lines[i][j] + if self.board[m] == 1: + if self.lineValues[i] < 40: + return (Move.YOU_FOX, m) + else: + return (Move.GET_OUT, m) + return (Move.CONCEDES, -1) + + # choose move in corners or center boxes of square 4x4 + def moveDiagonals(self, i, s): + if 0 < (i % 4) < 3: + jrange = [1, 2] + else: + jrange = [0, 3] + for j in jrange: + m = self.lines[i][j] + if self.board[m] == s: + return (Move.TAKES, m) + return None + +class Qubit: + + def moveCode(self, board, m): + x, y, z = board.get3DPosition(m) + return "{:d}{:d}{:d}".format(z+1, y+1, x+1) + + def showWin(self, board, i): + for m in board.lines[i]: + print(self.moveCode(board, m)) + + def showBoard(self, board): + c = " YM" + for z in range(4): + for y in range(4): + print(" " * y, end="") + for x in range(4): + p = board.get(x, y, z) + print("({}) ".format(c[p.value]), end="") + print("\n") + print("\n") + + def humanMove(self, board): + print("") + c = "1234" + while True: + h = input("Your move?\n") + if h == "1": + return False + if h == "0": + self.showBoard(board) + continue + if (len(h) == 3) and (h[0] in c) and (h[1] in c) and (h[2] in c): + x = c.find(h[2]) + y = c.find(h[1]) + z = c.find(h[0]) + if board.move3D(x, y, z, Player.HUMAN): + break + + print("That square is used. Try again.") + else: + print("Incorrect move. Retype it--") + + return True + + def play(self): + print("Qubic\n") + print("Create Computing Morristown, New Jersey\n\n\n") + while True: + c = input("Do you want instructions?\n") + if len(c) >= 1 and (c[0] in "ynYN"): + break + print("Incorrect answer. Please type 'yes' or 'no.") + + c = c.lower() + if c[0] == 'y': + print("The game is Tic-Tac-Toe in a 4 x 4 x 4 cube.") + print("Each move is indicated by a 3 digit number, with each") + print("digit between 1 and 4 inclusive. The digits indicate the") + print("level, row, and column, respectively, of the occupied") + print("place.\n") + + print("To print the playing board, type 0 (zero) as your move.") + print("The program will print the board with your moves indicated") + print("with a (Y), the machine's moves with an (M), and") + print("unused squares with a ( ).\n") + + print("To stop the program run, type 1 as your move.\n\n") + + + + play_again = True + while play_again: + board = TicTacToe3D() + + while True: + s = input("Do you want to move first?\n") + if len(s) >= 1 and (s[0] in "ynYN"): + break + print("Incorrect answer. Please type 'yes' or 'no'.") + + skipHuman = s[0] in "nN" + + move_text = ["Machine moves to", + "Machine likes", + "Machine takes", + "Let's see you get out of this: Machine moves to", + "You fox. Just in the nick of time, machine moves to", + "Nice try. Machine moves to"] + + while True: + if not skipHuman: + if not self.humanMove(board): + break + skipHuman = False + + m = board.machineMove() + if m[0] == Move.HUMAN_WIN: + print("You win as follows,") + self.showWin(board, m[2]) + break + elif m[0] == Move.MACHINE_WIN: + print("Machine moves to {}, and wins as follows".format(self.moveCode(board, m[1]))) + self.showWin(board, m[2]) + break + elif m[0] == Move.DRAW: + print("The game is a draw.") + break + elif m[0] == Move.CONCEDES: + print("Machine concedes this game.") + break + else: + print(move_text[m[0].value - Move.MOVES.value]) + print(self.moveCode(board, m[1])) + board.move(m[1], Player.MACHINE) + + self.showBoard(board) + + print(" ") + while True: + x = input("Do you want to try another game\n") + if len(x) >= 1 and x[0] in "ynYN": + break + print("Incorrect answer. Please Type 'yes' or 'no'.") + + play_again = x[0] in "yY" + + + +if __name__ == "__main__": + game = Qubit() + game.play() From 39ba532739ddcd358ecc4ce3719f8973f733a53a Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 4 Oct 2021 17:45:55 +1100 Subject: [PATCH 413/749] Add C# implementaion of 86 Target --- 86 Target/csharp/Target.sln | 34 +++++++ 86 Target/csharp/Target/Angle.cs | 18 ++++ 86 Target/csharp/Target/Explosion.cs | 22 +++++ 86 Target/csharp/Target/FiringRange.cs | 26 ++++++ 86 Target/csharp/Target/Game.cs | 89 +++++++++++++++++++ 86 Target/csharp/Target/Input.cs | 59 ++++++++++++ 86 Target/csharp/Target/Offset.cs | 21 +++++ 86 Target/csharp/Target/Point.cs | 47 ++++++++++ 86 Target/csharp/Target/Program.cs | 39 ++++++++ 86 Target/csharp/Target/RandomExtensions.cs | 14 +++ .../Target/Strings/TitleAndInstructions.txt | 18 ++++ 86 Target/csharp/Target/Target.csproj | 12 +++ 12 files changed, 399 insertions(+) create mode 100644 86 Target/csharp/Target.sln create mode 100644 86 Target/csharp/Target/Angle.cs create mode 100644 86 Target/csharp/Target/Explosion.cs create mode 100644 86 Target/csharp/Target/FiringRange.cs create mode 100644 86 Target/csharp/Target/Game.cs create mode 100644 86 Target/csharp/Target/Input.cs create mode 100644 86 Target/csharp/Target/Offset.cs create mode 100644 86 Target/csharp/Target/Point.cs create mode 100644 86 Target/csharp/Target/Program.cs create mode 100644 86 Target/csharp/Target/RandomExtensions.cs create mode 100644 86 Target/csharp/Target/Strings/TitleAndInstructions.txt create mode 100644 86 Target/csharp/Target/Target.csproj diff --git a/86 Target/csharp/Target.sln b/86 Target/csharp/Target.sln new file mode 100644 index 00000000..3e111702 --- /dev/null +++ b/86 Target/csharp/Target.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Target", "Target\Target.csproj", "{8B0B5114-1D05-4F8D-B328-EA2FB89992E7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Debug|x64.ActiveCfg = Debug|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Debug|x64.Build.0 = Debug|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Debug|x86.ActiveCfg = Debug|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Debug|x86.Build.0 = Debug|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Release|Any CPU.Build.0 = Release|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Release|x64.ActiveCfg = Release|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Release|x64.Build.0 = Release|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Release|x86.ActiveCfg = Release|Any CPU + {8B0B5114-1D05-4F8D-B328-EA2FB89992E7}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/86 Target/csharp/Target/Angle.cs b/86 Target/csharp/Target/Angle.cs new file mode 100644 index 00000000..a14dd782 --- /dev/null +++ b/86 Target/csharp/Target/Angle.cs @@ -0,0 +1,18 @@ +namespace Target +{ + internal class Angle + { + // Use same precision for constants as original code + private const float PI = 3.14159f; + private const float DegreesPerRadian = 57.296f; + + private readonly float _radians; + + private Angle(float radians) => _radians = radians; + + public static Angle InDegrees(float degrees) => new (degrees / DegreesPerRadian); + public static Angle InRotations(float rotations) => new (2 * PI * rotations); + + public static implicit operator float(Angle angle) => angle._radians; + } +} diff --git a/86 Target/csharp/Target/Explosion.cs b/86 Target/csharp/Target/Explosion.cs new file mode 100644 index 00000000..89a94a93 --- /dev/null +++ b/86 Target/csharp/Target/Explosion.cs @@ -0,0 +1,22 @@ +namespace Target +{ + internal class Explosion + { + private readonly Point _position; + + public Explosion(Point position, Offset targetOffset) + { + _position = position; + FromTarget = targetOffset; + DistanceToTarget = targetOffset.Distance; + } + + public Point Position => _position; + public Offset FromTarget { get; } + public float DistanceToTarget { get; } + public string GetBearing() => _position.GetBearing(); + + public bool IsHit => DistanceToTarget <= 20; + public bool IsTooClose => _position.Distance < 20; + } +} diff --git a/86 Target/csharp/Target/FiringRange.cs b/86 Target/csharp/Target/FiringRange.cs new file mode 100644 index 00000000..368dc453 --- /dev/null +++ b/86 Target/csharp/Target/FiringRange.cs @@ -0,0 +1,26 @@ +using System; + +namespace Target +{ + internal class FiringRange + { + private readonly Random random; + + public FiringRange() + { + random = new Random(); + NextTarget(); + } + + public Point TargetPosition { get; private set; } + + public void NextTarget() => TargetPosition = random.NextPosition(); + + public Explosion Fire(Angle angleFromX, Angle angleFromZ, float distance) + { + var explosionPosition = new Point(angleFromX, angleFromZ, distance); + var targetOffset = explosionPosition - TargetPosition; + return new (explosionPosition, targetOffset); + } + } +} diff --git a/86 Target/csharp/Target/Game.cs b/86 Target/csharp/Target/Game.cs new file mode 100644 index 00000000..2cef015a --- /dev/null +++ b/86 Target/csharp/Target/Game.cs @@ -0,0 +1,89 @@ +using System; + +namespace Target +{ + internal class Game + { + private readonly FiringRange _firingRange; + private int _shotCount; + + private Game(FiringRange firingRange) + { + _firingRange = firingRange; + } + + public static void Play(FiringRange firingRange) => new Game(firingRange).Play(); + + private void Play() + { + var target = _firingRange.TargetPosition; + Console.WriteLine(target.GetBearing()); + Console.WriteLine($"Target sighted: approximate coordinates: {target}"); + + while (true) + { + Console.WriteLine($" Estimated distance: {target.EstimateDistance()}"); + Console.WriteLine(); + + var explosion = Shoot(); + + if (explosion.IsTooClose) + { + Console.WriteLine("You blew yourself up!!"); + return; + } + + Console.WriteLine(explosion.GetBearing()); + + if (explosion.IsHit) + { + ReportHit(explosion.DistanceToTarget); + return; + } + + ReportMiss(explosion); + } + } + + private Explosion Shoot() + { + var input = Input.ReadNumbers("Input angle deviation from X, angle deviation from Z, distance", 3); + _shotCount++; + Console.WriteLine(); + + return _firingRange.Fire(Angle.InDegrees(input[0]), Angle.InDegrees(input[1]), input[2]); + } + + private void ReportHit(float distance) + { + Console.WriteLine(); + Console.WriteLine($" * * * HIT * * * Target is non-functional"); + Console.WriteLine(); + Console.WriteLine($"Distance of explosion from target was {distance} kilometers."); + Console.WriteLine(); + Console.WriteLine($"Mission accomplished in {_shotCount} shots."); + } + + private void ReportMiss(Explosion explosion) + { + ReportMiss(explosion.FromTarget); + Console.WriteLine($"Approx position of explosion: {explosion.Position}"); + Console.WriteLine($" Distance from target = {explosion.DistanceToTarget}"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + private void ReportMiss(Offset targetOffset) + { + ReportMiss(targetOffset.DeltaX, "in front of", "behind"); + ReportMiss(targetOffset.DeltaY, "to left of", "to right of"); + ReportMiss(targetOffset.DeltaZ, "above", "below"); + } + + private void ReportMiss(float delta, string positiveText, string negativeText) => + Console.WriteLine(delta >= 0 ? GetOffsetText(positiveText, delta) : GetOffsetText(negativeText, -delta)); + + private static string GetOffsetText(string text, float distance) => $"Shot {text} target {distance} kilometers."; + } +} diff --git a/86 Target/csharp/Target/Input.cs b/86 Target/csharp/Target/Input.cs new file mode 100644 index 00000000..3cfce2c0 --- /dev/null +++ b/86 Target/csharp/Target/Input.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +namespace Target +{ + // Provides input methods which emulate the BASIC interpreter's keyboard input routines + internal static class Input + { + internal static void Prompt(string text = "") => Console.Write($"{text}? "); + + internal static List ReadNumbers(string prompt, int requiredCount) + { + var numbers = new List(); + + while (!TryReadNumbers(prompt, requiredCount, numbers)) + { + numbers.Clear(); + prompt = ""; + } + + return numbers; + } + + private static bool TryReadNumbers(string prompt, int requiredCount, List numbers) + { + Prompt(prompt); + var inputValues = ReadStrings(); + + foreach (var value in inputValues) + { + if (numbers.Count == requiredCount) + { + Console.WriteLine("!Extra input ingored"); + break; + } + + if (!TryParseNumber(value, out var number)) + { + return false; + } + + numbers.Add(number); + } + + return numbers.Count == requiredCount || TryReadNumbers("?", requiredCount, numbers); + } + + private static string[] ReadStrings() => Console.ReadLine().Split(',', StringSplitOptions.TrimEntries); + + private static bool TryParseNumber(string text, out float number) + { + if (float.TryParse(text, out number)) { return true; } + + Console.WriteLine("!Number expected - retry input line"); + number = default; + return false; + } + } +} diff --git a/86 Target/csharp/Target/Offset.cs b/86 Target/csharp/Target/Offset.cs new file mode 100644 index 00000000..2bd8710c --- /dev/null +++ b/86 Target/csharp/Target/Offset.cs @@ -0,0 +1,21 @@ +using System; + +namespace Target +{ + internal class Offset + { + public Offset(float deltaX, float deltaY, float deltaZ) + { + DeltaX = deltaX; + DeltaY = deltaY; + DeltaZ = deltaZ; + + Distance = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ + deltaZ); + } + + public float DeltaX { get; } + public float DeltaY { get; } + public float DeltaZ { get; } + public float Distance { get; } + } +} diff --git a/86 Target/csharp/Target/Point.cs b/86 Target/csharp/Target/Point.cs new file mode 100644 index 00000000..f004b1c4 --- /dev/null +++ b/86 Target/csharp/Target/Point.cs @@ -0,0 +1,47 @@ +using System; + +namespace Target +{ + internal class Point + { + private readonly float _angleFromX; + private readonly float _angleFromZ; + + private readonly float _x; + private readonly float _y; + private readonly float _z; + + private int _estimateCount; + + public Point(Angle angleFromX, Angle angleFromZ, float distance) + { + _angleFromX = angleFromX; + _angleFromZ = angleFromZ; + Distance = distance; + + _x = distance * (float)Math.Sin(_angleFromZ) * (float)Math.Cos(_angleFromX); + _y = distance * (float)Math.Sin(_angleFromZ) * (float)Math.Sin(_angleFromX); + _z = distance * (float)Math.Cos(_angleFromZ); + } + + public float Distance { get; } + + public float EstimateDistance() => + ++_estimateCount switch + { + 1 => EstimateDistance(20), + 2 => EstimateDistance(10), + 3 => EstimateDistance(5), + 4 => EstimateDistance(1), + _ => Distance + }; + + public float EstimateDistance(int precision) => (float)Math.Floor(Distance / precision) * precision; + + public string GetBearing() => $"Radians from X axis = {_angleFromX} from Z axis = {_angleFromZ}"; + + public override string ToString() => $"X= {_x} Y = {_y} Z= {_z}"; + + public static Offset operator -(Point p1, Point p2) => new (p1._x - p2._x, p1._y - p2._y, p1._z - p2._z); + } +} diff --git a/86 Target/csharp/Target/Program.cs b/86 Target/csharp/Target/Program.cs new file mode 100644 index 00000000..b861f0e6 --- /dev/null +++ b/86 Target/csharp/Target/Program.cs @@ -0,0 +1,39 @@ +using System; +using System.Reflection; + +namespace Target +{ + class Program + { + static void Main(string[] args) + { + DisplayTitleAndInstructions(); + + var firingRange = new FiringRange(); + + while (true) + { + Game.Play(firingRange); + + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("Next target..."); + Console.WriteLine(); + + firingRange.NextTarget(); + } + } + + private static void DisplayTitleAndInstructions() + { + using var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream("Target.Strings.TitleAndInstructions.txt"); + using var stdout = Console.OpenStandardOutput(); + + stream.CopyTo(stdout); + } + } +} diff --git a/86 Target/csharp/Target/RandomExtensions.cs b/86 Target/csharp/Target/RandomExtensions.cs new file mode 100644 index 00000000..45443c26 --- /dev/null +++ b/86 Target/csharp/Target/RandomExtensions.cs @@ -0,0 +1,14 @@ +using System; + +namespace Target +{ + internal static class RandomExtensions + { + public static float NextFloat(this Random rnd) => (float)rnd.NextDouble(); + + public static Point NextPosition(this Random rnd) => new ( + Angle.InRotations(rnd.NextFloat()), + Angle.InRotations(rnd.NextFloat()), + 100000 * rnd.NextFloat() + rnd.NextFloat()); + } +} diff --git a/86 Target/csharp/Target/Strings/TitleAndInstructions.txt b/86 Target/csharp/Target/Strings/TitleAndInstructions.txt new file mode 100644 index 00000000..0142e420 --- /dev/null +++ b/86 Target/csharp/Target/Strings/TitleAndInstructions.txt @@ -0,0 +1,18 @@ + Target + Creative Computing Morristown, New Jersey + + + +You are the weapons officer on the Starship Enterprise +and this is a test to see how accurate a shot you +are in a three-dimensional range. You will be told +the radian offset for the X and Z axes, the location +of the target in three dimensional rectangular coordinates, +the approximate number of degrees from the X and Z +axes, and the approximate distance to the target. +You will then proceed to shoot at the target until it is +destroyed! + +Good luck!! + + diff --git a/86 Target/csharp/Target/Target.csproj b/86 Target/csharp/Target/Target.csproj new file mode 100644 index 00000000..2df33b67 --- /dev/null +++ b/86 Target/csharp/Target/Target.csproj @@ -0,0 +1,12 @@ + + + + Exe + net5.0 + + + + + + + From 8d68705f4aa7d1471b8f005e9279e8cdaac02410 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 4 Oct 2021 23:02:53 +1100 Subject: [PATCH 414/749] Add C# implementation of 62 Mugwump --- 62 Mugwump/csharp/Mugwump.sln | 34 +++++++++++ 62 Mugwump/csharp/Mugwump/Game.cs | 36 +++++++++++ 62 Mugwump/csharp/Mugwump/Grid.cs | 40 +++++++++++++ 62 Mugwump/csharp/Mugwump/Input.cs | 66 +++++++++++++++++++++ 62 Mugwump/csharp/Mugwump/Mugwump.cs | 20 +++++++ 62 Mugwump/csharp/Mugwump/Mugwump.csproj | 11 ++++ 62 Mugwump/csharp/Mugwump/Offset.cs | 16 +++++ 62 Mugwump/csharp/Mugwump/Position.cs | 9 +++ 62 Mugwump/csharp/Mugwump/Program.cs | 33 +++++++++++ 62 Mugwump/csharp/Mugwump/Strings/Intro.txt | 15 +++++ 10 files changed, 280 insertions(+) create mode 100644 62 Mugwump/csharp/Mugwump.sln create mode 100644 62 Mugwump/csharp/Mugwump/Game.cs create mode 100644 62 Mugwump/csharp/Mugwump/Grid.cs create mode 100644 62 Mugwump/csharp/Mugwump/Input.cs create mode 100644 62 Mugwump/csharp/Mugwump/Mugwump.cs create mode 100644 62 Mugwump/csharp/Mugwump/Mugwump.csproj create mode 100644 62 Mugwump/csharp/Mugwump/Offset.cs create mode 100644 62 Mugwump/csharp/Mugwump/Position.cs create mode 100644 62 Mugwump/csharp/Mugwump/Program.cs create mode 100644 62 Mugwump/csharp/Mugwump/Strings/Intro.txt diff --git a/62 Mugwump/csharp/Mugwump.sln b/62 Mugwump/csharp/Mugwump.sln new file mode 100644 index 00000000..bc3cfbff --- /dev/null +++ b/62 Mugwump/csharp/Mugwump.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mugwump", "Mugwump\Mugwump.csproj", "{83F42802-4E7C-49B5-A022-DB9B6A65F2C6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Debug|x64.Build.0 = Debug|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Debug|x86.ActiveCfg = Debug|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Debug|x86.Build.0 = Debug|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Release|Any CPU.Build.0 = Release|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Release|x64.ActiveCfg = Release|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Release|x64.Build.0 = Release|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Release|x86.ActiveCfg = Release|Any CPU + {83F42802-4E7C-49B5-A022-DB9B6A65F2C6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/62 Mugwump/csharp/Mugwump/Game.cs b/62 Mugwump/csharp/Mugwump/Game.cs new file mode 100644 index 00000000..bf72d44e --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Game.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; + +namespace Mugwump +{ + internal class Game + { + private readonly Grid _grid; + + private Game(Random random) + { + _grid = new Grid(Enumerable.Range(1, 4).Select(id => new Mugwump(id, random.Next(10), random.Next(10)))); + } + + public static void Play(Random random) => new Game(random).Play(); + + private void Play() + { + for (int turn = 1; turn <= 10; turn++) + { + var guess = Input.ReadGuess($"Turn no. {turn} -- what is your guess"); + + if (_grid.Check(guess)) + { + Console.WriteLine(); + Console.WriteLine($"You got them all in {turn} turns!"); + return; + } + } + + Console.WriteLine(); + Console.WriteLine("Sorry, that's 10 tries. Here is where they're hiding:"); + _grid.Reveal(); + } + } +} diff --git a/62 Mugwump/csharp/Mugwump/Grid.cs b/62 Mugwump/csharp/Mugwump/Grid.cs new file mode 100644 index 00000000..dd89c638 --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Grid.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mugwump +{ + internal class Grid + { + private readonly List _mugwumps; + + public Grid(IEnumerable mugwumps) + { + _mugwumps = mugwumps.ToList(); + } + + public bool Check(Position guess) + { + foreach (var mugwump in _mugwumps.ToList()) + { + var (found, distance) = mugwump.FindFrom(guess); + + Console.WriteLine(found ? $"You have found {mugwump}" : $"You are {distance} units from {mugwump}"); + if (found) + { + _mugwumps.Remove(mugwump); + } + } + + return _mugwumps.Count == 0; + } + + public void Reveal() + { + foreach (var mugwump in _mugwumps.ToList()) + { + Console.WriteLine(mugwump.Reveal()); + } + } + } +} diff --git a/62 Mugwump/csharp/Mugwump/Input.cs b/62 Mugwump/csharp/Mugwump/Input.cs new file mode 100644 index 00000000..97222c3e --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Input.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; + +namespace Mugwump +{ + // Provides input methods which emulate the BASIC interpreter's keyboard input routines + internal static class Input + { + internal static Position ReadGuess(string prompt) + { + Console.WriteLine(); + Console.WriteLine(); + var input = ReadNumbers(prompt, 2); + return new Position(input[0], input[1]); + } + + private static void Prompt(string text = "") => Console.Write($"{text}? "); + + private static List ReadNumbers(string prompt, int requiredCount) + { + var numbers = new List(); + + while (!TryReadNumbers(prompt, requiredCount, numbers)) + { + prompt = ""; + } + + return numbers; + } + + private static bool TryReadNumbers(string prompt, int requiredCount, List numbers) + { + Prompt(prompt); + var inputValues = ReadStrings(); + + foreach (var value in inputValues) + { + if (numbers.Count == requiredCount) + { + Console.WriteLine("!Extra input ingored"); + return true; + } + + if (!TryParseNumber(value, out var number)) + { + return false; + } + + numbers.Add(number); + } + + return numbers.Count == requiredCount || TryReadNumbers("?", requiredCount, numbers); + } + + private static string[] ReadStrings() => Console.ReadLine().Split(',', StringSplitOptions.TrimEntries); + + private static bool TryParseNumber(string text, out float number) + { + if (float.TryParse(text, out number)) { return true; } + + Console.WriteLine("!Number expected - retry input line"); + number = default; + return false; + } + } +} diff --git a/62 Mugwump/csharp/Mugwump/Mugwump.cs b/62 Mugwump/csharp/Mugwump/Mugwump.cs new file mode 100644 index 00000000..bd117c63 --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Mugwump.cs @@ -0,0 +1,20 @@ +namespace Mugwump +{ + internal class Mugwump + { + private readonly int _id; + private readonly Position _position; + + public Mugwump(int id, int x, int y) + { + _id = id; + _position = new Position(x, y); + } + + public (bool, Distance) FindFrom(Position guess) => (guess == _position, guess - _position); + + public string Reveal() => $"{this} is at {_position}"; + + public override string ToString() => $"Mugwump {_id}"; + } +} diff --git a/62 Mugwump/csharp/Mugwump/Mugwump.csproj b/62 Mugwump/csharp/Mugwump/Mugwump.csproj new file mode 100644 index 00000000..fc2efa30 --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Mugwump.csproj @@ -0,0 +1,11 @@ + + + + Exe + net5.0 + + + + + + diff --git a/62 Mugwump/csharp/Mugwump/Offset.cs b/62 Mugwump/csharp/Mugwump/Offset.cs new file mode 100644 index 00000000..c62e3862 --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Offset.cs @@ -0,0 +1,16 @@ +using System; + +namespace Mugwump +{ + internal class Distance + { + private readonly float _value; + + public Distance(float deltaX, float deltaY) + { + _value = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY); + } + + public override string ToString() => $"{_value:0.0}"; + } +} diff --git a/62 Mugwump/csharp/Mugwump/Position.cs b/62 Mugwump/csharp/Mugwump/Position.cs new file mode 100644 index 00000000..6005ae8b --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Position.cs @@ -0,0 +1,9 @@ +namespace Mugwump +{ + internal record Position(float X, float Y) + { + public override string ToString() => $"( {X} , {Y} )"; + + public static Distance operator -(Position p1, Position p2) => new(p1.X - p2.X, p1.Y - p2.Y); + } +} diff --git a/62 Mugwump/csharp/Mugwump/Program.cs b/62 Mugwump/csharp/Mugwump/Program.cs new file mode 100644 index 00000000..6121b81d --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Program.cs @@ -0,0 +1,33 @@ +using System; +using System.Reflection; + +namespace Mugwump +{ + class Program + { + static void Main(string[] args) + { + DisplayIntro(); + + var random = new Random(); + + while (true) + { + Game.Play(random); + + Console.WriteLine(); + Console.WriteLine("That was fun! Let's play again......."); + Console.WriteLine("Four more mugwumps are now in hiding."); + } + } + + private static void DisplayIntro() + { + using var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream("Mugwump.Strings.Intro.txt"); + using var stdout = Console.OpenStandardOutput(); + + stream.CopyTo(stdout); + } + } +} diff --git a/62 Mugwump/csharp/Mugwump/Strings/Intro.txt b/62 Mugwump/csharp/Mugwump/Strings/Intro.txt new file mode 100644 index 00000000..30ede4d6 --- /dev/null +++ b/62 Mugwump/csharp/Mugwump/Strings/Intro.txt @@ -0,0 +1,15 @@ + Mugwump + Creative Computing Morristown, New Jersey + + + +The object of this game is to find four mugwumps +hidden on a 10 by 10 grid. Homebase is position 0,0. +Any guess you make must be two numbers with each +number between 0 and 9, inclusive. First number +is distance to right of homebase and second number +is distance above homebase. + +You get 10 tries. After each try, I will tell +you how far you are from each wugwump. + From c3cf57fa6448b81cbd7d84ac6b67189470a697ce Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 14:12:57 +1100 Subject: [PATCH 415/749] Ported to Python --- 38 Fur Trader/python/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/38 Fur Trader/python/README.md b/38 Fur Trader/python/README.md index 781945ec..827a606d 100644 --- a/38 Fur Trader/python/README.md +++ b/38 Fur Trader/python/README.md @@ -1,3 +1,25 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Python](https://www.python.org/about/) + +##### Translator Notes: +I tried to preserve as much of the original layout and flow of the code +as possible. However I did use quasi enumerated types for the Fort numbers +and Fur types. I think this was certinaly a change for the better, and +makes the code much easier to read. + +I program in many different languages on a daily basis. Most languages +require brackets around expressions, so I just cannot bring myself to +write an expression without brackets. IMHO it makes the code easier to study, +but it does contravene the Python PEP-8 Style guide. + +Interestingly the code seems to have a bug around the prices of Fox Furs. +The commodity-rate for these is stored in the variable `D1`, however some +paths through the code do not set this price. So there was a chance of +using this uninitialised, or whatever the previous loop set. I don't +think this was the original authors intent. So I preserved the original flow +of the code (using the previous `D1` value), but also catching the +uninitialised path, and assigning a "best guess" value. + +krt@krt.com.au 2020-10-10 + From cba02b2d2e954447c7fca95fc95acb3664867670 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 14:13:08 +1100 Subject: [PATCH 416/749] Ported to Python --- 38 Fur Trader/python/furtrader.py | 297 ++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100755 38 Fur Trader/python/furtrader.py diff --git a/38 Fur Trader/python/furtrader.py b/38 Fur Trader/python/furtrader.py new file mode 100755 index 00000000..6844fb4c --- /dev/null +++ b/38 Fur Trader/python/furtrader.py @@ -0,0 +1,297 @@ +#! /usr/bin/env python3 + +import sys # for system function, like exit() +import random # for generating random numbers + +from enum import IntEnum # for setting the fur type numbers + +### global variables for storing player's status +player_funds = 0 # no money +player_furs = [ 0, 0, 0, 0 ] # no furs + + +### Constants +FUR_MINK = 0 +FUR_BEAVER = 1 +FUR_ERMINE = 2 +FUR_FOX = 3 +MAX_FURS = 190 +FUR_NAMES = [ "MINK", "BEAVER", "ERMINE", "FOX" ] + +FORT_MONTREAL = 1 +FORT_QUEBEC = 2 +FORT_NEWYORK = 3 +FORT_NAMES = [ "HOCHELAGA (MONTREAL)", "STADACONA (QUEBEC)", "NEW YORK" ] + + + +def printAtColumn( column:int, words:str ): + """ Print the words at the specified column """ + spaces = ' ' * column # make a fat string of spaces + print( spaces + words ) + + +def showIntroduction(): + """ Show the player the introductory message """ + print( "YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN " ) + print( "1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET" ) + print( "SUPPLIES FOR THE NEXT YEAR. YOU HAVE A CHOICE OF THREE" ) + print( "FORTS AT WHICH YOU MAY TRADE. THE COST OF SUPPLIES" ) + print( "AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND" ) + print( "ON THE FORT THAT YOU CHOOSE." ) + print( "" ) + + +def getFortChoice(): + """ Show the player the choices of Fort, get their input, if the + input is a valid choice (1,2,3) return it, otherwise keep + prompting the user. """ + result = 0 + while ( result == 0 ): + print( "" ) + print( "YOU MAY TRADE YOUR FURS AT FORT 1, FORT 2," ) + print( "OR FORT 3. FORT 1 IS FORT HOCHELAGA (MONTREAL)" ) + print( "AND IS UNDER THE PROTECTION OF THE FRENCH ARMY." ) + print( "FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE" ) + print( "PROTECTION OF THE FRENCH ARMY. HOWEVER, YOU MUST" ) + print( "MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS." ) + print( "FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL." ) + print( "YOU MUST CROSS THROUGH IROQUOIS LAND." ) + print( "ANSWER 1, 2, OR 3." ) + + player_choice = input( ">> " ) # get input from the player + + # try to convert the player's string input into an integer + try: + result = int( player_choice ) # string to integer + except: + # Whatever the player typed, it could not be interpreted as a number + pass + + return result + + +def showFortComment( which_fort ): + """ Print the description for the fort """ + print( "" ) + if ( which_fort == FORT_MONTREAL ): + print( "YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT" ) + print( "IS FAR FROM ANY SEAPORT. THE VALUE" ) + print( "YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST" ) + print( "OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK." ) + elif ( which_fort == FORT_QUEBEC ): + print( "YOU HAVE CHOSEN A HARD ROUTE. IT IS, IN COMPARSION," ) + print( "HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN" ) + print( "THE ROUTE TO NEW YORK. YOU WILL RECEIVE AN AVERAGE VALUE" ) + print( "FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE." ) + elif ( which_fort == FORT_NEWYORK ): + print( "YOU HAVE CHOSEN THE MOST DIFFICULT ROUTE. AT" ) + print( "FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE" ) + print( "FOR YOUR FURS. THE COST OF YOUR SUPPLIES" ) + print( "WILL BE LOWER THAN AT ALL THE OTHER FORTS." ) + else: + print( "Internal error #1, fort " + str( which_fort ) + " does not exist" ) + sys.exit( 1 ) # you have a bug + print( "" ) + + +def getYesOrNo(): + """ Prompt the player to enter 'YES' or 'NO'. Keep prompting until + valid input is entered. Accept various spellings by only + checking the first letter of input. + Return a single letter 'Y' or 'N' """ + result = 0 + while ( result not in ( 'Y', 'N' ) ): + player_choice = input( "ANSWER YES OR NO >>" ) + player_choice = player_choice.strip().upper() # trim spaces, make upper-case + if ( player_choice.startswith( 'Y' ) ): + result = 'Y' + elif ( player_choice.startswith( 'N' ) ): + result = 'N' + return result + + +def getFursPurchase(): + """ Prompt the player for how many of each fur type they want. + Accept numeric inputs, re-prompting on incorrect input values """ + results = [] + + print( "YOUR 190 FURS ARE DISTRIBUTED AMONG THE FOLLOWING" ) + print( "KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX." ) + print( "" ) + + for i in ( range( len( FUR_NAMES ) ) ): + print( "HOW MANY " + FUR_NAMES[i] + " DO YOU HAVE" ) + count_str = input( ">> " ) + try: + count = int( count_str ) + results.append( count ) + except: + # invalid input, prompt again by re-looping + i -= 1 + return results + + + +### +### MAIN +### + +if ( __name__ == '__main__' ): + + printAtColumn( 31, "FUR TRADER" ) + printAtColumn( 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" ) + printAtColumn( 15, "(Ported to Python Oct 2012 krt@krt.com.au)" ) + print( "\n\n\n" ) + + game_state = 'starting' + fox_price = None # sometimes this takes the "last" price (probably this was a bug) + + while ( True ): + + if ( game_state == 'starting' ): + showIntroduction() + + player_funds = 600 # Initial player start money + player_furs = [ 0, 0, 0, 0 ] # Player fur inventory + + print( "DO YOU WISH TO TRADE FURS?" ) + should_trade = getYesOrNo() + if ( should_trade == 'N' ): + sys.exit( 0 ) # STOP + game_state = 'trading' + + elif ( game_state == 'trading' ): + print( "" ) + print( "YOU HAVE $ %1.2f IN SAVINGS" % ( player_funds ) ) + print( "AND 190 FURS TO BEGIN THE EXPEDITION" ) + player_furs = getFursPurchase() + + if ( sum( player_furs ) > MAX_FURS ): + print( "" ) + print( "YOU MAY NOT HAVE THAT MANY FURS." ) + print( "DO NOT TRY TO CHEAT. I CAN ADD." ) + print( "YOU MUST START AGAIN." ) + state = 'starting' # T/N: Wow, harsh. + else: + game_state = 'choosing fort' + + elif ( game_state == 'choosing fort' ): + which_fort = getFortChoice() + showFortComment( which_fort ) + print( "DO YOU WANT TO TRADE AT ANOTHER FORT?" ) + change_fort = getYesOrNo() + if ( change_fort == 'N' ): + game_state = 'travelling' + + elif ( game_state == 'travelling' ): + print( "" ) + if ( which_fort == FORT_MONTREAL ): + mink_price = int( ( 0.2 * random.random() + 0.70 ) * 100 + 0.5 ) / 100 #INT((.2*RND(1)+.7)*10^2+.5)/10^2 + ermine_price = int( ( 0.2 * random.random() + 0.65 ) * 100 + 0.5 ) / 100 #INT((.2*RND(1)+.65)*10^2+.5)/10^2 + beaver_price = int( ( 0.2 * random.random() + 0.75 ) * 100 + 0.5 ) / 100 #INT((.2*RND(1)+.75)*10^2+.5)/10^2 + fox_price = int( ( 0.2 * random.random() + 0.80 ) * 100 + 0.5 ) / 100 #INT((.2*RND(1)+.8)*10^2+.5)/10^2 + + print( "SUPPLIES AT FORT HOCHELAGA COST $150.00." ) + print( "YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00." ) + player_funds -= 160 + + elif ( which_fort == FORT_QUEBEC ): + mink_price = int( ( 0.30 * random.random() + 0.85 ) * 100 + 0.5 ) / 100 #INT((.3*RND(1)+.85)*10^2+.5)/10^2 + ermine_price = int( ( 0.15 * random.random() + 0.80 ) * 100 + 0.5 ) / 100 #INT((.15*RND(1)+.8)*10^2+.5)/10^2 + beaver_price = int( ( 0.20 * random.random() + 0.90 ) * 100 + 0.5 ) / 100 #INT((.2*RND(1)+.9)*10^2+.5)/10^2 + fox_price = int( ( 0.25 * random.random() + 1.10 ) * 100 + 0.5 ) / 100 #INT((.25*RND(1)+1.1)*10^2+.5)/10^2 + event_picker = int( 10 * random.random() ) + 1 + + if ( event_picker <= 2 ): + print( "YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS" ) + print( "THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND" ) + print( "THEM STOLEN WHEN YOU RETURNED." ) + player_furs[ FUR_BEAVER ] = 0 + elif ( event_picker <= 6 ): + print( "YOU ARRIVED SAFELY AT FORT STADACONA." ) + elif ( event_picker <= 8 ): + print( "YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU" ) + print( "LOST ALL YOUR FURS." ) + player_furs = [ 0, 0, 0, 0 ] + elif ( event_picker <= 10 ): + print( "YOUR FOX PELTS WERE NOT CURED PROPERLY." ) + print( "NO ONE WILL BUY THEM." ) + player_furs[ FUR_FOX ] = 0 + else: + print( "Internal Error #3, Out-of-bounds event_picker" + str( event_picker ) ) + sys.exit( 1 ) # you have a bug + + print( "" ) + print( "SUPPLIES AT FORT STADACONA COST $125.00." ) + print( "YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00." ) + player_funds -= 140 + + elif ( which_fort == FORT_NEWYORK ): + mink_price = int( ( 0.15 * random.random() + 1.05 ) * 100 + 0.5 ) / 100 #INT((.15*RND(1)+1.05)*10^2+.5)/10^2 + ermine_price = int( ( 0.15 * random.random() + 0.95 ) * 100 + 0.5 ) / 100 #INT((.15*RND(1)+.95)*10^2+.5)/10^2 + beaver_price = int( ( 0.25 * random.random() + 1.00 ) * 100 + 0.5 ) / 100 #INT((.25*RND(1)+1.00)*10^2+.5)/10^2 + if ( fox_price == None ): + # Original Bug? There is no Fox price generated for New York, it will use any previous "D1" price + # So if there was no previous value, make one up + fox_price = int( ( 0.25 * random.random() + 1.05 ) * 100 + 0.5 ) / 100 # not in orginal code + event_picker = int( 10 * random.random() ) + 1 + + if ( event_picker <= 2 ): + print( "YOU WERE ATTACKED BY A PARTY OF IROQUOIS." ) + print( "ALL PEOPLE IN YOUR TRADING GROUP WERE" ) + print( "KILLED. THIS ENDS THE GAME." ) + sys.exit( 0 ) + elif ( event_picker <= 6 ): + print( "YOU WERE LUCKY. YOU ARRIVED SAFELY" ) + print( "AT FORT NEW YORK." ) + elif ( event_picker <= 8 ): + print( "YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY." ) + print( "HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND." ) + player_furs = [ 0, 0, 0, 0 ] + elif ( event_picker <= 10 ): + mink_price /= 2 + fox_price /= 2 + print( "YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP." ) + print( "YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS." ) + else: + print( "Internal Error #4, Out-of-bounds event_picker" + str( event_picker ) ) + sys.exit( 1 ) # you have a bug + + print( "" ) + print( "SUPPLIES AT NEW YORK COST $85.00." ) + print( "YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00." ) + player_funds -= 105 + + + else: + print( "Internal error #2, fort " + str( which_fort ) + " does not exist" ) + sys.exit( 1 ) # you have a bug + + # Calculate sales + beaver_value = beaver_price * player_furs[ FUR_BEAVER ] + fox_value = fox_price * player_furs[ FUR_FOX ] + ermine_value = ermine_price * player_furs[ FUR_ERMINE ] + mink_value = mink_price * player_furs[ FUR_MINK ] + + print( "" ) + print( "YOUR BEAVER SOLD FOR $%6.2f" % ( beaver_value ) ) + print( "YOUR FOX SOLD FOR $%6.2f" % ( fox_value ) ) + print( "YOUR ERMINE SOLD FOR $%6.2f" % ( ermine_value ) ) + print( "YOUR MINK SOLD FOR $%6.2f" % ( mink_value ) ) + + player_funds += beaver_value + fox_value + ermine_value + mink_value + + print( "" ) + print( "YOU NOW HAVE $ %1.2f INCLUDING YOUR PREVIOUS SAVINGS" % ( player_funds ) ) + + print( "" ) + print( "DO YOU WANT TO TRADE FURS NEXT YEAR?" ) + should_trade = getYesOrNo() + if ( should_trade == 'N' ): + sys.exit( 0 ) # STOP + else: + game_state = 'trading' + + + From 11ab68414312be7f7e32668d5bcc485e87d2bab3 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 14:17:03 +1100 Subject: [PATCH 417/749] Remove redundant import --- 38 Fur Trader/python/furtrader.py | 1 - 1 file changed, 1 deletion(-) diff --git a/38 Fur Trader/python/furtrader.py b/38 Fur Trader/python/furtrader.py index 6844fb4c..52c8929e 100755 --- a/38 Fur Trader/python/furtrader.py +++ b/38 Fur Trader/python/furtrader.py @@ -3,7 +3,6 @@ import sys # for system function, like exit() import random # for generating random numbers -from enum import IntEnum # for setting the fur type numbers ### global variables for storing player's status player_funds = 0 # no money From dec0c0c4e4c19e1036936429bff24e48c97a0807 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 14:19:52 +1100 Subject: [PATCH 418/749] Make fur-count a proper constant --- 38 Fur Trader/python/furtrader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/38 Fur Trader/python/furtrader.py b/38 Fur Trader/python/furtrader.py index 52c8929e..165e8a1f 100755 --- a/38 Fur Trader/python/furtrader.py +++ b/38 Fur Trader/python/furtrader.py @@ -115,7 +115,7 @@ def getFursPurchase(): Accept numeric inputs, re-prompting on incorrect input values """ results = [] - print( "YOUR 190 FURS ARE DISTRIBUTED AMONG THE FOLLOWING" ) + print( "YOUR " + str( MAX_FURS ) + " FURS ARE DISTRIBUTED AMONG THE FOLLOWING" ) print( "KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX." ) print( "" ) @@ -163,7 +163,7 @@ if ( __name__ == '__main__' ): elif ( game_state == 'trading' ): print( "" ) print( "YOU HAVE $ %1.2f IN SAVINGS" % ( player_funds ) ) - print( "AND 190 FURS TO BEGIN THE EXPEDITION" ) + print( "AND " + str( MAX_FURS ) + " FURS TO BEGIN THE EXPEDITION" ) player_furs = getFursPurchase() if ( sum( player_furs ) > MAX_FURS ): From cef132d246adbde65d7131203b9f87fc8c8895a0 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 14:27:01 +1100 Subject: [PATCH 419/749] Fix typo --- 38 Fur Trader/python/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/38 Fur Trader/python/README.md b/38 Fur Trader/python/README.md index 827a606d..d90f8449 100644 --- a/38 Fur Trader/python/README.md +++ b/38 Fur Trader/python/README.md @@ -5,7 +5,7 @@ Conversion to [Python](https://www.python.org/about/) ##### Translator Notes: I tried to preserve as much of the original layout and flow of the code as possible. However I did use quasi enumerated types for the Fort numbers -and Fur types. I think this was certinaly a change for the better, and +and Fur types. I think this was certainly a change for the better, and makes the code much easier to read. I program in many different languages on a daily basis. Most languages From 069f908452fa0dd913647323baf83ba20e69c3d1 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 14:27:26 +1100 Subject: [PATCH 420/749] Look and feel of YES/NO prompt - match rest of inputs --- 38 Fur Trader/python/furtrader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/38 Fur Trader/python/furtrader.py b/38 Fur Trader/python/furtrader.py index 165e8a1f..422e6059 100755 --- a/38 Fur Trader/python/furtrader.py +++ b/38 Fur Trader/python/furtrader.py @@ -101,7 +101,8 @@ def getYesOrNo(): Return a single letter 'Y' or 'N' """ result = 0 while ( result not in ( 'Y', 'N' ) ): - player_choice = input( "ANSWER YES OR NO >>" ) + print( "ANSWER YES OR NO" ) + player_choice = input( ">> " ) player_choice = player_choice.strip().upper() # trim spaces, make upper-case if ( player_choice.startswith( 'Y' ) ): result = 'Y' From 0f5665fae4733915fe703b048935ebc502841b81 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 16:43:50 +1100 Subject: [PATCH 421/749] Fixed bug for re-starting on user's bad maths --- 38 Fur Trader/python/furtrader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/38 Fur Trader/python/furtrader.py b/38 Fur Trader/python/furtrader.py index 422e6059..b26b2f1a 100755 --- a/38 Fur Trader/python/furtrader.py +++ b/38 Fur Trader/python/furtrader.py @@ -172,7 +172,7 @@ if ( __name__ == '__main__' ): print( "YOU MAY NOT HAVE THAT MANY FURS." ) print( "DO NOT TRY TO CHEAT. I CAN ADD." ) print( "YOU MUST START AGAIN." ) - state = 'starting' # T/N: Wow, harsh. + game_state = 'starting' # T/N: Wow, harsh. else: game_state = 'choosing fort' From 13f355f5fa15351995c7365c14f39a1fce280f90 Mon Sep 17 00:00:00 2001 From: kingsley Date: Sun, 10 Oct 2021 17:26:32 +1100 Subject: [PATCH 422/749] Added Version in simple ANSI-C --- 38 Fur Trader/c/README.md | 23 ++ 38 Fur Trader/c/furtrader.c | 475 ++++++++++++++++++++++++++++++++++++ 2 files changed, 498 insertions(+) create mode 100644 38 Fur Trader/c/README.md create mode 100755 38 Fur Trader/c/furtrader.c diff --git a/38 Fur Trader/c/README.md b/38 Fur Trader/c/README.md new file mode 100644 index 00000000..a5b55dd8 --- /dev/null +++ b/38 Fur Trader/c/README.md @@ -0,0 +1,23 @@ +Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) + +Conversion to [ANSI-C](https://en.wikipedia.org/wiki/ANSI_C) + +##### Translator Notes: +I tried to preserve as much of the original layout and flow of the code +as possible. However I did use enumerated types for the Fort numbers +and Fur types. I think this was certainly a change for the better, and +makes the code much easier to read. + +I also tried to minimise the use of pointers, and stuck with old-school +C formatting, because you never know how old the compiler is. + +Interestingly the code seems to have a bug around the prices of Fox Furs. +The commodity-rate for these is stored in the variable `D1`, however some +paths through the code do not set this price. So there was a chance of +using this uninitialised, or whatever the previous loop set. I don't +think this was the original authors intent. So I preserved the original flow +of the code (using the previous `D1` value), but also catching the +uninitialised path, and assigning a "best guess" value. + +krt@krt.com.au 2020-10-10 + diff --git a/38 Fur Trader/c/furtrader.c b/38 Fur Trader/c/furtrader.c new file mode 100755 index 00000000..80ffbcef --- /dev/null +++ b/38 Fur Trader/c/furtrader.c @@ -0,0 +1,475 @@ + +/* + * Ported from furtrader.bas to ANSI C (C99) by krt@krt.com.au + * + * compile with: + * gcc -g -Wall -Werror furtrader.c -o furtrader + */ + +#include +#include +#include +#include + + +/* Constants */ +#define FUR_TYPE_COUNT 4 +#define FUR_MINK 0 +#define FUR_BEAVER 1 +#define FUR_ERMINE 2 +#define FUR_FOX 3 +#define MAX_FURS 190 +const char *FUR_NAMES[FUR_TYPE_COUNT] = { "MINK", "BEAVER", "ERMINE", "FOX" }; + +#define FORT_TYPE_COUNT 3 +#define FORT_MONTREAL 1 +#define FORT_QUEBEC 2 +#define FORT_NEWYORK 3 +const char *FORT_NAMES[FORT_TYPE_COUNT] = { "HOCHELAGA (MONTREAL)", "STADACONA (QUEBEC)", "NEW YORK" }; + + + +/* Print the words at the specified column */ +void printAtColumn( int column, const char *words ) +{ + int i; + for ( i=0; i> " ); /* prompt the user */ + fgets( buffer, sizeof( buffer ), stdin ); /* read from the console into the buffer */ + result = (int)strtol( buffer, &endstr, 10 ); /* only simple error checking */ + + if ( endstr == buffer ) /* was the string -> integer ok? */ + result = -1; + } + + return result; +} + + +/* + * Prompt the user for YES/NO input. + * When input is given, try to work out if it's YES, Yes, yes, Y, etc. + * And convert to a single upper-case letter + * Returns a character of 'Y' or 'N'. + */ +char getYesOrNo() +{ + char result = '!'; + char buffer[64]; /* somewhere to store user input */ + + while ( !( result == 'Y' || result == 'N' ) ) /* While the answer was not Yes or No */ + { + print( "ANSWER YES OR NO" ); + printf( ">> " ); + + fgets( buffer, sizeof( buffer ), stdin ); /* read from the console into the buffer */ + if ( buffer[0] == 'Y' || buffer[0] == 'y' ) + result = 'Y'; + else if ( buffer[0] == 'N' || buffer[0] == 'n' ) + result = 'N'; + } + + return result; +} + + + +/* + * Show the player the choices of Fort, get their input, if the + * input is a valid choice (1,2,3) return it, otherwise keep + * prompting the user. + */ +int getFortChoice() +{ + int result = 0; + + while ( result == 0 ) + { + print( "" ); + print( "YOU MAY TRADE YOUR FURS AT FORT 1, FORT 2," ); + print( "OR FORT 3. FORT 1 IS FORT HOCHELAGA (MONTREAL)" ); + print( "AND IS UNDER THE PROTECTION OF THE FRENCH ARMY." ); + print( "FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE" ); + print( "PROTECTION OF THE FRENCH ARMY. HOWEVER, YOU MUST" ); + print( "MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS." ); + print( "FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL." ); + print( "YOU MUST CROSS THROUGH IROQUOIS LAND." ); + print( "ANSWER 1, 2, OR 3." ); + + result = getNumericInput(); /* get input from the player */ + } + + return result; +} + + +/* + * Print the description for the fort + */ +void showFortComment( int which_fort ) +{ + print( "" ); + if ( which_fort == FORT_MONTREAL ) + { + print( "YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT" ); + print( "IS FAR FROM ANY SEAPORT. THE VALUE" ); + print( "YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST" ); + print( "OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK." ); + } + else if ( which_fort == FORT_QUEBEC ) + { + print( "YOU HAVE CHOSEN A HARD ROUTE. IT IS, IN COMPARSION," ); + print( "HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN" ); + print( "THE ROUTE TO NEW YORK. YOU WILL RECEIVE AN AVERAGE VALUE" ); + print( "FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE." ); + } + else if ( which_fort == FORT_NEWYORK ) + { + print( "YOU HAVE CHOSEN THE MOST DIFFICULT ROUTE. AT" ); + print( "FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE" ); + print( "FOR YOUR FURS. THE COST OF YOUR SUPPLIES" ); + print( "WILL BE LOWER THAN AT ALL THE OTHER FORTS." ); + } + else + { + printf( "Internal error #1, fort %d does not exist\n", which_fort ); + exit( 1 ); /* you have a bug */ + } + print( "" ); +} + + +/* + * Prompt the player for how many of each fur type they want. + * Accept numeric inputs, re-prompting on incorrect input values + */ +void getFursPurchase( int *furs ) +{ + int i; + + printf( "YOUR %d FURS ARE DISTRIBUTED AMONG THE FOLLOWING\n", FUR_TYPE_COUNT ); + print( "KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX." ); + print( "" ); + + for ( i=0; i MAX_FURS ) + { + print( "" ); + print( "YOU MAY NOT HAVE THAT MANY FURS." ); + print( "DO NOT TRY TO CHEAT. I CAN ADD." ); + print( "YOU MUST START AGAIN." ); + print( "" ); + game_state = STATE_STARTING; /* T/N: Wow, harsh. */ + } + else + { + game_state = STATE_CHOOSING_FORT; + } + } + + else if ( game_state == STATE_CHOOSING_FORT ) + { + which_fort = getFortChoice(); + showFortComment( which_fort ); + print( "DO YOU WANT TO TRADE AT ANOTHER FORT?" ); + yes_or_no = getYesOrNo(); + if ( yes_or_no == 'N' ) + game_state = STATE_TRAVELLING; + } + + else if ( game_state == STATE_TRAVELLING ) + { + print( "" ); + if ( which_fort == FORT_MONTREAL ) + { + mink_price = ( ( 0.2 * randFloat() + 0.70 ) * 100 + 0.5 ) / 100; + ermine_price = ( ( 0.2 * randFloat() + 0.65 ) * 100 + 0.5 ) / 100; + beaver_price = ( ( 0.2 * randFloat() + 0.75 ) * 100 + 0.5 ) / 100; + fox_price = ( ( 0.2 * randFloat() + 0.80 ) * 100 + 0.5 ) / 100; + + print( "SUPPLIES AT FORT HOCHELAGA COST $150.00." ); + print( "YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00." ); + player_funds -= 160; + } + + else if ( which_fort == FORT_QUEBEC ) + { + mink_price = ( ( 0.30 * randFloat() + 0.85 ) * 100 + 0.5 ) / 100; + ermine_price = ( ( 0.15 * randFloat() + 0.80 ) * 100 + 0.5 ) / 100; + beaver_price = ( ( 0.20 * randFloat() + 0.90 ) * 100 + 0.5 ) / 100; + fox_price = ( ( 0.25 * randFloat() + 1.10 ) * 100 + 0.5 ) / 100; + event_picker = ( 10 * randFloat() ) + 1; + + if ( event_picker <= 2 ) + { + print( "YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS" ); + print( "THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND" ); + print( "THEM STOLEN WHEN YOU RETURNED." ); + player_furs[ FUR_BEAVER ] = 0; + } + else if ( event_picker <= 6 ) + { + print( "YOU ARRIVED SAFELY AT FORT STADACONA." ); + } + else if ( event_picker <= 8 ) + { + print( "YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU" ); + print( "LOST ALL YOUR FURS." ); + zeroInventory( player_furs ); + } + else if ( event_picker <= 10 ) + { + print( "YOUR FOX PELTS WERE NOT CURED PROPERLY." ); + print( "NO ONE WILL BUY THEM." ); + player_furs[ FUR_FOX ] = 0; + } + else + { + printf( "Internal Error #3, Out-of-bounds event_picker %d\n", event_picker ); + exit( 1 ); /* you have a bug */ + } + + print( "" ); + print( "SUPPLIES AT FORT STADACONA COST $125.00." ); + print( "YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00." ); + player_funds -= 140; + } + + else if ( which_fort == FORT_NEWYORK ) + { + mink_price = ( ( 0.15 * randFloat() + 1.05 ) * 100 + 0.5 ) / 100; + ermine_price = ( ( 0.15 * randFloat() + 0.95 ) * 100 + 0.5 ) / 100; + beaver_price = ( ( 0.25 * randFloat() + 1.00 ) * 100 + 0.5 ) / 100; + if ( fox_price < 0 ) + { + /* Original Bug? There is no Fox price generated for New York, + it will use any previous "D1" price. + So if there was no previous value, make one up */ + fox_price = ( ( 0.25 * randFloat() + 1.05 ) * 100 + 0.5 ) / 100; /* not in orginal code */ + } + event_picker = ( 10 * randFloat() ) + 1; + + if ( event_picker <= 2 ) + { + print( "YOU WERE ATTACKED BY A PARTY OF IROQUOIS." ); + print( "ALL PEOPLE IN YOUR TRADING GROUP WERE" ); + print( "KILLED. THIS ENDS THE GAME." ); + exit( 0 ); + } + else if ( event_picker <= 6 ) + { + print( "YOU WERE LUCKY. YOU ARRIVED SAFELY" ); + print( "AT FORT NEW YORK." ); + } + else if ( event_picker <= 8 ) + { + print( "YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY." ); + print( "HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND." ); + zeroInventory( player_furs ); + } + else if ( event_picker <= 10 ) + { + mink_price /= 2; + fox_price /= 2; + print( "YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP." ); + print( "YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS." ); + } + else + { + print( "Internal Error #4, Out-of-bounds event_picker %d\n" ); + exit( 1 ); /* you have a bug */ + } + + print( "" ); + print( "SUPPLIES AT NEW YORK COST $85.00." ); + print( "YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00." ); + player_funds -= 105; + } + + else + { + printf( "Internal error #2, fort %d does not exist\n", which_fort ); + exit( 1 ); /* you have a bug */ + } + + /* Calculate sales */ + beaver_value = beaver_price * player_furs[ FUR_BEAVER ]; + fox_value = fox_price * player_furs[ FUR_FOX ]; + ermine_value = ermine_price * player_furs[ FUR_ERMINE ]; + mink_value = mink_price * player_furs[ FUR_MINK ]; + + print( "" ); + printf( "YOUR BEAVER SOLD FOR $%6.2f\n", beaver_value ); + printf( "YOUR FOX SOLD FOR $%6.2f\n", fox_value ); + printf( "YOUR ERMINE SOLD FOR $%6.2f\n", ermine_value ); + printf( "YOUR MINK SOLD FOR $%6.2f\n", mink_value ); + + player_funds += beaver_value + fox_value + ermine_value + mink_value; + + print( "" ); + printf( "YOU NOW HAVE $ %1.2f INCLUDING YOUR PREVIOUS SAVINGS\n", player_funds ); + + print( "" ); + print( "DO YOU WANT TO TRADE FURS NEXT YEAR?" ); + yes_or_no = getYesOrNo(); + if ( yes_or_no == 'N' ) + exit( 0 ); /* STOP */ + else + game_state = STATE_TRADING; + + } + } + + return 0; /* exit OK */ +} + From cfb26209865b1825b50895b0eaec61fd1f2b62c1 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 11 Oct 2021 23:27:58 +1100 Subject: [PATCH 423/749] Implement 58 Love in C# --- 58 Love/csharp/Love.sln | 34 +++++++++++++++ 58 Love/csharp/Love/Input.cs | 26 +++++++++++ 58 Love/csharp/Love/Love.csproj | 11 +++++ 58 Love/csharp/Love/LovePattern.cs | 57 +++++++++++++++++++++++++ 58 Love/csharp/Love/Program.cs | 31 ++++++++++++++ 58 Love/csharp/Love/SourceCharacters.cs | 38 +++++++++++++++++ 58 Love/csharp/Love/Strings/Intro.txt | 10 +++++ 7 files changed, 207 insertions(+) create mode 100644 58 Love/csharp/Love.sln create mode 100644 58 Love/csharp/Love/Input.cs create mode 100644 58 Love/csharp/Love/Love.csproj create mode 100644 58 Love/csharp/Love/LovePattern.cs create mode 100644 58 Love/csharp/Love/Program.cs create mode 100644 58 Love/csharp/Love/SourceCharacters.cs create mode 100644 58 Love/csharp/Love/Strings/Intro.txt diff --git a/58 Love/csharp/Love.sln b/58 Love/csharp/Love.sln new file mode 100644 index 00000000..a89fd1d8 --- /dev/null +++ b/58 Love/csharp/Love.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Love", "Love\Love.csproj", "{FC74E025-A50D-4E19-9337-87F2E4A9F83E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Debug|x64.ActiveCfg = Debug|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Debug|x64.Build.0 = Debug|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Debug|x86.ActiveCfg = Debug|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Debug|x86.Build.0 = Debug|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Release|Any CPU.Build.0 = Release|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Release|x64.ActiveCfg = Release|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Release|x64.Build.0 = Release|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Release|x86.ActiveCfg = Release|Any CPU + {FC74E025-A50D-4E19-9337-87F2E4A9F83E}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/58 Love/csharp/Love/Input.cs b/58 Love/csharp/Love/Input.cs new file mode 100644 index 00000000..030e3ead --- /dev/null +++ b/58 Love/csharp/Love/Input.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace Love +{ + // Provides input methods which emulate the BASIC interpreter's keyboard input routines + internal static class Input + { + private static void Prompt(string text = "") => Console.Write($"{text}? "); + + public static string ReadLine(string prompt) + { + Prompt(prompt); + var values = ReadStrings(); + + if (values.Length > 1) + { + Console.WriteLine("!Extra input ingored"); + } + + return values[0]; + } + + private static string[] ReadStrings() => Console.ReadLine().Split(',', StringSplitOptions.TrimEntries); + } +} diff --git a/58 Love/csharp/Love/Love.csproj b/58 Love/csharp/Love/Love.csproj new file mode 100644 index 00000000..fc2efa30 --- /dev/null +++ b/58 Love/csharp/Love/Love.csproj @@ -0,0 +1,11 @@ + + + + Exe + net5.0 + + + + + + diff --git a/58 Love/csharp/Love/LovePattern.cs b/58 Love/csharp/Love/LovePattern.cs new file mode 100644 index 00000000..4c24ed84 --- /dev/null +++ b/58 Love/csharp/Love/LovePattern.cs @@ -0,0 +1,57 @@ +using System.IO; + +namespace Love +{ + internal class LovePattern + { + private readonly int[] _segmentLengths = new[] { + 60, 1, 12, 26, 9, 12, 3, 8, 24, 17, 8, 4, 6, 23, 21, 6, 4, 6, 22, 12, 5, + 6, 5, 4, 6, 21, 11, 8, 6, 4, 4, 6, 21, 10, 10, 5, 4, 4, 6, 21, 9, 11, 5, + 4, 4, 6, 21, 8, 11, 6, 4, 4, 6, 21, 7, 11, 7, 4, 4, 6, 21, 6, 11, 8, 4, + 4, 6, 19, 1, 1, 5, 11, 9, 4, 4, 6, 19, 1, 1, 5, 10, 10, 4, 4, 6, 18, 2, + 1, 6, 8, 11, 4, 4, 6, 17, 3, 1, 7, 5, 13, 4, 4, 6, 15, 5, 2, 23, 5, 1, + 29, 5, 17, 8, 1, 29, 9, 9, 12, 1, 13, 5, 40, 1, 1, 13, 5, 40, 1, 4, 6, + 13, 3, 10, 6, 12, 5, 1, 5, 6, 11, 3, 11, 6, 14, 3, 1, 5, 6, 11, 3, 11, + 6, 15, 2, 1, 6, 6, 9, 3, 12, 6, 16, 1, 1, 6, 6, 9, 3, 12, 6, 7, 1, 10, + 7, 6, 7, 3, 13, 6, 6, 2, 10, 7, 6, 7, 3, 13, 14, 10, 8, 6, 5, 3, 14, 6, + 6, 2, 10, 8, 6, 5, 3, 14, 6, 7, 1, 10, 9, 6, 3, 3, 15, 6, 16, 1, 1, 9, + 6, 3, 3, 15, 6, 15, 2, 1, 10, 6, 1, 3, 16, 6, 14, 3, 1, 10, 10, 16, 6, + 12, 5, 1, 11, 8, 13, 27, 1, 11, 8, 13, 27, 1, 60 + }; + + public int LineLength => 60; + + internal void Write(SourceCharacters source, Stream destination) + { + using var writer = new StreamWriter(destination); + + WritePadding(writer); + + var lineLength = 0; + + foreach (var segmentLength in _segmentLengths) + { + foreach (var character in source.GetCharacters(segmentLength)) + { + writer.Write(character); + } + lineLength += segmentLength; + if (lineLength >= LineLength) + { + writer.WriteLine(); + lineLength = 0; + } + } + + WritePadding(writer); + } + + private void WritePadding(StreamWriter writer) + { + for (int i = 0; i < 10; i++) + { + writer.WriteLine(); + } + } + } +} diff --git a/58 Love/csharp/Love/Program.cs b/58 Love/csharp/Love/Program.cs new file mode 100644 index 00000000..a9784466 --- /dev/null +++ b/58 Love/csharp/Love/Program.cs @@ -0,0 +1,31 @@ +using System; +using System.Reflection; + +namespace Love +{ + internal class Program + { + static void Main(string[] args) + { + DisplayIntro(); + + var message = Input.ReadLine("Your message, please"); + var pattern = new LovePattern(); + + var source = new SourceCharacters(pattern.LineLength, message); + + using var destination = Console.OpenStandardOutput(); + + pattern.Write(source, destination); + } + + private static void DisplayIntro() + { + using var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream("Love.Strings.Intro.txt"); + using var stdout = Console.OpenStandardOutput(); + + stream.CopyTo(stdout); + } + } +} diff --git a/58 Love/csharp/Love/SourceCharacters.cs b/58 Love/csharp/Love/SourceCharacters.cs new file mode 100644 index 00000000..64716f9c --- /dev/null +++ b/58 Love/csharp/Love/SourceCharacters.cs @@ -0,0 +1,38 @@ +using System; + +namespace Love +{ + internal class SourceCharacters + { + private readonly int _lineLength; + private readonly char[][] _chars; + private int _currentRow; + private int _currentIndex; + + public SourceCharacters(int lineLength, string message) + { + _lineLength = lineLength; + _chars = new[] { new char[lineLength], new char[lineLength] }; + + for (int i = 0; i < lineLength; i++) + { + _chars[0][i] = message[i % message.Length]; + _chars[1][i] = ' '; + } + } + + public ReadOnlySpan GetCharacters(int count) + { + var span = new ReadOnlySpan(_chars[_currentRow], _currentIndex, count); + + _currentRow = 1 - _currentRow; + _currentIndex += count; + if (_currentIndex >= _lineLength) + { + _currentIndex = _currentRow = 0; + } + + return span; + } + } +} diff --git a/58 Love/csharp/Love/Strings/Intro.txt b/58 Love/csharp/Love/Strings/Intro.txt new file mode 100644 index 00000000..bcf1afe2 --- /dev/null +++ b/58 Love/csharp/Love/Strings/Intro.txt @@ -0,0 +1,10 @@ + Love + Creative Computing Morristown, New Jersey + + + +A tribute to the great American artist, Robert Indiana. +His greatest work will be reproduced with a message of +your choice up to 60 characters. If you can't think of +a message, simply type the word 'LOVE' + From be308c8368d94ffcb8c5cf3deda3d6444137925c Mon Sep 17 00:00:00 2001 From: kingsley Date: Tue, 12 Oct 2021 09:04:46 +1100 Subject: [PATCH 424/749] New and shiny! --- 61 Math Dice/pascal/mathdice.pas | 129 +++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 61 Math Dice/pascal/mathdice.pas diff --git a/61 Math Dice/pascal/mathdice.pas b/61 Math Dice/pascal/mathdice.pas new file mode 100644 index 00000000..617f898f --- /dev/null +++ b/61 Math Dice/pascal/mathdice.pas @@ -0,0 +1,129 @@ +(* + * Ported from mathdice.bas to Pascal by krt@krt.com.au + * + * Compile with Free Pascal (https://www.freepascal.org/) ~ + * fpc mathdice.pas + *) + +program MathDice; + + +procedure printDice( face_value: integer ); +(* Prints a box with spots representing a die face for the user *) +begin + writeln( ' ----- ' ); + + if ( face_value = 1 ) then + writeln( 'I I' ) + else if ( ( face_value = 2 ) or ( face_value = 3 ) ) then + writeln( 'I * I' ) + else + writeln( 'I * * I' ); + + if ( ( face_value = 2 ) or ( face_value = 4 ) ) then + writeln( 'I I' ) + else if ( face_value = 6 ) then + writeln( 'I * * I' ) + else + writeln( 'I * I' ); + + if ( face_value = 1 ) then + writeln( 'I I' ) + else if ( ( face_value = 2 ) or ( face_value = 3 ) ) then + writeln( 'I * I' ) + else + writeln( 'I * * I' ); + + writeln( ' ----- ' ); +end; + + +procedure writeAtColumn( width: integer; words: string ); +(* Prints worth of spaces before the to justify the text *) +var + i: integer; +begin + for i := 1 to width do + write( ' ' ); + writeln( words ); +end; + + +function inputNumber(): integer; +(* Get a number from the player with error checking. + If they type a non-number, ask them again *) +var + player_input: string; (* The string entered by the player *) + player_answer: integer; (* The converted value of the text *) + input_error: integer; (* The letter's column that caused an error *) +begin + + input_error := 1; + while ( input_error <> 0 ) do + begin + readln( player_input ); + + val( player_input, player_answer, input_error ); + + if ( input_error <> 0 ) then + write( 'Please input a number: ' ); + end; + + inputNumber := player_answer; +end; + + + +var + dice1: integer; (* die 1 face value *) + dice2: integer; (* die 2 face value *) + answer: integer; (* the sum of the dice *) + player_answer: integer; (* The value entered by the player *) +begin + writeAtColumn( 31, 'MATH DICE' ); + writeAtColumn( 15, 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY' ); + writeAtColumn( 15, '(Ported to Pascal Oct 2012 krt@krt.com.au)' ); + writeln( '' ); + writeln( '' ); + writeln( '' ); + + writeln( 'THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE.' ); + writeln( 'WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION' ); + writeln( 'MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY.' ); + writeln( 'TO CONCLUDE THE LESSON, TYPE CONTROL-C AS YOUR ANSWER.' ); + writeln( '' ); + writeln( '' ); + + while ( true ) do + begin + dice1 := Random( 6 ) + 1; (* Random number between 1 and 6 (including) *) + dice2 := Random( 6 ) + 1; (* Random number between 1 and 6 (including) *) + answer := dice1 + dice2; + + (* Show the player two dice faces *) + printDice( dice1 ); + writeln( ' +' ); + printDice( dice2 ); + + write( ' = ' ); + + player_answer := inputNumber(); + + if ( player_answer <> answer ) then + begin + (* Give the player a second chance at the answer... *) + writeln( 'NO, COUNT THE SPOTS AND GIVE ANOTHER ANSWER.' ); + write( ' = ' ); + player_answer := inputNumber(); + end; + + if ( player_answer <> answer ) then + writeln( 'NO, THE ANSWER IS ', answer ) + else + writeln( 'RIGHT!' ); + + writeln( '' ); + writeln( 'THE DICE ROLL AGAIN...' ); + end; +end. + From edc46aa65f742f79304f049040c20e1e57021063 Mon Sep 17 00:00:00 2001 From: kingsley Date: Tue, 12 Oct 2021 09:05:04 +1100 Subject: [PATCH 425/749] Added some translation notes --- 61 Math Dice/pascal/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/61 Math Dice/pascal/README.md b/61 Math Dice/pascal/README.md index aa1b3ae5..0e40aa9f 100644 --- a/61 Math Dice/pascal/README.md +++ b/61 Math Dice/pascal/README.md @@ -1,3 +1,15 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language)) + +##### Translator Notes: +I tried to preserve as much of the original layout and flow of the code +as possible. I added a procedure for the printing of the die-face; and +another to read an integer from the player, as I was unhappy with the runtime +error message spat out when a non-number is given to readln(). + +I was torn between using the correct singular term "die" instead of "dice". +In the end I used a (poor?) combination of both. + +krt@krt.com.au 2020-10-12 + From 6d923cce9c96f5739469ddb0fc31ac03f834b7b0 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Tue, 19 Oct 2021 22:10:17 +1100 Subject: [PATCH 426/749] Add C# implementation of 87 3-D Plot --- 87 3-D Plot/csharp/Plot.sln | 34 +++++++++++++++++++++++++ 87 3-D Plot/csharp/Plot/Function.cs | 39 +++++++++++++++++++++++++++++ 87 3-D Plot/csharp/Plot/Plot.csproj | 8 ++++++ 87 3-D Plot/csharp/Plot/Program.cs | 38 ++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 87 3-D Plot/csharp/Plot.sln create mode 100644 87 3-D Plot/csharp/Plot/Function.cs create mode 100644 87 3-D Plot/csharp/Plot/Plot.csproj create mode 100644 87 3-D Plot/csharp/Plot/Program.cs diff --git a/87 3-D Plot/csharp/Plot.sln b/87 3-D Plot/csharp/Plot.sln new file mode 100644 index 00000000..1402bc2a --- /dev/null +++ b/87 3-D Plot/csharp/Plot.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plot", "Plot\Plot.csproj", "{8857AE83-F481-43B0-AA51-D78E1340BD93}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Debug|x64.ActiveCfg = Debug|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Debug|x64.Build.0 = Debug|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Debug|x86.ActiveCfg = Debug|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Debug|x86.Build.0 = Debug|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Release|Any CPU.Build.0 = Release|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Release|x64.ActiveCfg = Release|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Release|x64.Build.0 = Release|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Release|x86.ActiveCfg = Release|Any CPU + {8857AE83-F481-43B0-AA51-D78E1340BD93}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/87 3-D Plot/csharp/Plot/Function.cs b/87 3-D Plot/csharp/Plot/Function.cs new file mode 100644 index 00000000..3a459d4e --- /dev/null +++ b/87 3-D Plot/csharp/Plot/Function.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; + +namespace Plot +{ + internal static class Function + { + internal static IEnumerable> GetRows() + { + for (var x = -30f; x <= 30f; x += 1.5f) + { + yield return GetValues(x); + } + } + + private static IEnumerable GetValues(float x) + { + var zPrevious = 0; + var yLimit = 5 * (int)(Math.Sqrt(900 - x * x) / 5); + + for (var y = yLimit; y >= -yLimit; y -= 5) + { + var z = GetValue(x, y); + + if (z > zPrevious) + { + zPrevious = z; + yield return z; + } + } + } + + private static int GetValue(float x, float y) + { + var r = (float)Math.Sqrt(x * x + y * y); + return (int)(25 + 30 * Math.Exp(-r * r / 100) - 0.7f * y); + } + } +} diff --git a/87 3-D Plot/csharp/Plot/Plot.csproj b/87 3-D Plot/csharp/Plot/Plot.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/87 3-D Plot/csharp/Plot/Plot.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/87 3-D Plot/csharp/Plot/Program.cs b/87 3-D Plot/csharp/Plot/Program.cs new file mode 100644 index 00000000..132c41ef --- /dev/null +++ b/87 3-D Plot/csharp/Plot/Program.cs @@ -0,0 +1,38 @@ +using System; + +namespace Plot +{ + class Program + { + static void Main(string[] args) + { + PrintTitle(); + + foreach (var row in Function.GetRows()) + { + foreach (var z in row) + { + Plot(z); + } + Console.WriteLine(); + } + } + + private static void PrintTitle() + { + Console.WriteLine(" 3D Plot"); + Console.WriteLine(" Creative Computing Morristown, New Jersey"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + private static void Plot(int z) + { + var x = Console.GetCursorPosition().Top; + Console.SetCursorPosition(z, x); + Console.Write("*"); + } + } +} From 6b194366fb38ce04927e75e09fc2555264aeb58d Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 30 Oct 2021 22:32:22 +1100 Subject: [PATCH 427/749] Add project sturcture --- 90 Tower/csharp/Tower.sln | 34 ++++++++++++++++++++++++++++++ 90 Tower/csharp/Tower/Program.cs | 12 +++++++++++ 90 Tower/csharp/Tower/Tower.csproj | 8 +++++++ 3 files changed, 54 insertions(+) create mode 100644 90 Tower/csharp/Tower.sln create mode 100644 90 Tower/csharp/Tower/Program.cs create mode 100644 90 Tower/csharp/Tower/Tower.csproj diff --git a/90 Tower/csharp/Tower.sln b/90 Tower/csharp/Tower.sln new file mode 100644 index 00000000..2c6e524d --- /dev/null +++ b/90 Tower/csharp/Tower.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tower", "tower\Tower.csproj", "{2E14FCD5-A52C-4292-A7F4-0C7E5780C962}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Debug|x64.ActiveCfg = Debug|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Debug|x64.Build.0 = Debug|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Debug|x86.Build.0 = Debug|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Release|Any CPU.Build.0 = Release|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Release|x64.ActiveCfg = Release|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Release|x64.Build.0 = Release|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Release|x86.ActiveCfg = Release|Any CPU + {2E14FCD5-A52C-4292-A7F4-0C7E5780C962}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/90 Tower/csharp/Tower/Program.cs b/90 Tower/csharp/Tower/Program.cs new file mode 100644 index 00000000..4793b817 --- /dev/null +++ b/90 Tower/csharp/Tower/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace Tower +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/90 Tower/csharp/Tower/Tower.csproj b/90 Tower/csharp/Tower/Tower.csproj new file mode 100644 index 00000000..20827042 --- /dev/null +++ b/90 Tower/csharp/Tower/Tower.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + From ee8322dcafd851837eaf93ed06d72d4ebfe1f586 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 30 Oct 2021 22:33:49 +1100 Subject: [PATCH 428/749] Add string resources --- .../Tower/Resources/Congratulations.txt | 2 + .../Tower/Resources/DiskCountPrompt.txt | 1 + .../csharp/Tower/Resources/DiskCountQuit.txt | 2 + .../csharp/Tower/Resources/DiskCountRetry.txt | 1 + .../csharp/Tower/Resources/DiskPrompt.txt | 1 + 90 Tower/csharp/Tower/Resources/DiskQuit.txt | 1 + 90 Tower/csharp/Tower/Resources/DiskRetry.txt | 1 + .../Tower/Resources/DiskUnavailable.txt | 1 + .../csharp/Tower/Resources/IllegalMove.txt | 3 ++ .../csharp/Tower/Resources/Instructions.txt | 10 +++++ 90 Tower/csharp/Tower/Resources/Intro.txt | 11 ++++++ .../csharp/Tower/Resources/NeedlePrompt.txt | 1 + .../csharp/Tower/Resources/NeedleQuit.txt | 2 + .../csharp/Tower/Resources/NeedleRetry.txt | 2 + .../Tower/Resources/PlayAgainPrompt.txt | 2 + 90 Tower/csharp/Tower/Resources/Strings.cs | 38 +++++++++++++++++++ 90 Tower/csharp/Tower/Resources/Thanks.txt | 2 + 90 Tower/csharp/Tower/Resources/Title.txt | 11 ++++++ .../csharp/Tower/Resources/TooManyMoves.txt | 2 + .../csharp/Tower/Resources/YesNoPrompt.txt | 2 + 90 Tower/csharp/Tower/Tower.csproj | 4 ++ 21 files changed, 100 insertions(+) create mode 100644 90 Tower/csharp/Tower/Resources/Congratulations.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskCountPrompt.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskCountQuit.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskCountRetry.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskPrompt.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskQuit.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskRetry.txt create mode 100644 90 Tower/csharp/Tower/Resources/DiskUnavailable.txt create mode 100644 90 Tower/csharp/Tower/Resources/IllegalMove.txt create mode 100644 90 Tower/csharp/Tower/Resources/Instructions.txt create mode 100644 90 Tower/csharp/Tower/Resources/Intro.txt create mode 100644 90 Tower/csharp/Tower/Resources/NeedlePrompt.txt create mode 100644 90 Tower/csharp/Tower/Resources/NeedleQuit.txt create mode 100644 90 Tower/csharp/Tower/Resources/NeedleRetry.txt create mode 100644 90 Tower/csharp/Tower/Resources/PlayAgainPrompt.txt create mode 100644 90 Tower/csharp/Tower/Resources/Strings.cs create mode 100644 90 Tower/csharp/Tower/Resources/Thanks.txt create mode 100644 90 Tower/csharp/Tower/Resources/Title.txt create mode 100644 90 Tower/csharp/Tower/Resources/TooManyMoves.txt create mode 100644 90 Tower/csharp/Tower/Resources/YesNoPrompt.txt diff --git a/90 Tower/csharp/Tower/Resources/Congratulations.txt b/90 Tower/csharp/Tower/Resources/Congratulations.txt new file mode 100644 index 00000000..332297b2 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/Congratulations.txt @@ -0,0 +1,2 @@ + +Congratulations diff --git a/90 Tower/csharp/Tower/Resources/DiskCountPrompt.txt b/90 Tower/csharp/Tower/Resources/DiskCountPrompt.txt new file mode 100644 index 00000000..a45c3461 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskCountPrompt.txt @@ -0,0 +1 @@ +How many disks do you want to move (7 is max) \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/DiskCountQuit.txt b/90 Tower/csharp/Tower/Resources/DiskCountQuit.txt new file mode 100644 index 00000000..b573854d --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskCountQuit.txt @@ -0,0 +1,2 @@ +All right, wise guy, if you can't play the game right, I'll +just take my puzzle and go home. So long. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/DiskCountRetry.txt b/90 Tower/csharp/Tower/Resources/DiskCountRetry.txt new file mode 100644 index 00000000..c8ec4b10 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskCountRetry.txt @@ -0,0 +1 @@ +Sorry, but i can't do that job for you. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/DiskPrompt.txt b/90 Tower/csharp/Tower/Resources/DiskPrompt.txt new file mode 100644 index 00000000..a7f127db --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskPrompt.txt @@ -0,0 +1 @@ +Which disk would you like to move \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/DiskQuit.txt b/90 Tower/csharp/Tower/Resources/DiskQuit.txt new file mode 100644 index 00000000..56d19d5f --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskQuit.txt @@ -0,0 +1 @@ +Stop wasting my time. Go bother someone else. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/DiskRetry.txt b/90 Tower/csharp/Tower/Resources/DiskRetry.txt new file mode 100644 index 00000000..1efe29b4 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskRetry.txt @@ -0,0 +1 @@ +Illegal entry... You may only type 3, 5, 7, 9, 11, 13, or 15. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/DiskUnavailable.txt b/90 Tower/csharp/Tower/Resources/DiskUnavailable.txt new file mode 100644 index 00000000..721ddccf --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskUnavailable.txt @@ -0,0 +1 @@ +That disk is below another one. Make another choice. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/IllegalMove.txt b/90 Tower/csharp/Tower/Resources/IllegalMove.txt new file mode 100644 index 00000000..243c8d8f --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/IllegalMove.txt @@ -0,0 +1,3 @@ +You can't place a larger disk on top of a smaller one, +it might crush it! +Now then, \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/Instructions.txt b/90 Tower/csharp/Tower/Resources/Instructions.txt new file mode 100644 index 00000000..93c71b8d --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/Instructions.txt @@ -0,0 +1,10 @@ +In this program, we shall refer to disks by numerical code. +3 will represent the smallest disk, 5 the next size, +7 the next, and so on, up to 15. If you do the puzzle with +2 disks, their code names would be 13 and 15. With 3 disks +the code names would be 11, 13 and 15, etc. The needles +are numbered from left to right, 1 to 3. We will +startup with the disks on needle 1, and attempt to move them +to needle 3. + +Good luck! diff --git a/90 Tower/csharp/Tower/Resources/Intro.txt b/90 Tower/csharp/Tower/Resources/Intro.txt new file mode 100644 index 00000000..a88049a9 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/Intro.txt @@ -0,0 +1,11 @@ + Towers + Creative Computing Morristown, New Jersey + + + +Towers of Hanoi puzzle. + +You must transfer the disks from the left to the right +tower, one at a time, never putting a larger dish on a +smaller disk. + diff --git a/90 Tower/csharp/Tower/Resources/NeedlePrompt.txt b/90 Tower/csharp/Tower/Resources/NeedlePrompt.txt new file mode 100644 index 00000000..59dcebe7 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/NeedlePrompt.txt @@ -0,0 +1 @@ +Place disk on which needle \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/NeedleQuit.txt b/90 Tower/csharp/Tower/Resources/NeedleQuit.txt new file mode 100644 index 00000000..e75e3d87 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/NeedleQuit.txt @@ -0,0 +1,2 @@ +I tried to warn you, but you wouldn't listen, +Bye bye, big shot. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/NeedleRetry.txt b/90 Tower/csharp/Tower/Resources/NeedleRetry.txt new file mode 100644 index 00000000..19701eec --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/NeedleRetry.txt @@ -0,0 +1,2 @@ +I'll assume you hit the wrong key this time. But watch it, +I only allow one mistake \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/PlayAgainPrompt.txt b/90 Tower/csharp/Tower/Resources/PlayAgainPrompt.txt new file mode 100644 index 00000000..3972e7bd --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/PlayAgainPrompt.txt @@ -0,0 +1,2 @@ + +Try again (Yes or No) \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/Strings.cs b/90 Tower/csharp/Tower/Resources/Strings.cs new file mode 100644 index 00000000..62b84d0a --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/Strings.cs @@ -0,0 +1,38 @@ +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Tower.Resources +{ + internal static class Strings + { + internal static string Congratulations => GetResource(); + internal static string DiskCountPrompt => GetResource(); + internal static string DiskCountQuit => GetResource(); + internal static string DiskCountRetry => GetResource(); + internal static string DiskPrompt => GetResource(); + internal static string DiskQuit => GetResource(); + internal static string DiskRetry => GetResource(); + internal static string DiskUnavailable => GetResource(); + internal static string IllegalMove => GetResource(); + internal static string Instructions => GetResource(); + internal static string Intro => GetResource(); + internal static string NeedlePrompt => GetResource(); + internal static string NeedleQuit => GetResource(); + internal static string NeedleRetry => GetResource(); + internal static string PlayAgainPrompt => GetResource(); + internal static string Thanks => GetResource(); + internal static string Title => GetResource(); + internal static string TooManyMoves => GetResource(); + internal static string YesNoPrompt => GetResource(); + + private static string GetResource([CallerMemberName] string name = "") + { + var streamName = $"Tower.Resources.{name}.txt"; + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(streamName); + using var reader = new StreamReader(stream); + + return reader.ReadToEnd(); + } + } +} diff --git a/90 Tower/csharp/Tower/Resources/Thanks.txt b/90 Tower/csharp/Tower/Resources/Thanks.txt new file mode 100644 index 00000000..435d89c7 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/Thanks.txt @@ -0,0 +1,2 @@ + +Thanks for the game! diff --git a/90 Tower/csharp/Tower/Resources/Title.txt b/90 Tower/csharp/Tower/Resources/Title.txt new file mode 100644 index 00000000..a88049a9 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/Title.txt @@ -0,0 +1,11 @@ + Towers + Creative Computing Morristown, New Jersey + + + +Towers of Hanoi puzzle. + +You must transfer the disks from the left to the right +tower, one at a time, never putting a larger dish on a +smaller disk. + diff --git a/90 Tower/csharp/Tower/Resources/TooManyMoves.txt b/90 Tower/csharp/Tower/Resources/TooManyMoves.txt new file mode 100644 index 00000000..c517218e --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/TooManyMoves.txt @@ -0,0 +1,2 @@ +Sorry, but i have orders to stop is you make more than +128 moves. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/YesNoPrompt.txt b/90 Tower/csharp/Tower/Resources/YesNoPrompt.txt new file mode 100644 index 00000000..62612ce2 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/YesNoPrompt.txt @@ -0,0 +1,2 @@ + +'Yes' or 'No' please \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Tower.csproj b/90 Tower/csharp/Tower/Tower.csproj index 20827042..c0de0594 100644 --- a/90 Tower/csharp/Tower/Tower.csproj +++ b/90 Tower/csharp/Tower/Tower.csproj @@ -5,4 +5,8 @@ net5.0 + + + + From db11f064e9e8ca3e62f5c25c689b0b1223ed5eda Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 30 Oct 2021 23:07:50 +1100 Subject: [PATCH 429/749] Add imput routines --- 90 Tower/csharp/Tower/UI/Input.cs | 83 ++++++++++++++++++++++++++++++ 90 Tower/csharp/Tower/UI/Prompt.cs | 41 +++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 90 Tower/csharp/Tower/UI/Input.cs create mode 100644 90 Tower/csharp/Tower/UI/Prompt.cs diff --git a/90 Tower/csharp/Tower/UI/Input.cs b/90 Tower/csharp/Tower/UI/Input.cs new file mode 100644 index 00000000..9b2d3747 --- /dev/null +++ b/90 Tower/csharp/Tower/UI/Input.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; + +namespace Tower.UI +{ + // Provides input methods which emulate the BASIC interpreter's keyboard input routines + internal static class Input + { + private static void Prompt(string text = "") => Console.Write($"{text}? "); + + internal static bool ReadYesNo(string prompt, string retryPrompt) + { + var response = ReadString(prompt); + + while (true) + { + if (response.Equals("No", StringComparison.InvariantCultureIgnoreCase)) { return false; } + if (response.Equals("Yes", StringComparison.InvariantCultureIgnoreCase)) { return true; } + response = ReadString(retryPrompt); + } + } + + internal static bool TryReadNumber(Prompt prompt, out int number) + { + var message = prompt.Message; + + for (int retryCount = 0; retryCount <= prompt.RetriesAllowed; retryCount++) + { + if (retryCount > 0) { Console.WriteLine(prompt.RetryMessage); } + + if (prompt.TryValidateResponse(ReadNumber(message), out number)) { return true; } + + if (!prompt.RepeatPrompt) { message = ""; } + } + + Console.WriteLine(prompt.QuitMessage); + + number = 0; + return false; + } + + private static float ReadNumber(string prompt) + { + Prompt(prompt); + + while (true) + { + var inputValues = ReadStrings(); + + if (TryParseNumber(inputValues[0], out var number)) + { + if (inputValues.Length > 1) + { + Console.WriteLine("!Extra input ingored"); + } + + return number; + } + } + } + + private static string ReadString(string prompt) + { + var inputValues = ReadStrings(); + if (inputValues.Length > 1) + { + Console.WriteLine("!Extra input ingored"); + } + return inputValues[0]; + } + + private static string[] ReadStrings() => Console.ReadLine().Split(',', StringSplitOptions.TrimEntries); + + private static bool TryParseNumber(string text, out float number) + { + if (float.TryParse(text, out number)) { return true; } + + Console.WriteLine("!Number expected - retry input line"); + number = default; + return false; + } + } +} diff --git a/90 Tower/csharp/Tower/UI/Prompt.cs b/90 Tower/csharp/Tower/UI/Prompt.cs new file mode 100644 index 00000000..bc83f7a6 --- /dev/null +++ b/90 Tower/csharp/Tower/UI/Prompt.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Linq; +using static Tower.Resources.Strings; + +namespace Tower.UI +{ + internal class Prompt + { + public static Prompt DiskCount = + new(DiskCountPrompt, DiskCountRetry, DiskCountQuit, 1, 2, 3, 4, 5, 6, 7) { RetriesAllowed = 2 }; + + public static Prompt Disk = + new(DiskPrompt, DiskRetry, DiskQuit, 3, 5, 7, 9, 11, 13, 15) { RepeatPrompt = false }; + + public static Prompt Needle = new(NeedlePrompt, NeedleRetry, NeedleQuit, 1, 2, 3); + + private readonly HashSet _validValues; + + private Prompt(string prompt, string retryMessage, string quitMessage, params int[] validValues) + { + Message = prompt; + RetryMessage = retryMessage; + QuitMessage = quitMessage; + _validValues = validValues.ToHashSet(); + RetriesAllowed = 1; + RepeatPrompt = true; + } + + public string Message { get; } + public string RetryMessage { get; } + public string QuitMessage { get; } + public int RetriesAllowed { get; private set; } + public bool RepeatPrompt { get; private set; } + + public bool TryValidateResponse(float number, out int integer) + { + integer = (int)number; + return integer == number && _validValues.Contains(integer); + } + } +} \ No newline at end of file From 882f51057d5cdca3d559eb2451b7fe7b369af3c5 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 30 Oct 2021 23:52:13 +1100 Subject: [PATCH 430/749] Add tower models --- 90 Tower/csharp/Tower/Models/Needle.cs | 31 +++++++++++++ 90 Tower/csharp/Tower/Models/Towers.cs | 60 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 90 Tower/csharp/Tower/Models/Needle.cs create mode 100644 90 Tower/csharp/Tower/Models/Towers.cs diff --git a/90 Tower/csharp/Tower/Models/Needle.cs b/90 Tower/csharp/Tower/Models/Needle.cs new file mode 100644 index 00000000..e373efe9 --- /dev/null +++ b/90 Tower/csharp/Tower/Models/Needle.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Tower.Models +{ + internal class Needle : IEnumerable + { + private readonly Stack _disks = new Stack(); + + public int Top => _disks.TryPeek(out var disc) ? disc : default; + + public bool TryPut(int disc) + { + if (_disks.Count == 0 || disc < _disks.Peek()) + { + _disks.Push(disc); + return true; + } + + return false; + } + + public bool TryGetTopDisk(out int disk) => _disks.TryPop(out disk); + + public IEnumerator GetEnumerator() => + Enumerable.Repeat(1, 7 - _disks.Count).Concat(_disks).GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Models/Towers.cs b/90 Tower/csharp/Tower/Models/Towers.cs new file mode 100644 index 00000000..830fa631 --- /dev/null +++ b/90 Tower/csharp/Tower/Models/Towers.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Tower.Models +{ + internal class Towers : IEnumerable<(int, int, int)> + { + private readonly Needle[] _needles = new[] { new Needle(), new Needle(), new Needle() }; + + public bool TryFindDisk(int disk, out int needle) + { + for (needle = 1; needle <= 3; needle++) + { + if (_needles[needle].Top == disk) { return true; } + } + + return false; + } + + public bool TryMoveDisk(int from, int to) + { + if (!_needles[from].TryGetTopDisk(out var disk)) + { + throw new InvalidOperationException($"Needle {from} is empty"); + } + + if (_needles[to].TryPut(disk)) { return true; } + + _needles[from].TryPut(disk); + return false; + } + + public IEnumerator<(int, int, int)> GetEnumerator() => new TowersEnumerator(_needles); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + private class TowersEnumerator : IEnumerator<(int First, int Second, int Third)> + { + private readonly List> _enumerators; + + public TowersEnumerator(Needle[] needles) + { + _enumerators = needles.Select(n => n.GetEnumerator()).ToList(); + } + + public (int First, int Second, int Third) Current => + (_enumerators[0].Current, _enumerators[1].Current, _enumerators[2].Current); + + object IEnumerator.Current => Current; + + public void Dispose() => _enumerators.ForEach(e => e.Dispose()); + + public bool MoveNext() => _enumerators.All(e => e.MoveNext()); + + public void Reset() => _enumerators.ForEach(e => e.Reset()); + } + } +} \ No newline at end of file From 26374f143cbb7400d96b1772382b9b7c044663b3 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 31 Oct 2021 10:46:39 +1100 Subject: [PATCH 431/749] Add TowerDisplay --- 90 Tower/csharp/Tower/Models/Needle.cs | 10 +++---- 90 Tower/csharp/Tower/Models/Towers.cs | 4 +-- 90 Tower/csharp/Tower/UI/TowerDisplay.cs | 37 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 90 Tower/csharp/Tower/UI/TowerDisplay.cs diff --git a/90 Tower/csharp/Tower/Models/Needle.cs b/90 Tower/csharp/Tower/Models/Needle.cs index e373efe9..f47329d6 100644 --- a/90 Tower/csharp/Tower/Models/Needle.cs +++ b/90 Tower/csharp/Tower/Models/Needle.cs @@ -8,13 +8,13 @@ namespace Tower.Models { private readonly Stack _disks = new Stack(); - public int Top => _disks.TryPeek(out var disc) ? disc : default; + public int Top => _disks.TryPeek(out var disk) ? disk : default; - public bool TryPut(int disc) + public bool TryPut(int disk) { - if (_disks.Count == 0 || disc < _disks.Peek()) + if (_disks.Count == 0 || disk < _disks.Peek()) { - _disks.Push(disc); + _disks.Push(disk); return true; } @@ -24,7 +24,7 @@ namespace Tower.Models public bool TryGetTopDisk(out int disk) => _disks.TryPop(out disk); public IEnumerator GetEnumerator() => - Enumerable.Repeat(1, 7 - _disks.Count).Concat(_disks).GetEnumerator(); + Enumerable.Repeat(0, 7 - _disks.Count).Concat(_disks).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/90 Tower/csharp/Tower/Models/Towers.cs b/90 Tower/csharp/Tower/Models/Towers.cs index 830fa631..7672ad52 100644 --- a/90 Tower/csharp/Tower/Models/Towers.cs +++ b/90 Tower/csharp/Tower/Models/Towers.cs @@ -36,7 +36,7 @@ namespace Tower.Models IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - private class TowersEnumerator : IEnumerator<(int First, int Second, int Third)> + private class TowersEnumerator : IEnumerator<(int, int, int)> { private readonly List> _enumerators; @@ -45,7 +45,7 @@ namespace Tower.Models _enumerators = needles.Select(n => n.GetEnumerator()).ToList(); } - public (int First, int Second, int Third) Current => + public (int, int, int) Current => (_enumerators[0].Current, _enumerators[1].Current, _enumerators[2].Current); object IEnumerator.Current => Current; diff --git a/90 Tower/csharp/Tower/UI/TowerDisplay.cs b/90 Tower/csharp/Tower/UI/TowerDisplay.cs new file mode 100644 index 00000000..f8a56261 --- /dev/null +++ b/90 Tower/csharp/Tower/UI/TowerDisplay.cs @@ -0,0 +1,37 @@ +using System; +using System.Text; +using Tower.Models; + +namespace Tower.UI +{ + internal class TowerDisplay + { + private readonly Towers _towers; + + public TowerDisplay(Towers towers) + { + _towers = towers; + } + + public override string ToString() + { + var builder = new StringBuilder(); + + foreach (var row in _towers) + { + AddTower(row.Item1); + AddTower(row.Item2); + AddTower(row.Item3); + builder.AppendLine(); + } + + return builder.ToString(); + + void AddTower(int size) + { + var padding = 10 - size / 2; + builder.Append(' ', padding).Append('*', Math.Max(1, size)).Append(' ', padding); + } + } + } +} \ No newline at end of file From d26dbf036a3cebfeddd52932baa3a18d4d8f93f6 Mon Sep 17 00:00:00 2001 From: Chris Reuter Date: Sun, 21 Nov 2021 18:30:21 -0500 Subject: [PATCH 432/749] Removed spaces from top-level directory names. Spaces tend to cause annoyances in a Unix-style shell environment. This change fixes that. --- {01 Acey Ducey => 01_Acey_Ducey}/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/aceyducey.bas | 0 {01 Acey Ducey => 01_Acey_Ducey}/csharp/AceyDucey.csproj | 0 {01 Acey Ducey => 01_Acey_Ducey}/csharp/AceyDucey.sln | 0 {01 Acey Ducey => 01_Acey_Ducey}/csharp/Game.cs | 0 {01 Acey Ducey => 01_Acey_Ducey}/csharp/GameState.cs | 0 {01 Acey Ducey => 01_Acey_Ducey}/csharp/Program.cs | 0 {01 Acey Ducey => 01_Acey_Ducey}/csharp/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/java/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/java/src/AceyDucey.java | 0 {01 Acey Ducey => 01_Acey_Ducey}/java/src/AceyDuceyGame.java | 0 {01 Acey Ducey => 01_Acey_Ducey}/java/src/Card.java | 0 {01 Acey Ducey => 01_Acey_Ducey}/javascript/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/javascript/aceyducey.html | 0 {01 Acey Ducey => 01_Acey_Ducey}/javascript/aceyducey.js | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/.gitattributes | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/.gitignore | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/README.md | 0 .../pascal/object-pascal/aceyducey.lpi | 0 .../pascal/object-pascal/aceyducey.pas | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/object-pascal/deck.pas | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/object-pascal/game.pas | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/simple/aceyducey.lpi | 0 {01 Acey Ducey => 01_Acey_Ducey}/pascal/simple/aceyducey.pas | 0 {01 Acey Ducey => 01_Acey_Ducey}/perl/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/perl/aceyducey.pl | 0 {01 Acey Ducey => 01_Acey_Ducey}/python/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/python/acey_ducey.py | 0 {01 Acey Ducey => 01_Acey_Ducey}/python/aceyducey.py | 0 {01 Acey Ducey => 01_Acey_Ducey}/ruby/README.md | 0 {01 Acey Ducey => 01_Acey_Ducey}/ruby/aceyducey.rb | 0 {01 Acey Ducey => 01_Acey_Ducey}/vbnet/README.md | 0 {02 Amazing => 02_Amazing}/README.md | 0 {02 Amazing => 02_Amazing}/amazing.bas | 0 {02 Amazing => 02_Amazing}/csharp/Amazing.cs | 0 {02 Amazing => 02_Amazing}/csharp/Amazing.csproj | 0 {02 Amazing => 02_Amazing}/csharp/Amazing.sln | 0 {02 Amazing => 02_Amazing}/csharp/README.md | 0 {02 Amazing => 02_Amazing}/java/Amazing.java | 0 {02 Amazing => 02_Amazing}/java/AmazingGame.java | 0 {02 Amazing => 02_Amazing}/java/README.md | 0 {02 Amazing => 02_Amazing}/javascript/README.md | 0 {02 Amazing => 02_Amazing}/javascript/amazing.html | 0 {02 Amazing => 02_Amazing}/javascript/amazing.js | 0 {02 Amazing => 02_Amazing}/pascal/.gitattributes | 0 {02 Amazing => 02_Amazing}/pascal/.gitignore | 0 {02 Amazing => 02_Amazing}/pascal/README.md | 0 {02 Amazing => 02_Amazing}/pascal/object-pascal/amazing.lpi | 0 {02 Amazing => 02_Amazing}/pascal/object-pascal/amazing.pas | 0 .../pascal/object-pascal/amazingapplication.pas | 0 {02 Amazing => 02_Amazing}/pascal/object-pascal/maze.pas | 0 {02 Amazing => 02_Amazing}/pascal/object-pascal/room.pas | 0 {02 Amazing => 02_Amazing}/pascal/simple/amazing.lpi | 0 {02 Amazing => 02_Amazing}/pascal/simple/amazing.pas | 0 {02 Amazing => 02_Amazing}/perl/README.md | 0 {02 Amazing => 02_Amazing}/python/README.md | 0 {02 Amazing => 02_Amazing}/python/amazing.py | 0 {02 Amazing => 02_Amazing}/ruby/README.md | 0 {02 Amazing => 02_Amazing}/ruby/amazing.rb | 0 {02 Amazing => 02_Amazing}/vbnet/README.md | 0 {03 Animal => 03_Animal}/README.md | 0 {03 Animal => 03_Animal}/animal.bas | 0 {03 Animal => 03_Animal}/csharp/Animal.csproj | 0 {03 Animal => 03_Animal}/csharp/Animal.sln | 0 {03 Animal => 03_Animal}/csharp/Branch.cs | 0 {03 Animal => 03_Animal}/csharp/Program.cs | 0 {03 Animal => 03_Animal}/csharp/README.md | 0 {03 Animal => 03_Animal}/java/Animal.java | 0 {03 Animal => 03_Animal}/java/README.md | 0 {03 Animal => 03_Animal}/javascript/README.md | 0 {03 Animal => 03_Animal}/javascript/animal.html | 0 {03 Animal => 03_Animal}/javascript/animal.js | 0 {03 Animal => 03_Animal}/pascal/README.md | 0 {03 Animal => 03_Animal}/perl/README.md | 0 {03 Animal => 03_Animal}/python/README.md | 0 {03 Animal => 03_Animal}/python/animal.py | 0 {03 Animal => 03_Animal}/ruby/README.md | 0 {03 Animal => 03_Animal}/ruby/animal.rb | 0 {03 Animal => 03_Animal}/vbnet/README.md | 0 {04 Awari => 04_Awari}/README.md | 0 {04 Awari => 04_Awari}/awari.bas | 0 {04 Awari => 04_Awari}/csharp/README.md | 0 {04 Awari => 04_Awari}/java/Awari.java | 0 {04 Awari => 04_Awari}/java/AwariGame.java | 0 {04 Awari => 04_Awari}/java/README.md | 0 {04 Awari => 04_Awari}/javascript/README.md | 0 {04 Awari => 04_Awari}/javascript/awari.html | 0 {04 Awari => 04_Awari}/javascript/awari.js | 0 {04 Awari => 04_Awari}/pascal/README.md | 0 {04 Awari => 04_Awari}/perl/README.md | 0 {04 Awari => 04_Awari}/python/README.md | 0 {04 Awari => 04_Awari}/python/awari.py | 0 {04 Awari => 04_Awari}/ruby/README.md | 0 {04 Awari => 04_Awari}/vbnet/README.md | 0 {05 Bagels => 05_Bagels}/README.md | 0 {05 Bagels => 05_Bagels}/bagels.bas | 0 {05 Bagels => 05_Bagels}/csharp/BagelNumber.cs | 0 {05 Bagels => 05_Bagels}/csharp/Bagels.csproj | 0 {05 Bagels => 05_Bagels}/csharp/Game.cs | 0 {05 Bagels => 05_Bagels}/csharp/GameBase.cs | 0 {05 Bagels => 05_Bagels}/csharp/Program.cs | 0 {05 Bagels => 05_Bagels}/csharp/README.md | 0 {05 Bagels => 05_Bagels}/java/BagelGame.java | 0 {05 Bagels => 05_Bagels}/java/Bagels.java | 0 {05 Bagels => 05_Bagels}/java/README.md | 0 {05 Bagels => 05_Bagels}/javascript/README.md | 0 {05 Bagels => 05_Bagels}/javascript/bagels.html | 0 {05 Bagels => 05_Bagels}/javascript/bagels.js | 0 {05 Bagels => 05_Bagels}/pascal/README.md | 0 {05 Bagels => 05_Bagels}/perl/README.md | 0 {05 Bagels => 05_Bagels}/python/README.md | 0 {05 Bagels => 05_Bagels}/python/bagels.py | 0 {05 Bagels => 05_Bagels}/ruby/README.md | 0 {05 Bagels => 05_Bagels}/ruby/bagels.rb | 0 {05 Bagels => 05_Bagels}/vbnet/README.md | 0 {06 Banner => 06_Banner}/README.md | 0 {06 Banner => 06_Banner}/banner.bas | 0 {06 Banner => 06_Banner}/csharp/README.md | 0 {06 Banner => 06_Banner}/csharp/banner.cs | 0 {06 Banner => 06_Banner}/csharp/banner.csproj | 0 {06 Banner => 06_Banner}/csharp/banner.sln | 0 {06 Banner => 06_Banner}/java/Banner.java | 0 {06 Banner => 06_Banner}/java/README.md | 0 {06 Banner => 06_Banner}/javascript/README.md | 0 {06 Banner => 06_Banner}/javascript/banner.html | 0 {06 Banner => 06_Banner}/javascript/banner.js | 0 {06 Banner => 06_Banner}/pascal/README.md | 0 {06 Banner => 06_Banner}/perl/README.md | 0 {06 Banner => 06_Banner}/python/README.md | 0 {06 Banner => 06_Banner}/python/banner.py | 0 {06 Banner => 06_Banner}/ruby/README.md | 0 {06 Banner => 06_Banner}/vbnet/README.md | 0 {06 Banner => 06_Banner}/vbnet/banner.sln | 0 {06 Banner => 06_Banner}/vbnet/banner.vb | 0 {06 Banner => 06_Banner}/vbnet/banner.vbproj | 0 {07 Basketball => 07_Basketball}/README.md | 0 {07 Basketball => 07_Basketball}/basketball.bas | 0 {07 Basketball => 07_Basketball}/csharp/README.md | 0 {07 Basketball => 07_Basketball}/java/README.md | 0 {07 Basketball => 07_Basketball}/javascript/README.md | 0 {07 Basketball => 07_Basketball}/javascript/basketball.html | 0 {07 Basketball => 07_Basketball}/javascript/basketball.js | 0 {07 Basketball => 07_Basketball}/pascal/README.md | 0 {07 Basketball => 07_Basketball}/perl/README.md | 0 {07 Basketball => 07_Basketball}/python/README.md | 0 {07 Basketball => 07_Basketball}/ruby/README.md | 0 {07 Basketball => 07_Basketball}/vbnet/README.md | 0 {08 Batnum => 08_Batnum}/README.md | 0 {08 Batnum => 08_Batnum}/batnum.bas | 0 {08 Batnum => 08_Batnum}/csharp/Batnum.csproj | 0 {08 Batnum => 08_Batnum}/csharp/Batnum.sln | 0 {08 Batnum => 08_Batnum}/csharp/BatnumGame.cs | 0 {08 Batnum => 08_Batnum}/csharp/ConsoleUtilities.cs | 0 {08 Batnum => 08_Batnum}/csharp/Program.cs | 0 {08 Batnum => 08_Batnum}/csharp/Properties/Resources.Designer.cs | 0 {08 Batnum => 08_Batnum}/csharp/Properties/Resources.en.resx | 0 {08 Batnum => 08_Batnum}/csharp/Properties/Resources.fr.resx | 0 {08 Batnum => 08_Batnum}/csharp/Properties/Resources.resx | 0 {08 Batnum => 08_Batnum}/csharp/README.md | 0 {08 Batnum => 08_Batnum}/java/README.md | 0 {08 Batnum => 08_Batnum}/java/src/BatNum.java | 0 {08 Batnum => 08_Batnum}/java/src/BatNumGame.java | 0 {08 Batnum => 08_Batnum}/javascript/README.md | 0 {08 Batnum => 08_Batnum}/javascript/batnum.html | 0 {08 Batnum => 08_Batnum}/javascript/batnum.js | 0 {08 Batnum => 08_Batnum}/pascal/README.md | 0 {08 Batnum => 08_Batnum}/perl/README.md | 0 {08 Batnum => 08_Batnum}/python/README.md | 0 {08 Batnum => 08_Batnum}/python/batnum.py | 0 {08 Batnum => 08_Batnum}/ruby/README.md | 0 {08 Batnum => 08_Batnum}/vbnet/Program.vb | 0 {08 Batnum => 08_Batnum}/vbnet/README.md | 0 {08 Batnum => 08_Batnum}/vbnet/batnum.sln | 0 {08 Batnum => 08_Batnum}/vbnet/batnum.vbproj | 0 {09 Battle => 09_Battle}/README.md | 0 {09 Battle => 09_Battle}/battle.bas | 0 {09 Battle => 09_Battle}/csharp/Battle.csproj | 0 {09 Battle => 09_Battle}/csharp/Battle.sln | 0 {09 Battle => 09_Battle}/csharp/Game.cs | 0 {09 Battle => 09_Battle}/csharp/Program.cs | 0 {09 Battle => 09_Battle}/csharp/README.md | 0 {09 Battle => 09_Battle}/java/README.md | 0 {09 Battle => 09_Battle}/javascript/README.md | 0 {09 Battle => 09_Battle}/javascript/battle.html | 0 {09 Battle => 09_Battle}/javascript/battle.js | 0 {09 Battle => 09_Battle}/pascal/README.md | 0 {09 Battle => 09_Battle}/perl/README.md | 0 {09 Battle => 09_Battle}/python/README.md | 0 {09 Battle => 09_Battle}/ruby/README.md | 0 {09 Battle => 09_Battle}/vbnet/README.md | 0 {10 Blackjack => 10_Blackjack}/README.md | 0 {10 Blackjack => 10_Blackjack}/blackjack.bas | 0 {10 Blackjack => 10_Blackjack}/csharp/Blackjack.csproj | 0 {10 Blackjack => 10_Blackjack}/csharp/Card.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/Deck.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/Game.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/Hand.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/Player.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/Program.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/Prompt.cs | 0 {10 Blackjack => 10_Blackjack}/csharp/README.md | 0 {10 Blackjack => 10_Blackjack}/java/README.md | 0 {10 Blackjack => 10_Blackjack}/javascript/README.md | 0 {10 Blackjack => 10_Blackjack}/javascript/blackjack.html | 0 {10 Blackjack => 10_Blackjack}/javascript/blackjack.js | 0 {10 Blackjack => 10_Blackjack}/pascal/README.md | 0 {10 Blackjack => 10_Blackjack}/perl/README.md | 0 {10 Blackjack => 10_Blackjack}/python/README.md | 0 {10 Blackjack => 10_Blackjack}/ruby/README.md | 0 {10 Blackjack => 10_Blackjack}/vbnet/README.md | 0 {11 Bombardment => 11_Bombardment}/README.md | 0 {11 Bombardment => 11_Bombardment}/bombardment.bas | 0 {11 Bombardment => 11_Bombardment}/csharp/README.md | 0 {11 Bombardment => 11_Bombardment}/java/README.md | 0 {11 Bombardment => 11_Bombardment}/java/src/Bombardment.java | 0 {11 Bombardment => 11_Bombardment}/java/src/BombardmentGame.java | 0 {11 Bombardment => 11_Bombardment}/javascript/README.md | 0 {11 Bombardment => 11_Bombardment}/javascript/bombardment.html | 0 {11 Bombardment => 11_Bombardment}/javascript/bombardment.js | 0 {11 Bombardment => 11_Bombardment}/pascal/README.md | 0 {11 Bombardment => 11_Bombardment}/perl/README.md | 0 {11 Bombardment => 11_Bombardment}/python/README.md | 0 {11 Bombardment => 11_Bombardment}/python/bombardment.py | 0 {11 Bombardment => 11_Bombardment}/ruby/README.md | 0 {11 Bombardment => 11_Bombardment}/ruby/bombardment.rb | 0 {11 Bombardment => 11_Bombardment}/vbnet/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/bombsaway.bas | 0 {12 Bombs Away => 12_Bombs_Away}/csharp/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/java/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/java/src/BombsAway.java | 0 {12 Bombs Away => 12_Bombs_Away}/java/src/BombsAwayGame.java | 0 {12 Bombs Away => 12_Bombs_Away}/javascript/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/javascript/bombsaway.html | 0 {12 Bombs Away => 12_Bombs_Away}/javascript/bombsaway.js | 0 {12 Bombs Away => 12_Bombs_Away}/pascal/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/perl/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/python/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/ruby/README.md | 0 {12 Bombs Away => 12_Bombs_Away}/vbnet/README.md | 0 {13 Bounce => 13_Bounce}/README.md | 0 {13 Bounce => 13_Bounce}/bounce.bas | 0 {13 Bounce => 13_Bounce}/csharp/README.md | 0 {13 Bounce => 13_Bounce}/java/Bounce.java | 0 {13 Bounce => 13_Bounce}/java/README.md | 0 {13 Bounce => 13_Bounce}/javascript/README.md | 0 {13 Bounce => 13_Bounce}/javascript/bounce.html | 0 {13 Bounce => 13_Bounce}/javascript/bounce.js | 0 {13 Bounce => 13_Bounce}/pascal/README.md | 0 {13 Bounce => 13_Bounce}/perl/README.md | 0 {13 Bounce => 13_Bounce}/python/README.md | 0 {13 Bounce => 13_Bounce}/python/bounce.py | 0 {13 Bounce => 13_Bounce}/ruby/README.md | 0 {13 Bounce => 13_Bounce}/vbnet/README.md | 0 {14 Bowling => 14_Bowling}/README.md | 0 {14 Bowling => 14_Bowling}/bowling.bas | 0 {14 Bowling => 14_Bowling}/csharp/README.md | 0 {14 Bowling => 14_Bowling}/java/Bowling.java | 0 {14 Bowling => 14_Bowling}/java/README.md | 0 {14 Bowling => 14_Bowling}/javascript/README.md | 0 {14 Bowling => 14_Bowling}/javascript/bowling.html | 0 {14 Bowling => 14_Bowling}/javascript/bowling.js | 0 {14 Bowling => 14_Bowling}/pascal/README.md | 0 {14 Bowling => 14_Bowling}/perl/README.md | 0 {14 Bowling => 14_Bowling}/python/README.md | 0 {14 Bowling => 14_Bowling}/python/bowling.py | 0 {14 Bowling => 14_Bowling}/ruby/README.md | 0 {14 Bowling => 14_Bowling}/vbnet/README.md | 0 {15 Boxing => 15_Boxing}/README.md | 0 {15 Boxing => 15_Boxing}/boxing.bas | 0 {15 Boxing => 15_Boxing}/csharp/README.md | 0 {15 Boxing => 15_Boxing}/java/Basic.java | 0 {15 Boxing => 15_Boxing}/java/Boxing.java | 0 {15 Boxing => 15_Boxing}/java/BoxingGame.java | 0 {15 Boxing => 15_Boxing}/java/GameSession.java | 0 {15 Boxing => 15_Boxing}/java/Player.java | 0 {15 Boxing => 15_Boxing}/java/Punch.java | 0 {15 Boxing => 15_Boxing}/java/README.md | 0 {15 Boxing => 15_Boxing}/javascript/README.md | 0 {15 Boxing => 15_Boxing}/javascript/boxing.html | 0 {15 Boxing => 15_Boxing}/javascript/boxing.js | 0 {15 Boxing => 15_Boxing}/pascal/README.md | 0 {15 Boxing => 15_Boxing}/perl/README.md | 0 {15 Boxing => 15_Boxing}/python/README.md | 0 {15 Boxing => 15_Boxing}/python/boxing.py | 0 {15 Boxing => 15_Boxing}/ruby/README.md | 0 {15 Boxing => 15_Boxing}/vbnet/README.md | 0 {16 Bug => 16_Bug}/README.md | 0 {16 Bug => 16_Bug}/bug.bas | 0 {16 Bug => 16_Bug}/csharp/README.md | 0 {16 Bug => 16_Bug}/java/README.md | 0 {16 Bug => 16_Bug}/java/src/Bug.java | 0 {16 Bug => 16_Bug}/java/src/BugGame.java | 0 {16 Bug => 16_Bug}/java/src/ComputerBug.java | 0 {16 Bug => 16_Bug}/java/src/Insect.java | 0 {16 Bug => 16_Bug}/java/src/PlayerBug.java | 0 {16 Bug => 16_Bug}/javascript/README.md | 0 {16 Bug => 16_Bug}/javascript/bug.html | 0 {16 Bug => 16_Bug}/javascript/bug.js | 0 {16 Bug => 16_Bug}/pascal/README.md | 0 {16 Bug => 16_Bug}/perl/README.md | 0 {16 Bug => 16_Bug}/python/README.md | 0 {16 Bug => 16_Bug}/ruby/README.md | 0 {16 Bug => 16_Bug}/vbnet/README.md | 0 {17 Bullfight => 17_Bullfight}/README.md | 0 {17 Bullfight => 17_Bullfight}/bullfight.bas | 0 {17 Bullfight => 17_Bullfight}/csharp/Bullfight.sln | 0 {17 Bullfight => 17_Bullfight}/csharp/Game.csproj | 0 {17 Bullfight => 17_Bullfight}/csharp/README.md | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Action.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/ActionResult.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/BullFight.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Controller.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Events/BullCharging.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Events/Event.cs | 0 .../csharp/src/Events/MatchCompleted.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Events/MatchStarted.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Events/PlayerGored.cs | 0 .../csharp/src/Events/PlayerSurvived.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Mediator.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Program.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Quality.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/Reward.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/RiskLevel.cs | 0 {17 Bullfight => 17_Bullfight}/csharp/src/View.cs | 0 {17 Bullfight => 17_Bullfight}/java/README.md | 0 {17 Bullfight => 17_Bullfight}/javascript/README.md | 0 {17 Bullfight => 17_Bullfight}/javascript/bullfight.html | 0 {17 Bullfight => 17_Bullfight}/javascript/bullfight.js | 0 {17 Bullfight => 17_Bullfight}/pascal/README.md | 0 {17 Bullfight => 17_Bullfight}/perl/README.md | 0 {17 Bullfight => 17_Bullfight}/python/README.md | 0 {17 Bullfight => 17_Bullfight}/ruby/README.md | 0 {17 Bullfight => 17_Bullfight}/vbnet/README.md | 0 {18 Bullseye => 18_Bullseye}/README.md | 0 {18 Bullseye => 18_Bullseye}/bullseye.bas | 0 {18 Bullseye => 18_Bullseye}/csharp/README.md | 0 {18 Bullseye => 18_Bullseye}/java/README.md | 0 {18 Bullseye => 18_Bullseye}/java/src/Bullseye.java | 0 {18 Bullseye => 18_Bullseye}/java/src/BullseyeGame.java | 0 {18 Bullseye => 18_Bullseye}/java/src/Player.java | 0 {18 Bullseye => 18_Bullseye}/java/src/Shot.java | 0 {18 Bullseye => 18_Bullseye}/javascript/README.md | 0 {18 Bullseye => 18_Bullseye}/javascript/bullseye.html | 0 {18 Bullseye => 18_Bullseye}/javascript/bullseye.js | 0 {18 Bullseye => 18_Bullseye}/pascal/README.md | 0 {18 Bullseye => 18_Bullseye}/perl/README.md | 0 {18 Bullseye => 18_Bullseye}/perl/bullseye.pl | 0 {18 Bullseye => 18_Bullseye}/python/README.md | 0 {18 Bullseye => 18_Bullseye}/ruby/README.md | 0 {18 Bullseye => 18_Bullseye}/vbnet/README.md | 0 {19 Bunny => 19_Bunny}/README.md | 0 {19 Bunny => 19_Bunny}/bunny.bas | 0 {19 Bunny => 19_Bunny}/csharp/README.md | 0 {19 Bunny => 19_Bunny}/java/README.md | 0 {19 Bunny => 19_Bunny}/java/src/Bunny.java | 0 {19 Bunny => 19_Bunny}/javascript/README.md | 0 {19 Bunny => 19_Bunny}/javascript/bunny.html | 0 {19 Bunny => 19_Bunny}/javascript/bunny.js | 0 {19 Bunny => 19_Bunny}/pascal/README.md | 0 {19 Bunny => 19_Bunny}/perl/README.md | 0 {19 Bunny => 19_Bunny}/perl/bunny.pl | 0 {19 Bunny => 19_Bunny}/python/README.md | 0 {19 Bunny => 19_Bunny}/python/bunny.py | 0 {19 Bunny => 19_Bunny}/ruby/README.md | 0 {19 Bunny => 19_Bunny}/ruby/bunny-faithful.rb | 0 {19 Bunny => 19_Bunny}/ruby/bunny-modern.rb | 0 {19 Bunny => 19_Bunny}/vbnet/README.md | 0 {20 Buzzword => 20_Buzzword}/README.md | 0 {20 Buzzword => 20_Buzzword}/buzzword.bas | 0 {20 Buzzword => 20_Buzzword}/csharp/README.md | 0 {20 Buzzword => 20_Buzzword}/java/README.md | 0 {20 Buzzword => 20_Buzzword}/java/src/Buzzword.java | 0 {20 Buzzword => 20_Buzzword}/javascript/README.md | 0 {20 Buzzword => 20_Buzzword}/javascript/buzzword.html | 0 {20 Buzzword => 20_Buzzword}/javascript/buzzword.js | 0 {20 Buzzword => 20_Buzzword}/pascal/README.md | 0 {20 Buzzword => 20_Buzzword}/perl/README.md | 0 {20 Buzzword => 20_Buzzword}/perl/buzzword.pl | 0 {20 Buzzword => 20_Buzzword}/python/README.md | 0 {20 Buzzword => 20_Buzzword}/python/buzzword.py | 0 {20 Buzzword => 20_Buzzword}/ruby/README.md | 0 {20 Buzzword => 20_Buzzword}/ruby/buzzword.rb | 0 {20 Buzzword => 20_Buzzword}/vbnet/README.md | 0 {21 Calendar => 21_Calendar}/README.md | 0 {21 Calendar => 21_Calendar}/calendar.bas | 0 {21 Calendar => 21_Calendar}/csharp/README.md | 0 {21 Calendar => 21_Calendar}/java/Calendar.java | 0 {21 Calendar => 21_Calendar}/java/README.md | 0 {21 Calendar => 21_Calendar}/javascript/README.md | 0 {21 Calendar => 21_Calendar}/javascript/calendar.html | 0 {21 Calendar => 21_Calendar}/javascript/calendar.js | 0 {21 Calendar => 21_Calendar}/pascal/README.md | 0 {21 Calendar => 21_Calendar}/perl/README.md | 0 {21 Calendar => 21_Calendar}/python/README.md | 0 {21 Calendar => 21_Calendar}/ruby/README.md | 0 {21 Calendar => 21_Calendar}/vbnet/README.md | 0 {22 Change => 22_Change}/README.md | 0 {22 Change => 22_Change}/change.bas | 0 {22 Change => 22_Change}/csharp/README.md | 0 {22 Change => 22_Change}/java/README.md | 0 {22 Change => 22_Change}/java/src/Change.java | 0 {22 Change => 22_Change}/java/src/ChangeGame.java | 0 {22 Change => 22_Change}/javascript/README.md | 0 {22 Change => 22_Change}/javascript/change.html | 0 {22 Change => 22_Change}/javascript/change.js | 0 {22 Change => 22_Change}/pascal/README.md | 0 {22 Change => 22_Change}/perl/README.md | 0 {22 Change => 22_Change}/python/README.md | 0 {22 Change => 22_Change}/python/change.py | 0 {22 Change => 22_Change}/ruby/README.md | 0 {22 Change => 22_Change}/vbnet/README.md | 0 {23 Checkers => 23_Checkers}/README.md | 0 {23 Checkers => 23_Checkers}/checkers.annotated.bas | 0 {23 Checkers => 23_Checkers}/checkers.bas | 0 {23 Checkers => 23_Checkers}/csharp/README.md | 0 {23 Checkers => 23_Checkers}/java/README.md | 0 {23 Checkers => 23_Checkers}/javascript/README.md | 0 {23 Checkers => 23_Checkers}/javascript/checkers.html | 0 {23 Checkers => 23_Checkers}/javascript/checkers.js | 0 {23 Checkers => 23_Checkers}/pascal/README.md | 0 {23 Checkers => 23_Checkers}/perl/README.md | 0 {23 Checkers => 23_Checkers}/python/README.md | 0 {23 Checkers => 23_Checkers}/python/checkers.py | 0 {23 Checkers => 23_Checkers}/ruby/README.md | 0 {23 Checkers => 23_Checkers}/ruby/checkers.rb | 0 {23 Checkers => 23_Checkers}/vbnet/README.md | 0 {24 Chemist => 24_Chemist}/README.md | 0 {24 Chemist => 24_Chemist}/chemist.bas | 0 {24 Chemist => 24_Chemist}/csharp/Chemist/Chemist.sln | 0 {24 Chemist => 24_Chemist}/csharp/Chemist/Chemist/Chemist.csproj | 0 {24 Chemist => 24_Chemist}/csharp/Chemist/Chemist/Program.cs | 0 {24 Chemist => 24_Chemist}/csharp/README.md | 0 {24 Chemist => 24_Chemist}/java/README.md | 0 {24 Chemist => 24_Chemist}/java/src/Chemist.java | 0 {24 Chemist => 24_Chemist}/java/src/ChemistGame.java | 0 {24 Chemist => 24_Chemist}/javascript/README.md | 0 {24 Chemist => 24_Chemist}/javascript/chemist.html | 0 {24 Chemist => 24_Chemist}/javascript/chemist.js | 0 {24 Chemist => 24_Chemist}/pascal/README.md | 0 {24 Chemist => 24_Chemist}/perl/README.md | 0 {24 Chemist => 24_Chemist}/perlchemist.pl | 0 {24 Chemist => 24_Chemist}/python/README.md | 0 {24 Chemist => 24_Chemist}/python/chemist.py | 0 {24 Chemist => 24_Chemist}/ruby/README.md | 0 {24 Chemist => 24_Chemist}/vbnet/README.md | 0 {25 Chief => 25_Chief}/README.md | 0 {25 Chief => 25_Chief}/chief.bas | 0 {25 Chief => 25_Chief}/csharp/README.md | 0 {25 Chief => 25_Chief}/java/README.md | 0 {25 Chief => 25_Chief}/java/src/Chief.java | 0 {25 Chief => 25_Chief}/java/src/ChiefGame.java | 0 {25 Chief => 25_Chief}/javascript/README.md | 0 {25 Chief => 25_Chief}/javascript/chief.html | 0 {25 Chief => 25_Chief}/javascript/chief.js | 0 {25 Chief => 25_Chief}/pascal/README.md | 0 {25 Chief => 25_Chief}/perl/README.md | 0 {25 Chief => 25_Chief}/python/README.md | 0 {25 Chief => 25_Chief}/ruby/README.md | 0 {25 Chief => 25_Chief}/vbnet/README.md | 0 {26 Chomp => 26_Chomp}/README.md | 0 {26 Chomp => 26_Chomp}/chomp.bas | 0 {26 Chomp => 26_Chomp}/csharp/README.md | 0 {26 Chomp => 26_Chomp}/java/Chomp.java | 0 {26 Chomp => 26_Chomp}/java/README.md | 0 {26 Chomp => 26_Chomp}/javascript/README.md | 0 {26 Chomp => 26_Chomp}/javascript/chomp.html | 0 {26 Chomp => 26_Chomp}/javascript/chomp.js | 0 {26 Chomp => 26_Chomp}/pascal/README.md | 0 {26 Chomp => 26_Chomp}/perl/README.md | 0 {26 Chomp => 26_Chomp}/python/README.md | 0 {26 Chomp => 26_Chomp}/python/chomp.py | 0 {26 Chomp => 26_Chomp}/ruby/README.md | 0 {26 Chomp => 26_Chomp}/vbnet/README.md | 0 {27 Civil War => 27_Civil_War}/README.md | 0 {27 Civil War => 27_Civil_War}/civilwar.bas | 0 {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar.sln | 0 {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/Army.cs | 0 {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/Battle.cs | 0 .../csharp/CivilWar/CivilWar/CivilWar.csproj | 0 .../csharp/CivilWar/CivilWar/ConsoleUtils.cs | 0 .../csharp/CivilWar/CivilWar/GameOptions.cs | 0 .../csharp/CivilWar/CivilWar/Program.cs | 0 {27 Civil War => 27_Civil_War}/csharp/README.md | 0 {27 Civil War => 27_Civil_War}/java/README.md | 0 {27 Civil War => 27_Civil_War}/javascript/README.md | 0 {27 Civil War => 27_Civil_War}/javascript/civilwar.html | 0 {27 Civil War => 27_Civil_War}/javascript/civilwar.js | 0 {27 Civil War => 27_Civil_War}/pascal/README.md | 0 {27 Civil War => 27_Civil_War}/perl/README.md | 0 {27 Civil War => 27_Civil_War}/python/README.md | 0 {27 Civil War => 27_Civil_War}/ruby/README.md | 0 {27 Civil War => 27_Civil_War}/vbnet/README.md | 0 {28 Combat => 28_Combat}/README.md | 0 {28 Combat => 28_Combat}/combat.bas | 0 {28 Combat => 28_Combat}/csharp/Combat.sln | 0 {28 Combat => 28_Combat}/csharp/Game.csproj | 0 {28 Combat => 28_Combat}/csharp/README.md | 0 {28 Combat => 28_Combat}/csharp/src/ArmedForces.cs | 0 {28 Combat => 28_Combat}/csharp/src/Ceasefire.cs | 0 {28 Combat => 28_Combat}/csharp/src/Controller.cs | 0 {28 Combat => 28_Combat}/csharp/src/FinalCampaign.cs | 0 {28 Combat => 28_Combat}/csharp/src/InitialCampaign.cs | 0 {28 Combat => 28_Combat}/csharp/src/MilitaryBranch.cs | 0 {28 Combat => 28_Combat}/csharp/src/Program.cs | 0 {28 Combat => 28_Combat}/csharp/src/View.cs | 0 {28 Combat => 28_Combat}/csharp/src/WarResult.cs | 0 {28 Combat => 28_Combat}/csharp/src/WarState.cs | 0 {28 Combat => 28_Combat}/java/Combat.java | 0 {28 Combat => 28_Combat}/java/README.md | 0 {28 Combat => 28_Combat}/javascript/README.md | 0 {28 Combat => 28_Combat}/javascript/combat.html | 0 {28 Combat => 28_Combat}/javascript/combat.js | 0 {28 Combat => 28_Combat}/pascal/README.md | 0 {28 Combat => 28_Combat}/perl/README.md | 0 {28 Combat => 28_Combat}/python/README.md | 0 {28 Combat => 28_Combat}/ruby/README.md | 0 {28 Combat => 28_Combat}/vbnet/README.md | 0 {29 Craps => 29_Craps}/README.md | 0 {29 Craps => 29_Craps}/craps.bas | 0 {29 Craps => 29_Craps}/csharp/Craps/.gitignore | 0 {29 Craps => 29_Craps}/csharp/Craps/Craps.sln | 0 {29 Craps => 29_Craps}/csharp/Craps/Craps/Craps.csproj | 0 {29 Craps => 29_Craps}/csharp/Craps/Craps/CrapsGame.cs | 0 {29 Craps => 29_Craps}/csharp/Craps/Craps/Dice.cs | 0 {29 Craps => 29_Craps}/csharp/Craps/Craps/Program.cs | 0 {29 Craps => 29_Craps}/csharp/Craps/Craps/UserInterface.cs | 0 .../csharp/Craps/CrapsTester/CrapsTester.csproj | 0 {29 Craps => 29_Craps}/csharp/Craps/CrapsTester/CrapsTests.cs | 0 {29 Craps => 29_Craps}/csharp/README.md | 0 {29 Craps => 29_Craps}/java/README.md | 0 {29 Craps => 29_Craps}/javascript/README.md | 0 {29 Craps => 29_Craps}/javascript/craps.html | 0 {29 Craps => 29_Craps}/javascript/craps.js | 0 {29 Craps => 29_Craps}/pascal/README.md | 0 {29 Craps => 29_Craps}/perl/README.md | 0 {29 Craps => 29_Craps}/python/README.md | 0 {29 Craps => 29_Craps}/ruby/README.md | 0 {29 Craps => 29_Craps}/vbnet/README.md | 0 {30 Cube => 30_Cube}/README.md | 0 {30 Cube => 30_Cube}/csharp/README.md | 0 {30 Cube => 30_Cube}/cube.bas | 0 {30 Cube => 30_Cube}/java/README.md | 0 {30 Cube => 30_Cube}/javascript/README.md | 0 {30 Cube => 30_Cube}/javascript/cube.html | 0 {30 Cube => 30_Cube}/javascript/cube.js | 0 {30 Cube => 30_Cube}/pascal/README.md | 0 {30 Cube => 30_Cube}/perl/README.md | 0 {30 Cube => 30_Cube}/python/README.md | 0 {30 Cube => 30_Cube}/python/cube.py | 0 {30 Cube => 30_Cube}/ruby/README.md | 0 {30 Cube => 30_Cube}/vbnet/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/csharp/DepthCharge.sln | 0 {31 Depth Charge => 31_Depth_Charge}/csharp/Game.csproj | 0 {31 Depth Charge => 31_Depth_Charge}/csharp/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/csharp/src/Controller.cs | 0 {31 Depth Charge => 31_Depth_Charge}/csharp/src/Program.cs | 0 {31 Depth Charge => 31_Depth_Charge}/csharp/src/View.cs | 0 {31 Depth Charge => 31_Depth_Charge}/depthcharge.bas | 0 {31 Depth Charge => 31_Depth_Charge}/java/DepthCharge.java | 0 {31 Depth Charge => 31_Depth_Charge}/java/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/javascript/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/javascript/depthcharge.html | 0 {31 Depth Charge => 31_Depth_Charge}/javascript/depthcharge.js | 0 {31 Depth Charge => 31_Depth_Charge}/pascal/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/perl/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/perl/depth-charge.pl | 0 {31 Depth Charge => 31_Depth_Charge}/python/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/python/depth_charge.py | 0 {31 Depth Charge => 31_Depth_Charge}/ruby/README.md | 0 {31 Depth Charge => 31_Depth_Charge}/vbnet/README.md | 0 {32 Diamond => 32_Diamond}/README.md | 0 {32 Diamond => 32_Diamond}/csharp/README.md | 0 {32 Diamond => 32_Diamond}/diamond.bas | 0 {32 Diamond => 32_Diamond}/java/Diamond.java | 0 {32 Diamond => 32_Diamond}/java/README.md | 0 {32 Diamond => 32_Diamond}/javascript/README.md | 0 {32 Diamond => 32_Diamond}/javascript/diamond.html | 0 {32 Diamond => 32_Diamond}/javascript/diamond.js | 0 {32 Diamond => 32_Diamond}/pascal/README.md | 0 {32 Diamond => 32_Diamond}/perl/README.md | 0 {32 Diamond => 32_Diamond}/perl/diamond.pl | 0 {32 Diamond => 32_Diamond}/python/README.md | 0 {32 Diamond => 32_Diamond}/python/diamond.py | 0 {32 Diamond => 32_Diamond}/ruby/README.md | 0 {32 Diamond => 32_Diamond}/ruby/diamond.rb | 0 {32 Diamond => 32_Diamond}/vbnet/README.md | 0 {33 Dice => 33_Dice}/README.md | 0 {33 Dice => 33_Dice}/csharp/Dice.csproj | 0 {33 Dice => 33_Dice}/csharp/Game.cs | 0 {33 Dice => 33_Dice}/csharp/Program.cs | 0 {33 Dice => 33_Dice}/csharp/README.md | 0 {33 Dice => 33_Dice}/csharp/RollGenerator.cs | 0 {33 Dice => 33_Dice}/dice.bas | 0 {33 Dice => 33_Dice}/java/README.md | 0 {33 Dice => 33_Dice}/java/src/Dice.java | 0 {33 Dice => 33_Dice}/java/src/DiceGame.java | 0 {33 Dice => 33_Dice}/javascript/README.md | 0 {33 Dice => 33_Dice}/javascript/dice.html | 0 {33 Dice => 33_Dice}/javascript/dice.js | 0 {33 Dice => 33_Dice}/pascal/README.md | 0 {33 Dice => 33_Dice}/perl/README.md | 0 {33 Dice => 33_Dice}/perl/dice.pl | 0 {33 Dice => 33_Dice}/python/README.md | 0 {33 Dice => 33_Dice}/python/dice.py | 0 {33 Dice => 33_Dice}/ruby/README.md | 0 {33 Dice => 33_Dice}/ruby/dice.rb | 0 {33 Dice => 33_Dice}/vbnet/README.md | 0 {34 Digits => 34_Digits}/README.md | 0 {34 Digits => 34_Digits}/csharp/README.md | 0 {34 Digits => 34_Digits}/digits.bas | 0 {34 Digits => 34_Digits}/java/Digits.java | 0 {34 Digits => 34_Digits}/java/README.md | 0 {34 Digits => 34_Digits}/javascript/README.md | 0 {34 Digits => 34_Digits}/javascript/digits.html | 0 {34 Digits => 34_Digits}/javascript/digits.js | 0 {34 Digits => 34_Digits}/pascal/README.md | 0 {34 Digits => 34_Digits}/perl/README.md | 0 {34 Digits => 34_Digits}/python/README.md | 0 {34 Digits => 34_Digits}/ruby/README.md | 0 {34 Digits => 34_Digits}/vbnet/README.md | 0 {35 Even Wins => 35_Even_Wins}/README.md | 0 {35 Even Wins => 35_Even_Wins}/csharp/README.md | 0 {35 Even Wins => 35_Even_Wins}/evenwins.bas | 0 {35 Even Wins => 35_Even_Wins}/gameofevenwins.bas | 0 {35 Even Wins => 35_Even_Wins}/java/README.md | 0 {35 Even Wins => 35_Even_Wins}/javascript/README.md | 0 {35 Even Wins => 35_Even_Wins}/javascript/evenwins.html | 0 {35 Even Wins => 35_Even_Wins}/javascript/evenwins.js | 0 {35 Even Wins => 35_Even_Wins}/javascript/gameofevenwins.html | 0 {35 Even Wins => 35_Even_Wins}/javascript/gameofevenwins.js | 0 {35 Even Wins => 35_Even_Wins}/pascal/README.md | 0 {35 Even Wins => 35_Even_Wins}/perl/README.md | 0 {35 Even Wins => 35_Even_Wins}/python/README.md | 0 {35 Even Wins => 35_Even_Wins}/ruby/README.md | 0 {35 Even Wins => 35_Even_Wins}/vbnet/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/csharp/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/flipflop.bas | 0 {36 Flip Flop => 36_Flip_Flop}/java/FlipFlop.java | 0 {36 Flip Flop => 36_Flip_Flop}/java/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/javascript/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/javascript/flipflop.html | 0 {36 Flip Flop => 36_Flip_Flop}/javascript/flipflop.js | 0 {36 Flip Flop => 36_Flip_Flop}/pascal/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/perl/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/python/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/ruby/README.md | 0 {36 Flip Flop => 36_Flip_Flop}/vbnet/README.md | 0 {37 Football => 37_Football}/README.md | 0 {37 Football => 37_Football}/csharp/README.md | 0 {37 Football => 37_Football}/football.bas | 0 {37 Football => 37_Football}/ftball.bas | 0 {37 Football => 37_Football}/java/README.md | 0 {37 Football => 37_Football}/javascript/README.md | 0 {37 Football => 37_Football}/javascript/football.html | 0 {37 Football => 37_Football}/javascript/football.js | 0 {37 Football => 37_Football}/javascript/ftball.html | 0 {37 Football => 37_Football}/javascript/ftball.js | 0 {37 Football => 37_Football}/pascal/README.md | 0 {37 Football => 37_Football}/perl/README.md | 0 {37 Football => 37_Football}/python/README.md | 0 {37 Football => 37_Football}/ruby/README.md | 0 {37 Football => 37_Football}/vbnet/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/c/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/c/furtrader.c | 0 {38 Fur Trader => 38_Fur_Trader}/csharp/FurTrader.csproj | 0 {38 Fur Trader => 38_Fur_Trader}/csharp/FurTrader.sln | 0 {38 Fur Trader => 38_Fur_Trader}/csharp/Game.cs | 0 {38 Fur Trader => 38_Fur_Trader}/csharp/GameState.cs | 0 {38 Fur Trader => 38_Fur_Trader}/csharp/Program.cs | 0 {38 Fur Trader => 38_Fur_Trader}/csharp/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/furtrader.bas | 0 {38 Fur Trader => 38_Fur_Trader}/java/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/java/src/FurTrader.java | 0 {38 Fur Trader => 38_Fur_Trader}/java/src/FurTraderGame.java | 0 {38 Fur Trader => 38_Fur_Trader}/java/src/Pelt.java | 0 {38 Fur Trader => 38_Fur_Trader}/javascript/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/javascript/furtrader.html | 0 {38 Fur Trader => 38_Fur_Trader}/javascript/furtrader.js | 0 {38 Fur Trader => 38_Fur_Trader}/pascal/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/perl/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/python/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/python/furtrader.py | 0 {38 Fur Trader => 38_Fur_Trader}/ruby/README.md | 0 {38 Fur Trader => 38_Fur_Trader}/vbnet/README.md | 0 {39 Golf => 39_Golf}/README.md | 0 {39 Golf => 39_Golf}/csharp/Program.cs | 0 {39 Golf => 39_Golf}/csharp/README.md | 0 {39 Golf => 39_Golf}/golf.bas | 0 {39 Golf => 39_Golf}/java/README.md | 0 {39 Golf => 39_Golf}/javascript/README.md | 0 {39 Golf => 39_Golf}/javascript/golf.html | 0 {39 Golf => 39_Golf}/javascript/golf.js | 0 {39 Golf => 39_Golf}/pascal/README.md | 0 {39 Golf => 39_Golf}/perl/README.md | 0 {39 Golf => 39_Golf}/python/README.md | 0 {39 Golf => 39_Golf}/ruby/README.md | 0 {39 Golf => 39_Golf}/vbnet/README.md | 0 {40 Gomoko => 40_Gomoko}/README.md | 0 {40 Gomoko => 40_Gomoko}/csharp/README.md | 0 {40 Gomoko => 40_Gomoko}/gomoko.bas | 0 {40 Gomoko => 40_Gomoko}/java/Gomoko.java | 0 {40 Gomoko => 40_Gomoko}/java/README.md | 0 {40 Gomoko => 40_Gomoko}/javascript/README.md | 0 {40 Gomoko => 40_Gomoko}/javascript/gomoko.html | 0 {40 Gomoko => 40_Gomoko}/javascript/gomoko.js | 0 {40 Gomoko => 40_Gomoko}/pascal/README.md | 0 {40 Gomoko => 40_Gomoko}/perl/README.md | 0 {40 Gomoko => 40_Gomoko}/python/README.md | 0 {40 Gomoko => 40_Gomoko}/ruby/README.md | 0 {40 Gomoko => 40_Gomoko}/vbnet/README.md | 0 {41 Guess => 41_Guess}/README.md | 0 {41 Guess => 41_Guess}/csharp/README.md | 0 {41 Guess => 41_Guess}/guess.bas | 0 {41 Guess => 41_Guess}/java/README.md | 0 {41 Guess => 41_Guess}/java/src/Guess.java | 0 {41 Guess => 41_Guess}/java/src/GuessGame.java | 0 {41 Guess => 41_Guess}/javascript/README.md | 0 {41 Guess => 41_Guess}/javascript/guess.html | 0 {41 Guess => 41_Guess}/javascript/guess.js | 0 {41 Guess => 41_Guess}/pascal/README.md | 0 {41 Guess => 41_Guess}/perl/README.md | 0 {41 Guess => 41_Guess}/perl/guess.pl | 0 {41 Guess => 41_Guess}/python/README.md | 0 {41 Guess => 41_Guess}/python/guess.py | 0 {41 Guess => 41_Guess}/ruby/README.md | 0 {41 Guess => 41_Guess}/vbnet/README.md | 0 {42 Gunner => 42_Gunner}/README.md | 0 {42 Gunner => 42_Gunner}/csharp/README.md | 0 {42 Gunner => 42_Gunner}/gunner.bas | 0 {42 Gunner => 42_Gunner}/java/Gunner.java | 0 {42 Gunner => 42_Gunner}/java/README.md | 0 {42 Gunner => 42_Gunner}/javascript/README.md | 0 {42 Gunner => 42_Gunner}/javascript/gunner.html | 0 {42 Gunner => 42_Gunner}/javascript/gunner.js | 0 {42 Gunner => 42_Gunner}/pascal/README.md | 0 {42 Gunner => 42_Gunner}/perl/README.md | 0 {42 Gunner => 42_Gunner}/python/README.md | 0 {42 Gunner => 42_Gunner}/python/gunner.py | 0 {42 Gunner => 42_Gunner}/ruby/README.md | 0 {42 Gunner => 42_Gunner}/vbnet/README.md | 0 {43 Hammurabi => 43_Hammurabi}/README.md | 0 {43 Hammurabi => 43_Hammurabi}/csharp/Game.csproj | 0 {43 Hammurabi => 43_Hammurabi}/csharp/Hammurabi.sln | 0 {43 Hammurabi => 43_Hammurabi}/csharp/README.md | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/ActionResult.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/Controller.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/GameResult.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/GameState.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/GreatOffence.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/PerformanceRating.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/Program.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/Rules.cs | 0 {43 Hammurabi => 43_Hammurabi}/csharp/src/View.cs | 0 {43 Hammurabi => 43_Hammurabi}/hammurabi.bas | 0 {43 Hammurabi => 43_Hammurabi}/java/README.md | 0 {43 Hammurabi => 43_Hammurabi}/java/src/Hamurabi.java | 0 {43 Hammurabi => 43_Hammurabi}/java/src/HamurabiGame.java | 0 {43 Hammurabi => 43_Hammurabi}/javascript/README.md | 0 {43 Hammurabi => 43_Hammurabi}/javascript/hammurabi.html | 0 {43 Hammurabi => 43_Hammurabi}/javascript/hammurabi.js | 0 {43 Hammurabi => 43_Hammurabi}/pascal/README.md | 0 {43 Hammurabi => 43_Hammurabi}/perl/README.md | 0 {43 Hammurabi => 43_Hammurabi}/python/README.md | 0 {43 Hammurabi => 43_Hammurabi}/python/hamurabi.py | 0 {43 Hammurabi => 43_Hammurabi}/ruby/README.md | 0 {43 Hammurabi => 43_Hammurabi}/vbnet/README.md | 0 {44 Hangman => 44_Hangman}/README.md | 0 {44 Hangman => 44_Hangman}/csharp/Hangman/Graphic.cs | 0 {44 Hangman => 44_Hangman}/csharp/Hangman/Hangman.csproj | 0 {44 Hangman => 44_Hangman}/csharp/Hangman/Hangman.sln | 0 {44 Hangman => 44_Hangman}/csharp/Hangman/Program.cs | 0 {44 Hangman => 44_Hangman}/csharp/README.md | 0 {44 Hangman => 44_Hangman}/hangman.bas | 0 {44 Hangman => 44_Hangman}/java/Hangman.java | 0 {44 Hangman => 44_Hangman}/java/README.md | 0 {44 Hangman => 44_Hangman}/javascript/README.md | 0 {44 Hangman => 44_Hangman}/javascript/hangman.html | 0 {44 Hangman => 44_Hangman}/javascript/hangman.js | 0 {44 Hangman => 44_Hangman}/pascal/README.md | 0 {44 Hangman => 44_Hangman}/perl/README.md | 0 {44 Hangman => 44_Hangman}/python/README.md | 0 {44 Hangman => 44_Hangman}/python/hangman.py | 0 {44 Hangman => 44_Hangman}/ruby/README.md | 0 {44 Hangman => 44_Hangman}/vbnet/README.md | 0 {45 Hello => 45_Hello}/README.md | 0 {45 Hello => 45_Hello}/csharp/README.md | 0 {45 Hello => 45_Hello}/hello.bas | 0 {45 Hello => 45_Hello}/java/Hello.java | 0 {45 Hello => 45_Hello}/java/README.md | 0 {45 Hello => 45_Hello}/javascript/README.md | 0 {45 Hello => 45_Hello}/javascript/hello.html | 0 {45 Hello => 45_Hello}/javascript/hello.js | 0 {45 Hello => 45_Hello}/pascal/README.md | 0 {45 Hello => 45_Hello}/perl/README.md | 0 {45 Hello => 45_Hello}/python/README.md | 0 {45 Hello => 45_Hello}/python/hello.py | 0 {45 Hello => 45_Hello}/ruby/README.md | 0 {45 Hello => 45_Hello}/vbnet/README.md | 0 {46 Hexapawn => 46_Hexapawn}/README.md | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn.sln | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Board.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Cell.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Computer.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Game.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/GameSeries.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Hexapawn.csproj | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Human.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/IPlayer.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Input.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Move.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Pawn.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Program.cs | 0 {46 Hexapawn => 46_Hexapawn}/csharp/README.md | 0 {46 Hexapawn => 46_Hexapawn}/hexapawn.bas | 0 {46 Hexapawn => 46_Hexapawn}/java/README.md | 0 {46 Hexapawn => 46_Hexapawn}/javascript/README.md | 0 {46 Hexapawn => 46_Hexapawn}/javascript/hexapawn.html | 0 {46 Hexapawn => 46_Hexapawn}/javascript/hexapawn.js | 0 {46 Hexapawn => 46_Hexapawn}/pascal/README.md | 0 {46 Hexapawn => 46_Hexapawn}/perl/README.md | 0 {46 Hexapawn => 46_Hexapawn}/python/README.md | 0 {46 Hexapawn => 46_Hexapawn}/python/hexapawn.py | 0 {46 Hexapawn => 46_Hexapawn}/ruby/README.md | 0 {46 Hexapawn => 46_Hexapawn}/vbnet/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/csharp/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/csharp/hi-lo.cs | 0 {47 Hi-Lo => 47_Hi-Lo}/csharp/hi-lo.csproj | 0 {47 Hi-Lo => 47_Hi-Lo}/hi-lo.bas | 0 {47 Hi-Lo => 47_Hi-Lo}/java/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/java/src/HiLo.java | 0 {47 Hi-Lo => 47_Hi-Lo}/java/src/HiLoGame.java | 0 {47 Hi-Lo => 47_Hi-Lo}/javascript/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/javascript/hi-lo.html | 0 {47 Hi-Lo => 47_Hi-Lo}/javascript/hi-lo.js | 0 {47 Hi-Lo => 47_Hi-Lo}/pascal/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/perl/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/perl/hi-lo.pl | 0 {47 Hi-Lo => 47_Hi-Lo}/python/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/python/hilo.py | 0 {47 Hi-Lo => 47_Hi-Lo}/ruby/README.md | 0 {47 Hi-Lo => 47_Hi-Lo}/vbnet/README.md | 0 {48 High IQ => 48_High_IQ}/README.md | 0 {48 High IQ => 48_High_IQ}/csharp/README.md | 0 {48 High IQ => 48_High_IQ}/highiq.bas | 0 {48 High IQ => 48_High_IQ}/java/README.md | 0 {48 High IQ => 48_High_IQ}/javascript/README.md | 0 {48 High IQ => 48_High_IQ}/javascript/highiq.html | 0 {48 High IQ => 48_High_IQ}/javascript/highiq.js | 0 {48 High IQ => 48_High_IQ}/pascal/README.md | 0 {48 High IQ => 48_High_IQ}/perl/README.md | 0 {48 High IQ => 48_High_IQ}/python/README.md | 0 {48 High IQ => 48_High_IQ}/ruby/README.md | 0 {48 High IQ => 48_High_IQ}/vbnet/README.md | 0 {49 Hockey => 49_Hockey}/README.md | 0 {49 Hockey => 49_Hockey}/csharp/README.md | 0 {49 Hockey => 49_Hockey}/hockey.bas | 0 {49 Hockey => 49_Hockey}/java/README.md | 0 {49 Hockey => 49_Hockey}/javascript/README.md | 0 {49 Hockey => 49_Hockey}/javascript/hockey.html | 0 {49 Hockey => 49_Hockey}/javascript/hockey.js | 0 {49 Hockey => 49_Hockey}/pascal/README.md | 0 {49 Hockey => 49_Hockey}/perl/README.md | 0 {49 Hockey => 49_Hockey}/python/README.md | 0 {49 Hockey => 49_Hockey}/ruby/README.md | 0 {49 Hockey => 49_Hockey}/vbnet/README.md | 0 {50 Horserace => 50_Horserace}/README.md | 0 {50 Horserace => 50_Horserace}/csharp/README.md | 0 {50 Horserace => 50_Horserace}/horserace.bas | 0 {50 Horserace => 50_Horserace}/java/README.md | 0 {50 Horserace => 50_Horserace}/javascript/README.md | 0 {50 Horserace => 50_Horserace}/javascript/horserace.html | 0 {50 Horserace => 50_Horserace}/javascript/horserace.js | 0 {50 Horserace => 50_Horserace}/pascal/README.md | 0 {50 Horserace => 50_Horserace}/perl/README.md | 0 {50 Horserace => 50_Horserace}/python/README.md | 0 {50 Horserace => 50_Horserace}/ruby/README.md | 0 {50 Horserace => 50_Horserace}/vbnet/README.md | 0 {51 Hurkle => 51_Hurkle}/README.md | 0 {51 Hurkle => 51_Hurkle}/csharp/.gitignore | 0 {51 Hurkle => 51_Hurkle}/csharp/README.md | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/CardinalDirection.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/ConsoleHurkleView.cs | 0 .../csharp/src/hurkle/FailedGuessViewModel.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/GamePoint.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/GuessViewModel.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/HurkleGame.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/IHurkleView.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/LossViewModel.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/Program.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/VictoryViewModel.cs | 0 {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/hurkle.csproj | 0 {51 Hurkle => 51_Hurkle}/hurkle.bas | 0 {51 Hurkle => 51_Hurkle}/java/README.md | 0 {51 Hurkle => 51_Hurkle}/java/src/Hurkle.java | 0 {51 Hurkle => 51_Hurkle}/java/src/HurkleGame.java | 0 {51 Hurkle => 51_Hurkle}/javascript/README.md | 0 {51 Hurkle => 51_Hurkle}/javascript/hurkle.html | 0 {51 Hurkle => 51_Hurkle}/javascript/hurkle.js | 0 {51 Hurkle => 51_Hurkle}/pascal/README.md | 0 {51 Hurkle => 51_Hurkle}/perl/README.md | 0 {51 Hurkle => 51_Hurkle}/python/README.md | 0 {51 Hurkle => 51_Hurkle}/python/hurkle.py | 0 {51 Hurkle => 51_Hurkle}/ruby/README.md | 0 {51 Hurkle => 51_Hurkle}/ruby/hurkle.rb | 0 {51 Hurkle => 51_Hurkle}/vbnet/README.md | 0 {52 Kinema => 52_Kinema}/README.md | 0 {52 Kinema => 52_Kinema}/csharp/README.md | 0 {52 Kinema => 52_Kinema}/java/README.md | 0 {52 Kinema => 52_Kinema}/java/src/Kinema.java | 0 {52 Kinema => 52_Kinema}/java/src/KinemaGame.java | 0 {52 Kinema => 52_Kinema}/javascript/README.md | 0 {52 Kinema => 52_Kinema}/javascript/kinema.html | 0 {52 Kinema => 52_Kinema}/javascript/kinema.js | 0 {52 Kinema => 52_Kinema}/kinema.bas | 0 {52 Kinema => 52_Kinema}/pascal/README.md | 0 {52 Kinema => 52_Kinema}/perl/README.md | 0 {52 Kinema => 52_Kinema}/perl/kinema.pl | 0 {52 Kinema => 52_Kinema}/python/README.md | 0 {52 Kinema => 52_Kinema}/python/kinema.py | 0 {52 Kinema => 52_Kinema}/ruby/README.md | 0 {52 Kinema => 52_Kinema}/vbnet/README.md | 0 {53 King => 53_King}/README.md | 0 {53 King => 53_King}/csharp/README.md | 0 {53 King => 53_King}/java/README.md | 0 {53 King => 53_King}/javascript/README.md | 0 {53 King => 53_King}/javascript/king.html | 0 {53 King => 53_King}/javascript/king.js | 0 {53 King => 53_King}/king.bas | 0 {53 King => 53_King}/pascal/README.md | 0 {53 King => 53_King}/perl/README.md | 0 {53 King => 53_King}/python/README.md | 0 {53 King => 53_King}/ruby/README.md | 0 {53 King => 53_King}/vbnet/README.md | 0 {54 Letter => 54_Letter}/README.md | 0 {54 Letter => 54_Letter}/csharp/README.md | 0 {54 Letter => 54_Letter}/java/README.md | 0 {54 Letter => 54_Letter}/java/src/Letter.java | 0 {54 Letter => 54_Letter}/java/src/LetterGame.java | 0 {54 Letter => 54_Letter}/javascript/README.md | 0 {54 Letter => 54_Letter}/javascript/letter.html | 0 {54 Letter => 54_Letter}/javascript/letter.js | 0 {54 Letter => 54_Letter}/letter.bas | 0 {54 Letter => 54_Letter}/pascal/README.md | 0 {54 Letter => 54_Letter}/perl/README.md | 0 {54 Letter => 54_Letter}/perl/letter.pl | 0 {54 Letter => 54_Letter}/python/README.md | 0 {54 Letter => 54_Letter}/python/letter.py | 0 {54 Letter => 54_Letter}/ruby/README.md | 0 {54 Letter => 54_Letter}/vbnet/README.md | 0 {55 Life => 55_Life}/README.md | 0 {55 Life => 55_Life}/csharp/README.md | 0 {55 Life => 55_Life}/java/README.md | 0 {55 Life => 55_Life}/javascript/README.md | 0 {55 Life => 55_Life}/javascript/life.html | 0 {55 Life => 55_Life}/javascript/life.js | 0 {55 Life => 55_Life}/life.bas | 0 {55 Life => 55_Life}/pascal/README.md | 0 {55 Life => 55_Life}/perl/README.md | 0 {55 Life => 55_Life}/python/README.md | 0 {55 Life => 55_Life}/python/life.py | 0 {55 Life => 55_Life}/ruby/README.md | 0 {55 Life => 55_Life}/ruby/life.rb | 0 {55 Life => 55_Life}/vbnet/README.md | 0 {56 Life for Two => 56_Life_for_Two}/README.md | 0 {56 Life for Two => 56_Life_for_Two}/csharp/README.md | 0 {56 Life for Two => 56_Life_for_Two}/java/README.md | 0 {56 Life for Two => 56_Life_for_Two}/javascript/README.md | 0 {56 Life for Two => 56_Life_for_Two}/javascript/lifefortwo.html | 0 {56 Life for Two => 56_Life_for_Two}/javascript/lifefortwo.js | 0 {56 Life for Two => 56_Life_for_Two}/lifefortwo.bas | 0 {56 Life for Two => 56_Life_for_Two}/pascal/README.md | 0 {56 Life for Two => 56_Life_for_Two}/perl/README.md | 0 {56 Life for Two => 56_Life_for_Two}/python/README.md | 0 {56 Life for Two => 56_Life_for_Two}/ruby/README.md | 0 {56 Life for Two => 56_Life_for_Two}/vbnet/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/csharp/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/csharp/litquiz.cs | 0 {57 Literature Quiz => 57_Literature_Quiz}/java/README.md | 0 .../java/src/LiteratureQuiz.java | 0 .../java/src/LiteratureQuizGame.java | 0 {57 Literature Quiz => 57_Literature_Quiz}/javascript/README.md | 0 .../javascript/literature-quiz-node.mjs | 0 .../javascript/litquiz.html | 0 {57 Literature Quiz => 57_Literature_Quiz}/javascript/litquiz.js | 0 {57 Literature Quiz => 57_Literature_Quiz}/litquiz.bas | 0 {57 Literature Quiz => 57_Literature_Quiz}/pascal/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/perl/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/perl/litquiz.pl | 0 {57 Literature Quiz => 57_Literature_Quiz}/python/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/python/litquiz.py | 0 {57 Literature Quiz => 57_Literature_Quiz}/ruby/README.md | 0 {57 Literature Quiz => 57_Literature_Quiz}/vbnet/README.md | 0 {58 Love => 58_Love}/README.md | 0 {58 Love => 58_Love}/csharp/Love.sln | 0 {58 Love => 58_Love}/csharp/Love/Input.cs | 0 {58 Love => 58_Love}/csharp/Love/Love.csproj | 0 {58 Love => 58_Love}/csharp/Love/LovePattern.cs | 0 {58 Love => 58_Love}/csharp/Love/Program.cs | 0 {58 Love => 58_Love}/csharp/Love/SourceCharacters.cs | 0 {58 Love => 58_Love}/csharp/Love/Strings/Intro.txt | 0 {58 Love => 58_Love}/csharp/README.md | 0 {58 Love => 58_Love}/java/README.md | 0 {58 Love => 58_Love}/java/src/Love.java | 0 {58 Love => 58_Love}/javascript/README.md | 0 {58 Love => 58_Love}/javascript/love.html | 0 {58 Love => 58_Love}/javascript/love.js | 0 {58 Love => 58_Love}/love.bas | 0 {58 Love => 58_Love}/pascal/README.md | 0 {58 Love => 58_Love}/perl/README.md | 0 {58 Love => 58_Love}/perl/love.pl | 0 {58 Love => 58_Love}/python/README.md | 0 {58 Love => 58_Love}/python/love.py | 0 {58 Love => 58_Love}/ruby/README.md | 0 {58 Love => 58_Love}/vbnet/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/csharp/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/java/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lem.html | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lem.js | 0 .../javascript/lunar.html | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lunar.js | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/lem.bas | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/lunar.bas | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/pascal/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/perl/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/python/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/python/lunar.py | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/rocket.bas | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/ruby/README.md | 0 {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/vbnet/README.md | 0 {60 Mastermind => 60_Mastermind}/README.md | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/Game.csproj | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/Code.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/CodeFactory.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/ColorInfo.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/Colors.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/Command.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/Controller.cs | 0 .../csharp/Game/src/EnumerableExtensions.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/Program.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/TurnResult.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Game/src/View.cs | 0 {60 Mastermind => 60_Mastermind}/csharp/Mastermind.sln | 0 {60 Mastermind => 60_Mastermind}/csharp/README.md | 0 {60 Mastermind => 60_Mastermind}/java/README.md | 0 {60 Mastermind => 60_Mastermind}/javascript/README.md | 0 {60 Mastermind => 60_Mastermind}/javascript/mastermind.html | 0 {60 Mastermind => 60_Mastermind}/javascript/mastermind.js | 0 {60 Mastermind => 60_Mastermind}/mastermind.bas | 0 {60 Mastermind => 60_Mastermind}/pascal/README.md | 0 {60 Mastermind => 60_Mastermind}/perl/README.md | 0 {60 Mastermind => 60_Mastermind}/python/README.md | 0 {60 Mastermind => 60_Mastermind}/python/mastermind.py | 0 {60 Mastermind => 60_Mastermind}/ruby/README.md | 0 {60 Mastermind => 60_Mastermind}/vbnet/README.md | 0 {61 Math Dice => 61_Math_Dice}/README.md | 0 {61 Math Dice => 61_Math_Dice}/csharp/GameState.cs | 0 {61 Math Dice => 61_Math_Dice}/csharp/MathDice.csproj | 0 {61 Math Dice => 61_Math_Dice}/csharp/MathDice.sln | 0 {61 Math Dice => 61_Math_Dice}/csharp/Program.cs | 0 {61 Math Dice => 61_Math_Dice}/csharp/README.md | 0 {61 Math Dice => 61_Math_Dice}/csharp/StringExtensions.cs | 0 {61 Math Dice => 61_Math_Dice}/java/Die.java | 0 {61 Math Dice => 61_Math_Dice}/java/MathDice.java | 0 {61 Math Dice => 61_Math_Dice}/java/README.md | 0 {61 Math Dice => 61_Math_Dice}/javascript/README.md | 0 {61 Math Dice => 61_Math_Dice}/javascript/mathdice.html | 0 {61 Math Dice => 61_Math_Dice}/javascript/mathdice.js | 0 {61 Math Dice => 61_Math_Dice}/mathdice.bas | 0 {61 Math Dice => 61_Math_Dice}/pascal/README.md | 0 {61 Math Dice => 61_Math_Dice}/pascal/mathdice.pas | 0 {61 Math Dice => 61_Math_Dice}/perl/README.md | 0 {61 Math Dice => 61_Math_Dice}/python/README.md | 0 {61 Math Dice => 61_Math_Dice}/python/mathdice.py | 0 {61 Math Dice => 61_Math_Dice}/ruby/README.md | 0 {61 Math Dice => 61_Math_Dice}/vbnet/README.md | 0 {62 Mugwump => 62_Mugwump}/README.md | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump.sln | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Game.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Grid.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Input.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Mugwump.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Mugwump.csproj | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Offset.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Position.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Program.cs | 0 {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Strings/Intro.txt | 0 {62 Mugwump => 62_Mugwump}/csharp/README.md | 0 {62 Mugwump => 62_Mugwump}/java/README.md | 0 {62 Mugwump => 62_Mugwump}/java/src/Mugwump.java | 0 {62 Mugwump => 62_Mugwump}/javascript/README.md | 0 {62 Mugwump => 62_Mugwump}/javascript/mugwump.html | 0 {62 Mugwump => 62_Mugwump}/javascript/mugwump.js | 0 {62 Mugwump => 62_Mugwump}/mugwump.bas | 0 {62 Mugwump => 62_Mugwump}/pascal/README.md | 0 {62 Mugwump => 62_Mugwump}/perl/README.md | 0 {62 Mugwump => 62_Mugwump}/python/README.md | 0 {62 Mugwump => 62_Mugwump}/python/mugwump.py | 0 {62 Mugwump => 62_Mugwump}/ruby/README.md | 0 {62 Mugwump => 62_Mugwump}/vbnet/README.md | 0 {63 Name => 63_Name}/README.md | 0 {63 Name => 63_Name}/csharp/Name.csproj | 0 {63 Name => 63_Name}/csharp/Name.sln | 0 {63 Name => 63_Name}/csharp/Program.cs | 0 {63 Name => 63_Name}/csharp/README.md | 0 {63 Name => 63_Name}/csharp/StringExtensions.cs | 0 {63 Name => 63_Name}/java/README.md | 0 {63 Name => 63_Name}/java/main.class | 0 {63 Name => 63_Name}/javascript/README.md | 0 {63 Name => 63_Name}/javascript/name.html | 0 {63 Name => 63_Name}/javascript/name.js | 0 {63 Name => 63_Name}/name.bas | 0 {63 Name => 63_Name}/pascal/README.md | 0 {63 Name => 63_Name}/perl/README.md | 0 {63 Name => 63_Name}/perl/name.pl | 0 {63 Name => 63_Name}/python/README.md | 0 {63 Name => 63_Name}/python/name.py | 0 {63 Name => 63_Name}/ruby/README.md | 0 {63 Name => 63_Name}/vbnet/README.md | 0 {64 Nicomachus => 64_Nicomachus}/README.md | 0 {64 Nicomachus => 64_Nicomachus}/csharp/README.md | 0 {64 Nicomachus => 64_Nicomachus}/java/README.md | 0 {64 Nicomachus => 64_Nicomachus}/java/src/Nicomachus.java | 0 {64 Nicomachus => 64_Nicomachus}/javascript/README.md | 0 {64 Nicomachus => 64_Nicomachus}/javascript/nicomachus.html | 0 {64 Nicomachus => 64_Nicomachus}/javascript/nicomachus.js | 0 {64 Nicomachus => 64_Nicomachus}/nicomachus.bas | 0 {64 Nicomachus => 64_Nicomachus}/pascal/README.md | 0 {64 Nicomachus => 64_Nicomachus}/perl/README.md | 0 {64 Nicomachus => 64_Nicomachus}/perl/nicomachus.pl | 0 {64 Nicomachus => 64_Nicomachus}/python/README.md | 0 {64 Nicomachus => 64_Nicomachus}/python/nicomachus.py | 0 {64 Nicomachus => 64_Nicomachus}/ruby/README.md | 0 {64 Nicomachus => 64_Nicomachus}/vbnet/README.md | 0 {65 Nim => 65_Nim}/README.md | 0 {65 Nim => 65_Nim}/csharp/README.md | 0 {65 Nim => 65_Nim}/java/README.md | 0 {65 Nim => 65_Nim}/javascript/README.md | 0 {65 Nim => 65_Nim}/javascript/nim.html | 0 {65 Nim => 65_Nim}/javascript/nim.js | 0 {65 Nim => 65_Nim}/nim.bas | 0 {65 Nim => 65_Nim}/pascal/README.md | 0 {65 Nim => 65_Nim}/perl/README.md | 0 {65 Nim => 65_Nim}/python/README.md | 0 {65 Nim => 65_Nim}/ruby/README.md | 0 {65 Nim => 65_Nim}/vbnet/README.md | 0 {66 Number => 66_Number}/README.md | 0 {66 Number => 66_Number}/csharp/README.md | 0 {66 Number => 66_Number}/java/Number.java | 0 {66 Number => 66_Number}/java/README.md | 0 {66 Number => 66_Number}/java/main.class | 0 {66 Number => 66_Number}/javascript/README.md | 0 {66 Number => 66_Number}/javascript/number.html | 0 {66 Number => 66_Number}/javascript/number.js | 0 {66 Number => 66_Number}/number.bas | 0 {66 Number => 66_Number}/pascal/README.md | 0 {66 Number => 66_Number}/perl/README.md | 0 {66 Number => 66_Number}/perl/number.pl | 0 {66 Number => 66_Number}/python/README.md | 0 {66 Number => 66_Number}/python/number.py | 0 {66 Number => 66_Number}/ruby/README.md | 0 {66 Number => 66_Number}/vbnet/README.md | 0 {67 One Check => 67_One_Check}/README.md | 0 {67 One Check => 67_One_Check}/csharp/README.md | 0 {67 One Check => 67_One_Check}/java/OneCheck.java | 0 {67 One Check => 67_One_Check}/java/README.md | 0 {67 One Check => 67_One_Check}/javascript/README.md | 0 {67 One Check => 67_One_Check}/javascript/onecheck.html | 0 {67 One Check => 67_One_Check}/javascript/onecheck.js | 0 {67 One Check => 67_One_Check}/onecheck.bas | 0 {67 One Check => 67_One_Check}/pascal/README.md | 0 {67 One Check => 67_One_Check}/perl/README.md | 0 {67 One Check => 67_One_Check}/python/README.md | 0 {67 One Check => 67_One_Check}/ruby/README.md | 0 {67 One Check => 67_One_Check}/vbnet/README.md | 0 {68 Orbit => 68_Orbit}/README.md | 0 {68 Orbit => 68_Orbit}/csharp/README.md | 0 {68 Orbit => 68_Orbit}/java/Orbit.java | 0 {68 Orbit => 68_Orbit}/java/README.md | 0 {68 Orbit => 68_Orbit}/javascript/README.md | 0 {68 Orbit => 68_Orbit}/javascript/orbit.html | 0 {68 Orbit => 68_Orbit}/javascript/orbit.js | 0 {68 Orbit => 68_Orbit}/orbit.bas | 0 {68 Orbit => 68_Orbit}/pascal/README.md | 0 {68 Orbit => 68_Orbit}/perl/README.md | 0 {68 Orbit => 68_Orbit}/python/README.md | 0 {68 Orbit => 68_Orbit}/python/orbit.py | 0 {68 Orbit => 68_Orbit}/ruby/README.md | 0 {68 Orbit => 68_Orbit}/vbnet/README.md | 0 {69 Pizza => 69_Pizza}/README.md | 0 {69 Pizza => 69_Pizza}/csharp/README.md | 0 {69 Pizza => 69_Pizza}/java/README.md | 0 {69 Pizza => 69_Pizza}/java/src/Pizza.java | 0 {69 Pizza => 69_Pizza}/java/src/PizzaGame.java | 0 {69 Pizza => 69_Pizza}/javascript/README.md | 0 {69 Pizza => 69_Pizza}/javascript/pizza.html | 0 {69 Pizza => 69_Pizza}/javascript/pizza.js | 0 {69 Pizza => 69_Pizza}/pascal/README.md | 0 {69 Pizza => 69_Pizza}/perl/README.md | 0 {69 Pizza => 69_Pizza}/pizza.bas | 0 {69 Pizza => 69_Pizza}/python/README.md | 0 {69 Pizza => 69_Pizza}/python/pizza.py | 0 {69 Pizza => 69_Pizza}/ruby/README.md | 0 {69 Pizza => 69_Pizza}/vbnet/README.md | 0 {70 Poetry => 70_Poetry}/README.md | 0 {70 Poetry => 70_Poetry}/csharp/README.md | 0 {70 Poetry => 70_Poetry}/java/Poetry.java | 0 {70 Poetry => 70_Poetry}/java/README.md | 0 {70 Poetry => 70_Poetry}/javascript/README.md | 0 {70 Poetry => 70_Poetry}/javascript/poetry.html | 0 {70 Poetry => 70_Poetry}/javascript/poetry.js | 0 {70 Poetry => 70_Poetry}/pascal/README.md | 0 {70 Poetry => 70_Poetry}/perl/README.md | 0 {70 Poetry => 70_Poetry}/perl/poetry.pl | 0 {70 Poetry => 70_Poetry}/poetry.bas | 0 {70 Poetry => 70_Poetry}/poetry.pl | 0 {70 Poetry => 70_Poetry}/python/README.md | 0 {70 Poetry => 70_Poetry}/python/poetry.py | 0 {70 Poetry => 70_Poetry}/ruby/README.md | 0 {70 Poetry => 70_Poetry}/vbnet/README.md | 0 {71 Poker => 71_Poker}/README.md | 0 {71 Poker => 71_Poker}/csharp/README.md | 0 {71 Poker => 71_Poker}/java/README.md | 0 {71 Poker => 71_Poker}/javascript/README.md | 0 {71 Poker => 71_Poker}/javascript/poker.html | 0 {71 Poker => 71_Poker}/javascript/poker.js | 0 {71 Poker => 71_Poker}/pascal/README.md | 0 {71 Poker => 71_Poker}/perl/README.md | 0 {71 Poker => 71_Poker}/poker.bas | 0 {71 Poker => 71_Poker}/python/README.md | 0 {71 Poker => 71_Poker}/ruby/README.md | 0 {71 Poker => 71_Poker}/vbnet/README.md | 0 {72 Queen => 72_Queen}/README.md | 0 {72 Queen => 72_Queen}/csharp/README.md | 0 {72 Queen => 72_Queen}/java/README.md | 0 {72 Queen => 72_Queen}/javascript/README.md | 0 {72 Queen => 72_Queen}/javascript/queen.html | 0 {72 Queen => 72_Queen}/javascript/queen.js | 0 {72 Queen => 72_Queen}/pascal/README.md | 0 {72 Queen => 72_Queen}/perl/README.md | 0 {72 Queen => 72_Queen}/python/README.md | 0 {72 Queen => 72_Queen}/queen.bas | 0 {72 Queen => 72_Queen}/ruby/README.md | 0 {72 Queen => 72_Queen}/vbnet/README.md | 0 {73 Reverse => 73_Reverse}/README.md | 0 {73 Reverse => 73_Reverse}/csharp/README.md | 0 {73 Reverse => 73_Reverse}/java/README.md | 0 {73 Reverse => 73_Reverse}/java/Reverse.java | 0 {73 Reverse => 73_Reverse}/javascript/README.md | 0 {73 Reverse => 73_Reverse}/javascript/reverse.html | 0 {73 Reverse => 73_Reverse}/javascript/reverse.js | 0 {73 Reverse => 73_Reverse}/pascal/README.md | 0 {73 Reverse => 73_Reverse}/perl/README.md | 0 {73 Reverse => 73_Reverse}/python/README.md | 0 {73 Reverse => 73_Reverse}/python/reverse.py | 0 {73 Reverse => 73_Reverse}/reverse.bas | 0 {73 Reverse => 73_Reverse}/ruby/README.md | 0 {73 Reverse => 73_Reverse}/vbnet/README.md | 0 {73 Reverse => 73_Reverse}/vbnet/Reverse.vb | 0 {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/README.md | 0 .../csharp/Choice.cs | 0 .../csharp/Choices.cs | 0 {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/Game.cs | 0 .../csharp/Program.cs | 0 .../csharp/README.md | 0 .../csharp/RockScissorsPaper.csproj | 0 {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/java/README.md | 0 .../java/src/RockScissors.java | 0 .../javascript/README.md | 0 .../javascript/rockscissors.html | 0 .../javascript/rockscissors.js | 0 .../pascal/README.md | 0 {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/perl/README.md | 0 .../perl/rockscissors.pl | 0 .../python/README.md | 0 .../python/rockscissors.py | 0 .../rockscissors.bas | 0 {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/ruby/README.md | 0 .../vbnet/README.md | 0 {75 Roulette => 75_Roulette}/README.md | 0 {75 Roulette => 75_Roulette}/csharp/README.md | 0 {75 Roulette => 75_Roulette}/java/README.md | 0 {75 Roulette => 75_Roulette}/javascript/README.md | 0 {75 Roulette => 75_Roulette}/javascript/roulette.html | 0 {75 Roulette => 75_Roulette}/javascript/roulette.js | 0 {75 Roulette => 75_Roulette}/pascal/README.md | 0 {75 Roulette => 75_Roulette}/perl/README.md | 0 {75 Roulette => 75_Roulette}/python/README.md | 0 {75 Roulette => 75_Roulette}/roulette.bas | 0 {75 Roulette => 75_Roulette}/ruby/README.md | 0 {75 Roulette => 75_Roulette}/vbnet/README.md | 0 {76 Russian Roulette => 76_Russian_Roulette}/README.md | 0 {76 Russian Roulette => 76_Russian_Roulette}/csharp/README.md | 0 .../csharp/RussianRoulette/Program.cs | 0 .../csharp/RussianRoulette/RussianRoulette.csproj | 0 .../csharp/RussianRoulette/RussianRoulette.sln | 0 {76 Russian Roulette => 76_Russian_Roulette}/java/README.md | 0 .../java/src/RussianRoulette.java | 0 {76 Russian Roulette => 76_Russian_Roulette}/javascript/README.md | 0 .../javascript/russianroulette.html | 0 .../javascript/russianroulette.js | 0 {76 Russian Roulette => 76_Russian_Roulette}/pascal/README.md | 0 {76 Russian Roulette => 76_Russian_Roulette}/perl/README.md | 0 .../perl/russianroulette.pl | 0 {76 Russian Roulette => 76_Russian_Roulette}/python/README.md | 0 .../python/russianroulette.py | 0 {76 Russian Roulette => 76_Russian_Roulette}/ruby/README.md | 0 {76 Russian Roulette => 76_Russian_Roulette}/russianroulette.bas | 0 {76 Russian Roulette => 76_Russian_Roulette}/vbnet/README.md | 0 {77 Salvo => 77_Salvo}/README.md | 0 {77 Salvo => 77_Salvo}/csharp/README.md | 0 {77 Salvo => 77_Salvo}/java/README.md | 0 {77 Salvo => 77_Salvo}/javascript/README.md | 0 {77 Salvo => 77_Salvo}/javascript/salvo.html | 0 {77 Salvo => 77_Salvo}/javascript/salvo.js | 0 {77 Salvo => 77_Salvo}/pascal/README.md | 0 {77 Salvo => 77_Salvo}/perl/README.md | 0 {77 Salvo => 77_Salvo}/python/README.md | 0 {77 Salvo => 77_Salvo}/python/salvo.ipynb | 0 {77 Salvo => 77_Salvo}/python/salvo.py | 0 {77 Salvo => 77_Salvo}/ruby/README.md | 0 {77 Salvo => 77_Salvo}/salvo.bas | 0 {77 Salvo => 77_Salvo}/vbnet/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/csharp/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/csharp/SineWave/SineWave.sln | 0 .../csharp/SineWave/SineWave/Program.cs | 0 .../csharp/SineWave/SineWave/SineWave.csproj | 0 {78 Sine Wave => 78_Sine_Wave}/java/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/java/src/SineWave.java | 0 {78 Sine Wave => 78_Sine_Wave}/javascript/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/javascript/sinewave.js | 0 {78 Sine Wave => 78_Sine_Wave}/pascal/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/perl/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/perl/sinewave.pl | 0 {78 Sine Wave => 78_Sine_Wave}/python/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/python/sinewave.py | 0 {78 Sine Wave => 78_Sine_Wave}/ruby/README.md | 0 {78 Sine Wave => 78_Sine_Wave}/ruby/sinewave.rb | 0 {78 Sine Wave => 78_Sine_Wave}/sinewave.bas | 0 {78 Sine Wave => 78_Sine_Wave}/vbnet/README.md | 0 {79 Slalom => 79_Slalom}/README.md | 0 {79 Slalom => 79_Slalom}/csharp/README.md | 0 {79 Slalom => 79_Slalom}/java/README.md | 0 {79 Slalom => 79_Slalom}/javascript/README.md | 0 {79 Slalom => 79_Slalom}/javascript/slalom.html | 0 {79 Slalom => 79_Slalom}/javascript/slalom.js | 0 {79 Slalom => 79_Slalom}/pascal/README.md | 0 {79 Slalom => 79_Slalom}/perl/README.md | 0 {79 Slalom => 79_Slalom}/python/README.md | 0 {79 Slalom => 79_Slalom}/ruby/README.md | 0 {79 Slalom => 79_Slalom}/slalom.bas | 0 {79 Slalom => 79_Slalom}/vbnet/README.md | 0 {80 Slots => 80_Slots}/README.md | 0 {80 Slots => 80_Slots}/csharp/README.md | 0 {80 Slots => 80_Slots}/java/README.md | 0 {80 Slots => 80_Slots}/java/src/Slots.java | 0 {80 Slots => 80_Slots}/java/src/SlotsGame.java | 0 {80 Slots => 80_Slots}/javascript/README.md | 0 {80 Slots => 80_Slots}/javascript/slots.html | 0 {80 Slots => 80_Slots}/javascript/slots.js | 0 {80 Slots => 80_Slots}/pascal/README.md | 0 {80 Slots => 80_Slots}/perl/README.md | 0 {80 Slots => 80_Slots}/python/README.md | 0 {80 Slots => 80_Slots}/python/slots.py | 0 {80 Slots => 80_Slots}/ruby/README.md | 0 {80 Slots => 80_Slots}/slots.bas | 0 {80 Slots => 80_Slots}/vbnet/README.md | 0 {81 Splat => 81_Splat}/README.md | 0 {81 Splat => 81_Splat}/csharp/README.md | 0 {81 Splat => 81_Splat}/java/README.md | 0 {81 Splat => 81_Splat}/javascript/README.md | 0 {81 Splat => 81_Splat}/javascript/splat.html | 0 {81 Splat => 81_Splat}/javascript/splat.js | 0 {81 Splat => 81_Splat}/pascal/README.md | 0 {81 Splat => 81_Splat}/perl/README.md | 0 {81 Splat => 81_Splat}/python/README.md | 0 {81 Splat => 81_Splat}/python/splat.py | 0 {81 Splat => 81_Splat}/ruby/README.md | 0 {81 Splat => 81_Splat}/splat.bas | 0 {81 Splat => 81_Splat}/vbnet/README.md | 0 {82 Stars => 82_Stars}/README.md | 0 {82 Stars => 82_Stars}/csharp/README.md | 0 {82 Stars => 82_Stars}/csharp/Stars.sln | 0 {82 Stars => 82_Stars}/csharp/Stars/Game.cs | 0 {82 Stars => 82_Stars}/csharp/Stars/Input.cs | 0 {82 Stars => 82_Stars}/csharp/Stars/Program.cs | 0 {82 Stars => 82_Stars}/csharp/Stars/Stars.csproj | 0 {82 Stars => 82_Stars}/java/README.md | 0 {82 Stars => 82_Stars}/java/src/Stars.java | 0 {82 Stars => 82_Stars}/java/src/StarsGame.java | 0 {82 Stars => 82_Stars}/javascript/README.md | 0 {82 Stars => 82_Stars}/javascript/stars.html | 0 {82 Stars => 82_Stars}/javascript/stars.js | 0 {82 Stars => 82_Stars}/pascal/README.md | 0 {82 Stars => 82_Stars}/perl/README.md | 0 {82 Stars => 82_Stars}/python/README.md | 0 {82 Stars => 82_Stars}/python/stars.py | 0 {82 Stars => 82_Stars}/ruby/README.md | 0 {82 Stars => 82_Stars}/stars.bas | 0 {82 Stars => 82_Stars}/vbnet/README.md | 0 {83 Stock Market => 83_Stock_Market}/README.md | 0 {83 Stock Market => 83_Stock_Market}/csharp/Game.csproj | 0 {83 Stock Market => 83_Stock_Market}/csharp/README.md | 0 {83 Stock Market => 83_Stock_Market}/csharp/StockMarket.sln | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/Assets.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/Broker.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/Company.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/Controller.cs | 0 .../csharp/src/Extensions/EnumerableExtensions.cs | 0 .../csharp/src/Extensions/ImmutableArrayExtensions.cs | 0 .../csharp/src/Extensions/RandomExtensions.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/Program.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/StockMarket.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/TradingDay.cs | 0 .../csharp/src/TransactionResult.cs | 0 {83 Stock Market => 83_Stock_Market}/csharp/src/View.cs | 0 {83 Stock Market => 83_Stock_Market}/java/README.md | 0 {83 Stock Market => 83_Stock_Market}/javascript/README.md | 0 {83 Stock Market => 83_Stock_Market}/javascript/stockmarket.html | 0 {83 Stock Market => 83_Stock_Market}/javascript/stockmarket.js | 0 {83 Stock Market => 83_Stock_Market}/pascal/README.md | 0 {83 Stock Market => 83_Stock_Market}/perl/README.md | 0 {83 Stock Market => 83_Stock_Market}/python/README.md | 0 {83 Stock Market => 83_Stock_Market}/ruby/README.md | 0 {83 Stock Market => 83_Stock_Market}/stockmarket.bas | 0 {83 Stock Market => 83_Stock_Market}/vbnet/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/README.md | 0 .../csharp/Commands/Command.cs | 0 .../csharp/Commands/CommandExtensions.cs | 0 .../csharp/Commands/CommandResult.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Game.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Input.cs | 0 .../csharp/Objects/Enterprise.cs | 0 .../csharp/Objects/Klingon.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Objects/Star.cs | 0 .../csharp/Objects/Starbase.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Output.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Program.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Random.cs | 0 .../csharp/Resources/CombatArea.txt | 0 .../csharp/Resources/Congratulations.txt | 0 .../csharp/Resources/CourtMartial.txt | 0 .../csharp/Resources/Destroyed.txt | 0 .../csharp/Resources/EndOfMission.txt | 0 .../csharp/Resources/Enterprise.txt | 0 .../csharp/Resources/Instructions.txt | 0 .../csharp/Resources/LowShields.txt | 0 .../csharp/Resources/NoEnemyShips.txt | 0 .../csharp/Resources/NoStarbase.txt | 0 .../csharp/Resources/NowEntering.txt | 0 .../csharp/Resources/Orders.txt | 0 .../csharp/Resources/PermissionDenied.txt | 0 .../csharp/Resources/Protected.txt | 0 .../csharp/Resources/RegionNames.txt | 0 .../csharp/Resources/RelievedOfCommand.txt | 0 .../csharp/Resources/RepairEstimate.txt | 0 .../csharp/Resources/RepairPrompt.txt | 0 .../csharp/Resources/ReplayPrompt.txt | 0 .../csharp/Resources/ShieldsDropped.txt | 0 .../csharp/Resources/ShieldsSet.txt | 0 .../csharp/Resources/ShortRangeSensorsOut.txt | 0 .../csharp/Resources/StartText.txt | 0 .../csharp/Resources/Stranded.txt | 0 .../csharp/Resources/Strings.cs | 0 .../csharp/Resources/Title.txt | 0 .../csharp/Space/Coordinates.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/Course.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/Galaxy.cs | 0 .../csharp/Space/Quadrant.cs | 0 .../csharp/Space/QuadrantInfo.cs | 0 .../csharp/StringExtensions.cs | 0 .../csharp/SuperStarTrek.csproj | 0 .../csharp/SuperStarTrek.sln | 0 .../csharp/Systems/ComputerFunctions/ComputerFunction.cs | 0 .../csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs | 0 .../Systems/ComputerFunctions/DirectionDistanceCalculator.cs | 0 .../csharp/Systems/ComputerFunctions/GalacticReport.cs | 0 .../csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs | 0 .../csharp/Systems/ComputerFunctions/NavigationCalculator.cs | 0 .../csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs | 0 .../csharp/Systems/ComputerFunctions/StatusReport.cs | 0 .../csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs | 0 .../csharp/Systems/DamageControl.cs | 0 .../csharp/Systems/LibraryComputer.cs | 0 .../csharp/Systems/LongRangeSensors.cs | 0 .../csharp/Systems/PhaserControl.cs | 0 .../csharp/Systems/PhotonTubes.cs | 0 .../csharp/Systems/ShieldControl.cs | 0 .../csharp/Systems/ShortRangeSensors.cs | 0 .../csharp/Systems/Subsystem.cs | 0 .../csharp/Systems/WarpEngines.cs | 0 .../csharp/Utils/DirectionAndDistance.cs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/instructions.txt | 0 {84 Super Star Trek => 84_Super_Star_Trek}/java/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/javascript/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/javascript/cli.mjs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/javascript/index.html | 0 .../javascript/package.json | 0 .../javascript/superstartrek.mjs | 0 {84 Super Star Trek => 84_Super_Star_Trek}/pascal/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/perl/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/python/README.md | 0 .../python/superstartrek.py | 0 .../python/superstartrekins.py | 0 {84 Super Star Trek => 84_Super_Star_Trek}/ruby/README.md | 0 {84 Super Star Trek => 84_Super_Star_Trek}/superstartrek.bas | 0 {84 Super Star Trek => 84_Super_Star_Trek}/superstartrekins.bas | 0 {84 Super Star Trek => 84_Super_Star_Trek}/vbnet/README.md | 0 {85 Synonym => 85_Synonym}/README.md | 0 {85 Synonym => 85_Synonym}/csharp/README.md | 0 {85 Synonym => 85_Synonym}/java/README.md | 0 {85 Synonym => 85_Synonym}/java/src/Synonym.java | 0 {85 Synonym => 85_Synonym}/java/src/SynonymGame.java | 0 {85 Synonym => 85_Synonym}/java/src/SynonymList.java | 0 {85 Synonym => 85_Synonym}/javascript/README.md | 0 {85 Synonym => 85_Synonym}/javascript/synonym.html | 0 {85 Synonym => 85_Synonym}/javascript/synonym.js | 0 {85 Synonym => 85_Synonym}/pascal/README.md | 0 {85 Synonym => 85_Synonym}/perl/README.md | 0 {85 Synonym => 85_Synonym}/python/README.md | 0 {85 Synonym => 85_Synonym}/python/synonym.py | 0 {85 Synonym => 85_Synonym}/ruby/README.md | 0 {85 Synonym => 85_Synonym}/synonym.bas | 0 {85 Synonym => 85_Synonym}/vbnet/README.md | 0 {86 Target => 86_Target}/README.md | 0 {86 Target => 86_Target}/csharp/README.md | 0 {86 Target => 86_Target}/csharp/Target.sln | 0 {86 Target => 86_Target}/csharp/Target/Angle.cs | 0 {86 Target => 86_Target}/csharp/Target/Explosion.cs | 0 {86 Target => 86_Target}/csharp/Target/FiringRange.cs | 0 {86 Target => 86_Target}/csharp/Target/Game.cs | 0 {86 Target => 86_Target}/csharp/Target/Input.cs | 0 {86 Target => 86_Target}/csharp/Target/Offset.cs | 0 {86 Target => 86_Target}/csharp/Target/Point.cs | 0 {86 Target => 86_Target}/csharp/Target/Program.cs | 0 {86 Target => 86_Target}/csharp/Target/RandomExtensions.cs | 0 .../csharp/Target/Strings/TitleAndInstructions.txt | 0 {86 Target => 86_Target}/csharp/Target/Target.csproj | 0 {86 Target => 86_Target}/java/README.md | 0 {86 Target => 86_Target}/java/Target.java | 0 {86 Target => 86_Target}/javascript/README.md | 0 {86 Target => 86_Target}/javascript/target.html | 0 {86 Target => 86_Target}/javascript/target.js | 0 {86 Target => 86_Target}/pascal/README.md | 0 {86 Target => 86_Target}/perl/README.md | 0 {86 Target => 86_Target}/python/README.md | 0 {86 Target => 86_Target}/python/target.py | 0 {86 Target => 86_Target}/ruby/README.md | 0 {86 Target => 86_Target}/target.bas | 0 {86 Target => 86_Target}/vbnet/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/3dplot.bas | 0 {87 3-D Plot => 87_3-D_Plot}/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/csharp/Plot.sln | 0 {87 3-D Plot => 87_3-D_Plot}/csharp/Plot/Function.cs | 0 {87 3-D Plot => 87_3-D_Plot}/csharp/Plot/Plot.csproj | 0 {87 3-D Plot => 87_3-D_Plot}/csharp/Plot/Program.cs | 0 {87 3-D Plot => 87_3-D_Plot}/csharp/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/java/Plot3D.java | 0 {87 3-D Plot => 87_3-D_Plot}/java/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/javascript/3dplot.html | 0 {87 3-D Plot => 87_3-D_Plot}/javascript/3dplot.js | 0 {87 3-D Plot => 87_3-D_Plot}/javascript/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/pascal/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/perl/3dplot.pl | 0 {87 3-D Plot => 87_3-D_Plot}/perl/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/python/3dplot.py | 0 {87 3-D Plot => 87_3-D_Plot}/python/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/ruby/3dplot.rb | 0 {87 3-D Plot => 87_3-D_Plot}/ruby/README.md | 0 {87 3-D Plot => 87_3-D_Plot}/vbnet/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/csharp/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/java/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/javascript/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/javascript/qubit.html | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/javascript/qubit.js | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/pascal/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/perl/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/python/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/python/qubit.py | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/qubit.bas | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/ruby/README.md | 0 {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/vbnet/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/csharp/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/java/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/java/src/Board.java | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/java/src/TicTacToe2.java | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe1.html | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe1.js | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe2.html | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe2.js | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/pascal/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/perl/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/python/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/python/tictactoe2.py | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/ruby/README.md | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/tictactoe1.bas | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/tictactoe2.bas | 0 {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/vbnet/README.md | 0 {90 Tower => 90_Tower}/README.md | 0 {90 Tower => 90_Tower}/csharp/README.md | 0 {90 Tower => 90_Tower}/java/README.md | 0 {90 Tower => 90_Tower}/java/Tower.java | 0 {90 Tower => 90_Tower}/javascript/README.md | 0 {90 Tower => 90_Tower}/javascript/tower.html | 0 {90 Tower => 90_Tower}/javascript/tower.js | 0 {90 Tower => 90_Tower}/pascal/README.md | 0 {90 Tower => 90_Tower}/perl/README.md | 0 {90 Tower => 90_Tower}/python/README.md | 0 {90 Tower => 90_Tower}/ruby/README.md | 0 {90 Tower => 90_Tower}/tower.bas | 0 {90 Tower => 90_Tower}/vbnet/README.md | 0 {91 Train => 91_Train}/README.md | 0 {91 Train => 91_Train}/csharp/README.md | 0 {91 Train => 91_Train}/java/README.md | 0 {91 Train => 91_Train}/java/src/Train.java | 0 {91 Train => 91_Train}/javascript/README.md | 0 {91 Train => 91_Train}/javascript/train.html | 0 {91 Train => 91_Train}/javascript/train.js | 0 {91 Train => 91_Train}/pascal/README.md | 0 {91 Train => 91_Train}/perl/README.md | 0 {91 Train => 91_Train}/perl/train.pl | 0 {91 Train => 91_Train}/python/README.md | 0 {91 Train => 91_Train}/python/train.py | 0 {91 Train => 91_Train}/ruby/README.md | 0 {91 Train => 91_Train}/ruby/train.rb | 0 {91 Train => 91_Train}/train.bas | 0 {91 Train => 91_Train}/vbnet/README.md | 0 {92 Trap => 92_Trap}/README.md | 0 {92 Trap => 92_Trap}/csharp/README.md | 0 {92 Trap => 92_Trap}/java/README.md | 0 {92 Trap => 92_Trap}/java/src/Trap.java | 0 {92 Trap => 92_Trap}/java/src/TrapGame.java | 0 {92 Trap => 92_Trap}/javascript/README.md | 0 {92 Trap => 92_Trap}/javascript/trap.html | 0 {92 Trap => 92_Trap}/javascript/trap.js | 0 {92 Trap => 92_Trap}/pascal/README.md | 0 {92 Trap => 92_Trap}/perl/README.md | 0 {92 Trap => 92_Trap}/perl/trap.pl | 0 {92 Trap => 92_Trap}/python/README.md | 0 {92 Trap => 92_Trap}/python/trap.py | 0 {92 Trap => 92_Trap}/ruby/README.md | 0 {92 Trap => 92_Trap}/trap.bas | 0 {92 Trap => 92_Trap}/vbnet/README.md | 0 {93 23 Matches => 93_23_Matches}/23matches.bas | 0 {93 23 Matches => 93_23_Matches}/README.md | 0 {93 23 Matches => 93_23_Matches}/csharp/README.md | 0 {93 23 Matches => 93_23_Matches}/java/README.md | 0 {93 23 Matches => 93_23_Matches}/java/TwentyThreeMatches.java | 0 {93 23 Matches => 93_23_Matches}/javascript/23matches.html | 0 {93 23 Matches => 93_23_Matches}/javascript/23matches.js | 0 {93 23 Matches => 93_23_Matches}/javascript/README.md | 0 {93 23 Matches => 93_23_Matches}/pascal/README.md | 0 {93 23 Matches => 93_23_Matches}/perl/README.md | 0 {93 23 Matches => 93_23_Matches}/python/23matches.py | 0 {93 23 Matches => 93_23_Matches}/python/README.md | 0 {93 23 Matches => 93_23_Matches}/ruby/README.md | 0 {93 23 Matches => 93_23_Matches}/vbnet/README.md | 0 {94 War => 94_War}/README.md | 0 {94 War => 94_War}/csharp/README.md | 0 {94 War => 94_War}/csharp/War/War.sln | 0 {94 War => 94_War}/csharp/War/War/Cards.cs | 0 {94 War => 94_War}/csharp/War/War/Program.cs | 0 {94 War => 94_War}/csharp/War/War/UserInterface.cs | 0 {94 War => 94_War}/csharp/War/War/War.csproj | 0 {94 War => 94_War}/csharp/War/WarTester/Tests.cs | 0 {94 War => 94_War}/csharp/War/WarTester/WarTester.csproj | 0 {94 War => 94_War}/java/README.md | 0 {94 War => 94_War}/java/War.java | 0 {94 War => 94_War}/javascript/README.md | 0 {94 War => 94_War}/javascript/war.html | 0 {94 War => 94_War}/javascript/war.js | 0 {94 War => 94_War}/pascal/README.md | 0 {94 War => 94_War}/perl/README.md | 0 {94 War => 94_War}/python/README.md | 0 {94 War => 94_War}/python/war.py | 0 {94 War => 94_War}/ruby/README.md | 0 {94 War => 94_War}/vbnet/README.md | 0 {94 War => 94_War}/war.bas | 0 {95 Weekday => 95_Weekday}/README.md | 0 {95 Weekday => 95_Weekday}/csharp/README.md | 0 {95 Weekday => 95_Weekday}/java/README.md | 0 {95 Weekday => 95_Weekday}/java/Weekday.java | 0 {95 Weekday => 95_Weekday}/javascript/README.md | 0 {95 Weekday => 95_Weekday}/javascript/weekday.html | 0 {95 Weekday => 95_Weekday}/javascript/weekday.js | 0 {95 Weekday => 95_Weekday}/pascal/README.md | 0 {95 Weekday => 95_Weekday}/perl/README.md | 0 {95 Weekday => 95_Weekday}/python/README.md | 0 {95 Weekday => 95_Weekday}/python/weekday.py | 0 {95 Weekday => 95_Weekday}/ruby/README.md | 0 {95 Weekday => 95_Weekday}/vbnet/README.md | 0 {95 Weekday => 95_Weekday}/weekday.bas | 0 {96 Word => 96_Word}/README.md | 0 {96 Word => 96_Word}/csharp/Program.cs | 0 {96 Word => 96_Word}/csharp/README.md | 0 {96 Word => 96_Word}/csharp/word.csproj | 0 {96 Word => 96_Word}/csharp/word.sln | 0 {96 Word => 96_Word}/java/README.md | 0 {96 Word => 96_Word}/java/Word.java | 0 {96 Word => 96_Word}/javascript/README.md | 0 {96 Word => 96_Word}/javascript/word.html | 0 {96 Word => 96_Word}/javascript/word.js | 0 {96 Word => 96_Word}/pascal/README.md | 0 {96 Word => 96_Word}/perl/README.md | 0 {96 Word => 96_Word}/python/README.md | 0 {96 Word => 96_Word}/python/word.py | 0 {96 Word => 96_Word}/ruby/README.md | 0 {96 Word => 96_Word}/ruby/word.rb | 0 {96 Word => 96_Word}/vbnet/Program.vb | 0 {96 Word => 96_Word}/vbnet/README.md | 0 {96 Word => 96_Word}/vbnet/word.sln | 0 {96 Word => 96_Word}/vbnet/word.vbproj | 0 {96 Word => 96_Word}/word.bas | 0 1725 files changed, 0 insertions(+), 0 deletions(-) rename {01 Acey Ducey => 01_Acey_Ducey}/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/aceyducey.bas (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/csharp/AceyDucey.csproj (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/csharp/AceyDucey.sln (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/csharp/Game.cs (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/csharp/GameState.cs (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/csharp/Program.cs (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/csharp/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/java/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/java/src/AceyDucey.java (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/java/src/AceyDuceyGame.java (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/java/src/Card.java (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/javascript/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/javascript/aceyducey.html (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/javascript/aceyducey.js (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/.gitattributes (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/.gitignore (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/object-pascal/aceyducey.lpi (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/object-pascal/aceyducey.pas (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/object-pascal/deck.pas (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/object-pascal/game.pas (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/simple/aceyducey.lpi (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/pascal/simple/aceyducey.pas (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/perl/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/perl/aceyducey.pl (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/python/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/python/acey_ducey.py (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/python/aceyducey.py (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/ruby/README.md (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/ruby/aceyducey.rb (100%) rename {01 Acey Ducey => 01_Acey_Ducey}/vbnet/README.md (100%) rename {02 Amazing => 02_Amazing}/README.md (100%) rename {02 Amazing => 02_Amazing}/amazing.bas (100%) rename {02 Amazing => 02_Amazing}/csharp/Amazing.cs (100%) rename {02 Amazing => 02_Amazing}/csharp/Amazing.csproj (100%) rename {02 Amazing => 02_Amazing}/csharp/Amazing.sln (100%) rename {02 Amazing => 02_Amazing}/csharp/README.md (100%) rename {02 Amazing => 02_Amazing}/java/Amazing.java (100%) rename {02 Amazing => 02_Amazing}/java/AmazingGame.java (100%) rename {02 Amazing => 02_Amazing}/java/README.md (100%) rename {02 Amazing => 02_Amazing}/javascript/README.md (100%) rename {02 Amazing => 02_Amazing}/javascript/amazing.html (100%) rename {02 Amazing => 02_Amazing}/javascript/amazing.js (100%) rename {02 Amazing => 02_Amazing}/pascal/.gitattributes (100%) rename {02 Amazing => 02_Amazing}/pascal/.gitignore (100%) rename {02 Amazing => 02_Amazing}/pascal/README.md (100%) rename {02 Amazing => 02_Amazing}/pascal/object-pascal/amazing.lpi (100%) rename {02 Amazing => 02_Amazing}/pascal/object-pascal/amazing.pas (100%) rename {02 Amazing => 02_Amazing}/pascal/object-pascal/amazingapplication.pas (100%) rename {02 Amazing => 02_Amazing}/pascal/object-pascal/maze.pas (100%) rename {02 Amazing => 02_Amazing}/pascal/object-pascal/room.pas (100%) rename {02 Amazing => 02_Amazing}/pascal/simple/amazing.lpi (100%) rename {02 Amazing => 02_Amazing}/pascal/simple/amazing.pas (100%) rename {02 Amazing => 02_Amazing}/perl/README.md (100%) rename {02 Amazing => 02_Amazing}/python/README.md (100%) rename {02 Amazing => 02_Amazing}/python/amazing.py (100%) rename {02 Amazing => 02_Amazing}/ruby/README.md (100%) rename {02 Amazing => 02_Amazing}/ruby/amazing.rb (100%) rename {02 Amazing => 02_Amazing}/vbnet/README.md (100%) rename {03 Animal => 03_Animal}/README.md (100%) rename {03 Animal => 03_Animal}/animal.bas (100%) rename {03 Animal => 03_Animal}/csharp/Animal.csproj (100%) rename {03 Animal => 03_Animal}/csharp/Animal.sln (100%) rename {03 Animal => 03_Animal}/csharp/Branch.cs (100%) rename {03 Animal => 03_Animal}/csharp/Program.cs (100%) rename {03 Animal => 03_Animal}/csharp/README.md (100%) rename {03 Animal => 03_Animal}/java/Animal.java (100%) rename {03 Animal => 03_Animal}/java/README.md (100%) rename {03 Animal => 03_Animal}/javascript/README.md (100%) rename {03 Animal => 03_Animal}/javascript/animal.html (100%) rename {03 Animal => 03_Animal}/javascript/animal.js (100%) rename {03 Animal => 03_Animal}/pascal/README.md (100%) rename {03 Animal => 03_Animal}/perl/README.md (100%) rename {03 Animal => 03_Animal}/python/README.md (100%) rename {03 Animal => 03_Animal}/python/animal.py (100%) rename {03 Animal => 03_Animal}/ruby/README.md (100%) rename {03 Animal => 03_Animal}/ruby/animal.rb (100%) rename {03 Animal => 03_Animal}/vbnet/README.md (100%) rename {04 Awari => 04_Awari}/README.md (100%) rename {04 Awari => 04_Awari}/awari.bas (100%) rename {04 Awari => 04_Awari}/csharp/README.md (100%) rename {04 Awari => 04_Awari}/java/Awari.java (100%) rename {04 Awari => 04_Awari}/java/AwariGame.java (100%) rename {04 Awari => 04_Awari}/java/README.md (100%) rename {04 Awari => 04_Awari}/javascript/README.md (100%) rename {04 Awari => 04_Awari}/javascript/awari.html (100%) rename {04 Awari => 04_Awari}/javascript/awari.js (100%) rename {04 Awari => 04_Awari}/pascal/README.md (100%) rename {04 Awari => 04_Awari}/perl/README.md (100%) rename {04 Awari => 04_Awari}/python/README.md (100%) rename {04 Awari => 04_Awari}/python/awari.py (100%) rename {04 Awari => 04_Awari}/ruby/README.md (100%) rename {04 Awari => 04_Awari}/vbnet/README.md (100%) rename {05 Bagels => 05_Bagels}/README.md (100%) rename {05 Bagels => 05_Bagels}/bagels.bas (100%) rename {05 Bagels => 05_Bagels}/csharp/BagelNumber.cs (100%) rename {05 Bagels => 05_Bagels}/csharp/Bagels.csproj (100%) rename {05 Bagels => 05_Bagels}/csharp/Game.cs (100%) rename {05 Bagels => 05_Bagels}/csharp/GameBase.cs (100%) rename {05 Bagels => 05_Bagels}/csharp/Program.cs (100%) rename {05 Bagels => 05_Bagels}/csharp/README.md (100%) rename {05 Bagels => 05_Bagels}/java/BagelGame.java (100%) rename {05 Bagels => 05_Bagels}/java/Bagels.java (100%) rename {05 Bagels => 05_Bagels}/java/README.md (100%) rename {05 Bagels => 05_Bagels}/javascript/README.md (100%) rename {05 Bagels => 05_Bagels}/javascript/bagels.html (100%) rename {05 Bagels => 05_Bagels}/javascript/bagels.js (100%) rename {05 Bagels => 05_Bagels}/pascal/README.md (100%) rename {05 Bagels => 05_Bagels}/perl/README.md (100%) rename {05 Bagels => 05_Bagels}/python/README.md (100%) rename {05 Bagels => 05_Bagels}/python/bagels.py (100%) rename {05 Bagels => 05_Bagels}/ruby/README.md (100%) rename {05 Bagels => 05_Bagels}/ruby/bagels.rb (100%) rename {05 Bagels => 05_Bagels}/vbnet/README.md (100%) rename {06 Banner => 06_Banner}/README.md (100%) rename {06 Banner => 06_Banner}/banner.bas (100%) rename {06 Banner => 06_Banner}/csharp/README.md (100%) rename {06 Banner => 06_Banner}/csharp/banner.cs (100%) rename {06 Banner => 06_Banner}/csharp/banner.csproj (100%) rename {06 Banner => 06_Banner}/csharp/banner.sln (100%) rename {06 Banner => 06_Banner}/java/Banner.java (100%) rename {06 Banner => 06_Banner}/java/README.md (100%) rename {06 Banner => 06_Banner}/javascript/README.md (100%) rename {06 Banner => 06_Banner}/javascript/banner.html (100%) rename {06 Banner => 06_Banner}/javascript/banner.js (100%) rename {06 Banner => 06_Banner}/pascal/README.md (100%) rename {06 Banner => 06_Banner}/perl/README.md (100%) rename {06 Banner => 06_Banner}/python/README.md (100%) rename {06 Banner => 06_Banner}/python/banner.py (100%) rename {06 Banner => 06_Banner}/ruby/README.md (100%) rename {06 Banner => 06_Banner}/vbnet/README.md (100%) rename {06 Banner => 06_Banner}/vbnet/banner.sln (100%) rename {06 Banner => 06_Banner}/vbnet/banner.vb (100%) rename {06 Banner => 06_Banner}/vbnet/banner.vbproj (100%) rename {07 Basketball => 07_Basketball}/README.md (100%) rename {07 Basketball => 07_Basketball}/basketball.bas (100%) rename {07 Basketball => 07_Basketball}/csharp/README.md (100%) rename {07 Basketball => 07_Basketball}/java/README.md (100%) rename {07 Basketball => 07_Basketball}/javascript/README.md (100%) rename {07 Basketball => 07_Basketball}/javascript/basketball.html (100%) rename {07 Basketball => 07_Basketball}/javascript/basketball.js (100%) rename {07 Basketball => 07_Basketball}/pascal/README.md (100%) rename {07 Basketball => 07_Basketball}/perl/README.md (100%) rename {07 Basketball => 07_Basketball}/python/README.md (100%) rename {07 Basketball => 07_Basketball}/ruby/README.md (100%) rename {07 Basketball => 07_Basketball}/vbnet/README.md (100%) rename {08 Batnum => 08_Batnum}/README.md (100%) rename {08 Batnum => 08_Batnum}/batnum.bas (100%) rename {08 Batnum => 08_Batnum}/csharp/Batnum.csproj (100%) rename {08 Batnum => 08_Batnum}/csharp/Batnum.sln (100%) rename {08 Batnum => 08_Batnum}/csharp/BatnumGame.cs (100%) rename {08 Batnum => 08_Batnum}/csharp/ConsoleUtilities.cs (100%) rename {08 Batnum => 08_Batnum}/csharp/Program.cs (100%) rename {08 Batnum => 08_Batnum}/csharp/Properties/Resources.Designer.cs (100%) rename {08 Batnum => 08_Batnum}/csharp/Properties/Resources.en.resx (100%) rename {08 Batnum => 08_Batnum}/csharp/Properties/Resources.fr.resx (100%) rename {08 Batnum => 08_Batnum}/csharp/Properties/Resources.resx (100%) rename {08 Batnum => 08_Batnum}/csharp/README.md (100%) rename {08 Batnum => 08_Batnum}/java/README.md (100%) rename {08 Batnum => 08_Batnum}/java/src/BatNum.java (100%) rename {08 Batnum => 08_Batnum}/java/src/BatNumGame.java (100%) rename {08 Batnum => 08_Batnum}/javascript/README.md (100%) rename {08 Batnum => 08_Batnum}/javascript/batnum.html (100%) rename {08 Batnum => 08_Batnum}/javascript/batnum.js (100%) rename {08 Batnum => 08_Batnum}/pascal/README.md (100%) rename {08 Batnum => 08_Batnum}/perl/README.md (100%) rename {08 Batnum => 08_Batnum}/python/README.md (100%) rename {08 Batnum => 08_Batnum}/python/batnum.py (100%) rename {08 Batnum => 08_Batnum}/ruby/README.md (100%) rename {08 Batnum => 08_Batnum}/vbnet/Program.vb (100%) rename {08 Batnum => 08_Batnum}/vbnet/README.md (100%) rename {08 Batnum => 08_Batnum}/vbnet/batnum.sln (100%) rename {08 Batnum => 08_Batnum}/vbnet/batnum.vbproj (100%) rename {09 Battle => 09_Battle}/README.md (100%) rename {09 Battle => 09_Battle}/battle.bas (100%) rename {09 Battle => 09_Battle}/csharp/Battle.csproj (100%) rename {09 Battle => 09_Battle}/csharp/Battle.sln (100%) rename {09 Battle => 09_Battle}/csharp/Game.cs (100%) rename {09 Battle => 09_Battle}/csharp/Program.cs (100%) rename {09 Battle => 09_Battle}/csharp/README.md (100%) rename {09 Battle => 09_Battle}/java/README.md (100%) rename {09 Battle => 09_Battle}/javascript/README.md (100%) rename {09 Battle => 09_Battle}/javascript/battle.html (100%) rename {09 Battle => 09_Battle}/javascript/battle.js (100%) rename {09 Battle => 09_Battle}/pascal/README.md (100%) rename {09 Battle => 09_Battle}/perl/README.md (100%) rename {09 Battle => 09_Battle}/python/README.md (100%) rename {09 Battle => 09_Battle}/ruby/README.md (100%) rename {09 Battle => 09_Battle}/vbnet/README.md (100%) rename {10 Blackjack => 10_Blackjack}/README.md (100%) rename {10 Blackjack => 10_Blackjack}/blackjack.bas (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Blackjack.csproj (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Card.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Deck.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Game.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Hand.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Player.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Program.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/Prompt.cs (100%) rename {10 Blackjack => 10_Blackjack}/csharp/README.md (100%) rename {10 Blackjack => 10_Blackjack}/java/README.md (100%) rename {10 Blackjack => 10_Blackjack}/javascript/README.md (100%) rename {10 Blackjack => 10_Blackjack}/javascript/blackjack.html (100%) rename {10 Blackjack => 10_Blackjack}/javascript/blackjack.js (100%) rename {10 Blackjack => 10_Blackjack}/pascal/README.md (100%) rename {10 Blackjack => 10_Blackjack}/perl/README.md (100%) rename {10 Blackjack => 10_Blackjack}/python/README.md (100%) rename {10 Blackjack => 10_Blackjack}/ruby/README.md (100%) rename {10 Blackjack => 10_Blackjack}/vbnet/README.md (100%) rename {11 Bombardment => 11_Bombardment}/README.md (100%) rename {11 Bombardment => 11_Bombardment}/bombardment.bas (100%) rename {11 Bombardment => 11_Bombardment}/csharp/README.md (100%) rename {11 Bombardment => 11_Bombardment}/java/README.md (100%) rename {11 Bombardment => 11_Bombardment}/java/src/Bombardment.java (100%) rename {11 Bombardment => 11_Bombardment}/java/src/BombardmentGame.java (100%) rename {11 Bombardment => 11_Bombardment}/javascript/README.md (100%) rename {11 Bombardment => 11_Bombardment}/javascript/bombardment.html (100%) rename {11 Bombardment => 11_Bombardment}/javascript/bombardment.js (100%) rename {11 Bombardment => 11_Bombardment}/pascal/README.md (100%) rename {11 Bombardment => 11_Bombardment}/perl/README.md (100%) rename {11 Bombardment => 11_Bombardment}/python/README.md (100%) rename {11 Bombardment => 11_Bombardment}/python/bombardment.py (100%) rename {11 Bombardment => 11_Bombardment}/ruby/README.md (100%) rename {11 Bombardment => 11_Bombardment}/ruby/bombardment.rb (100%) rename {11 Bombardment => 11_Bombardment}/vbnet/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/bombsaway.bas (100%) rename {12 Bombs Away => 12_Bombs_Away}/csharp/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/java/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/java/src/BombsAway.java (100%) rename {12 Bombs Away => 12_Bombs_Away}/java/src/BombsAwayGame.java (100%) rename {12 Bombs Away => 12_Bombs_Away}/javascript/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/javascript/bombsaway.html (100%) rename {12 Bombs Away => 12_Bombs_Away}/javascript/bombsaway.js (100%) rename {12 Bombs Away => 12_Bombs_Away}/pascal/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/perl/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/python/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/ruby/README.md (100%) rename {12 Bombs Away => 12_Bombs_Away}/vbnet/README.md (100%) rename {13 Bounce => 13_Bounce}/README.md (100%) rename {13 Bounce => 13_Bounce}/bounce.bas (100%) rename {13 Bounce => 13_Bounce}/csharp/README.md (100%) rename {13 Bounce => 13_Bounce}/java/Bounce.java (100%) rename {13 Bounce => 13_Bounce}/java/README.md (100%) rename {13 Bounce => 13_Bounce}/javascript/README.md (100%) rename {13 Bounce => 13_Bounce}/javascript/bounce.html (100%) rename {13 Bounce => 13_Bounce}/javascript/bounce.js (100%) rename {13 Bounce => 13_Bounce}/pascal/README.md (100%) rename {13 Bounce => 13_Bounce}/perl/README.md (100%) rename {13 Bounce => 13_Bounce}/python/README.md (100%) rename {13 Bounce => 13_Bounce}/python/bounce.py (100%) rename {13 Bounce => 13_Bounce}/ruby/README.md (100%) rename {13 Bounce => 13_Bounce}/vbnet/README.md (100%) rename {14 Bowling => 14_Bowling}/README.md (100%) rename {14 Bowling => 14_Bowling}/bowling.bas (100%) rename {14 Bowling => 14_Bowling}/csharp/README.md (100%) rename {14 Bowling => 14_Bowling}/java/Bowling.java (100%) rename {14 Bowling => 14_Bowling}/java/README.md (100%) rename {14 Bowling => 14_Bowling}/javascript/README.md (100%) rename {14 Bowling => 14_Bowling}/javascript/bowling.html (100%) rename {14 Bowling => 14_Bowling}/javascript/bowling.js (100%) rename {14 Bowling => 14_Bowling}/pascal/README.md (100%) rename {14 Bowling => 14_Bowling}/perl/README.md (100%) rename {14 Bowling => 14_Bowling}/python/README.md (100%) rename {14 Bowling => 14_Bowling}/python/bowling.py (100%) rename {14 Bowling => 14_Bowling}/ruby/README.md (100%) rename {14 Bowling => 14_Bowling}/vbnet/README.md (100%) rename {15 Boxing => 15_Boxing}/README.md (100%) rename {15 Boxing => 15_Boxing}/boxing.bas (100%) rename {15 Boxing => 15_Boxing}/csharp/README.md (100%) rename {15 Boxing => 15_Boxing}/java/Basic.java (100%) rename {15 Boxing => 15_Boxing}/java/Boxing.java (100%) rename {15 Boxing => 15_Boxing}/java/BoxingGame.java (100%) rename {15 Boxing => 15_Boxing}/java/GameSession.java (100%) rename {15 Boxing => 15_Boxing}/java/Player.java (100%) rename {15 Boxing => 15_Boxing}/java/Punch.java (100%) rename {15 Boxing => 15_Boxing}/java/README.md (100%) rename {15 Boxing => 15_Boxing}/javascript/README.md (100%) rename {15 Boxing => 15_Boxing}/javascript/boxing.html (100%) rename {15 Boxing => 15_Boxing}/javascript/boxing.js (100%) rename {15 Boxing => 15_Boxing}/pascal/README.md (100%) rename {15 Boxing => 15_Boxing}/perl/README.md (100%) rename {15 Boxing => 15_Boxing}/python/README.md (100%) rename {15 Boxing => 15_Boxing}/python/boxing.py (100%) rename {15 Boxing => 15_Boxing}/ruby/README.md (100%) rename {15 Boxing => 15_Boxing}/vbnet/README.md (100%) rename {16 Bug => 16_Bug}/README.md (100%) rename {16 Bug => 16_Bug}/bug.bas (100%) rename {16 Bug => 16_Bug}/csharp/README.md (100%) rename {16 Bug => 16_Bug}/java/README.md (100%) rename {16 Bug => 16_Bug}/java/src/Bug.java (100%) rename {16 Bug => 16_Bug}/java/src/BugGame.java (100%) rename {16 Bug => 16_Bug}/java/src/ComputerBug.java (100%) rename {16 Bug => 16_Bug}/java/src/Insect.java (100%) rename {16 Bug => 16_Bug}/java/src/PlayerBug.java (100%) rename {16 Bug => 16_Bug}/javascript/README.md (100%) rename {16 Bug => 16_Bug}/javascript/bug.html (100%) rename {16 Bug => 16_Bug}/javascript/bug.js (100%) rename {16 Bug => 16_Bug}/pascal/README.md (100%) rename {16 Bug => 16_Bug}/perl/README.md (100%) rename {16 Bug => 16_Bug}/python/README.md (100%) rename {16 Bug => 16_Bug}/ruby/README.md (100%) rename {16 Bug => 16_Bug}/vbnet/README.md (100%) rename {17 Bullfight => 17_Bullfight}/README.md (100%) rename {17 Bullfight => 17_Bullfight}/bullfight.bas (100%) rename {17 Bullfight => 17_Bullfight}/csharp/Bullfight.sln (100%) rename {17 Bullfight => 17_Bullfight}/csharp/Game.csproj (100%) rename {17 Bullfight => 17_Bullfight}/csharp/README.md (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Action.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/ActionResult.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/BullFight.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Controller.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Events/BullCharging.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Events/Event.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Events/MatchCompleted.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Events/MatchStarted.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Events/PlayerGored.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Events/PlayerSurvived.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Mediator.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Program.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Quality.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/Reward.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/RiskLevel.cs (100%) rename {17 Bullfight => 17_Bullfight}/csharp/src/View.cs (100%) rename {17 Bullfight => 17_Bullfight}/java/README.md (100%) rename {17 Bullfight => 17_Bullfight}/javascript/README.md (100%) rename {17 Bullfight => 17_Bullfight}/javascript/bullfight.html (100%) rename {17 Bullfight => 17_Bullfight}/javascript/bullfight.js (100%) rename {17 Bullfight => 17_Bullfight}/pascal/README.md (100%) rename {17 Bullfight => 17_Bullfight}/perl/README.md (100%) rename {17 Bullfight => 17_Bullfight}/python/README.md (100%) rename {17 Bullfight => 17_Bullfight}/ruby/README.md (100%) rename {17 Bullfight => 17_Bullfight}/vbnet/README.md (100%) rename {18 Bullseye => 18_Bullseye}/README.md (100%) rename {18 Bullseye => 18_Bullseye}/bullseye.bas (100%) rename {18 Bullseye => 18_Bullseye}/csharp/README.md (100%) rename {18 Bullseye => 18_Bullseye}/java/README.md (100%) rename {18 Bullseye => 18_Bullseye}/java/src/Bullseye.java (100%) rename {18 Bullseye => 18_Bullseye}/java/src/BullseyeGame.java (100%) rename {18 Bullseye => 18_Bullseye}/java/src/Player.java (100%) rename {18 Bullseye => 18_Bullseye}/java/src/Shot.java (100%) rename {18 Bullseye => 18_Bullseye}/javascript/README.md (100%) rename {18 Bullseye => 18_Bullseye}/javascript/bullseye.html (100%) rename {18 Bullseye => 18_Bullseye}/javascript/bullseye.js (100%) rename {18 Bullseye => 18_Bullseye}/pascal/README.md (100%) rename {18 Bullseye => 18_Bullseye}/perl/README.md (100%) rename {18 Bullseye => 18_Bullseye}/perl/bullseye.pl (100%) rename {18 Bullseye => 18_Bullseye}/python/README.md (100%) rename {18 Bullseye => 18_Bullseye}/ruby/README.md (100%) rename {18 Bullseye => 18_Bullseye}/vbnet/README.md (100%) rename {19 Bunny => 19_Bunny}/README.md (100%) rename {19 Bunny => 19_Bunny}/bunny.bas (100%) rename {19 Bunny => 19_Bunny}/csharp/README.md (100%) rename {19 Bunny => 19_Bunny}/java/README.md (100%) rename {19 Bunny => 19_Bunny}/java/src/Bunny.java (100%) rename {19 Bunny => 19_Bunny}/javascript/README.md (100%) rename {19 Bunny => 19_Bunny}/javascript/bunny.html (100%) rename {19 Bunny => 19_Bunny}/javascript/bunny.js (100%) rename {19 Bunny => 19_Bunny}/pascal/README.md (100%) rename {19 Bunny => 19_Bunny}/perl/README.md (100%) rename {19 Bunny => 19_Bunny}/perl/bunny.pl (100%) rename {19 Bunny => 19_Bunny}/python/README.md (100%) rename {19 Bunny => 19_Bunny}/python/bunny.py (100%) rename {19 Bunny => 19_Bunny}/ruby/README.md (100%) rename {19 Bunny => 19_Bunny}/ruby/bunny-faithful.rb (100%) rename {19 Bunny => 19_Bunny}/ruby/bunny-modern.rb (100%) rename {19 Bunny => 19_Bunny}/vbnet/README.md (100%) rename {20 Buzzword => 20_Buzzword}/README.md (100%) rename {20 Buzzword => 20_Buzzword}/buzzword.bas (100%) rename {20 Buzzword => 20_Buzzword}/csharp/README.md (100%) rename {20 Buzzword => 20_Buzzword}/java/README.md (100%) rename {20 Buzzword => 20_Buzzword}/java/src/Buzzword.java (100%) rename {20 Buzzword => 20_Buzzword}/javascript/README.md (100%) rename {20 Buzzword => 20_Buzzword}/javascript/buzzword.html (100%) rename {20 Buzzword => 20_Buzzword}/javascript/buzzword.js (100%) rename {20 Buzzword => 20_Buzzword}/pascal/README.md (100%) rename {20 Buzzword => 20_Buzzword}/perl/README.md (100%) rename {20 Buzzword => 20_Buzzword}/perl/buzzword.pl (100%) rename {20 Buzzword => 20_Buzzword}/python/README.md (100%) rename {20 Buzzword => 20_Buzzword}/python/buzzword.py (100%) rename {20 Buzzword => 20_Buzzword}/ruby/README.md (100%) rename {20 Buzzword => 20_Buzzword}/ruby/buzzword.rb (100%) rename {20 Buzzword => 20_Buzzword}/vbnet/README.md (100%) rename {21 Calendar => 21_Calendar}/README.md (100%) rename {21 Calendar => 21_Calendar}/calendar.bas (100%) rename {21 Calendar => 21_Calendar}/csharp/README.md (100%) rename {21 Calendar => 21_Calendar}/java/Calendar.java (100%) rename {21 Calendar => 21_Calendar}/java/README.md (100%) rename {21 Calendar => 21_Calendar}/javascript/README.md (100%) rename {21 Calendar => 21_Calendar}/javascript/calendar.html (100%) rename {21 Calendar => 21_Calendar}/javascript/calendar.js (100%) rename {21 Calendar => 21_Calendar}/pascal/README.md (100%) rename {21 Calendar => 21_Calendar}/perl/README.md (100%) rename {21 Calendar => 21_Calendar}/python/README.md (100%) rename {21 Calendar => 21_Calendar}/ruby/README.md (100%) rename {21 Calendar => 21_Calendar}/vbnet/README.md (100%) rename {22 Change => 22_Change}/README.md (100%) rename {22 Change => 22_Change}/change.bas (100%) rename {22 Change => 22_Change}/csharp/README.md (100%) rename {22 Change => 22_Change}/java/README.md (100%) rename {22 Change => 22_Change}/java/src/Change.java (100%) rename {22 Change => 22_Change}/java/src/ChangeGame.java (100%) rename {22 Change => 22_Change}/javascript/README.md (100%) rename {22 Change => 22_Change}/javascript/change.html (100%) rename {22 Change => 22_Change}/javascript/change.js (100%) rename {22 Change => 22_Change}/pascal/README.md (100%) rename {22 Change => 22_Change}/perl/README.md (100%) rename {22 Change => 22_Change}/python/README.md (100%) rename {22 Change => 22_Change}/python/change.py (100%) rename {22 Change => 22_Change}/ruby/README.md (100%) rename {22 Change => 22_Change}/vbnet/README.md (100%) rename {23 Checkers => 23_Checkers}/README.md (100%) rename {23 Checkers => 23_Checkers}/checkers.annotated.bas (100%) rename {23 Checkers => 23_Checkers}/checkers.bas (100%) rename {23 Checkers => 23_Checkers}/csharp/README.md (100%) rename {23 Checkers => 23_Checkers}/java/README.md (100%) rename {23 Checkers => 23_Checkers}/javascript/README.md (100%) rename {23 Checkers => 23_Checkers}/javascript/checkers.html (100%) rename {23 Checkers => 23_Checkers}/javascript/checkers.js (100%) rename {23 Checkers => 23_Checkers}/pascal/README.md (100%) rename {23 Checkers => 23_Checkers}/perl/README.md (100%) rename {23 Checkers => 23_Checkers}/python/README.md (100%) rename {23 Checkers => 23_Checkers}/python/checkers.py (100%) rename {23 Checkers => 23_Checkers}/ruby/README.md (100%) rename {23 Checkers => 23_Checkers}/ruby/checkers.rb (100%) rename {23 Checkers => 23_Checkers}/vbnet/README.md (100%) rename {24 Chemist => 24_Chemist}/README.md (100%) rename {24 Chemist => 24_Chemist}/chemist.bas (100%) rename {24 Chemist => 24_Chemist}/csharp/Chemist/Chemist.sln (100%) rename {24 Chemist => 24_Chemist}/csharp/Chemist/Chemist/Chemist.csproj (100%) rename {24 Chemist => 24_Chemist}/csharp/Chemist/Chemist/Program.cs (100%) rename {24 Chemist => 24_Chemist}/csharp/README.md (100%) rename {24 Chemist => 24_Chemist}/java/README.md (100%) rename {24 Chemist => 24_Chemist}/java/src/Chemist.java (100%) rename {24 Chemist => 24_Chemist}/java/src/ChemistGame.java (100%) rename {24 Chemist => 24_Chemist}/javascript/README.md (100%) rename {24 Chemist => 24_Chemist}/javascript/chemist.html (100%) rename {24 Chemist => 24_Chemist}/javascript/chemist.js (100%) rename {24 Chemist => 24_Chemist}/pascal/README.md (100%) rename {24 Chemist => 24_Chemist}/perl/README.md (100%) rename {24 Chemist => 24_Chemist}/perlchemist.pl (100%) rename {24 Chemist => 24_Chemist}/python/README.md (100%) rename {24 Chemist => 24_Chemist}/python/chemist.py (100%) rename {24 Chemist => 24_Chemist}/ruby/README.md (100%) rename {24 Chemist => 24_Chemist}/vbnet/README.md (100%) rename {25 Chief => 25_Chief}/README.md (100%) rename {25 Chief => 25_Chief}/chief.bas (100%) rename {25 Chief => 25_Chief}/csharp/README.md (100%) rename {25 Chief => 25_Chief}/java/README.md (100%) rename {25 Chief => 25_Chief}/java/src/Chief.java (100%) rename {25 Chief => 25_Chief}/java/src/ChiefGame.java (100%) rename {25 Chief => 25_Chief}/javascript/README.md (100%) rename {25 Chief => 25_Chief}/javascript/chief.html (100%) rename {25 Chief => 25_Chief}/javascript/chief.js (100%) rename {25 Chief => 25_Chief}/pascal/README.md (100%) rename {25 Chief => 25_Chief}/perl/README.md (100%) rename {25 Chief => 25_Chief}/python/README.md (100%) rename {25 Chief => 25_Chief}/ruby/README.md (100%) rename {25 Chief => 25_Chief}/vbnet/README.md (100%) rename {26 Chomp => 26_Chomp}/README.md (100%) rename {26 Chomp => 26_Chomp}/chomp.bas (100%) rename {26 Chomp => 26_Chomp}/csharp/README.md (100%) rename {26 Chomp => 26_Chomp}/java/Chomp.java (100%) rename {26 Chomp => 26_Chomp}/java/README.md (100%) rename {26 Chomp => 26_Chomp}/javascript/README.md (100%) rename {26 Chomp => 26_Chomp}/javascript/chomp.html (100%) rename {26 Chomp => 26_Chomp}/javascript/chomp.js (100%) rename {26 Chomp => 26_Chomp}/pascal/README.md (100%) rename {26 Chomp => 26_Chomp}/perl/README.md (100%) rename {26 Chomp => 26_Chomp}/python/README.md (100%) rename {26 Chomp => 26_Chomp}/python/chomp.py (100%) rename {26 Chomp => 26_Chomp}/ruby/README.md (100%) rename {26 Chomp => 26_Chomp}/vbnet/README.md (100%) rename {27 Civil War => 27_Civil_War}/README.md (100%) rename {27 Civil War => 27_Civil_War}/civilwar.bas (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar.sln (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/Army.cs (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/Battle.cs (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/CivilWar.csproj (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/ConsoleUtils.cs (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/GameOptions.cs (100%) rename {27 Civil War => 27_Civil_War}/csharp/CivilWar/CivilWar/Program.cs (100%) rename {27 Civil War => 27_Civil_War}/csharp/README.md (100%) rename {27 Civil War => 27_Civil_War}/java/README.md (100%) rename {27 Civil War => 27_Civil_War}/javascript/README.md (100%) rename {27 Civil War => 27_Civil_War}/javascript/civilwar.html (100%) rename {27 Civil War => 27_Civil_War}/javascript/civilwar.js (100%) rename {27 Civil War => 27_Civil_War}/pascal/README.md (100%) rename {27 Civil War => 27_Civil_War}/perl/README.md (100%) rename {27 Civil War => 27_Civil_War}/python/README.md (100%) rename {27 Civil War => 27_Civil_War}/ruby/README.md (100%) rename {27 Civil War => 27_Civil_War}/vbnet/README.md (100%) rename {28 Combat => 28_Combat}/README.md (100%) rename {28 Combat => 28_Combat}/combat.bas (100%) rename {28 Combat => 28_Combat}/csharp/Combat.sln (100%) rename {28 Combat => 28_Combat}/csharp/Game.csproj (100%) rename {28 Combat => 28_Combat}/csharp/README.md (100%) rename {28 Combat => 28_Combat}/csharp/src/ArmedForces.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/Ceasefire.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/Controller.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/FinalCampaign.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/InitialCampaign.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/MilitaryBranch.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/Program.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/View.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/WarResult.cs (100%) rename {28 Combat => 28_Combat}/csharp/src/WarState.cs (100%) rename {28 Combat => 28_Combat}/java/Combat.java (100%) rename {28 Combat => 28_Combat}/java/README.md (100%) rename {28 Combat => 28_Combat}/javascript/README.md (100%) rename {28 Combat => 28_Combat}/javascript/combat.html (100%) rename {28 Combat => 28_Combat}/javascript/combat.js (100%) rename {28 Combat => 28_Combat}/pascal/README.md (100%) rename {28 Combat => 28_Combat}/perl/README.md (100%) rename {28 Combat => 28_Combat}/python/README.md (100%) rename {28 Combat => 28_Combat}/ruby/README.md (100%) rename {28 Combat => 28_Combat}/vbnet/README.md (100%) rename {29 Craps => 29_Craps}/README.md (100%) rename {29 Craps => 29_Craps}/craps.bas (100%) rename {29 Craps => 29_Craps}/csharp/Craps/.gitignore (100%) rename {29 Craps => 29_Craps}/csharp/Craps/Craps.sln (100%) rename {29 Craps => 29_Craps}/csharp/Craps/Craps/Craps.csproj (100%) rename {29 Craps => 29_Craps}/csharp/Craps/Craps/CrapsGame.cs (100%) rename {29 Craps => 29_Craps}/csharp/Craps/Craps/Dice.cs (100%) rename {29 Craps => 29_Craps}/csharp/Craps/Craps/Program.cs (100%) rename {29 Craps => 29_Craps}/csharp/Craps/Craps/UserInterface.cs (100%) rename {29 Craps => 29_Craps}/csharp/Craps/CrapsTester/CrapsTester.csproj (100%) rename {29 Craps => 29_Craps}/csharp/Craps/CrapsTester/CrapsTests.cs (100%) rename {29 Craps => 29_Craps}/csharp/README.md (100%) rename {29 Craps => 29_Craps}/java/README.md (100%) rename {29 Craps => 29_Craps}/javascript/README.md (100%) rename {29 Craps => 29_Craps}/javascript/craps.html (100%) rename {29 Craps => 29_Craps}/javascript/craps.js (100%) rename {29 Craps => 29_Craps}/pascal/README.md (100%) rename {29 Craps => 29_Craps}/perl/README.md (100%) rename {29 Craps => 29_Craps}/python/README.md (100%) rename {29 Craps => 29_Craps}/ruby/README.md (100%) rename {29 Craps => 29_Craps}/vbnet/README.md (100%) rename {30 Cube => 30_Cube}/README.md (100%) rename {30 Cube => 30_Cube}/csharp/README.md (100%) rename {30 Cube => 30_Cube}/cube.bas (100%) rename {30 Cube => 30_Cube}/java/README.md (100%) rename {30 Cube => 30_Cube}/javascript/README.md (100%) rename {30 Cube => 30_Cube}/javascript/cube.html (100%) rename {30 Cube => 30_Cube}/javascript/cube.js (100%) rename {30 Cube => 30_Cube}/pascal/README.md (100%) rename {30 Cube => 30_Cube}/perl/README.md (100%) rename {30 Cube => 30_Cube}/python/README.md (100%) rename {30 Cube => 30_Cube}/python/cube.py (100%) rename {30 Cube => 30_Cube}/ruby/README.md (100%) rename {30 Cube => 30_Cube}/vbnet/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/csharp/DepthCharge.sln (100%) rename {31 Depth Charge => 31_Depth_Charge}/csharp/Game.csproj (100%) rename {31 Depth Charge => 31_Depth_Charge}/csharp/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/csharp/src/Controller.cs (100%) rename {31 Depth Charge => 31_Depth_Charge}/csharp/src/Program.cs (100%) rename {31 Depth Charge => 31_Depth_Charge}/csharp/src/View.cs (100%) rename {31 Depth Charge => 31_Depth_Charge}/depthcharge.bas (100%) rename {31 Depth Charge => 31_Depth_Charge}/java/DepthCharge.java (100%) rename {31 Depth Charge => 31_Depth_Charge}/java/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/javascript/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/javascript/depthcharge.html (100%) rename {31 Depth Charge => 31_Depth_Charge}/javascript/depthcharge.js (100%) rename {31 Depth Charge => 31_Depth_Charge}/pascal/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/perl/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/perl/depth-charge.pl (100%) rename {31 Depth Charge => 31_Depth_Charge}/python/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/python/depth_charge.py (100%) rename {31 Depth Charge => 31_Depth_Charge}/ruby/README.md (100%) rename {31 Depth Charge => 31_Depth_Charge}/vbnet/README.md (100%) rename {32 Diamond => 32_Diamond}/README.md (100%) rename {32 Diamond => 32_Diamond}/csharp/README.md (100%) rename {32 Diamond => 32_Diamond}/diamond.bas (100%) rename {32 Diamond => 32_Diamond}/java/Diamond.java (100%) rename {32 Diamond => 32_Diamond}/java/README.md (100%) rename {32 Diamond => 32_Diamond}/javascript/README.md (100%) rename {32 Diamond => 32_Diamond}/javascript/diamond.html (100%) rename {32 Diamond => 32_Diamond}/javascript/diamond.js (100%) rename {32 Diamond => 32_Diamond}/pascal/README.md (100%) rename {32 Diamond => 32_Diamond}/perl/README.md (100%) rename {32 Diamond => 32_Diamond}/perl/diamond.pl (100%) rename {32 Diamond => 32_Diamond}/python/README.md (100%) rename {32 Diamond => 32_Diamond}/python/diamond.py (100%) rename {32 Diamond => 32_Diamond}/ruby/README.md (100%) rename {32 Diamond => 32_Diamond}/ruby/diamond.rb (100%) rename {32 Diamond => 32_Diamond}/vbnet/README.md (100%) rename {33 Dice => 33_Dice}/README.md (100%) rename {33 Dice => 33_Dice}/csharp/Dice.csproj (100%) rename {33 Dice => 33_Dice}/csharp/Game.cs (100%) rename {33 Dice => 33_Dice}/csharp/Program.cs (100%) rename {33 Dice => 33_Dice}/csharp/README.md (100%) rename {33 Dice => 33_Dice}/csharp/RollGenerator.cs (100%) rename {33 Dice => 33_Dice}/dice.bas (100%) rename {33 Dice => 33_Dice}/java/README.md (100%) rename {33 Dice => 33_Dice}/java/src/Dice.java (100%) rename {33 Dice => 33_Dice}/java/src/DiceGame.java (100%) rename {33 Dice => 33_Dice}/javascript/README.md (100%) rename {33 Dice => 33_Dice}/javascript/dice.html (100%) rename {33 Dice => 33_Dice}/javascript/dice.js (100%) rename {33 Dice => 33_Dice}/pascal/README.md (100%) rename {33 Dice => 33_Dice}/perl/README.md (100%) rename {33 Dice => 33_Dice}/perl/dice.pl (100%) rename {33 Dice => 33_Dice}/python/README.md (100%) rename {33 Dice => 33_Dice}/python/dice.py (100%) rename {33 Dice => 33_Dice}/ruby/README.md (100%) rename {33 Dice => 33_Dice}/ruby/dice.rb (100%) rename {33 Dice => 33_Dice}/vbnet/README.md (100%) rename {34 Digits => 34_Digits}/README.md (100%) rename {34 Digits => 34_Digits}/csharp/README.md (100%) rename {34 Digits => 34_Digits}/digits.bas (100%) rename {34 Digits => 34_Digits}/java/Digits.java (100%) rename {34 Digits => 34_Digits}/java/README.md (100%) rename {34 Digits => 34_Digits}/javascript/README.md (100%) rename {34 Digits => 34_Digits}/javascript/digits.html (100%) rename {34 Digits => 34_Digits}/javascript/digits.js (100%) rename {34 Digits => 34_Digits}/pascal/README.md (100%) rename {34 Digits => 34_Digits}/perl/README.md (100%) rename {34 Digits => 34_Digits}/python/README.md (100%) rename {34 Digits => 34_Digits}/ruby/README.md (100%) rename {34 Digits => 34_Digits}/vbnet/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/csharp/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/evenwins.bas (100%) rename {35 Even Wins => 35_Even_Wins}/gameofevenwins.bas (100%) rename {35 Even Wins => 35_Even_Wins}/java/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/javascript/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/javascript/evenwins.html (100%) rename {35 Even Wins => 35_Even_Wins}/javascript/evenwins.js (100%) rename {35 Even Wins => 35_Even_Wins}/javascript/gameofevenwins.html (100%) rename {35 Even Wins => 35_Even_Wins}/javascript/gameofevenwins.js (100%) rename {35 Even Wins => 35_Even_Wins}/pascal/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/perl/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/python/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/ruby/README.md (100%) rename {35 Even Wins => 35_Even_Wins}/vbnet/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/csharp/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/flipflop.bas (100%) rename {36 Flip Flop => 36_Flip_Flop}/java/FlipFlop.java (100%) rename {36 Flip Flop => 36_Flip_Flop}/java/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/javascript/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/javascript/flipflop.html (100%) rename {36 Flip Flop => 36_Flip_Flop}/javascript/flipflop.js (100%) rename {36 Flip Flop => 36_Flip_Flop}/pascal/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/perl/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/python/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/ruby/README.md (100%) rename {36 Flip Flop => 36_Flip_Flop}/vbnet/README.md (100%) rename {37 Football => 37_Football}/README.md (100%) rename {37 Football => 37_Football}/csharp/README.md (100%) rename {37 Football => 37_Football}/football.bas (100%) rename {37 Football => 37_Football}/ftball.bas (100%) rename {37 Football => 37_Football}/java/README.md (100%) rename {37 Football => 37_Football}/javascript/README.md (100%) rename {37 Football => 37_Football}/javascript/football.html (100%) rename {37 Football => 37_Football}/javascript/football.js (100%) rename {37 Football => 37_Football}/javascript/ftball.html (100%) rename {37 Football => 37_Football}/javascript/ftball.js (100%) rename {37 Football => 37_Football}/pascal/README.md (100%) rename {37 Football => 37_Football}/perl/README.md (100%) rename {37 Football => 37_Football}/python/README.md (100%) rename {37 Football => 37_Football}/ruby/README.md (100%) rename {37 Football => 37_Football}/vbnet/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/c/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/c/furtrader.c (100%) rename {38 Fur Trader => 38_Fur_Trader}/csharp/FurTrader.csproj (100%) rename {38 Fur Trader => 38_Fur_Trader}/csharp/FurTrader.sln (100%) rename {38 Fur Trader => 38_Fur_Trader}/csharp/Game.cs (100%) rename {38 Fur Trader => 38_Fur_Trader}/csharp/GameState.cs (100%) rename {38 Fur Trader => 38_Fur_Trader}/csharp/Program.cs (100%) rename {38 Fur Trader => 38_Fur_Trader}/csharp/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/furtrader.bas (100%) rename {38 Fur Trader => 38_Fur_Trader}/java/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/java/src/FurTrader.java (100%) rename {38 Fur Trader => 38_Fur_Trader}/java/src/FurTraderGame.java (100%) rename {38 Fur Trader => 38_Fur_Trader}/java/src/Pelt.java (100%) rename {38 Fur Trader => 38_Fur_Trader}/javascript/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/javascript/furtrader.html (100%) rename {38 Fur Trader => 38_Fur_Trader}/javascript/furtrader.js (100%) rename {38 Fur Trader => 38_Fur_Trader}/pascal/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/perl/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/python/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/python/furtrader.py (100%) rename {38 Fur Trader => 38_Fur_Trader}/ruby/README.md (100%) rename {38 Fur Trader => 38_Fur_Trader}/vbnet/README.md (100%) rename {39 Golf => 39_Golf}/README.md (100%) rename {39 Golf => 39_Golf}/csharp/Program.cs (100%) rename {39 Golf => 39_Golf}/csharp/README.md (100%) rename {39 Golf => 39_Golf}/golf.bas (100%) rename {39 Golf => 39_Golf}/java/README.md (100%) rename {39 Golf => 39_Golf}/javascript/README.md (100%) rename {39 Golf => 39_Golf}/javascript/golf.html (100%) rename {39 Golf => 39_Golf}/javascript/golf.js (100%) rename {39 Golf => 39_Golf}/pascal/README.md (100%) rename {39 Golf => 39_Golf}/perl/README.md (100%) rename {39 Golf => 39_Golf}/python/README.md (100%) rename {39 Golf => 39_Golf}/ruby/README.md (100%) rename {39 Golf => 39_Golf}/vbnet/README.md (100%) rename {40 Gomoko => 40_Gomoko}/README.md (100%) rename {40 Gomoko => 40_Gomoko}/csharp/README.md (100%) rename {40 Gomoko => 40_Gomoko}/gomoko.bas (100%) rename {40 Gomoko => 40_Gomoko}/java/Gomoko.java (100%) rename {40 Gomoko => 40_Gomoko}/java/README.md (100%) rename {40 Gomoko => 40_Gomoko}/javascript/README.md (100%) rename {40 Gomoko => 40_Gomoko}/javascript/gomoko.html (100%) rename {40 Gomoko => 40_Gomoko}/javascript/gomoko.js (100%) rename {40 Gomoko => 40_Gomoko}/pascal/README.md (100%) rename {40 Gomoko => 40_Gomoko}/perl/README.md (100%) rename {40 Gomoko => 40_Gomoko}/python/README.md (100%) rename {40 Gomoko => 40_Gomoko}/ruby/README.md (100%) rename {40 Gomoko => 40_Gomoko}/vbnet/README.md (100%) rename {41 Guess => 41_Guess}/README.md (100%) rename {41 Guess => 41_Guess}/csharp/README.md (100%) rename {41 Guess => 41_Guess}/guess.bas (100%) rename {41 Guess => 41_Guess}/java/README.md (100%) rename {41 Guess => 41_Guess}/java/src/Guess.java (100%) rename {41 Guess => 41_Guess}/java/src/GuessGame.java (100%) rename {41 Guess => 41_Guess}/javascript/README.md (100%) rename {41 Guess => 41_Guess}/javascript/guess.html (100%) rename {41 Guess => 41_Guess}/javascript/guess.js (100%) rename {41 Guess => 41_Guess}/pascal/README.md (100%) rename {41 Guess => 41_Guess}/perl/README.md (100%) rename {41 Guess => 41_Guess}/perl/guess.pl (100%) rename {41 Guess => 41_Guess}/python/README.md (100%) rename {41 Guess => 41_Guess}/python/guess.py (100%) rename {41 Guess => 41_Guess}/ruby/README.md (100%) rename {41 Guess => 41_Guess}/vbnet/README.md (100%) rename {42 Gunner => 42_Gunner}/README.md (100%) rename {42 Gunner => 42_Gunner}/csharp/README.md (100%) rename {42 Gunner => 42_Gunner}/gunner.bas (100%) rename {42 Gunner => 42_Gunner}/java/Gunner.java (100%) rename {42 Gunner => 42_Gunner}/java/README.md (100%) rename {42 Gunner => 42_Gunner}/javascript/README.md (100%) rename {42 Gunner => 42_Gunner}/javascript/gunner.html (100%) rename {42 Gunner => 42_Gunner}/javascript/gunner.js (100%) rename {42 Gunner => 42_Gunner}/pascal/README.md (100%) rename {42 Gunner => 42_Gunner}/perl/README.md (100%) rename {42 Gunner => 42_Gunner}/python/README.md (100%) rename {42 Gunner => 42_Gunner}/python/gunner.py (100%) rename {42 Gunner => 42_Gunner}/ruby/README.md (100%) rename {42 Gunner => 42_Gunner}/vbnet/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/Game.csproj (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/Hammurabi.sln (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/ActionResult.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/Controller.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/GameResult.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/GameState.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/GreatOffence.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/PerformanceRating.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/Program.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/Rules.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/csharp/src/View.cs (100%) rename {43 Hammurabi => 43_Hammurabi}/hammurabi.bas (100%) rename {43 Hammurabi => 43_Hammurabi}/java/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/java/src/Hamurabi.java (100%) rename {43 Hammurabi => 43_Hammurabi}/java/src/HamurabiGame.java (100%) rename {43 Hammurabi => 43_Hammurabi}/javascript/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/javascript/hammurabi.html (100%) rename {43 Hammurabi => 43_Hammurabi}/javascript/hammurabi.js (100%) rename {43 Hammurabi => 43_Hammurabi}/pascal/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/perl/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/python/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/python/hamurabi.py (100%) rename {43 Hammurabi => 43_Hammurabi}/ruby/README.md (100%) rename {43 Hammurabi => 43_Hammurabi}/vbnet/README.md (100%) rename {44 Hangman => 44_Hangman}/README.md (100%) rename {44 Hangman => 44_Hangman}/csharp/Hangman/Graphic.cs (100%) rename {44 Hangman => 44_Hangman}/csharp/Hangman/Hangman.csproj (100%) rename {44 Hangman => 44_Hangman}/csharp/Hangman/Hangman.sln (100%) rename {44 Hangman => 44_Hangman}/csharp/Hangman/Program.cs (100%) rename {44 Hangman => 44_Hangman}/csharp/README.md (100%) rename {44 Hangman => 44_Hangman}/hangman.bas (100%) rename {44 Hangman => 44_Hangman}/java/Hangman.java (100%) rename {44 Hangman => 44_Hangman}/java/README.md (100%) rename {44 Hangman => 44_Hangman}/javascript/README.md (100%) rename {44 Hangman => 44_Hangman}/javascript/hangman.html (100%) rename {44 Hangman => 44_Hangman}/javascript/hangman.js (100%) rename {44 Hangman => 44_Hangman}/pascal/README.md (100%) rename {44 Hangman => 44_Hangman}/perl/README.md (100%) rename {44 Hangman => 44_Hangman}/python/README.md (100%) rename {44 Hangman => 44_Hangman}/python/hangman.py (100%) rename {44 Hangman => 44_Hangman}/ruby/README.md (100%) rename {44 Hangman => 44_Hangman}/vbnet/README.md (100%) rename {45 Hello => 45_Hello}/README.md (100%) rename {45 Hello => 45_Hello}/csharp/README.md (100%) rename {45 Hello => 45_Hello}/hello.bas (100%) rename {45 Hello => 45_Hello}/java/Hello.java (100%) rename {45 Hello => 45_Hello}/java/README.md (100%) rename {45 Hello => 45_Hello}/javascript/README.md (100%) rename {45 Hello => 45_Hello}/javascript/hello.html (100%) rename {45 Hello => 45_Hello}/javascript/hello.js (100%) rename {45 Hello => 45_Hello}/pascal/README.md (100%) rename {45 Hello => 45_Hello}/perl/README.md (100%) rename {45 Hello => 45_Hello}/python/README.md (100%) rename {45 Hello => 45_Hello}/python/hello.py (100%) rename {45 Hello => 45_Hello}/ruby/README.md (100%) rename {45 Hello => 45_Hello}/vbnet/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn.sln (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Board.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Cell.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Computer.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Game.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/GameSeries.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Hexapawn.csproj (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Human.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/IPlayer.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Input.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Move.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Pawn.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/Hexapawn/Program.cs (100%) rename {46 Hexapawn => 46_Hexapawn}/csharp/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/hexapawn.bas (100%) rename {46 Hexapawn => 46_Hexapawn}/java/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/javascript/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/javascript/hexapawn.html (100%) rename {46 Hexapawn => 46_Hexapawn}/javascript/hexapawn.js (100%) rename {46 Hexapawn => 46_Hexapawn}/pascal/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/perl/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/python/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/python/hexapawn.py (100%) rename {46 Hexapawn => 46_Hexapawn}/ruby/README.md (100%) rename {46 Hexapawn => 46_Hexapawn}/vbnet/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/csharp/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/csharp/hi-lo.cs (100%) rename {47 Hi-Lo => 47_Hi-Lo}/csharp/hi-lo.csproj (100%) rename {47 Hi-Lo => 47_Hi-Lo}/hi-lo.bas (100%) rename {47 Hi-Lo => 47_Hi-Lo}/java/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/java/src/HiLo.java (100%) rename {47 Hi-Lo => 47_Hi-Lo}/java/src/HiLoGame.java (100%) rename {47 Hi-Lo => 47_Hi-Lo}/javascript/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/javascript/hi-lo.html (100%) rename {47 Hi-Lo => 47_Hi-Lo}/javascript/hi-lo.js (100%) rename {47 Hi-Lo => 47_Hi-Lo}/pascal/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/perl/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/perl/hi-lo.pl (100%) rename {47 Hi-Lo => 47_Hi-Lo}/python/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/python/hilo.py (100%) rename {47 Hi-Lo => 47_Hi-Lo}/ruby/README.md (100%) rename {47 Hi-Lo => 47_Hi-Lo}/vbnet/README.md (100%) rename {48 High IQ => 48_High_IQ}/README.md (100%) rename {48 High IQ => 48_High_IQ}/csharp/README.md (100%) rename {48 High IQ => 48_High_IQ}/highiq.bas (100%) rename {48 High IQ => 48_High_IQ}/java/README.md (100%) rename {48 High IQ => 48_High_IQ}/javascript/README.md (100%) rename {48 High IQ => 48_High_IQ}/javascript/highiq.html (100%) rename {48 High IQ => 48_High_IQ}/javascript/highiq.js (100%) rename {48 High IQ => 48_High_IQ}/pascal/README.md (100%) rename {48 High IQ => 48_High_IQ}/perl/README.md (100%) rename {48 High IQ => 48_High_IQ}/python/README.md (100%) rename {48 High IQ => 48_High_IQ}/ruby/README.md (100%) rename {48 High IQ => 48_High_IQ}/vbnet/README.md (100%) rename {49 Hockey => 49_Hockey}/README.md (100%) rename {49 Hockey => 49_Hockey}/csharp/README.md (100%) rename {49 Hockey => 49_Hockey}/hockey.bas (100%) rename {49 Hockey => 49_Hockey}/java/README.md (100%) rename {49 Hockey => 49_Hockey}/javascript/README.md (100%) rename {49 Hockey => 49_Hockey}/javascript/hockey.html (100%) rename {49 Hockey => 49_Hockey}/javascript/hockey.js (100%) rename {49 Hockey => 49_Hockey}/pascal/README.md (100%) rename {49 Hockey => 49_Hockey}/perl/README.md (100%) rename {49 Hockey => 49_Hockey}/python/README.md (100%) rename {49 Hockey => 49_Hockey}/ruby/README.md (100%) rename {49 Hockey => 49_Hockey}/vbnet/README.md (100%) rename {50 Horserace => 50_Horserace}/README.md (100%) rename {50 Horserace => 50_Horserace}/csharp/README.md (100%) rename {50 Horserace => 50_Horserace}/horserace.bas (100%) rename {50 Horserace => 50_Horserace}/java/README.md (100%) rename {50 Horserace => 50_Horserace}/javascript/README.md (100%) rename {50 Horserace => 50_Horserace}/javascript/horserace.html (100%) rename {50 Horserace => 50_Horserace}/javascript/horserace.js (100%) rename {50 Horserace => 50_Horserace}/pascal/README.md (100%) rename {50 Horserace => 50_Horserace}/perl/README.md (100%) rename {50 Horserace => 50_Horserace}/python/README.md (100%) rename {50 Horserace => 50_Horserace}/ruby/README.md (100%) rename {50 Horserace => 50_Horserace}/vbnet/README.md (100%) rename {51 Hurkle => 51_Hurkle}/README.md (100%) rename {51 Hurkle => 51_Hurkle}/csharp/.gitignore (100%) rename {51 Hurkle => 51_Hurkle}/csharp/README.md (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/CardinalDirection.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/ConsoleHurkleView.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/FailedGuessViewModel.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/GamePoint.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/GuessViewModel.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/HurkleGame.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/IHurkleView.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/LossViewModel.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/Program.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/VictoryViewModel.cs (100%) rename {51 Hurkle => 51_Hurkle}/csharp/src/hurkle/hurkle.csproj (100%) rename {51 Hurkle => 51_Hurkle}/hurkle.bas (100%) rename {51 Hurkle => 51_Hurkle}/java/README.md (100%) rename {51 Hurkle => 51_Hurkle}/java/src/Hurkle.java (100%) rename {51 Hurkle => 51_Hurkle}/java/src/HurkleGame.java (100%) rename {51 Hurkle => 51_Hurkle}/javascript/README.md (100%) rename {51 Hurkle => 51_Hurkle}/javascript/hurkle.html (100%) rename {51 Hurkle => 51_Hurkle}/javascript/hurkle.js (100%) rename {51 Hurkle => 51_Hurkle}/pascal/README.md (100%) rename {51 Hurkle => 51_Hurkle}/perl/README.md (100%) rename {51 Hurkle => 51_Hurkle}/python/README.md (100%) rename {51 Hurkle => 51_Hurkle}/python/hurkle.py (100%) rename {51 Hurkle => 51_Hurkle}/ruby/README.md (100%) rename {51 Hurkle => 51_Hurkle}/ruby/hurkle.rb (100%) rename {51 Hurkle => 51_Hurkle}/vbnet/README.md (100%) rename {52 Kinema => 52_Kinema}/README.md (100%) rename {52 Kinema => 52_Kinema}/csharp/README.md (100%) rename {52 Kinema => 52_Kinema}/java/README.md (100%) rename {52 Kinema => 52_Kinema}/java/src/Kinema.java (100%) rename {52 Kinema => 52_Kinema}/java/src/KinemaGame.java (100%) rename {52 Kinema => 52_Kinema}/javascript/README.md (100%) rename {52 Kinema => 52_Kinema}/javascript/kinema.html (100%) rename {52 Kinema => 52_Kinema}/javascript/kinema.js (100%) rename {52 Kinema => 52_Kinema}/kinema.bas (100%) rename {52 Kinema => 52_Kinema}/pascal/README.md (100%) rename {52 Kinema => 52_Kinema}/perl/README.md (100%) rename {52 Kinema => 52_Kinema}/perl/kinema.pl (100%) rename {52 Kinema => 52_Kinema}/python/README.md (100%) rename {52 Kinema => 52_Kinema}/python/kinema.py (100%) rename {52 Kinema => 52_Kinema}/ruby/README.md (100%) rename {52 Kinema => 52_Kinema}/vbnet/README.md (100%) rename {53 King => 53_King}/README.md (100%) rename {53 King => 53_King}/csharp/README.md (100%) rename {53 King => 53_King}/java/README.md (100%) rename {53 King => 53_King}/javascript/README.md (100%) rename {53 King => 53_King}/javascript/king.html (100%) rename {53 King => 53_King}/javascript/king.js (100%) rename {53 King => 53_King}/king.bas (100%) rename {53 King => 53_King}/pascal/README.md (100%) rename {53 King => 53_King}/perl/README.md (100%) rename {53 King => 53_King}/python/README.md (100%) rename {53 King => 53_King}/ruby/README.md (100%) rename {53 King => 53_King}/vbnet/README.md (100%) rename {54 Letter => 54_Letter}/README.md (100%) rename {54 Letter => 54_Letter}/csharp/README.md (100%) rename {54 Letter => 54_Letter}/java/README.md (100%) rename {54 Letter => 54_Letter}/java/src/Letter.java (100%) rename {54 Letter => 54_Letter}/java/src/LetterGame.java (100%) rename {54 Letter => 54_Letter}/javascript/README.md (100%) rename {54 Letter => 54_Letter}/javascript/letter.html (100%) rename {54 Letter => 54_Letter}/javascript/letter.js (100%) rename {54 Letter => 54_Letter}/letter.bas (100%) rename {54 Letter => 54_Letter}/pascal/README.md (100%) rename {54 Letter => 54_Letter}/perl/README.md (100%) rename {54 Letter => 54_Letter}/perl/letter.pl (100%) rename {54 Letter => 54_Letter}/python/README.md (100%) rename {54 Letter => 54_Letter}/python/letter.py (100%) rename {54 Letter => 54_Letter}/ruby/README.md (100%) rename {54 Letter => 54_Letter}/vbnet/README.md (100%) rename {55 Life => 55_Life}/README.md (100%) rename {55 Life => 55_Life}/csharp/README.md (100%) rename {55 Life => 55_Life}/java/README.md (100%) rename {55 Life => 55_Life}/javascript/README.md (100%) rename {55 Life => 55_Life}/javascript/life.html (100%) rename {55 Life => 55_Life}/javascript/life.js (100%) rename {55 Life => 55_Life}/life.bas (100%) rename {55 Life => 55_Life}/pascal/README.md (100%) rename {55 Life => 55_Life}/perl/README.md (100%) rename {55 Life => 55_Life}/python/README.md (100%) rename {55 Life => 55_Life}/python/life.py (100%) rename {55 Life => 55_Life}/ruby/README.md (100%) rename {55 Life => 55_Life}/ruby/life.rb (100%) rename {55 Life => 55_Life}/vbnet/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/csharp/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/java/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/javascript/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/javascript/lifefortwo.html (100%) rename {56 Life for Two => 56_Life_for_Two}/javascript/lifefortwo.js (100%) rename {56 Life for Two => 56_Life_for_Two}/lifefortwo.bas (100%) rename {56 Life for Two => 56_Life_for_Two}/pascal/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/perl/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/python/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/ruby/README.md (100%) rename {56 Life for Two => 56_Life_for_Two}/vbnet/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/csharp/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/csharp/litquiz.cs (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/java/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/java/src/LiteratureQuiz.java (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/java/src/LiteratureQuizGame.java (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/javascript/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/javascript/literature-quiz-node.mjs (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/javascript/litquiz.html (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/javascript/litquiz.js (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/litquiz.bas (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/pascal/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/perl/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/perl/litquiz.pl (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/python/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/python/litquiz.py (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/ruby/README.md (100%) rename {57 Literature Quiz => 57_Literature_Quiz}/vbnet/README.md (100%) rename {58 Love => 58_Love}/README.md (100%) rename {58 Love => 58_Love}/csharp/Love.sln (100%) rename {58 Love => 58_Love}/csharp/Love/Input.cs (100%) rename {58 Love => 58_Love}/csharp/Love/Love.csproj (100%) rename {58 Love => 58_Love}/csharp/Love/LovePattern.cs (100%) rename {58 Love => 58_Love}/csharp/Love/Program.cs (100%) rename {58 Love => 58_Love}/csharp/Love/SourceCharacters.cs (100%) rename {58 Love => 58_Love}/csharp/Love/Strings/Intro.txt (100%) rename {58 Love => 58_Love}/csharp/README.md (100%) rename {58 Love => 58_Love}/java/README.md (100%) rename {58 Love => 58_Love}/java/src/Love.java (100%) rename {58 Love => 58_Love}/javascript/README.md (100%) rename {58 Love => 58_Love}/javascript/love.html (100%) rename {58 Love => 58_Love}/javascript/love.js (100%) rename {58 Love => 58_Love}/love.bas (100%) rename {58 Love => 58_Love}/pascal/README.md (100%) rename {58 Love => 58_Love}/perl/README.md (100%) rename {58 Love => 58_Love}/perl/love.pl (100%) rename {58 Love => 58_Love}/python/README.md (100%) rename {58 Love => 58_Love}/python/love.py (100%) rename {58 Love => 58_Love}/ruby/README.md (100%) rename {58 Love => 58_Love}/vbnet/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/csharp/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/java/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lem.html (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lem.js (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lunar.html (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/javascript/lunar.js (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/lem.bas (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/lunar.bas (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/pascal/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/perl/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/python/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/python/lunar.py (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/rocket.bas (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/ruby/README.md (100%) rename {59 Lunar LEM Rocket => 59_Lunar_LEM_Rocket}/vbnet/README.md (100%) rename {60 Mastermind => 60_Mastermind}/README.md (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/Game.csproj (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/Code.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/CodeFactory.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/ColorInfo.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/Colors.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/Command.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/Controller.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/EnumerableExtensions.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/Program.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/TurnResult.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Game/src/View.cs (100%) rename {60 Mastermind => 60_Mastermind}/csharp/Mastermind.sln (100%) rename {60 Mastermind => 60_Mastermind}/csharp/README.md (100%) rename {60 Mastermind => 60_Mastermind}/java/README.md (100%) rename {60 Mastermind => 60_Mastermind}/javascript/README.md (100%) rename {60 Mastermind => 60_Mastermind}/javascript/mastermind.html (100%) rename {60 Mastermind => 60_Mastermind}/javascript/mastermind.js (100%) rename {60 Mastermind => 60_Mastermind}/mastermind.bas (100%) rename {60 Mastermind => 60_Mastermind}/pascal/README.md (100%) rename {60 Mastermind => 60_Mastermind}/perl/README.md (100%) rename {60 Mastermind => 60_Mastermind}/python/README.md (100%) rename {60 Mastermind => 60_Mastermind}/python/mastermind.py (100%) rename {60 Mastermind => 60_Mastermind}/ruby/README.md (100%) rename {60 Mastermind => 60_Mastermind}/vbnet/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/csharp/GameState.cs (100%) rename {61 Math Dice => 61_Math_Dice}/csharp/MathDice.csproj (100%) rename {61 Math Dice => 61_Math_Dice}/csharp/MathDice.sln (100%) rename {61 Math Dice => 61_Math_Dice}/csharp/Program.cs (100%) rename {61 Math Dice => 61_Math_Dice}/csharp/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/csharp/StringExtensions.cs (100%) rename {61 Math Dice => 61_Math_Dice}/java/Die.java (100%) rename {61 Math Dice => 61_Math_Dice}/java/MathDice.java (100%) rename {61 Math Dice => 61_Math_Dice}/java/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/javascript/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/javascript/mathdice.html (100%) rename {61 Math Dice => 61_Math_Dice}/javascript/mathdice.js (100%) rename {61 Math Dice => 61_Math_Dice}/mathdice.bas (100%) rename {61 Math Dice => 61_Math_Dice}/pascal/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/pascal/mathdice.pas (100%) rename {61 Math Dice => 61_Math_Dice}/perl/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/python/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/python/mathdice.py (100%) rename {61 Math Dice => 61_Math_Dice}/ruby/README.md (100%) rename {61 Math Dice => 61_Math_Dice}/vbnet/README.md (100%) rename {62 Mugwump => 62_Mugwump}/README.md (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump.sln (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Game.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Grid.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Input.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Mugwump.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Mugwump.csproj (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Offset.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Position.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Program.cs (100%) rename {62 Mugwump => 62_Mugwump}/csharp/Mugwump/Strings/Intro.txt (100%) rename {62 Mugwump => 62_Mugwump}/csharp/README.md (100%) rename {62 Mugwump => 62_Mugwump}/java/README.md (100%) rename {62 Mugwump => 62_Mugwump}/java/src/Mugwump.java (100%) rename {62 Mugwump => 62_Mugwump}/javascript/README.md (100%) rename {62 Mugwump => 62_Mugwump}/javascript/mugwump.html (100%) rename {62 Mugwump => 62_Mugwump}/javascript/mugwump.js (100%) rename {62 Mugwump => 62_Mugwump}/mugwump.bas (100%) rename {62 Mugwump => 62_Mugwump}/pascal/README.md (100%) rename {62 Mugwump => 62_Mugwump}/perl/README.md (100%) rename {62 Mugwump => 62_Mugwump}/python/README.md (100%) rename {62 Mugwump => 62_Mugwump}/python/mugwump.py (100%) rename {62 Mugwump => 62_Mugwump}/ruby/README.md (100%) rename {62 Mugwump => 62_Mugwump}/vbnet/README.md (100%) rename {63 Name => 63_Name}/README.md (100%) rename {63 Name => 63_Name}/csharp/Name.csproj (100%) rename {63 Name => 63_Name}/csharp/Name.sln (100%) rename {63 Name => 63_Name}/csharp/Program.cs (100%) rename {63 Name => 63_Name}/csharp/README.md (100%) rename {63 Name => 63_Name}/csharp/StringExtensions.cs (100%) rename {63 Name => 63_Name}/java/README.md (100%) rename {63 Name => 63_Name}/java/main.class (100%) rename {63 Name => 63_Name}/javascript/README.md (100%) rename {63 Name => 63_Name}/javascript/name.html (100%) rename {63 Name => 63_Name}/javascript/name.js (100%) rename {63 Name => 63_Name}/name.bas (100%) rename {63 Name => 63_Name}/pascal/README.md (100%) rename {63 Name => 63_Name}/perl/README.md (100%) rename {63 Name => 63_Name}/perl/name.pl (100%) rename {63 Name => 63_Name}/python/README.md (100%) rename {63 Name => 63_Name}/python/name.py (100%) rename {63 Name => 63_Name}/ruby/README.md (100%) rename {63 Name => 63_Name}/vbnet/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/csharp/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/java/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/java/src/Nicomachus.java (100%) rename {64 Nicomachus => 64_Nicomachus}/javascript/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/javascript/nicomachus.html (100%) rename {64 Nicomachus => 64_Nicomachus}/javascript/nicomachus.js (100%) rename {64 Nicomachus => 64_Nicomachus}/nicomachus.bas (100%) rename {64 Nicomachus => 64_Nicomachus}/pascal/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/perl/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/perl/nicomachus.pl (100%) rename {64 Nicomachus => 64_Nicomachus}/python/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/python/nicomachus.py (100%) rename {64 Nicomachus => 64_Nicomachus}/ruby/README.md (100%) rename {64 Nicomachus => 64_Nicomachus}/vbnet/README.md (100%) rename {65 Nim => 65_Nim}/README.md (100%) rename {65 Nim => 65_Nim}/csharp/README.md (100%) rename {65 Nim => 65_Nim}/java/README.md (100%) rename {65 Nim => 65_Nim}/javascript/README.md (100%) rename {65 Nim => 65_Nim}/javascript/nim.html (100%) rename {65 Nim => 65_Nim}/javascript/nim.js (100%) rename {65 Nim => 65_Nim}/nim.bas (100%) rename {65 Nim => 65_Nim}/pascal/README.md (100%) rename {65 Nim => 65_Nim}/perl/README.md (100%) rename {65 Nim => 65_Nim}/python/README.md (100%) rename {65 Nim => 65_Nim}/ruby/README.md (100%) rename {65 Nim => 65_Nim}/vbnet/README.md (100%) rename {66 Number => 66_Number}/README.md (100%) rename {66 Number => 66_Number}/csharp/README.md (100%) rename {66 Number => 66_Number}/java/Number.java (100%) rename {66 Number => 66_Number}/java/README.md (100%) rename {66 Number => 66_Number}/java/main.class (100%) rename {66 Number => 66_Number}/javascript/README.md (100%) rename {66 Number => 66_Number}/javascript/number.html (100%) rename {66 Number => 66_Number}/javascript/number.js (100%) rename {66 Number => 66_Number}/number.bas (100%) rename {66 Number => 66_Number}/pascal/README.md (100%) rename {66 Number => 66_Number}/perl/README.md (100%) rename {66 Number => 66_Number}/perl/number.pl (100%) rename {66 Number => 66_Number}/python/README.md (100%) rename {66 Number => 66_Number}/python/number.py (100%) rename {66 Number => 66_Number}/ruby/README.md (100%) rename {66 Number => 66_Number}/vbnet/README.md (100%) rename {67 One Check => 67_One_Check}/README.md (100%) rename {67 One Check => 67_One_Check}/csharp/README.md (100%) rename {67 One Check => 67_One_Check}/java/OneCheck.java (100%) rename {67 One Check => 67_One_Check}/java/README.md (100%) rename {67 One Check => 67_One_Check}/javascript/README.md (100%) rename {67 One Check => 67_One_Check}/javascript/onecheck.html (100%) rename {67 One Check => 67_One_Check}/javascript/onecheck.js (100%) rename {67 One Check => 67_One_Check}/onecheck.bas (100%) rename {67 One Check => 67_One_Check}/pascal/README.md (100%) rename {67 One Check => 67_One_Check}/perl/README.md (100%) rename {67 One Check => 67_One_Check}/python/README.md (100%) rename {67 One Check => 67_One_Check}/ruby/README.md (100%) rename {67 One Check => 67_One_Check}/vbnet/README.md (100%) rename {68 Orbit => 68_Orbit}/README.md (100%) rename {68 Orbit => 68_Orbit}/csharp/README.md (100%) rename {68 Orbit => 68_Orbit}/java/Orbit.java (100%) rename {68 Orbit => 68_Orbit}/java/README.md (100%) rename {68 Orbit => 68_Orbit}/javascript/README.md (100%) rename {68 Orbit => 68_Orbit}/javascript/orbit.html (100%) rename {68 Orbit => 68_Orbit}/javascript/orbit.js (100%) rename {68 Orbit => 68_Orbit}/orbit.bas (100%) rename {68 Orbit => 68_Orbit}/pascal/README.md (100%) rename {68 Orbit => 68_Orbit}/perl/README.md (100%) rename {68 Orbit => 68_Orbit}/python/README.md (100%) rename {68 Orbit => 68_Orbit}/python/orbit.py (100%) rename {68 Orbit => 68_Orbit}/ruby/README.md (100%) rename {68 Orbit => 68_Orbit}/vbnet/README.md (100%) rename {69 Pizza => 69_Pizza}/README.md (100%) rename {69 Pizza => 69_Pizza}/csharp/README.md (100%) rename {69 Pizza => 69_Pizza}/java/README.md (100%) rename {69 Pizza => 69_Pizza}/java/src/Pizza.java (100%) rename {69 Pizza => 69_Pizza}/java/src/PizzaGame.java (100%) rename {69 Pizza => 69_Pizza}/javascript/README.md (100%) rename {69 Pizza => 69_Pizza}/javascript/pizza.html (100%) rename {69 Pizza => 69_Pizza}/javascript/pizza.js (100%) rename {69 Pizza => 69_Pizza}/pascal/README.md (100%) rename {69 Pizza => 69_Pizza}/perl/README.md (100%) rename {69 Pizza => 69_Pizza}/pizza.bas (100%) rename {69 Pizza => 69_Pizza}/python/README.md (100%) rename {69 Pizza => 69_Pizza}/python/pizza.py (100%) rename {69 Pizza => 69_Pizza}/ruby/README.md (100%) rename {69 Pizza => 69_Pizza}/vbnet/README.md (100%) rename {70 Poetry => 70_Poetry}/README.md (100%) rename {70 Poetry => 70_Poetry}/csharp/README.md (100%) rename {70 Poetry => 70_Poetry}/java/Poetry.java (100%) rename {70 Poetry => 70_Poetry}/java/README.md (100%) rename {70 Poetry => 70_Poetry}/javascript/README.md (100%) rename {70 Poetry => 70_Poetry}/javascript/poetry.html (100%) rename {70 Poetry => 70_Poetry}/javascript/poetry.js (100%) rename {70 Poetry => 70_Poetry}/pascal/README.md (100%) rename {70 Poetry => 70_Poetry}/perl/README.md (100%) rename {70 Poetry => 70_Poetry}/perl/poetry.pl (100%) rename {70 Poetry => 70_Poetry}/poetry.bas (100%) rename {70 Poetry => 70_Poetry}/poetry.pl (100%) rename {70 Poetry => 70_Poetry}/python/README.md (100%) rename {70 Poetry => 70_Poetry}/python/poetry.py (100%) rename {70 Poetry => 70_Poetry}/ruby/README.md (100%) rename {70 Poetry => 70_Poetry}/vbnet/README.md (100%) rename {71 Poker => 71_Poker}/README.md (100%) rename {71 Poker => 71_Poker}/csharp/README.md (100%) rename {71 Poker => 71_Poker}/java/README.md (100%) rename {71 Poker => 71_Poker}/javascript/README.md (100%) rename {71 Poker => 71_Poker}/javascript/poker.html (100%) rename {71 Poker => 71_Poker}/javascript/poker.js (100%) rename {71 Poker => 71_Poker}/pascal/README.md (100%) rename {71 Poker => 71_Poker}/perl/README.md (100%) rename {71 Poker => 71_Poker}/poker.bas (100%) rename {71 Poker => 71_Poker}/python/README.md (100%) rename {71 Poker => 71_Poker}/ruby/README.md (100%) rename {71 Poker => 71_Poker}/vbnet/README.md (100%) rename {72 Queen => 72_Queen}/README.md (100%) rename {72 Queen => 72_Queen}/csharp/README.md (100%) rename {72 Queen => 72_Queen}/java/README.md (100%) rename {72 Queen => 72_Queen}/javascript/README.md (100%) rename {72 Queen => 72_Queen}/javascript/queen.html (100%) rename {72 Queen => 72_Queen}/javascript/queen.js (100%) rename {72 Queen => 72_Queen}/pascal/README.md (100%) rename {72 Queen => 72_Queen}/perl/README.md (100%) rename {72 Queen => 72_Queen}/python/README.md (100%) rename {72 Queen => 72_Queen}/queen.bas (100%) rename {72 Queen => 72_Queen}/ruby/README.md (100%) rename {72 Queen => 72_Queen}/vbnet/README.md (100%) rename {73 Reverse => 73_Reverse}/README.md (100%) rename {73 Reverse => 73_Reverse}/csharp/README.md (100%) rename {73 Reverse => 73_Reverse}/java/README.md (100%) rename {73 Reverse => 73_Reverse}/java/Reverse.java (100%) rename {73 Reverse => 73_Reverse}/javascript/README.md (100%) rename {73 Reverse => 73_Reverse}/javascript/reverse.html (100%) rename {73 Reverse => 73_Reverse}/javascript/reverse.js (100%) rename {73 Reverse => 73_Reverse}/pascal/README.md (100%) rename {73 Reverse => 73_Reverse}/perl/README.md (100%) rename {73 Reverse => 73_Reverse}/python/README.md (100%) rename {73 Reverse => 73_Reverse}/python/reverse.py (100%) rename {73 Reverse => 73_Reverse}/reverse.bas (100%) rename {73 Reverse => 73_Reverse}/ruby/README.md (100%) rename {73 Reverse => 73_Reverse}/vbnet/README.md (100%) rename {73 Reverse => 73_Reverse}/vbnet/Reverse.vb (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/Choice.cs (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/Choices.cs (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/Game.cs (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/Program.cs (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/csharp/RockScissorsPaper.csproj (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/java/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/java/src/RockScissors.java (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/javascript/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/javascript/rockscissors.html (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/javascript/rockscissors.js (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/pascal/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/perl/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/perl/rockscissors.pl (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/python/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/python/rockscissors.py (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/rockscissors.bas (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/ruby/README.md (100%) rename {74 Rock Scissors Paper => 74_Rock_Scissors_Paper}/vbnet/README.md (100%) rename {75 Roulette => 75_Roulette}/README.md (100%) rename {75 Roulette => 75_Roulette}/csharp/README.md (100%) rename {75 Roulette => 75_Roulette}/java/README.md (100%) rename {75 Roulette => 75_Roulette}/javascript/README.md (100%) rename {75 Roulette => 75_Roulette}/javascript/roulette.html (100%) rename {75 Roulette => 75_Roulette}/javascript/roulette.js (100%) rename {75 Roulette => 75_Roulette}/pascal/README.md (100%) rename {75 Roulette => 75_Roulette}/perl/README.md (100%) rename {75 Roulette => 75_Roulette}/python/README.md (100%) rename {75 Roulette => 75_Roulette}/roulette.bas (100%) rename {75 Roulette => 75_Roulette}/ruby/README.md (100%) rename {75 Roulette => 75_Roulette}/vbnet/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/csharp/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/csharp/RussianRoulette/Program.cs (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/csharp/RussianRoulette/RussianRoulette.csproj (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/csharp/RussianRoulette/RussianRoulette.sln (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/java/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/java/src/RussianRoulette.java (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/javascript/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/javascript/russianroulette.html (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/javascript/russianroulette.js (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/pascal/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/perl/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/perl/russianroulette.pl (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/python/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/python/russianroulette.py (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/ruby/README.md (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/russianroulette.bas (100%) rename {76 Russian Roulette => 76_Russian_Roulette}/vbnet/README.md (100%) rename {77 Salvo => 77_Salvo}/README.md (100%) rename {77 Salvo => 77_Salvo}/csharp/README.md (100%) rename {77 Salvo => 77_Salvo}/java/README.md (100%) rename {77 Salvo => 77_Salvo}/javascript/README.md (100%) rename {77 Salvo => 77_Salvo}/javascript/salvo.html (100%) rename {77 Salvo => 77_Salvo}/javascript/salvo.js (100%) rename {77 Salvo => 77_Salvo}/pascal/README.md (100%) rename {77 Salvo => 77_Salvo}/perl/README.md (100%) rename {77 Salvo => 77_Salvo}/python/README.md (100%) rename {77 Salvo => 77_Salvo}/python/salvo.ipynb (100%) rename {77 Salvo => 77_Salvo}/python/salvo.py (100%) rename {77 Salvo => 77_Salvo}/ruby/README.md (100%) rename {77 Salvo => 77_Salvo}/salvo.bas (100%) rename {77 Salvo => 77_Salvo}/vbnet/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/csharp/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/csharp/SineWave/SineWave.sln (100%) rename {78 Sine Wave => 78_Sine_Wave}/csharp/SineWave/SineWave/Program.cs (100%) rename {78 Sine Wave => 78_Sine_Wave}/csharp/SineWave/SineWave/SineWave.csproj (100%) rename {78 Sine Wave => 78_Sine_Wave}/java/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/java/src/SineWave.java (100%) rename {78 Sine Wave => 78_Sine_Wave}/javascript/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/javascript/sinewave.js (100%) rename {78 Sine Wave => 78_Sine_Wave}/pascal/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/perl/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/perl/sinewave.pl (100%) rename {78 Sine Wave => 78_Sine_Wave}/python/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/python/sinewave.py (100%) rename {78 Sine Wave => 78_Sine_Wave}/ruby/README.md (100%) rename {78 Sine Wave => 78_Sine_Wave}/ruby/sinewave.rb (100%) rename {78 Sine Wave => 78_Sine_Wave}/sinewave.bas (100%) rename {78 Sine Wave => 78_Sine_Wave}/vbnet/README.md (100%) rename {79 Slalom => 79_Slalom}/README.md (100%) rename {79 Slalom => 79_Slalom}/csharp/README.md (100%) rename {79 Slalom => 79_Slalom}/java/README.md (100%) rename {79 Slalom => 79_Slalom}/javascript/README.md (100%) rename {79 Slalom => 79_Slalom}/javascript/slalom.html (100%) rename {79 Slalom => 79_Slalom}/javascript/slalom.js (100%) rename {79 Slalom => 79_Slalom}/pascal/README.md (100%) rename {79 Slalom => 79_Slalom}/perl/README.md (100%) rename {79 Slalom => 79_Slalom}/python/README.md (100%) rename {79 Slalom => 79_Slalom}/ruby/README.md (100%) rename {79 Slalom => 79_Slalom}/slalom.bas (100%) rename {79 Slalom => 79_Slalom}/vbnet/README.md (100%) rename {80 Slots => 80_Slots}/README.md (100%) rename {80 Slots => 80_Slots}/csharp/README.md (100%) rename {80 Slots => 80_Slots}/java/README.md (100%) rename {80 Slots => 80_Slots}/java/src/Slots.java (100%) rename {80 Slots => 80_Slots}/java/src/SlotsGame.java (100%) rename {80 Slots => 80_Slots}/javascript/README.md (100%) rename {80 Slots => 80_Slots}/javascript/slots.html (100%) rename {80 Slots => 80_Slots}/javascript/slots.js (100%) rename {80 Slots => 80_Slots}/pascal/README.md (100%) rename {80 Slots => 80_Slots}/perl/README.md (100%) rename {80 Slots => 80_Slots}/python/README.md (100%) rename {80 Slots => 80_Slots}/python/slots.py (100%) rename {80 Slots => 80_Slots}/ruby/README.md (100%) rename {80 Slots => 80_Slots}/slots.bas (100%) rename {80 Slots => 80_Slots}/vbnet/README.md (100%) rename {81 Splat => 81_Splat}/README.md (100%) rename {81 Splat => 81_Splat}/csharp/README.md (100%) rename {81 Splat => 81_Splat}/java/README.md (100%) rename {81 Splat => 81_Splat}/javascript/README.md (100%) rename {81 Splat => 81_Splat}/javascript/splat.html (100%) rename {81 Splat => 81_Splat}/javascript/splat.js (100%) rename {81 Splat => 81_Splat}/pascal/README.md (100%) rename {81 Splat => 81_Splat}/perl/README.md (100%) rename {81 Splat => 81_Splat}/python/README.md (100%) rename {81 Splat => 81_Splat}/python/splat.py (100%) rename {81 Splat => 81_Splat}/ruby/README.md (100%) rename {81 Splat => 81_Splat}/splat.bas (100%) rename {81 Splat => 81_Splat}/vbnet/README.md (100%) rename {82 Stars => 82_Stars}/README.md (100%) rename {82 Stars => 82_Stars}/csharp/README.md (100%) rename {82 Stars => 82_Stars}/csharp/Stars.sln (100%) rename {82 Stars => 82_Stars}/csharp/Stars/Game.cs (100%) rename {82 Stars => 82_Stars}/csharp/Stars/Input.cs (100%) rename {82 Stars => 82_Stars}/csharp/Stars/Program.cs (100%) rename {82 Stars => 82_Stars}/csharp/Stars/Stars.csproj (100%) rename {82 Stars => 82_Stars}/java/README.md (100%) rename {82 Stars => 82_Stars}/java/src/Stars.java (100%) rename {82 Stars => 82_Stars}/java/src/StarsGame.java (100%) rename {82 Stars => 82_Stars}/javascript/README.md (100%) rename {82 Stars => 82_Stars}/javascript/stars.html (100%) rename {82 Stars => 82_Stars}/javascript/stars.js (100%) rename {82 Stars => 82_Stars}/pascal/README.md (100%) rename {82 Stars => 82_Stars}/perl/README.md (100%) rename {82 Stars => 82_Stars}/python/README.md (100%) rename {82 Stars => 82_Stars}/python/stars.py (100%) rename {82 Stars => 82_Stars}/ruby/README.md (100%) rename {82 Stars => 82_Stars}/stars.bas (100%) rename {82 Stars => 82_Stars}/vbnet/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/Game.csproj (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/StockMarket.sln (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Assets.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Broker.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Company.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Controller.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Extensions/EnumerableExtensions.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Extensions/ImmutableArrayExtensions.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Extensions/RandomExtensions.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/Program.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/StockMarket.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/TradingDay.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/TransactionResult.cs (100%) rename {83 Stock Market => 83_Stock_Market}/csharp/src/View.cs (100%) rename {83 Stock Market => 83_Stock_Market}/java/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/javascript/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/javascript/stockmarket.html (100%) rename {83 Stock Market => 83_Stock_Market}/javascript/stockmarket.js (100%) rename {83 Stock Market => 83_Stock_Market}/pascal/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/perl/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/python/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/ruby/README.md (100%) rename {83 Stock Market => 83_Stock_Market}/stockmarket.bas (100%) rename {83 Stock Market => 83_Stock_Market}/vbnet/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Commands/Command.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Commands/CommandExtensions.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Commands/CommandResult.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Game.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Input.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Objects/Enterprise.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Objects/Klingon.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Objects/Star.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Objects/Starbase.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Output.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Program.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Random.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/CombatArea.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Congratulations.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/CourtMartial.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Destroyed.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/EndOfMission.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Enterprise.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Instructions.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/LowShields.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/NoEnemyShips.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/NoStarbase.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/NowEntering.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Orders.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/PermissionDenied.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Protected.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/RegionNames.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/RelievedOfCommand.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/RepairEstimate.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/RepairPrompt.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/ReplayPrompt.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/ShieldsDropped.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/ShieldsSet.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/ShortRangeSensorsOut.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/StartText.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Stranded.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Strings.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Resources/Title.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/Coordinates.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/Course.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/Galaxy.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/Quadrant.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Space/QuadrantInfo.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/StringExtensions.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/SuperStarTrek.csproj (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/SuperStarTrek.sln (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/ComputerFunction.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/GalacticReport.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/NavigationCalculator.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/StatusReport.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/DamageControl.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/LibraryComputer.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/LongRangeSensors.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/PhaserControl.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/PhotonTubes.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ShieldControl.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/ShortRangeSensors.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/Subsystem.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Systems/WarpEngines.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/csharp/Utils/DirectionAndDistance.cs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/instructions.txt (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/java/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/javascript/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/javascript/cli.mjs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/javascript/index.html (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/javascript/package.json (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/javascript/superstartrek.mjs (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/pascal/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/perl/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/python/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/python/superstartrek.py (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/python/superstartrekins.py (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/ruby/README.md (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/superstartrek.bas (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/superstartrekins.bas (100%) rename {84 Super Star Trek => 84_Super_Star_Trek}/vbnet/README.md (100%) rename {85 Synonym => 85_Synonym}/README.md (100%) rename {85 Synonym => 85_Synonym}/csharp/README.md (100%) rename {85 Synonym => 85_Synonym}/java/README.md (100%) rename {85 Synonym => 85_Synonym}/java/src/Synonym.java (100%) rename {85 Synonym => 85_Synonym}/java/src/SynonymGame.java (100%) rename {85 Synonym => 85_Synonym}/java/src/SynonymList.java (100%) rename {85 Synonym => 85_Synonym}/javascript/README.md (100%) rename {85 Synonym => 85_Synonym}/javascript/synonym.html (100%) rename {85 Synonym => 85_Synonym}/javascript/synonym.js (100%) rename {85 Synonym => 85_Synonym}/pascal/README.md (100%) rename {85 Synonym => 85_Synonym}/perl/README.md (100%) rename {85 Synonym => 85_Synonym}/python/README.md (100%) rename {85 Synonym => 85_Synonym}/python/synonym.py (100%) rename {85 Synonym => 85_Synonym}/ruby/README.md (100%) rename {85 Synonym => 85_Synonym}/synonym.bas (100%) rename {85 Synonym => 85_Synonym}/vbnet/README.md (100%) rename {86 Target => 86_Target}/README.md (100%) rename {86 Target => 86_Target}/csharp/README.md (100%) rename {86 Target => 86_Target}/csharp/Target.sln (100%) rename {86 Target => 86_Target}/csharp/Target/Angle.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Explosion.cs (100%) rename {86 Target => 86_Target}/csharp/Target/FiringRange.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Game.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Input.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Offset.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Point.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Program.cs (100%) rename {86 Target => 86_Target}/csharp/Target/RandomExtensions.cs (100%) rename {86 Target => 86_Target}/csharp/Target/Strings/TitleAndInstructions.txt (100%) rename {86 Target => 86_Target}/csharp/Target/Target.csproj (100%) rename {86 Target => 86_Target}/java/README.md (100%) rename {86 Target => 86_Target}/java/Target.java (100%) rename {86 Target => 86_Target}/javascript/README.md (100%) rename {86 Target => 86_Target}/javascript/target.html (100%) rename {86 Target => 86_Target}/javascript/target.js (100%) rename {86 Target => 86_Target}/pascal/README.md (100%) rename {86 Target => 86_Target}/perl/README.md (100%) rename {86 Target => 86_Target}/python/README.md (100%) rename {86 Target => 86_Target}/python/target.py (100%) rename {86 Target => 86_Target}/ruby/README.md (100%) rename {86 Target => 86_Target}/target.bas (100%) rename {86 Target => 86_Target}/vbnet/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/3dplot.bas (100%) rename {87 3-D Plot => 87_3-D_Plot}/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/csharp/Plot.sln (100%) rename {87 3-D Plot => 87_3-D_Plot}/csharp/Plot/Function.cs (100%) rename {87 3-D Plot => 87_3-D_Plot}/csharp/Plot/Plot.csproj (100%) rename {87 3-D Plot => 87_3-D_Plot}/csharp/Plot/Program.cs (100%) rename {87 3-D Plot => 87_3-D_Plot}/csharp/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/java/Plot3D.java (100%) rename {87 3-D Plot => 87_3-D_Plot}/java/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/javascript/3dplot.html (100%) rename {87 3-D Plot => 87_3-D_Plot}/javascript/3dplot.js (100%) rename {87 3-D Plot => 87_3-D_Plot}/javascript/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/pascal/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/perl/3dplot.pl (100%) rename {87 3-D Plot => 87_3-D_Plot}/perl/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/python/3dplot.py (100%) rename {87 3-D Plot => 87_3-D_Plot}/python/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/ruby/3dplot.rb (100%) rename {87 3-D Plot => 87_3-D_Plot}/ruby/README.md (100%) rename {87 3-D Plot => 87_3-D_Plot}/vbnet/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/csharp/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/java/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/javascript/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/javascript/qubit.html (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/javascript/qubit.js (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/pascal/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/perl/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/python/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/python/qubit.py (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/qubit.bas (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/ruby/README.md (100%) rename {88 3-D Tic-Tac-Toe => 88_3-D_Tic-Tac-Toe}/vbnet/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/csharp/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/java/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/java/src/Board.java (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/java/src/TicTacToe2.java (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe1.html (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe1.js (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe2.html (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/javascript/tictactoe2.js (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/pascal/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/perl/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/python/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/python/tictactoe2.py (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/ruby/README.md (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/tictactoe1.bas (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/tictactoe2.bas (100%) rename {89 Tic-Tac-Toe => 89_Tic-Tac-Toe}/vbnet/README.md (100%) rename {90 Tower => 90_Tower}/README.md (100%) rename {90 Tower => 90_Tower}/csharp/README.md (100%) rename {90 Tower => 90_Tower}/java/README.md (100%) rename {90 Tower => 90_Tower}/java/Tower.java (100%) rename {90 Tower => 90_Tower}/javascript/README.md (100%) rename {90 Tower => 90_Tower}/javascript/tower.html (100%) rename {90 Tower => 90_Tower}/javascript/tower.js (100%) rename {90 Tower => 90_Tower}/pascal/README.md (100%) rename {90 Tower => 90_Tower}/perl/README.md (100%) rename {90 Tower => 90_Tower}/python/README.md (100%) rename {90 Tower => 90_Tower}/ruby/README.md (100%) rename {90 Tower => 90_Tower}/tower.bas (100%) rename {90 Tower => 90_Tower}/vbnet/README.md (100%) rename {91 Train => 91_Train}/README.md (100%) rename {91 Train => 91_Train}/csharp/README.md (100%) rename {91 Train => 91_Train}/java/README.md (100%) rename {91 Train => 91_Train}/java/src/Train.java (100%) rename {91 Train => 91_Train}/javascript/README.md (100%) rename {91 Train => 91_Train}/javascript/train.html (100%) rename {91 Train => 91_Train}/javascript/train.js (100%) rename {91 Train => 91_Train}/pascal/README.md (100%) rename {91 Train => 91_Train}/perl/README.md (100%) rename {91 Train => 91_Train}/perl/train.pl (100%) rename {91 Train => 91_Train}/python/README.md (100%) rename {91 Train => 91_Train}/python/train.py (100%) rename {91 Train => 91_Train}/ruby/README.md (100%) rename {91 Train => 91_Train}/ruby/train.rb (100%) rename {91 Train => 91_Train}/train.bas (100%) rename {91 Train => 91_Train}/vbnet/README.md (100%) rename {92 Trap => 92_Trap}/README.md (100%) rename {92 Trap => 92_Trap}/csharp/README.md (100%) rename {92 Trap => 92_Trap}/java/README.md (100%) rename {92 Trap => 92_Trap}/java/src/Trap.java (100%) rename {92 Trap => 92_Trap}/java/src/TrapGame.java (100%) rename {92 Trap => 92_Trap}/javascript/README.md (100%) rename {92 Trap => 92_Trap}/javascript/trap.html (100%) rename {92 Trap => 92_Trap}/javascript/trap.js (100%) rename {92 Trap => 92_Trap}/pascal/README.md (100%) rename {92 Trap => 92_Trap}/perl/README.md (100%) rename {92 Trap => 92_Trap}/perl/trap.pl (100%) rename {92 Trap => 92_Trap}/python/README.md (100%) rename {92 Trap => 92_Trap}/python/trap.py (100%) rename {92 Trap => 92_Trap}/ruby/README.md (100%) rename {92 Trap => 92_Trap}/trap.bas (100%) rename {92 Trap => 92_Trap}/vbnet/README.md (100%) rename {93 23 Matches => 93_23_Matches}/23matches.bas (100%) rename {93 23 Matches => 93_23_Matches}/README.md (100%) rename {93 23 Matches => 93_23_Matches}/csharp/README.md (100%) rename {93 23 Matches => 93_23_Matches}/java/README.md (100%) rename {93 23 Matches => 93_23_Matches}/java/TwentyThreeMatches.java (100%) rename {93 23 Matches => 93_23_Matches}/javascript/23matches.html (100%) rename {93 23 Matches => 93_23_Matches}/javascript/23matches.js (100%) rename {93 23 Matches => 93_23_Matches}/javascript/README.md (100%) rename {93 23 Matches => 93_23_Matches}/pascal/README.md (100%) rename {93 23 Matches => 93_23_Matches}/perl/README.md (100%) rename {93 23 Matches => 93_23_Matches}/python/23matches.py (100%) rename {93 23 Matches => 93_23_Matches}/python/README.md (100%) rename {93 23 Matches => 93_23_Matches}/ruby/README.md (100%) rename {93 23 Matches => 93_23_Matches}/vbnet/README.md (100%) rename {94 War => 94_War}/README.md (100%) rename {94 War => 94_War}/csharp/README.md (100%) rename {94 War => 94_War}/csharp/War/War.sln (100%) rename {94 War => 94_War}/csharp/War/War/Cards.cs (100%) rename {94 War => 94_War}/csharp/War/War/Program.cs (100%) rename {94 War => 94_War}/csharp/War/War/UserInterface.cs (100%) rename {94 War => 94_War}/csharp/War/War/War.csproj (100%) rename {94 War => 94_War}/csharp/War/WarTester/Tests.cs (100%) rename {94 War => 94_War}/csharp/War/WarTester/WarTester.csproj (100%) rename {94 War => 94_War}/java/README.md (100%) rename {94 War => 94_War}/java/War.java (100%) rename {94 War => 94_War}/javascript/README.md (100%) rename {94 War => 94_War}/javascript/war.html (100%) rename {94 War => 94_War}/javascript/war.js (100%) rename {94 War => 94_War}/pascal/README.md (100%) rename {94 War => 94_War}/perl/README.md (100%) rename {94 War => 94_War}/python/README.md (100%) rename {94 War => 94_War}/python/war.py (100%) rename {94 War => 94_War}/ruby/README.md (100%) rename {94 War => 94_War}/vbnet/README.md (100%) rename {94 War => 94_War}/war.bas (100%) rename {95 Weekday => 95_Weekday}/README.md (100%) rename {95 Weekday => 95_Weekday}/csharp/README.md (100%) rename {95 Weekday => 95_Weekday}/java/README.md (100%) rename {95 Weekday => 95_Weekday}/java/Weekday.java (100%) rename {95 Weekday => 95_Weekday}/javascript/README.md (100%) rename {95 Weekday => 95_Weekday}/javascript/weekday.html (100%) rename {95 Weekday => 95_Weekday}/javascript/weekday.js (100%) rename {95 Weekday => 95_Weekday}/pascal/README.md (100%) rename {95 Weekday => 95_Weekday}/perl/README.md (100%) rename {95 Weekday => 95_Weekday}/python/README.md (100%) rename {95 Weekday => 95_Weekday}/python/weekday.py (100%) rename {95 Weekday => 95_Weekday}/ruby/README.md (100%) rename {95 Weekday => 95_Weekday}/vbnet/README.md (100%) rename {95 Weekday => 95_Weekday}/weekday.bas (100%) rename {96 Word => 96_Word}/README.md (100%) rename {96 Word => 96_Word}/csharp/Program.cs (100%) rename {96 Word => 96_Word}/csharp/README.md (100%) rename {96 Word => 96_Word}/csharp/word.csproj (100%) rename {96 Word => 96_Word}/csharp/word.sln (100%) rename {96 Word => 96_Word}/java/README.md (100%) rename {96 Word => 96_Word}/java/Word.java (100%) rename {96 Word => 96_Word}/javascript/README.md (100%) rename {96 Word => 96_Word}/javascript/word.html (100%) rename {96 Word => 96_Word}/javascript/word.js (100%) rename {96 Word => 96_Word}/pascal/README.md (100%) rename {96 Word => 96_Word}/perl/README.md (100%) rename {96 Word => 96_Word}/python/README.md (100%) rename {96 Word => 96_Word}/python/word.py (100%) rename {96 Word => 96_Word}/ruby/README.md (100%) rename {96 Word => 96_Word}/ruby/word.rb (100%) rename {96 Word => 96_Word}/vbnet/Program.vb (100%) rename {96 Word => 96_Word}/vbnet/README.md (100%) rename {96 Word => 96_Word}/vbnet/word.sln (100%) rename {96 Word => 96_Word}/vbnet/word.vbproj (100%) rename {96 Word => 96_Word}/word.bas (100%) diff --git a/01 Acey Ducey/README.md b/01_Acey_Ducey/README.md similarity index 100% rename from 01 Acey Ducey/README.md rename to 01_Acey_Ducey/README.md diff --git a/01 Acey Ducey/aceyducey.bas b/01_Acey_Ducey/aceyducey.bas similarity index 100% rename from 01 Acey Ducey/aceyducey.bas rename to 01_Acey_Ducey/aceyducey.bas diff --git a/01 Acey Ducey/csharp/AceyDucey.csproj b/01_Acey_Ducey/csharp/AceyDucey.csproj similarity index 100% rename from 01 Acey Ducey/csharp/AceyDucey.csproj rename to 01_Acey_Ducey/csharp/AceyDucey.csproj diff --git a/01 Acey Ducey/csharp/AceyDucey.sln b/01_Acey_Ducey/csharp/AceyDucey.sln similarity index 100% rename from 01 Acey Ducey/csharp/AceyDucey.sln rename to 01_Acey_Ducey/csharp/AceyDucey.sln diff --git a/01 Acey Ducey/csharp/Game.cs b/01_Acey_Ducey/csharp/Game.cs similarity index 100% rename from 01 Acey Ducey/csharp/Game.cs rename to 01_Acey_Ducey/csharp/Game.cs diff --git a/01 Acey Ducey/csharp/GameState.cs b/01_Acey_Ducey/csharp/GameState.cs similarity index 100% rename from 01 Acey Ducey/csharp/GameState.cs rename to 01_Acey_Ducey/csharp/GameState.cs diff --git a/01 Acey Ducey/csharp/Program.cs b/01_Acey_Ducey/csharp/Program.cs similarity index 100% rename from 01 Acey Ducey/csharp/Program.cs rename to 01_Acey_Ducey/csharp/Program.cs diff --git a/01 Acey Ducey/csharp/README.md b/01_Acey_Ducey/csharp/README.md similarity index 100% rename from 01 Acey Ducey/csharp/README.md rename to 01_Acey_Ducey/csharp/README.md diff --git a/01 Acey Ducey/java/README.md b/01_Acey_Ducey/java/README.md similarity index 100% rename from 01 Acey Ducey/java/README.md rename to 01_Acey_Ducey/java/README.md diff --git a/01 Acey Ducey/java/src/AceyDucey.java b/01_Acey_Ducey/java/src/AceyDucey.java similarity index 100% rename from 01 Acey Ducey/java/src/AceyDucey.java rename to 01_Acey_Ducey/java/src/AceyDucey.java diff --git a/01 Acey Ducey/java/src/AceyDuceyGame.java b/01_Acey_Ducey/java/src/AceyDuceyGame.java similarity index 100% rename from 01 Acey Ducey/java/src/AceyDuceyGame.java rename to 01_Acey_Ducey/java/src/AceyDuceyGame.java diff --git a/01 Acey Ducey/java/src/Card.java b/01_Acey_Ducey/java/src/Card.java similarity index 100% rename from 01 Acey Ducey/java/src/Card.java rename to 01_Acey_Ducey/java/src/Card.java diff --git a/01 Acey Ducey/javascript/README.md b/01_Acey_Ducey/javascript/README.md similarity index 100% rename from 01 Acey Ducey/javascript/README.md rename to 01_Acey_Ducey/javascript/README.md diff --git a/01 Acey Ducey/javascript/aceyducey.html b/01_Acey_Ducey/javascript/aceyducey.html similarity index 100% rename from 01 Acey Ducey/javascript/aceyducey.html rename to 01_Acey_Ducey/javascript/aceyducey.html diff --git a/01 Acey Ducey/javascript/aceyducey.js b/01_Acey_Ducey/javascript/aceyducey.js similarity index 100% rename from 01 Acey Ducey/javascript/aceyducey.js rename to 01_Acey_Ducey/javascript/aceyducey.js diff --git a/01 Acey Ducey/pascal/.gitattributes b/01_Acey_Ducey/pascal/.gitattributes similarity index 100% rename from 01 Acey Ducey/pascal/.gitattributes rename to 01_Acey_Ducey/pascal/.gitattributes diff --git a/01 Acey Ducey/pascal/.gitignore b/01_Acey_Ducey/pascal/.gitignore similarity index 100% rename from 01 Acey Ducey/pascal/.gitignore rename to 01_Acey_Ducey/pascal/.gitignore diff --git a/01 Acey Ducey/pascal/README.md b/01_Acey_Ducey/pascal/README.md similarity index 100% rename from 01 Acey Ducey/pascal/README.md rename to 01_Acey_Ducey/pascal/README.md diff --git a/01 Acey Ducey/pascal/object-pascal/aceyducey.lpi b/01_Acey_Ducey/pascal/object-pascal/aceyducey.lpi similarity index 100% rename from 01 Acey Ducey/pascal/object-pascal/aceyducey.lpi rename to 01_Acey_Ducey/pascal/object-pascal/aceyducey.lpi diff --git a/01 Acey Ducey/pascal/object-pascal/aceyducey.pas b/01_Acey_Ducey/pascal/object-pascal/aceyducey.pas similarity index 100% rename from 01 Acey Ducey/pascal/object-pascal/aceyducey.pas rename to 01_Acey_Ducey/pascal/object-pascal/aceyducey.pas diff --git a/01 Acey Ducey/pascal/object-pascal/deck.pas b/01_Acey_Ducey/pascal/object-pascal/deck.pas similarity index 100% rename from 01 Acey Ducey/pascal/object-pascal/deck.pas rename to 01_Acey_Ducey/pascal/object-pascal/deck.pas diff --git a/01 Acey Ducey/pascal/object-pascal/game.pas b/01_Acey_Ducey/pascal/object-pascal/game.pas similarity index 100% rename from 01 Acey Ducey/pascal/object-pascal/game.pas rename to 01_Acey_Ducey/pascal/object-pascal/game.pas diff --git a/01 Acey Ducey/pascal/simple/aceyducey.lpi b/01_Acey_Ducey/pascal/simple/aceyducey.lpi similarity index 100% rename from 01 Acey Ducey/pascal/simple/aceyducey.lpi rename to 01_Acey_Ducey/pascal/simple/aceyducey.lpi diff --git a/01 Acey Ducey/pascal/simple/aceyducey.pas b/01_Acey_Ducey/pascal/simple/aceyducey.pas similarity index 100% rename from 01 Acey Ducey/pascal/simple/aceyducey.pas rename to 01_Acey_Ducey/pascal/simple/aceyducey.pas diff --git a/01 Acey Ducey/perl/README.md b/01_Acey_Ducey/perl/README.md similarity index 100% rename from 01 Acey Ducey/perl/README.md rename to 01_Acey_Ducey/perl/README.md diff --git a/01 Acey Ducey/perl/aceyducey.pl b/01_Acey_Ducey/perl/aceyducey.pl similarity index 100% rename from 01 Acey Ducey/perl/aceyducey.pl rename to 01_Acey_Ducey/perl/aceyducey.pl diff --git a/01 Acey Ducey/python/README.md b/01_Acey_Ducey/python/README.md similarity index 100% rename from 01 Acey Ducey/python/README.md rename to 01_Acey_Ducey/python/README.md diff --git a/01 Acey Ducey/python/acey_ducey.py b/01_Acey_Ducey/python/acey_ducey.py similarity index 100% rename from 01 Acey Ducey/python/acey_ducey.py rename to 01_Acey_Ducey/python/acey_ducey.py diff --git a/01 Acey Ducey/python/aceyducey.py b/01_Acey_Ducey/python/aceyducey.py similarity index 100% rename from 01 Acey Ducey/python/aceyducey.py rename to 01_Acey_Ducey/python/aceyducey.py diff --git a/01 Acey Ducey/ruby/README.md b/01_Acey_Ducey/ruby/README.md similarity index 100% rename from 01 Acey Ducey/ruby/README.md rename to 01_Acey_Ducey/ruby/README.md diff --git a/01 Acey Ducey/ruby/aceyducey.rb b/01_Acey_Ducey/ruby/aceyducey.rb similarity index 100% rename from 01 Acey Ducey/ruby/aceyducey.rb rename to 01_Acey_Ducey/ruby/aceyducey.rb diff --git a/01 Acey Ducey/vbnet/README.md b/01_Acey_Ducey/vbnet/README.md similarity index 100% rename from 01 Acey Ducey/vbnet/README.md rename to 01_Acey_Ducey/vbnet/README.md diff --git a/02 Amazing/README.md b/02_Amazing/README.md similarity index 100% rename from 02 Amazing/README.md rename to 02_Amazing/README.md diff --git a/02 Amazing/amazing.bas b/02_Amazing/amazing.bas similarity index 100% rename from 02 Amazing/amazing.bas rename to 02_Amazing/amazing.bas diff --git a/02 Amazing/csharp/Amazing.cs b/02_Amazing/csharp/Amazing.cs similarity index 100% rename from 02 Amazing/csharp/Amazing.cs rename to 02_Amazing/csharp/Amazing.cs diff --git a/02 Amazing/csharp/Amazing.csproj b/02_Amazing/csharp/Amazing.csproj similarity index 100% rename from 02 Amazing/csharp/Amazing.csproj rename to 02_Amazing/csharp/Amazing.csproj diff --git a/02 Amazing/csharp/Amazing.sln b/02_Amazing/csharp/Amazing.sln similarity index 100% rename from 02 Amazing/csharp/Amazing.sln rename to 02_Amazing/csharp/Amazing.sln diff --git a/02 Amazing/csharp/README.md b/02_Amazing/csharp/README.md similarity index 100% rename from 02 Amazing/csharp/README.md rename to 02_Amazing/csharp/README.md diff --git a/02 Amazing/java/Amazing.java b/02_Amazing/java/Amazing.java similarity index 100% rename from 02 Amazing/java/Amazing.java rename to 02_Amazing/java/Amazing.java diff --git a/02 Amazing/java/AmazingGame.java b/02_Amazing/java/AmazingGame.java similarity index 100% rename from 02 Amazing/java/AmazingGame.java rename to 02_Amazing/java/AmazingGame.java diff --git a/02 Amazing/java/README.md b/02_Amazing/java/README.md similarity index 100% rename from 02 Amazing/java/README.md rename to 02_Amazing/java/README.md diff --git a/02 Amazing/javascript/README.md b/02_Amazing/javascript/README.md similarity index 100% rename from 02 Amazing/javascript/README.md rename to 02_Amazing/javascript/README.md diff --git a/02 Amazing/javascript/amazing.html b/02_Amazing/javascript/amazing.html similarity index 100% rename from 02 Amazing/javascript/amazing.html rename to 02_Amazing/javascript/amazing.html diff --git a/02 Amazing/javascript/amazing.js b/02_Amazing/javascript/amazing.js similarity index 100% rename from 02 Amazing/javascript/amazing.js rename to 02_Amazing/javascript/amazing.js diff --git a/02 Amazing/pascal/.gitattributes b/02_Amazing/pascal/.gitattributes similarity index 100% rename from 02 Amazing/pascal/.gitattributes rename to 02_Amazing/pascal/.gitattributes diff --git a/02 Amazing/pascal/.gitignore b/02_Amazing/pascal/.gitignore similarity index 100% rename from 02 Amazing/pascal/.gitignore rename to 02_Amazing/pascal/.gitignore diff --git a/02 Amazing/pascal/README.md b/02_Amazing/pascal/README.md similarity index 100% rename from 02 Amazing/pascal/README.md rename to 02_Amazing/pascal/README.md diff --git a/02 Amazing/pascal/object-pascal/amazing.lpi b/02_Amazing/pascal/object-pascal/amazing.lpi similarity index 100% rename from 02 Amazing/pascal/object-pascal/amazing.lpi rename to 02_Amazing/pascal/object-pascal/amazing.lpi diff --git a/02 Amazing/pascal/object-pascal/amazing.pas b/02_Amazing/pascal/object-pascal/amazing.pas similarity index 100% rename from 02 Amazing/pascal/object-pascal/amazing.pas rename to 02_Amazing/pascal/object-pascal/amazing.pas diff --git a/02 Amazing/pascal/object-pascal/amazingapplication.pas b/02_Amazing/pascal/object-pascal/amazingapplication.pas similarity index 100% rename from 02 Amazing/pascal/object-pascal/amazingapplication.pas rename to 02_Amazing/pascal/object-pascal/amazingapplication.pas diff --git a/02 Amazing/pascal/object-pascal/maze.pas b/02_Amazing/pascal/object-pascal/maze.pas similarity index 100% rename from 02 Amazing/pascal/object-pascal/maze.pas rename to 02_Amazing/pascal/object-pascal/maze.pas diff --git a/02 Amazing/pascal/object-pascal/room.pas b/02_Amazing/pascal/object-pascal/room.pas similarity index 100% rename from 02 Amazing/pascal/object-pascal/room.pas rename to 02_Amazing/pascal/object-pascal/room.pas diff --git a/02 Amazing/pascal/simple/amazing.lpi b/02_Amazing/pascal/simple/amazing.lpi similarity index 100% rename from 02 Amazing/pascal/simple/amazing.lpi rename to 02_Amazing/pascal/simple/amazing.lpi diff --git a/02 Amazing/pascal/simple/amazing.pas b/02_Amazing/pascal/simple/amazing.pas similarity index 100% rename from 02 Amazing/pascal/simple/amazing.pas rename to 02_Amazing/pascal/simple/amazing.pas diff --git a/02 Amazing/perl/README.md b/02_Amazing/perl/README.md similarity index 100% rename from 02 Amazing/perl/README.md rename to 02_Amazing/perl/README.md diff --git a/02 Amazing/python/README.md b/02_Amazing/python/README.md similarity index 100% rename from 02 Amazing/python/README.md rename to 02_Amazing/python/README.md diff --git a/02 Amazing/python/amazing.py b/02_Amazing/python/amazing.py similarity index 100% rename from 02 Amazing/python/amazing.py rename to 02_Amazing/python/amazing.py diff --git a/02 Amazing/ruby/README.md b/02_Amazing/ruby/README.md similarity index 100% rename from 02 Amazing/ruby/README.md rename to 02_Amazing/ruby/README.md diff --git a/02 Amazing/ruby/amazing.rb b/02_Amazing/ruby/amazing.rb similarity index 100% rename from 02 Amazing/ruby/amazing.rb rename to 02_Amazing/ruby/amazing.rb diff --git a/02 Amazing/vbnet/README.md b/02_Amazing/vbnet/README.md similarity index 100% rename from 02 Amazing/vbnet/README.md rename to 02_Amazing/vbnet/README.md diff --git a/03 Animal/README.md b/03_Animal/README.md similarity index 100% rename from 03 Animal/README.md rename to 03_Animal/README.md diff --git a/03 Animal/animal.bas b/03_Animal/animal.bas similarity index 100% rename from 03 Animal/animal.bas rename to 03_Animal/animal.bas diff --git a/03 Animal/csharp/Animal.csproj b/03_Animal/csharp/Animal.csproj similarity index 100% rename from 03 Animal/csharp/Animal.csproj rename to 03_Animal/csharp/Animal.csproj diff --git a/03 Animal/csharp/Animal.sln b/03_Animal/csharp/Animal.sln similarity index 100% rename from 03 Animal/csharp/Animal.sln rename to 03_Animal/csharp/Animal.sln diff --git a/03 Animal/csharp/Branch.cs b/03_Animal/csharp/Branch.cs similarity index 100% rename from 03 Animal/csharp/Branch.cs rename to 03_Animal/csharp/Branch.cs diff --git a/03 Animal/csharp/Program.cs b/03_Animal/csharp/Program.cs similarity index 100% rename from 03 Animal/csharp/Program.cs rename to 03_Animal/csharp/Program.cs diff --git a/03 Animal/csharp/README.md b/03_Animal/csharp/README.md similarity index 100% rename from 03 Animal/csharp/README.md rename to 03_Animal/csharp/README.md diff --git a/03 Animal/java/Animal.java b/03_Animal/java/Animal.java similarity index 100% rename from 03 Animal/java/Animal.java rename to 03_Animal/java/Animal.java diff --git a/03 Animal/java/README.md b/03_Animal/java/README.md similarity index 100% rename from 03 Animal/java/README.md rename to 03_Animal/java/README.md diff --git a/03 Animal/javascript/README.md b/03_Animal/javascript/README.md similarity index 100% rename from 03 Animal/javascript/README.md rename to 03_Animal/javascript/README.md diff --git a/03 Animal/javascript/animal.html b/03_Animal/javascript/animal.html similarity index 100% rename from 03 Animal/javascript/animal.html rename to 03_Animal/javascript/animal.html diff --git a/03 Animal/javascript/animal.js b/03_Animal/javascript/animal.js similarity index 100% rename from 03 Animal/javascript/animal.js rename to 03_Animal/javascript/animal.js diff --git a/03 Animal/pascal/README.md b/03_Animal/pascal/README.md similarity index 100% rename from 03 Animal/pascal/README.md rename to 03_Animal/pascal/README.md diff --git a/03 Animal/perl/README.md b/03_Animal/perl/README.md similarity index 100% rename from 03 Animal/perl/README.md rename to 03_Animal/perl/README.md diff --git a/03 Animal/python/README.md b/03_Animal/python/README.md similarity index 100% rename from 03 Animal/python/README.md rename to 03_Animal/python/README.md diff --git a/03 Animal/python/animal.py b/03_Animal/python/animal.py similarity index 100% rename from 03 Animal/python/animal.py rename to 03_Animal/python/animal.py diff --git a/03 Animal/ruby/README.md b/03_Animal/ruby/README.md similarity index 100% rename from 03 Animal/ruby/README.md rename to 03_Animal/ruby/README.md diff --git a/03 Animal/ruby/animal.rb b/03_Animal/ruby/animal.rb similarity index 100% rename from 03 Animal/ruby/animal.rb rename to 03_Animal/ruby/animal.rb diff --git a/03 Animal/vbnet/README.md b/03_Animal/vbnet/README.md similarity index 100% rename from 03 Animal/vbnet/README.md rename to 03_Animal/vbnet/README.md diff --git a/04 Awari/README.md b/04_Awari/README.md similarity index 100% rename from 04 Awari/README.md rename to 04_Awari/README.md diff --git a/04 Awari/awari.bas b/04_Awari/awari.bas similarity index 100% rename from 04 Awari/awari.bas rename to 04_Awari/awari.bas diff --git a/04 Awari/csharp/README.md b/04_Awari/csharp/README.md similarity index 100% rename from 04 Awari/csharp/README.md rename to 04_Awari/csharp/README.md diff --git a/04 Awari/java/Awari.java b/04_Awari/java/Awari.java similarity index 100% rename from 04 Awari/java/Awari.java rename to 04_Awari/java/Awari.java diff --git a/04 Awari/java/AwariGame.java b/04_Awari/java/AwariGame.java similarity index 100% rename from 04 Awari/java/AwariGame.java rename to 04_Awari/java/AwariGame.java diff --git a/04 Awari/java/README.md b/04_Awari/java/README.md similarity index 100% rename from 04 Awari/java/README.md rename to 04_Awari/java/README.md diff --git a/04 Awari/javascript/README.md b/04_Awari/javascript/README.md similarity index 100% rename from 04 Awari/javascript/README.md rename to 04_Awari/javascript/README.md diff --git a/04 Awari/javascript/awari.html b/04_Awari/javascript/awari.html similarity index 100% rename from 04 Awari/javascript/awari.html rename to 04_Awari/javascript/awari.html diff --git a/04 Awari/javascript/awari.js b/04_Awari/javascript/awari.js similarity index 100% rename from 04 Awari/javascript/awari.js rename to 04_Awari/javascript/awari.js diff --git a/04 Awari/pascal/README.md b/04_Awari/pascal/README.md similarity index 100% rename from 04 Awari/pascal/README.md rename to 04_Awari/pascal/README.md diff --git a/04 Awari/perl/README.md b/04_Awari/perl/README.md similarity index 100% rename from 04 Awari/perl/README.md rename to 04_Awari/perl/README.md diff --git a/04 Awari/python/README.md b/04_Awari/python/README.md similarity index 100% rename from 04 Awari/python/README.md rename to 04_Awari/python/README.md diff --git a/04 Awari/python/awari.py b/04_Awari/python/awari.py similarity index 100% rename from 04 Awari/python/awari.py rename to 04_Awari/python/awari.py diff --git a/04 Awari/ruby/README.md b/04_Awari/ruby/README.md similarity index 100% rename from 04 Awari/ruby/README.md rename to 04_Awari/ruby/README.md diff --git a/04 Awari/vbnet/README.md b/04_Awari/vbnet/README.md similarity index 100% rename from 04 Awari/vbnet/README.md rename to 04_Awari/vbnet/README.md diff --git a/05 Bagels/README.md b/05_Bagels/README.md similarity index 100% rename from 05 Bagels/README.md rename to 05_Bagels/README.md diff --git a/05 Bagels/bagels.bas b/05_Bagels/bagels.bas similarity index 100% rename from 05 Bagels/bagels.bas rename to 05_Bagels/bagels.bas diff --git a/05 Bagels/csharp/BagelNumber.cs b/05_Bagels/csharp/BagelNumber.cs similarity index 100% rename from 05 Bagels/csharp/BagelNumber.cs rename to 05_Bagels/csharp/BagelNumber.cs diff --git a/05 Bagels/csharp/Bagels.csproj b/05_Bagels/csharp/Bagels.csproj similarity index 100% rename from 05 Bagels/csharp/Bagels.csproj rename to 05_Bagels/csharp/Bagels.csproj diff --git a/05 Bagels/csharp/Game.cs b/05_Bagels/csharp/Game.cs similarity index 100% rename from 05 Bagels/csharp/Game.cs rename to 05_Bagels/csharp/Game.cs diff --git a/05 Bagels/csharp/GameBase.cs b/05_Bagels/csharp/GameBase.cs similarity index 100% rename from 05 Bagels/csharp/GameBase.cs rename to 05_Bagels/csharp/GameBase.cs diff --git a/05 Bagels/csharp/Program.cs b/05_Bagels/csharp/Program.cs similarity index 100% rename from 05 Bagels/csharp/Program.cs rename to 05_Bagels/csharp/Program.cs diff --git a/05 Bagels/csharp/README.md b/05_Bagels/csharp/README.md similarity index 100% rename from 05 Bagels/csharp/README.md rename to 05_Bagels/csharp/README.md diff --git a/05 Bagels/java/BagelGame.java b/05_Bagels/java/BagelGame.java similarity index 100% rename from 05 Bagels/java/BagelGame.java rename to 05_Bagels/java/BagelGame.java diff --git a/05 Bagels/java/Bagels.java b/05_Bagels/java/Bagels.java similarity index 100% rename from 05 Bagels/java/Bagels.java rename to 05_Bagels/java/Bagels.java diff --git a/05 Bagels/java/README.md b/05_Bagels/java/README.md similarity index 100% rename from 05 Bagels/java/README.md rename to 05_Bagels/java/README.md diff --git a/05 Bagels/javascript/README.md b/05_Bagels/javascript/README.md similarity index 100% rename from 05 Bagels/javascript/README.md rename to 05_Bagels/javascript/README.md diff --git a/05 Bagels/javascript/bagels.html b/05_Bagels/javascript/bagels.html similarity index 100% rename from 05 Bagels/javascript/bagels.html rename to 05_Bagels/javascript/bagels.html diff --git a/05 Bagels/javascript/bagels.js b/05_Bagels/javascript/bagels.js similarity index 100% rename from 05 Bagels/javascript/bagels.js rename to 05_Bagels/javascript/bagels.js diff --git a/05 Bagels/pascal/README.md b/05_Bagels/pascal/README.md similarity index 100% rename from 05 Bagels/pascal/README.md rename to 05_Bagels/pascal/README.md diff --git a/05 Bagels/perl/README.md b/05_Bagels/perl/README.md similarity index 100% rename from 05 Bagels/perl/README.md rename to 05_Bagels/perl/README.md diff --git a/05 Bagels/python/README.md b/05_Bagels/python/README.md similarity index 100% rename from 05 Bagels/python/README.md rename to 05_Bagels/python/README.md diff --git a/05 Bagels/python/bagels.py b/05_Bagels/python/bagels.py similarity index 100% rename from 05 Bagels/python/bagels.py rename to 05_Bagels/python/bagels.py diff --git a/05 Bagels/ruby/README.md b/05_Bagels/ruby/README.md similarity index 100% rename from 05 Bagels/ruby/README.md rename to 05_Bagels/ruby/README.md diff --git a/05 Bagels/ruby/bagels.rb b/05_Bagels/ruby/bagels.rb similarity index 100% rename from 05 Bagels/ruby/bagels.rb rename to 05_Bagels/ruby/bagels.rb diff --git a/05 Bagels/vbnet/README.md b/05_Bagels/vbnet/README.md similarity index 100% rename from 05 Bagels/vbnet/README.md rename to 05_Bagels/vbnet/README.md diff --git a/06 Banner/README.md b/06_Banner/README.md similarity index 100% rename from 06 Banner/README.md rename to 06_Banner/README.md diff --git a/06 Banner/banner.bas b/06_Banner/banner.bas similarity index 100% rename from 06 Banner/banner.bas rename to 06_Banner/banner.bas diff --git a/06 Banner/csharp/README.md b/06_Banner/csharp/README.md similarity index 100% rename from 06 Banner/csharp/README.md rename to 06_Banner/csharp/README.md diff --git a/06 Banner/csharp/banner.cs b/06_Banner/csharp/banner.cs similarity index 100% rename from 06 Banner/csharp/banner.cs rename to 06_Banner/csharp/banner.cs diff --git a/06 Banner/csharp/banner.csproj b/06_Banner/csharp/banner.csproj similarity index 100% rename from 06 Banner/csharp/banner.csproj rename to 06_Banner/csharp/banner.csproj diff --git a/06 Banner/csharp/banner.sln b/06_Banner/csharp/banner.sln similarity index 100% rename from 06 Banner/csharp/banner.sln rename to 06_Banner/csharp/banner.sln diff --git a/06 Banner/java/Banner.java b/06_Banner/java/Banner.java similarity index 100% rename from 06 Banner/java/Banner.java rename to 06_Banner/java/Banner.java diff --git a/06 Banner/java/README.md b/06_Banner/java/README.md similarity index 100% rename from 06 Banner/java/README.md rename to 06_Banner/java/README.md diff --git a/06 Banner/javascript/README.md b/06_Banner/javascript/README.md similarity index 100% rename from 06 Banner/javascript/README.md rename to 06_Banner/javascript/README.md diff --git a/06 Banner/javascript/banner.html b/06_Banner/javascript/banner.html similarity index 100% rename from 06 Banner/javascript/banner.html rename to 06_Banner/javascript/banner.html diff --git a/06 Banner/javascript/banner.js b/06_Banner/javascript/banner.js similarity index 100% rename from 06 Banner/javascript/banner.js rename to 06_Banner/javascript/banner.js diff --git a/06 Banner/pascal/README.md b/06_Banner/pascal/README.md similarity index 100% rename from 06 Banner/pascal/README.md rename to 06_Banner/pascal/README.md diff --git a/06 Banner/perl/README.md b/06_Banner/perl/README.md similarity index 100% rename from 06 Banner/perl/README.md rename to 06_Banner/perl/README.md diff --git a/06 Banner/python/README.md b/06_Banner/python/README.md similarity index 100% rename from 06 Banner/python/README.md rename to 06_Banner/python/README.md diff --git a/06 Banner/python/banner.py b/06_Banner/python/banner.py similarity index 100% rename from 06 Banner/python/banner.py rename to 06_Banner/python/banner.py diff --git a/06 Banner/ruby/README.md b/06_Banner/ruby/README.md similarity index 100% rename from 06 Banner/ruby/README.md rename to 06_Banner/ruby/README.md diff --git a/06 Banner/vbnet/README.md b/06_Banner/vbnet/README.md similarity index 100% rename from 06 Banner/vbnet/README.md rename to 06_Banner/vbnet/README.md diff --git a/06 Banner/vbnet/banner.sln b/06_Banner/vbnet/banner.sln similarity index 100% rename from 06 Banner/vbnet/banner.sln rename to 06_Banner/vbnet/banner.sln diff --git a/06 Banner/vbnet/banner.vb b/06_Banner/vbnet/banner.vb similarity index 100% rename from 06 Banner/vbnet/banner.vb rename to 06_Banner/vbnet/banner.vb diff --git a/06 Banner/vbnet/banner.vbproj b/06_Banner/vbnet/banner.vbproj similarity index 100% rename from 06 Banner/vbnet/banner.vbproj rename to 06_Banner/vbnet/banner.vbproj diff --git a/07 Basketball/README.md b/07_Basketball/README.md similarity index 100% rename from 07 Basketball/README.md rename to 07_Basketball/README.md diff --git a/07 Basketball/basketball.bas b/07_Basketball/basketball.bas similarity index 100% rename from 07 Basketball/basketball.bas rename to 07_Basketball/basketball.bas diff --git a/07 Basketball/csharp/README.md b/07_Basketball/csharp/README.md similarity index 100% rename from 07 Basketball/csharp/README.md rename to 07_Basketball/csharp/README.md diff --git a/07 Basketball/java/README.md b/07_Basketball/java/README.md similarity index 100% rename from 07 Basketball/java/README.md rename to 07_Basketball/java/README.md diff --git a/07 Basketball/javascript/README.md b/07_Basketball/javascript/README.md similarity index 100% rename from 07 Basketball/javascript/README.md rename to 07_Basketball/javascript/README.md diff --git a/07 Basketball/javascript/basketball.html b/07_Basketball/javascript/basketball.html similarity index 100% rename from 07 Basketball/javascript/basketball.html rename to 07_Basketball/javascript/basketball.html diff --git a/07 Basketball/javascript/basketball.js b/07_Basketball/javascript/basketball.js similarity index 100% rename from 07 Basketball/javascript/basketball.js rename to 07_Basketball/javascript/basketball.js diff --git a/07 Basketball/pascal/README.md b/07_Basketball/pascal/README.md similarity index 100% rename from 07 Basketball/pascal/README.md rename to 07_Basketball/pascal/README.md diff --git a/07 Basketball/perl/README.md b/07_Basketball/perl/README.md similarity index 100% rename from 07 Basketball/perl/README.md rename to 07_Basketball/perl/README.md diff --git a/07 Basketball/python/README.md b/07_Basketball/python/README.md similarity index 100% rename from 07 Basketball/python/README.md rename to 07_Basketball/python/README.md diff --git a/07 Basketball/ruby/README.md b/07_Basketball/ruby/README.md similarity index 100% rename from 07 Basketball/ruby/README.md rename to 07_Basketball/ruby/README.md diff --git a/07 Basketball/vbnet/README.md b/07_Basketball/vbnet/README.md similarity index 100% rename from 07 Basketball/vbnet/README.md rename to 07_Basketball/vbnet/README.md diff --git a/08 Batnum/README.md b/08_Batnum/README.md similarity index 100% rename from 08 Batnum/README.md rename to 08_Batnum/README.md diff --git a/08 Batnum/batnum.bas b/08_Batnum/batnum.bas similarity index 100% rename from 08 Batnum/batnum.bas rename to 08_Batnum/batnum.bas diff --git a/08 Batnum/csharp/Batnum.csproj b/08_Batnum/csharp/Batnum.csproj similarity index 100% rename from 08 Batnum/csharp/Batnum.csproj rename to 08_Batnum/csharp/Batnum.csproj diff --git a/08 Batnum/csharp/Batnum.sln b/08_Batnum/csharp/Batnum.sln similarity index 100% rename from 08 Batnum/csharp/Batnum.sln rename to 08_Batnum/csharp/Batnum.sln diff --git a/08 Batnum/csharp/BatnumGame.cs b/08_Batnum/csharp/BatnumGame.cs similarity index 100% rename from 08 Batnum/csharp/BatnumGame.cs rename to 08_Batnum/csharp/BatnumGame.cs diff --git a/08 Batnum/csharp/ConsoleUtilities.cs b/08_Batnum/csharp/ConsoleUtilities.cs similarity index 100% rename from 08 Batnum/csharp/ConsoleUtilities.cs rename to 08_Batnum/csharp/ConsoleUtilities.cs diff --git a/08 Batnum/csharp/Program.cs b/08_Batnum/csharp/Program.cs similarity index 100% rename from 08 Batnum/csharp/Program.cs rename to 08_Batnum/csharp/Program.cs diff --git a/08 Batnum/csharp/Properties/Resources.Designer.cs b/08_Batnum/csharp/Properties/Resources.Designer.cs similarity index 100% rename from 08 Batnum/csharp/Properties/Resources.Designer.cs rename to 08_Batnum/csharp/Properties/Resources.Designer.cs diff --git a/08 Batnum/csharp/Properties/Resources.en.resx b/08_Batnum/csharp/Properties/Resources.en.resx similarity index 100% rename from 08 Batnum/csharp/Properties/Resources.en.resx rename to 08_Batnum/csharp/Properties/Resources.en.resx diff --git a/08 Batnum/csharp/Properties/Resources.fr.resx b/08_Batnum/csharp/Properties/Resources.fr.resx similarity index 100% rename from 08 Batnum/csharp/Properties/Resources.fr.resx rename to 08_Batnum/csharp/Properties/Resources.fr.resx diff --git a/08 Batnum/csharp/Properties/Resources.resx b/08_Batnum/csharp/Properties/Resources.resx similarity index 100% rename from 08 Batnum/csharp/Properties/Resources.resx rename to 08_Batnum/csharp/Properties/Resources.resx diff --git a/08 Batnum/csharp/README.md b/08_Batnum/csharp/README.md similarity index 100% rename from 08 Batnum/csharp/README.md rename to 08_Batnum/csharp/README.md diff --git a/08 Batnum/java/README.md b/08_Batnum/java/README.md similarity index 100% rename from 08 Batnum/java/README.md rename to 08_Batnum/java/README.md diff --git a/08 Batnum/java/src/BatNum.java b/08_Batnum/java/src/BatNum.java similarity index 100% rename from 08 Batnum/java/src/BatNum.java rename to 08_Batnum/java/src/BatNum.java diff --git a/08 Batnum/java/src/BatNumGame.java b/08_Batnum/java/src/BatNumGame.java similarity index 100% rename from 08 Batnum/java/src/BatNumGame.java rename to 08_Batnum/java/src/BatNumGame.java diff --git a/08 Batnum/javascript/README.md b/08_Batnum/javascript/README.md similarity index 100% rename from 08 Batnum/javascript/README.md rename to 08_Batnum/javascript/README.md diff --git a/08 Batnum/javascript/batnum.html b/08_Batnum/javascript/batnum.html similarity index 100% rename from 08 Batnum/javascript/batnum.html rename to 08_Batnum/javascript/batnum.html diff --git a/08 Batnum/javascript/batnum.js b/08_Batnum/javascript/batnum.js similarity index 100% rename from 08 Batnum/javascript/batnum.js rename to 08_Batnum/javascript/batnum.js diff --git a/08 Batnum/pascal/README.md b/08_Batnum/pascal/README.md similarity index 100% rename from 08 Batnum/pascal/README.md rename to 08_Batnum/pascal/README.md diff --git a/08 Batnum/perl/README.md b/08_Batnum/perl/README.md similarity index 100% rename from 08 Batnum/perl/README.md rename to 08_Batnum/perl/README.md diff --git a/08 Batnum/python/README.md b/08_Batnum/python/README.md similarity index 100% rename from 08 Batnum/python/README.md rename to 08_Batnum/python/README.md diff --git a/08 Batnum/python/batnum.py b/08_Batnum/python/batnum.py similarity index 100% rename from 08 Batnum/python/batnum.py rename to 08_Batnum/python/batnum.py diff --git a/08 Batnum/ruby/README.md b/08_Batnum/ruby/README.md similarity index 100% rename from 08 Batnum/ruby/README.md rename to 08_Batnum/ruby/README.md diff --git a/08 Batnum/vbnet/Program.vb b/08_Batnum/vbnet/Program.vb similarity index 100% rename from 08 Batnum/vbnet/Program.vb rename to 08_Batnum/vbnet/Program.vb diff --git a/08 Batnum/vbnet/README.md b/08_Batnum/vbnet/README.md similarity index 100% rename from 08 Batnum/vbnet/README.md rename to 08_Batnum/vbnet/README.md diff --git a/08 Batnum/vbnet/batnum.sln b/08_Batnum/vbnet/batnum.sln similarity index 100% rename from 08 Batnum/vbnet/batnum.sln rename to 08_Batnum/vbnet/batnum.sln diff --git a/08 Batnum/vbnet/batnum.vbproj b/08_Batnum/vbnet/batnum.vbproj similarity index 100% rename from 08 Batnum/vbnet/batnum.vbproj rename to 08_Batnum/vbnet/batnum.vbproj diff --git a/09 Battle/README.md b/09_Battle/README.md similarity index 100% rename from 09 Battle/README.md rename to 09_Battle/README.md diff --git a/09 Battle/battle.bas b/09_Battle/battle.bas similarity index 100% rename from 09 Battle/battle.bas rename to 09_Battle/battle.bas diff --git a/09 Battle/csharp/Battle.csproj b/09_Battle/csharp/Battle.csproj similarity index 100% rename from 09 Battle/csharp/Battle.csproj rename to 09_Battle/csharp/Battle.csproj diff --git a/09 Battle/csharp/Battle.sln b/09_Battle/csharp/Battle.sln similarity index 100% rename from 09 Battle/csharp/Battle.sln rename to 09_Battle/csharp/Battle.sln diff --git a/09 Battle/csharp/Game.cs b/09_Battle/csharp/Game.cs similarity index 100% rename from 09 Battle/csharp/Game.cs rename to 09_Battle/csharp/Game.cs diff --git a/09 Battle/csharp/Program.cs b/09_Battle/csharp/Program.cs similarity index 100% rename from 09 Battle/csharp/Program.cs rename to 09_Battle/csharp/Program.cs diff --git a/09 Battle/csharp/README.md b/09_Battle/csharp/README.md similarity index 100% rename from 09 Battle/csharp/README.md rename to 09_Battle/csharp/README.md diff --git a/09 Battle/java/README.md b/09_Battle/java/README.md similarity index 100% rename from 09 Battle/java/README.md rename to 09_Battle/java/README.md diff --git a/09 Battle/javascript/README.md b/09_Battle/javascript/README.md similarity index 100% rename from 09 Battle/javascript/README.md rename to 09_Battle/javascript/README.md diff --git a/09 Battle/javascript/battle.html b/09_Battle/javascript/battle.html similarity index 100% rename from 09 Battle/javascript/battle.html rename to 09_Battle/javascript/battle.html diff --git a/09 Battle/javascript/battle.js b/09_Battle/javascript/battle.js similarity index 100% rename from 09 Battle/javascript/battle.js rename to 09_Battle/javascript/battle.js diff --git a/09 Battle/pascal/README.md b/09_Battle/pascal/README.md similarity index 100% rename from 09 Battle/pascal/README.md rename to 09_Battle/pascal/README.md diff --git a/09 Battle/perl/README.md b/09_Battle/perl/README.md similarity index 100% rename from 09 Battle/perl/README.md rename to 09_Battle/perl/README.md diff --git a/09 Battle/python/README.md b/09_Battle/python/README.md similarity index 100% rename from 09 Battle/python/README.md rename to 09_Battle/python/README.md diff --git a/09 Battle/ruby/README.md b/09_Battle/ruby/README.md similarity index 100% rename from 09 Battle/ruby/README.md rename to 09_Battle/ruby/README.md diff --git a/09 Battle/vbnet/README.md b/09_Battle/vbnet/README.md similarity index 100% rename from 09 Battle/vbnet/README.md rename to 09_Battle/vbnet/README.md diff --git a/10 Blackjack/README.md b/10_Blackjack/README.md similarity index 100% rename from 10 Blackjack/README.md rename to 10_Blackjack/README.md diff --git a/10 Blackjack/blackjack.bas b/10_Blackjack/blackjack.bas similarity index 100% rename from 10 Blackjack/blackjack.bas rename to 10_Blackjack/blackjack.bas diff --git a/10 Blackjack/csharp/Blackjack.csproj b/10_Blackjack/csharp/Blackjack.csproj similarity index 100% rename from 10 Blackjack/csharp/Blackjack.csproj rename to 10_Blackjack/csharp/Blackjack.csproj diff --git a/10 Blackjack/csharp/Card.cs b/10_Blackjack/csharp/Card.cs similarity index 100% rename from 10 Blackjack/csharp/Card.cs rename to 10_Blackjack/csharp/Card.cs diff --git a/10 Blackjack/csharp/Deck.cs b/10_Blackjack/csharp/Deck.cs similarity index 100% rename from 10 Blackjack/csharp/Deck.cs rename to 10_Blackjack/csharp/Deck.cs diff --git a/10 Blackjack/csharp/Game.cs b/10_Blackjack/csharp/Game.cs similarity index 100% rename from 10 Blackjack/csharp/Game.cs rename to 10_Blackjack/csharp/Game.cs diff --git a/10 Blackjack/csharp/Hand.cs b/10_Blackjack/csharp/Hand.cs similarity index 100% rename from 10 Blackjack/csharp/Hand.cs rename to 10_Blackjack/csharp/Hand.cs diff --git a/10 Blackjack/csharp/Player.cs b/10_Blackjack/csharp/Player.cs similarity index 100% rename from 10 Blackjack/csharp/Player.cs rename to 10_Blackjack/csharp/Player.cs diff --git a/10 Blackjack/csharp/Program.cs b/10_Blackjack/csharp/Program.cs similarity index 100% rename from 10 Blackjack/csharp/Program.cs rename to 10_Blackjack/csharp/Program.cs diff --git a/10 Blackjack/csharp/Prompt.cs b/10_Blackjack/csharp/Prompt.cs similarity index 100% rename from 10 Blackjack/csharp/Prompt.cs rename to 10_Blackjack/csharp/Prompt.cs diff --git a/10 Blackjack/csharp/README.md b/10_Blackjack/csharp/README.md similarity index 100% rename from 10 Blackjack/csharp/README.md rename to 10_Blackjack/csharp/README.md diff --git a/10 Blackjack/java/README.md b/10_Blackjack/java/README.md similarity index 100% rename from 10 Blackjack/java/README.md rename to 10_Blackjack/java/README.md diff --git a/10 Blackjack/javascript/README.md b/10_Blackjack/javascript/README.md similarity index 100% rename from 10 Blackjack/javascript/README.md rename to 10_Blackjack/javascript/README.md diff --git a/10 Blackjack/javascript/blackjack.html b/10_Blackjack/javascript/blackjack.html similarity index 100% rename from 10 Blackjack/javascript/blackjack.html rename to 10_Blackjack/javascript/blackjack.html diff --git a/10 Blackjack/javascript/blackjack.js b/10_Blackjack/javascript/blackjack.js similarity index 100% rename from 10 Blackjack/javascript/blackjack.js rename to 10_Blackjack/javascript/blackjack.js diff --git a/10 Blackjack/pascal/README.md b/10_Blackjack/pascal/README.md similarity index 100% rename from 10 Blackjack/pascal/README.md rename to 10_Blackjack/pascal/README.md diff --git a/10 Blackjack/perl/README.md b/10_Blackjack/perl/README.md similarity index 100% rename from 10 Blackjack/perl/README.md rename to 10_Blackjack/perl/README.md diff --git a/10 Blackjack/python/README.md b/10_Blackjack/python/README.md similarity index 100% rename from 10 Blackjack/python/README.md rename to 10_Blackjack/python/README.md diff --git a/10 Blackjack/ruby/README.md b/10_Blackjack/ruby/README.md similarity index 100% rename from 10 Blackjack/ruby/README.md rename to 10_Blackjack/ruby/README.md diff --git a/10 Blackjack/vbnet/README.md b/10_Blackjack/vbnet/README.md similarity index 100% rename from 10 Blackjack/vbnet/README.md rename to 10_Blackjack/vbnet/README.md diff --git a/11 Bombardment/README.md b/11_Bombardment/README.md similarity index 100% rename from 11 Bombardment/README.md rename to 11_Bombardment/README.md diff --git a/11 Bombardment/bombardment.bas b/11_Bombardment/bombardment.bas similarity index 100% rename from 11 Bombardment/bombardment.bas rename to 11_Bombardment/bombardment.bas diff --git a/11 Bombardment/csharp/README.md b/11_Bombardment/csharp/README.md similarity index 100% rename from 11 Bombardment/csharp/README.md rename to 11_Bombardment/csharp/README.md diff --git a/11 Bombardment/java/README.md b/11_Bombardment/java/README.md similarity index 100% rename from 11 Bombardment/java/README.md rename to 11_Bombardment/java/README.md diff --git a/11 Bombardment/java/src/Bombardment.java b/11_Bombardment/java/src/Bombardment.java similarity index 100% rename from 11 Bombardment/java/src/Bombardment.java rename to 11_Bombardment/java/src/Bombardment.java diff --git a/11 Bombardment/java/src/BombardmentGame.java b/11_Bombardment/java/src/BombardmentGame.java similarity index 100% rename from 11 Bombardment/java/src/BombardmentGame.java rename to 11_Bombardment/java/src/BombardmentGame.java diff --git a/11 Bombardment/javascript/README.md b/11_Bombardment/javascript/README.md similarity index 100% rename from 11 Bombardment/javascript/README.md rename to 11_Bombardment/javascript/README.md diff --git a/11 Bombardment/javascript/bombardment.html b/11_Bombardment/javascript/bombardment.html similarity index 100% rename from 11 Bombardment/javascript/bombardment.html rename to 11_Bombardment/javascript/bombardment.html diff --git a/11 Bombardment/javascript/bombardment.js b/11_Bombardment/javascript/bombardment.js similarity index 100% rename from 11 Bombardment/javascript/bombardment.js rename to 11_Bombardment/javascript/bombardment.js diff --git a/11 Bombardment/pascal/README.md b/11_Bombardment/pascal/README.md similarity index 100% rename from 11 Bombardment/pascal/README.md rename to 11_Bombardment/pascal/README.md diff --git a/11 Bombardment/perl/README.md b/11_Bombardment/perl/README.md similarity index 100% rename from 11 Bombardment/perl/README.md rename to 11_Bombardment/perl/README.md diff --git a/11 Bombardment/python/README.md b/11_Bombardment/python/README.md similarity index 100% rename from 11 Bombardment/python/README.md rename to 11_Bombardment/python/README.md diff --git a/11 Bombardment/python/bombardment.py b/11_Bombardment/python/bombardment.py similarity index 100% rename from 11 Bombardment/python/bombardment.py rename to 11_Bombardment/python/bombardment.py diff --git a/11 Bombardment/ruby/README.md b/11_Bombardment/ruby/README.md similarity index 100% rename from 11 Bombardment/ruby/README.md rename to 11_Bombardment/ruby/README.md diff --git a/11 Bombardment/ruby/bombardment.rb b/11_Bombardment/ruby/bombardment.rb similarity index 100% rename from 11 Bombardment/ruby/bombardment.rb rename to 11_Bombardment/ruby/bombardment.rb diff --git a/11 Bombardment/vbnet/README.md b/11_Bombardment/vbnet/README.md similarity index 100% rename from 11 Bombardment/vbnet/README.md rename to 11_Bombardment/vbnet/README.md diff --git a/12 Bombs Away/README.md b/12_Bombs_Away/README.md similarity index 100% rename from 12 Bombs Away/README.md rename to 12_Bombs_Away/README.md diff --git a/12 Bombs Away/bombsaway.bas b/12_Bombs_Away/bombsaway.bas similarity index 100% rename from 12 Bombs Away/bombsaway.bas rename to 12_Bombs_Away/bombsaway.bas diff --git a/12 Bombs Away/csharp/README.md b/12_Bombs_Away/csharp/README.md similarity index 100% rename from 12 Bombs Away/csharp/README.md rename to 12_Bombs_Away/csharp/README.md diff --git a/12 Bombs Away/java/README.md b/12_Bombs_Away/java/README.md similarity index 100% rename from 12 Bombs Away/java/README.md rename to 12_Bombs_Away/java/README.md diff --git a/12 Bombs Away/java/src/BombsAway.java b/12_Bombs_Away/java/src/BombsAway.java similarity index 100% rename from 12 Bombs Away/java/src/BombsAway.java rename to 12_Bombs_Away/java/src/BombsAway.java diff --git a/12 Bombs Away/java/src/BombsAwayGame.java b/12_Bombs_Away/java/src/BombsAwayGame.java similarity index 100% rename from 12 Bombs Away/java/src/BombsAwayGame.java rename to 12_Bombs_Away/java/src/BombsAwayGame.java diff --git a/12 Bombs Away/javascript/README.md b/12_Bombs_Away/javascript/README.md similarity index 100% rename from 12 Bombs Away/javascript/README.md rename to 12_Bombs_Away/javascript/README.md diff --git a/12 Bombs Away/javascript/bombsaway.html b/12_Bombs_Away/javascript/bombsaway.html similarity index 100% rename from 12 Bombs Away/javascript/bombsaway.html rename to 12_Bombs_Away/javascript/bombsaway.html diff --git a/12 Bombs Away/javascript/bombsaway.js b/12_Bombs_Away/javascript/bombsaway.js similarity index 100% rename from 12 Bombs Away/javascript/bombsaway.js rename to 12_Bombs_Away/javascript/bombsaway.js diff --git a/12 Bombs Away/pascal/README.md b/12_Bombs_Away/pascal/README.md similarity index 100% rename from 12 Bombs Away/pascal/README.md rename to 12_Bombs_Away/pascal/README.md diff --git a/12 Bombs Away/perl/README.md b/12_Bombs_Away/perl/README.md similarity index 100% rename from 12 Bombs Away/perl/README.md rename to 12_Bombs_Away/perl/README.md diff --git a/12 Bombs Away/python/README.md b/12_Bombs_Away/python/README.md similarity index 100% rename from 12 Bombs Away/python/README.md rename to 12_Bombs_Away/python/README.md diff --git a/12 Bombs Away/ruby/README.md b/12_Bombs_Away/ruby/README.md similarity index 100% rename from 12 Bombs Away/ruby/README.md rename to 12_Bombs_Away/ruby/README.md diff --git a/12 Bombs Away/vbnet/README.md b/12_Bombs_Away/vbnet/README.md similarity index 100% rename from 12 Bombs Away/vbnet/README.md rename to 12_Bombs_Away/vbnet/README.md diff --git a/13 Bounce/README.md b/13_Bounce/README.md similarity index 100% rename from 13 Bounce/README.md rename to 13_Bounce/README.md diff --git a/13 Bounce/bounce.bas b/13_Bounce/bounce.bas similarity index 100% rename from 13 Bounce/bounce.bas rename to 13_Bounce/bounce.bas diff --git a/13 Bounce/csharp/README.md b/13_Bounce/csharp/README.md similarity index 100% rename from 13 Bounce/csharp/README.md rename to 13_Bounce/csharp/README.md diff --git a/13 Bounce/java/Bounce.java b/13_Bounce/java/Bounce.java similarity index 100% rename from 13 Bounce/java/Bounce.java rename to 13_Bounce/java/Bounce.java diff --git a/13 Bounce/java/README.md b/13_Bounce/java/README.md similarity index 100% rename from 13 Bounce/java/README.md rename to 13_Bounce/java/README.md diff --git a/13 Bounce/javascript/README.md b/13_Bounce/javascript/README.md similarity index 100% rename from 13 Bounce/javascript/README.md rename to 13_Bounce/javascript/README.md diff --git a/13 Bounce/javascript/bounce.html b/13_Bounce/javascript/bounce.html similarity index 100% rename from 13 Bounce/javascript/bounce.html rename to 13_Bounce/javascript/bounce.html diff --git a/13 Bounce/javascript/bounce.js b/13_Bounce/javascript/bounce.js similarity index 100% rename from 13 Bounce/javascript/bounce.js rename to 13_Bounce/javascript/bounce.js diff --git a/13 Bounce/pascal/README.md b/13_Bounce/pascal/README.md similarity index 100% rename from 13 Bounce/pascal/README.md rename to 13_Bounce/pascal/README.md diff --git a/13 Bounce/perl/README.md b/13_Bounce/perl/README.md similarity index 100% rename from 13 Bounce/perl/README.md rename to 13_Bounce/perl/README.md diff --git a/13 Bounce/python/README.md b/13_Bounce/python/README.md similarity index 100% rename from 13 Bounce/python/README.md rename to 13_Bounce/python/README.md diff --git a/13 Bounce/python/bounce.py b/13_Bounce/python/bounce.py similarity index 100% rename from 13 Bounce/python/bounce.py rename to 13_Bounce/python/bounce.py diff --git a/13 Bounce/ruby/README.md b/13_Bounce/ruby/README.md similarity index 100% rename from 13 Bounce/ruby/README.md rename to 13_Bounce/ruby/README.md diff --git a/13 Bounce/vbnet/README.md b/13_Bounce/vbnet/README.md similarity index 100% rename from 13 Bounce/vbnet/README.md rename to 13_Bounce/vbnet/README.md diff --git a/14 Bowling/README.md b/14_Bowling/README.md similarity index 100% rename from 14 Bowling/README.md rename to 14_Bowling/README.md diff --git a/14 Bowling/bowling.bas b/14_Bowling/bowling.bas similarity index 100% rename from 14 Bowling/bowling.bas rename to 14_Bowling/bowling.bas diff --git a/14 Bowling/csharp/README.md b/14_Bowling/csharp/README.md similarity index 100% rename from 14 Bowling/csharp/README.md rename to 14_Bowling/csharp/README.md diff --git a/14 Bowling/java/Bowling.java b/14_Bowling/java/Bowling.java similarity index 100% rename from 14 Bowling/java/Bowling.java rename to 14_Bowling/java/Bowling.java diff --git a/14 Bowling/java/README.md b/14_Bowling/java/README.md similarity index 100% rename from 14 Bowling/java/README.md rename to 14_Bowling/java/README.md diff --git a/14 Bowling/javascript/README.md b/14_Bowling/javascript/README.md similarity index 100% rename from 14 Bowling/javascript/README.md rename to 14_Bowling/javascript/README.md diff --git a/14 Bowling/javascript/bowling.html b/14_Bowling/javascript/bowling.html similarity index 100% rename from 14 Bowling/javascript/bowling.html rename to 14_Bowling/javascript/bowling.html diff --git a/14 Bowling/javascript/bowling.js b/14_Bowling/javascript/bowling.js similarity index 100% rename from 14 Bowling/javascript/bowling.js rename to 14_Bowling/javascript/bowling.js diff --git a/14 Bowling/pascal/README.md b/14_Bowling/pascal/README.md similarity index 100% rename from 14 Bowling/pascal/README.md rename to 14_Bowling/pascal/README.md diff --git a/14 Bowling/perl/README.md b/14_Bowling/perl/README.md similarity index 100% rename from 14 Bowling/perl/README.md rename to 14_Bowling/perl/README.md diff --git a/14 Bowling/python/README.md b/14_Bowling/python/README.md similarity index 100% rename from 14 Bowling/python/README.md rename to 14_Bowling/python/README.md diff --git a/14 Bowling/python/bowling.py b/14_Bowling/python/bowling.py similarity index 100% rename from 14 Bowling/python/bowling.py rename to 14_Bowling/python/bowling.py diff --git a/14 Bowling/ruby/README.md b/14_Bowling/ruby/README.md similarity index 100% rename from 14 Bowling/ruby/README.md rename to 14_Bowling/ruby/README.md diff --git a/14 Bowling/vbnet/README.md b/14_Bowling/vbnet/README.md similarity index 100% rename from 14 Bowling/vbnet/README.md rename to 14_Bowling/vbnet/README.md diff --git a/15 Boxing/README.md b/15_Boxing/README.md similarity index 100% rename from 15 Boxing/README.md rename to 15_Boxing/README.md diff --git a/15 Boxing/boxing.bas b/15_Boxing/boxing.bas similarity index 100% rename from 15 Boxing/boxing.bas rename to 15_Boxing/boxing.bas diff --git a/15 Boxing/csharp/README.md b/15_Boxing/csharp/README.md similarity index 100% rename from 15 Boxing/csharp/README.md rename to 15_Boxing/csharp/README.md diff --git a/15 Boxing/java/Basic.java b/15_Boxing/java/Basic.java similarity index 100% rename from 15 Boxing/java/Basic.java rename to 15_Boxing/java/Basic.java diff --git a/15 Boxing/java/Boxing.java b/15_Boxing/java/Boxing.java similarity index 100% rename from 15 Boxing/java/Boxing.java rename to 15_Boxing/java/Boxing.java diff --git a/15 Boxing/java/BoxingGame.java b/15_Boxing/java/BoxingGame.java similarity index 100% rename from 15 Boxing/java/BoxingGame.java rename to 15_Boxing/java/BoxingGame.java diff --git a/15 Boxing/java/GameSession.java b/15_Boxing/java/GameSession.java similarity index 100% rename from 15 Boxing/java/GameSession.java rename to 15_Boxing/java/GameSession.java diff --git a/15 Boxing/java/Player.java b/15_Boxing/java/Player.java similarity index 100% rename from 15 Boxing/java/Player.java rename to 15_Boxing/java/Player.java diff --git a/15 Boxing/java/Punch.java b/15_Boxing/java/Punch.java similarity index 100% rename from 15 Boxing/java/Punch.java rename to 15_Boxing/java/Punch.java diff --git a/15 Boxing/java/README.md b/15_Boxing/java/README.md similarity index 100% rename from 15 Boxing/java/README.md rename to 15_Boxing/java/README.md diff --git a/15 Boxing/javascript/README.md b/15_Boxing/javascript/README.md similarity index 100% rename from 15 Boxing/javascript/README.md rename to 15_Boxing/javascript/README.md diff --git a/15 Boxing/javascript/boxing.html b/15_Boxing/javascript/boxing.html similarity index 100% rename from 15 Boxing/javascript/boxing.html rename to 15_Boxing/javascript/boxing.html diff --git a/15 Boxing/javascript/boxing.js b/15_Boxing/javascript/boxing.js similarity index 100% rename from 15 Boxing/javascript/boxing.js rename to 15_Boxing/javascript/boxing.js diff --git a/15 Boxing/pascal/README.md b/15_Boxing/pascal/README.md similarity index 100% rename from 15 Boxing/pascal/README.md rename to 15_Boxing/pascal/README.md diff --git a/15 Boxing/perl/README.md b/15_Boxing/perl/README.md similarity index 100% rename from 15 Boxing/perl/README.md rename to 15_Boxing/perl/README.md diff --git a/15 Boxing/python/README.md b/15_Boxing/python/README.md similarity index 100% rename from 15 Boxing/python/README.md rename to 15_Boxing/python/README.md diff --git a/15 Boxing/python/boxing.py b/15_Boxing/python/boxing.py similarity index 100% rename from 15 Boxing/python/boxing.py rename to 15_Boxing/python/boxing.py diff --git a/15 Boxing/ruby/README.md b/15_Boxing/ruby/README.md similarity index 100% rename from 15 Boxing/ruby/README.md rename to 15_Boxing/ruby/README.md diff --git a/15 Boxing/vbnet/README.md b/15_Boxing/vbnet/README.md similarity index 100% rename from 15 Boxing/vbnet/README.md rename to 15_Boxing/vbnet/README.md diff --git a/16 Bug/README.md b/16_Bug/README.md similarity index 100% rename from 16 Bug/README.md rename to 16_Bug/README.md diff --git a/16 Bug/bug.bas b/16_Bug/bug.bas similarity index 100% rename from 16 Bug/bug.bas rename to 16_Bug/bug.bas diff --git a/16 Bug/csharp/README.md b/16_Bug/csharp/README.md similarity index 100% rename from 16 Bug/csharp/README.md rename to 16_Bug/csharp/README.md diff --git a/16 Bug/java/README.md b/16_Bug/java/README.md similarity index 100% rename from 16 Bug/java/README.md rename to 16_Bug/java/README.md diff --git a/16 Bug/java/src/Bug.java b/16_Bug/java/src/Bug.java similarity index 100% rename from 16 Bug/java/src/Bug.java rename to 16_Bug/java/src/Bug.java diff --git a/16 Bug/java/src/BugGame.java b/16_Bug/java/src/BugGame.java similarity index 100% rename from 16 Bug/java/src/BugGame.java rename to 16_Bug/java/src/BugGame.java diff --git a/16 Bug/java/src/ComputerBug.java b/16_Bug/java/src/ComputerBug.java similarity index 100% rename from 16 Bug/java/src/ComputerBug.java rename to 16_Bug/java/src/ComputerBug.java diff --git a/16 Bug/java/src/Insect.java b/16_Bug/java/src/Insect.java similarity index 100% rename from 16 Bug/java/src/Insect.java rename to 16_Bug/java/src/Insect.java diff --git a/16 Bug/java/src/PlayerBug.java b/16_Bug/java/src/PlayerBug.java similarity index 100% rename from 16 Bug/java/src/PlayerBug.java rename to 16_Bug/java/src/PlayerBug.java diff --git a/16 Bug/javascript/README.md b/16_Bug/javascript/README.md similarity index 100% rename from 16 Bug/javascript/README.md rename to 16_Bug/javascript/README.md diff --git a/16 Bug/javascript/bug.html b/16_Bug/javascript/bug.html similarity index 100% rename from 16 Bug/javascript/bug.html rename to 16_Bug/javascript/bug.html diff --git a/16 Bug/javascript/bug.js b/16_Bug/javascript/bug.js similarity index 100% rename from 16 Bug/javascript/bug.js rename to 16_Bug/javascript/bug.js diff --git a/16 Bug/pascal/README.md b/16_Bug/pascal/README.md similarity index 100% rename from 16 Bug/pascal/README.md rename to 16_Bug/pascal/README.md diff --git a/16 Bug/perl/README.md b/16_Bug/perl/README.md similarity index 100% rename from 16 Bug/perl/README.md rename to 16_Bug/perl/README.md diff --git a/16 Bug/python/README.md b/16_Bug/python/README.md similarity index 100% rename from 16 Bug/python/README.md rename to 16_Bug/python/README.md diff --git a/16 Bug/ruby/README.md b/16_Bug/ruby/README.md similarity index 100% rename from 16 Bug/ruby/README.md rename to 16_Bug/ruby/README.md diff --git a/16 Bug/vbnet/README.md b/16_Bug/vbnet/README.md similarity index 100% rename from 16 Bug/vbnet/README.md rename to 16_Bug/vbnet/README.md diff --git a/17 Bullfight/README.md b/17_Bullfight/README.md similarity index 100% rename from 17 Bullfight/README.md rename to 17_Bullfight/README.md diff --git a/17 Bullfight/bullfight.bas b/17_Bullfight/bullfight.bas similarity index 100% rename from 17 Bullfight/bullfight.bas rename to 17_Bullfight/bullfight.bas diff --git a/17 Bullfight/csharp/Bullfight.sln b/17_Bullfight/csharp/Bullfight.sln similarity index 100% rename from 17 Bullfight/csharp/Bullfight.sln rename to 17_Bullfight/csharp/Bullfight.sln diff --git a/17 Bullfight/csharp/Game.csproj b/17_Bullfight/csharp/Game.csproj similarity index 100% rename from 17 Bullfight/csharp/Game.csproj rename to 17_Bullfight/csharp/Game.csproj diff --git a/17 Bullfight/csharp/README.md b/17_Bullfight/csharp/README.md similarity index 100% rename from 17 Bullfight/csharp/README.md rename to 17_Bullfight/csharp/README.md diff --git a/17 Bullfight/csharp/src/Action.cs b/17_Bullfight/csharp/src/Action.cs similarity index 100% rename from 17 Bullfight/csharp/src/Action.cs rename to 17_Bullfight/csharp/src/Action.cs diff --git a/17 Bullfight/csharp/src/ActionResult.cs b/17_Bullfight/csharp/src/ActionResult.cs similarity index 100% rename from 17 Bullfight/csharp/src/ActionResult.cs rename to 17_Bullfight/csharp/src/ActionResult.cs diff --git a/17 Bullfight/csharp/src/BullFight.cs b/17_Bullfight/csharp/src/BullFight.cs similarity index 100% rename from 17 Bullfight/csharp/src/BullFight.cs rename to 17_Bullfight/csharp/src/BullFight.cs diff --git a/17 Bullfight/csharp/src/Controller.cs b/17_Bullfight/csharp/src/Controller.cs similarity index 100% rename from 17 Bullfight/csharp/src/Controller.cs rename to 17_Bullfight/csharp/src/Controller.cs diff --git a/17 Bullfight/csharp/src/Events/BullCharging.cs b/17_Bullfight/csharp/src/Events/BullCharging.cs similarity index 100% rename from 17 Bullfight/csharp/src/Events/BullCharging.cs rename to 17_Bullfight/csharp/src/Events/BullCharging.cs diff --git a/17 Bullfight/csharp/src/Events/Event.cs b/17_Bullfight/csharp/src/Events/Event.cs similarity index 100% rename from 17 Bullfight/csharp/src/Events/Event.cs rename to 17_Bullfight/csharp/src/Events/Event.cs diff --git a/17 Bullfight/csharp/src/Events/MatchCompleted.cs b/17_Bullfight/csharp/src/Events/MatchCompleted.cs similarity index 100% rename from 17 Bullfight/csharp/src/Events/MatchCompleted.cs rename to 17_Bullfight/csharp/src/Events/MatchCompleted.cs diff --git a/17 Bullfight/csharp/src/Events/MatchStarted.cs b/17_Bullfight/csharp/src/Events/MatchStarted.cs similarity index 100% rename from 17 Bullfight/csharp/src/Events/MatchStarted.cs rename to 17_Bullfight/csharp/src/Events/MatchStarted.cs diff --git a/17 Bullfight/csharp/src/Events/PlayerGored.cs b/17_Bullfight/csharp/src/Events/PlayerGored.cs similarity index 100% rename from 17 Bullfight/csharp/src/Events/PlayerGored.cs rename to 17_Bullfight/csharp/src/Events/PlayerGored.cs diff --git a/17 Bullfight/csharp/src/Events/PlayerSurvived.cs b/17_Bullfight/csharp/src/Events/PlayerSurvived.cs similarity index 100% rename from 17 Bullfight/csharp/src/Events/PlayerSurvived.cs rename to 17_Bullfight/csharp/src/Events/PlayerSurvived.cs diff --git a/17 Bullfight/csharp/src/Mediator.cs b/17_Bullfight/csharp/src/Mediator.cs similarity index 100% rename from 17 Bullfight/csharp/src/Mediator.cs rename to 17_Bullfight/csharp/src/Mediator.cs diff --git a/17 Bullfight/csharp/src/Program.cs b/17_Bullfight/csharp/src/Program.cs similarity index 100% rename from 17 Bullfight/csharp/src/Program.cs rename to 17_Bullfight/csharp/src/Program.cs diff --git a/17 Bullfight/csharp/src/Quality.cs b/17_Bullfight/csharp/src/Quality.cs similarity index 100% rename from 17 Bullfight/csharp/src/Quality.cs rename to 17_Bullfight/csharp/src/Quality.cs diff --git a/17 Bullfight/csharp/src/Reward.cs b/17_Bullfight/csharp/src/Reward.cs similarity index 100% rename from 17 Bullfight/csharp/src/Reward.cs rename to 17_Bullfight/csharp/src/Reward.cs diff --git a/17 Bullfight/csharp/src/RiskLevel.cs b/17_Bullfight/csharp/src/RiskLevel.cs similarity index 100% rename from 17 Bullfight/csharp/src/RiskLevel.cs rename to 17_Bullfight/csharp/src/RiskLevel.cs diff --git a/17 Bullfight/csharp/src/View.cs b/17_Bullfight/csharp/src/View.cs similarity index 100% rename from 17 Bullfight/csharp/src/View.cs rename to 17_Bullfight/csharp/src/View.cs diff --git a/17 Bullfight/java/README.md b/17_Bullfight/java/README.md similarity index 100% rename from 17 Bullfight/java/README.md rename to 17_Bullfight/java/README.md diff --git a/17 Bullfight/javascript/README.md b/17_Bullfight/javascript/README.md similarity index 100% rename from 17 Bullfight/javascript/README.md rename to 17_Bullfight/javascript/README.md diff --git a/17 Bullfight/javascript/bullfight.html b/17_Bullfight/javascript/bullfight.html similarity index 100% rename from 17 Bullfight/javascript/bullfight.html rename to 17_Bullfight/javascript/bullfight.html diff --git a/17 Bullfight/javascript/bullfight.js b/17_Bullfight/javascript/bullfight.js similarity index 100% rename from 17 Bullfight/javascript/bullfight.js rename to 17_Bullfight/javascript/bullfight.js diff --git a/17 Bullfight/pascal/README.md b/17_Bullfight/pascal/README.md similarity index 100% rename from 17 Bullfight/pascal/README.md rename to 17_Bullfight/pascal/README.md diff --git a/17 Bullfight/perl/README.md b/17_Bullfight/perl/README.md similarity index 100% rename from 17 Bullfight/perl/README.md rename to 17_Bullfight/perl/README.md diff --git a/17 Bullfight/python/README.md b/17_Bullfight/python/README.md similarity index 100% rename from 17 Bullfight/python/README.md rename to 17_Bullfight/python/README.md diff --git a/17 Bullfight/ruby/README.md b/17_Bullfight/ruby/README.md similarity index 100% rename from 17 Bullfight/ruby/README.md rename to 17_Bullfight/ruby/README.md diff --git a/17 Bullfight/vbnet/README.md b/17_Bullfight/vbnet/README.md similarity index 100% rename from 17 Bullfight/vbnet/README.md rename to 17_Bullfight/vbnet/README.md diff --git a/18 Bullseye/README.md b/18_Bullseye/README.md similarity index 100% rename from 18 Bullseye/README.md rename to 18_Bullseye/README.md diff --git a/18 Bullseye/bullseye.bas b/18_Bullseye/bullseye.bas similarity index 100% rename from 18 Bullseye/bullseye.bas rename to 18_Bullseye/bullseye.bas diff --git a/18 Bullseye/csharp/README.md b/18_Bullseye/csharp/README.md similarity index 100% rename from 18 Bullseye/csharp/README.md rename to 18_Bullseye/csharp/README.md diff --git a/18 Bullseye/java/README.md b/18_Bullseye/java/README.md similarity index 100% rename from 18 Bullseye/java/README.md rename to 18_Bullseye/java/README.md diff --git a/18 Bullseye/java/src/Bullseye.java b/18_Bullseye/java/src/Bullseye.java similarity index 100% rename from 18 Bullseye/java/src/Bullseye.java rename to 18_Bullseye/java/src/Bullseye.java diff --git a/18 Bullseye/java/src/BullseyeGame.java b/18_Bullseye/java/src/BullseyeGame.java similarity index 100% rename from 18 Bullseye/java/src/BullseyeGame.java rename to 18_Bullseye/java/src/BullseyeGame.java diff --git a/18 Bullseye/java/src/Player.java b/18_Bullseye/java/src/Player.java similarity index 100% rename from 18 Bullseye/java/src/Player.java rename to 18_Bullseye/java/src/Player.java diff --git a/18 Bullseye/java/src/Shot.java b/18_Bullseye/java/src/Shot.java similarity index 100% rename from 18 Bullseye/java/src/Shot.java rename to 18_Bullseye/java/src/Shot.java diff --git a/18 Bullseye/javascript/README.md b/18_Bullseye/javascript/README.md similarity index 100% rename from 18 Bullseye/javascript/README.md rename to 18_Bullseye/javascript/README.md diff --git a/18 Bullseye/javascript/bullseye.html b/18_Bullseye/javascript/bullseye.html similarity index 100% rename from 18 Bullseye/javascript/bullseye.html rename to 18_Bullseye/javascript/bullseye.html diff --git a/18 Bullseye/javascript/bullseye.js b/18_Bullseye/javascript/bullseye.js similarity index 100% rename from 18 Bullseye/javascript/bullseye.js rename to 18_Bullseye/javascript/bullseye.js diff --git a/18 Bullseye/pascal/README.md b/18_Bullseye/pascal/README.md similarity index 100% rename from 18 Bullseye/pascal/README.md rename to 18_Bullseye/pascal/README.md diff --git a/18 Bullseye/perl/README.md b/18_Bullseye/perl/README.md similarity index 100% rename from 18 Bullseye/perl/README.md rename to 18_Bullseye/perl/README.md diff --git a/18 Bullseye/perl/bullseye.pl b/18_Bullseye/perl/bullseye.pl similarity index 100% rename from 18 Bullseye/perl/bullseye.pl rename to 18_Bullseye/perl/bullseye.pl diff --git a/18 Bullseye/python/README.md b/18_Bullseye/python/README.md similarity index 100% rename from 18 Bullseye/python/README.md rename to 18_Bullseye/python/README.md diff --git a/18 Bullseye/ruby/README.md b/18_Bullseye/ruby/README.md similarity index 100% rename from 18 Bullseye/ruby/README.md rename to 18_Bullseye/ruby/README.md diff --git a/18 Bullseye/vbnet/README.md b/18_Bullseye/vbnet/README.md similarity index 100% rename from 18 Bullseye/vbnet/README.md rename to 18_Bullseye/vbnet/README.md diff --git a/19 Bunny/README.md b/19_Bunny/README.md similarity index 100% rename from 19 Bunny/README.md rename to 19_Bunny/README.md diff --git a/19 Bunny/bunny.bas b/19_Bunny/bunny.bas similarity index 100% rename from 19 Bunny/bunny.bas rename to 19_Bunny/bunny.bas diff --git a/19 Bunny/csharp/README.md b/19_Bunny/csharp/README.md similarity index 100% rename from 19 Bunny/csharp/README.md rename to 19_Bunny/csharp/README.md diff --git a/19 Bunny/java/README.md b/19_Bunny/java/README.md similarity index 100% rename from 19 Bunny/java/README.md rename to 19_Bunny/java/README.md diff --git a/19 Bunny/java/src/Bunny.java b/19_Bunny/java/src/Bunny.java similarity index 100% rename from 19 Bunny/java/src/Bunny.java rename to 19_Bunny/java/src/Bunny.java diff --git a/19 Bunny/javascript/README.md b/19_Bunny/javascript/README.md similarity index 100% rename from 19 Bunny/javascript/README.md rename to 19_Bunny/javascript/README.md diff --git a/19 Bunny/javascript/bunny.html b/19_Bunny/javascript/bunny.html similarity index 100% rename from 19 Bunny/javascript/bunny.html rename to 19_Bunny/javascript/bunny.html diff --git a/19 Bunny/javascript/bunny.js b/19_Bunny/javascript/bunny.js similarity index 100% rename from 19 Bunny/javascript/bunny.js rename to 19_Bunny/javascript/bunny.js diff --git a/19 Bunny/pascal/README.md b/19_Bunny/pascal/README.md similarity index 100% rename from 19 Bunny/pascal/README.md rename to 19_Bunny/pascal/README.md diff --git a/19 Bunny/perl/README.md b/19_Bunny/perl/README.md similarity index 100% rename from 19 Bunny/perl/README.md rename to 19_Bunny/perl/README.md diff --git a/19 Bunny/perl/bunny.pl b/19_Bunny/perl/bunny.pl similarity index 100% rename from 19 Bunny/perl/bunny.pl rename to 19_Bunny/perl/bunny.pl diff --git a/19 Bunny/python/README.md b/19_Bunny/python/README.md similarity index 100% rename from 19 Bunny/python/README.md rename to 19_Bunny/python/README.md diff --git a/19 Bunny/python/bunny.py b/19_Bunny/python/bunny.py similarity index 100% rename from 19 Bunny/python/bunny.py rename to 19_Bunny/python/bunny.py diff --git a/19 Bunny/ruby/README.md b/19_Bunny/ruby/README.md similarity index 100% rename from 19 Bunny/ruby/README.md rename to 19_Bunny/ruby/README.md diff --git a/19 Bunny/ruby/bunny-faithful.rb b/19_Bunny/ruby/bunny-faithful.rb similarity index 100% rename from 19 Bunny/ruby/bunny-faithful.rb rename to 19_Bunny/ruby/bunny-faithful.rb diff --git a/19 Bunny/ruby/bunny-modern.rb b/19_Bunny/ruby/bunny-modern.rb similarity index 100% rename from 19 Bunny/ruby/bunny-modern.rb rename to 19_Bunny/ruby/bunny-modern.rb diff --git a/19 Bunny/vbnet/README.md b/19_Bunny/vbnet/README.md similarity index 100% rename from 19 Bunny/vbnet/README.md rename to 19_Bunny/vbnet/README.md diff --git a/20 Buzzword/README.md b/20_Buzzword/README.md similarity index 100% rename from 20 Buzzword/README.md rename to 20_Buzzword/README.md diff --git a/20 Buzzword/buzzword.bas b/20_Buzzword/buzzword.bas similarity index 100% rename from 20 Buzzword/buzzword.bas rename to 20_Buzzword/buzzword.bas diff --git a/20 Buzzword/csharp/README.md b/20_Buzzword/csharp/README.md similarity index 100% rename from 20 Buzzword/csharp/README.md rename to 20_Buzzword/csharp/README.md diff --git a/20 Buzzword/java/README.md b/20_Buzzword/java/README.md similarity index 100% rename from 20 Buzzword/java/README.md rename to 20_Buzzword/java/README.md diff --git a/20 Buzzword/java/src/Buzzword.java b/20_Buzzword/java/src/Buzzword.java similarity index 100% rename from 20 Buzzword/java/src/Buzzword.java rename to 20_Buzzword/java/src/Buzzword.java diff --git a/20 Buzzword/javascript/README.md b/20_Buzzword/javascript/README.md similarity index 100% rename from 20 Buzzword/javascript/README.md rename to 20_Buzzword/javascript/README.md diff --git a/20 Buzzword/javascript/buzzword.html b/20_Buzzword/javascript/buzzword.html similarity index 100% rename from 20 Buzzword/javascript/buzzword.html rename to 20_Buzzword/javascript/buzzword.html diff --git a/20 Buzzword/javascript/buzzword.js b/20_Buzzword/javascript/buzzword.js similarity index 100% rename from 20 Buzzword/javascript/buzzword.js rename to 20_Buzzword/javascript/buzzword.js diff --git a/20 Buzzword/pascal/README.md b/20_Buzzword/pascal/README.md similarity index 100% rename from 20 Buzzword/pascal/README.md rename to 20_Buzzword/pascal/README.md diff --git a/20 Buzzword/perl/README.md b/20_Buzzword/perl/README.md similarity index 100% rename from 20 Buzzword/perl/README.md rename to 20_Buzzword/perl/README.md diff --git a/20 Buzzword/perl/buzzword.pl b/20_Buzzword/perl/buzzword.pl similarity index 100% rename from 20 Buzzword/perl/buzzword.pl rename to 20_Buzzword/perl/buzzword.pl diff --git a/20 Buzzword/python/README.md b/20_Buzzword/python/README.md similarity index 100% rename from 20 Buzzword/python/README.md rename to 20_Buzzword/python/README.md diff --git a/20 Buzzword/python/buzzword.py b/20_Buzzword/python/buzzword.py similarity index 100% rename from 20 Buzzword/python/buzzword.py rename to 20_Buzzword/python/buzzword.py diff --git a/20 Buzzword/ruby/README.md b/20_Buzzword/ruby/README.md similarity index 100% rename from 20 Buzzword/ruby/README.md rename to 20_Buzzword/ruby/README.md diff --git a/20 Buzzword/ruby/buzzword.rb b/20_Buzzword/ruby/buzzword.rb similarity index 100% rename from 20 Buzzword/ruby/buzzword.rb rename to 20_Buzzword/ruby/buzzword.rb diff --git a/20 Buzzword/vbnet/README.md b/20_Buzzword/vbnet/README.md similarity index 100% rename from 20 Buzzword/vbnet/README.md rename to 20_Buzzword/vbnet/README.md diff --git a/21 Calendar/README.md b/21_Calendar/README.md similarity index 100% rename from 21 Calendar/README.md rename to 21_Calendar/README.md diff --git a/21 Calendar/calendar.bas b/21_Calendar/calendar.bas similarity index 100% rename from 21 Calendar/calendar.bas rename to 21_Calendar/calendar.bas diff --git a/21 Calendar/csharp/README.md b/21_Calendar/csharp/README.md similarity index 100% rename from 21 Calendar/csharp/README.md rename to 21_Calendar/csharp/README.md diff --git a/21 Calendar/java/Calendar.java b/21_Calendar/java/Calendar.java similarity index 100% rename from 21 Calendar/java/Calendar.java rename to 21_Calendar/java/Calendar.java diff --git a/21 Calendar/java/README.md b/21_Calendar/java/README.md similarity index 100% rename from 21 Calendar/java/README.md rename to 21_Calendar/java/README.md diff --git a/21 Calendar/javascript/README.md b/21_Calendar/javascript/README.md similarity index 100% rename from 21 Calendar/javascript/README.md rename to 21_Calendar/javascript/README.md diff --git a/21 Calendar/javascript/calendar.html b/21_Calendar/javascript/calendar.html similarity index 100% rename from 21 Calendar/javascript/calendar.html rename to 21_Calendar/javascript/calendar.html diff --git a/21 Calendar/javascript/calendar.js b/21_Calendar/javascript/calendar.js similarity index 100% rename from 21 Calendar/javascript/calendar.js rename to 21_Calendar/javascript/calendar.js diff --git a/21 Calendar/pascal/README.md b/21_Calendar/pascal/README.md similarity index 100% rename from 21 Calendar/pascal/README.md rename to 21_Calendar/pascal/README.md diff --git a/21 Calendar/perl/README.md b/21_Calendar/perl/README.md similarity index 100% rename from 21 Calendar/perl/README.md rename to 21_Calendar/perl/README.md diff --git a/21 Calendar/python/README.md b/21_Calendar/python/README.md similarity index 100% rename from 21 Calendar/python/README.md rename to 21_Calendar/python/README.md diff --git a/21 Calendar/ruby/README.md b/21_Calendar/ruby/README.md similarity index 100% rename from 21 Calendar/ruby/README.md rename to 21_Calendar/ruby/README.md diff --git a/21 Calendar/vbnet/README.md b/21_Calendar/vbnet/README.md similarity index 100% rename from 21 Calendar/vbnet/README.md rename to 21_Calendar/vbnet/README.md diff --git a/22 Change/README.md b/22_Change/README.md similarity index 100% rename from 22 Change/README.md rename to 22_Change/README.md diff --git a/22 Change/change.bas b/22_Change/change.bas similarity index 100% rename from 22 Change/change.bas rename to 22_Change/change.bas diff --git a/22 Change/csharp/README.md b/22_Change/csharp/README.md similarity index 100% rename from 22 Change/csharp/README.md rename to 22_Change/csharp/README.md diff --git a/22 Change/java/README.md b/22_Change/java/README.md similarity index 100% rename from 22 Change/java/README.md rename to 22_Change/java/README.md diff --git a/22 Change/java/src/Change.java b/22_Change/java/src/Change.java similarity index 100% rename from 22 Change/java/src/Change.java rename to 22_Change/java/src/Change.java diff --git a/22 Change/java/src/ChangeGame.java b/22_Change/java/src/ChangeGame.java similarity index 100% rename from 22 Change/java/src/ChangeGame.java rename to 22_Change/java/src/ChangeGame.java diff --git a/22 Change/javascript/README.md b/22_Change/javascript/README.md similarity index 100% rename from 22 Change/javascript/README.md rename to 22_Change/javascript/README.md diff --git a/22 Change/javascript/change.html b/22_Change/javascript/change.html similarity index 100% rename from 22 Change/javascript/change.html rename to 22_Change/javascript/change.html diff --git a/22 Change/javascript/change.js b/22_Change/javascript/change.js similarity index 100% rename from 22 Change/javascript/change.js rename to 22_Change/javascript/change.js diff --git a/22 Change/pascal/README.md b/22_Change/pascal/README.md similarity index 100% rename from 22 Change/pascal/README.md rename to 22_Change/pascal/README.md diff --git a/22 Change/perl/README.md b/22_Change/perl/README.md similarity index 100% rename from 22 Change/perl/README.md rename to 22_Change/perl/README.md diff --git a/22 Change/python/README.md b/22_Change/python/README.md similarity index 100% rename from 22 Change/python/README.md rename to 22_Change/python/README.md diff --git a/22 Change/python/change.py b/22_Change/python/change.py similarity index 100% rename from 22 Change/python/change.py rename to 22_Change/python/change.py diff --git a/22 Change/ruby/README.md b/22_Change/ruby/README.md similarity index 100% rename from 22 Change/ruby/README.md rename to 22_Change/ruby/README.md diff --git a/22 Change/vbnet/README.md b/22_Change/vbnet/README.md similarity index 100% rename from 22 Change/vbnet/README.md rename to 22_Change/vbnet/README.md diff --git a/23 Checkers/README.md b/23_Checkers/README.md similarity index 100% rename from 23 Checkers/README.md rename to 23_Checkers/README.md diff --git a/23 Checkers/checkers.annotated.bas b/23_Checkers/checkers.annotated.bas similarity index 100% rename from 23 Checkers/checkers.annotated.bas rename to 23_Checkers/checkers.annotated.bas diff --git a/23 Checkers/checkers.bas b/23_Checkers/checkers.bas similarity index 100% rename from 23 Checkers/checkers.bas rename to 23_Checkers/checkers.bas diff --git a/23 Checkers/csharp/README.md b/23_Checkers/csharp/README.md similarity index 100% rename from 23 Checkers/csharp/README.md rename to 23_Checkers/csharp/README.md diff --git a/23 Checkers/java/README.md b/23_Checkers/java/README.md similarity index 100% rename from 23 Checkers/java/README.md rename to 23_Checkers/java/README.md diff --git a/23 Checkers/javascript/README.md b/23_Checkers/javascript/README.md similarity index 100% rename from 23 Checkers/javascript/README.md rename to 23_Checkers/javascript/README.md diff --git a/23 Checkers/javascript/checkers.html b/23_Checkers/javascript/checkers.html similarity index 100% rename from 23 Checkers/javascript/checkers.html rename to 23_Checkers/javascript/checkers.html diff --git a/23 Checkers/javascript/checkers.js b/23_Checkers/javascript/checkers.js similarity index 100% rename from 23 Checkers/javascript/checkers.js rename to 23_Checkers/javascript/checkers.js diff --git a/23 Checkers/pascal/README.md b/23_Checkers/pascal/README.md similarity index 100% rename from 23 Checkers/pascal/README.md rename to 23_Checkers/pascal/README.md diff --git a/23 Checkers/perl/README.md b/23_Checkers/perl/README.md similarity index 100% rename from 23 Checkers/perl/README.md rename to 23_Checkers/perl/README.md diff --git a/23 Checkers/python/README.md b/23_Checkers/python/README.md similarity index 100% rename from 23 Checkers/python/README.md rename to 23_Checkers/python/README.md diff --git a/23 Checkers/python/checkers.py b/23_Checkers/python/checkers.py similarity index 100% rename from 23 Checkers/python/checkers.py rename to 23_Checkers/python/checkers.py diff --git a/23 Checkers/ruby/README.md b/23_Checkers/ruby/README.md similarity index 100% rename from 23 Checkers/ruby/README.md rename to 23_Checkers/ruby/README.md diff --git a/23 Checkers/ruby/checkers.rb b/23_Checkers/ruby/checkers.rb similarity index 100% rename from 23 Checkers/ruby/checkers.rb rename to 23_Checkers/ruby/checkers.rb diff --git a/23 Checkers/vbnet/README.md b/23_Checkers/vbnet/README.md similarity index 100% rename from 23 Checkers/vbnet/README.md rename to 23_Checkers/vbnet/README.md diff --git a/24 Chemist/README.md b/24_Chemist/README.md similarity index 100% rename from 24 Chemist/README.md rename to 24_Chemist/README.md diff --git a/24 Chemist/chemist.bas b/24_Chemist/chemist.bas similarity index 100% rename from 24 Chemist/chemist.bas rename to 24_Chemist/chemist.bas diff --git a/24 Chemist/csharp/Chemist/Chemist.sln b/24_Chemist/csharp/Chemist/Chemist.sln similarity index 100% rename from 24 Chemist/csharp/Chemist/Chemist.sln rename to 24_Chemist/csharp/Chemist/Chemist.sln diff --git a/24 Chemist/csharp/Chemist/Chemist/Chemist.csproj b/24_Chemist/csharp/Chemist/Chemist/Chemist.csproj similarity index 100% rename from 24 Chemist/csharp/Chemist/Chemist/Chemist.csproj rename to 24_Chemist/csharp/Chemist/Chemist/Chemist.csproj diff --git a/24 Chemist/csharp/Chemist/Chemist/Program.cs b/24_Chemist/csharp/Chemist/Chemist/Program.cs similarity index 100% rename from 24 Chemist/csharp/Chemist/Chemist/Program.cs rename to 24_Chemist/csharp/Chemist/Chemist/Program.cs diff --git a/24 Chemist/csharp/README.md b/24_Chemist/csharp/README.md similarity index 100% rename from 24 Chemist/csharp/README.md rename to 24_Chemist/csharp/README.md diff --git a/24 Chemist/java/README.md b/24_Chemist/java/README.md similarity index 100% rename from 24 Chemist/java/README.md rename to 24_Chemist/java/README.md diff --git a/24 Chemist/java/src/Chemist.java b/24_Chemist/java/src/Chemist.java similarity index 100% rename from 24 Chemist/java/src/Chemist.java rename to 24_Chemist/java/src/Chemist.java diff --git a/24 Chemist/java/src/ChemistGame.java b/24_Chemist/java/src/ChemistGame.java similarity index 100% rename from 24 Chemist/java/src/ChemistGame.java rename to 24_Chemist/java/src/ChemistGame.java diff --git a/24 Chemist/javascript/README.md b/24_Chemist/javascript/README.md similarity index 100% rename from 24 Chemist/javascript/README.md rename to 24_Chemist/javascript/README.md diff --git a/24 Chemist/javascript/chemist.html b/24_Chemist/javascript/chemist.html similarity index 100% rename from 24 Chemist/javascript/chemist.html rename to 24_Chemist/javascript/chemist.html diff --git a/24 Chemist/javascript/chemist.js b/24_Chemist/javascript/chemist.js similarity index 100% rename from 24 Chemist/javascript/chemist.js rename to 24_Chemist/javascript/chemist.js diff --git a/24 Chemist/pascal/README.md b/24_Chemist/pascal/README.md similarity index 100% rename from 24 Chemist/pascal/README.md rename to 24_Chemist/pascal/README.md diff --git a/24 Chemist/perl/README.md b/24_Chemist/perl/README.md similarity index 100% rename from 24 Chemist/perl/README.md rename to 24_Chemist/perl/README.md diff --git a/24 Chemist/perlchemist.pl b/24_Chemist/perlchemist.pl similarity index 100% rename from 24 Chemist/perlchemist.pl rename to 24_Chemist/perlchemist.pl diff --git a/24 Chemist/python/README.md b/24_Chemist/python/README.md similarity index 100% rename from 24 Chemist/python/README.md rename to 24_Chemist/python/README.md diff --git a/24 Chemist/python/chemist.py b/24_Chemist/python/chemist.py similarity index 100% rename from 24 Chemist/python/chemist.py rename to 24_Chemist/python/chemist.py diff --git a/24 Chemist/ruby/README.md b/24_Chemist/ruby/README.md similarity index 100% rename from 24 Chemist/ruby/README.md rename to 24_Chemist/ruby/README.md diff --git a/24 Chemist/vbnet/README.md b/24_Chemist/vbnet/README.md similarity index 100% rename from 24 Chemist/vbnet/README.md rename to 24_Chemist/vbnet/README.md diff --git a/25 Chief/README.md b/25_Chief/README.md similarity index 100% rename from 25 Chief/README.md rename to 25_Chief/README.md diff --git a/25 Chief/chief.bas b/25_Chief/chief.bas similarity index 100% rename from 25 Chief/chief.bas rename to 25_Chief/chief.bas diff --git a/25 Chief/csharp/README.md b/25_Chief/csharp/README.md similarity index 100% rename from 25 Chief/csharp/README.md rename to 25_Chief/csharp/README.md diff --git a/25 Chief/java/README.md b/25_Chief/java/README.md similarity index 100% rename from 25 Chief/java/README.md rename to 25_Chief/java/README.md diff --git a/25 Chief/java/src/Chief.java b/25_Chief/java/src/Chief.java similarity index 100% rename from 25 Chief/java/src/Chief.java rename to 25_Chief/java/src/Chief.java diff --git a/25 Chief/java/src/ChiefGame.java b/25_Chief/java/src/ChiefGame.java similarity index 100% rename from 25 Chief/java/src/ChiefGame.java rename to 25_Chief/java/src/ChiefGame.java diff --git a/25 Chief/javascript/README.md b/25_Chief/javascript/README.md similarity index 100% rename from 25 Chief/javascript/README.md rename to 25_Chief/javascript/README.md diff --git a/25 Chief/javascript/chief.html b/25_Chief/javascript/chief.html similarity index 100% rename from 25 Chief/javascript/chief.html rename to 25_Chief/javascript/chief.html diff --git a/25 Chief/javascript/chief.js b/25_Chief/javascript/chief.js similarity index 100% rename from 25 Chief/javascript/chief.js rename to 25_Chief/javascript/chief.js diff --git a/25 Chief/pascal/README.md b/25_Chief/pascal/README.md similarity index 100% rename from 25 Chief/pascal/README.md rename to 25_Chief/pascal/README.md diff --git a/25 Chief/perl/README.md b/25_Chief/perl/README.md similarity index 100% rename from 25 Chief/perl/README.md rename to 25_Chief/perl/README.md diff --git a/25 Chief/python/README.md b/25_Chief/python/README.md similarity index 100% rename from 25 Chief/python/README.md rename to 25_Chief/python/README.md diff --git a/25 Chief/ruby/README.md b/25_Chief/ruby/README.md similarity index 100% rename from 25 Chief/ruby/README.md rename to 25_Chief/ruby/README.md diff --git a/25 Chief/vbnet/README.md b/25_Chief/vbnet/README.md similarity index 100% rename from 25 Chief/vbnet/README.md rename to 25_Chief/vbnet/README.md diff --git a/26 Chomp/README.md b/26_Chomp/README.md similarity index 100% rename from 26 Chomp/README.md rename to 26_Chomp/README.md diff --git a/26 Chomp/chomp.bas b/26_Chomp/chomp.bas similarity index 100% rename from 26 Chomp/chomp.bas rename to 26_Chomp/chomp.bas diff --git a/26 Chomp/csharp/README.md b/26_Chomp/csharp/README.md similarity index 100% rename from 26 Chomp/csharp/README.md rename to 26_Chomp/csharp/README.md diff --git a/26 Chomp/java/Chomp.java b/26_Chomp/java/Chomp.java similarity index 100% rename from 26 Chomp/java/Chomp.java rename to 26_Chomp/java/Chomp.java diff --git a/26 Chomp/java/README.md b/26_Chomp/java/README.md similarity index 100% rename from 26 Chomp/java/README.md rename to 26_Chomp/java/README.md diff --git a/26 Chomp/javascript/README.md b/26_Chomp/javascript/README.md similarity index 100% rename from 26 Chomp/javascript/README.md rename to 26_Chomp/javascript/README.md diff --git a/26 Chomp/javascript/chomp.html b/26_Chomp/javascript/chomp.html similarity index 100% rename from 26 Chomp/javascript/chomp.html rename to 26_Chomp/javascript/chomp.html diff --git a/26 Chomp/javascript/chomp.js b/26_Chomp/javascript/chomp.js similarity index 100% rename from 26 Chomp/javascript/chomp.js rename to 26_Chomp/javascript/chomp.js diff --git a/26 Chomp/pascal/README.md b/26_Chomp/pascal/README.md similarity index 100% rename from 26 Chomp/pascal/README.md rename to 26_Chomp/pascal/README.md diff --git a/26 Chomp/perl/README.md b/26_Chomp/perl/README.md similarity index 100% rename from 26 Chomp/perl/README.md rename to 26_Chomp/perl/README.md diff --git a/26 Chomp/python/README.md b/26_Chomp/python/README.md similarity index 100% rename from 26 Chomp/python/README.md rename to 26_Chomp/python/README.md diff --git a/26 Chomp/python/chomp.py b/26_Chomp/python/chomp.py similarity index 100% rename from 26 Chomp/python/chomp.py rename to 26_Chomp/python/chomp.py diff --git a/26 Chomp/ruby/README.md b/26_Chomp/ruby/README.md similarity index 100% rename from 26 Chomp/ruby/README.md rename to 26_Chomp/ruby/README.md diff --git a/26 Chomp/vbnet/README.md b/26_Chomp/vbnet/README.md similarity index 100% rename from 26 Chomp/vbnet/README.md rename to 26_Chomp/vbnet/README.md diff --git a/27 Civil War/README.md b/27_Civil_War/README.md similarity index 100% rename from 27 Civil War/README.md rename to 27_Civil_War/README.md diff --git a/27 Civil War/civilwar.bas b/27_Civil_War/civilwar.bas similarity index 100% rename from 27 Civil War/civilwar.bas rename to 27_Civil_War/civilwar.bas diff --git a/27 Civil War/csharp/CivilWar/CivilWar.sln b/27_Civil_War/csharp/CivilWar/CivilWar.sln similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar.sln rename to 27_Civil_War/csharp/CivilWar/CivilWar.sln diff --git a/27 Civil War/csharp/CivilWar/CivilWar/Army.cs b/27_Civil_War/csharp/CivilWar/CivilWar/Army.cs similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar/Army.cs rename to 27_Civil_War/csharp/CivilWar/CivilWar/Army.cs diff --git a/27 Civil War/csharp/CivilWar/CivilWar/Battle.cs b/27_Civil_War/csharp/CivilWar/CivilWar/Battle.cs similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar/Battle.cs rename to 27_Civil_War/csharp/CivilWar/CivilWar/Battle.cs diff --git a/27 Civil War/csharp/CivilWar/CivilWar/CivilWar.csproj b/27_Civil_War/csharp/CivilWar/CivilWar/CivilWar.csproj similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar/CivilWar.csproj rename to 27_Civil_War/csharp/CivilWar/CivilWar/CivilWar.csproj diff --git a/27 Civil War/csharp/CivilWar/CivilWar/ConsoleUtils.cs b/27_Civil_War/csharp/CivilWar/CivilWar/ConsoleUtils.cs similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar/ConsoleUtils.cs rename to 27_Civil_War/csharp/CivilWar/CivilWar/ConsoleUtils.cs diff --git a/27 Civil War/csharp/CivilWar/CivilWar/GameOptions.cs b/27_Civil_War/csharp/CivilWar/CivilWar/GameOptions.cs similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar/GameOptions.cs rename to 27_Civil_War/csharp/CivilWar/CivilWar/GameOptions.cs diff --git a/27 Civil War/csharp/CivilWar/CivilWar/Program.cs b/27_Civil_War/csharp/CivilWar/CivilWar/Program.cs similarity index 100% rename from 27 Civil War/csharp/CivilWar/CivilWar/Program.cs rename to 27_Civil_War/csharp/CivilWar/CivilWar/Program.cs diff --git a/27 Civil War/csharp/README.md b/27_Civil_War/csharp/README.md similarity index 100% rename from 27 Civil War/csharp/README.md rename to 27_Civil_War/csharp/README.md diff --git a/27 Civil War/java/README.md b/27_Civil_War/java/README.md similarity index 100% rename from 27 Civil War/java/README.md rename to 27_Civil_War/java/README.md diff --git a/27 Civil War/javascript/README.md b/27_Civil_War/javascript/README.md similarity index 100% rename from 27 Civil War/javascript/README.md rename to 27_Civil_War/javascript/README.md diff --git a/27 Civil War/javascript/civilwar.html b/27_Civil_War/javascript/civilwar.html similarity index 100% rename from 27 Civil War/javascript/civilwar.html rename to 27_Civil_War/javascript/civilwar.html diff --git a/27 Civil War/javascript/civilwar.js b/27_Civil_War/javascript/civilwar.js similarity index 100% rename from 27 Civil War/javascript/civilwar.js rename to 27_Civil_War/javascript/civilwar.js diff --git a/27 Civil War/pascal/README.md b/27_Civil_War/pascal/README.md similarity index 100% rename from 27 Civil War/pascal/README.md rename to 27_Civil_War/pascal/README.md diff --git a/27 Civil War/perl/README.md b/27_Civil_War/perl/README.md similarity index 100% rename from 27 Civil War/perl/README.md rename to 27_Civil_War/perl/README.md diff --git a/27 Civil War/python/README.md b/27_Civil_War/python/README.md similarity index 100% rename from 27 Civil War/python/README.md rename to 27_Civil_War/python/README.md diff --git a/27 Civil War/ruby/README.md b/27_Civil_War/ruby/README.md similarity index 100% rename from 27 Civil War/ruby/README.md rename to 27_Civil_War/ruby/README.md diff --git a/27 Civil War/vbnet/README.md b/27_Civil_War/vbnet/README.md similarity index 100% rename from 27 Civil War/vbnet/README.md rename to 27_Civil_War/vbnet/README.md diff --git a/28 Combat/README.md b/28_Combat/README.md similarity index 100% rename from 28 Combat/README.md rename to 28_Combat/README.md diff --git a/28 Combat/combat.bas b/28_Combat/combat.bas similarity index 100% rename from 28 Combat/combat.bas rename to 28_Combat/combat.bas diff --git a/28 Combat/csharp/Combat.sln b/28_Combat/csharp/Combat.sln similarity index 100% rename from 28 Combat/csharp/Combat.sln rename to 28_Combat/csharp/Combat.sln diff --git a/28 Combat/csharp/Game.csproj b/28_Combat/csharp/Game.csproj similarity index 100% rename from 28 Combat/csharp/Game.csproj rename to 28_Combat/csharp/Game.csproj diff --git a/28 Combat/csharp/README.md b/28_Combat/csharp/README.md similarity index 100% rename from 28 Combat/csharp/README.md rename to 28_Combat/csharp/README.md diff --git a/28 Combat/csharp/src/ArmedForces.cs b/28_Combat/csharp/src/ArmedForces.cs similarity index 100% rename from 28 Combat/csharp/src/ArmedForces.cs rename to 28_Combat/csharp/src/ArmedForces.cs diff --git a/28 Combat/csharp/src/Ceasefire.cs b/28_Combat/csharp/src/Ceasefire.cs similarity index 100% rename from 28 Combat/csharp/src/Ceasefire.cs rename to 28_Combat/csharp/src/Ceasefire.cs diff --git a/28 Combat/csharp/src/Controller.cs b/28_Combat/csharp/src/Controller.cs similarity index 100% rename from 28 Combat/csharp/src/Controller.cs rename to 28_Combat/csharp/src/Controller.cs diff --git a/28 Combat/csharp/src/FinalCampaign.cs b/28_Combat/csharp/src/FinalCampaign.cs similarity index 100% rename from 28 Combat/csharp/src/FinalCampaign.cs rename to 28_Combat/csharp/src/FinalCampaign.cs diff --git a/28 Combat/csharp/src/InitialCampaign.cs b/28_Combat/csharp/src/InitialCampaign.cs similarity index 100% rename from 28 Combat/csharp/src/InitialCampaign.cs rename to 28_Combat/csharp/src/InitialCampaign.cs diff --git a/28 Combat/csharp/src/MilitaryBranch.cs b/28_Combat/csharp/src/MilitaryBranch.cs similarity index 100% rename from 28 Combat/csharp/src/MilitaryBranch.cs rename to 28_Combat/csharp/src/MilitaryBranch.cs diff --git a/28 Combat/csharp/src/Program.cs b/28_Combat/csharp/src/Program.cs similarity index 100% rename from 28 Combat/csharp/src/Program.cs rename to 28_Combat/csharp/src/Program.cs diff --git a/28 Combat/csharp/src/View.cs b/28_Combat/csharp/src/View.cs similarity index 100% rename from 28 Combat/csharp/src/View.cs rename to 28_Combat/csharp/src/View.cs diff --git a/28 Combat/csharp/src/WarResult.cs b/28_Combat/csharp/src/WarResult.cs similarity index 100% rename from 28 Combat/csharp/src/WarResult.cs rename to 28_Combat/csharp/src/WarResult.cs diff --git a/28 Combat/csharp/src/WarState.cs b/28_Combat/csharp/src/WarState.cs similarity index 100% rename from 28 Combat/csharp/src/WarState.cs rename to 28_Combat/csharp/src/WarState.cs diff --git a/28 Combat/java/Combat.java b/28_Combat/java/Combat.java similarity index 100% rename from 28 Combat/java/Combat.java rename to 28_Combat/java/Combat.java diff --git a/28 Combat/java/README.md b/28_Combat/java/README.md similarity index 100% rename from 28 Combat/java/README.md rename to 28_Combat/java/README.md diff --git a/28 Combat/javascript/README.md b/28_Combat/javascript/README.md similarity index 100% rename from 28 Combat/javascript/README.md rename to 28_Combat/javascript/README.md diff --git a/28 Combat/javascript/combat.html b/28_Combat/javascript/combat.html similarity index 100% rename from 28 Combat/javascript/combat.html rename to 28_Combat/javascript/combat.html diff --git a/28 Combat/javascript/combat.js b/28_Combat/javascript/combat.js similarity index 100% rename from 28 Combat/javascript/combat.js rename to 28_Combat/javascript/combat.js diff --git a/28 Combat/pascal/README.md b/28_Combat/pascal/README.md similarity index 100% rename from 28 Combat/pascal/README.md rename to 28_Combat/pascal/README.md diff --git a/28 Combat/perl/README.md b/28_Combat/perl/README.md similarity index 100% rename from 28 Combat/perl/README.md rename to 28_Combat/perl/README.md diff --git a/28 Combat/python/README.md b/28_Combat/python/README.md similarity index 100% rename from 28 Combat/python/README.md rename to 28_Combat/python/README.md diff --git a/28 Combat/ruby/README.md b/28_Combat/ruby/README.md similarity index 100% rename from 28 Combat/ruby/README.md rename to 28_Combat/ruby/README.md diff --git a/28 Combat/vbnet/README.md b/28_Combat/vbnet/README.md similarity index 100% rename from 28 Combat/vbnet/README.md rename to 28_Combat/vbnet/README.md diff --git a/29 Craps/README.md b/29_Craps/README.md similarity index 100% rename from 29 Craps/README.md rename to 29_Craps/README.md diff --git a/29 Craps/craps.bas b/29_Craps/craps.bas similarity index 100% rename from 29 Craps/craps.bas rename to 29_Craps/craps.bas diff --git a/29 Craps/csharp/Craps/.gitignore b/29_Craps/csharp/Craps/.gitignore similarity index 100% rename from 29 Craps/csharp/Craps/.gitignore rename to 29_Craps/csharp/Craps/.gitignore diff --git a/29 Craps/csharp/Craps/Craps.sln b/29_Craps/csharp/Craps/Craps.sln similarity index 100% rename from 29 Craps/csharp/Craps/Craps.sln rename to 29_Craps/csharp/Craps/Craps.sln diff --git a/29 Craps/csharp/Craps/Craps/Craps.csproj b/29_Craps/csharp/Craps/Craps/Craps.csproj similarity index 100% rename from 29 Craps/csharp/Craps/Craps/Craps.csproj rename to 29_Craps/csharp/Craps/Craps/Craps.csproj diff --git a/29 Craps/csharp/Craps/Craps/CrapsGame.cs b/29_Craps/csharp/Craps/Craps/CrapsGame.cs similarity index 100% rename from 29 Craps/csharp/Craps/Craps/CrapsGame.cs rename to 29_Craps/csharp/Craps/Craps/CrapsGame.cs diff --git a/29 Craps/csharp/Craps/Craps/Dice.cs b/29_Craps/csharp/Craps/Craps/Dice.cs similarity index 100% rename from 29 Craps/csharp/Craps/Craps/Dice.cs rename to 29_Craps/csharp/Craps/Craps/Dice.cs diff --git a/29 Craps/csharp/Craps/Craps/Program.cs b/29_Craps/csharp/Craps/Craps/Program.cs similarity index 100% rename from 29 Craps/csharp/Craps/Craps/Program.cs rename to 29_Craps/csharp/Craps/Craps/Program.cs diff --git a/29 Craps/csharp/Craps/Craps/UserInterface.cs b/29_Craps/csharp/Craps/Craps/UserInterface.cs similarity index 100% rename from 29 Craps/csharp/Craps/Craps/UserInterface.cs rename to 29_Craps/csharp/Craps/Craps/UserInterface.cs diff --git a/29 Craps/csharp/Craps/CrapsTester/CrapsTester.csproj b/29_Craps/csharp/Craps/CrapsTester/CrapsTester.csproj similarity index 100% rename from 29 Craps/csharp/Craps/CrapsTester/CrapsTester.csproj rename to 29_Craps/csharp/Craps/CrapsTester/CrapsTester.csproj diff --git a/29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs b/29_Craps/csharp/Craps/CrapsTester/CrapsTests.cs similarity index 100% rename from 29 Craps/csharp/Craps/CrapsTester/CrapsTests.cs rename to 29_Craps/csharp/Craps/CrapsTester/CrapsTests.cs diff --git a/29 Craps/csharp/README.md b/29_Craps/csharp/README.md similarity index 100% rename from 29 Craps/csharp/README.md rename to 29_Craps/csharp/README.md diff --git a/29 Craps/java/README.md b/29_Craps/java/README.md similarity index 100% rename from 29 Craps/java/README.md rename to 29_Craps/java/README.md diff --git a/29 Craps/javascript/README.md b/29_Craps/javascript/README.md similarity index 100% rename from 29 Craps/javascript/README.md rename to 29_Craps/javascript/README.md diff --git a/29 Craps/javascript/craps.html b/29_Craps/javascript/craps.html similarity index 100% rename from 29 Craps/javascript/craps.html rename to 29_Craps/javascript/craps.html diff --git a/29 Craps/javascript/craps.js b/29_Craps/javascript/craps.js similarity index 100% rename from 29 Craps/javascript/craps.js rename to 29_Craps/javascript/craps.js diff --git a/29 Craps/pascal/README.md b/29_Craps/pascal/README.md similarity index 100% rename from 29 Craps/pascal/README.md rename to 29_Craps/pascal/README.md diff --git a/29 Craps/perl/README.md b/29_Craps/perl/README.md similarity index 100% rename from 29 Craps/perl/README.md rename to 29_Craps/perl/README.md diff --git a/29 Craps/python/README.md b/29_Craps/python/README.md similarity index 100% rename from 29 Craps/python/README.md rename to 29_Craps/python/README.md diff --git a/29 Craps/ruby/README.md b/29_Craps/ruby/README.md similarity index 100% rename from 29 Craps/ruby/README.md rename to 29_Craps/ruby/README.md diff --git a/29 Craps/vbnet/README.md b/29_Craps/vbnet/README.md similarity index 100% rename from 29 Craps/vbnet/README.md rename to 29_Craps/vbnet/README.md diff --git a/30 Cube/README.md b/30_Cube/README.md similarity index 100% rename from 30 Cube/README.md rename to 30_Cube/README.md diff --git a/30 Cube/csharp/README.md b/30_Cube/csharp/README.md similarity index 100% rename from 30 Cube/csharp/README.md rename to 30_Cube/csharp/README.md diff --git a/30 Cube/cube.bas b/30_Cube/cube.bas similarity index 100% rename from 30 Cube/cube.bas rename to 30_Cube/cube.bas diff --git a/30 Cube/java/README.md b/30_Cube/java/README.md similarity index 100% rename from 30 Cube/java/README.md rename to 30_Cube/java/README.md diff --git a/30 Cube/javascript/README.md b/30_Cube/javascript/README.md similarity index 100% rename from 30 Cube/javascript/README.md rename to 30_Cube/javascript/README.md diff --git a/30 Cube/javascript/cube.html b/30_Cube/javascript/cube.html similarity index 100% rename from 30 Cube/javascript/cube.html rename to 30_Cube/javascript/cube.html diff --git a/30 Cube/javascript/cube.js b/30_Cube/javascript/cube.js similarity index 100% rename from 30 Cube/javascript/cube.js rename to 30_Cube/javascript/cube.js diff --git a/30 Cube/pascal/README.md b/30_Cube/pascal/README.md similarity index 100% rename from 30 Cube/pascal/README.md rename to 30_Cube/pascal/README.md diff --git a/30 Cube/perl/README.md b/30_Cube/perl/README.md similarity index 100% rename from 30 Cube/perl/README.md rename to 30_Cube/perl/README.md diff --git a/30 Cube/python/README.md b/30_Cube/python/README.md similarity index 100% rename from 30 Cube/python/README.md rename to 30_Cube/python/README.md diff --git a/30 Cube/python/cube.py b/30_Cube/python/cube.py similarity index 100% rename from 30 Cube/python/cube.py rename to 30_Cube/python/cube.py diff --git a/30 Cube/ruby/README.md b/30_Cube/ruby/README.md similarity index 100% rename from 30 Cube/ruby/README.md rename to 30_Cube/ruby/README.md diff --git a/30 Cube/vbnet/README.md b/30_Cube/vbnet/README.md similarity index 100% rename from 30 Cube/vbnet/README.md rename to 30_Cube/vbnet/README.md diff --git a/31 Depth Charge/README.md b/31_Depth_Charge/README.md similarity index 100% rename from 31 Depth Charge/README.md rename to 31_Depth_Charge/README.md diff --git a/31 Depth Charge/csharp/DepthCharge.sln b/31_Depth_Charge/csharp/DepthCharge.sln similarity index 100% rename from 31 Depth Charge/csharp/DepthCharge.sln rename to 31_Depth_Charge/csharp/DepthCharge.sln diff --git a/31 Depth Charge/csharp/Game.csproj b/31_Depth_Charge/csharp/Game.csproj similarity index 100% rename from 31 Depth Charge/csharp/Game.csproj rename to 31_Depth_Charge/csharp/Game.csproj diff --git a/31 Depth Charge/csharp/README.md b/31_Depth_Charge/csharp/README.md similarity index 100% rename from 31 Depth Charge/csharp/README.md rename to 31_Depth_Charge/csharp/README.md diff --git a/31 Depth Charge/csharp/src/Controller.cs b/31_Depth_Charge/csharp/src/Controller.cs similarity index 100% rename from 31 Depth Charge/csharp/src/Controller.cs rename to 31_Depth_Charge/csharp/src/Controller.cs diff --git a/31 Depth Charge/csharp/src/Program.cs b/31_Depth_Charge/csharp/src/Program.cs similarity index 100% rename from 31 Depth Charge/csharp/src/Program.cs rename to 31_Depth_Charge/csharp/src/Program.cs diff --git a/31 Depth Charge/csharp/src/View.cs b/31_Depth_Charge/csharp/src/View.cs similarity index 100% rename from 31 Depth Charge/csharp/src/View.cs rename to 31_Depth_Charge/csharp/src/View.cs diff --git a/31 Depth Charge/depthcharge.bas b/31_Depth_Charge/depthcharge.bas similarity index 100% rename from 31 Depth Charge/depthcharge.bas rename to 31_Depth_Charge/depthcharge.bas diff --git a/31 Depth Charge/java/DepthCharge.java b/31_Depth_Charge/java/DepthCharge.java similarity index 100% rename from 31 Depth Charge/java/DepthCharge.java rename to 31_Depth_Charge/java/DepthCharge.java diff --git a/31 Depth Charge/java/README.md b/31_Depth_Charge/java/README.md similarity index 100% rename from 31 Depth Charge/java/README.md rename to 31_Depth_Charge/java/README.md diff --git a/31 Depth Charge/javascript/README.md b/31_Depth_Charge/javascript/README.md similarity index 100% rename from 31 Depth Charge/javascript/README.md rename to 31_Depth_Charge/javascript/README.md diff --git a/31 Depth Charge/javascript/depthcharge.html b/31_Depth_Charge/javascript/depthcharge.html similarity index 100% rename from 31 Depth Charge/javascript/depthcharge.html rename to 31_Depth_Charge/javascript/depthcharge.html diff --git a/31 Depth Charge/javascript/depthcharge.js b/31_Depth_Charge/javascript/depthcharge.js similarity index 100% rename from 31 Depth Charge/javascript/depthcharge.js rename to 31_Depth_Charge/javascript/depthcharge.js diff --git a/31 Depth Charge/pascal/README.md b/31_Depth_Charge/pascal/README.md similarity index 100% rename from 31 Depth Charge/pascal/README.md rename to 31_Depth_Charge/pascal/README.md diff --git a/31 Depth Charge/perl/README.md b/31_Depth_Charge/perl/README.md similarity index 100% rename from 31 Depth Charge/perl/README.md rename to 31_Depth_Charge/perl/README.md diff --git a/31 Depth Charge/perl/depth-charge.pl b/31_Depth_Charge/perl/depth-charge.pl similarity index 100% rename from 31 Depth Charge/perl/depth-charge.pl rename to 31_Depth_Charge/perl/depth-charge.pl diff --git a/31 Depth Charge/python/README.md b/31_Depth_Charge/python/README.md similarity index 100% rename from 31 Depth Charge/python/README.md rename to 31_Depth_Charge/python/README.md diff --git a/31 Depth Charge/python/depth_charge.py b/31_Depth_Charge/python/depth_charge.py similarity index 100% rename from 31 Depth Charge/python/depth_charge.py rename to 31_Depth_Charge/python/depth_charge.py diff --git a/31 Depth Charge/ruby/README.md b/31_Depth_Charge/ruby/README.md similarity index 100% rename from 31 Depth Charge/ruby/README.md rename to 31_Depth_Charge/ruby/README.md diff --git a/31 Depth Charge/vbnet/README.md b/31_Depth_Charge/vbnet/README.md similarity index 100% rename from 31 Depth Charge/vbnet/README.md rename to 31_Depth_Charge/vbnet/README.md diff --git a/32 Diamond/README.md b/32_Diamond/README.md similarity index 100% rename from 32 Diamond/README.md rename to 32_Diamond/README.md diff --git a/32 Diamond/csharp/README.md b/32_Diamond/csharp/README.md similarity index 100% rename from 32 Diamond/csharp/README.md rename to 32_Diamond/csharp/README.md diff --git a/32 Diamond/diamond.bas b/32_Diamond/diamond.bas similarity index 100% rename from 32 Diamond/diamond.bas rename to 32_Diamond/diamond.bas diff --git a/32 Diamond/java/Diamond.java b/32_Diamond/java/Diamond.java similarity index 100% rename from 32 Diamond/java/Diamond.java rename to 32_Diamond/java/Diamond.java diff --git a/32 Diamond/java/README.md b/32_Diamond/java/README.md similarity index 100% rename from 32 Diamond/java/README.md rename to 32_Diamond/java/README.md diff --git a/32 Diamond/javascript/README.md b/32_Diamond/javascript/README.md similarity index 100% rename from 32 Diamond/javascript/README.md rename to 32_Diamond/javascript/README.md diff --git a/32 Diamond/javascript/diamond.html b/32_Diamond/javascript/diamond.html similarity index 100% rename from 32 Diamond/javascript/diamond.html rename to 32_Diamond/javascript/diamond.html diff --git a/32 Diamond/javascript/diamond.js b/32_Diamond/javascript/diamond.js similarity index 100% rename from 32 Diamond/javascript/diamond.js rename to 32_Diamond/javascript/diamond.js diff --git a/32 Diamond/pascal/README.md b/32_Diamond/pascal/README.md similarity index 100% rename from 32 Diamond/pascal/README.md rename to 32_Diamond/pascal/README.md diff --git a/32 Diamond/perl/README.md b/32_Diamond/perl/README.md similarity index 100% rename from 32 Diamond/perl/README.md rename to 32_Diamond/perl/README.md diff --git a/32 Diamond/perl/diamond.pl b/32_Diamond/perl/diamond.pl similarity index 100% rename from 32 Diamond/perl/diamond.pl rename to 32_Diamond/perl/diamond.pl diff --git a/32 Diamond/python/README.md b/32_Diamond/python/README.md similarity index 100% rename from 32 Diamond/python/README.md rename to 32_Diamond/python/README.md diff --git a/32 Diamond/python/diamond.py b/32_Diamond/python/diamond.py similarity index 100% rename from 32 Diamond/python/diamond.py rename to 32_Diamond/python/diamond.py diff --git a/32 Diamond/ruby/README.md b/32_Diamond/ruby/README.md similarity index 100% rename from 32 Diamond/ruby/README.md rename to 32_Diamond/ruby/README.md diff --git a/32 Diamond/ruby/diamond.rb b/32_Diamond/ruby/diamond.rb similarity index 100% rename from 32 Diamond/ruby/diamond.rb rename to 32_Diamond/ruby/diamond.rb diff --git a/32 Diamond/vbnet/README.md b/32_Diamond/vbnet/README.md similarity index 100% rename from 32 Diamond/vbnet/README.md rename to 32_Diamond/vbnet/README.md diff --git a/33 Dice/README.md b/33_Dice/README.md similarity index 100% rename from 33 Dice/README.md rename to 33_Dice/README.md diff --git a/33 Dice/csharp/Dice.csproj b/33_Dice/csharp/Dice.csproj similarity index 100% rename from 33 Dice/csharp/Dice.csproj rename to 33_Dice/csharp/Dice.csproj diff --git a/33 Dice/csharp/Game.cs b/33_Dice/csharp/Game.cs similarity index 100% rename from 33 Dice/csharp/Game.cs rename to 33_Dice/csharp/Game.cs diff --git a/33 Dice/csharp/Program.cs b/33_Dice/csharp/Program.cs similarity index 100% rename from 33 Dice/csharp/Program.cs rename to 33_Dice/csharp/Program.cs diff --git a/33 Dice/csharp/README.md b/33_Dice/csharp/README.md similarity index 100% rename from 33 Dice/csharp/README.md rename to 33_Dice/csharp/README.md diff --git a/33 Dice/csharp/RollGenerator.cs b/33_Dice/csharp/RollGenerator.cs similarity index 100% rename from 33 Dice/csharp/RollGenerator.cs rename to 33_Dice/csharp/RollGenerator.cs diff --git a/33 Dice/dice.bas b/33_Dice/dice.bas similarity index 100% rename from 33 Dice/dice.bas rename to 33_Dice/dice.bas diff --git a/33 Dice/java/README.md b/33_Dice/java/README.md similarity index 100% rename from 33 Dice/java/README.md rename to 33_Dice/java/README.md diff --git a/33 Dice/java/src/Dice.java b/33_Dice/java/src/Dice.java similarity index 100% rename from 33 Dice/java/src/Dice.java rename to 33_Dice/java/src/Dice.java diff --git a/33 Dice/java/src/DiceGame.java b/33_Dice/java/src/DiceGame.java similarity index 100% rename from 33 Dice/java/src/DiceGame.java rename to 33_Dice/java/src/DiceGame.java diff --git a/33 Dice/javascript/README.md b/33_Dice/javascript/README.md similarity index 100% rename from 33 Dice/javascript/README.md rename to 33_Dice/javascript/README.md diff --git a/33 Dice/javascript/dice.html b/33_Dice/javascript/dice.html similarity index 100% rename from 33 Dice/javascript/dice.html rename to 33_Dice/javascript/dice.html diff --git a/33 Dice/javascript/dice.js b/33_Dice/javascript/dice.js similarity index 100% rename from 33 Dice/javascript/dice.js rename to 33_Dice/javascript/dice.js diff --git a/33 Dice/pascal/README.md b/33_Dice/pascal/README.md similarity index 100% rename from 33 Dice/pascal/README.md rename to 33_Dice/pascal/README.md diff --git a/33 Dice/perl/README.md b/33_Dice/perl/README.md similarity index 100% rename from 33 Dice/perl/README.md rename to 33_Dice/perl/README.md diff --git a/33 Dice/perl/dice.pl b/33_Dice/perl/dice.pl similarity index 100% rename from 33 Dice/perl/dice.pl rename to 33_Dice/perl/dice.pl diff --git a/33 Dice/python/README.md b/33_Dice/python/README.md similarity index 100% rename from 33 Dice/python/README.md rename to 33_Dice/python/README.md diff --git a/33 Dice/python/dice.py b/33_Dice/python/dice.py similarity index 100% rename from 33 Dice/python/dice.py rename to 33_Dice/python/dice.py diff --git a/33 Dice/ruby/README.md b/33_Dice/ruby/README.md similarity index 100% rename from 33 Dice/ruby/README.md rename to 33_Dice/ruby/README.md diff --git a/33 Dice/ruby/dice.rb b/33_Dice/ruby/dice.rb similarity index 100% rename from 33 Dice/ruby/dice.rb rename to 33_Dice/ruby/dice.rb diff --git a/33 Dice/vbnet/README.md b/33_Dice/vbnet/README.md similarity index 100% rename from 33 Dice/vbnet/README.md rename to 33_Dice/vbnet/README.md diff --git a/34 Digits/README.md b/34_Digits/README.md similarity index 100% rename from 34 Digits/README.md rename to 34_Digits/README.md diff --git a/34 Digits/csharp/README.md b/34_Digits/csharp/README.md similarity index 100% rename from 34 Digits/csharp/README.md rename to 34_Digits/csharp/README.md diff --git a/34 Digits/digits.bas b/34_Digits/digits.bas similarity index 100% rename from 34 Digits/digits.bas rename to 34_Digits/digits.bas diff --git a/34 Digits/java/Digits.java b/34_Digits/java/Digits.java similarity index 100% rename from 34 Digits/java/Digits.java rename to 34_Digits/java/Digits.java diff --git a/34 Digits/java/README.md b/34_Digits/java/README.md similarity index 100% rename from 34 Digits/java/README.md rename to 34_Digits/java/README.md diff --git a/34 Digits/javascript/README.md b/34_Digits/javascript/README.md similarity index 100% rename from 34 Digits/javascript/README.md rename to 34_Digits/javascript/README.md diff --git a/34 Digits/javascript/digits.html b/34_Digits/javascript/digits.html similarity index 100% rename from 34 Digits/javascript/digits.html rename to 34_Digits/javascript/digits.html diff --git a/34 Digits/javascript/digits.js b/34_Digits/javascript/digits.js similarity index 100% rename from 34 Digits/javascript/digits.js rename to 34_Digits/javascript/digits.js diff --git a/34 Digits/pascal/README.md b/34_Digits/pascal/README.md similarity index 100% rename from 34 Digits/pascal/README.md rename to 34_Digits/pascal/README.md diff --git a/34 Digits/perl/README.md b/34_Digits/perl/README.md similarity index 100% rename from 34 Digits/perl/README.md rename to 34_Digits/perl/README.md diff --git a/34 Digits/python/README.md b/34_Digits/python/README.md similarity index 100% rename from 34 Digits/python/README.md rename to 34_Digits/python/README.md diff --git a/34 Digits/ruby/README.md b/34_Digits/ruby/README.md similarity index 100% rename from 34 Digits/ruby/README.md rename to 34_Digits/ruby/README.md diff --git a/34 Digits/vbnet/README.md b/34_Digits/vbnet/README.md similarity index 100% rename from 34 Digits/vbnet/README.md rename to 34_Digits/vbnet/README.md diff --git a/35 Even Wins/README.md b/35_Even_Wins/README.md similarity index 100% rename from 35 Even Wins/README.md rename to 35_Even_Wins/README.md diff --git a/35 Even Wins/csharp/README.md b/35_Even_Wins/csharp/README.md similarity index 100% rename from 35 Even Wins/csharp/README.md rename to 35_Even_Wins/csharp/README.md diff --git a/35 Even Wins/evenwins.bas b/35_Even_Wins/evenwins.bas similarity index 100% rename from 35 Even Wins/evenwins.bas rename to 35_Even_Wins/evenwins.bas diff --git a/35 Even Wins/gameofevenwins.bas b/35_Even_Wins/gameofevenwins.bas similarity index 100% rename from 35 Even Wins/gameofevenwins.bas rename to 35_Even_Wins/gameofevenwins.bas diff --git a/35 Even Wins/java/README.md b/35_Even_Wins/java/README.md similarity index 100% rename from 35 Even Wins/java/README.md rename to 35_Even_Wins/java/README.md diff --git a/35 Even Wins/javascript/README.md b/35_Even_Wins/javascript/README.md similarity index 100% rename from 35 Even Wins/javascript/README.md rename to 35_Even_Wins/javascript/README.md diff --git a/35 Even Wins/javascript/evenwins.html b/35_Even_Wins/javascript/evenwins.html similarity index 100% rename from 35 Even Wins/javascript/evenwins.html rename to 35_Even_Wins/javascript/evenwins.html diff --git a/35 Even Wins/javascript/evenwins.js b/35_Even_Wins/javascript/evenwins.js similarity index 100% rename from 35 Even Wins/javascript/evenwins.js rename to 35_Even_Wins/javascript/evenwins.js diff --git a/35 Even Wins/javascript/gameofevenwins.html b/35_Even_Wins/javascript/gameofevenwins.html similarity index 100% rename from 35 Even Wins/javascript/gameofevenwins.html rename to 35_Even_Wins/javascript/gameofevenwins.html diff --git a/35 Even Wins/javascript/gameofevenwins.js b/35_Even_Wins/javascript/gameofevenwins.js similarity index 100% rename from 35 Even Wins/javascript/gameofevenwins.js rename to 35_Even_Wins/javascript/gameofevenwins.js diff --git a/35 Even Wins/pascal/README.md b/35_Even_Wins/pascal/README.md similarity index 100% rename from 35 Even Wins/pascal/README.md rename to 35_Even_Wins/pascal/README.md diff --git a/35 Even Wins/perl/README.md b/35_Even_Wins/perl/README.md similarity index 100% rename from 35 Even Wins/perl/README.md rename to 35_Even_Wins/perl/README.md diff --git a/35 Even Wins/python/README.md b/35_Even_Wins/python/README.md similarity index 100% rename from 35 Even Wins/python/README.md rename to 35_Even_Wins/python/README.md diff --git a/35 Even Wins/ruby/README.md b/35_Even_Wins/ruby/README.md similarity index 100% rename from 35 Even Wins/ruby/README.md rename to 35_Even_Wins/ruby/README.md diff --git a/35 Even Wins/vbnet/README.md b/35_Even_Wins/vbnet/README.md similarity index 100% rename from 35 Even Wins/vbnet/README.md rename to 35_Even_Wins/vbnet/README.md diff --git a/36 Flip Flop/README.md b/36_Flip_Flop/README.md similarity index 100% rename from 36 Flip Flop/README.md rename to 36_Flip_Flop/README.md diff --git a/36 Flip Flop/csharp/README.md b/36_Flip_Flop/csharp/README.md similarity index 100% rename from 36 Flip Flop/csharp/README.md rename to 36_Flip_Flop/csharp/README.md diff --git a/36 Flip Flop/flipflop.bas b/36_Flip_Flop/flipflop.bas similarity index 100% rename from 36 Flip Flop/flipflop.bas rename to 36_Flip_Flop/flipflop.bas diff --git a/36 Flip Flop/java/FlipFlop.java b/36_Flip_Flop/java/FlipFlop.java similarity index 100% rename from 36 Flip Flop/java/FlipFlop.java rename to 36_Flip_Flop/java/FlipFlop.java diff --git a/36 Flip Flop/java/README.md b/36_Flip_Flop/java/README.md similarity index 100% rename from 36 Flip Flop/java/README.md rename to 36_Flip_Flop/java/README.md diff --git a/36 Flip Flop/javascript/README.md b/36_Flip_Flop/javascript/README.md similarity index 100% rename from 36 Flip Flop/javascript/README.md rename to 36_Flip_Flop/javascript/README.md diff --git a/36 Flip Flop/javascript/flipflop.html b/36_Flip_Flop/javascript/flipflop.html similarity index 100% rename from 36 Flip Flop/javascript/flipflop.html rename to 36_Flip_Flop/javascript/flipflop.html diff --git a/36 Flip Flop/javascript/flipflop.js b/36_Flip_Flop/javascript/flipflop.js similarity index 100% rename from 36 Flip Flop/javascript/flipflop.js rename to 36_Flip_Flop/javascript/flipflop.js diff --git a/36 Flip Flop/pascal/README.md b/36_Flip_Flop/pascal/README.md similarity index 100% rename from 36 Flip Flop/pascal/README.md rename to 36_Flip_Flop/pascal/README.md diff --git a/36 Flip Flop/perl/README.md b/36_Flip_Flop/perl/README.md similarity index 100% rename from 36 Flip Flop/perl/README.md rename to 36_Flip_Flop/perl/README.md diff --git a/36 Flip Flop/python/README.md b/36_Flip_Flop/python/README.md similarity index 100% rename from 36 Flip Flop/python/README.md rename to 36_Flip_Flop/python/README.md diff --git a/36 Flip Flop/ruby/README.md b/36_Flip_Flop/ruby/README.md similarity index 100% rename from 36 Flip Flop/ruby/README.md rename to 36_Flip_Flop/ruby/README.md diff --git a/36 Flip Flop/vbnet/README.md b/36_Flip_Flop/vbnet/README.md similarity index 100% rename from 36 Flip Flop/vbnet/README.md rename to 36_Flip_Flop/vbnet/README.md diff --git a/37 Football/README.md b/37_Football/README.md similarity index 100% rename from 37 Football/README.md rename to 37_Football/README.md diff --git a/37 Football/csharp/README.md b/37_Football/csharp/README.md similarity index 100% rename from 37 Football/csharp/README.md rename to 37_Football/csharp/README.md diff --git a/37 Football/football.bas b/37_Football/football.bas similarity index 100% rename from 37 Football/football.bas rename to 37_Football/football.bas diff --git a/37 Football/ftball.bas b/37_Football/ftball.bas similarity index 100% rename from 37 Football/ftball.bas rename to 37_Football/ftball.bas diff --git a/37 Football/java/README.md b/37_Football/java/README.md similarity index 100% rename from 37 Football/java/README.md rename to 37_Football/java/README.md diff --git a/37 Football/javascript/README.md b/37_Football/javascript/README.md similarity index 100% rename from 37 Football/javascript/README.md rename to 37_Football/javascript/README.md diff --git a/37 Football/javascript/football.html b/37_Football/javascript/football.html similarity index 100% rename from 37 Football/javascript/football.html rename to 37_Football/javascript/football.html diff --git a/37 Football/javascript/football.js b/37_Football/javascript/football.js similarity index 100% rename from 37 Football/javascript/football.js rename to 37_Football/javascript/football.js diff --git a/37 Football/javascript/ftball.html b/37_Football/javascript/ftball.html similarity index 100% rename from 37 Football/javascript/ftball.html rename to 37_Football/javascript/ftball.html diff --git a/37 Football/javascript/ftball.js b/37_Football/javascript/ftball.js similarity index 100% rename from 37 Football/javascript/ftball.js rename to 37_Football/javascript/ftball.js diff --git a/37 Football/pascal/README.md b/37_Football/pascal/README.md similarity index 100% rename from 37 Football/pascal/README.md rename to 37_Football/pascal/README.md diff --git a/37 Football/perl/README.md b/37_Football/perl/README.md similarity index 100% rename from 37 Football/perl/README.md rename to 37_Football/perl/README.md diff --git a/37 Football/python/README.md b/37_Football/python/README.md similarity index 100% rename from 37 Football/python/README.md rename to 37_Football/python/README.md diff --git a/37 Football/ruby/README.md b/37_Football/ruby/README.md similarity index 100% rename from 37 Football/ruby/README.md rename to 37_Football/ruby/README.md diff --git a/37 Football/vbnet/README.md b/37_Football/vbnet/README.md similarity index 100% rename from 37 Football/vbnet/README.md rename to 37_Football/vbnet/README.md diff --git a/38 Fur Trader/README.md b/38_Fur_Trader/README.md similarity index 100% rename from 38 Fur Trader/README.md rename to 38_Fur_Trader/README.md diff --git a/38 Fur Trader/c/README.md b/38_Fur_Trader/c/README.md similarity index 100% rename from 38 Fur Trader/c/README.md rename to 38_Fur_Trader/c/README.md diff --git a/38 Fur Trader/c/furtrader.c b/38_Fur_Trader/c/furtrader.c similarity index 100% rename from 38 Fur Trader/c/furtrader.c rename to 38_Fur_Trader/c/furtrader.c diff --git a/38 Fur Trader/csharp/FurTrader.csproj b/38_Fur_Trader/csharp/FurTrader.csproj similarity index 100% rename from 38 Fur Trader/csharp/FurTrader.csproj rename to 38_Fur_Trader/csharp/FurTrader.csproj diff --git a/38 Fur Trader/csharp/FurTrader.sln b/38_Fur_Trader/csharp/FurTrader.sln similarity index 100% rename from 38 Fur Trader/csharp/FurTrader.sln rename to 38_Fur_Trader/csharp/FurTrader.sln diff --git a/38 Fur Trader/csharp/Game.cs b/38_Fur_Trader/csharp/Game.cs similarity index 100% rename from 38 Fur Trader/csharp/Game.cs rename to 38_Fur_Trader/csharp/Game.cs diff --git a/38 Fur Trader/csharp/GameState.cs b/38_Fur_Trader/csharp/GameState.cs similarity index 100% rename from 38 Fur Trader/csharp/GameState.cs rename to 38_Fur_Trader/csharp/GameState.cs diff --git a/38 Fur Trader/csharp/Program.cs b/38_Fur_Trader/csharp/Program.cs similarity index 100% rename from 38 Fur Trader/csharp/Program.cs rename to 38_Fur_Trader/csharp/Program.cs diff --git a/38 Fur Trader/csharp/README.md b/38_Fur_Trader/csharp/README.md similarity index 100% rename from 38 Fur Trader/csharp/README.md rename to 38_Fur_Trader/csharp/README.md diff --git a/38 Fur Trader/furtrader.bas b/38_Fur_Trader/furtrader.bas similarity index 100% rename from 38 Fur Trader/furtrader.bas rename to 38_Fur_Trader/furtrader.bas diff --git a/38 Fur Trader/java/README.md b/38_Fur_Trader/java/README.md similarity index 100% rename from 38 Fur Trader/java/README.md rename to 38_Fur_Trader/java/README.md diff --git a/38 Fur Trader/java/src/FurTrader.java b/38_Fur_Trader/java/src/FurTrader.java similarity index 100% rename from 38 Fur Trader/java/src/FurTrader.java rename to 38_Fur_Trader/java/src/FurTrader.java diff --git a/38 Fur Trader/java/src/FurTraderGame.java b/38_Fur_Trader/java/src/FurTraderGame.java similarity index 100% rename from 38 Fur Trader/java/src/FurTraderGame.java rename to 38_Fur_Trader/java/src/FurTraderGame.java diff --git a/38 Fur Trader/java/src/Pelt.java b/38_Fur_Trader/java/src/Pelt.java similarity index 100% rename from 38 Fur Trader/java/src/Pelt.java rename to 38_Fur_Trader/java/src/Pelt.java diff --git a/38 Fur Trader/javascript/README.md b/38_Fur_Trader/javascript/README.md similarity index 100% rename from 38 Fur Trader/javascript/README.md rename to 38_Fur_Trader/javascript/README.md diff --git a/38 Fur Trader/javascript/furtrader.html b/38_Fur_Trader/javascript/furtrader.html similarity index 100% rename from 38 Fur Trader/javascript/furtrader.html rename to 38_Fur_Trader/javascript/furtrader.html diff --git a/38 Fur Trader/javascript/furtrader.js b/38_Fur_Trader/javascript/furtrader.js similarity index 100% rename from 38 Fur Trader/javascript/furtrader.js rename to 38_Fur_Trader/javascript/furtrader.js diff --git a/38 Fur Trader/pascal/README.md b/38_Fur_Trader/pascal/README.md similarity index 100% rename from 38 Fur Trader/pascal/README.md rename to 38_Fur_Trader/pascal/README.md diff --git a/38 Fur Trader/perl/README.md b/38_Fur_Trader/perl/README.md similarity index 100% rename from 38 Fur Trader/perl/README.md rename to 38_Fur_Trader/perl/README.md diff --git a/38 Fur Trader/python/README.md b/38_Fur_Trader/python/README.md similarity index 100% rename from 38 Fur Trader/python/README.md rename to 38_Fur_Trader/python/README.md diff --git a/38 Fur Trader/python/furtrader.py b/38_Fur_Trader/python/furtrader.py similarity index 100% rename from 38 Fur Trader/python/furtrader.py rename to 38_Fur_Trader/python/furtrader.py diff --git a/38 Fur Trader/ruby/README.md b/38_Fur_Trader/ruby/README.md similarity index 100% rename from 38 Fur Trader/ruby/README.md rename to 38_Fur_Trader/ruby/README.md diff --git a/38 Fur Trader/vbnet/README.md b/38_Fur_Trader/vbnet/README.md similarity index 100% rename from 38 Fur Trader/vbnet/README.md rename to 38_Fur_Trader/vbnet/README.md diff --git a/39 Golf/README.md b/39_Golf/README.md similarity index 100% rename from 39 Golf/README.md rename to 39_Golf/README.md diff --git a/39 Golf/csharp/Program.cs b/39_Golf/csharp/Program.cs similarity index 100% rename from 39 Golf/csharp/Program.cs rename to 39_Golf/csharp/Program.cs diff --git a/39 Golf/csharp/README.md b/39_Golf/csharp/README.md similarity index 100% rename from 39 Golf/csharp/README.md rename to 39_Golf/csharp/README.md diff --git a/39 Golf/golf.bas b/39_Golf/golf.bas similarity index 100% rename from 39 Golf/golf.bas rename to 39_Golf/golf.bas diff --git a/39 Golf/java/README.md b/39_Golf/java/README.md similarity index 100% rename from 39 Golf/java/README.md rename to 39_Golf/java/README.md diff --git a/39 Golf/javascript/README.md b/39_Golf/javascript/README.md similarity index 100% rename from 39 Golf/javascript/README.md rename to 39_Golf/javascript/README.md diff --git a/39 Golf/javascript/golf.html b/39_Golf/javascript/golf.html similarity index 100% rename from 39 Golf/javascript/golf.html rename to 39_Golf/javascript/golf.html diff --git a/39 Golf/javascript/golf.js b/39_Golf/javascript/golf.js similarity index 100% rename from 39 Golf/javascript/golf.js rename to 39_Golf/javascript/golf.js diff --git a/39 Golf/pascal/README.md b/39_Golf/pascal/README.md similarity index 100% rename from 39 Golf/pascal/README.md rename to 39_Golf/pascal/README.md diff --git a/39 Golf/perl/README.md b/39_Golf/perl/README.md similarity index 100% rename from 39 Golf/perl/README.md rename to 39_Golf/perl/README.md diff --git a/39 Golf/python/README.md b/39_Golf/python/README.md similarity index 100% rename from 39 Golf/python/README.md rename to 39_Golf/python/README.md diff --git a/39 Golf/ruby/README.md b/39_Golf/ruby/README.md similarity index 100% rename from 39 Golf/ruby/README.md rename to 39_Golf/ruby/README.md diff --git a/39 Golf/vbnet/README.md b/39_Golf/vbnet/README.md similarity index 100% rename from 39 Golf/vbnet/README.md rename to 39_Golf/vbnet/README.md diff --git a/40 Gomoko/README.md b/40_Gomoko/README.md similarity index 100% rename from 40 Gomoko/README.md rename to 40_Gomoko/README.md diff --git a/40 Gomoko/csharp/README.md b/40_Gomoko/csharp/README.md similarity index 100% rename from 40 Gomoko/csharp/README.md rename to 40_Gomoko/csharp/README.md diff --git a/40 Gomoko/gomoko.bas b/40_Gomoko/gomoko.bas similarity index 100% rename from 40 Gomoko/gomoko.bas rename to 40_Gomoko/gomoko.bas diff --git a/40 Gomoko/java/Gomoko.java b/40_Gomoko/java/Gomoko.java similarity index 100% rename from 40 Gomoko/java/Gomoko.java rename to 40_Gomoko/java/Gomoko.java diff --git a/40 Gomoko/java/README.md b/40_Gomoko/java/README.md similarity index 100% rename from 40 Gomoko/java/README.md rename to 40_Gomoko/java/README.md diff --git a/40 Gomoko/javascript/README.md b/40_Gomoko/javascript/README.md similarity index 100% rename from 40 Gomoko/javascript/README.md rename to 40_Gomoko/javascript/README.md diff --git a/40 Gomoko/javascript/gomoko.html b/40_Gomoko/javascript/gomoko.html similarity index 100% rename from 40 Gomoko/javascript/gomoko.html rename to 40_Gomoko/javascript/gomoko.html diff --git a/40 Gomoko/javascript/gomoko.js b/40_Gomoko/javascript/gomoko.js similarity index 100% rename from 40 Gomoko/javascript/gomoko.js rename to 40_Gomoko/javascript/gomoko.js diff --git a/40 Gomoko/pascal/README.md b/40_Gomoko/pascal/README.md similarity index 100% rename from 40 Gomoko/pascal/README.md rename to 40_Gomoko/pascal/README.md diff --git a/40 Gomoko/perl/README.md b/40_Gomoko/perl/README.md similarity index 100% rename from 40 Gomoko/perl/README.md rename to 40_Gomoko/perl/README.md diff --git a/40 Gomoko/python/README.md b/40_Gomoko/python/README.md similarity index 100% rename from 40 Gomoko/python/README.md rename to 40_Gomoko/python/README.md diff --git a/40 Gomoko/ruby/README.md b/40_Gomoko/ruby/README.md similarity index 100% rename from 40 Gomoko/ruby/README.md rename to 40_Gomoko/ruby/README.md diff --git a/40 Gomoko/vbnet/README.md b/40_Gomoko/vbnet/README.md similarity index 100% rename from 40 Gomoko/vbnet/README.md rename to 40_Gomoko/vbnet/README.md diff --git a/41 Guess/README.md b/41_Guess/README.md similarity index 100% rename from 41 Guess/README.md rename to 41_Guess/README.md diff --git a/41 Guess/csharp/README.md b/41_Guess/csharp/README.md similarity index 100% rename from 41 Guess/csharp/README.md rename to 41_Guess/csharp/README.md diff --git a/41 Guess/guess.bas b/41_Guess/guess.bas similarity index 100% rename from 41 Guess/guess.bas rename to 41_Guess/guess.bas diff --git a/41 Guess/java/README.md b/41_Guess/java/README.md similarity index 100% rename from 41 Guess/java/README.md rename to 41_Guess/java/README.md diff --git a/41 Guess/java/src/Guess.java b/41_Guess/java/src/Guess.java similarity index 100% rename from 41 Guess/java/src/Guess.java rename to 41_Guess/java/src/Guess.java diff --git a/41 Guess/java/src/GuessGame.java b/41_Guess/java/src/GuessGame.java similarity index 100% rename from 41 Guess/java/src/GuessGame.java rename to 41_Guess/java/src/GuessGame.java diff --git a/41 Guess/javascript/README.md b/41_Guess/javascript/README.md similarity index 100% rename from 41 Guess/javascript/README.md rename to 41_Guess/javascript/README.md diff --git a/41 Guess/javascript/guess.html b/41_Guess/javascript/guess.html similarity index 100% rename from 41 Guess/javascript/guess.html rename to 41_Guess/javascript/guess.html diff --git a/41 Guess/javascript/guess.js b/41_Guess/javascript/guess.js similarity index 100% rename from 41 Guess/javascript/guess.js rename to 41_Guess/javascript/guess.js diff --git a/41 Guess/pascal/README.md b/41_Guess/pascal/README.md similarity index 100% rename from 41 Guess/pascal/README.md rename to 41_Guess/pascal/README.md diff --git a/41 Guess/perl/README.md b/41_Guess/perl/README.md similarity index 100% rename from 41 Guess/perl/README.md rename to 41_Guess/perl/README.md diff --git a/41 Guess/perl/guess.pl b/41_Guess/perl/guess.pl similarity index 100% rename from 41 Guess/perl/guess.pl rename to 41_Guess/perl/guess.pl diff --git a/41 Guess/python/README.md b/41_Guess/python/README.md similarity index 100% rename from 41 Guess/python/README.md rename to 41_Guess/python/README.md diff --git a/41 Guess/python/guess.py b/41_Guess/python/guess.py similarity index 100% rename from 41 Guess/python/guess.py rename to 41_Guess/python/guess.py diff --git a/41 Guess/ruby/README.md b/41_Guess/ruby/README.md similarity index 100% rename from 41 Guess/ruby/README.md rename to 41_Guess/ruby/README.md diff --git a/41 Guess/vbnet/README.md b/41_Guess/vbnet/README.md similarity index 100% rename from 41 Guess/vbnet/README.md rename to 41_Guess/vbnet/README.md diff --git a/42 Gunner/README.md b/42_Gunner/README.md similarity index 100% rename from 42 Gunner/README.md rename to 42_Gunner/README.md diff --git a/42 Gunner/csharp/README.md b/42_Gunner/csharp/README.md similarity index 100% rename from 42 Gunner/csharp/README.md rename to 42_Gunner/csharp/README.md diff --git a/42 Gunner/gunner.bas b/42_Gunner/gunner.bas similarity index 100% rename from 42 Gunner/gunner.bas rename to 42_Gunner/gunner.bas diff --git a/42 Gunner/java/Gunner.java b/42_Gunner/java/Gunner.java similarity index 100% rename from 42 Gunner/java/Gunner.java rename to 42_Gunner/java/Gunner.java diff --git a/42 Gunner/java/README.md b/42_Gunner/java/README.md similarity index 100% rename from 42 Gunner/java/README.md rename to 42_Gunner/java/README.md diff --git a/42 Gunner/javascript/README.md b/42_Gunner/javascript/README.md similarity index 100% rename from 42 Gunner/javascript/README.md rename to 42_Gunner/javascript/README.md diff --git a/42 Gunner/javascript/gunner.html b/42_Gunner/javascript/gunner.html similarity index 100% rename from 42 Gunner/javascript/gunner.html rename to 42_Gunner/javascript/gunner.html diff --git a/42 Gunner/javascript/gunner.js b/42_Gunner/javascript/gunner.js similarity index 100% rename from 42 Gunner/javascript/gunner.js rename to 42_Gunner/javascript/gunner.js diff --git a/42 Gunner/pascal/README.md b/42_Gunner/pascal/README.md similarity index 100% rename from 42 Gunner/pascal/README.md rename to 42_Gunner/pascal/README.md diff --git a/42 Gunner/perl/README.md b/42_Gunner/perl/README.md similarity index 100% rename from 42 Gunner/perl/README.md rename to 42_Gunner/perl/README.md diff --git a/42 Gunner/python/README.md b/42_Gunner/python/README.md similarity index 100% rename from 42 Gunner/python/README.md rename to 42_Gunner/python/README.md diff --git a/42 Gunner/python/gunner.py b/42_Gunner/python/gunner.py similarity index 100% rename from 42 Gunner/python/gunner.py rename to 42_Gunner/python/gunner.py diff --git a/42 Gunner/ruby/README.md b/42_Gunner/ruby/README.md similarity index 100% rename from 42 Gunner/ruby/README.md rename to 42_Gunner/ruby/README.md diff --git a/42 Gunner/vbnet/README.md b/42_Gunner/vbnet/README.md similarity index 100% rename from 42 Gunner/vbnet/README.md rename to 42_Gunner/vbnet/README.md diff --git a/43 Hammurabi/README.md b/43_Hammurabi/README.md similarity index 100% rename from 43 Hammurabi/README.md rename to 43_Hammurabi/README.md diff --git a/43 Hammurabi/csharp/Game.csproj b/43_Hammurabi/csharp/Game.csproj similarity index 100% rename from 43 Hammurabi/csharp/Game.csproj rename to 43_Hammurabi/csharp/Game.csproj diff --git a/43 Hammurabi/csharp/Hammurabi.sln b/43_Hammurabi/csharp/Hammurabi.sln similarity index 100% rename from 43 Hammurabi/csharp/Hammurabi.sln rename to 43_Hammurabi/csharp/Hammurabi.sln diff --git a/43 Hammurabi/csharp/README.md b/43_Hammurabi/csharp/README.md similarity index 100% rename from 43 Hammurabi/csharp/README.md rename to 43_Hammurabi/csharp/README.md diff --git a/43 Hammurabi/csharp/src/ActionResult.cs b/43_Hammurabi/csharp/src/ActionResult.cs similarity index 100% rename from 43 Hammurabi/csharp/src/ActionResult.cs rename to 43_Hammurabi/csharp/src/ActionResult.cs diff --git a/43 Hammurabi/csharp/src/Controller.cs b/43_Hammurabi/csharp/src/Controller.cs similarity index 100% rename from 43 Hammurabi/csharp/src/Controller.cs rename to 43_Hammurabi/csharp/src/Controller.cs diff --git a/43 Hammurabi/csharp/src/GameResult.cs b/43_Hammurabi/csharp/src/GameResult.cs similarity index 100% rename from 43 Hammurabi/csharp/src/GameResult.cs rename to 43_Hammurabi/csharp/src/GameResult.cs diff --git a/43 Hammurabi/csharp/src/GameState.cs b/43_Hammurabi/csharp/src/GameState.cs similarity index 100% rename from 43 Hammurabi/csharp/src/GameState.cs rename to 43_Hammurabi/csharp/src/GameState.cs diff --git a/43 Hammurabi/csharp/src/GreatOffence.cs b/43_Hammurabi/csharp/src/GreatOffence.cs similarity index 100% rename from 43 Hammurabi/csharp/src/GreatOffence.cs rename to 43_Hammurabi/csharp/src/GreatOffence.cs diff --git a/43 Hammurabi/csharp/src/PerformanceRating.cs b/43_Hammurabi/csharp/src/PerformanceRating.cs similarity index 100% rename from 43 Hammurabi/csharp/src/PerformanceRating.cs rename to 43_Hammurabi/csharp/src/PerformanceRating.cs diff --git a/43 Hammurabi/csharp/src/Program.cs b/43_Hammurabi/csharp/src/Program.cs similarity index 100% rename from 43 Hammurabi/csharp/src/Program.cs rename to 43_Hammurabi/csharp/src/Program.cs diff --git a/43 Hammurabi/csharp/src/Rules.cs b/43_Hammurabi/csharp/src/Rules.cs similarity index 100% rename from 43 Hammurabi/csharp/src/Rules.cs rename to 43_Hammurabi/csharp/src/Rules.cs diff --git a/43 Hammurabi/csharp/src/View.cs b/43_Hammurabi/csharp/src/View.cs similarity index 100% rename from 43 Hammurabi/csharp/src/View.cs rename to 43_Hammurabi/csharp/src/View.cs diff --git a/43 Hammurabi/hammurabi.bas b/43_Hammurabi/hammurabi.bas similarity index 100% rename from 43 Hammurabi/hammurabi.bas rename to 43_Hammurabi/hammurabi.bas diff --git a/43 Hammurabi/java/README.md b/43_Hammurabi/java/README.md similarity index 100% rename from 43 Hammurabi/java/README.md rename to 43_Hammurabi/java/README.md diff --git a/43 Hammurabi/java/src/Hamurabi.java b/43_Hammurabi/java/src/Hamurabi.java similarity index 100% rename from 43 Hammurabi/java/src/Hamurabi.java rename to 43_Hammurabi/java/src/Hamurabi.java diff --git a/43 Hammurabi/java/src/HamurabiGame.java b/43_Hammurabi/java/src/HamurabiGame.java similarity index 100% rename from 43 Hammurabi/java/src/HamurabiGame.java rename to 43_Hammurabi/java/src/HamurabiGame.java diff --git a/43 Hammurabi/javascript/README.md b/43_Hammurabi/javascript/README.md similarity index 100% rename from 43 Hammurabi/javascript/README.md rename to 43_Hammurabi/javascript/README.md diff --git a/43 Hammurabi/javascript/hammurabi.html b/43_Hammurabi/javascript/hammurabi.html similarity index 100% rename from 43 Hammurabi/javascript/hammurabi.html rename to 43_Hammurabi/javascript/hammurabi.html diff --git a/43 Hammurabi/javascript/hammurabi.js b/43_Hammurabi/javascript/hammurabi.js similarity index 100% rename from 43 Hammurabi/javascript/hammurabi.js rename to 43_Hammurabi/javascript/hammurabi.js diff --git a/43 Hammurabi/pascal/README.md b/43_Hammurabi/pascal/README.md similarity index 100% rename from 43 Hammurabi/pascal/README.md rename to 43_Hammurabi/pascal/README.md diff --git a/43 Hammurabi/perl/README.md b/43_Hammurabi/perl/README.md similarity index 100% rename from 43 Hammurabi/perl/README.md rename to 43_Hammurabi/perl/README.md diff --git a/43 Hammurabi/python/README.md b/43_Hammurabi/python/README.md similarity index 100% rename from 43 Hammurabi/python/README.md rename to 43_Hammurabi/python/README.md diff --git a/43 Hammurabi/python/hamurabi.py b/43_Hammurabi/python/hamurabi.py similarity index 100% rename from 43 Hammurabi/python/hamurabi.py rename to 43_Hammurabi/python/hamurabi.py diff --git a/43 Hammurabi/ruby/README.md b/43_Hammurabi/ruby/README.md similarity index 100% rename from 43 Hammurabi/ruby/README.md rename to 43_Hammurabi/ruby/README.md diff --git a/43 Hammurabi/vbnet/README.md b/43_Hammurabi/vbnet/README.md similarity index 100% rename from 43 Hammurabi/vbnet/README.md rename to 43_Hammurabi/vbnet/README.md diff --git a/44 Hangman/README.md b/44_Hangman/README.md similarity index 100% rename from 44 Hangman/README.md rename to 44_Hangman/README.md diff --git a/44 Hangman/csharp/Hangman/Graphic.cs b/44_Hangman/csharp/Hangman/Graphic.cs similarity index 100% rename from 44 Hangman/csharp/Hangman/Graphic.cs rename to 44_Hangman/csharp/Hangman/Graphic.cs diff --git a/44 Hangman/csharp/Hangman/Hangman.csproj b/44_Hangman/csharp/Hangman/Hangman.csproj similarity index 100% rename from 44 Hangman/csharp/Hangman/Hangman.csproj rename to 44_Hangman/csharp/Hangman/Hangman.csproj diff --git a/44 Hangman/csharp/Hangman/Hangman.sln b/44_Hangman/csharp/Hangman/Hangman.sln similarity index 100% rename from 44 Hangman/csharp/Hangman/Hangman.sln rename to 44_Hangman/csharp/Hangman/Hangman.sln diff --git a/44 Hangman/csharp/Hangman/Program.cs b/44_Hangman/csharp/Hangman/Program.cs similarity index 100% rename from 44 Hangman/csharp/Hangman/Program.cs rename to 44_Hangman/csharp/Hangman/Program.cs diff --git a/44 Hangman/csharp/README.md b/44_Hangman/csharp/README.md similarity index 100% rename from 44 Hangman/csharp/README.md rename to 44_Hangman/csharp/README.md diff --git a/44 Hangman/hangman.bas b/44_Hangman/hangman.bas similarity index 100% rename from 44 Hangman/hangman.bas rename to 44_Hangman/hangman.bas diff --git a/44 Hangman/java/Hangman.java b/44_Hangman/java/Hangman.java similarity index 100% rename from 44 Hangman/java/Hangman.java rename to 44_Hangman/java/Hangman.java diff --git a/44 Hangman/java/README.md b/44_Hangman/java/README.md similarity index 100% rename from 44 Hangman/java/README.md rename to 44_Hangman/java/README.md diff --git a/44 Hangman/javascript/README.md b/44_Hangman/javascript/README.md similarity index 100% rename from 44 Hangman/javascript/README.md rename to 44_Hangman/javascript/README.md diff --git a/44 Hangman/javascript/hangman.html b/44_Hangman/javascript/hangman.html similarity index 100% rename from 44 Hangman/javascript/hangman.html rename to 44_Hangman/javascript/hangman.html diff --git a/44 Hangman/javascript/hangman.js b/44_Hangman/javascript/hangman.js similarity index 100% rename from 44 Hangman/javascript/hangman.js rename to 44_Hangman/javascript/hangman.js diff --git a/44 Hangman/pascal/README.md b/44_Hangman/pascal/README.md similarity index 100% rename from 44 Hangman/pascal/README.md rename to 44_Hangman/pascal/README.md diff --git a/44 Hangman/perl/README.md b/44_Hangman/perl/README.md similarity index 100% rename from 44 Hangman/perl/README.md rename to 44_Hangman/perl/README.md diff --git a/44 Hangman/python/README.md b/44_Hangman/python/README.md similarity index 100% rename from 44 Hangman/python/README.md rename to 44_Hangman/python/README.md diff --git a/44 Hangman/python/hangman.py b/44_Hangman/python/hangman.py similarity index 100% rename from 44 Hangman/python/hangman.py rename to 44_Hangman/python/hangman.py diff --git a/44 Hangman/ruby/README.md b/44_Hangman/ruby/README.md similarity index 100% rename from 44 Hangman/ruby/README.md rename to 44_Hangman/ruby/README.md diff --git a/44 Hangman/vbnet/README.md b/44_Hangman/vbnet/README.md similarity index 100% rename from 44 Hangman/vbnet/README.md rename to 44_Hangman/vbnet/README.md diff --git a/45 Hello/README.md b/45_Hello/README.md similarity index 100% rename from 45 Hello/README.md rename to 45_Hello/README.md diff --git a/45 Hello/csharp/README.md b/45_Hello/csharp/README.md similarity index 100% rename from 45 Hello/csharp/README.md rename to 45_Hello/csharp/README.md diff --git a/45 Hello/hello.bas b/45_Hello/hello.bas similarity index 100% rename from 45 Hello/hello.bas rename to 45_Hello/hello.bas diff --git a/45 Hello/java/Hello.java b/45_Hello/java/Hello.java similarity index 100% rename from 45 Hello/java/Hello.java rename to 45_Hello/java/Hello.java diff --git a/45 Hello/java/README.md b/45_Hello/java/README.md similarity index 100% rename from 45 Hello/java/README.md rename to 45_Hello/java/README.md diff --git a/45 Hello/javascript/README.md b/45_Hello/javascript/README.md similarity index 100% rename from 45 Hello/javascript/README.md rename to 45_Hello/javascript/README.md diff --git a/45 Hello/javascript/hello.html b/45_Hello/javascript/hello.html similarity index 100% rename from 45 Hello/javascript/hello.html rename to 45_Hello/javascript/hello.html diff --git a/45 Hello/javascript/hello.js b/45_Hello/javascript/hello.js similarity index 100% rename from 45 Hello/javascript/hello.js rename to 45_Hello/javascript/hello.js diff --git a/45 Hello/pascal/README.md b/45_Hello/pascal/README.md similarity index 100% rename from 45 Hello/pascal/README.md rename to 45_Hello/pascal/README.md diff --git a/45 Hello/perl/README.md b/45_Hello/perl/README.md similarity index 100% rename from 45 Hello/perl/README.md rename to 45_Hello/perl/README.md diff --git a/45 Hello/python/README.md b/45_Hello/python/README.md similarity index 100% rename from 45 Hello/python/README.md rename to 45_Hello/python/README.md diff --git a/45 Hello/python/hello.py b/45_Hello/python/hello.py similarity index 100% rename from 45 Hello/python/hello.py rename to 45_Hello/python/hello.py diff --git a/45 Hello/ruby/README.md b/45_Hello/ruby/README.md similarity index 100% rename from 45 Hello/ruby/README.md rename to 45_Hello/ruby/README.md diff --git a/45 Hello/vbnet/README.md b/45_Hello/vbnet/README.md similarity index 100% rename from 45 Hello/vbnet/README.md rename to 45_Hello/vbnet/README.md diff --git a/46 Hexapawn/README.md b/46_Hexapawn/README.md similarity index 100% rename from 46 Hexapawn/README.md rename to 46_Hexapawn/README.md diff --git a/46 Hexapawn/csharp/Hexapawn.sln b/46_Hexapawn/csharp/Hexapawn.sln similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn.sln rename to 46_Hexapawn/csharp/Hexapawn.sln diff --git a/46 Hexapawn/csharp/Hexapawn/Board.cs b/46_Hexapawn/csharp/Hexapawn/Board.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Board.cs rename to 46_Hexapawn/csharp/Hexapawn/Board.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Cell.cs b/46_Hexapawn/csharp/Hexapawn/Cell.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Cell.cs rename to 46_Hexapawn/csharp/Hexapawn/Cell.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Computer.cs b/46_Hexapawn/csharp/Hexapawn/Computer.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Computer.cs rename to 46_Hexapawn/csharp/Hexapawn/Computer.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Game.cs b/46_Hexapawn/csharp/Hexapawn/Game.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Game.cs rename to 46_Hexapawn/csharp/Hexapawn/Game.cs diff --git a/46 Hexapawn/csharp/Hexapawn/GameSeries.cs b/46_Hexapawn/csharp/Hexapawn/GameSeries.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/GameSeries.cs rename to 46_Hexapawn/csharp/Hexapawn/GameSeries.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj b/46_Hexapawn/csharp/Hexapawn/Hexapawn.csproj similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Hexapawn.csproj rename to 46_Hexapawn/csharp/Hexapawn/Hexapawn.csproj diff --git a/46 Hexapawn/csharp/Hexapawn/Human.cs b/46_Hexapawn/csharp/Hexapawn/Human.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Human.cs rename to 46_Hexapawn/csharp/Hexapawn/Human.cs diff --git a/46 Hexapawn/csharp/Hexapawn/IPlayer.cs b/46_Hexapawn/csharp/Hexapawn/IPlayer.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/IPlayer.cs rename to 46_Hexapawn/csharp/Hexapawn/IPlayer.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Input.cs b/46_Hexapawn/csharp/Hexapawn/Input.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Input.cs rename to 46_Hexapawn/csharp/Hexapawn/Input.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Move.cs b/46_Hexapawn/csharp/Hexapawn/Move.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Move.cs rename to 46_Hexapawn/csharp/Hexapawn/Move.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Pawn.cs b/46_Hexapawn/csharp/Hexapawn/Pawn.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Pawn.cs rename to 46_Hexapawn/csharp/Hexapawn/Pawn.cs diff --git a/46 Hexapawn/csharp/Hexapawn/Program.cs b/46_Hexapawn/csharp/Hexapawn/Program.cs similarity index 100% rename from 46 Hexapawn/csharp/Hexapawn/Program.cs rename to 46_Hexapawn/csharp/Hexapawn/Program.cs diff --git a/46 Hexapawn/csharp/README.md b/46_Hexapawn/csharp/README.md similarity index 100% rename from 46 Hexapawn/csharp/README.md rename to 46_Hexapawn/csharp/README.md diff --git a/46 Hexapawn/hexapawn.bas b/46_Hexapawn/hexapawn.bas similarity index 100% rename from 46 Hexapawn/hexapawn.bas rename to 46_Hexapawn/hexapawn.bas diff --git a/46 Hexapawn/java/README.md b/46_Hexapawn/java/README.md similarity index 100% rename from 46 Hexapawn/java/README.md rename to 46_Hexapawn/java/README.md diff --git a/46 Hexapawn/javascript/README.md b/46_Hexapawn/javascript/README.md similarity index 100% rename from 46 Hexapawn/javascript/README.md rename to 46_Hexapawn/javascript/README.md diff --git a/46 Hexapawn/javascript/hexapawn.html b/46_Hexapawn/javascript/hexapawn.html similarity index 100% rename from 46 Hexapawn/javascript/hexapawn.html rename to 46_Hexapawn/javascript/hexapawn.html diff --git a/46 Hexapawn/javascript/hexapawn.js b/46_Hexapawn/javascript/hexapawn.js similarity index 100% rename from 46 Hexapawn/javascript/hexapawn.js rename to 46_Hexapawn/javascript/hexapawn.js diff --git a/46 Hexapawn/pascal/README.md b/46_Hexapawn/pascal/README.md similarity index 100% rename from 46 Hexapawn/pascal/README.md rename to 46_Hexapawn/pascal/README.md diff --git a/46 Hexapawn/perl/README.md b/46_Hexapawn/perl/README.md similarity index 100% rename from 46 Hexapawn/perl/README.md rename to 46_Hexapawn/perl/README.md diff --git a/46 Hexapawn/python/README.md b/46_Hexapawn/python/README.md similarity index 100% rename from 46 Hexapawn/python/README.md rename to 46_Hexapawn/python/README.md diff --git a/46 Hexapawn/python/hexapawn.py b/46_Hexapawn/python/hexapawn.py similarity index 100% rename from 46 Hexapawn/python/hexapawn.py rename to 46_Hexapawn/python/hexapawn.py diff --git a/46 Hexapawn/ruby/README.md b/46_Hexapawn/ruby/README.md similarity index 100% rename from 46 Hexapawn/ruby/README.md rename to 46_Hexapawn/ruby/README.md diff --git a/46 Hexapawn/vbnet/README.md b/46_Hexapawn/vbnet/README.md similarity index 100% rename from 46 Hexapawn/vbnet/README.md rename to 46_Hexapawn/vbnet/README.md diff --git a/47 Hi-Lo/README.md b/47_Hi-Lo/README.md similarity index 100% rename from 47 Hi-Lo/README.md rename to 47_Hi-Lo/README.md diff --git a/47 Hi-Lo/csharp/README.md b/47_Hi-Lo/csharp/README.md similarity index 100% rename from 47 Hi-Lo/csharp/README.md rename to 47_Hi-Lo/csharp/README.md diff --git a/47 Hi-Lo/csharp/hi-lo.cs b/47_Hi-Lo/csharp/hi-lo.cs similarity index 100% rename from 47 Hi-Lo/csharp/hi-lo.cs rename to 47_Hi-Lo/csharp/hi-lo.cs diff --git a/47 Hi-Lo/csharp/hi-lo.csproj b/47_Hi-Lo/csharp/hi-lo.csproj similarity index 100% rename from 47 Hi-Lo/csharp/hi-lo.csproj rename to 47_Hi-Lo/csharp/hi-lo.csproj diff --git a/47 Hi-Lo/hi-lo.bas b/47_Hi-Lo/hi-lo.bas similarity index 100% rename from 47 Hi-Lo/hi-lo.bas rename to 47_Hi-Lo/hi-lo.bas diff --git a/47 Hi-Lo/java/README.md b/47_Hi-Lo/java/README.md similarity index 100% rename from 47 Hi-Lo/java/README.md rename to 47_Hi-Lo/java/README.md diff --git a/47 Hi-Lo/java/src/HiLo.java b/47_Hi-Lo/java/src/HiLo.java similarity index 100% rename from 47 Hi-Lo/java/src/HiLo.java rename to 47_Hi-Lo/java/src/HiLo.java diff --git a/47 Hi-Lo/java/src/HiLoGame.java b/47_Hi-Lo/java/src/HiLoGame.java similarity index 100% rename from 47 Hi-Lo/java/src/HiLoGame.java rename to 47_Hi-Lo/java/src/HiLoGame.java diff --git a/47 Hi-Lo/javascript/README.md b/47_Hi-Lo/javascript/README.md similarity index 100% rename from 47 Hi-Lo/javascript/README.md rename to 47_Hi-Lo/javascript/README.md diff --git a/47 Hi-Lo/javascript/hi-lo.html b/47_Hi-Lo/javascript/hi-lo.html similarity index 100% rename from 47 Hi-Lo/javascript/hi-lo.html rename to 47_Hi-Lo/javascript/hi-lo.html diff --git a/47 Hi-Lo/javascript/hi-lo.js b/47_Hi-Lo/javascript/hi-lo.js similarity index 100% rename from 47 Hi-Lo/javascript/hi-lo.js rename to 47_Hi-Lo/javascript/hi-lo.js diff --git a/47 Hi-Lo/pascal/README.md b/47_Hi-Lo/pascal/README.md similarity index 100% rename from 47 Hi-Lo/pascal/README.md rename to 47_Hi-Lo/pascal/README.md diff --git a/47 Hi-Lo/perl/README.md b/47_Hi-Lo/perl/README.md similarity index 100% rename from 47 Hi-Lo/perl/README.md rename to 47_Hi-Lo/perl/README.md diff --git a/47 Hi-Lo/perl/hi-lo.pl b/47_Hi-Lo/perl/hi-lo.pl similarity index 100% rename from 47 Hi-Lo/perl/hi-lo.pl rename to 47_Hi-Lo/perl/hi-lo.pl diff --git a/47 Hi-Lo/python/README.md b/47_Hi-Lo/python/README.md similarity index 100% rename from 47 Hi-Lo/python/README.md rename to 47_Hi-Lo/python/README.md diff --git a/47 Hi-Lo/python/hilo.py b/47_Hi-Lo/python/hilo.py similarity index 100% rename from 47 Hi-Lo/python/hilo.py rename to 47_Hi-Lo/python/hilo.py diff --git a/47 Hi-Lo/ruby/README.md b/47_Hi-Lo/ruby/README.md similarity index 100% rename from 47 Hi-Lo/ruby/README.md rename to 47_Hi-Lo/ruby/README.md diff --git a/47 Hi-Lo/vbnet/README.md b/47_Hi-Lo/vbnet/README.md similarity index 100% rename from 47 Hi-Lo/vbnet/README.md rename to 47_Hi-Lo/vbnet/README.md diff --git a/48 High IQ/README.md b/48_High_IQ/README.md similarity index 100% rename from 48 High IQ/README.md rename to 48_High_IQ/README.md diff --git a/48 High IQ/csharp/README.md b/48_High_IQ/csharp/README.md similarity index 100% rename from 48 High IQ/csharp/README.md rename to 48_High_IQ/csharp/README.md diff --git a/48 High IQ/highiq.bas b/48_High_IQ/highiq.bas similarity index 100% rename from 48 High IQ/highiq.bas rename to 48_High_IQ/highiq.bas diff --git a/48 High IQ/java/README.md b/48_High_IQ/java/README.md similarity index 100% rename from 48 High IQ/java/README.md rename to 48_High_IQ/java/README.md diff --git a/48 High IQ/javascript/README.md b/48_High_IQ/javascript/README.md similarity index 100% rename from 48 High IQ/javascript/README.md rename to 48_High_IQ/javascript/README.md diff --git a/48 High IQ/javascript/highiq.html b/48_High_IQ/javascript/highiq.html similarity index 100% rename from 48 High IQ/javascript/highiq.html rename to 48_High_IQ/javascript/highiq.html diff --git a/48 High IQ/javascript/highiq.js b/48_High_IQ/javascript/highiq.js similarity index 100% rename from 48 High IQ/javascript/highiq.js rename to 48_High_IQ/javascript/highiq.js diff --git a/48 High IQ/pascal/README.md b/48_High_IQ/pascal/README.md similarity index 100% rename from 48 High IQ/pascal/README.md rename to 48_High_IQ/pascal/README.md diff --git a/48 High IQ/perl/README.md b/48_High_IQ/perl/README.md similarity index 100% rename from 48 High IQ/perl/README.md rename to 48_High_IQ/perl/README.md diff --git a/48 High IQ/python/README.md b/48_High_IQ/python/README.md similarity index 100% rename from 48 High IQ/python/README.md rename to 48_High_IQ/python/README.md diff --git a/48 High IQ/ruby/README.md b/48_High_IQ/ruby/README.md similarity index 100% rename from 48 High IQ/ruby/README.md rename to 48_High_IQ/ruby/README.md diff --git a/48 High IQ/vbnet/README.md b/48_High_IQ/vbnet/README.md similarity index 100% rename from 48 High IQ/vbnet/README.md rename to 48_High_IQ/vbnet/README.md diff --git a/49 Hockey/README.md b/49_Hockey/README.md similarity index 100% rename from 49 Hockey/README.md rename to 49_Hockey/README.md diff --git a/49 Hockey/csharp/README.md b/49_Hockey/csharp/README.md similarity index 100% rename from 49 Hockey/csharp/README.md rename to 49_Hockey/csharp/README.md diff --git a/49 Hockey/hockey.bas b/49_Hockey/hockey.bas similarity index 100% rename from 49 Hockey/hockey.bas rename to 49_Hockey/hockey.bas diff --git a/49 Hockey/java/README.md b/49_Hockey/java/README.md similarity index 100% rename from 49 Hockey/java/README.md rename to 49_Hockey/java/README.md diff --git a/49 Hockey/javascript/README.md b/49_Hockey/javascript/README.md similarity index 100% rename from 49 Hockey/javascript/README.md rename to 49_Hockey/javascript/README.md diff --git a/49 Hockey/javascript/hockey.html b/49_Hockey/javascript/hockey.html similarity index 100% rename from 49 Hockey/javascript/hockey.html rename to 49_Hockey/javascript/hockey.html diff --git a/49 Hockey/javascript/hockey.js b/49_Hockey/javascript/hockey.js similarity index 100% rename from 49 Hockey/javascript/hockey.js rename to 49_Hockey/javascript/hockey.js diff --git a/49 Hockey/pascal/README.md b/49_Hockey/pascal/README.md similarity index 100% rename from 49 Hockey/pascal/README.md rename to 49_Hockey/pascal/README.md diff --git a/49 Hockey/perl/README.md b/49_Hockey/perl/README.md similarity index 100% rename from 49 Hockey/perl/README.md rename to 49_Hockey/perl/README.md diff --git a/49 Hockey/python/README.md b/49_Hockey/python/README.md similarity index 100% rename from 49 Hockey/python/README.md rename to 49_Hockey/python/README.md diff --git a/49 Hockey/ruby/README.md b/49_Hockey/ruby/README.md similarity index 100% rename from 49 Hockey/ruby/README.md rename to 49_Hockey/ruby/README.md diff --git a/49 Hockey/vbnet/README.md b/49_Hockey/vbnet/README.md similarity index 100% rename from 49 Hockey/vbnet/README.md rename to 49_Hockey/vbnet/README.md diff --git a/50 Horserace/README.md b/50_Horserace/README.md similarity index 100% rename from 50 Horserace/README.md rename to 50_Horserace/README.md diff --git a/50 Horserace/csharp/README.md b/50_Horserace/csharp/README.md similarity index 100% rename from 50 Horserace/csharp/README.md rename to 50_Horserace/csharp/README.md diff --git a/50 Horserace/horserace.bas b/50_Horserace/horserace.bas similarity index 100% rename from 50 Horserace/horserace.bas rename to 50_Horserace/horserace.bas diff --git a/50 Horserace/java/README.md b/50_Horserace/java/README.md similarity index 100% rename from 50 Horserace/java/README.md rename to 50_Horserace/java/README.md diff --git a/50 Horserace/javascript/README.md b/50_Horserace/javascript/README.md similarity index 100% rename from 50 Horserace/javascript/README.md rename to 50_Horserace/javascript/README.md diff --git a/50 Horserace/javascript/horserace.html b/50_Horserace/javascript/horserace.html similarity index 100% rename from 50 Horserace/javascript/horserace.html rename to 50_Horserace/javascript/horserace.html diff --git a/50 Horserace/javascript/horserace.js b/50_Horserace/javascript/horserace.js similarity index 100% rename from 50 Horserace/javascript/horserace.js rename to 50_Horserace/javascript/horserace.js diff --git a/50 Horserace/pascal/README.md b/50_Horserace/pascal/README.md similarity index 100% rename from 50 Horserace/pascal/README.md rename to 50_Horserace/pascal/README.md diff --git a/50 Horserace/perl/README.md b/50_Horserace/perl/README.md similarity index 100% rename from 50 Horserace/perl/README.md rename to 50_Horserace/perl/README.md diff --git a/50 Horserace/python/README.md b/50_Horserace/python/README.md similarity index 100% rename from 50 Horserace/python/README.md rename to 50_Horserace/python/README.md diff --git a/50 Horserace/ruby/README.md b/50_Horserace/ruby/README.md similarity index 100% rename from 50 Horserace/ruby/README.md rename to 50_Horserace/ruby/README.md diff --git a/50 Horserace/vbnet/README.md b/50_Horserace/vbnet/README.md similarity index 100% rename from 50 Horserace/vbnet/README.md rename to 50_Horserace/vbnet/README.md diff --git a/51 Hurkle/README.md b/51_Hurkle/README.md similarity index 100% rename from 51 Hurkle/README.md rename to 51_Hurkle/README.md diff --git a/51 Hurkle/csharp/.gitignore b/51_Hurkle/csharp/.gitignore similarity index 100% rename from 51 Hurkle/csharp/.gitignore rename to 51_Hurkle/csharp/.gitignore diff --git a/51 Hurkle/csharp/README.md b/51_Hurkle/csharp/README.md similarity index 100% rename from 51 Hurkle/csharp/README.md rename to 51_Hurkle/csharp/README.md diff --git a/51 Hurkle/csharp/src/hurkle/CardinalDirection.cs b/51_Hurkle/csharp/src/hurkle/CardinalDirection.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/CardinalDirection.cs rename to 51_Hurkle/csharp/src/hurkle/CardinalDirection.cs diff --git a/51 Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs b/51_Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs rename to 51_Hurkle/csharp/src/hurkle/ConsoleHurkleView.cs diff --git a/51 Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs b/51_Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs rename to 51_Hurkle/csharp/src/hurkle/FailedGuessViewModel.cs diff --git a/51 Hurkle/csharp/src/hurkle/GamePoint.cs b/51_Hurkle/csharp/src/hurkle/GamePoint.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/GamePoint.cs rename to 51_Hurkle/csharp/src/hurkle/GamePoint.cs diff --git a/51 Hurkle/csharp/src/hurkle/GuessViewModel.cs b/51_Hurkle/csharp/src/hurkle/GuessViewModel.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/GuessViewModel.cs rename to 51_Hurkle/csharp/src/hurkle/GuessViewModel.cs diff --git a/51 Hurkle/csharp/src/hurkle/HurkleGame.cs b/51_Hurkle/csharp/src/hurkle/HurkleGame.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/HurkleGame.cs rename to 51_Hurkle/csharp/src/hurkle/HurkleGame.cs diff --git a/51 Hurkle/csharp/src/hurkle/IHurkleView.cs b/51_Hurkle/csharp/src/hurkle/IHurkleView.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/IHurkleView.cs rename to 51_Hurkle/csharp/src/hurkle/IHurkleView.cs diff --git a/51 Hurkle/csharp/src/hurkle/LossViewModel.cs b/51_Hurkle/csharp/src/hurkle/LossViewModel.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/LossViewModel.cs rename to 51_Hurkle/csharp/src/hurkle/LossViewModel.cs diff --git a/51 Hurkle/csharp/src/hurkle/Program.cs b/51_Hurkle/csharp/src/hurkle/Program.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/Program.cs rename to 51_Hurkle/csharp/src/hurkle/Program.cs diff --git a/51 Hurkle/csharp/src/hurkle/VictoryViewModel.cs b/51_Hurkle/csharp/src/hurkle/VictoryViewModel.cs similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/VictoryViewModel.cs rename to 51_Hurkle/csharp/src/hurkle/VictoryViewModel.cs diff --git a/51 Hurkle/csharp/src/hurkle/hurkle.csproj b/51_Hurkle/csharp/src/hurkle/hurkle.csproj similarity index 100% rename from 51 Hurkle/csharp/src/hurkle/hurkle.csproj rename to 51_Hurkle/csharp/src/hurkle/hurkle.csproj diff --git a/51 Hurkle/hurkle.bas b/51_Hurkle/hurkle.bas similarity index 100% rename from 51 Hurkle/hurkle.bas rename to 51_Hurkle/hurkle.bas diff --git a/51 Hurkle/java/README.md b/51_Hurkle/java/README.md similarity index 100% rename from 51 Hurkle/java/README.md rename to 51_Hurkle/java/README.md diff --git a/51 Hurkle/java/src/Hurkle.java b/51_Hurkle/java/src/Hurkle.java similarity index 100% rename from 51 Hurkle/java/src/Hurkle.java rename to 51_Hurkle/java/src/Hurkle.java diff --git a/51 Hurkle/java/src/HurkleGame.java b/51_Hurkle/java/src/HurkleGame.java similarity index 100% rename from 51 Hurkle/java/src/HurkleGame.java rename to 51_Hurkle/java/src/HurkleGame.java diff --git a/51 Hurkle/javascript/README.md b/51_Hurkle/javascript/README.md similarity index 100% rename from 51 Hurkle/javascript/README.md rename to 51_Hurkle/javascript/README.md diff --git a/51 Hurkle/javascript/hurkle.html b/51_Hurkle/javascript/hurkle.html similarity index 100% rename from 51 Hurkle/javascript/hurkle.html rename to 51_Hurkle/javascript/hurkle.html diff --git a/51 Hurkle/javascript/hurkle.js b/51_Hurkle/javascript/hurkle.js similarity index 100% rename from 51 Hurkle/javascript/hurkle.js rename to 51_Hurkle/javascript/hurkle.js diff --git a/51 Hurkle/pascal/README.md b/51_Hurkle/pascal/README.md similarity index 100% rename from 51 Hurkle/pascal/README.md rename to 51_Hurkle/pascal/README.md diff --git a/51 Hurkle/perl/README.md b/51_Hurkle/perl/README.md similarity index 100% rename from 51 Hurkle/perl/README.md rename to 51_Hurkle/perl/README.md diff --git a/51 Hurkle/python/README.md b/51_Hurkle/python/README.md similarity index 100% rename from 51 Hurkle/python/README.md rename to 51_Hurkle/python/README.md diff --git a/51 Hurkle/python/hurkle.py b/51_Hurkle/python/hurkle.py similarity index 100% rename from 51 Hurkle/python/hurkle.py rename to 51_Hurkle/python/hurkle.py diff --git a/51 Hurkle/ruby/README.md b/51_Hurkle/ruby/README.md similarity index 100% rename from 51 Hurkle/ruby/README.md rename to 51_Hurkle/ruby/README.md diff --git a/51 Hurkle/ruby/hurkle.rb b/51_Hurkle/ruby/hurkle.rb similarity index 100% rename from 51 Hurkle/ruby/hurkle.rb rename to 51_Hurkle/ruby/hurkle.rb diff --git a/51 Hurkle/vbnet/README.md b/51_Hurkle/vbnet/README.md similarity index 100% rename from 51 Hurkle/vbnet/README.md rename to 51_Hurkle/vbnet/README.md diff --git a/52 Kinema/README.md b/52_Kinema/README.md similarity index 100% rename from 52 Kinema/README.md rename to 52_Kinema/README.md diff --git a/52 Kinema/csharp/README.md b/52_Kinema/csharp/README.md similarity index 100% rename from 52 Kinema/csharp/README.md rename to 52_Kinema/csharp/README.md diff --git a/52 Kinema/java/README.md b/52_Kinema/java/README.md similarity index 100% rename from 52 Kinema/java/README.md rename to 52_Kinema/java/README.md diff --git a/52 Kinema/java/src/Kinema.java b/52_Kinema/java/src/Kinema.java similarity index 100% rename from 52 Kinema/java/src/Kinema.java rename to 52_Kinema/java/src/Kinema.java diff --git a/52 Kinema/java/src/KinemaGame.java b/52_Kinema/java/src/KinemaGame.java similarity index 100% rename from 52 Kinema/java/src/KinemaGame.java rename to 52_Kinema/java/src/KinemaGame.java diff --git a/52 Kinema/javascript/README.md b/52_Kinema/javascript/README.md similarity index 100% rename from 52 Kinema/javascript/README.md rename to 52_Kinema/javascript/README.md diff --git a/52 Kinema/javascript/kinema.html b/52_Kinema/javascript/kinema.html similarity index 100% rename from 52 Kinema/javascript/kinema.html rename to 52_Kinema/javascript/kinema.html diff --git a/52 Kinema/javascript/kinema.js b/52_Kinema/javascript/kinema.js similarity index 100% rename from 52 Kinema/javascript/kinema.js rename to 52_Kinema/javascript/kinema.js diff --git a/52 Kinema/kinema.bas b/52_Kinema/kinema.bas similarity index 100% rename from 52 Kinema/kinema.bas rename to 52_Kinema/kinema.bas diff --git a/52 Kinema/pascal/README.md b/52_Kinema/pascal/README.md similarity index 100% rename from 52 Kinema/pascal/README.md rename to 52_Kinema/pascal/README.md diff --git a/52 Kinema/perl/README.md b/52_Kinema/perl/README.md similarity index 100% rename from 52 Kinema/perl/README.md rename to 52_Kinema/perl/README.md diff --git a/52 Kinema/perl/kinema.pl b/52_Kinema/perl/kinema.pl similarity index 100% rename from 52 Kinema/perl/kinema.pl rename to 52_Kinema/perl/kinema.pl diff --git a/52 Kinema/python/README.md b/52_Kinema/python/README.md similarity index 100% rename from 52 Kinema/python/README.md rename to 52_Kinema/python/README.md diff --git a/52 Kinema/python/kinema.py b/52_Kinema/python/kinema.py similarity index 100% rename from 52 Kinema/python/kinema.py rename to 52_Kinema/python/kinema.py diff --git a/52 Kinema/ruby/README.md b/52_Kinema/ruby/README.md similarity index 100% rename from 52 Kinema/ruby/README.md rename to 52_Kinema/ruby/README.md diff --git a/52 Kinema/vbnet/README.md b/52_Kinema/vbnet/README.md similarity index 100% rename from 52 Kinema/vbnet/README.md rename to 52_Kinema/vbnet/README.md diff --git a/53 King/README.md b/53_King/README.md similarity index 100% rename from 53 King/README.md rename to 53_King/README.md diff --git a/53 King/csharp/README.md b/53_King/csharp/README.md similarity index 100% rename from 53 King/csharp/README.md rename to 53_King/csharp/README.md diff --git a/53 King/java/README.md b/53_King/java/README.md similarity index 100% rename from 53 King/java/README.md rename to 53_King/java/README.md diff --git a/53 King/javascript/README.md b/53_King/javascript/README.md similarity index 100% rename from 53 King/javascript/README.md rename to 53_King/javascript/README.md diff --git a/53 King/javascript/king.html b/53_King/javascript/king.html similarity index 100% rename from 53 King/javascript/king.html rename to 53_King/javascript/king.html diff --git a/53 King/javascript/king.js b/53_King/javascript/king.js similarity index 100% rename from 53 King/javascript/king.js rename to 53_King/javascript/king.js diff --git a/53 King/king.bas b/53_King/king.bas similarity index 100% rename from 53 King/king.bas rename to 53_King/king.bas diff --git a/53 King/pascal/README.md b/53_King/pascal/README.md similarity index 100% rename from 53 King/pascal/README.md rename to 53_King/pascal/README.md diff --git a/53 King/perl/README.md b/53_King/perl/README.md similarity index 100% rename from 53 King/perl/README.md rename to 53_King/perl/README.md diff --git a/53 King/python/README.md b/53_King/python/README.md similarity index 100% rename from 53 King/python/README.md rename to 53_King/python/README.md diff --git a/53 King/ruby/README.md b/53_King/ruby/README.md similarity index 100% rename from 53 King/ruby/README.md rename to 53_King/ruby/README.md diff --git a/53 King/vbnet/README.md b/53_King/vbnet/README.md similarity index 100% rename from 53 King/vbnet/README.md rename to 53_King/vbnet/README.md diff --git a/54 Letter/README.md b/54_Letter/README.md similarity index 100% rename from 54 Letter/README.md rename to 54_Letter/README.md diff --git a/54 Letter/csharp/README.md b/54_Letter/csharp/README.md similarity index 100% rename from 54 Letter/csharp/README.md rename to 54_Letter/csharp/README.md diff --git a/54 Letter/java/README.md b/54_Letter/java/README.md similarity index 100% rename from 54 Letter/java/README.md rename to 54_Letter/java/README.md diff --git a/54 Letter/java/src/Letter.java b/54_Letter/java/src/Letter.java similarity index 100% rename from 54 Letter/java/src/Letter.java rename to 54_Letter/java/src/Letter.java diff --git a/54 Letter/java/src/LetterGame.java b/54_Letter/java/src/LetterGame.java similarity index 100% rename from 54 Letter/java/src/LetterGame.java rename to 54_Letter/java/src/LetterGame.java diff --git a/54 Letter/javascript/README.md b/54_Letter/javascript/README.md similarity index 100% rename from 54 Letter/javascript/README.md rename to 54_Letter/javascript/README.md diff --git a/54 Letter/javascript/letter.html b/54_Letter/javascript/letter.html similarity index 100% rename from 54 Letter/javascript/letter.html rename to 54_Letter/javascript/letter.html diff --git a/54 Letter/javascript/letter.js b/54_Letter/javascript/letter.js similarity index 100% rename from 54 Letter/javascript/letter.js rename to 54_Letter/javascript/letter.js diff --git a/54 Letter/letter.bas b/54_Letter/letter.bas similarity index 100% rename from 54 Letter/letter.bas rename to 54_Letter/letter.bas diff --git a/54 Letter/pascal/README.md b/54_Letter/pascal/README.md similarity index 100% rename from 54 Letter/pascal/README.md rename to 54_Letter/pascal/README.md diff --git a/54 Letter/perl/README.md b/54_Letter/perl/README.md similarity index 100% rename from 54 Letter/perl/README.md rename to 54_Letter/perl/README.md diff --git a/54 Letter/perl/letter.pl b/54_Letter/perl/letter.pl similarity index 100% rename from 54 Letter/perl/letter.pl rename to 54_Letter/perl/letter.pl diff --git a/54 Letter/python/README.md b/54_Letter/python/README.md similarity index 100% rename from 54 Letter/python/README.md rename to 54_Letter/python/README.md diff --git a/54 Letter/python/letter.py b/54_Letter/python/letter.py similarity index 100% rename from 54 Letter/python/letter.py rename to 54_Letter/python/letter.py diff --git a/54 Letter/ruby/README.md b/54_Letter/ruby/README.md similarity index 100% rename from 54 Letter/ruby/README.md rename to 54_Letter/ruby/README.md diff --git a/54 Letter/vbnet/README.md b/54_Letter/vbnet/README.md similarity index 100% rename from 54 Letter/vbnet/README.md rename to 54_Letter/vbnet/README.md diff --git a/55 Life/README.md b/55_Life/README.md similarity index 100% rename from 55 Life/README.md rename to 55_Life/README.md diff --git a/55 Life/csharp/README.md b/55_Life/csharp/README.md similarity index 100% rename from 55 Life/csharp/README.md rename to 55_Life/csharp/README.md diff --git a/55 Life/java/README.md b/55_Life/java/README.md similarity index 100% rename from 55 Life/java/README.md rename to 55_Life/java/README.md diff --git a/55 Life/javascript/README.md b/55_Life/javascript/README.md similarity index 100% rename from 55 Life/javascript/README.md rename to 55_Life/javascript/README.md diff --git a/55 Life/javascript/life.html b/55_Life/javascript/life.html similarity index 100% rename from 55 Life/javascript/life.html rename to 55_Life/javascript/life.html diff --git a/55 Life/javascript/life.js b/55_Life/javascript/life.js similarity index 100% rename from 55 Life/javascript/life.js rename to 55_Life/javascript/life.js diff --git a/55 Life/life.bas b/55_Life/life.bas similarity index 100% rename from 55 Life/life.bas rename to 55_Life/life.bas diff --git a/55 Life/pascal/README.md b/55_Life/pascal/README.md similarity index 100% rename from 55 Life/pascal/README.md rename to 55_Life/pascal/README.md diff --git a/55 Life/perl/README.md b/55_Life/perl/README.md similarity index 100% rename from 55 Life/perl/README.md rename to 55_Life/perl/README.md diff --git a/55 Life/python/README.md b/55_Life/python/README.md similarity index 100% rename from 55 Life/python/README.md rename to 55_Life/python/README.md diff --git a/55 Life/python/life.py b/55_Life/python/life.py similarity index 100% rename from 55 Life/python/life.py rename to 55_Life/python/life.py diff --git a/55 Life/ruby/README.md b/55_Life/ruby/README.md similarity index 100% rename from 55 Life/ruby/README.md rename to 55_Life/ruby/README.md diff --git a/55 Life/ruby/life.rb b/55_Life/ruby/life.rb similarity index 100% rename from 55 Life/ruby/life.rb rename to 55_Life/ruby/life.rb diff --git a/55 Life/vbnet/README.md b/55_Life/vbnet/README.md similarity index 100% rename from 55 Life/vbnet/README.md rename to 55_Life/vbnet/README.md diff --git a/56 Life for Two/README.md b/56_Life_for_Two/README.md similarity index 100% rename from 56 Life for Two/README.md rename to 56_Life_for_Two/README.md diff --git a/56 Life for Two/csharp/README.md b/56_Life_for_Two/csharp/README.md similarity index 100% rename from 56 Life for Two/csharp/README.md rename to 56_Life_for_Two/csharp/README.md diff --git a/56 Life for Two/java/README.md b/56_Life_for_Two/java/README.md similarity index 100% rename from 56 Life for Two/java/README.md rename to 56_Life_for_Two/java/README.md diff --git a/56 Life for Two/javascript/README.md b/56_Life_for_Two/javascript/README.md similarity index 100% rename from 56 Life for Two/javascript/README.md rename to 56_Life_for_Two/javascript/README.md diff --git a/56 Life for Two/javascript/lifefortwo.html b/56_Life_for_Two/javascript/lifefortwo.html similarity index 100% rename from 56 Life for Two/javascript/lifefortwo.html rename to 56_Life_for_Two/javascript/lifefortwo.html diff --git a/56 Life for Two/javascript/lifefortwo.js b/56_Life_for_Two/javascript/lifefortwo.js similarity index 100% rename from 56 Life for Two/javascript/lifefortwo.js rename to 56_Life_for_Two/javascript/lifefortwo.js diff --git a/56 Life for Two/lifefortwo.bas b/56_Life_for_Two/lifefortwo.bas similarity index 100% rename from 56 Life for Two/lifefortwo.bas rename to 56_Life_for_Two/lifefortwo.bas diff --git a/56 Life for Two/pascal/README.md b/56_Life_for_Two/pascal/README.md similarity index 100% rename from 56 Life for Two/pascal/README.md rename to 56_Life_for_Two/pascal/README.md diff --git a/56 Life for Two/perl/README.md b/56_Life_for_Two/perl/README.md similarity index 100% rename from 56 Life for Two/perl/README.md rename to 56_Life_for_Two/perl/README.md diff --git a/56 Life for Two/python/README.md b/56_Life_for_Two/python/README.md similarity index 100% rename from 56 Life for Two/python/README.md rename to 56_Life_for_Two/python/README.md diff --git a/56 Life for Two/ruby/README.md b/56_Life_for_Two/ruby/README.md similarity index 100% rename from 56 Life for Two/ruby/README.md rename to 56_Life_for_Two/ruby/README.md diff --git a/56 Life for Two/vbnet/README.md b/56_Life_for_Two/vbnet/README.md similarity index 100% rename from 56 Life for Two/vbnet/README.md rename to 56_Life_for_Two/vbnet/README.md diff --git a/57 Literature Quiz/README.md b/57_Literature_Quiz/README.md similarity index 100% rename from 57 Literature Quiz/README.md rename to 57_Literature_Quiz/README.md diff --git a/57 Literature Quiz/csharp/README.md b/57_Literature_Quiz/csharp/README.md similarity index 100% rename from 57 Literature Quiz/csharp/README.md rename to 57_Literature_Quiz/csharp/README.md diff --git a/57 Literature Quiz/csharp/litquiz.cs b/57_Literature_Quiz/csharp/litquiz.cs similarity index 100% rename from 57 Literature Quiz/csharp/litquiz.cs rename to 57_Literature_Quiz/csharp/litquiz.cs diff --git a/57 Literature Quiz/java/README.md b/57_Literature_Quiz/java/README.md similarity index 100% rename from 57 Literature Quiz/java/README.md rename to 57_Literature_Quiz/java/README.md diff --git a/57 Literature Quiz/java/src/LiteratureQuiz.java b/57_Literature_Quiz/java/src/LiteratureQuiz.java similarity index 100% rename from 57 Literature Quiz/java/src/LiteratureQuiz.java rename to 57_Literature_Quiz/java/src/LiteratureQuiz.java diff --git a/57 Literature Quiz/java/src/LiteratureQuizGame.java b/57_Literature_Quiz/java/src/LiteratureQuizGame.java similarity index 100% rename from 57 Literature Quiz/java/src/LiteratureQuizGame.java rename to 57_Literature_Quiz/java/src/LiteratureQuizGame.java diff --git a/57 Literature Quiz/javascript/README.md b/57_Literature_Quiz/javascript/README.md similarity index 100% rename from 57 Literature Quiz/javascript/README.md rename to 57_Literature_Quiz/javascript/README.md diff --git a/57 Literature Quiz/javascript/literature-quiz-node.mjs b/57_Literature_Quiz/javascript/literature-quiz-node.mjs similarity index 100% rename from 57 Literature Quiz/javascript/literature-quiz-node.mjs rename to 57_Literature_Quiz/javascript/literature-quiz-node.mjs diff --git a/57 Literature Quiz/javascript/litquiz.html b/57_Literature_Quiz/javascript/litquiz.html similarity index 100% rename from 57 Literature Quiz/javascript/litquiz.html rename to 57_Literature_Quiz/javascript/litquiz.html diff --git a/57 Literature Quiz/javascript/litquiz.js b/57_Literature_Quiz/javascript/litquiz.js similarity index 100% rename from 57 Literature Quiz/javascript/litquiz.js rename to 57_Literature_Quiz/javascript/litquiz.js diff --git a/57 Literature Quiz/litquiz.bas b/57_Literature_Quiz/litquiz.bas similarity index 100% rename from 57 Literature Quiz/litquiz.bas rename to 57_Literature_Quiz/litquiz.bas diff --git a/57 Literature Quiz/pascal/README.md b/57_Literature_Quiz/pascal/README.md similarity index 100% rename from 57 Literature Quiz/pascal/README.md rename to 57_Literature_Quiz/pascal/README.md diff --git a/57 Literature Quiz/perl/README.md b/57_Literature_Quiz/perl/README.md similarity index 100% rename from 57 Literature Quiz/perl/README.md rename to 57_Literature_Quiz/perl/README.md diff --git a/57 Literature Quiz/perl/litquiz.pl b/57_Literature_Quiz/perl/litquiz.pl similarity index 100% rename from 57 Literature Quiz/perl/litquiz.pl rename to 57_Literature_Quiz/perl/litquiz.pl diff --git a/57 Literature Quiz/python/README.md b/57_Literature_Quiz/python/README.md similarity index 100% rename from 57 Literature Quiz/python/README.md rename to 57_Literature_Quiz/python/README.md diff --git a/57 Literature Quiz/python/litquiz.py b/57_Literature_Quiz/python/litquiz.py similarity index 100% rename from 57 Literature Quiz/python/litquiz.py rename to 57_Literature_Quiz/python/litquiz.py diff --git a/57 Literature Quiz/ruby/README.md b/57_Literature_Quiz/ruby/README.md similarity index 100% rename from 57 Literature Quiz/ruby/README.md rename to 57_Literature_Quiz/ruby/README.md diff --git a/57 Literature Quiz/vbnet/README.md b/57_Literature_Quiz/vbnet/README.md similarity index 100% rename from 57 Literature Quiz/vbnet/README.md rename to 57_Literature_Quiz/vbnet/README.md diff --git a/58 Love/README.md b/58_Love/README.md similarity index 100% rename from 58 Love/README.md rename to 58_Love/README.md diff --git a/58 Love/csharp/Love.sln b/58_Love/csharp/Love.sln similarity index 100% rename from 58 Love/csharp/Love.sln rename to 58_Love/csharp/Love.sln diff --git a/58 Love/csharp/Love/Input.cs b/58_Love/csharp/Love/Input.cs similarity index 100% rename from 58 Love/csharp/Love/Input.cs rename to 58_Love/csharp/Love/Input.cs diff --git a/58 Love/csharp/Love/Love.csproj b/58_Love/csharp/Love/Love.csproj similarity index 100% rename from 58 Love/csharp/Love/Love.csproj rename to 58_Love/csharp/Love/Love.csproj diff --git a/58 Love/csharp/Love/LovePattern.cs b/58_Love/csharp/Love/LovePattern.cs similarity index 100% rename from 58 Love/csharp/Love/LovePattern.cs rename to 58_Love/csharp/Love/LovePattern.cs diff --git a/58 Love/csharp/Love/Program.cs b/58_Love/csharp/Love/Program.cs similarity index 100% rename from 58 Love/csharp/Love/Program.cs rename to 58_Love/csharp/Love/Program.cs diff --git a/58 Love/csharp/Love/SourceCharacters.cs b/58_Love/csharp/Love/SourceCharacters.cs similarity index 100% rename from 58 Love/csharp/Love/SourceCharacters.cs rename to 58_Love/csharp/Love/SourceCharacters.cs diff --git a/58 Love/csharp/Love/Strings/Intro.txt b/58_Love/csharp/Love/Strings/Intro.txt similarity index 100% rename from 58 Love/csharp/Love/Strings/Intro.txt rename to 58_Love/csharp/Love/Strings/Intro.txt diff --git a/58 Love/csharp/README.md b/58_Love/csharp/README.md similarity index 100% rename from 58 Love/csharp/README.md rename to 58_Love/csharp/README.md diff --git a/58 Love/java/README.md b/58_Love/java/README.md similarity index 100% rename from 58 Love/java/README.md rename to 58_Love/java/README.md diff --git a/58 Love/java/src/Love.java b/58_Love/java/src/Love.java similarity index 100% rename from 58 Love/java/src/Love.java rename to 58_Love/java/src/Love.java diff --git a/58 Love/javascript/README.md b/58_Love/javascript/README.md similarity index 100% rename from 58 Love/javascript/README.md rename to 58_Love/javascript/README.md diff --git a/58 Love/javascript/love.html b/58_Love/javascript/love.html similarity index 100% rename from 58 Love/javascript/love.html rename to 58_Love/javascript/love.html diff --git a/58 Love/javascript/love.js b/58_Love/javascript/love.js similarity index 100% rename from 58 Love/javascript/love.js rename to 58_Love/javascript/love.js diff --git a/58 Love/love.bas b/58_Love/love.bas similarity index 100% rename from 58 Love/love.bas rename to 58_Love/love.bas diff --git a/58 Love/pascal/README.md b/58_Love/pascal/README.md similarity index 100% rename from 58 Love/pascal/README.md rename to 58_Love/pascal/README.md diff --git a/58 Love/perl/README.md b/58_Love/perl/README.md similarity index 100% rename from 58 Love/perl/README.md rename to 58_Love/perl/README.md diff --git a/58 Love/perl/love.pl b/58_Love/perl/love.pl similarity index 100% rename from 58 Love/perl/love.pl rename to 58_Love/perl/love.pl diff --git a/58 Love/python/README.md b/58_Love/python/README.md similarity index 100% rename from 58 Love/python/README.md rename to 58_Love/python/README.md diff --git a/58 Love/python/love.py b/58_Love/python/love.py similarity index 100% rename from 58 Love/python/love.py rename to 58_Love/python/love.py diff --git a/58 Love/ruby/README.md b/58_Love/ruby/README.md similarity index 100% rename from 58 Love/ruby/README.md rename to 58_Love/ruby/README.md diff --git a/58 Love/vbnet/README.md b/58_Love/vbnet/README.md similarity index 100% rename from 58 Love/vbnet/README.md rename to 58_Love/vbnet/README.md diff --git a/59 Lunar LEM Rocket/README.md b/59_Lunar_LEM_Rocket/README.md similarity index 100% rename from 59 Lunar LEM Rocket/README.md rename to 59_Lunar_LEM_Rocket/README.md diff --git a/59 Lunar LEM Rocket/csharp/README.md b/59_Lunar_LEM_Rocket/csharp/README.md similarity index 100% rename from 59 Lunar LEM Rocket/csharp/README.md rename to 59_Lunar_LEM_Rocket/csharp/README.md diff --git a/59 Lunar LEM Rocket/java/README.md b/59_Lunar_LEM_Rocket/java/README.md similarity index 100% rename from 59 Lunar LEM Rocket/java/README.md rename to 59_Lunar_LEM_Rocket/java/README.md diff --git a/59 Lunar LEM Rocket/javascript/README.md b/59_Lunar_LEM_Rocket/javascript/README.md similarity index 100% rename from 59 Lunar LEM Rocket/javascript/README.md rename to 59_Lunar_LEM_Rocket/javascript/README.md diff --git a/59 Lunar LEM Rocket/javascript/lem.html b/59_Lunar_LEM_Rocket/javascript/lem.html similarity index 100% rename from 59 Lunar LEM Rocket/javascript/lem.html rename to 59_Lunar_LEM_Rocket/javascript/lem.html diff --git a/59 Lunar LEM Rocket/javascript/lem.js b/59_Lunar_LEM_Rocket/javascript/lem.js similarity index 100% rename from 59 Lunar LEM Rocket/javascript/lem.js rename to 59_Lunar_LEM_Rocket/javascript/lem.js diff --git a/59 Lunar LEM Rocket/javascript/lunar.html b/59_Lunar_LEM_Rocket/javascript/lunar.html similarity index 100% rename from 59 Lunar LEM Rocket/javascript/lunar.html rename to 59_Lunar_LEM_Rocket/javascript/lunar.html diff --git a/59 Lunar LEM Rocket/javascript/lunar.js b/59_Lunar_LEM_Rocket/javascript/lunar.js similarity index 100% rename from 59 Lunar LEM Rocket/javascript/lunar.js rename to 59_Lunar_LEM_Rocket/javascript/lunar.js diff --git a/59 Lunar LEM Rocket/lem.bas b/59_Lunar_LEM_Rocket/lem.bas similarity index 100% rename from 59 Lunar LEM Rocket/lem.bas rename to 59_Lunar_LEM_Rocket/lem.bas diff --git a/59 Lunar LEM Rocket/lunar.bas b/59_Lunar_LEM_Rocket/lunar.bas similarity index 100% rename from 59 Lunar LEM Rocket/lunar.bas rename to 59_Lunar_LEM_Rocket/lunar.bas diff --git a/59 Lunar LEM Rocket/pascal/README.md b/59_Lunar_LEM_Rocket/pascal/README.md similarity index 100% rename from 59 Lunar LEM Rocket/pascal/README.md rename to 59_Lunar_LEM_Rocket/pascal/README.md diff --git a/59 Lunar LEM Rocket/perl/README.md b/59_Lunar_LEM_Rocket/perl/README.md similarity index 100% rename from 59 Lunar LEM Rocket/perl/README.md rename to 59_Lunar_LEM_Rocket/perl/README.md diff --git a/59 Lunar LEM Rocket/python/README.md b/59_Lunar_LEM_Rocket/python/README.md similarity index 100% rename from 59 Lunar LEM Rocket/python/README.md rename to 59_Lunar_LEM_Rocket/python/README.md diff --git a/59 Lunar LEM Rocket/python/lunar.py b/59_Lunar_LEM_Rocket/python/lunar.py similarity index 100% rename from 59 Lunar LEM Rocket/python/lunar.py rename to 59_Lunar_LEM_Rocket/python/lunar.py diff --git a/59 Lunar LEM Rocket/rocket.bas b/59_Lunar_LEM_Rocket/rocket.bas similarity index 100% rename from 59 Lunar LEM Rocket/rocket.bas rename to 59_Lunar_LEM_Rocket/rocket.bas diff --git a/59 Lunar LEM Rocket/ruby/README.md b/59_Lunar_LEM_Rocket/ruby/README.md similarity index 100% rename from 59 Lunar LEM Rocket/ruby/README.md rename to 59_Lunar_LEM_Rocket/ruby/README.md diff --git a/59 Lunar LEM Rocket/vbnet/README.md b/59_Lunar_LEM_Rocket/vbnet/README.md similarity index 100% rename from 59 Lunar LEM Rocket/vbnet/README.md rename to 59_Lunar_LEM_Rocket/vbnet/README.md diff --git a/60 Mastermind/README.md b/60_Mastermind/README.md similarity index 100% rename from 60 Mastermind/README.md rename to 60_Mastermind/README.md diff --git a/60 Mastermind/csharp/Game/Game.csproj b/60_Mastermind/csharp/Game/Game.csproj similarity index 100% rename from 60 Mastermind/csharp/Game/Game.csproj rename to 60_Mastermind/csharp/Game/Game.csproj diff --git a/60 Mastermind/csharp/Game/src/Code.cs b/60_Mastermind/csharp/Game/src/Code.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/Code.cs rename to 60_Mastermind/csharp/Game/src/Code.cs diff --git a/60 Mastermind/csharp/Game/src/CodeFactory.cs b/60_Mastermind/csharp/Game/src/CodeFactory.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/CodeFactory.cs rename to 60_Mastermind/csharp/Game/src/CodeFactory.cs diff --git a/60 Mastermind/csharp/Game/src/ColorInfo.cs b/60_Mastermind/csharp/Game/src/ColorInfo.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/ColorInfo.cs rename to 60_Mastermind/csharp/Game/src/ColorInfo.cs diff --git a/60 Mastermind/csharp/Game/src/Colors.cs b/60_Mastermind/csharp/Game/src/Colors.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/Colors.cs rename to 60_Mastermind/csharp/Game/src/Colors.cs diff --git a/60 Mastermind/csharp/Game/src/Command.cs b/60_Mastermind/csharp/Game/src/Command.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/Command.cs rename to 60_Mastermind/csharp/Game/src/Command.cs diff --git a/60 Mastermind/csharp/Game/src/Controller.cs b/60_Mastermind/csharp/Game/src/Controller.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/Controller.cs rename to 60_Mastermind/csharp/Game/src/Controller.cs diff --git a/60 Mastermind/csharp/Game/src/EnumerableExtensions.cs b/60_Mastermind/csharp/Game/src/EnumerableExtensions.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/EnumerableExtensions.cs rename to 60_Mastermind/csharp/Game/src/EnumerableExtensions.cs diff --git a/60 Mastermind/csharp/Game/src/Program.cs b/60_Mastermind/csharp/Game/src/Program.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/Program.cs rename to 60_Mastermind/csharp/Game/src/Program.cs diff --git a/60 Mastermind/csharp/Game/src/TurnResult.cs b/60_Mastermind/csharp/Game/src/TurnResult.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/TurnResult.cs rename to 60_Mastermind/csharp/Game/src/TurnResult.cs diff --git a/60 Mastermind/csharp/Game/src/View.cs b/60_Mastermind/csharp/Game/src/View.cs similarity index 100% rename from 60 Mastermind/csharp/Game/src/View.cs rename to 60_Mastermind/csharp/Game/src/View.cs diff --git a/60 Mastermind/csharp/Mastermind.sln b/60_Mastermind/csharp/Mastermind.sln similarity index 100% rename from 60 Mastermind/csharp/Mastermind.sln rename to 60_Mastermind/csharp/Mastermind.sln diff --git a/60 Mastermind/csharp/README.md b/60_Mastermind/csharp/README.md similarity index 100% rename from 60 Mastermind/csharp/README.md rename to 60_Mastermind/csharp/README.md diff --git a/60 Mastermind/java/README.md b/60_Mastermind/java/README.md similarity index 100% rename from 60 Mastermind/java/README.md rename to 60_Mastermind/java/README.md diff --git a/60 Mastermind/javascript/README.md b/60_Mastermind/javascript/README.md similarity index 100% rename from 60 Mastermind/javascript/README.md rename to 60_Mastermind/javascript/README.md diff --git a/60 Mastermind/javascript/mastermind.html b/60_Mastermind/javascript/mastermind.html similarity index 100% rename from 60 Mastermind/javascript/mastermind.html rename to 60_Mastermind/javascript/mastermind.html diff --git a/60 Mastermind/javascript/mastermind.js b/60_Mastermind/javascript/mastermind.js similarity index 100% rename from 60 Mastermind/javascript/mastermind.js rename to 60_Mastermind/javascript/mastermind.js diff --git a/60 Mastermind/mastermind.bas b/60_Mastermind/mastermind.bas similarity index 100% rename from 60 Mastermind/mastermind.bas rename to 60_Mastermind/mastermind.bas diff --git a/60 Mastermind/pascal/README.md b/60_Mastermind/pascal/README.md similarity index 100% rename from 60 Mastermind/pascal/README.md rename to 60_Mastermind/pascal/README.md diff --git a/60 Mastermind/perl/README.md b/60_Mastermind/perl/README.md similarity index 100% rename from 60 Mastermind/perl/README.md rename to 60_Mastermind/perl/README.md diff --git a/60 Mastermind/python/README.md b/60_Mastermind/python/README.md similarity index 100% rename from 60 Mastermind/python/README.md rename to 60_Mastermind/python/README.md diff --git a/60 Mastermind/python/mastermind.py b/60_Mastermind/python/mastermind.py similarity index 100% rename from 60 Mastermind/python/mastermind.py rename to 60_Mastermind/python/mastermind.py diff --git a/60 Mastermind/ruby/README.md b/60_Mastermind/ruby/README.md similarity index 100% rename from 60 Mastermind/ruby/README.md rename to 60_Mastermind/ruby/README.md diff --git a/60 Mastermind/vbnet/README.md b/60_Mastermind/vbnet/README.md similarity index 100% rename from 60 Mastermind/vbnet/README.md rename to 60_Mastermind/vbnet/README.md diff --git a/61 Math Dice/README.md b/61_Math_Dice/README.md similarity index 100% rename from 61 Math Dice/README.md rename to 61_Math_Dice/README.md diff --git a/61 Math Dice/csharp/GameState.cs b/61_Math_Dice/csharp/GameState.cs similarity index 100% rename from 61 Math Dice/csharp/GameState.cs rename to 61_Math_Dice/csharp/GameState.cs diff --git a/61 Math Dice/csharp/MathDice.csproj b/61_Math_Dice/csharp/MathDice.csproj similarity index 100% rename from 61 Math Dice/csharp/MathDice.csproj rename to 61_Math_Dice/csharp/MathDice.csproj diff --git a/61 Math Dice/csharp/MathDice.sln b/61_Math_Dice/csharp/MathDice.sln similarity index 100% rename from 61 Math Dice/csharp/MathDice.sln rename to 61_Math_Dice/csharp/MathDice.sln diff --git a/61 Math Dice/csharp/Program.cs b/61_Math_Dice/csharp/Program.cs similarity index 100% rename from 61 Math Dice/csharp/Program.cs rename to 61_Math_Dice/csharp/Program.cs diff --git a/61 Math Dice/csharp/README.md b/61_Math_Dice/csharp/README.md similarity index 100% rename from 61 Math Dice/csharp/README.md rename to 61_Math_Dice/csharp/README.md diff --git a/61 Math Dice/csharp/StringExtensions.cs b/61_Math_Dice/csharp/StringExtensions.cs similarity index 100% rename from 61 Math Dice/csharp/StringExtensions.cs rename to 61_Math_Dice/csharp/StringExtensions.cs diff --git a/61 Math Dice/java/Die.java b/61_Math_Dice/java/Die.java similarity index 100% rename from 61 Math Dice/java/Die.java rename to 61_Math_Dice/java/Die.java diff --git a/61 Math Dice/java/MathDice.java b/61_Math_Dice/java/MathDice.java similarity index 100% rename from 61 Math Dice/java/MathDice.java rename to 61_Math_Dice/java/MathDice.java diff --git a/61 Math Dice/java/README.md b/61_Math_Dice/java/README.md similarity index 100% rename from 61 Math Dice/java/README.md rename to 61_Math_Dice/java/README.md diff --git a/61 Math Dice/javascript/README.md b/61_Math_Dice/javascript/README.md similarity index 100% rename from 61 Math Dice/javascript/README.md rename to 61_Math_Dice/javascript/README.md diff --git a/61 Math Dice/javascript/mathdice.html b/61_Math_Dice/javascript/mathdice.html similarity index 100% rename from 61 Math Dice/javascript/mathdice.html rename to 61_Math_Dice/javascript/mathdice.html diff --git a/61 Math Dice/javascript/mathdice.js b/61_Math_Dice/javascript/mathdice.js similarity index 100% rename from 61 Math Dice/javascript/mathdice.js rename to 61_Math_Dice/javascript/mathdice.js diff --git a/61 Math Dice/mathdice.bas b/61_Math_Dice/mathdice.bas similarity index 100% rename from 61 Math Dice/mathdice.bas rename to 61_Math_Dice/mathdice.bas diff --git a/61 Math Dice/pascal/README.md b/61_Math_Dice/pascal/README.md similarity index 100% rename from 61 Math Dice/pascal/README.md rename to 61_Math_Dice/pascal/README.md diff --git a/61 Math Dice/pascal/mathdice.pas b/61_Math_Dice/pascal/mathdice.pas similarity index 100% rename from 61 Math Dice/pascal/mathdice.pas rename to 61_Math_Dice/pascal/mathdice.pas diff --git a/61 Math Dice/perl/README.md b/61_Math_Dice/perl/README.md similarity index 100% rename from 61 Math Dice/perl/README.md rename to 61_Math_Dice/perl/README.md diff --git a/61 Math Dice/python/README.md b/61_Math_Dice/python/README.md similarity index 100% rename from 61 Math Dice/python/README.md rename to 61_Math_Dice/python/README.md diff --git a/61 Math Dice/python/mathdice.py b/61_Math_Dice/python/mathdice.py similarity index 100% rename from 61 Math Dice/python/mathdice.py rename to 61_Math_Dice/python/mathdice.py diff --git a/61 Math Dice/ruby/README.md b/61_Math_Dice/ruby/README.md similarity index 100% rename from 61 Math Dice/ruby/README.md rename to 61_Math_Dice/ruby/README.md diff --git a/61 Math Dice/vbnet/README.md b/61_Math_Dice/vbnet/README.md similarity index 100% rename from 61 Math Dice/vbnet/README.md rename to 61_Math_Dice/vbnet/README.md diff --git a/62 Mugwump/README.md b/62_Mugwump/README.md similarity index 100% rename from 62 Mugwump/README.md rename to 62_Mugwump/README.md diff --git a/62 Mugwump/csharp/Mugwump.sln b/62_Mugwump/csharp/Mugwump.sln similarity index 100% rename from 62 Mugwump/csharp/Mugwump.sln rename to 62_Mugwump/csharp/Mugwump.sln diff --git a/62 Mugwump/csharp/Mugwump/Game.cs b/62_Mugwump/csharp/Mugwump/Game.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Game.cs rename to 62_Mugwump/csharp/Mugwump/Game.cs diff --git a/62 Mugwump/csharp/Mugwump/Grid.cs b/62_Mugwump/csharp/Mugwump/Grid.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Grid.cs rename to 62_Mugwump/csharp/Mugwump/Grid.cs diff --git a/62 Mugwump/csharp/Mugwump/Input.cs b/62_Mugwump/csharp/Mugwump/Input.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Input.cs rename to 62_Mugwump/csharp/Mugwump/Input.cs diff --git a/62 Mugwump/csharp/Mugwump/Mugwump.cs b/62_Mugwump/csharp/Mugwump/Mugwump.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Mugwump.cs rename to 62_Mugwump/csharp/Mugwump/Mugwump.cs diff --git a/62 Mugwump/csharp/Mugwump/Mugwump.csproj b/62_Mugwump/csharp/Mugwump/Mugwump.csproj similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Mugwump.csproj rename to 62_Mugwump/csharp/Mugwump/Mugwump.csproj diff --git a/62 Mugwump/csharp/Mugwump/Offset.cs b/62_Mugwump/csharp/Mugwump/Offset.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Offset.cs rename to 62_Mugwump/csharp/Mugwump/Offset.cs diff --git a/62 Mugwump/csharp/Mugwump/Position.cs b/62_Mugwump/csharp/Mugwump/Position.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Position.cs rename to 62_Mugwump/csharp/Mugwump/Position.cs diff --git a/62 Mugwump/csharp/Mugwump/Program.cs b/62_Mugwump/csharp/Mugwump/Program.cs similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Program.cs rename to 62_Mugwump/csharp/Mugwump/Program.cs diff --git a/62 Mugwump/csharp/Mugwump/Strings/Intro.txt b/62_Mugwump/csharp/Mugwump/Strings/Intro.txt similarity index 100% rename from 62 Mugwump/csharp/Mugwump/Strings/Intro.txt rename to 62_Mugwump/csharp/Mugwump/Strings/Intro.txt diff --git a/62 Mugwump/csharp/README.md b/62_Mugwump/csharp/README.md similarity index 100% rename from 62 Mugwump/csharp/README.md rename to 62_Mugwump/csharp/README.md diff --git a/62 Mugwump/java/README.md b/62_Mugwump/java/README.md similarity index 100% rename from 62 Mugwump/java/README.md rename to 62_Mugwump/java/README.md diff --git a/62 Mugwump/java/src/Mugwump.java b/62_Mugwump/java/src/Mugwump.java similarity index 100% rename from 62 Mugwump/java/src/Mugwump.java rename to 62_Mugwump/java/src/Mugwump.java diff --git a/62 Mugwump/javascript/README.md b/62_Mugwump/javascript/README.md similarity index 100% rename from 62 Mugwump/javascript/README.md rename to 62_Mugwump/javascript/README.md diff --git a/62 Mugwump/javascript/mugwump.html b/62_Mugwump/javascript/mugwump.html similarity index 100% rename from 62 Mugwump/javascript/mugwump.html rename to 62_Mugwump/javascript/mugwump.html diff --git a/62 Mugwump/javascript/mugwump.js b/62_Mugwump/javascript/mugwump.js similarity index 100% rename from 62 Mugwump/javascript/mugwump.js rename to 62_Mugwump/javascript/mugwump.js diff --git a/62 Mugwump/mugwump.bas b/62_Mugwump/mugwump.bas similarity index 100% rename from 62 Mugwump/mugwump.bas rename to 62_Mugwump/mugwump.bas diff --git a/62 Mugwump/pascal/README.md b/62_Mugwump/pascal/README.md similarity index 100% rename from 62 Mugwump/pascal/README.md rename to 62_Mugwump/pascal/README.md diff --git a/62 Mugwump/perl/README.md b/62_Mugwump/perl/README.md similarity index 100% rename from 62 Mugwump/perl/README.md rename to 62_Mugwump/perl/README.md diff --git a/62 Mugwump/python/README.md b/62_Mugwump/python/README.md similarity index 100% rename from 62 Mugwump/python/README.md rename to 62_Mugwump/python/README.md diff --git a/62 Mugwump/python/mugwump.py b/62_Mugwump/python/mugwump.py similarity index 100% rename from 62 Mugwump/python/mugwump.py rename to 62_Mugwump/python/mugwump.py diff --git a/62 Mugwump/ruby/README.md b/62_Mugwump/ruby/README.md similarity index 100% rename from 62 Mugwump/ruby/README.md rename to 62_Mugwump/ruby/README.md diff --git a/62 Mugwump/vbnet/README.md b/62_Mugwump/vbnet/README.md similarity index 100% rename from 62 Mugwump/vbnet/README.md rename to 62_Mugwump/vbnet/README.md diff --git a/63 Name/README.md b/63_Name/README.md similarity index 100% rename from 63 Name/README.md rename to 63_Name/README.md diff --git a/63 Name/csharp/Name.csproj b/63_Name/csharp/Name.csproj similarity index 100% rename from 63 Name/csharp/Name.csproj rename to 63_Name/csharp/Name.csproj diff --git a/63 Name/csharp/Name.sln b/63_Name/csharp/Name.sln similarity index 100% rename from 63 Name/csharp/Name.sln rename to 63_Name/csharp/Name.sln diff --git a/63 Name/csharp/Program.cs b/63_Name/csharp/Program.cs similarity index 100% rename from 63 Name/csharp/Program.cs rename to 63_Name/csharp/Program.cs diff --git a/63 Name/csharp/README.md b/63_Name/csharp/README.md similarity index 100% rename from 63 Name/csharp/README.md rename to 63_Name/csharp/README.md diff --git a/63 Name/csharp/StringExtensions.cs b/63_Name/csharp/StringExtensions.cs similarity index 100% rename from 63 Name/csharp/StringExtensions.cs rename to 63_Name/csharp/StringExtensions.cs diff --git a/63 Name/java/README.md b/63_Name/java/README.md similarity index 100% rename from 63 Name/java/README.md rename to 63_Name/java/README.md diff --git a/63 Name/java/main.class b/63_Name/java/main.class similarity index 100% rename from 63 Name/java/main.class rename to 63_Name/java/main.class diff --git a/63 Name/javascript/README.md b/63_Name/javascript/README.md similarity index 100% rename from 63 Name/javascript/README.md rename to 63_Name/javascript/README.md diff --git a/63 Name/javascript/name.html b/63_Name/javascript/name.html similarity index 100% rename from 63 Name/javascript/name.html rename to 63_Name/javascript/name.html diff --git a/63 Name/javascript/name.js b/63_Name/javascript/name.js similarity index 100% rename from 63 Name/javascript/name.js rename to 63_Name/javascript/name.js diff --git a/63 Name/name.bas b/63_Name/name.bas similarity index 100% rename from 63 Name/name.bas rename to 63_Name/name.bas diff --git a/63 Name/pascal/README.md b/63_Name/pascal/README.md similarity index 100% rename from 63 Name/pascal/README.md rename to 63_Name/pascal/README.md diff --git a/63 Name/perl/README.md b/63_Name/perl/README.md similarity index 100% rename from 63 Name/perl/README.md rename to 63_Name/perl/README.md diff --git a/63 Name/perl/name.pl b/63_Name/perl/name.pl similarity index 100% rename from 63 Name/perl/name.pl rename to 63_Name/perl/name.pl diff --git a/63 Name/python/README.md b/63_Name/python/README.md similarity index 100% rename from 63 Name/python/README.md rename to 63_Name/python/README.md diff --git a/63 Name/python/name.py b/63_Name/python/name.py similarity index 100% rename from 63 Name/python/name.py rename to 63_Name/python/name.py diff --git a/63 Name/ruby/README.md b/63_Name/ruby/README.md similarity index 100% rename from 63 Name/ruby/README.md rename to 63_Name/ruby/README.md diff --git a/63 Name/vbnet/README.md b/63_Name/vbnet/README.md similarity index 100% rename from 63 Name/vbnet/README.md rename to 63_Name/vbnet/README.md diff --git a/64 Nicomachus/README.md b/64_Nicomachus/README.md similarity index 100% rename from 64 Nicomachus/README.md rename to 64_Nicomachus/README.md diff --git a/64 Nicomachus/csharp/README.md b/64_Nicomachus/csharp/README.md similarity index 100% rename from 64 Nicomachus/csharp/README.md rename to 64_Nicomachus/csharp/README.md diff --git a/64 Nicomachus/java/README.md b/64_Nicomachus/java/README.md similarity index 100% rename from 64 Nicomachus/java/README.md rename to 64_Nicomachus/java/README.md diff --git a/64 Nicomachus/java/src/Nicomachus.java b/64_Nicomachus/java/src/Nicomachus.java similarity index 100% rename from 64 Nicomachus/java/src/Nicomachus.java rename to 64_Nicomachus/java/src/Nicomachus.java diff --git a/64 Nicomachus/javascript/README.md b/64_Nicomachus/javascript/README.md similarity index 100% rename from 64 Nicomachus/javascript/README.md rename to 64_Nicomachus/javascript/README.md diff --git a/64 Nicomachus/javascript/nicomachus.html b/64_Nicomachus/javascript/nicomachus.html similarity index 100% rename from 64 Nicomachus/javascript/nicomachus.html rename to 64_Nicomachus/javascript/nicomachus.html diff --git a/64 Nicomachus/javascript/nicomachus.js b/64_Nicomachus/javascript/nicomachus.js similarity index 100% rename from 64 Nicomachus/javascript/nicomachus.js rename to 64_Nicomachus/javascript/nicomachus.js diff --git a/64 Nicomachus/nicomachus.bas b/64_Nicomachus/nicomachus.bas similarity index 100% rename from 64 Nicomachus/nicomachus.bas rename to 64_Nicomachus/nicomachus.bas diff --git a/64 Nicomachus/pascal/README.md b/64_Nicomachus/pascal/README.md similarity index 100% rename from 64 Nicomachus/pascal/README.md rename to 64_Nicomachus/pascal/README.md diff --git a/64 Nicomachus/perl/README.md b/64_Nicomachus/perl/README.md similarity index 100% rename from 64 Nicomachus/perl/README.md rename to 64_Nicomachus/perl/README.md diff --git a/64 Nicomachus/perl/nicomachus.pl b/64_Nicomachus/perl/nicomachus.pl similarity index 100% rename from 64 Nicomachus/perl/nicomachus.pl rename to 64_Nicomachus/perl/nicomachus.pl diff --git a/64 Nicomachus/python/README.md b/64_Nicomachus/python/README.md similarity index 100% rename from 64 Nicomachus/python/README.md rename to 64_Nicomachus/python/README.md diff --git a/64 Nicomachus/python/nicomachus.py b/64_Nicomachus/python/nicomachus.py similarity index 100% rename from 64 Nicomachus/python/nicomachus.py rename to 64_Nicomachus/python/nicomachus.py diff --git a/64 Nicomachus/ruby/README.md b/64_Nicomachus/ruby/README.md similarity index 100% rename from 64 Nicomachus/ruby/README.md rename to 64_Nicomachus/ruby/README.md diff --git a/64 Nicomachus/vbnet/README.md b/64_Nicomachus/vbnet/README.md similarity index 100% rename from 64 Nicomachus/vbnet/README.md rename to 64_Nicomachus/vbnet/README.md diff --git a/65 Nim/README.md b/65_Nim/README.md similarity index 100% rename from 65 Nim/README.md rename to 65_Nim/README.md diff --git a/65 Nim/csharp/README.md b/65_Nim/csharp/README.md similarity index 100% rename from 65 Nim/csharp/README.md rename to 65_Nim/csharp/README.md diff --git a/65 Nim/java/README.md b/65_Nim/java/README.md similarity index 100% rename from 65 Nim/java/README.md rename to 65_Nim/java/README.md diff --git a/65 Nim/javascript/README.md b/65_Nim/javascript/README.md similarity index 100% rename from 65 Nim/javascript/README.md rename to 65_Nim/javascript/README.md diff --git a/65 Nim/javascript/nim.html b/65_Nim/javascript/nim.html similarity index 100% rename from 65 Nim/javascript/nim.html rename to 65_Nim/javascript/nim.html diff --git a/65 Nim/javascript/nim.js b/65_Nim/javascript/nim.js similarity index 100% rename from 65 Nim/javascript/nim.js rename to 65_Nim/javascript/nim.js diff --git a/65 Nim/nim.bas b/65_Nim/nim.bas similarity index 100% rename from 65 Nim/nim.bas rename to 65_Nim/nim.bas diff --git a/65 Nim/pascal/README.md b/65_Nim/pascal/README.md similarity index 100% rename from 65 Nim/pascal/README.md rename to 65_Nim/pascal/README.md diff --git a/65 Nim/perl/README.md b/65_Nim/perl/README.md similarity index 100% rename from 65 Nim/perl/README.md rename to 65_Nim/perl/README.md diff --git a/65 Nim/python/README.md b/65_Nim/python/README.md similarity index 100% rename from 65 Nim/python/README.md rename to 65_Nim/python/README.md diff --git a/65 Nim/ruby/README.md b/65_Nim/ruby/README.md similarity index 100% rename from 65 Nim/ruby/README.md rename to 65_Nim/ruby/README.md diff --git a/65 Nim/vbnet/README.md b/65_Nim/vbnet/README.md similarity index 100% rename from 65 Nim/vbnet/README.md rename to 65_Nim/vbnet/README.md diff --git a/66 Number/README.md b/66_Number/README.md similarity index 100% rename from 66 Number/README.md rename to 66_Number/README.md diff --git a/66 Number/csharp/README.md b/66_Number/csharp/README.md similarity index 100% rename from 66 Number/csharp/README.md rename to 66_Number/csharp/README.md diff --git a/66 Number/java/Number.java b/66_Number/java/Number.java similarity index 100% rename from 66 Number/java/Number.java rename to 66_Number/java/Number.java diff --git a/66 Number/java/README.md b/66_Number/java/README.md similarity index 100% rename from 66 Number/java/README.md rename to 66_Number/java/README.md diff --git a/66 Number/java/main.class b/66_Number/java/main.class similarity index 100% rename from 66 Number/java/main.class rename to 66_Number/java/main.class diff --git a/66 Number/javascript/README.md b/66_Number/javascript/README.md similarity index 100% rename from 66 Number/javascript/README.md rename to 66_Number/javascript/README.md diff --git a/66 Number/javascript/number.html b/66_Number/javascript/number.html similarity index 100% rename from 66 Number/javascript/number.html rename to 66_Number/javascript/number.html diff --git a/66 Number/javascript/number.js b/66_Number/javascript/number.js similarity index 100% rename from 66 Number/javascript/number.js rename to 66_Number/javascript/number.js diff --git a/66 Number/number.bas b/66_Number/number.bas similarity index 100% rename from 66 Number/number.bas rename to 66_Number/number.bas diff --git a/66 Number/pascal/README.md b/66_Number/pascal/README.md similarity index 100% rename from 66 Number/pascal/README.md rename to 66_Number/pascal/README.md diff --git a/66 Number/perl/README.md b/66_Number/perl/README.md similarity index 100% rename from 66 Number/perl/README.md rename to 66_Number/perl/README.md diff --git a/66 Number/perl/number.pl b/66_Number/perl/number.pl similarity index 100% rename from 66 Number/perl/number.pl rename to 66_Number/perl/number.pl diff --git a/66 Number/python/README.md b/66_Number/python/README.md similarity index 100% rename from 66 Number/python/README.md rename to 66_Number/python/README.md diff --git a/66 Number/python/number.py b/66_Number/python/number.py similarity index 100% rename from 66 Number/python/number.py rename to 66_Number/python/number.py diff --git a/66 Number/ruby/README.md b/66_Number/ruby/README.md similarity index 100% rename from 66 Number/ruby/README.md rename to 66_Number/ruby/README.md diff --git a/66 Number/vbnet/README.md b/66_Number/vbnet/README.md similarity index 100% rename from 66 Number/vbnet/README.md rename to 66_Number/vbnet/README.md diff --git a/67 One Check/README.md b/67_One_Check/README.md similarity index 100% rename from 67 One Check/README.md rename to 67_One_Check/README.md diff --git a/67 One Check/csharp/README.md b/67_One_Check/csharp/README.md similarity index 100% rename from 67 One Check/csharp/README.md rename to 67_One_Check/csharp/README.md diff --git a/67 One Check/java/OneCheck.java b/67_One_Check/java/OneCheck.java similarity index 100% rename from 67 One Check/java/OneCheck.java rename to 67_One_Check/java/OneCheck.java diff --git a/67 One Check/java/README.md b/67_One_Check/java/README.md similarity index 100% rename from 67 One Check/java/README.md rename to 67_One_Check/java/README.md diff --git a/67 One Check/javascript/README.md b/67_One_Check/javascript/README.md similarity index 100% rename from 67 One Check/javascript/README.md rename to 67_One_Check/javascript/README.md diff --git a/67 One Check/javascript/onecheck.html b/67_One_Check/javascript/onecheck.html similarity index 100% rename from 67 One Check/javascript/onecheck.html rename to 67_One_Check/javascript/onecheck.html diff --git a/67 One Check/javascript/onecheck.js b/67_One_Check/javascript/onecheck.js similarity index 100% rename from 67 One Check/javascript/onecheck.js rename to 67_One_Check/javascript/onecheck.js diff --git a/67 One Check/onecheck.bas b/67_One_Check/onecheck.bas similarity index 100% rename from 67 One Check/onecheck.bas rename to 67_One_Check/onecheck.bas diff --git a/67 One Check/pascal/README.md b/67_One_Check/pascal/README.md similarity index 100% rename from 67 One Check/pascal/README.md rename to 67_One_Check/pascal/README.md diff --git a/67 One Check/perl/README.md b/67_One_Check/perl/README.md similarity index 100% rename from 67 One Check/perl/README.md rename to 67_One_Check/perl/README.md diff --git a/67 One Check/python/README.md b/67_One_Check/python/README.md similarity index 100% rename from 67 One Check/python/README.md rename to 67_One_Check/python/README.md diff --git a/67 One Check/ruby/README.md b/67_One_Check/ruby/README.md similarity index 100% rename from 67 One Check/ruby/README.md rename to 67_One_Check/ruby/README.md diff --git a/67 One Check/vbnet/README.md b/67_One_Check/vbnet/README.md similarity index 100% rename from 67 One Check/vbnet/README.md rename to 67_One_Check/vbnet/README.md diff --git a/68 Orbit/README.md b/68_Orbit/README.md similarity index 100% rename from 68 Orbit/README.md rename to 68_Orbit/README.md diff --git a/68 Orbit/csharp/README.md b/68_Orbit/csharp/README.md similarity index 100% rename from 68 Orbit/csharp/README.md rename to 68_Orbit/csharp/README.md diff --git a/68 Orbit/java/Orbit.java b/68_Orbit/java/Orbit.java similarity index 100% rename from 68 Orbit/java/Orbit.java rename to 68_Orbit/java/Orbit.java diff --git a/68 Orbit/java/README.md b/68_Orbit/java/README.md similarity index 100% rename from 68 Orbit/java/README.md rename to 68_Orbit/java/README.md diff --git a/68 Orbit/javascript/README.md b/68_Orbit/javascript/README.md similarity index 100% rename from 68 Orbit/javascript/README.md rename to 68_Orbit/javascript/README.md diff --git a/68 Orbit/javascript/orbit.html b/68_Orbit/javascript/orbit.html similarity index 100% rename from 68 Orbit/javascript/orbit.html rename to 68_Orbit/javascript/orbit.html diff --git a/68 Orbit/javascript/orbit.js b/68_Orbit/javascript/orbit.js similarity index 100% rename from 68 Orbit/javascript/orbit.js rename to 68_Orbit/javascript/orbit.js diff --git a/68 Orbit/orbit.bas b/68_Orbit/orbit.bas similarity index 100% rename from 68 Orbit/orbit.bas rename to 68_Orbit/orbit.bas diff --git a/68 Orbit/pascal/README.md b/68_Orbit/pascal/README.md similarity index 100% rename from 68 Orbit/pascal/README.md rename to 68_Orbit/pascal/README.md diff --git a/68 Orbit/perl/README.md b/68_Orbit/perl/README.md similarity index 100% rename from 68 Orbit/perl/README.md rename to 68_Orbit/perl/README.md diff --git a/68 Orbit/python/README.md b/68_Orbit/python/README.md similarity index 100% rename from 68 Orbit/python/README.md rename to 68_Orbit/python/README.md diff --git a/68 Orbit/python/orbit.py b/68_Orbit/python/orbit.py similarity index 100% rename from 68 Orbit/python/orbit.py rename to 68_Orbit/python/orbit.py diff --git a/68 Orbit/ruby/README.md b/68_Orbit/ruby/README.md similarity index 100% rename from 68 Orbit/ruby/README.md rename to 68_Orbit/ruby/README.md diff --git a/68 Orbit/vbnet/README.md b/68_Orbit/vbnet/README.md similarity index 100% rename from 68 Orbit/vbnet/README.md rename to 68_Orbit/vbnet/README.md diff --git a/69 Pizza/README.md b/69_Pizza/README.md similarity index 100% rename from 69 Pizza/README.md rename to 69_Pizza/README.md diff --git a/69 Pizza/csharp/README.md b/69_Pizza/csharp/README.md similarity index 100% rename from 69 Pizza/csharp/README.md rename to 69_Pizza/csharp/README.md diff --git a/69 Pizza/java/README.md b/69_Pizza/java/README.md similarity index 100% rename from 69 Pizza/java/README.md rename to 69_Pizza/java/README.md diff --git a/69 Pizza/java/src/Pizza.java b/69_Pizza/java/src/Pizza.java similarity index 100% rename from 69 Pizza/java/src/Pizza.java rename to 69_Pizza/java/src/Pizza.java diff --git a/69 Pizza/java/src/PizzaGame.java b/69_Pizza/java/src/PizzaGame.java similarity index 100% rename from 69 Pizza/java/src/PizzaGame.java rename to 69_Pizza/java/src/PizzaGame.java diff --git a/69 Pizza/javascript/README.md b/69_Pizza/javascript/README.md similarity index 100% rename from 69 Pizza/javascript/README.md rename to 69_Pizza/javascript/README.md diff --git a/69 Pizza/javascript/pizza.html b/69_Pizza/javascript/pizza.html similarity index 100% rename from 69 Pizza/javascript/pizza.html rename to 69_Pizza/javascript/pizza.html diff --git a/69 Pizza/javascript/pizza.js b/69_Pizza/javascript/pizza.js similarity index 100% rename from 69 Pizza/javascript/pizza.js rename to 69_Pizza/javascript/pizza.js diff --git a/69 Pizza/pascal/README.md b/69_Pizza/pascal/README.md similarity index 100% rename from 69 Pizza/pascal/README.md rename to 69_Pizza/pascal/README.md diff --git a/69 Pizza/perl/README.md b/69_Pizza/perl/README.md similarity index 100% rename from 69 Pizza/perl/README.md rename to 69_Pizza/perl/README.md diff --git a/69 Pizza/pizza.bas b/69_Pizza/pizza.bas similarity index 100% rename from 69 Pizza/pizza.bas rename to 69_Pizza/pizza.bas diff --git a/69 Pizza/python/README.md b/69_Pizza/python/README.md similarity index 100% rename from 69 Pizza/python/README.md rename to 69_Pizza/python/README.md diff --git a/69 Pizza/python/pizza.py b/69_Pizza/python/pizza.py similarity index 100% rename from 69 Pizza/python/pizza.py rename to 69_Pizza/python/pizza.py diff --git a/69 Pizza/ruby/README.md b/69_Pizza/ruby/README.md similarity index 100% rename from 69 Pizza/ruby/README.md rename to 69_Pizza/ruby/README.md diff --git a/69 Pizza/vbnet/README.md b/69_Pizza/vbnet/README.md similarity index 100% rename from 69 Pizza/vbnet/README.md rename to 69_Pizza/vbnet/README.md diff --git a/70 Poetry/README.md b/70_Poetry/README.md similarity index 100% rename from 70 Poetry/README.md rename to 70_Poetry/README.md diff --git a/70 Poetry/csharp/README.md b/70_Poetry/csharp/README.md similarity index 100% rename from 70 Poetry/csharp/README.md rename to 70_Poetry/csharp/README.md diff --git a/70 Poetry/java/Poetry.java b/70_Poetry/java/Poetry.java similarity index 100% rename from 70 Poetry/java/Poetry.java rename to 70_Poetry/java/Poetry.java diff --git a/70 Poetry/java/README.md b/70_Poetry/java/README.md similarity index 100% rename from 70 Poetry/java/README.md rename to 70_Poetry/java/README.md diff --git a/70 Poetry/javascript/README.md b/70_Poetry/javascript/README.md similarity index 100% rename from 70 Poetry/javascript/README.md rename to 70_Poetry/javascript/README.md diff --git a/70 Poetry/javascript/poetry.html b/70_Poetry/javascript/poetry.html similarity index 100% rename from 70 Poetry/javascript/poetry.html rename to 70_Poetry/javascript/poetry.html diff --git a/70 Poetry/javascript/poetry.js b/70_Poetry/javascript/poetry.js similarity index 100% rename from 70 Poetry/javascript/poetry.js rename to 70_Poetry/javascript/poetry.js diff --git a/70 Poetry/pascal/README.md b/70_Poetry/pascal/README.md similarity index 100% rename from 70 Poetry/pascal/README.md rename to 70_Poetry/pascal/README.md diff --git a/70 Poetry/perl/README.md b/70_Poetry/perl/README.md similarity index 100% rename from 70 Poetry/perl/README.md rename to 70_Poetry/perl/README.md diff --git a/70 Poetry/perl/poetry.pl b/70_Poetry/perl/poetry.pl similarity index 100% rename from 70 Poetry/perl/poetry.pl rename to 70_Poetry/perl/poetry.pl diff --git a/70 Poetry/poetry.bas b/70_Poetry/poetry.bas similarity index 100% rename from 70 Poetry/poetry.bas rename to 70_Poetry/poetry.bas diff --git a/70 Poetry/poetry.pl b/70_Poetry/poetry.pl similarity index 100% rename from 70 Poetry/poetry.pl rename to 70_Poetry/poetry.pl diff --git a/70 Poetry/python/README.md b/70_Poetry/python/README.md similarity index 100% rename from 70 Poetry/python/README.md rename to 70_Poetry/python/README.md diff --git a/70 Poetry/python/poetry.py b/70_Poetry/python/poetry.py similarity index 100% rename from 70 Poetry/python/poetry.py rename to 70_Poetry/python/poetry.py diff --git a/70 Poetry/ruby/README.md b/70_Poetry/ruby/README.md similarity index 100% rename from 70 Poetry/ruby/README.md rename to 70_Poetry/ruby/README.md diff --git a/70 Poetry/vbnet/README.md b/70_Poetry/vbnet/README.md similarity index 100% rename from 70 Poetry/vbnet/README.md rename to 70_Poetry/vbnet/README.md diff --git a/71 Poker/README.md b/71_Poker/README.md similarity index 100% rename from 71 Poker/README.md rename to 71_Poker/README.md diff --git a/71 Poker/csharp/README.md b/71_Poker/csharp/README.md similarity index 100% rename from 71 Poker/csharp/README.md rename to 71_Poker/csharp/README.md diff --git a/71 Poker/java/README.md b/71_Poker/java/README.md similarity index 100% rename from 71 Poker/java/README.md rename to 71_Poker/java/README.md diff --git a/71 Poker/javascript/README.md b/71_Poker/javascript/README.md similarity index 100% rename from 71 Poker/javascript/README.md rename to 71_Poker/javascript/README.md diff --git a/71 Poker/javascript/poker.html b/71_Poker/javascript/poker.html similarity index 100% rename from 71 Poker/javascript/poker.html rename to 71_Poker/javascript/poker.html diff --git a/71 Poker/javascript/poker.js b/71_Poker/javascript/poker.js similarity index 100% rename from 71 Poker/javascript/poker.js rename to 71_Poker/javascript/poker.js diff --git a/71 Poker/pascal/README.md b/71_Poker/pascal/README.md similarity index 100% rename from 71 Poker/pascal/README.md rename to 71_Poker/pascal/README.md diff --git a/71 Poker/perl/README.md b/71_Poker/perl/README.md similarity index 100% rename from 71 Poker/perl/README.md rename to 71_Poker/perl/README.md diff --git a/71 Poker/poker.bas b/71_Poker/poker.bas similarity index 100% rename from 71 Poker/poker.bas rename to 71_Poker/poker.bas diff --git a/71 Poker/python/README.md b/71_Poker/python/README.md similarity index 100% rename from 71 Poker/python/README.md rename to 71_Poker/python/README.md diff --git a/71 Poker/ruby/README.md b/71_Poker/ruby/README.md similarity index 100% rename from 71 Poker/ruby/README.md rename to 71_Poker/ruby/README.md diff --git a/71 Poker/vbnet/README.md b/71_Poker/vbnet/README.md similarity index 100% rename from 71 Poker/vbnet/README.md rename to 71_Poker/vbnet/README.md diff --git a/72 Queen/README.md b/72_Queen/README.md similarity index 100% rename from 72 Queen/README.md rename to 72_Queen/README.md diff --git a/72 Queen/csharp/README.md b/72_Queen/csharp/README.md similarity index 100% rename from 72 Queen/csharp/README.md rename to 72_Queen/csharp/README.md diff --git a/72 Queen/java/README.md b/72_Queen/java/README.md similarity index 100% rename from 72 Queen/java/README.md rename to 72_Queen/java/README.md diff --git a/72 Queen/javascript/README.md b/72_Queen/javascript/README.md similarity index 100% rename from 72 Queen/javascript/README.md rename to 72_Queen/javascript/README.md diff --git a/72 Queen/javascript/queen.html b/72_Queen/javascript/queen.html similarity index 100% rename from 72 Queen/javascript/queen.html rename to 72_Queen/javascript/queen.html diff --git a/72 Queen/javascript/queen.js b/72_Queen/javascript/queen.js similarity index 100% rename from 72 Queen/javascript/queen.js rename to 72_Queen/javascript/queen.js diff --git a/72 Queen/pascal/README.md b/72_Queen/pascal/README.md similarity index 100% rename from 72 Queen/pascal/README.md rename to 72_Queen/pascal/README.md diff --git a/72 Queen/perl/README.md b/72_Queen/perl/README.md similarity index 100% rename from 72 Queen/perl/README.md rename to 72_Queen/perl/README.md diff --git a/72 Queen/python/README.md b/72_Queen/python/README.md similarity index 100% rename from 72 Queen/python/README.md rename to 72_Queen/python/README.md diff --git a/72 Queen/queen.bas b/72_Queen/queen.bas similarity index 100% rename from 72 Queen/queen.bas rename to 72_Queen/queen.bas diff --git a/72 Queen/ruby/README.md b/72_Queen/ruby/README.md similarity index 100% rename from 72 Queen/ruby/README.md rename to 72_Queen/ruby/README.md diff --git a/72 Queen/vbnet/README.md b/72_Queen/vbnet/README.md similarity index 100% rename from 72 Queen/vbnet/README.md rename to 72_Queen/vbnet/README.md diff --git a/73 Reverse/README.md b/73_Reverse/README.md similarity index 100% rename from 73 Reverse/README.md rename to 73_Reverse/README.md diff --git a/73 Reverse/csharp/README.md b/73_Reverse/csharp/README.md similarity index 100% rename from 73 Reverse/csharp/README.md rename to 73_Reverse/csharp/README.md diff --git a/73 Reverse/java/README.md b/73_Reverse/java/README.md similarity index 100% rename from 73 Reverse/java/README.md rename to 73_Reverse/java/README.md diff --git a/73 Reverse/java/Reverse.java b/73_Reverse/java/Reverse.java similarity index 100% rename from 73 Reverse/java/Reverse.java rename to 73_Reverse/java/Reverse.java diff --git a/73 Reverse/javascript/README.md b/73_Reverse/javascript/README.md similarity index 100% rename from 73 Reverse/javascript/README.md rename to 73_Reverse/javascript/README.md diff --git a/73 Reverse/javascript/reverse.html b/73_Reverse/javascript/reverse.html similarity index 100% rename from 73 Reverse/javascript/reverse.html rename to 73_Reverse/javascript/reverse.html diff --git a/73 Reverse/javascript/reverse.js b/73_Reverse/javascript/reverse.js similarity index 100% rename from 73 Reverse/javascript/reverse.js rename to 73_Reverse/javascript/reverse.js diff --git a/73 Reverse/pascal/README.md b/73_Reverse/pascal/README.md similarity index 100% rename from 73 Reverse/pascal/README.md rename to 73_Reverse/pascal/README.md diff --git a/73 Reverse/perl/README.md b/73_Reverse/perl/README.md similarity index 100% rename from 73 Reverse/perl/README.md rename to 73_Reverse/perl/README.md diff --git a/73 Reverse/python/README.md b/73_Reverse/python/README.md similarity index 100% rename from 73 Reverse/python/README.md rename to 73_Reverse/python/README.md diff --git a/73 Reverse/python/reverse.py b/73_Reverse/python/reverse.py similarity index 100% rename from 73 Reverse/python/reverse.py rename to 73_Reverse/python/reverse.py diff --git a/73 Reverse/reverse.bas b/73_Reverse/reverse.bas similarity index 100% rename from 73 Reverse/reverse.bas rename to 73_Reverse/reverse.bas diff --git a/73 Reverse/ruby/README.md b/73_Reverse/ruby/README.md similarity index 100% rename from 73 Reverse/ruby/README.md rename to 73_Reverse/ruby/README.md diff --git a/73 Reverse/vbnet/README.md b/73_Reverse/vbnet/README.md similarity index 100% rename from 73 Reverse/vbnet/README.md rename to 73_Reverse/vbnet/README.md diff --git a/73 Reverse/vbnet/Reverse.vb b/73_Reverse/vbnet/Reverse.vb similarity index 100% rename from 73 Reverse/vbnet/Reverse.vb rename to 73_Reverse/vbnet/Reverse.vb diff --git a/74 Rock Scissors Paper/README.md b/74_Rock_Scissors_Paper/README.md similarity index 100% rename from 74 Rock Scissors Paper/README.md rename to 74_Rock_Scissors_Paper/README.md diff --git a/74 Rock Scissors Paper/csharp/Choice.cs b/74_Rock_Scissors_Paper/csharp/Choice.cs similarity index 100% rename from 74 Rock Scissors Paper/csharp/Choice.cs rename to 74_Rock_Scissors_Paper/csharp/Choice.cs diff --git a/74 Rock Scissors Paper/csharp/Choices.cs b/74_Rock_Scissors_Paper/csharp/Choices.cs similarity index 100% rename from 74 Rock Scissors Paper/csharp/Choices.cs rename to 74_Rock_Scissors_Paper/csharp/Choices.cs diff --git a/74 Rock Scissors Paper/csharp/Game.cs b/74_Rock_Scissors_Paper/csharp/Game.cs similarity index 100% rename from 74 Rock Scissors Paper/csharp/Game.cs rename to 74_Rock_Scissors_Paper/csharp/Game.cs diff --git a/74 Rock Scissors Paper/csharp/Program.cs b/74_Rock_Scissors_Paper/csharp/Program.cs similarity index 100% rename from 74 Rock Scissors Paper/csharp/Program.cs rename to 74_Rock_Scissors_Paper/csharp/Program.cs diff --git a/74 Rock Scissors Paper/csharp/README.md b/74_Rock_Scissors_Paper/csharp/README.md similarity index 100% rename from 74 Rock Scissors Paper/csharp/README.md rename to 74_Rock_Scissors_Paper/csharp/README.md diff --git a/74 Rock Scissors Paper/csharp/RockScissorsPaper.csproj b/74_Rock_Scissors_Paper/csharp/RockScissorsPaper.csproj similarity index 100% rename from 74 Rock Scissors Paper/csharp/RockScissorsPaper.csproj rename to 74_Rock_Scissors_Paper/csharp/RockScissorsPaper.csproj diff --git a/74 Rock Scissors Paper/java/README.md b/74_Rock_Scissors_Paper/java/README.md similarity index 100% rename from 74 Rock Scissors Paper/java/README.md rename to 74_Rock_Scissors_Paper/java/README.md diff --git a/74 Rock Scissors Paper/java/src/RockScissors.java b/74_Rock_Scissors_Paper/java/src/RockScissors.java similarity index 100% rename from 74 Rock Scissors Paper/java/src/RockScissors.java rename to 74_Rock_Scissors_Paper/java/src/RockScissors.java diff --git a/74 Rock Scissors Paper/javascript/README.md b/74_Rock_Scissors_Paper/javascript/README.md similarity index 100% rename from 74 Rock Scissors Paper/javascript/README.md rename to 74_Rock_Scissors_Paper/javascript/README.md diff --git a/74 Rock Scissors Paper/javascript/rockscissors.html b/74_Rock_Scissors_Paper/javascript/rockscissors.html similarity index 100% rename from 74 Rock Scissors Paper/javascript/rockscissors.html rename to 74_Rock_Scissors_Paper/javascript/rockscissors.html diff --git a/74 Rock Scissors Paper/javascript/rockscissors.js b/74_Rock_Scissors_Paper/javascript/rockscissors.js similarity index 100% rename from 74 Rock Scissors Paper/javascript/rockscissors.js rename to 74_Rock_Scissors_Paper/javascript/rockscissors.js diff --git a/74 Rock Scissors Paper/pascal/README.md b/74_Rock_Scissors_Paper/pascal/README.md similarity index 100% rename from 74 Rock Scissors Paper/pascal/README.md rename to 74_Rock_Scissors_Paper/pascal/README.md diff --git a/74 Rock Scissors Paper/perl/README.md b/74_Rock_Scissors_Paper/perl/README.md similarity index 100% rename from 74 Rock Scissors Paper/perl/README.md rename to 74_Rock_Scissors_Paper/perl/README.md diff --git a/74 Rock Scissors Paper/perl/rockscissors.pl b/74_Rock_Scissors_Paper/perl/rockscissors.pl similarity index 100% rename from 74 Rock Scissors Paper/perl/rockscissors.pl rename to 74_Rock_Scissors_Paper/perl/rockscissors.pl diff --git a/74 Rock Scissors Paper/python/README.md b/74_Rock_Scissors_Paper/python/README.md similarity index 100% rename from 74 Rock Scissors Paper/python/README.md rename to 74_Rock_Scissors_Paper/python/README.md diff --git a/74 Rock Scissors Paper/python/rockscissors.py b/74_Rock_Scissors_Paper/python/rockscissors.py similarity index 100% rename from 74 Rock Scissors Paper/python/rockscissors.py rename to 74_Rock_Scissors_Paper/python/rockscissors.py diff --git a/74 Rock Scissors Paper/rockscissors.bas b/74_Rock_Scissors_Paper/rockscissors.bas similarity index 100% rename from 74 Rock Scissors Paper/rockscissors.bas rename to 74_Rock_Scissors_Paper/rockscissors.bas diff --git a/74 Rock Scissors Paper/ruby/README.md b/74_Rock_Scissors_Paper/ruby/README.md similarity index 100% rename from 74 Rock Scissors Paper/ruby/README.md rename to 74_Rock_Scissors_Paper/ruby/README.md diff --git a/74 Rock Scissors Paper/vbnet/README.md b/74_Rock_Scissors_Paper/vbnet/README.md similarity index 100% rename from 74 Rock Scissors Paper/vbnet/README.md rename to 74_Rock_Scissors_Paper/vbnet/README.md diff --git a/75 Roulette/README.md b/75_Roulette/README.md similarity index 100% rename from 75 Roulette/README.md rename to 75_Roulette/README.md diff --git a/75 Roulette/csharp/README.md b/75_Roulette/csharp/README.md similarity index 100% rename from 75 Roulette/csharp/README.md rename to 75_Roulette/csharp/README.md diff --git a/75 Roulette/java/README.md b/75_Roulette/java/README.md similarity index 100% rename from 75 Roulette/java/README.md rename to 75_Roulette/java/README.md diff --git a/75 Roulette/javascript/README.md b/75_Roulette/javascript/README.md similarity index 100% rename from 75 Roulette/javascript/README.md rename to 75_Roulette/javascript/README.md diff --git a/75 Roulette/javascript/roulette.html b/75_Roulette/javascript/roulette.html similarity index 100% rename from 75 Roulette/javascript/roulette.html rename to 75_Roulette/javascript/roulette.html diff --git a/75 Roulette/javascript/roulette.js b/75_Roulette/javascript/roulette.js similarity index 100% rename from 75 Roulette/javascript/roulette.js rename to 75_Roulette/javascript/roulette.js diff --git a/75 Roulette/pascal/README.md b/75_Roulette/pascal/README.md similarity index 100% rename from 75 Roulette/pascal/README.md rename to 75_Roulette/pascal/README.md diff --git a/75 Roulette/perl/README.md b/75_Roulette/perl/README.md similarity index 100% rename from 75 Roulette/perl/README.md rename to 75_Roulette/perl/README.md diff --git a/75 Roulette/python/README.md b/75_Roulette/python/README.md similarity index 100% rename from 75 Roulette/python/README.md rename to 75_Roulette/python/README.md diff --git a/75 Roulette/roulette.bas b/75_Roulette/roulette.bas similarity index 100% rename from 75 Roulette/roulette.bas rename to 75_Roulette/roulette.bas diff --git a/75 Roulette/ruby/README.md b/75_Roulette/ruby/README.md similarity index 100% rename from 75 Roulette/ruby/README.md rename to 75_Roulette/ruby/README.md diff --git a/75 Roulette/vbnet/README.md b/75_Roulette/vbnet/README.md similarity index 100% rename from 75 Roulette/vbnet/README.md rename to 75_Roulette/vbnet/README.md diff --git a/76 Russian Roulette/README.md b/76_Russian_Roulette/README.md similarity index 100% rename from 76 Russian Roulette/README.md rename to 76_Russian_Roulette/README.md diff --git a/76 Russian Roulette/csharp/README.md b/76_Russian_Roulette/csharp/README.md similarity index 100% rename from 76 Russian Roulette/csharp/README.md rename to 76_Russian_Roulette/csharp/README.md diff --git a/76 Russian Roulette/csharp/RussianRoulette/Program.cs b/76_Russian_Roulette/csharp/RussianRoulette/Program.cs similarity index 100% rename from 76 Russian Roulette/csharp/RussianRoulette/Program.cs rename to 76_Russian_Roulette/csharp/RussianRoulette/Program.cs diff --git a/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.csproj b/76_Russian_Roulette/csharp/RussianRoulette/RussianRoulette.csproj similarity index 100% rename from 76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.csproj rename to 76_Russian_Roulette/csharp/RussianRoulette/RussianRoulette.csproj diff --git a/76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.sln b/76_Russian_Roulette/csharp/RussianRoulette/RussianRoulette.sln similarity index 100% rename from 76 Russian Roulette/csharp/RussianRoulette/RussianRoulette.sln rename to 76_Russian_Roulette/csharp/RussianRoulette/RussianRoulette.sln diff --git a/76 Russian Roulette/java/README.md b/76_Russian_Roulette/java/README.md similarity index 100% rename from 76 Russian Roulette/java/README.md rename to 76_Russian_Roulette/java/README.md diff --git a/76 Russian Roulette/java/src/RussianRoulette.java b/76_Russian_Roulette/java/src/RussianRoulette.java similarity index 100% rename from 76 Russian Roulette/java/src/RussianRoulette.java rename to 76_Russian_Roulette/java/src/RussianRoulette.java diff --git a/76 Russian Roulette/javascript/README.md b/76_Russian_Roulette/javascript/README.md similarity index 100% rename from 76 Russian Roulette/javascript/README.md rename to 76_Russian_Roulette/javascript/README.md diff --git a/76 Russian Roulette/javascript/russianroulette.html b/76_Russian_Roulette/javascript/russianroulette.html similarity index 100% rename from 76 Russian Roulette/javascript/russianroulette.html rename to 76_Russian_Roulette/javascript/russianroulette.html diff --git a/76 Russian Roulette/javascript/russianroulette.js b/76_Russian_Roulette/javascript/russianroulette.js similarity index 100% rename from 76 Russian Roulette/javascript/russianroulette.js rename to 76_Russian_Roulette/javascript/russianroulette.js diff --git a/76 Russian Roulette/pascal/README.md b/76_Russian_Roulette/pascal/README.md similarity index 100% rename from 76 Russian Roulette/pascal/README.md rename to 76_Russian_Roulette/pascal/README.md diff --git a/76 Russian Roulette/perl/README.md b/76_Russian_Roulette/perl/README.md similarity index 100% rename from 76 Russian Roulette/perl/README.md rename to 76_Russian_Roulette/perl/README.md diff --git a/76 Russian Roulette/perl/russianroulette.pl b/76_Russian_Roulette/perl/russianroulette.pl similarity index 100% rename from 76 Russian Roulette/perl/russianroulette.pl rename to 76_Russian_Roulette/perl/russianroulette.pl diff --git a/76 Russian Roulette/python/README.md b/76_Russian_Roulette/python/README.md similarity index 100% rename from 76 Russian Roulette/python/README.md rename to 76_Russian_Roulette/python/README.md diff --git a/76 Russian Roulette/python/russianroulette.py b/76_Russian_Roulette/python/russianroulette.py similarity index 100% rename from 76 Russian Roulette/python/russianroulette.py rename to 76_Russian_Roulette/python/russianroulette.py diff --git a/76 Russian Roulette/ruby/README.md b/76_Russian_Roulette/ruby/README.md similarity index 100% rename from 76 Russian Roulette/ruby/README.md rename to 76_Russian_Roulette/ruby/README.md diff --git a/76 Russian Roulette/russianroulette.bas b/76_Russian_Roulette/russianroulette.bas similarity index 100% rename from 76 Russian Roulette/russianroulette.bas rename to 76_Russian_Roulette/russianroulette.bas diff --git a/76 Russian Roulette/vbnet/README.md b/76_Russian_Roulette/vbnet/README.md similarity index 100% rename from 76 Russian Roulette/vbnet/README.md rename to 76_Russian_Roulette/vbnet/README.md diff --git a/77 Salvo/README.md b/77_Salvo/README.md similarity index 100% rename from 77 Salvo/README.md rename to 77_Salvo/README.md diff --git a/77 Salvo/csharp/README.md b/77_Salvo/csharp/README.md similarity index 100% rename from 77 Salvo/csharp/README.md rename to 77_Salvo/csharp/README.md diff --git a/77 Salvo/java/README.md b/77_Salvo/java/README.md similarity index 100% rename from 77 Salvo/java/README.md rename to 77_Salvo/java/README.md diff --git a/77 Salvo/javascript/README.md b/77_Salvo/javascript/README.md similarity index 100% rename from 77 Salvo/javascript/README.md rename to 77_Salvo/javascript/README.md diff --git a/77 Salvo/javascript/salvo.html b/77_Salvo/javascript/salvo.html similarity index 100% rename from 77 Salvo/javascript/salvo.html rename to 77_Salvo/javascript/salvo.html diff --git a/77 Salvo/javascript/salvo.js b/77_Salvo/javascript/salvo.js similarity index 100% rename from 77 Salvo/javascript/salvo.js rename to 77_Salvo/javascript/salvo.js diff --git a/77 Salvo/pascal/README.md b/77_Salvo/pascal/README.md similarity index 100% rename from 77 Salvo/pascal/README.md rename to 77_Salvo/pascal/README.md diff --git a/77 Salvo/perl/README.md b/77_Salvo/perl/README.md similarity index 100% rename from 77 Salvo/perl/README.md rename to 77_Salvo/perl/README.md diff --git a/77 Salvo/python/README.md b/77_Salvo/python/README.md similarity index 100% rename from 77 Salvo/python/README.md rename to 77_Salvo/python/README.md diff --git a/77 Salvo/python/salvo.ipynb b/77_Salvo/python/salvo.ipynb similarity index 100% rename from 77 Salvo/python/salvo.ipynb rename to 77_Salvo/python/salvo.ipynb diff --git a/77 Salvo/python/salvo.py b/77_Salvo/python/salvo.py similarity index 100% rename from 77 Salvo/python/salvo.py rename to 77_Salvo/python/salvo.py diff --git a/77 Salvo/ruby/README.md b/77_Salvo/ruby/README.md similarity index 100% rename from 77 Salvo/ruby/README.md rename to 77_Salvo/ruby/README.md diff --git a/77 Salvo/salvo.bas b/77_Salvo/salvo.bas similarity index 100% rename from 77 Salvo/salvo.bas rename to 77_Salvo/salvo.bas diff --git a/77 Salvo/vbnet/README.md b/77_Salvo/vbnet/README.md similarity index 100% rename from 77 Salvo/vbnet/README.md rename to 77_Salvo/vbnet/README.md diff --git a/78 Sine Wave/README.md b/78_Sine_Wave/README.md similarity index 100% rename from 78 Sine Wave/README.md rename to 78_Sine_Wave/README.md diff --git a/78 Sine Wave/csharp/README.md b/78_Sine_Wave/csharp/README.md similarity index 100% rename from 78 Sine Wave/csharp/README.md rename to 78_Sine_Wave/csharp/README.md diff --git a/78 Sine Wave/csharp/SineWave/SineWave.sln b/78_Sine_Wave/csharp/SineWave/SineWave.sln similarity index 100% rename from 78 Sine Wave/csharp/SineWave/SineWave.sln rename to 78_Sine_Wave/csharp/SineWave/SineWave.sln diff --git a/78 Sine Wave/csharp/SineWave/SineWave/Program.cs b/78_Sine_Wave/csharp/SineWave/SineWave/Program.cs similarity index 100% rename from 78 Sine Wave/csharp/SineWave/SineWave/Program.cs rename to 78_Sine_Wave/csharp/SineWave/SineWave/Program.cs diff --git a/78 Sine Wave/csharp/SineWave/SineWave/SineWave.csproj b/78_Sine_Wave/csharp/SineWave/SineWave/SineWave.csproj similarity index 100% rename from 78 Sine Wave/csharp/SineWave/SineWave/SineWave.csproj rename to 78_Sine_Wave/csharp/SineWave/SineWave/SineWave.csproj diff --git a/78 Sine Wave/java/README.md b/78_Sine_Wave/java/README.md similarity index 100% rename from 78 Sine Wave/java/README.md rename to 78_Sine_Wave/java/README.md diff --git a/78 Sine Wave/java/src/SineWave.java b/78_Sine_Wave/java/src/SineWave.java similarity index 100% rename from 78 Sine Wave/java/src/SineWave.java rename to 78_Sine_Wave/java/src/SineWave.java diff --git a/78 Sine Wave/javascript/README.md b/78_Sine_Wave/javascript/README.md similarity index 100% rename from 78 Sine Wave/javascript/README.md rename to 78_Sine_Wave/javascript/README.md diff --git a/78 Sine Wave/javascript/sinewave.js b/78_Sine_Wave/javascript/sinewave.js similarity index 100% rename from 78 Sine Wave/javascript/sinewave.js rename to 78_Sine_Wave/javascript/sinewave.js diff --git a/78 Sine Wave/pascal/README.md b/78_Sine_Wave/pascal/README.md similarity index 100% rename from 78 Sine Wave/pascal/README.md rename to 78_Sine_Wave/pascal/README.md diff --git a/78 Sine Wave/perl/README.md b/78_Sine_Wave/perl/README.md similarity index 100% rename from 78 Sine Wave/perl/README.md rename to 78_Sine_Wave/perl/README.md diff --git a/78 Sine Wave/perl/sinewave.pl b/78_Sine_Wave/perl/sinewave.pl similarity index 100% rename from 78 Sine Wave/perl/sinewave.pl rename to 78_Sine_Wave/perl/sinewave.pl diff --git a/78 Sine Wave/python/README.md b/78_Sine_Wave/python/README.md similarity index 100% rename from 78 Sine Wave/python/README.md rename to 78_Sine_Wave/python/README.md diff --git a/78 Sine Wave/python/sinewave.py b/78_Sine_Wave/python/sinewave.py similarity index 100% rename from 78 Sine Wave/python/sinewave.py rename to 78_Sine_Wave/python/sinewave.py diff --git a/78 Sine Wave/ruby/README.md b/78_Sine_Wave/ruby/README.md similarity index 100% rename from 78 Sine Wave/ruby/README.md rename to 78_Sine_Wave/ruby/README.md diff --git a/78 Sine Wave/ruby/sinewave.rb b/78_Sine_Wave/ruby/sinewave.rb similarity index 100% rename from 78 Sine Wave/ruby/sinewave.rb rename to 78_Sine_Wave/ruby/sinewave.rb diff --git a/78 Sine Wave/sinewave.bas b/78_Sine_Wave/sinewave.bas similarity index 100% rename from 78 Sine Wave/sinewave.bas rename to 78_Sine_Wave/sinewave.bas diff --git a/78 Sine Wave/vbnet/README.md b/78_Sine_Wave/vbnet/README.md similarity index 100% rename from 78 Sine Wave/vbnet/README.md rename to 78_Sine_Wave/vbnet/README.md diff --git a/79 Slalom/README.md b/79_Slalom/README.md similarity index 100% rename from 79 Slalom/README.md rename to 79_Slalom/README.md diff --git a/79 Slalom/csharp/README.md b/79_Slalom/csharp/README.md similarity index 100% rename from 79 Slalom/csharp/README.md rename to 79_Slalom/csharp/README.md diff --git a/79 Slalom/java/README.md b/79_Slalom/java/README.md similarity index 100% rename from 79 Slalom/java/README.md rename to 79_Slalom/java/README.md diff --git a/79 Slalom/javascript/README.md b/79_Slalom/javascript/README.md similarity index 100% rename from 79 Slalom/javascript/README.md rename to 79_Slalom/javascript/README.md diff --git a/79 Slalom/javascript/slalom.html b/79_Slalom/javascript/slalom.html similarity index 100% rename from 79 Slalom/javascript/slalom.html rename to 79_Slalom/javascript/slalom.html diff --git a/79 Slalom/javascript/slalom.js b/79_Slalom/javascript/slalom.js similarity index 100% rename from 79 Slalom/javascript/slalom.js rename to 79_Slalom/javascript/slalom.js diff --git a/79 Slalom/pascal/README.md b/79_Slalom/pascal/README.md similarity index 100% rename from 79 Slalom/pascal/README.md rename to 79_Slalom/pascal/README.md diff --git a/79 Slalom/perl/README.md b/79_Slalom/perl/README.md similarity index 100% rename from 79 Slalom/perl/README.md rename to 79_Slalom/perl/README.md diff --git a/79 Slalom/python/README.md b/79_Slalom/python/README.md similarity index 100% rename from 79 Slalom/python/README.md rename to 79_Slalom/python/README.md diff --git a/79 Slalom/ruby/README.md b/79_Slalom/ruby/README.md similarity index 100% rename from 79 Slalom/ruby/README.md rename to 79_Slalom/ruby/README.md diff --git a/79 Slalom/slalom.bas b/79_Slalom/slalom.bas similarity index 100% rename from 79 Slalom/slalom.bas rename to 79_Slalom/slalom.bas diff --git a/79 Slalom/vbnet/README.md b/79_Slalom/vbnet/README.md similarity index 100% rename from 79 Slalom/vbnet/README.md rename to 79_Slalom/vbnet/README.md diff --git a/80 Slots/README.md b/80_Slots/README.md similarity index 100% rename from 80 Slots/README.md rename to 80_Slots/README.md diff --git a/80 Slots/csharp/README.md b/80_Slots/csharp/README.md similarity index 100% rename from 80 Slots/csharp/README.md rename to 80_Slots/csharp/README.md diff --git a/80 Slots/java/README.md b/80_Slots/java/README.md similarity index 100% rename from 80 Slots/java/README.md rename to 80_Slots/java/README.md diff --git a/80 Slots/java/src/Slots.java b/80_Slots/java/src/Slots.java similarity index 100% rename from 80 Slots/java/src/Slots.java rename to 80_Slots/java/src/Slots.java diff --git a/80 Slots/java/src/SlotsGame.java b/80_Slots/java/src/SlotsGame.java similarity index 100% rename from 80 Slots/java/src/SlotsGame.java rename to 80_Slots/java/src/SlotsGame.java diff --git a/80 Slots/javascript/README.md b/80_Slots/javascript/README.md similarity index 100% rename from 80 Slots/javascript/README.md rename to 80_Slots/javascript/README.md diff --git a/80 Slots/javascript/slots.html b/80_Slots/javascript/slots.html similarity index 100% rename from 80 Slots/javascript/slots.html rename to 80_Slots/javascript/slots.html diff --git a/80 Slots/javascript/slots.js b/80_Slots/javascript/slots.js similarity index 100% rename from 80 Slots/javascript/slots.js rename to 80_Slots/javascript/slots.js diff --git a/80 Slots/pascal/README.md b/80_Slots/pascal/README.md similarity index 100% rename from 80 Slots/pascal/README.md rename to 80_Slots/pascal/README.md diff --git a/80 Slots/perl/README.md b/80_Slots/perl/README.md similarity index 100% rename from 80 Slots/perl/README.md rename to 80_Slots/perl/README.md diff --git a/80 Slots/python/README.md b/80_Slots/python/README.md similarity index 100% rename from 80 Slots/python/README.md rename to 80_Slots/python/README.md diff --git a/80 Slots/python/slots.py b/80_Slots/python/slots.py similarity index 100% rename from 80 Slots/python/slots.py rename to 80_Slots/python/slots.py diff --git a/80 Slots/ruby/README.md b/80_Slots/ruby/README.md similarity index 100% rename from 80 Slots/ruby/README.md rename to 80_Slots/ruby/README.md diff --git a/80 Slots/slots.bas b/80_Slots/slots.bas similarity index 100% rename from 80 Slots/slots.bas rename to 80_Slots/slots.bas diff --git a/80 Slots/vbnet/README.md b/80_Slots/vbnet/README.md similarity index 100% rename from 80 Slots/vbnet/README.md rename to 80_Slots/vbnet/README.md diff --git a/81 Splat/README.md b/81_Splat/README.md similarity index 100% rename from 81 Splat/README.md rename to 81_Splat/README.md diff --git a/81 Splat/csharp/README.md b/81_Splat/csharp/README.md similarity index 100% rename from 81 Splat/csharp/README.md rename to 81_Splat/csharp/README.md diff --git a/81 Splat/java/README.md b/81_Splat/java/README.md similarity index 100% rename from 81 Splat/java/README.md rename to 81_Splat/java/README.md diff --git a/81 Splat/javascript/README.md b/81_Splat/javascript/README.md similarity index 100% rename from 81 Splat/javascript/README.md rename to 81_Splat/javascript/README.md diff --git a/81 Splat/javascript/splat.html b/81_Splat/javascript/splat.html similarity index 100% rename from 81 Splat/javascript/splat.html rename to 81_Splat/javascript/splat.html diff --git a/81 Splat/javascript/splat.js b/81_Splat/javascript/splat.js similarity index 100% rename from 81 Splat/javascript/splat.js rename to 81_Splat/javascript/splat.js diff --git a/81 Splat/pascal/README.md b/81_Splat/pascal/README.md similarity index 100% rename from 81 Splat/pascal/README.md rename to 81_Splat/pascal/README.md diff --git a/81 Splat/perl/README.md b/81_Splat/perl/README.md similarity index 100% rename from 81 Splat/perl/README.md rename to 81_Splat/perl/README.md diff --git a/81 Splat/python/README.md b/81_Splat/python/README.md similarity index 100% rename from 81 Splat/python/README.md rename to 81_Splat/python/README.md diff --git a/81 Splat/python/splat.py b/81_Splat/python/splat.py similarity index 100% rename from 81 Splat/python/splat.py rename to 81_Splat/python/splat.py diff --git a/81 Splat/ruby/README.md b/81_Splat/ruby/README.md similarity index 100% rename from 81 Splat/ruby/README.md rename to 81_Splat/ruby/README.md diff --git a/81 Splat/splat.bas b/81_Splat/splat.bas similarity index 100% rename from 81 Splat/splat.bas rename to 81_Splat/splat.bas diff --git a/81 Splat/vbnet/README.md b/81_Splat/vbnet/README.md similarity index 100% rename from 81 Splat/vbnet/README.md rename to 81_Splat/vbnet/README.md diff --git a/82 Stars/README.md b/82_Stars/README.md similarity index 100% rename from 82 Stars/README.md rename to 82_Stars/README.md diff --git a/82 Stars/csharp/README.md b/82_Stars/csharp/README.md similarity index 100% rename from 82 Stars/csharp/README.md rename to 82_Stars/csharp/README.md diff --git a/82 Stars/csharp/Stars.sln b/82_Stars/csharp/Stars.sln similarity index 100% rename from 82 Stars/csharp/Stars.sln rename to 82_Stars/csharp/Stars.sln diff --git a/82 Stars/csharp/Stars/Game.cs b/82_Stars/csharp/Stars/Game.cs similarity index 100% rename from 82 Stars/csharp/Stars/Game.cs rename to 82_Stars/csharp/Stars/Game.cs diff --git a/82 Stars/csharp/Stars/Input.cs b/82_Stars/csharp/Stars/Input.cs similarity index 100% rename from 82 Stars/csharp/Stars/Input.cs rename to 82_Stars/csharp/Stars/Input.cs diff --git a/82 Stars/csharp/Stars/Program.cs b/82_Stars/csharp/Stars/Program.cs similarity index 100% rename from 82 Stars/csharp/Stars/Program.cs rename to 82_Stars/csharp/Stars/Program.cs diff --git a/82 Stars/csharp/Stars/Stars.csproj b/82_Stars/csharp/Stars/Stars.csproj similarity index 100% rename from 82 Stars/csharp/Stars/Stars.csproj rename to 82_Stars/csharp/Stars/Stars.csproj diff --git a/82 Stars/java/README.md b/82_Stars/java/README.md similarity index 100% rename from 82 Stars/java/README.md rename to 82_Stars/java/README.md diff --git a/82 Stars/java/src/Stars.java b/82_Stars/java/src/Stars.java similarity index 100% rename from 82 Stars/java/src/Stars.java rename to 82_Stars/java/src/Stars.java diff --git a/82 Stars/java/src/StarsGame.java b/82_Stars/java/src/StarsGame.java similarity index 100% rename from 82 Stars/java/src/StarsGame.java rename to 82_Stars/java/src/StarsGame.java diff --git a/82 Stars/javascript/README.md b/82_Stars/javascript/README.md similarity index 100% rename from 82 Stars/javascript/README.md rename to 82_Stars/javascript/README.md diff --git a/82 Stars/javascript/stars.html b/82_Stars/javascript/stars.html similarity index 100% rename from 82 Stars/javascript/stars.html rename to 82_Stars/javascript/stars.html diff --git a/82 Stars/javascript/stars.js b/82_Stars/javascript/stars.js similarity index 100% rename from 82 Stars/javascript/stars.js rename to 82_Stars/javascript/stars.js diff --git a/82 Stars/pascal/README.md b/82_Stars/pascal/README.md similarity index 100% rename from 82 Stars/pascal/README.md rename to 82_Stars/pascal/README.md diff --git a/82 Stars/perl/README.md b/82_Stars/perl/README.md similarity index 100% rename from 82 Stars/perl/README.md rename to 82_Stars/perl/README.md diff --git a/82 Stars/python/README.md b/82_Stars/python/README.md similarity index 100% rename from 82 Stars/python/README.md rename to 82_Stars/python/README.md diff --git a/82 Stars/python/stars.py b/82_Stars/python/stars.py similarity index 100% rename from 82 Stars/python/stars.py rename to 82_Stars/python/stars.py diff --git a/82 Stars/ruby/README.md b/82_Stars/ruby/README.md similarity index 100% rename from 82 Stars/ruby/README.md rename to 82_Stars/ruby/README.md diff --git a/82 Stars/stars.bas b/82_Stars/stars.bas similarity index 100% rename from 82 Stars/stars.bas rename to 82_Stars/stars.bas diff --git a/82 Stars/vbnet/README.md b/82_Stars/vbnet/README.md similarity index 100% rename from 82 Stars/vbnet/README.md rename to 82_Stars/vbnet/README.md diff --git a/83 Stock Market/README.md b/83_Stock_Market/README.md similarity index 100% rename from 83 Stock Market/README.md rename to 83_Stock_Market/README.md diff --git a/83 Stock Market/csharp/Game.csproj b/83_Stock_Market/csharp/Game.csproj similarity index 100% rename from 83 Stock Market/csharp/Game.csproj rename to 83_Stock_Market/csharp/Game.csproj diff --git a/83 Stock Market/csharp/README.md b/83_Stock_Market/csharp/README.md similarity index 100% rename from 83 Stock Market/csharp/README.md rename to 83_Stock_Market/csharp/README.md diff --git a/83 Stock Market/csharp/StockMarket.sln b/83_Stock_Market/csharp/StockMarket.sln similarity index 100% rename from 83 Stock Market/csharp/StockMarket.sln rename to 83_Stock_Market/csharp/StockMarket.sln diff --git a/83 Stock Market/csharp/src/Assets.cs b/83_Stock_Market/csharp/src/Assets.cs similarity index 100% rename from 83 Stock Market/csharp/src/Assets.cs rename to 83_Stock_Market/csharp/src/Assets.cs diff --git a/83 Stock Market/csharp/src/Broker.cs b/83_Stock_Market/csharp/src/Broker.cs similarity index 100% rename from 83 Stock Market/csharp/src/Broker.cs rename to 83_Stock_Market/csharp/src/Broker.cs diff --git a/83 Stock Market/csharp/src/Company.cs b/83_Stock_Market/csharp/src/Company.cs similarity index 100% rename from 83 Stock Market/csharp/src/Company.cs rename to 83_Stock_Market/csharp/src/Company.cs diff --git a/83 Stock Market/csharp/src/Controller.cs b/83_Stock_Market/csharp/src/Controller.cs similarity index 100% rename from 83 Stock Market/csharp/src/Controller.cs rename to 83_Stock_Market/csharp/src/Controller.cs diff --git a/83 Stock Market/csharp/src/Extensions/EnumerableExtensions.cs b/83_Stock_Market/csharp/src/Extensions/EnumerableExtensions.cs similarity index 100% rename from 83 Stock Market/csharp/src/Extensions/EnumerableExtensions.cs rename to 83_Stock_Market/csharp/src/Extensions/EnumerableExtensions.cs diff --git a/83 Stock Market/csharp/src/Extensions/ImmutableArrayExtensions.cs b/83_Stock_Market/csharp/src/Extensions/ImmutableArrayExtensions.cs similarity index 100% rename from 83 Stock Market/csharp/src/Extensions/ImmutableArrayExtensions.cs rename to 83_Stock_Market/csharp/src/Extensions/ImmutableArrayExtensions.cs diff --git a/83 Stock Market/csharp/src/Extensions/RandomExtensions.cs b/83_Stock_Market/csharp/src/Extensions/RandomExtensions.cs similarity index 100% rename from 83 Stock Market/csharp/src/Extensions/RandomExtensions.cs rename to 83_Stock_Market/csharp/src/Extensions/RandomExtensions.cs diff --git a/83 Stock Market/csharp/src/Program.cs b/83_Stock_Market/csharp/src/Program.cs similarity index 100% rename from 83 Stock Market/csharp/src/Program.cs rename to 83_Stock_Market/csharp/src/Program.cs diff --git a/83 Stock Market/csharp/src/StockMarket.cs b/83_Stock_Market/csharp/src/StockMarket.cs similarity index 100% rename from 83 Stock Market/csharp/src/StockMarket.cs rename to 83_Stock_Market/csharp/src/StockMarket.cs diff --git a/83 Stock Market/csharp/src/TradingDay.cs b/83_Stock_Market/csharp/src/TradingDay.cs similarity index 100% rename from 83 Stock Market/csharp/src/TradingDay.cs rename to 83_Stock_Market/csharp/src/TradingDay.cs diff --git a/83 Stock Market/csharp/src/TransactionResult.cs b/83_Stock_Market/csharp/src/TransactionResult.cs similarity index 100% rename from 83 Stock Market/csharp/src/TransactionResult.cs rename to 83_Stock_Market/csharp/src/TransactionResult.cs diff --git a/83 Stock Market/csharp/src/View.cs b/83_Stock_Market/csharp/src/View.cs similarity index 100% rename from 83 Stock Market/csharp/src/View.cs rename to 83_Stock_Market/csharp/src/View.cs diff --git a/83 Stock Market/java/README.md b/83_Stock_Market/java/README.md similarity index 100% rename from 83 Stock Market/java/README.md rename to 83_Stock_Market/java/README.md diff --git a/83 Stock Market/javascript/README.md b/83_Stock_Market/javascript/README.md similarity index 100% rename from 83 Stock Market/javascript/README.md rename to 83_Stock_Market/javascript/README.md diff --git a/83 Stock Market/javascript/stockmarket.html b/83_Stock_Market/javascript/stockmarket.html similarity index 100% rename from 83 Stock Market/javascript/stockmarket.html rename to 83_Stock_Market/javascript/stockmarket.html diff --git a/83 Stock Market/javascript/stockmarket.js b/83_Stock_Market/javascript/stockmarket.js similarity index 100% rename from 83 Stock Market/javascript/stockmarket.js rename to 83_Stock_Market/javascript/stockmarket.js diff --git a/83 Stock Market/pascal/README.md b/83_Stock_Market/pascal/README.md similarity index 100% rename from 83 Stock Market/pascal/README.md rename to 83_Stock_Market/pascal/README.md diff --git a/83 Stock Market/perl/README.md b/83_Stock_Market/perl/README.md similarity index 100% rename from 83 Stock Market/perl/README.md rename to 83_Stock_Market/perl/README.md diff --git a/83 Stock Market/python/README.md b/83_Stock_Market/python/README.md similarity index 100% rename from 83 Stock Market/python/README.md rename to 83_Stock_Market/python/README.md diff --git a/83 Stock Market/ruby/README.md b/83_Stock_Market/ruby/README.md similarity index 100% rename from 83 Stock Market/ruby/README.md rename to 83_Stock_Market/ruby/README.md diff --git a/83 Stock Market/stockmarket.bas b/83_Stock_Market/stockmarket.bas similarity index 100% rename from 83 Stock Market/stockmarket.bas rename to 83_Stock_Market/stockmarket.bas diff --git a/83 Stock Market/vbnet/README.md b/83_Stock_Market/vbnet/README.md similarity index 100% rename from 83 Stock Market/vbnet/README.md rename to 83_Stock_Market/vbnet/README.md diff --git a/84 Super Star Trek/README.md b/84_Super_Star_Trek/README.md similarity index 100% rename from 84 Super Star Trek/README.md rename to 84_Super_Star_Trek/README.md diff --git a/84 Super Star Trek/csharp/Commands/Command.cs b/84_Super_Star_Trek/csharp/Commands/Command.cs similarity index 100% rename from 84 Super Star Trek/csharp/Commands/Command.cs rename to 84_Super_Star_Trek/csharp/Commands/Command.cs diff --git a/84 Super Star Trek/csharp/Commands/CommandExtensions.cs b/84_Super_Star_Trek/csharp/Commands/CommandExtensions.cs similarity index 100% rename from 84 Super Star Trek/csharp/Commands/CommandExtensions.cs rename to 84_Super_Star_Trek/csharp/Commands/CommandExtensions.cs diff --git a/84 Super Star Trek/csharp/Commands/CommandResult.cs b/84_Super_Star_Trek/csharp/Commands/CommandResult.cs similarity index 100% rename from 84 Super Star Trek/csharp/Commands/CommandResult.cs rename to 84_Super_Star_Trek/csharp/Commands/CommandResult.cs diff --git a/84 Super Star Trek/csharp/Game.cs b/84_Super_Star_Trek/csharp/Game.cs similarity index 100% rename from 84 Super Star Trek/csharp/Game.cs rename to 84_Super_Star_Trek/csharp/Game.cs diff --git a/84 Super Star Trek/csharp/Input.cs b/84_Super_Star_Trek/csharp/Input.cs similarity index 100% rename from 84 Super Star Trek/csharp/Input.cs rename to 84_Super_Star_Trek/csharp/Input.cs diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84_Super_Star_Trek/csharp/Objects/Enterprise.cs similarity index 100% rename from 84 Super Star Trek/csharp/Objects/Enterprise.cs rename to 84_Super_Star_Trek/csharp/Objects/Enterprise.cs diff --git a/84 Super Star Trek/csharp/Objects/Klingon.cs b/84_Super_Star_Trek/csharp/Objects/Klingon.cs similarity index 100% rename from 84 Super Star Trek/csharp/Objects/Klingon.cs rename to 84_Super_Star_Trek/csharp/Objects/Klingon.cs diff --git a/84 Super Star Trek/csharp/Objects/Star.cs b/84_Super_Star_Trek/csharp/Objects/Star.cs similarity index 100% rename from 84 Super Star Trek/csharp/Objects/Star.cs rename to 84_Super_Star_Trek/csharp/Objects/Star.cs diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84_Super_Star_Trek/csharp/Objects/Starbase.cs similarity index 100% rename from 84 Super Star Trek/csharp/Objects/Starbase.cs rename to 84_Super_Star_Trek/csharp/Objects/Starbase.cs diff --git a/84 Super Star Trek/csharp/Output.cs b/84_Super_Star_Trek/csharp/Output.cs similarity index 100% rename from 84 Super Star Trek/csharp/Output.cs rename to 84_Super_Star_Trek/csharp/Output.cs diff --git a/84 Super Star Trek/csharp/Program.cs b/84_Super_Star_Trek/csharp/Program.cs similarity index 100% rename from 84 Super Star Trek/csharp/Program.cs rename to 84_Super_Star_Trek/csharp/Program.cs diff --git a/84 Super Star Trek/csharp/README.md b/84_Super_Star_Trek/csharp/README.md similarity index 100% rename from 84 Super Star Trek/csharp/README.md rename to 84_Super_Star_Trek/csharp/README.md diff --git a/84 Super Star Trek/csharp/Random.cs b/84_Super_Star_Trek/csharp/Random.cs similarity index 100% rename from 84 Super Star Trek/csharp/Random.cs rename to 84_Super_Star_Trek/csharp/Random.cs diff --git a/84 Super Star Trek/csharp/Resources/CombatArea.txt b/84_Super_Star_Trek/csharp/Resources/CombatArea.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/CombatArea.txt rename to 84_Super_Star_Trek/csharp/Resources/CombatArea.txt diff --git a/84 Super Star Trek/csharp/Resources/Congratulations.txt b/84_Super_Star_Trek/csharp/Resources/Congratulations.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Congratulations.txt rename to 84_Super_Star_Trek/csharp/Resources/Congratulations.txt diff --git a/84 Super Star Trek/csharp/Resources/CourtMartial.txt b/84_Super_Star_Trek/csharp/Resources/CourtMartial.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/CourtMartial.txt rename to 84_Super_Star_Trek/csharp/Resources/CourtMartial.txt diff --git a/84 Super Star Trek/csharp/Resources/Destroyed.txt b/84_Super_Star_Trek/csharp/Resources/Destroyed.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Destroyed.txt rename to 84_Super_Star_Trek/csharp/Resources/Destroyed.txt diff --git a/84 Super Star Trek/csharp/Resources/EndOfMission.txt b/84_Super_Star_Trek/csharp/Resources/EndOfMission.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/EndOfMission.txt rename to 84_Super_Star_Trek/csharp/Resources/EndOfMission.txt diff --git a/84 Super Star Trek/csharp/Resources/Enterprise.txt b/84_Super_Star_Trek/csharp/Resources/Enterprise.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Enterprise.txt rename to 84_Super_Star_Trek/csharp/Resources/Enterprise.txt diff --git a/84 Super Star Trek/csharp/Resources/Instructions.txt b/84_Super_Star_Trek/csharp/Resources/Instructions.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Instructions.txt rename to 84_Super_Star_Trek/csharp/Resources/Instructions.txt diff --git a/84 Super Star Trek/csharp/Resources/LowShields.txt b/84_Super_Star_Trek/csharp/Resources/LowShields.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/LowShields.txt rename to 84_Super_Star_Trek/csharp/Resources/LowShields.txt diff --git a/84 Super Star Trek/csharp/Resources/NoEnemyShips.txt b/84_Super_Star_Trek/csharp/Resources/NoEnemyShips.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/NoEnemyShips.txt rename to 84_Super_Star_Trek/csharp/Resources/NoEnemyShips.txt diff --git a/84 Super Star Trek/csharp/Resources/NoStarbase.txt b/84_Super_Star_Trek/csharp/Resources/NoStarbase.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/NoStarbase.txt rename to 84_Super_Star_Trek/csharp/Resources/NoStarbase.txt diff --git a/84 Super Star Trek/csharp/Resources/NowEntering.txt b/84_Super_Star_Trek/csharp/Resources/NowEntering.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/NowEntering.txt rename to 84_Super_Star_Trek/csharp/Resources/NowEntering.txt diff --git a/84 Super Star Trek/csharp/Resources/Orders.txt b/84_Super_Star_Trek/csharp/Resources/Orders.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Orders.txt rename to 84_Super_Star_Trek/csharp/Resources/Orders.txt diff --git a/84 Super Star Trek/csharp/Resources/PermissionDenied.txt b/84_Super_Star_Trek/csharp/Resources/PermissionDenied.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/PermissionDenied.txt rename to 84_Super_Star_Trek/csharp/Resources/PermissionDenied.txt diff --git a/84 Super Star Trek/csharp/Resources/Protected.txt b/84_Super_Star_Trek/csharp/Resources/Protected.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Protected.txt rename to 84_Super_Star_Trek/csharp/Resources/Protected.txt diff --git a/84 Super Star Trek/csharp/Resources/RegionNames.txt b/84_Super_Star_Trek/csharp/Resources/RegionNames.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/RegionNames.txt rename to 84_Super_Star_Trek/csharp/Resources/RegionNames.txt diff --git a/84 Super Star Trek/csharp/Resources/RelievedOfCommand.txt b/84_Super_Star_Trek/csharp/Resources/RelievedOfCommand.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/RelievedOfCommand.txt rename to 84_Super_Star_Trek/csharp/Resources/RelievedOfCommand.txt diff --git a/84 Super Star Trek/csharp/Resources/RepairEstimate.txt b/84_Super_Star_Trek/csharp/Resources/RepairEstimate.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/RepairEstimate.txt rename to 84_Super_Star_Trek/csharp/Resources/RepairEstimate.txt diff --git a/84 Super Star Trek/csharp/Resources/RepairPrompt.txt b/84_Super_Star_Trek/csharp/Resources/RepairPrompt.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/RepairPrompt.txt rename to 84_Super_Star_Trek/csharp/Resources/RepairPrompt.txt diff --git a/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt b/84_Super_Star_Trek/csharp/Resources/ReplayPrompt.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/ReplayPrompt.txt rename to 84_Super_Star_Trek/csharp/Resources/ReplayPrompt.txt diff --git a/84 Super Star Trek/csharp/Resources/ShieldsDropped.txt b/84_Super_Star_Trek/csharp/Resources/ShieldsDropped.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/ShieldsDropped.txt rename to 84_Super_Star_Trek/csharp/Resources/ShieldsDropped.txt diff --git a/84 Super Star Trek/csharp/Resources/ShieldsSet.txt b/84_Super_Star_Trek/csharp/Resources/ShieldsSet.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/ShieldsSet.txt rename to 84_Super_Star_Trek/csharp/Resources/ShieldsSet.txt diff --git a/84 Super Star Trek/csharp/Resources/ShortRangeSensorsOut.txt b/84_Super_Star_Trek/csharp/Resources/ShortRangeSensorsOut.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/ShortRangeSensorsOut.txt rename to 84_Super_Star_Trek/csharp/Resources/ShortRangeSensorsOut.txt diff --git a/84 Super Star Trek/csharp/Resources/StartText.txt b/84_Super_Star_Trek/csharp/Resources/StartText.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/StartText.txt rename to 84_Super_Star_Trek/csharp/Resources/StartText.txt diff --git a/84 Super Star Trek/csharp/Resources/Stranded.txt b/84_Super_Star_Trek/csharp/Resources/Stranded.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Stranded.txt rename to 84_Super_Star_Trek/csharp/Resources/Stranded.txt diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84_Super_Star_Trek/csharp/Resources/Strings.cs similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Strings.cs rename to 84_Super_Star_Trek/csharp/Resources/Strings.cs diff --git a/84 Super Star Trek/csharp/Resources/Title.txt b/84_Super_Star_Trek/csharp/Resources/Title.txt similarity index 100% rename from 84 Super Star Trek/csharp/Resources/Title.txt rename to 84_Super_Star_Trek/csharp/Resources/Title.txt diff --git a/84 Super Star Trek/csharp/Space/Coordinates.cs b/84_Super_Star_Trek/csharp/Space/Coordinates.cs similarity index 100% rename from 84 Super Star Trek/csharp/Space/Coordinates.cs rename to 84_Super_Star_Trek/csharp/Space/Coordinates.cs diff --git a/84 Super Star Trek/csharp/Space/Course.cs b/84_Super_Star_Trek/csharp/Space/Course.cs similarity index 100% rename from 84 Super Star Trek/csharp/Space/Course.cs rename to 84_Super_Star_Trek/csharp/Space/Course.cs diff --git a/84 Super Star Trek/csharp/Space/Galaxy.cs b/84_Super_Star_Trek/csharp/Space/Galaxy.cs similarity index 100% rename from 84 Super Star Trek/csharp/Space/Galaxy.cs rename to 84_Super_Star_Trek/csharp/Space/Galaxy.cs diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84_Super_Star_Trek/csharp/Space/Quadrant.cs similarity index 100% rename from 84 Super Star Trek/csharp/Space/Quadrant.cs rename to 84_Super_Star_Trek/csharp/Space/Quadrant.cs diff --git a/84 Super Star Trek/csharp/Space/QuadrantInfo.cs b/84_Super_Star_Trek/csharp/Space/QuadrantInfo.cs similarity index 100% rename from 84 Super Star Trek/csharp/Space/QuadrantInfo.cs rename to 84_Super_Star_Trek/csharp/Space/QuadrantInfo.cs diff --git a/84 Super Star Trek/csharp/StringExtensions.cs b/84_Super_Star_Trek/csharp/StringExtensions.cs similarity index 100% rename from 84 Super Star Trek/csharp/StringExtensions.cs rename to 84_Super_Star_Trek/csharp/StringExtensions.cs diff --git a/84 Super Star Trek/csharp/SuperStarTrek.csproj b/84_Super_Star_Trek/csharp/SuperStarTrek.csproj similarity index 100% rename from 84 Super Star Trek/csharp/SuperStarTrek.csproj rename to 84_Super_Star_Trek/csharp/SuperStarTrek.csproj diff --git a/84 Super Star Trek/csharp/SuperStarTrek.sln b/84_Super_Star_Trek/csharp/SuperStarTrek.sln similarity index 100% rename from 84 Super Star Trek/csharp/SuperStarTrek.sln rename to 84_Super_Star_Trek/csharp/SuperStarTrek.sln diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StatusReport.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/StatusReport.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StatusReport.cs diff --git a/84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs rename to 84_Super_Star_Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84_Super_Star_Trek/csharp/Systems/DamageControl.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/DamageControl.cs rename to 84_Super_Star_Trek/csharp/Systems/DamageControl.cs diff --git a/84 Super Star Trek/csharp/Systems/LibraryComputer.cs b/84_Super_Star_Trek/csharp/Systems/LibraryComputer.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/LibraryComputer.cs rename to 84_Super_Star_Trek/csharp/Systems/LibraryComputer.cs diff --git a/84 Super Star Trek/csharp/Systems/LongRangeSensors.cs b/84_Super_Star_Trek/csharp/Systems/LongRangeSensors.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/LongRangeSensors.cs rename to 84_Super_Star_Trek/csharp/Systems/LongRangeSensors.cs diff --git a/84 Super Star Trek/csharp/Systems/PhaserControl.cs b/84_Super_Star_Trek/csharp/Systems/PhaserControl.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/PhaserControl.cs rename to 84_Super_Star_Trek/csharp/Systems/PhaserControl.cs diff --git a/84 Super Star Trek/csharp/Systems/PhotonTubes.cs b/84_Super_Star_Trek/csharp/Systems/PhotonTubes.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/PhotonTubes.cs rename to 84_Super_Star_Trek/csharp/Systems/PhotonTubes.cs diff --git a/84 Super Star Trek/csharp/Systems/ShieldControl.cs b/84_Super_Star_Trek/csharp/Systems/ShieldControl.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ShieldControl.cs rename to 84_Super_Star_Trek/csharp/Systems/ShieldControl.cs diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84_Super_Star_Trek/csharp/Systems/ShortRangeSensors.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs rename to 84_Super_Star_Trek/csharp/Systems/ShortRangeSensors.cs diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84_Super_Star_Trek/csharp/Systems/Subsystem.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/Subsystem.cs rename to 84_Super_Star_Trek/csharp/Systems/Subsystem.cs diff --git a/84 Super Star Trek/csharp/Systems/WarpEngines.cs b/84_Super_Star_Trek/csharp/Systems/WarpEngines.cs similarity index 100% rename from 84 Super Star Trek/csharp/Systems/WarpEngines.cs rename to 84_Super_Star_Trek/csharp/Systems/WarpEngines.cs diff --git a/84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs b/84_Super_Star_Trek/csharp/Utils/DirectionAndDistance.cs similarity index 100% rename from 84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs rename to 84_Super_Star_Trek/csharp/Utils/DirectionAndDistance.cs diff --git a/84 Super Star Trek/instructions.txt b/84_Super_Star_Trek/instructions.txt similarity index 100% rename from 84 Super Star Trek/instructions.txt rename to 84_Super_Star_Trek/instructions.txt diff --git a/84 Super Star Trek/java/README.md b/84_Super_Star_Trek/java/README.md similarity index 100% rename from 84 Super Star Trek/java/README.md rename to 84_Super_Star_Trek/java/README.md diff --git a/84 Super Star Trek/javascript/README.md b/84_Super_Star_Trek/javascript/README.md similarity index 100% rename from 84 Super Star Trek/javascript/README.md rename to 84_Super_Star_Trek/javascript/README.md diff --git a/84 Super Star Trek/javascript/cli.mjs b/84_Super_Star_Trek/javascript/cli.mjs similarity index 100% rename from 84 Super Star Trek/javascript/cli.mjs rename to 84_Super_Star_Trek/javascript/cli.mjs diff --git a/84 Super Star Trek/javascript/index.html b/84_Super_Star_Trek/javascript/index.html similarity index 100% rename from 84 Super Star Trek/javascript/index.html rename to 84_Super_Star_Trek/javascript/index.html diff --git a/84 Super Star Trek/javascript/package.json b/84_Super_Star_Trek/javascript/package.json similarity index 100% rename from 84 Super Star Trek/javascript/package.json rename to 84_Super_Star_Trek/javascript/package.json diff --git a/84 Super Star Trek/javascript/superstartrek.mjs b/84_Super_Star_Trek/javascript/superstartrek.mjs similarity index 100% rename from 84 Super Star Trek/javascript/superstartrek.mjs rename to 84_Super_Star_Trek/javascript/superstartrek.mjs diff --git a/84 Super Star Trek/pascal/README.md b/84_Super_Star_Trek/pascal/README.md similarity index 100% rename from 84 Super Star Trek/pascal/README.md rename to 84_Super_Star_Trek/pascal/README.md diff --git a/84 Super Star Trek/perl/README.md b/84_Super_Star_Trek/perl/README.md similarity index 100% rename from 84 Super Star Trek/perl/README.md rename to 84_Super_Star_Trek/perl/README.md diff --git a/84 Super Star Trek/python/README.md b/84_Super_Star_Trek/python/README.md similarity index 100% rename from 84 Super Star Trek/python/README.md rename to 84_Super_Star_Trek/python/README.md diff --git a/84 Super Star Trek/python/superstartrek.py b/84_Super_Star_Trek/python/superstartrek.py similarity index 100% rename from 84 Super Star Trek/python/superstartrek.py rename to 84_Super_Star_Trek/python/superstartrek.py diff --git a/84 Super Star Trek/python/superstartrekins.py b/84_Super_Star_Trek/python/superstartrekins.py similarity index 100% rename from 84 Super Star Trek/python/superstartrekins.py rename to 84_Super_Star_Trek/python/superstartrekins.py diff --git a/84 Super Star Trek/ruby/README.md b/84_Super_Star_Trek/ruby/README.md similarity index 100% rename from 84 Super Star Trek/ruby/README.md rename to 84_Super_Star_Trek/ruby/README.md diff --git a/84 Super Star Trek/superstartrek.bas b/84_Super_Star_Trek/superstartrek.bas similarity index 100% rename from 84 Super Star Trek/superstartrek.bas rename to 84_Super_Star_Trek/superstartrek.bas diff --git a/84 Super Star Trek/superstartrekins.bas b/84_Super_Star_Trek/superstartrekins.bas similarity index 100% rename from 84 Super Star Trek/superstartrekins.bas rename to 84_Super_Star_Trek/superstartrekins.bas diff --git a/84 Super Star Trek/vbnet/README.md b/84_Super_Star_Trek/vbnet/README.md similarity index 100% rename from 84 Super Star Trek/vbnet/README.md rename to 84_Super_Star_Trek/vbnet/README.md diff --git a/85 Synonym/README.md b/85_Synonym/README.md similarity index 100% rename from 85 Synonym/README.md rename to 85_Synonym/README.md diff --git a/85 Synonym/csharp/README.md b/85_Synonym/csharp/README.md similarity index 100% rename from 85 Synonym/csharp/README.md rename to 85_Synonym/csharp/README.md diff --git a/85 Synonym/java/README.md b/85_Synonym/java/README.md similarity index 100% rename from 85 Synonym/java/README.md rename to 85_Synonym/java/README.md diff --git a/85 Synonym/java/src/Synonym.java b/85_Synonym/java/src/Synonym.java similarity index 100% rename from 85 Synonym/java/src/Synonym.java rename to 85_Synonym/java/src/Synonym.java diff --git a/85 Synonym/java/src/SynonymGame.java b/85_Synonym/java/src/SynonymGame.java similarity index 100% rename from 85 Synonym/java/src/SynonymGame.java rename to 85_Synonym/java/src/SynonymGame.java diff --git a/85 Synonym/java/src/SynonymList.java b/85_Synonym/java/src/SynonymList.java similarity index 100% rename from 85 Synonym/java/src/SynonymList.java rename to 85_Synonym/java/src/SynonymList.java diff --git a/85 Synonym/javascript/README.md b/85_Synonym/javascript/README.md similarity index 100% rename from 85 Synonym/javascript/README.md rename to 85_Synonym/javascript/README.md diff --git a/85 Synonym/javascript/synonym.html b/85_Synonym/javascript/synonym.html similarity index 100% rename from 85 Synonym/javascript/synonym.html rename to 85_Synonym/javascript/synonym.html diff --git a/85 Synonym/javascript/synonym.js b/85_Synonym/javascript/synonym.js similarity index 100% rename from 85 Synonym/javascript/synonym.js rename to 85_Synonym/javascript/synonym.js diff --git a/85 Synonym/pascal/README.md b/85_Synonym/pascal/README.md similarity index 100% rename from 85 Synonym/pascal/README.md rename to 85_Synonym/pascal/README.md diff --git a/85 Synonym/perl/README.md b/85_Synonym/perl/README.md similarity index 100% rename from 85 Synonym/perl/README.md rename to 85_Synonym/perl/README.md diff --git a/85 Synonym/python/README.md b/85_Synonym/python/README.md similarity index 100% rename from 85 Synonym/python/README.md rename to 85_Synonym/python/README.md diff --git a/85 Synonym/python/synonym.py b/85_Synonym/python/synonym.py similarity index 100% rename from 85 Synonym/python/synonym.py rename to 85_Synonym/python/synonym.py diff --git a/85 Synonym/ruby/README.md b/85_Synonym/ruby/README.md similarity index 100% rename from 85 Synonym/ruby/README.md rename to 85_Synonym/ruby/README.md diff --git a/85 Synonym/synonym.bas b/85_Synonym/synonym.bas similarity index 100% rename from 85 Synonym/synonym.bas rename to 85_Synonym/synonym.bas diff --git a/85 Synonym/vbnet/README.md b/85_Synonym/vbnet/README.md similarity index 100% rename from 85 Synonym/vbnet/README.md rename to 85_Synonym/vbnet/README.md diff --git a/86 Target/README.md b/86_Target/README.md similarity index 100% rename from 86 Target/README.md rename to 86_Target/README.md diff --git a/86 Target/csharp/README.md b/86_Target/csharp/README.md similarity index 100% rename from 86 Target/csharp/README.md rename to 86_Target/csharp/README.md diff --git a/86 Target/csharp/Target.sln b/86_Target/csharp/Target.sln similarity index 100% rename from 86 Target/csharp/Target.sln rename to 86_Target/csharp/Target.sln diff --git a/86 Target/csharp/Target/Angle.cs b/86_Target/csharp/Target/Angle.cs similarity index 100% rename from 86 Target/csharp/Target/Angle.cs rename to 86_Target/csharp/Target/Angle.cs diff --git a/86 Target/csharp/Target/Explosion.cs b/86_Target/csharp/Target/Explosion.cs similarity index 100% rename from 86 Target/csharp/Target/Explosion.cs rename to 86_Target/csharp/Target/Explosion.cs diff --git a/86 Target/csharp/Target/FiringRange.cs b/86_Target/csharp/Target/FiringRange.cs similarity index 100% rename from 86 Target/csharp/Target/FiringRange.cs rename to 86_Target/csharp/Target/FiringRange.cs diff --git a/86 Target/csharp/Target/Game.cs b/86_Target/csharp/Target/Game.cs similarity index 100% rename from 86 Target/csharp/Target/Game.cs rename to 86_Target/csharp/Target/Game.cs diff --git a/86 Target/csharp/Target/Input.cs b/86_Target/csharp/Target/Input.cs similarity index 100% rename from 86 Target/csharp/Target/Input.cs rename to 86_Target/csharp/Target/Input.cs diff --git a/86 Target/csharp/Target/Offset.cs b/86_Target/csharp/Target/Offset.cs similarity index 100% rename from 86 Target/csharp/Target/Offset.cs rename to 86_Target/csharp/Target/Offset.cs diff --git a/86 Target/csharp/Target/Point.cs b/86_Target/csharp/Target/Point.cs similarity index 100% rename from 86 Target/csharp/Target/Point.cs rename to 86_Target/csharp/Target/Point.cs diff --git a/86 Target/csharp/Target/Program.cs b/86_Target/csharp/Target/Program.cs similarity index 100% rename from 86 Target/csharp/Target/Program.cs rename to 86_Target/csharp/Target/Program.cs diff --git a/86 Target/csharp/Target/RandomExtensions.cs b/86_Target/csharp/Target/RandomExtensions.cs similarity index 100% rename from 86 Target/csharp/Target/RandomExtensions.cs rename to 86_Target/csharp/Target/RandomExtensions.cs diff --git a/86 Target/csharp/Target/Strings/TitleAndInstructions.txt b/86_Target/csharp/Target/Strings/TitleAndInstructions.txt similarity index 100% rename from 86 Target/csharp/Target/Strings/TitleAndInstructions.txt rename to 86_Target/csharp/Target/Strings/TitleAndInstructions.txt diff --git a/86 Target/csharp/Target/Target.csproj b/86_Target/csharp/Target/Target.csproj similarity index 100% rename from 86 Target/csharp/Target/Target.csproj rename to 86_Target/csharp/Target/Target.csproj diff --git a/86 Target/java/README.md b/86_Target/java/README.md similarity index 100% rename from 86 Target/java/README.md rename to 86_Target/java/README.md diff --git a/86 Target/java/Target.java b/86_Target/java/Target.java similarity index 100% rename from 86 Target/java/Target.java rename to 86_Target/java/Target.java diff --git a/86 Target/javascript/README.md b/86_Target/javascript/README.md similarity index 100% rename from 86 Target/javascript/README.md rename to 86_Target/javascript/README.md diff --git a/86 Target/javascript/target.html b/86_Target/javascript/target.html similarity index 100% rename from 86 Target/javascript/target.html rename to 86_Target/javascript/target.html diff --git a/86 Target/javascript/target.js b/86_Target/javascript/target.js similarity index 100% rename from 86 Target/javascript/target.js rename to 86_Target/javascript/target.js diff --git a/86 Target/pascal/README.md b/86_Target/pascal/README.md similarity index 100% rename from 86 Target/pascal/README.md rename to 86_Target/pascal/README.md diff --git a/86 Target/perl/README.md b/86_Target/perl/README.md similarity index 100% rename from 86 Target/perl/README.md rename to 86_Target/perl/README.md diff --git a/86 Target/python/README.md b/86_Target/python/README.md similarity index 100% rename from 86 Target/python/README.md rename to 86_Target/python/README.md diff --git a/86 Target/python/target.py b/86_Target/python/target.py similarity index 100% rename from 86 Target/python/target.py rename to 86_Target/python/target.py diff --git a/86 Target/ruby/README.md b/86_Target/ruby/README.md similarity index 100% rename from 86 Target/ruby/README.md rename to 86_Target/ruby/README.md diff --git a/86 Target/target.bas b/86_Target/target.bas similarity index 100% rename from 86 Target/target.bas rename to 86_Target/target.bas diff --git a/86 Target/vbnet/README.md b/86_Target/vbnet/README.md similarity index 100% rename from 86 Target/vbnet/README.md rename to 86_Target/vbnet/README.md diff --git a/87 3-D Plot/3dplot.bas b/87_3-D_Plot/3dplot.bas similarity index 100% rename from 87 3-D Plot/3dplot.bas rename to 87_3-D_Plot/3dplot.bas diff --git a/87 3-D Plot/README.md b/87_3-D_Plot/README.md similarity index 100% rename from 87 3-D Plot/README.md rename to 87_3-D_Plot/README.md diff --git a/87 3-D Plot/csharp/Plot.sln b/87_3-D_Plot/csharp/Plot.sln similarity index 100% rename from 87 3-D Plot/csharp/Plot.sln rename to 87_3-D_Plot/csharp/Plot.sln diff --git a/87 3-D Plot/csharp/Plot/Function.cs b/87_3-D_Plot/csharp/Plot/Function.cs similarity index 100% rename from 87 3-D Plot/csharp/Plot/Function.cs rename to 87_3-D_Plot/csharp/Plot/Function.cs diff --git a/87 3-D Plot/csharp/Plot/Plot.csproj b/87_3-D_Plot/csharp/Plot/Plot.csproj similarity index 100% rename from 87 3-D Plot/csharp/Plot/Plot.csproj rename to 87_3-D_Plot/csharp/Plot/Plot.csproj diff --git a/87 3-D Plot/csharp/Plot/Program.cs b/87_3-D_Plot/csharp/Plot/Program.cs similarity index 100% rename from 87 3-D Plot/csharp/Plot/Program.cs rename to 87_3-D_Plot/csharp/Plot/Program.cs diff --git a/87 3-D Plot/csharp/README.md b/87_3-D_Plot/csharp/README.md similarity index 100% rename from 87 3-D Plot/csharp/README.md rename to 87_3-D_Plot/csharp/README.md diff --git a/87 3-D Plot/java/Plot3D.java b/87_3-D_Plot/java/Plot3D.java similarity index 100% rename from 87 3-D Plot/java/Plot3D.java rename to 87_3-D_Plot/java/Plot3D.java diff --git a/87 3-D Plot/java/README.md b/87_3-D_Plot/java/README.md similarity index 100% rename from 87 3-D Plot/java/README.md rename to 87_3-D_Plot/java/README.md diff --git a/87 3-D Plot/javascript/3dplot.html b/87_3-D_Plot/javascript/3dplot.html similarity index 100% rename from 87 3-D Plot/javascript/3dplot.html rename to 87_3-D_Plot/javascript/3dplot.html diff --git a/87 3-D Plot/javascript/3dplot.js b/87_3-D_Plot/javascript/3dplot.js similarity index 100% rename from 87 3-D Plot/javascript/3dplot.js rename to 87_3-D_Plot/javascript/3dplot.js diff --git a/87 3-D Plot/javascript/README.md b/87_3-D_Plot/javascript/README.md similarity index 100% rename from 87 3-D Plot/javascript/README.md rename to 87_3-D_Plot/javascript/README.md diff --git a/87 3-D Plot/pascal/README.md b/87_3-D_Plot/pascal/README.md similarity index 100% rename from 87 3-D Plot/pascal/README.md rename to 87_3-D_Plot/pascal/README.md diff --git a/87 3-D Plot/perl/3dplot.pl b/87_3-D_Plot/perl/3dplot.pl similarity index 100% rename from 87 3-D Plot/perl/3dplot.pl rename to 87_3-D_Plot/perl/3dplot.pl diff --git a/87 3-D Plot/perl/README.md b/87_3-D_Plot/perl/README.md similarity index 100% rename from 87 3-D Plot/perl/README.md rename to 87_3-D_Plot/perl/README.md diff --git a/87 3-D Plot/python/3dplot.py b/87_3-D_Plot/python/3dplot.py similarity index 100% rename from 87 3-D Plot/python/3dplot.py rename to 87_3-D_Plot/python/3dplot.py diff --git a/87 3-D Plot/python/README.md b/87_3-D_Plot/python/README.md similarity index 100% rename from 87 3-D Plot/python/README.md rename to 87_3-D_Plot/python/README.md diff --git a/87 3-D Plot/ruby/3dplot.rb b/87_3-D_Plot/ruby/3dplot.rb similarity index 100% rename from 87 3-D Plot/ruby/3dplot.rb rename to 87_3-D_Plot/ruby/3dplot.rb diff --git a/87 3-D Plot/ruby/README.md b/87_3-D_Plot/ruby/README.md similarity index 100% rename from 87 3-D Plot/ruby/README.md rename to 87_3-D_Plot/ruby/README.md diff --git a/87 3-D Plot/vbnet/README.md b/87_3-D_Plot/vbnet/README.md similarity index 100% rename from 87 3-D Plot/vbnet/README.md rename to 87_3-D_Plot/vbnet/README.md diff --git a/88 3-D Tic-Tac-Toe/README.md b/88_3-D_Tic-Tac-Toe/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/README.md rename to 88_3-D_Tic-Tac-Toe/README.md diff --git a/88 3-D Tic-Tac-Toe/csharp/README.md b/88_3-D_Tic-Tac-Toe/csharp/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/csharp/README.md rename to 88_3-D_Tic-Tac-Toe/csharp/README.md diff --git a/88 3-D Tic-Tac-Toe/java/README.md b/88_3-D_Tic-Tac-Toe/java/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/java/README.md rename to 88_3-D_Tic-Tac-Toe/java/README.md diff --git a/88 3-D Tic-Tac-Toe/javascript/README.md b/88_3-D_Tic-Tac-Toe/javascript/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/javascript/README.md rename to 88_3-D_Tic-Tac-Toe/javascript/README.md diff --git a/88 3-D Tic-Tac-Toe/javascript/qubit.html b/88_3-D_Tic-Tac-Toe/javascript/qubit.html similarity index 100% rename from 88 3-D Tic-Tac-Toe/javascript/qubit.html rename to 88_3-D_Tic-Tac-Toe/javascript/qubit.html diff --git a/88 3-D Tic-Tac-Toe/javascript/qubit.js b/88_3-D_Tic-Tac-Toe/javascript/qubit.js similarity index 100% rename from 88 3-D Tic-Tac-Toe/javascript/qubit.js rename to 88_3-D_Tic-Tac-Toe/javascript/qubit.js diff --git a/88 3-D Tic-Tac-Toe/pascal/README.md b/88_3-D_Tic-Tac-Toe/pascal/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/pascal/README.md rename to 88_3-D_Tic-Tac-Toe/pascal/README.md diff --git a/88 3-D Tic-Tac-Toe/perl/README.md b/88_3-D_Tic-Tac-Toe/perl/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/perl/README.md rename to 88_3-D_Tic-Tac-Toe/perl/README.md diff --git a/88 3-D Tic-Tac-Toe/python/README.md b/88_3-D_Tic-Tac-Toe/python/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/python/README.md rename to 88_3-D_Tic-Tac-Toe/python/README.md diff --git a/88 3-D Tic-Tac-Toe/python/qubit.py b/88_3-D_Tic-Tac-Toe/python/qubit.py similarity index 100% rename from 88 3-D Tic-Tac-Toe/python/qubit.py rename to 88_3-D_Tic-Tac-Toe/python/qubit.py diff --git a/88 3-D Tic-Tac-Toe/qubit.bas b/88_3-D_Tic-Tac-Toe/qubit.bas similarity index 100% rename from 88 3-D Tic-Tac-Toe/qubit.bas rename to 88_3-D_Tic-Tac-Toe/qubit.bas diff --git a/88 3-D Tic-Tac-Toe/ruby/README.md b/88_3-D_Tic-Tac-Toe/ruby/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/ruby/README.md rename to 88_3-D_Tic-Tac-Toe/ruby/README.md diff --git a/88 3-D Tic-Tac-Toe/vbnet/README.md b/88_3-D_Tic-Tac-Toe/vbnet/README.md similarity index 100% rename from 88 3-D Tic-Tac-Toe/vbnet/README.md rename to 88_3-D_Tic-Tac-Toe/vbnet/README.md diff --git a/89 Tic-Tac-Toe/README.md b/89_Tic-Tac-Toe/README.md similarity index 100% rename from 89 Tic-Tac-Toe/README.md rename to 89_Tic-Tac-Toe/README.md diff --git a/89 Tic-Tac-Toe/csharp/README.md b/89_Tic-Tac-Toe/csharp/README.md similarity index 100% rename from 89 Tic-Tac-Toe/csharp/README.md rename to 89_Tic-Tac-Toe/csharp/README.md diff --git a/89 Tic-Tac-Toe/java/README.md b/89_Tic-Tac-Toe/java/README.md similarity index 100% rename from 89 Tic-Tac-Toe/java/README.md rename to 89_Tic-Tac-Toe/java/README.md diff --git a/89 Tic-Tac-Toe/java/src/Board.java b/89_Tic-Tac-Toe/java/src/Board.java similarity index 100% rename from 89 Tic-Tac-Toe/java/src/Board.java rename to 89_Tic-Tac-Toe/java/src/Board.java diff --git a/89 Tic-Tac-Toe/java/src/TicTacToe2.java b/89_Tic-Tac-Toe/java/src/TicTacToe2.java similarity index 100% rename from 89 Tic-Tac-Toe/java/src/TicTacToe2.java rename to 89_Tic-Tac-Toe/java/src/TicTacToe2.java diff --git a/89 Tic-Tac-Toe/javascript/README.md b/89_Tic-Tac-Toe/javascript/README.md similarity index 100% rename from 89 Tic-Tac-Toe/javascript/README.md rename to 89_Tic-Tac-Toe/javascript/README.md diff --git a/89 Tic-Tac-Toe/javascript/tictactoe1.html b/89_Tic-Tac-Toe/javascript/tictactoe1.html similarity index 100% rename from 89 Tic-Tac-Toe/javascript/tictactoe1.html rename to 89_Tic-Tac-Toe/javascript/tictactoe1.html diff --git a/89 Tic-Tac-Toe/javascript/tictactoe1.js b/89_Tic-Tac-Toe/javascript/tictactoe1.js similarity index 100% rename from 89 Tic-Tac-Toe/javascript/tictactoe1.js rename to 89_Tic-Tac-Toe/javascript/tictactoe1.js diff --git a/89 Tic-Tac-Toe/javascript/tictactoe2.html b/89_Tic-Tac-Toe/javascript/tictactoe2.html similarity index 100% rename from 89 Tic-Tac-Toe/javascript/tictactoe2.html rename to 89_Tic-Tac-Toe/javascript/tictactoe2.html diff --git a/89 Tic-Tac-Toe/javascript/tictactoe2.js b/89_Tic-Tac-Toe/javascript/tictactoe2.js similarity index 100% rename from 89 Tic-Tac-Toe/javascript/tictactoe2.js rename to 89_Tic-Tac-Toe/javascript/tictactoe2.js diff --git a/89 Tic-Tac-Toe/pascal/README.md b/89_Tic-Tac-Toe/pascal/README.md similarity index 100% rename from 89 Tic-Tac-Toe/pascal/README.md rename to 89_Tic-Tac-Toe/pascal/README.md diff --git a/89 Tic-Tac-Toe/perl/README.md b/89_Tic-Tac-Toe/perl/README.md similarity index 100% rename from 89 Tic-Tac-Toe/perl/README.md rename to 89_Tic-Tac-Toe/perl/README.md diff --git a/89 Tic-Tac-Toe/python/README.md b/89_Tic-Tac-Toe/python/README.md similarity index 100% rename from 89 Tic-Tac-Toe/python/README.md rename to 89_Tic-Tac-Toe/python/README.md diff --git a/89 Tic-Tac-Toe/python/tictactoe2.py b/89_Tic-Tac-Toe/python/tictactoe2.py similarity index 100% rename from 89 Tic-Tac-Toe/python/tictactoe2.py rename to 89_Tic-Tac-Toe/python/tictactoe2.py diff --git a/89 Tic-Tac-Toe/ruby/README.md b/89_Tic-Tac-Toe/ruby/README.md similarity index 100% rename from 89 Tic-Tac-Toe/ruby/README.md rename to 89_Tic-Tac-Toe/ruby/README.md diff --git a/89 Tic-Tac-Toe/tictactoe1.bas b/89_Tic-Tac-Toe/tictactoe1.bas similarity index 100% rename from 89 Tic-Tac-Toe/tictactoe1.bas rename to 89_Tic-Tac-Toe/tictactoe1.bas diff --git a/89 Tic-Tac-Toe/tictactoe2.bas b/89_Tic-Tac-Toe/tictactoe2.bas similarity index 100% rename from 89 Tic-Tac-Toe/tictactoe2.bas rename to 89_Tic-Tac-Toe/tictactoe2.bas diff --git a/89 Tic-Tac-Toe/vbnet/README.md b/89_Tic-Tac-Toe/vbnet/README.md similarity index 100% rename from 89 Tic-Tac-Toe/vbnet/README.md rename to 89_Tic-Tac-Toe/vbnet/README.md diff --git a/90 Tower/README.md b/90_Tower/README.md similarity index 100% rename from 90 Tower/README.md rename to 90_Tower/README.md diff --git a/90 Tower/csharp/README.md b/90_Tower/csharp/README.md similarity index 100% rename from 90 Tower/csharp/README.md rename to 90_Tower/csharp/README.md diff --git a/90 Tower/java/README.md b/90_Tower/java/README.md similarity index 100% rename from 90 Tower/java/README.md rename to 90_Tower/java/README.md diff --git a/90 Tower/java/Tower.java b/90_Tower/java/Tower.java similarity index 100% rename from 90 Tower/java/Tower.java rename to 90_Tower/java/Tower.java diff --git a/90 Tower/javascript/README.md b/90_Tower/javascript/README.md similarity index 100% rename from 90 Tower/javascript/README.md rename to 90_Tower/javascript/README.md diff --git a/90 Tower/javascript/tower.html b/90_Tower/javascript/tower.html similarity index 100% rename from 90 Tower/javascript/tower.html rename to 90_Tower/javascript/tower.html diff --git a/90 Tower/javascript/tower.js b/90_Tower/javascript/tower.js similarity index 100% rename from 90 Tower/javascript/tower.js rename to 90_Tower/javascript/tower.js diff --git a/90 Tower/pascal/README.md b/90_Tower/pascal/README.md similarity index 100% rename from 90 Tower/pascal/README.md rename to 90_Tower/pascal/README.md diff --git a/90 Tower/perl/README.md b/90_Tower/perl/README.md similarity index 100% rename from 90 Tower/perl/README.md rename to 90_Tower/perl/README.md diff --git a/90 Tower/python/README.md b/90_Tower/python/README.md similarity index 100% rename from 90 Tower/python/README.md rename to 90_Tower/python/README.md diff --git a/90 Tower/ruby/README.md b/90_Tower/ruby/README.md similarity index 100% rename from 90 Tower/ruby/README.md rename to 90_Tower/ruby/README.md diff --git a/90 Tower/tower.bas b/90_Tower/tower.bas similarity index 100% rename from 90 Tower/tower.bas rename to 90_Tower/tower.bas diff --git a/90 Tower/vbnet/README.md b/90_Tower/vbnet/README.md similarity index 100% rename from 90 Tower/vbnet/README.md rename to 90_Tower/vbnet/README.md diff --git a/91 Train/README.md b/91_Train/README.md similarity index 100% rename from 91 Train/README.md rename to 91_Train/README.md diff --git a/91 Train/csharp/README.md b/91_Train/csharp/README.md similarity index 100% rename from 91 Train/csharp/README.md rename to 91_Train/csharp/README.md diff --git a/91 Train/java/README.md b/91_Train/java/README.md similarity index 100% rename from 91 Train/java/README.md rename to 91_Train/java/README.md diff --git a/91 Train/java/src/Train.java b/91_Train/java/src/Train.java similarity index 100% rename from 91 Train/java/src/Train.java rename to 91_Train/java/src/Train.java diff --git a/91 Train/javascript/README.md b/91_Train/javascript/README.md similarity index 100% rename from 91 Train/javascript/README.md rename to 91_Train/javascript/README.md diff --git a/91 Train/javascript/train.html b/91_Train/javascript/train.html similarity index 100% rename from 91 Train/javascript/train.html rename to 91_Train/javascript/train.html diff --git a/91 Train/javascript/train.js b/91_Train/javascript/train.js similarity index 100% rename from 91 Train/javascript/train.js rename to 91_Train/javascript/train.js diff --git a/91 Train/pascal/README.md b/91_Train/pascal/README.md similarity index 100% rename from 91 Train/pascal/README.md rename to 91_Train/pascal/README.md diff --git a/91 Train/perl/README.md b/91_Train/perl/README.md similarity index 100% rename from 91 Train/perl/README.md rename to 91_Train/perl/README.md diff --git a/91 Train/perl/train.pl b/91_Train/perl/train.pl similarity index 100% rename from 91 Train/perl/train.pl rename to 91_Train/perl/train.pl diff --git a/91 Train/python/README.md b/91_Train/python/README.md similarity index 100% rename from 91 Train/python/README.md rename to 91_Train/python/README.md diff --git a/91 Train/python/train.py b/91_Train/python/train.py similarity index 100% rename from 91 Train/python/train.py rename to 91_Train/python/train.py diff --git a/91 Train/ruby/README.md b/91_Train/ruby/README.md similarity index 100% rename from 91 Train/ruby/README.md rename to 91_Train/ruby/README.md diff --git a/91 Train/ruby/train.rb b/91_Train/ruby/train.rb similarity index 100% rename from 91 Train/ruby/train.rb rename to 91_Train/ruby/train.rb diff --git a/91 Train/train.bas b/91_Train/train.bas similarity index 100% rename from 91 Train/train.bas rename to 91_Train/train.bas diff --git a/91 Train/vbnet/README.md b/91_Train/vbnet/README.md similarity index 100% rename from 91 Train/vbnet/README.md rename to 91_Train/vbnet/README.md diff --git a/92 Trap/README.md b/92_Trap/README.md similarity index 100% rename from 92 Trap/README.md rename to 92_Trap/README.md diff --git a/92 Trap/csharp/README.md b/92_Trap/csharp/README.md similarity index 100% rename from 92 Trap/csharp/README.md rename to 92_Trap/csharp/README.md diff --git a/92 Trap/java/README.md b/92_Trap/java/README.md similarity index 100% rename from 92 Trap/java/README.md rename to 92_Trap/java/README.md diff --git a/92 Trap/java/src/Trap.java b/92_Trap/java/src/Trap.java similarity index 100% rename from 92 Trap/java/src/Trap.java rename to 92_Trap/java/src/Trap.java diff --git a/92 Trap/java/src/TrapGame.java b/92_Trap/java/src/TrapGame.java similarity index 100% rename from 92 Trap/java/src/TrapGame.java rename to 92_Trap/java/src/TrapGame.java diff --git a/92 Trap/javascript/README.md b/92_Trap/javascript/README.md similarity index 100% rename from 92 Trap/javascript/README.md rename to 92_Trap/javascript/README.md diff --git a/92 Trap/javascript/trap.html b/92_Trap/javascript/trap.html similarity index 100% rename from 92 Trap/javascript/trap.html rename to 92_Trap/javascript/trap.html diff --git a/92 Trap/javascript/trap.js b/92_Trap/javascript/trap.js similarity index 100% rename from 92 Trap/javascript/trap.js rename to 92_Trap/javascript/trap.js diff --git a/92 Trap/pascal/README.md b/92_Trap/pascal/README.md similarity index 100% rename from 92 Trap/pascal/README.md rename to 92_Trap/pascal/README.md diff --git a/92 Trap/perl/README.md b/92_Trap/perl/README.md similarity index 100% rename from 92 Trap/perl/README.md rename to 92_Trap/perl/README.md diff --git a/92 Trap/perl/trap.pl b/92_Trap/perl/trap.pl similarity index 100% rename from 92 Trap/perl/trap.pl rename to 92_Trap/perl/trap.pl diff --git a/92 Trap/python/README.md b/92_Trap/python/README.md similarity index 100% rename from 92 Trap/python/README.md rename to 92_Trap/python/README.md diff --git a/92 Trap/python/trap.py b/92_Trap/python/trap.py similarity index 100% rename from 92 Trap/python/trap.py rename to 92_Trap/python/trap.py diff --git a/92 Trap/ruby/README.md b/92_Trap/ruby/README.md similarity index 100% rename from 92 Trap/ruby/README.md rename to 92_Trap/ruby/README.md diff --git a/92 Trap/trap.bas b/92_Trap/trap.bas similarity index 100% rename from 92 Trap/trap.bas rename to 92_Trap/trap.bas diff --git a/92 Trap/vbnet/README.md b/92_Trap/vbnet/README.md similarity index 100% rename from 92 Trap/vbnet/README.md rename to 92_Trap/vbnet/README.md diff --git a/93 23 Matches/23matches.bas b/93_23_Matches/23matches.bas similarity index 100% rename from 93 23 Matches/23matches.bas rename to 93_23_Matches/23matches.bas diff --git a/93 23 Matches/README.md b/93_23_Matches/README.md similarity index 100% rename from 93 23 Matches/README.md rename to 93_23_Matches/README.md diff --git a/93 23 Matches/csharp/README.md b/93_23_Matches/csharp/README.md similarity index 100% rename from 93 23 Matches/csharp/README.md rename to 93_23_Matches/csharp/README.md diff --git a/93 23 Matches/java/README.md b/93_23_Matches/java/README.md similarity index 100% rename from 93 23 Matches/java/README.md rename to 93_23_Matches/java/README.md diff --git a/93 23 Matches/java/TwentyThreeMatches.java b/93_23_Matches/java/TwentyThreeMatches.java similarity index 100% rename from 93 23 Matches/java/TwentyThreeMatches.java rename to 93_23_Matches/java/TwentyThreeMatches.java diff --git a/93 23 Matches/javascript/23matches.html b/93_23_Matches/javascript/23matches.html similarity index 100% rename from 93 23 Matches/javascript/23matches.html rename to 93_23_Matches/javascript/23matches.html diff --git a/93 23 Matches/javascript/23matches.js b/93_23_Matches/javascript/23matches.js similarity index 100% rename from 93 23 Matches/javascript/23matches.js rename to 93_23_Matches/javascript/23matches.js diff --git a/93 23 Matches/javascript/README.md b/93_23_Matches/javascript/README.md similarity index 100% rename from 93 23 Matches/javascript/README.md rename to 93_23_Matches/javascript/README.md diff --git a/93 23 Matches/pascal/README.md b/93_23_Matches/pascal/README.md similarity index 100% rename from 93 23 Matches/pascal/README.md rename to 93_23_Matches/pascal/README.md diff --git a/93 23 Matches/perl/README.md b/93_23_Matches/perl/README.md similarity index 100% rename from 93 23 Matches/perl/README.md rename to 93_23_Matches/perl/README.md diff --git a/93 23 Matches/python/23matches.py b/93_23_Matches/python/23matches.py similarity index 100% rename from 93 23 Matches/python/23matches.py rename to 93_23_Matches/python/23matches.py diff --git a/93 23 Matches/python/README.md b/93_23_Matches/python/README.md similarity index 100% rename from 93 23 Matches/python/README.md rename to 93_23_Matches/python/README.md diff --git a/93 23 Matches/ruby/README.md b/93_23_Matches/ruby/README.md similarity index 100% rename from 93 23 Matches/ruby/README.md rename to 93_23_Matches/ruby/README.md diff --git a/93 23 Matches/vbnet/README.md b/93_23_Matches/vbnet/README.md similarity index 100% rename from 93 23 Matches/vbnet/README.md rename to 93_23_Matches/vbnet/README.md diff --git a/94 War/README.md b/94_War/README.md similarity index 100% rename from 94 War/README.md rename to 94_War/README.md diff --git a/94 War/csharp/README.md b/94_War/csharp/README.md similarity index 100% rename from 94 War/csharp/README.md rename to 94_War/csharp/README.md diff --git a/94 War/csharp/War/War.sln b/94_War/csharp/War/War.sln similarity index 100% rename from 94 War/csharp/War/War.sln rename to 94_War/csharp/War/War.sln diff --git a/94 War/csharp/War/War/Cards.cs b/94_War/csharp/War/War/Cards.cs similarity index 100% rename from 94 War/csharp/War/War/Cards.cs rename to 94_War/csharp/War/War/Cards.cs diff --git a/94 War/csharp/War/War/Program.cs b/94_War/csharp/War/War/Program.cs similarity index 100% rename from 94 War/csharp/War/War/Program.cs rename to 94_War/csharp/War/War/Program.cs diff --git a/94 War/csharp/War/War/UserInterface.cs b/94_War/csharp/War/War/UserInterface.cs similarity index 100% rename from 94 War/csharp/War/War/UserInterface.cs rename to 94_War/csharp/War/War/UserInterface.cs diff --git a/94 War/csharp/War/War/War.csproj b/94_War/csharp/War/War/War.csproj similarity index 100% rename from 94 War/csharp/War/War/War.csproj rename to 94_War/csharp/War/War/War.csproj diff --git a/94 War/csharp/War/WarTester/Tests.cs b/94_War/csharp/War/WarTester/Tests.cs similarity index 100% rename from 94 War/csharp/War/WarTester/Tests.cs rename to 94_War/csharp/War/WarTester/Tests.cs diff --git a/94 War/csharp/War/WarTester/WarTester.csproj b/94_War/csharp/War/WarTester/WarTester.csproj similarity index 100% rename from 94 War/csharp/War/WarTester/WarTester.csproj rename to 94_War/csharp/War/WarTester/WarTester.csproj diff --git a/94 War/java/README.md b/94_War/java/README.md similarity index 100% rename from 94 War/java/README.md rename to 94_War/java/README.md diff --git a/94 War/java/War.java b/94_War/java/War.java similarity index 100% rename from 94 War/java/War.java rename to 94_War/java/War.java diff --git a/94 War/javascript/README.md b/94_War/javascript/README.md similarity index 100% rename from 94 War/javascript/README.md rename to 94_War/javascript/README.md diff --git a/94 War/javascript/war.html b/94_War/javascript/war.html similarity index 100% rename from 94 War/javascript/war.html rename to 94_War/javascript/war.html diff --git a/94 War/javascript/war.js b/94_War/javascript/war.js similarity index 100% rename from 94 War/javascript/war.js rename to 94_War/javascript/war.js diff --git a/94 War/pascal/README.md b/94_War/pascal/README.md similarity index 100% rename from 94 War/pascal/README.md rename to 94_War/pascal/README.md diff --git a/94 War/perl/README.md b/94_War/perl/README.md similarity index 100% rename from 94 War/perl/README.md rename to 94_War/perl/README.md diff --git a/94 War/python/README.md b/94_War/python/README.md similarity index 100% rename from 94 War/python/README.md rename to 94_War/python/README.md diff --git a/94 War/python/war.py b/94_War/python/war.py similarity index 100% rename from 94 War/python/war.py rename to 94_War/python/war.py diff --git a/94 War/ruby/README.md b/94_War/ruby/README.md similarity index 100% rename from 94 War/ruby/README.md rename to 94_War/ruby/README.md diff --git a/94 War/vbnet/README.md b/94_War/vbnet/README.md similarity index 100% rename from 94 War/vbnet/README.md rename to 94_War/vbnet/README.md diff --git a/94 War/war.bas b/94_War/war.bas similarity index 100% rename from 94 War/war.bas rename to 94_War/war.bas diff --git a/95 Weekday/README.md b/95_Weekday/README.md similarity index 100% rename from 95 Weekday/README.md rename to 95_Weekday/README.md diff --git a/95 Weekday/csharp/README.md b/95_Weekday/csharp/README.md similarity index 100% rename from 95 Weekday/csharp/README.md rename to 95_Weekday/csharp/README.md diff --git a/95 Weekday/java/README.md b/95_Weekday/java/README.md similarity index 100% rename from 95 Weekday/java/README.md rename to 95_Weekday/java/README.md diff --git a/95 Weekday/java/Weekday.java b/95_Weekday/java/Weekday.java similarity index 100% rename from 95 Weekday/java/Weekday.java rename to 95_Weekday/java/Weekday.java diff --git a/95 Weekday/javascript/README.md b/95_Weekday/javascript/README.md similarity index 100% rename from 95 Weekday/javascript/README.md rename to 95_Weekday/javascript/README.md diff --git a/95 Weekday/javascript/weekday.html b/95_Weekday/javascript/weekday.html similarity index 100% rename from 95 Weekday/javascript/weekday.html rename to 95_Weekday/javascript/weekday.html diff --git a/95 Weekday/javascript/weekday.js b/95_Weekday/javascript/weekday.js similarity index 100% rename from 95 Weekday/javascript/weekday.js rename to 95_Weekday/javascript/weekday.js diff --git a/95 Weekday/pascal/README.md b/95_Weekday/pascal/README.md similarity index 100% rename from 95 Weekday/pascal/README.md rename to 95_Weekday/pascal/README.md diff --git a/95 Weekday/perl/README.md b/95_Weekday/perl/README.md similarity index 100% rename from 95 Weekday/perl/README.md rename to 95_Weekday/perl/README.md diff --git a/95 Weekday/python/README.md b/95_Weekday/python/README.md similarity index 100% rename from 95 Weekday/python/README.md rename to 95_Weekday/python/README.md diff --git a/95 Weekday/python/weekday.py b/95_Weekday/python/weekday.py similarity index 100% rename from 95 Weekday/python/weekday.py rename to 95_Weekday/python/weekday.py diff --git a/95 Weekday/ruby/README.md b/95_Weekday/ruby/README.md similarity index 100% rename from 95 Weekday/ruby/README.md rename to 95_Weekday/ruby/README.md diff --git a/95 Weekday/vbnet/README.md b/95_Weekday/vbnet/README.md similarity index 100% rename from 95 Weekday/vbnet/README.md rename to 95_Weekday/vbnet/README.md diff --git a/95 Weekday/weekday.bas b/95_Weekday/weekday.bas similarity index 100% rename from 95 Weekday/weekday.bas rename to 95_Weekday/weekday.bas diff --git a/96 Word/README.md b/96_Word/README.md similarity index 100% rename from 96 Word/README.md rename to 96_Word/README.md diff --git a/96 Word/csharp/Program.cs b/96_Word/csharp/Program.cs similarity index 100% rename from 96 Word/csharp/Program.cs rename to 96_Word/csharp/Program.cs diff --git a/96 Word/csharp/README.md b/96_Word/csharp/README.md similarity index 100% rename from 96 Word/csharp/README.md rename to 96_Word/csharp/README.md diff --git a/96 Word/csharp/word.csproj b/96_Word/csharp/word.csproj similarity index 100% rename from 96 Word/csharp/word.csproj rename to 96_Word/csharp/word.csproj diff --git a/96 Word/csharp/word.sln b/96_Word/csharp/word.sln similarity index 100% rename from 96 Word/csharp/word.sln rename to 96_Word/csharp/word.sln diff --git a/96 Word/java/README.md b/96_Word/java/README.md similarity index 100% rename from 96 Word/java/README.md rename to 96_Word/java/README.md diff --git a/96 Word/java/Word.java b/96_Word/java/Word.java similarity index 100% rename from 96 Word/java/Word.java rename to 96_Word/java/Word.java diff --git a/96 Word/javascript/README.md b/96_Word/javascript/README.md similarity index 100% rename from 96 Word/javascript/README.md rename to 96_Word/javascript/README.md diff --git a/96 Word/javascript/word.html b/96_Word/javascript/word.html similarity index 100% rename from 96 Word/javascript/word.html rename to 96_Word/javascript/word.html diff --git a/96 Word/javascript/word.js b/96_Word/javascript/word.js similarity index 100% rename from 96 Word/javascript/word.js rename to 96_Word/javascript/word.js diff --git a/96 Word/pascal/README.md b/96_Word/pascal/README.md similarity index 100% rename from 96 Word/pascal/README.md rename to 96_Word/pascal/README.md diff --git a/96 Word/perl/README.md b/96_Word/perl/README.md similarity index 100% rename from 96 Word/perl/README.md rename to 96_Word/perl/README.md diff --git a/96 Word/python/README.md b/96_Word/python/README.md similarity index 100% rename from 96 Word/python/README.md rename to 96_Word/python/README.md diff --git a/96 Word/python/word.py b/96_Word/python/word.py similarity index 100% rename from 96 Word/python/word.py rename to 96_Word/python/word.py diff --git a/96 Word/ruby/README.md b/96_Word/ruby/README.md similarity index 100% rename from 96 Word/ruby/README.md rename to 96_Word/ruby/README.md diff --git a/96 Word/ruby/word.rb b/96_Word/ruby/word.rb similarity index 100% rename from 96 Word/ruby/word.rb rename to 96_Word/ruby/word.rb diff --git a/96 Word/vbnet/Program.vb b/96_Word/vbnet/Program.vb similarity index 100% rename from 96 Word/vbnet/Program.vb rename to 96_Word/vbnet/Program.vb diff --git a/96 Word/vbnet/README.md b/96_Word/vbnet/README.md similarity index 100% rename from 96 Word/vbnet/README.md rename to 96_Word/vbnet/README.md diff --git a/96 Word/vbnet/word.sln b/96_Word/vbnet/word.sln similarity index 100% rename from 96 Word/vbnet/word.sln rename to 96_Word/vbnet/word.sln diff --git a/96 Word/vbnet/word.vbproj b/96_Word/vbnet/word.vbproj similarity index 100% rename from 96 Word/vbnet/word.vbproj rename to 96_Word/vbnet/word.vbproj diff --git a/96 Word/word.bas b/96_Word/word.bas similarity index 100% rename from 96 Word/word.bas rename to 96_Word/word.bas From 36e49026e64d6554d63a5909eb1fd371acd6ef51 Mon Sep 17 00:00:00 2001 From: GwakMirae Date: Sat, 27 Nov 2021 16:14:12 +0900 Subject: [PATCH 433/749] make Digits.py for Python and add main() --- 34_Digits/python/Digits.py | 86 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 34_Digits/python/Digits.py diff --git a/34_Digits/python/Digits.py b/34_Digits/python/Digits.py new file mode 100644 index 00000000..5508375c --- /dev/null +++ b/34_Digits/python/Digits.py @@ -0,0 +1,86 @@ +if __name__ == '__main__': + printIntro() + if readInstructionChoice(): + printInstructions() + + a = 0 + b = 1 + c = 3 + + m = [[1] * 3 for i in range(27)] + k = [[9] * 3 for i in range(3)] + l = [[3] * 3 for i in range(9)] + + continueGame = True + while continueGame: + l[0][0] = 2 + l[4][1] = 2 + l[8][2] = 2 + z = 26 + z1 = 8 + z2 = 2 + runningCorrect = 0 + + for t in range(1, 4): + validNumbers = False + numbers = [] + while not validNumbers: + print() + numbers = read10Numbers() + validNumbers = True + for number in numbers: + if number < 0 or number > 2: + print("ONLY USE THE DIGITS '0', '1', OR '2'.") + print("LET'S TRY AGAIN.") + validNumbers = False + break + + print("\n%-14s%-14s%-14s%-14s" % ("MY GUESS", "YOUR NO.", "RESULT", "NO. RIGHT")) + + for number in numbers: + s = 0 + myGuess = 0 + for j in range(0, 3): + # What did the original author have in mind ? + # The first expression always results in 0 because a is always 0 + s1 = a * k[z2][j] + b * l[int(z1)][j] + c * m[int(z)][j] + if s < s1: + s = s1 + myGuess = j + elif s1 == s: + if random.random() >= 0.5: + myGuess = j + + result = "" + + if myGuess != number: + result = "WRONG" + else: + runningCorrect += 1 + result = "RIGHT" + m[int(z)][number] = m[int(z)][number] + 1 + l[int(z1)][number] = l[int(z1)][number] + 1 + k[int(z2)][number] = k[int(z2)][number] + 1 + z = z - (z / 9) * 9 + z = 3 * z + number + print("\n%-14d%-14d%-14s%-14d" % (myGuess, number, result, runningCorrect)) + + z1 = z - (z / 9) * 9 + z2 = number + + # print summary report + print() + if runningCorrect > 10: + print() + print("I GUESSED MORE THAN 1/3 OF YOUR NUMBERS.") + print("I WIN." + u"\u0007") + elif runningCorrect < 10: + print("I GUESSED LESS THAN 1/3 OF YOUR NUMBERS.") + print("YOU BEAT ME. CONGRATULATIONS *****") + else: + print("I GUESSED EXACTLY 1/3 OF YOUR NUMBERS.") + print("IT'S A TIE GAME.") + + continueGame = readContinueChoice() + + print("\nTHANKS FOR THE GAME.") \ No newline at end of file From c1380486d251485d74f9ede365775a2bf5060706 Mon Sep 17 00:00:00 2001 From: leecr1215 Date: Sat, 27 Nov 2021 16:22:01 +0900 Subject: [PATCH 434/749] feat: add fuctions --- 34_Digits/python/Digits.py | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/34_Digits/python/Digits.py b/34_Digits/python/Digits.py index 5508375c..48647c12 100644 --- a/34_Digits/python/Digits.py +++ b/34_Digits/python/Digits.py @@ -1,3 +1,58 @@ +import random + +def printIntro(): + print(" DIGITS") + print(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print("\n\n") + print("THIS IS A GAME OF GUESSING.") + + +def readInstructionChoice(): + print("FOR INSTRUCTIONS, TYPE '1', ELSE TYPE '0' ? ") + try: + choice = int(input()) + return choice == 1 + except (ValueError, TypeError) as m: + return False + + +def printInstructions(): + print("\n") + print("PLEASE TAKE A PIECE OF PAPER AND WRITE DOWN") + print("THE DIGITS '0', '1', OR '2' THIRTY TIMES AT RANDOM.") + print("ARRANGE THEM IN THREE LINES OF TEN DIGITS EACH.") + print("I WILL ASK FOR THEN TEN AT A TIME.") + print("I WILL ALWAYS GUESS THEM FIRST AND THEN LOOK AT YOUR") + print("NEXT NUMBER TO SEE IF I WAS RIGHT. BY PURE LUCK,") + print("I OUGHT TO BE RIGHT TEN TIMES. BUT I HOPE TO DO BETTER") + print("THAN THAT *****") + print() + + +def read10Numbers(): + print("TEN NUMBERS, PLEASE ? ") + numbers = [] + + for i in range(10): + validInput = False + while not validInput: + try: + n = int(input()) + validInput = True + numbers.append(n) + except (TypeError, ValueError) as e: + print("!NUMBER EXPECTED - RETRY INPUT LINE") + + return numbers + +def readContinueChoice(): + print("\nDO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO) ? ") + try: + choice = int(input()) + return choice == 1 + except (ValueError, TypeError) as m: + return False + if __name__ == '__main__': printIntro() if readInstructionChoice(): From 02eac5b514f5fab24dd7ee9ab9c7b81a5c226b0b Mon Sep 17 00:00:00 2001 From: sonyi00 Date: Sat, 27 Nov 2021 18:21:43 +0900 Subject: [PATCH 435/749] update main function --- 28_Combat/python/combat.py | 82 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 28_Combat/python/combat.py diff --git a/28_Combat/python/combat.py b/28_Combat/python/combat.py new file mode 100644 index 00000000..bc1e78b5 --- /dev/null +++ b/28_Combat/python/combat.py @@ -0,0 +1,82 @@ +def attackSecond(): + global usrArmy, usrNavy, usrAir, cpuArmy, cpuNavy, cpuAir + global planeCrashWin + numUnits = 0 + unitType = 0 + + print("") + print(" YOU ME") + print("ARMY ", end="") + print("%-14s%s\n" % (usrArmy, cpuArmy), end="") + print("NAVY ", end="") + print("%-14s%s\n" % (usrNavy, cpuNavy), end="") + print("A. F. ", end="") + print("%-14s%s\n" % (usrAir, cpuAir), end="") + + while True: + print("WHAT IS YOUR NEXT MOVE?") + print("ARMY=1 NAVY=2 AIR FORCE=3") + print("? ", end="") + unitType = int(input()) + if not ((unitType < 1) or (unitType > 3)): + break + + while True: + print("HOW MANY MEN") + print("? ", end="") + numUnits = int(input()) + if not((numUnits < 0) or ((unitType == 1) and (numUnits > usrArmy)) or ((unitType == 2) and (numUnits > usrNavy)) or ((unitType == 3) and (numUnits > usrAir))): + break + + if unitType == 1: + if numUnits < (cpuArmy/2): + print("I WIPED OUT YOUR ATTACK!") + usrArmy = usrArmy - numUnits + else: + print("YOU DESTROYED MY ARMY!") + cpuArmy = 0 + elif unitType == 2: + if numUnits < (cpuNavy/2): + print("I SUNK TWO OF YOUR BATTLESHIPS, AND MY AIR FORCE") + print("WIPED OUT YOUR UNGUARDED CAPITOL.") + usrArmy = int(usrArmy/4) + usrNavy = int(usrNavy/2) + else: + print("YOUR NAVY SHOT DOWN THREE OF MY XIII PLANES,") + print("AND SUNK THREE BATTLESHIPS.") + cpuAir = int(2*cpuAir/3) + cpuNavy = int(cpuNavy/2) + elif unitType == 3: + if numUnits > (cpuAir/2): + print("MY NAVY AND AIR FORCE IN A COMBINED ATTACK LEFT") + print("YOUR COUNTRY IN SHAMBLES.") + usrArmy = int(usrArmy/3) + usrNavy = int(usrNavy/3) + usrAir = int(usrAir/3) + else: + print("ONE OF YOUR PLANES CRASHED INTO MY HOUSE. I AM DEAD.") + print("MY COUNTRY FELL APART.") + planeCrashWin = True + + if planeCrashWin == False: + print("") + print("FROM THE RESULTS OF BOTH OF YOUR ATTACKS,") + + if (planeCrashWin == True) or ((usrArmy + usrNavy + usrAir) > (int(3/2*(cpuArmy + cpuNavy + cpuAir)))): + print("YOU WON, OH! SHUCKS!!!!") + elif (usrArmy + usrNavy + usrAir) < int(2/3*(cpuArmy + cpuNavy + cpuAir)): + print("YOU LOST-I CONQUERED YOUR COUNTRY. IT SERVES YOU") + print("RIGHT FOR PLAYING THIS STUPID GAME!!!") + else: + print("THE TREATY OF PARIS CONCLUDED THAT WE TAKE OUR") + print("RESPECTIVE COUNTRIES AND LIVE IN PEACE.") + + +def main(): + showIntro() + getForces() + attackFirst() + attackSecond() + +if __name__ == '__main__': + main() \ No newline at end of file From 9d7a904e680508d7323af54ccb49c75484a66d72 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 27 Nov 2021 22:53:17 +1100 Subject: [PATCH 436/749] Add game logic and fix resources --- 90 Tower/csharp/Tower/Game.cs | 78 +++++++++++++++++++ 90 Tower/csharp/Tower/Models/Needle.cs | 2 + 90 Tower/csharp/Tower/Models/Towers.cs | 41 ++++++++-- 90 Tower/csharp/Tower/Program.cs | 17 +++- .../Tower/Resources/Congratulations.txt | 2 +- .../csharp/Tower/Resources/DiskNotInPlay.txt | 1 + .../csharp/Tower/Resources/Instructions.txt | 1 + 90 Tower/csharp/Tower/Resources/Intro.txt | 4 - 90 Tower/csharp/Tower/Resources/Strings.cs | 2 + .../csharp/Tower/Resources/TaskFinished.txt | 2 + 90 Tower/csharp/Tower/Resources/Title.txt | 6 -- .../csharp/Tower/Resources/TooManyMoves.txt | 2 +- 90 Tower/csharp/Tower/UI/Input.cs | 2 + 90 Tower/csharp/Tower/UI/TowerDisplay.cs | 8 +- 14 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 90 Tower/csharp/Tower/Game.cs create mode 100644 90 Tower/csharp/Tower/Resources/DiskNotInPlay.txt create mode 100644 90 Tower/csharp/Tower/Resources/TaskFinished.txt diff --git a/90 Tower/csharp/Tower/Game.cs b/90 Tower/csharp/Tower/Game.cs new file mode 100644 index 00000000..7e0c7d0b --- /dev/null +++ b/90 Tower/csharp/Tower/Game.cs @@ -0,0 +1,78 @@ +using System; +using Tower.Models; +using Tower.Resources; +using Tower.UI; + +namespace Tower +{ + internal class Game + { + private readonly Towers _towers; + private readonly TowerDisplay _display; + private readonly int _optimalMoveCount; + private int _moveCount; + + public Game(int diskCount) + { + _towers = new Towers(diskCount); + _display = new TowerDisplay(_towers); + _optimalMoveCount = (1 << diskCount) - 1; + } + + public bool Play() + { + Console.Write(Strings.Instructions); + + Console.Write(_display); + + while (true) + { + if (!Input.TryReadNumber(Prompt.Disk, out int disk)) { return false; } + + if (!_towers.TryFindDisk(disk, out var from, out var message)) + { + Console.WriteLine(message); + continue; + } + + if (!Input.TryReadNumber(Prompt.Needle, out var to)) { return false; } + + if (!_towers.TryMoveDisk(from, to)) + { + Console.Write(Strings.IllegalMove); + continue; + } + + Console.Write(_display); + + var result = CheckProgress(); + if (result.HasValue) { return result.Value; } + } + } + + private bool? CheckProgress() + { + _moveCount++; + + if (_moveCount == 128) + { + Console.Write(Strings.TooManyMoves); + return false; + } + + if (_towers.Finished) + { + if (_moveCount == _optimalMoveCount) + { + Console.Write(Strings.Congratulations); + } + + Console.WriteLine(Strings.TaskFinished, _moveCount); + + return true; + } + + return default; + } + } +} diff --git a/90 Tower/csharp/Tower/Models/Needle.cs b/90 Tower/csharp/Tower/Models/Needle.cs index f47329d6..1cd929fa 100644 --- a/90 Tower/csharp/Tower/Models/Needle.cs +++ b/90 Tower/csharp/Tower/Models/Needle.cs @@ -8,6 +8,8 @@ namespace Tower.Models { private readonly Stack _disks = new Stack(); + public bool IsEmpty => _disks.Count == 0; + public int Top => _disks.TryPeek(out var disk) ? disk : default; public bool TryPut(int disk) diff --git a/90 Tower/csharp/Tower/Models/Towers.cs b/90 Tower/csharp/Tower/Models/Towers.cs index 7672ad52..4b03b933 100644 --- a/90 Tower/csharp/Tower/Models/Towers.cs +++ b/90 Tower/csharp/Tower/Models/Towers.cs @@ -2,33 +2,60 @@ using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using Tower.Resources; namespace Tower.Models { internal class Towers : IEnumerable<(int, int, int)> { - private readonly Needle[] _needles = new[] { new Needle(), new Needle(), new Needle() }; + private static int[] _availableDisks = new[] { 15, 13, 11, 9, 7, 5, 3 }; - public bool TryFindDisk(int disk, out int needle) + private readonly Needle[] _needles = new[] { new Needle(), new Needle(), new Needle() }; + private readonly int _smallestDisk; + + public Towers(int diskCount) { - for (needle = 1; needle <= 3; needle++) + foreach (int disk in _availableDisks.Take(diskCount)) { - if (_needles[needle].Top == disk) { return true; } + this[1].TryPut(disk); + _smallestDisk = disk; + } + } + + private Needle this[int i] => _needles[i-1]; + + public bool Finished => this[1].IsEmpty && this[2].IsEmpty; + + public bool TryFindDisk(int disk, out int needle, out string message) + { + needle = default; + message = default; + + if (disk < _smallestDisk) + { + message = Strings.DiskNotInPlay; + return false; } + for (needle = 1; needle <= 3; needle++) + { + if (this[needle].Top == disk) { return true; } + } + + message = Strings.DiskUnavailable; return false; } public bool TryMoveDisk(int from, int to) { - if (!_needles[from].TryGetTopDisk(out var disk)) + if (!this[from].TryGetTopDisk(out var disk)) { throw new InvalidOperationException($"Needle {from} is empty"); } - if (_needles[to].TryPut(disk)) { return true; } + if (this[to].TryPut(disk)) { return true; } - _needles[from].TryPut(disk); + this[from].TryPut(disk); return false; } diff --git a/90 Tower/csharp/Tower/Program.cs b/90 Tower/csharp/Tower/Program.cs index 4793b817..6bc9f107 100644 --- a/90 Tower/csharp/Tower/Program.cs +++ b/90 Tower/csharp/Tower/Program.cs @@ -1,4 +1,6 @@ using System; +using Tower.Resources; +using Tower.UI; namespace Tower { @@ -6,7 +8,20 @@ namespace Tower { static void Main(string[] args) { - Console.WriteLine("Hello World!"); + Console.Write(Strings.Title); + + do + { + Console.Write(Strings.Intro); + + if (!Input.TryReadNumber(Prompt.DiskCount, out var diskCount)) { return; } + + var game = new Game(diskCount); + + if (!game.Play()) { return; } + } while (Input.ReadYesNo(Strings.PlayAgainPrompt, Strings.YesNoPrompt)); + + Console.Write(Strings.Thanks); } } } diff --git a/90 Tower/csharp/Tower/Resources/Congratulations.txt b/90 Tower/csharp/Tower/Resources/Congratulations.txt index 332297b2..fb078fba 100644 --- a/90 Tower/csharp/Tower/Resources/Congratulations.txt +++ b/90 Tower/csharp/Tower/Resources/Congratulations.txt @@ -1,2 +1,2 @@ -Congratulations +Congratulations!! diff --git a/90 Tower/csharp/Tower/Resources/DiskNotInPlay.txt b/90 Tower/csharp/Tower/Resources/DiskNotInPlay.txt new file mode 100644 index 00000000..270ed0a5 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/DiskNotInPlay.txt @@ -0,0 +1 @@ +That disk is not in play. Make another choice. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/Instructions.txt b/90 Tower/csharp/Tower/Resources/Instructions.txt index 93c71b8d..ca75537b 100644 --- a/90 Tower/csharp/Tower/Resources/Instructions.txt +++ b/90 Tower/csharp/Tower/Resources/Instructions.txt @@ -8,3 +8,4 @@ startup with the disks on needle 1, and attempt to move them to needle 3. Good luck! + diff --git a/90 Tower/csharp/Tower/Resources/Intro.txt b/90 Tower/csharp/Tower/Resources/Intro.txt index a88049a9..e5345da6 100644 --- a/90 Tower/csharp/Tower/Resources/Intro.txt +++ b/90 Tower/csharp/Tower/Resources/Intro.txt @@ -1,7 +1,3 @@ - Towers - Creative Computing Morristown, New Jersey - - Towers of Hanoi puzzle. diff --git a/90 Tower/csharp/Tower/Resources/Strings.cs b/90 Tower/csharp/Tower/Resources/Strings.cs index 62b84d0a..0cd8f6e1 100644 --- a/90 Tower/csharp/Tower/Resources/Strings.cs +++ b/90 Tower/csharp/Tower/Resources/Strings.cs @@ -10,6 +10,7 @@ namespace Tower.Resources internal static string DiskCountPrompt => GetResource(); internal static string DiskCountQuit => GetResource(); internal static string DiskCountRetry => GetResource(); + internal static string DiskNotInPlay => GetResource(); internal static string DiskPrompt => GetResource(); internal static string DiskQuit => GetResource(); internal static string DiskRetry => GetResource(); @@ -21,6 +22,7 @@ namespace Tower.Resources internal static string NeedleQuit => GetResource(); internal static string NeedleRetry => GetResource(); internal static string PlayAgainPrompt => GetResource(); + internal static string TaskFinished => GetResource(); internal static string Thanks => GetResource(); internal static string Title => GetResource(); internal static string TooManyMoves => GetResource(); diff --git a/90 Tower/csharp/Tower/Resources/TaskFinished.txt b/90 Tower/csharp/Tower/Resources/TaskFinished.txt new file mode 100644 index 00000000..e1ea1309 --- /dev/null +++ b/90 Tower/csharp/Tower/Resources/TaskFinished.txt @@ -0,0 +1,2 @@ + +You have performed the task in {0} moves. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/Resources/Title.txt b/90 Tower/csharp/Tower/Resources/Title.txt index a88049a9..ae130577 100644 --- a/90 Tower/csharp/Tower/Resources/Title.txt +++ b/90 Tower/csharp/Tower/Resources/Title.txt @@ -3,9 +3,3 @@ -Towers of Hanoi puzzle. - -You must transfer the disks from the left to the right -tower, one at a time, never putting a larger dish on a -smaller disk. - diff --git a/90 Tower/csharp/Tower/Resources/TooManyMoves.txt b/90 Tower/csharp/Tower/Resources/TooManyMoves.txt index c517218e..680803a5 100644 --- a/90 Tower/csharp/Tower/Resources/TooManyMoves.txt +++ b/90 Tower/csharp/Tower/Resources/TooManyMoves.txt @@ -1,2 +1,2 @@ -Sorry, but i have orders to stop is you make more than +Sorry, but I have orders to stop if you make more than 128 moves. \ No newline at end of file diff --git a/90 Tower/csharp/Tower/UI/Input.cs b/90 Tower/csharp/Tower/UI/Input.cs index 9b2d3747..d1eca384 100644 --- a/90 Tower/csharp/Tower/UI/Input.cs +++ b/90 Tower/csharp/Tower/UI/Input.cs @@ -61,6 +61,8 @@ namespace Tower.UI private static string ReadString(string prompt) { + Prompt(prompt); + var inputValues = ReadStrings(); if (inputValues.Length > 1) { diff --git a/90 Tower/csharp/Tower/UI/TowerDisplay.cs b/90 Tower/csharp/Tower/UI/TowerDisplay.cs index f8a56261..2493201f 100644 --- a/90 Tower/csharp/Tower/UI/TowerDisplay.cs +++ b/90 Tower/csharp/Tower/UI/TowerDisplay.cs @@ -19,15 +19,15 @@ namespace Tower.UI foreach (var row in _towers) { - AddTower(row.Item1); - AddTower(row.Item2); - AddTower(row.Item3); + AppendTower(row.Item1); + AppendTower(row.Item2); + AppendTower(row.Item3); builder.AppendLine(); } return builder.ToString(); - void AddTower(int size) + void AppendTower(int size) { var padding = 10 - size / 2; builder.Append(' ', padding).Append('*', Math.Max(1, size)).Append(' ', padding); From 271c72b2353e541e1b15fbcb24a8f89fbf3e8ae1 Mon Sep 17 00:00:00 2001 From: Yejin Song <67140032+jinyesong@users.noreply.github.com> Date: Sun, 28 Nov 2021 09:53:52 +0900 Subject: [PATCH 437/749] update main function --- 28_Combat/python/combat.py | 105 ++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/28_Combat/python/combat.py b/28_Combat/python/combat.py index bc1e78b5..3d0f120e 100644 --- a/28_Combat/python/combat.py +++ b/28_Combat/python/combat.py @@ -1,3 +1,106 @@ +MAX_UNITS = 72000 +planeCrashWin = False +usrArmy = 0 +usrNavy = 0 +usrAir = 0 +cpuArmy = 30000 +cpuNavy = 20000 +cpuAir = 22000 + + +def showIntro(): + global MAX_UNITS + + print(" " * 32 + "COMBAT") + print(" " * 14 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print("\n\n") + print("I AM AT WAR WITH YOU.") + print("WE HAVE " + str(MAX_UNITS) + " SOLDIERS APIECE.") + + +def getForces(): + global usrArmy, usrNavy, usrAir + + while True: + print("DISTRIBUTE YOUR FORCES.") + print(" ME YOU") + print("ARMY " + str(cpuArmy) + " ? ", end="") + usrArmy = int(input()) + print("NAVY " + str(cpuNavy) + " ? ", end="") + usrNavy = int(input()) + print("A. F. " + str(cpuAir) + " ? ", end="") + usrAir = int(input()) + if not ((usrArmy + usrNavy + usrAir) > MAX_UNITS): + break + + +def attackFirst(): + global usrArmy, usrNavy, usrAir + global cpuArmy, cpuNavy, cpuAir + + numUnits = 0 + unitType = 0 + + while True: + print("YOU ATTACK FIRST. TYPE (1) FOR ARMY; (2) FOR NAVY;") + print("AND (3) FOR AIR FORCE.") + print("?", end=' ') + unitType = int(input()) + if not (unitType < 1 or unitType > 3): + break + + while True: + print("HOW MANY MEN") + print("?", end=' ') + numUnits = int(input()) + if not ((numUnits < 0) or ((unitType == 1) and (numUnits > usrArmy)) or ( + (unitType == 2) and (numUnits > usrNavy)) or ((unitType == 3) and (numUnits > usrAir))): + break + + if unitType == 1: + if numUnits < (usrArmy / 3): + print("YOU LOST " + str(numUnits) + " MEN FROM YOUR ARMY.") + usrArmy = usrArmy - numUnits + elif numUnits < (2 * usrArmy / 3): + print("YOU LOST " + str(int(numUnits / 3)) + " MEN, BUT I LOST " + str(int(2 * cpuArmy / 3))) + usrArmy = int(usrArmy - (numUnits / 3)) + cpuArmy = 0 + else: + print("YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO") + print("OF YOUR AIR FORCE BASES AND 3 ARMY BASES.") + usrArmy = int(usrArmy / 3) + usrAir = int(usrAir / 3) + cpuNavy = int(2 * cpuNavy / 3) + elif unitType == 2: + if numUnits < cpuNavy / 3: + print("YOUR ATTACK WAS STOPPED!") + usrNavy = usrNavy - numUnits + elif numUnits < 2 * cpuNavy / 3: + print("YOU DESTROYED " + str(int(2 * cpuNavy / 3)) + " OF MY ARMY.") + cpuNavy = int(cpuNavy / 3) + else: + print("YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO") + print("OF YOUR AIR FORCE BASES AND 3 ARMY BASES.") + usrArmy = int(usrArmy / 3) + usrAir = int(usrAir / 3) + cpuNavy = int(2 * cpuNavy / 3) + elif unitType == 3: + if numUnits < usrAir / 3: + print("YOUR ATTACK WAS WIPED OUT.") + usrAir = usrAir - numUnits + elif numUnits < 2 * usrAir / 3: + print("WE HAD A DOGFIGHT. YOU WON - AND FINISHED YOUR MISSION.") + cpuArmy = int(2 * cpuArmy / 3) + cpuNavy = int(cpuNavy / 3) + cpuAir = int(cpuAir / 3) + else: + print("YOU WIPED OUT ONE OF MY ARMY PATROLS, BUT I DESTROYED") + print("TWO NAVY BASES AND BOMBED THREE ARMY BASES.") + usrArmy = int(usrArmy / 4) + usrNavy = int(usrNavy / 3) + cpuArmy = int(2 * cpuArmy / 3) + + def attackSecond(): global usrArmy, usrNavy, usrAir, cpuArmy, cpuNavy, cpuAir global planeCrashWin @@ -71,7 +174,7 @@ def attackSecond(): print("THE TREATY OF PARIS CONCLUDED THAT WE TAKE OUR") print("RESPECTIVE COUNTRIES AND LIVE IN PEACE.") - + def main(): showIntro() getForces() From 40becf6e66b127c0f0c54abce0cab7b59d6ade27 Mon Sep 17 00:00:00 2001 From: Chris Reuter Date: Mon, 29 Nov 2021 13:37:56 -0500 Subject: [PATCH 438/749] Bug fix for Ruby version of Checkers We were using the result of Board.make_move!() to determine whether the current player could jump again. This worked by accident but was not part of the specified interface. I've changed the code to ignore the return value and instead query the move object itself. --- 23_Checkers/ruby/checkers.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/23_Checkers/ruby/checkers.rb b/23_Checkers/ruby/checkers.rb index cac0ab06..ec65e8d5 100644 --- a/23_Checkers/ruby/checkers.rb +++ b/23_Checkers/ruby/checkers.rb @@ -139,10 +139,10 @@ def my_turn(board, jumpStart = nil) # Do the move puts "My move: #{bestMove}" - canMoveAgain = board.make_move!(bestMove) + board.make_move!(bestMove) # Repeat (recursively) if we can make another jump - my_turn(board, bestMove.to) if canMoveAgain + my_turn(board, bestMove.to) if bestMove.jump? # No loss yet! return true @@ -182,8 +182,8 @@ def players_turn(board) return false if !from && !move return true if from && !move - canMoveAgain = board.make_move!(move) - return true unless canMoveAgain + board.make_move!(move) + return true unless move.jump? # If the player can jump again, repeat from the new position. from = move.to From 62e20eb135d14b7104d43dd4d57654ec25d62908 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Fri, 31 Dec 2021 22:45:39 -0800 Subject: [PATCH 439/749] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 241e2f74..8940299d 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,4 @@ Feel free to begin converting these classic games into the above list of modern, ### Have fun! -Thank you for taking part in this project to update a classic programming book -- one of the most influential programming books in computing history -- for 2021! +Thank you for taking part in this project to update a classic programming book -- one of the most influential programming books in computing history -- for 2022 and beyond! From f886f9b7ae6967b8839e29fde4944f5e369fe3a4 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Fri, 31 Dec 2021 22:46:16 -0800 Subject: [PATCH 440/749] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8940299d..d481611c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ ### What are we doing? -We're updating the first million selling computer book, [BASIC Computer Games](https://en.wikipedia.org/wiki/BASIC_Computer_Games), for 2021! +We're updating the first million selling computer book, [BASIC Computer Games](https://en.wikipedia.org/wiki/BASIC_Computer_Games), for 2022 and beyond! [Read book](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf) ### Where can we discuss it? -Please see [the discussion here](https://discourse.codinghorror.com/t/updating-101-basic-computer-games-for-2021/7927) for a worklog and conversation around this project. +Please see [the discussion here](https://discourse.codinghorror.com/t/-/7927) for a worklog and conversation around this project. ### Project structure @@ -14,7 +14,7 @@ I have moved all [the original BASIC source code](http://www.vintage-basic.net/g > I've included all the games here for your tinkering pleasure. I've tested and tweaked each one of them to make sure they'll run with Vintage BASIC, though you may see a few oddities. That's part of the fun of playing with BASIC: it never works quite the same on two machines. The games will play better if you keep CAPS LOCK on, as they were designed to be used with capital-letter input. -Each project has subfolders corresponding to the languages we'd like to see the games ported to. This is based on the [February 2021 TIOBE index of top languages](https://www.tiobe.com/tiobe-index/) that are _memory safe_ and _general purpose scripting language_ per [this post](https://discourse.codinghorror.com/t/updating-101-basic-computer-games-for-2021/7927/34): +Each project has subfolders corresponding to the languages we'd like to see the games ported to. This is based on the [February 2021 TIOBE index of top languages](https://www.tiobe.com/tiobe-index/) that are _memory safe_ and _general purpose scripting language_ per [this post](https://discourse.codinghorror.com/t/-/7927/34): - Java - Python From 7318b0b5d5185f61c7614e860dad7229c5cf0603 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 11:12:12 +0100 Subject: [PATCH 441/749] Added header --- 20_Buzzword/csharp/Buzzword.csproj | 8 ++++++++ 20_Buzzword/csharp/Buzzword.sln | 25 +++++++++++++++++++++++++ 20_Buzzword/csharp/Program.cs | 20 ++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 20_Buzzword/csharp/Buzzword.csproj create mode 100644 20_Buzzword/csharp/Buzzword.sln create mode 100644 20_Buzzword/csharp/Program.cs diff --git a/20_Buzzword/csharp/Buzzword.csproj b/20_Buzzword/csharp/Buzzword.csproj new file mode 100644 index 00000000..1d2d39a9 --- /dev/null +++ b/20_Buzzword/csharp/Buzzword.csproj @@ -0,0 +1,8 @@ + + + + Exe + net5.0 + + + diff --git a/20_Buzzword/csharp/Buzzword.sln b/20_Buzzword/csharp/Buzzword.sln new file mode 100644 index 00000000..ada2d937 --- /dev/null +++ b/20_Buzzword/csharp/Buzzword.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.810.15 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Buzzword", "Buzzword.csproj", "{E342DEB2-F009-47FD-85F6-E84965EAAB56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E342DEB2-F009-47FD-85F6-E84965EAAB56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E342DEB2-F009-47FD-85F6-E84965EAAB56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E342DEB2-F009-47FD-85F6-E84965EAAB56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E342DEB2-F009-47FD-85F6-E84965EAAB56}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {52F15A7F-671A-470D-91CE-F3B629B989B7} + EndGlobalSection +EndGlobal diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs new file mode 100644 index 00000000..5e5ea8ec --- /dev/null +++ b/20_Buzzword/csharp/Program.cs @@ -0,0 +1,20 @@ +using System; + +namespace Buzzword +{ + class Program + { + static void Header() + { + Console.WriteLine("Buzzword generator".PadLeft(26)); + Console.WriteLine("Creating Computing Morristown, New Jersey".PadLeft(15)); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + static void Main(string[] args) + { + Header(); + } + } +} From 2a6dc209c8efc96ae84e31f45f89abecf0b74313 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 11:17:05 +0100 Subject: [PATCH 442/749] Added Instructions --- 20_Buzzword/csharp/Program.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index 5e5ea8ec..f8c04586 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -12,9 +12,22 @@ namespace Buzzword Console.WriteLine(); Console.WriteLine(); } + + static void Instructions() + { + Console.WriteLine("This program prints highly acceptable phrases in\n" + + "'Educator-speak'that you can work into reports\n" + + "and speeches. Whenever a question mark is printed,\n" + + "type a 'Y' for another phrase or 'N' to quit."); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("Here's the first phrase:"); + } + static void Main(string[] args) { Header(); + Instructions(); } } } From ff67d7705ace820dc6336ce253548c0d44ae148c Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 11:59:28 +0100 Subject: [PATCH 443/749] Added GeneratePhrase --- 20_Buzzword/csharp/Program.cs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index f8c04586..1398d442 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -24,10 +24,41 @@ namespace Buzzword Console.WriteLine("Here's the first phrase:"); } + static string[] Phrases = new[] + { "ability", "basal", "behavioral", "child-centered", + "differentiated", "discovery", "flexible", "heterogenous", + "homogenous", "manipulative", "modular", "tavistock", + "individualized", "learning", "evaluative", "objective", + "cognitive", "enrichment", "scheduling", "humanistic", + "integrated", "non-graded", "training", "vertical age", + "motivational", "creative", "grouping", "modification", + "accountability", "process", "core curriculum", "algorithm", + "performance", "reinforcement", "open classroom", "resource", + "structure", "facility", "environment" }; + + static Random rnd = new Random(1); + + static string GeneratePhrase() + { + return $"{Phrases[(int)(13 * rnd.NextDouble() + 1) % Phrases.Length]} " + + $"{Phrases[(int)(13 * rnd.NextDouble() + 14) % Phrases.Length]} " + + $"{Phrases[(int)(13 * rnd.NextDouble() + 27) % Phrases.Length]}."; + } + static void Main(string[] args) { Header(); Instructions(); + + while (true) + { + Console.WriteLine(); + Console.WriteLine(GeneratePhrase()); + var answer = Console.ReadKey(); + + if (answer.Key == ConsoleKey.N) + break; + } } } } From 62645703d1d15ec40b9b6ebfffd31091165ee360 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 12:05:19 +0100 Subject: [PATCH 444/749] Starting sentence from capital letter --- 20_Buzzword/csharp/Program.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index 1398d442..dcfdcd38 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -36,11 +36,19 @@ namespace Buzzword "performance", "reinforcement", "open classroom", "resource", "structure", "facility", "environment" }; + static string Capitalize(string input) + { + if (string.IsNullOrWhiteSpace(input)) + return string.Empty; + + return input.Substring(0, 1).ToUpper() + input[1..]; + } + static Random rnd = new Random(1); static string GeneratePhrase() { - return $"{Phrases[(int)(13 * rnd.NextDouble() + 1) % Phrases.Length]} " + return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble() + 1) % Phrases.Length])} " + $"{Phrases[(int)(13 * rnd.NextDouble() + 14) % Phrases.Length]} " + $"{Phrases[(int)(13 * rnd.NextDouble() + 27) % Phrases.Length]}."; } @@ -54,8 +62,8 @@ namespace Buzzword { Console.WriteLine(); Console.WriteLine(GeneratePhrase()); - var answer = Console.ReadKey(); + var answer = Console.ReadKey(); if (answer.Key == ConsoleKey.N) break; } From e9cc632c7b0b884783218d6950820c3b8efbe32f Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 12:15:13 +0100 Subject: [PATCH 445/749] Better keyboard, cosmetics --- 20_Buzzword/csharp/Program.cs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index dcfdcd38..3506cc5e 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -13,15 +13,17 @@ namespace Buzzword Console.WriteLine(); } + static string keys = "type a 'Y' for another phrase or 'N' to quit"; + static void Instructions() { Console.WriteLine("This program prints highly acceptable phrases in\n" + "'Educator-speak'that you can work into reports\n" + "and speeches. Whenever a question mark is printed,\n" - + "type a 'Y' for another phrase or 'N' to quit."); + + $"{keys}."); Console.WriteLine(); Console.WriteLine(); - Console.WriteLine("Here's the first phrase:"); + Console.Write("Here's the first phrase:"); } static string[] Phrases = new[] @@ -50,7 +52,21 @@ namespace Buzzword { return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble() + 1) % Phrases.Length])} " + $"{Phrases[(int)(13 * rnd.NextDouble() + 14) % Phrases.Length]} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 27) % Phrases.Length]}."; + + $"{Phrases[(int)(13 * rnd.NextDouble() + 27) % Phrases.Length]}"; + } + + static bool Decision() + { + while (true) + { + var answer = Console.ReadKey(); + if (answer.Key == ConsoleKey.Y) + return true; + else if (answer.Key == ConsoleKey.N) + return false; + else + Console.WriteLine($"\n{keys}"); + } } static void Main(string[] args) @@ -62,11 +78,13 @@ namespace Buzzword { Console.WriteLine(); Console.WriteLine(GeneratePhrase()); + Console.WriteLine(); - var answer = Console.ReadKey(); - if (answer.Key == ConsoleKey.N) + if (!Decision()) break; } + + Console.WriteLine("\nCome back when you need help with another report!"); } } } From a1fd52ebfd5711575c445086b7c066cc889ee550 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 13:16:01 +0100 Subject: [PATCH 446/749] Modified seed, added some comments --- 20_Buzzword/csharp/Program.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index 3506cc5e..ec07d18d 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -46,13 +46,17 @@ namespace Buzzword return input.Substring(0, 1).ToUpper() + input[1..]; } - static Random rnd = new Random(1); + // Seed has been calculated to get the same effect as in original, + // at least in first phrase + static readonly Random rnd = new Random(1486); static string GeneratePhrase() { - return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble() + 1) % Phrases.Length])} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 14) % Phrases.Length]} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 27) % Phrases.Length]}"; + // Indexing from 0, so had to decrease generated numbers + // modulo Phrases.Length added to not get out of bond + return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble()) % Phrases.Length])} " + + $"{Phrases[(int)(13 * rnd.NextDouble() + 13) % Phrases.Length]} " + + $"{Phrases[(int)(13 * rnd.NextDouble() + 26) % Phrases.Length]}"; } static bool Decision() From cf659356152ef6c3111734844dbaf93962b46aa6 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 13:17:35 +0100 Subject: [PATCH 447/749] After modifying indexes modulo isn't needed, it appears --- 20_Buzzword/csharp/Program.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index ec07d18d..d4311141 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -53,10 +53,9 @@ namespace Buzzword static string GeneratePhrase() { // Indexing from 0, so had to decrease generated numbers - // modulo Phrases.Length added to not get out of bond - return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble()) % Phrases.Length])} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 13) % Phrases.Length]} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 26) % Phrases.Length]}"; + return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble())])} " + + $"{Phrases[(int)(13 * rnd.NextDouble() + 13)]} " + + $"{Phrases[(int)(13 * rnd.NextDouble() + 26)]}"; } static bool Decision() From aceddf559e6b8dad41528c2408a73e76b06d19c8 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 13:28:38 +0100 Subject: [PATCH 448/749] Added more comments, some cosmetic changes --- 20_Buzzword/csharp/Program.cs | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index d4311141..db72de7a 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -4,6 +4,9 @@ namespace Buzzword { class Program { + /// + /// Displays header. + /// static void Header() { Console.WriteLine("Buzzword generator".PadLeft(26)); @@ -13,12 +16,16 @@ namespace Buzzword Console.WriteLine(); } + // Information for the user about possible key input. static string keys = "type a 'Y' for another phrase or 'N' to quit"; + /// + /// Displays instructions. + /// static void Instructions() { Console.WriteLine("This program prints highly acceptable phrases in\n" - + "'Educator-speak'that you can work into reports\n" + + "'educator-speak' that you can work into reports\n" + "and speeches. Whenever a question mark is printed,\n" + $"{keys}."); Console.WriteLine(); @@ -26,7 +33,7 @@ namespace Buzzword Console.Write("Here's the first phrase:"); } - static string[] Phrases = new[] + static string[] Words = new[] { "ability", "basal", "behavioral", "child-centered", "differentiated", "discovery", "flexible", "heterogenous", "homogenous", "manipulative", "modular", "tavistock", @@ -38,6 +45,11 @@ namespace Buzzword "performance", "reinforcement", "open classroom", "resource", "structure", "facility", "environment" }; + /// + /// Capitalizes first letter of given string. + /// + /// + /// string static string Capitalize(string input) { if (string.IsNullOrWhiteSpace(input)) @@ -50,18 +62,29 @@ namespace Buzzword // at least in first phrase static readonly Random rnd = new Random(1486); + /// + /// Generates random phrase from words available in Words array. + /// + /// String representing random phrase where first letter is capitalized. static string GeneratePhrase() { // Indexing from 0, so had to decrease generated numbers - return $"{Capitalize(Phrases[(int)(13 * rnd.NextDouble())])} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 13)]} " - + $"{Phrases[(int)(13 * rnd.NextDouble() + 26)]}"; + // modulo Phrases.Length added to not get out of bond + return $"{Capitalize(Words[(int)(13 * rnd.NextDouble())])} " + + $"{Words[(int)(13 * rnd.NextDouble() + 13)]} " + + $"{Words[(int)(13 * rnd.NextDouble() + 26)]}"; } + /// + /// Handles user input. On wrong input it displays information about + /// valid keys in infinite loop. + /// + /// True if user pressed 'Y', false if 'N'. static bool Decision() { while (true) { + Console.Write("?"); var answer = Console.ReadKey(); if (answer.Key == ConsoleKey.Y) return true; From e23e9f6a9a5c5900cec099e1fdb2e1dc0c4315b2 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 13:39:03 +0100 Subject: [PATCH 449/749] Spelling --- 20_Buzzword/csharp/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index db72de7a..d940e534 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -36,7 +36,7 @@ namespace Buzzword static string[] Words = new[] { "ability", "basal", "behavioral", "child-centered", "differentiated", "discovery", "flexible", "heterogenous", - "homogenous", "manipulative", "modular", "tavistock", + "homogeneous", "manipulative", "modular", "tavistock", "individualized", "learning", "evaluative", "objective", "cognitive", "enrichment", "scheduling", "humanistic", "integrated", "non-graded", "training", "vertical age", From 5439ece5317c9ca33a0e2b65c3a4d51458fc6d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torben=20M=C3=B6ller?= Date: Sat, 1 Jan 2022 13:57:11 +0100 Subject: [PATCH 450/749] feat: Implement 78 Sine_Wave in Java --- 78_Sine_Wave/java/src/SineWave.java | 33 ++++++++++++----------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/78_Sine_Wave/java/src/SineWave.java b/78_Sine_Wave/java/src/SineWave.java index f3b3c7eb..0908791e 100644 --- a/78_Sine_Wave/java/src/SineWave.java +++ b/78_Sine_Wave/java/src/SineWave.java @@ -1,5 +1,3 @@ -import java.util.Arrays; - /** * Sine Wave * @@ -12,24 +10,19 @@ import java.util.Arrays; public class SineWave { public static void main(String[] args) { - - System.out.println("SINE WAVE"); - System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - System.out.println(); - - int toggle = 0; - for(double t = 0; t<40; t += .25) { - int a = 26 + (int) (25 * Math.sin(t)); - char[] repeat = new char[a]; - Arrays.fill(repeat,' '); - System.out.print(new String(repeat)); - if (toggle == 1) { - System.out.println("COMPUTING"); - toggle = 0; - } else { - System.out.println("CREATIVE"); - toggle = 1; - } + System.out.println(""" + SINE WAVE + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + """); + var isCreative = true; + for(var t = 0d; t<40; t += .25) { + //Indent output + var indentations = 26 + (int) (25 * Math.sin(t)); + System.out.print(" ".repeat(indentations)); + //Change output every iteration + var word = isCreative ? "CREATIVE" : "COMPUTING"; + System.out.println(word); + isCreative = !isCreative ; } } } From b1242d081cae763f2863d1e66eea549770024ca3 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 14:14:31 +0100 Subject: [PATCH 451/749] Better? --- 20_Buzzword/csharp/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index d940e534..b2dfa680 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -55,7 +55,7 @@ namespace Buzzword if (string.IsNullOrWhiteSpace(input)) return string.Empty; - return input.Substring(0, 1).ToUpper() + input[1..]; + return char.ToUpper(input[0]) + input[1..]; } // Seed has been calculated to get the same effect as in original, From 8cf778cb8706b835f7b70a364da2302adfe8bc4d Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 14:18:25 +0100 Subject: [PATCH 452/749] Comment changed --- 20_Buzzword/csharp/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index b2dfa680..ca1ed750 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -69,7 +69,7 @@ namespace Buzzword static string GeneratePhrase() { // Indexing from 0, so had to decrease generated numbers - // modulo Phrases.Length added to not get out of bond + // NextDouble used to reflect original return $"{Capitalize(Words[(int)(13 * rnd.NextDouble())])} " + $"{Words[(int)(13 * rnd.NextDouble() + 13)]} " + $"{Words[(int)(13 * rnd.NextDouble() + 26)]}"; From 520efaa20a44a3415a71a8dfb4c97e1c4a6cf0d3 Mon Sep 17 00:00:00 2001 From: Piotr Czajkowski Date: Sat, 1 Jan 2022 17:12:13 +0100 Subject: [PATCH 453/749] Maybe staying too close to original wasn't so good --- 20_Buzzword/csharp/Program.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/20_Buzzword/csharp/Program.cs b/20_Buzzword/csharp/Program.cs index ca1ed750..e9970d82 100644 --- a/20_Buzzword/csharp/Program.cs +++ b/20_Buzzword/csharp/Program.cs @@ -69,10 +69,9 @@ namespace Buzzword static string GeneratePhrase() { // Indexing from 0, so had to decrease generated numbers - // NextDouble used to reflect original - return $"{Capitalize(Words[(int)(13 * rnd.NextDouble())])} " - + $"{Words[(int)(13 * rnd.NextDouble() + 13)]} " - + $"{Words[(int)(13 * rnd.NextDouble() + 26)]}"; + return $"{Capitalize(Words[rnd.Next(13)])} " + + $"{Words[rnd.Next(13, 26)]} " + + $"{Words[rnd.Next(26, 39)]}"; } /// From f0f5c38c024269fa11008b091887780f6d33c417 Mon Sep 17 00:00:00 2001 From: Scott Halgrim Date: Sat, 1 Jan 2022 10:53:17 -0800 Subject: [PATCH 454/749] fix typo --- 01_Acey_Ducey/python/acey_ducey.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01_Acey_Ducey/python/acey_ducey.py b/01_Acey_Ducey/python/acey_ducey.py index 6832c7e0..8461dad1 100644 --- a/01_Acey_Ducey/python/acey_ducey.py +++ b/01_Acey_Ducey/python/acey_ducey.py @@ -78,7 +78,7 @@ if __name__ == "__main__": """ Acey-Ducey is played in the following manner The dealer (computer) deals two cards face up -You have an option to be or not bet depending +You have an option to bet or not bet depending on whether or not you feel the card will have a value between the first two. If you do not want to bet, input a 0 From 32e6b885ce3d8e6c05f3722dba8633a0e59c3af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torben=20M=C3=B6ller?= Date: Sat, 1 Jan 2022 20:17:09 +0100 Subject: [PATCH 455/749] feat: Implement 93 23_Matches in Java --- 93_23_Matches/java/CoinSide.java | 4 + 93_23_Matches/java/Messages.java | 70 ++++++ 93_23_Matches/java/TwentyThreeMatches.java | 218 ++++++------------ .../java/TwentyThreeMatchesGame.java | 24 ++ 4 files changed, 165 insertions(+), 151 deletions(-) create mode 100644 93_23_Matches/java/CoinSide.java create mode 100644 93_23_Matches/java/Messages.java create mode 100644 93_23_Matches/java/TwentyThreeMatchesGame.java diff --git a/93_23_Matches/java/CoinSide.java b/93_23_Matches/java/CoinSide.java new file mode 100644 index 00000000..7126e9b4 --- /dev/null +++ b/93_23_Matches/java/CoinSide.java @@ -0,0 +1,4 @@ +public enum CoinSide { + HEADS, + TAILS +} diff --git a/93_23_Matches/java/Messages.java b/93_23_Matches/java/Messages.java new file mode 100644 index 00000000..c0e52b7c --- /dev/null +++ b/93_23_Matches/java/Messages.java @@ -0,0 +1,70 @@ +public class Messages { + + // This is a utility class and contains only static members. + // Utility classes are not meant to be instantiated. + private Messages() { + throw new IllegalStateException("Utility class"); + } + + public static final String INTRO = """ + 23 MATCHES + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + + THIS IS A GAME CALLED '23 MATCHES'. + + WHEN IT IS YOUR TURN, YOU MAY TAKE ONE, TWO, OR THREE + MATCHES. THE OBJECT OF THE GAME IS NOT TO HAVE TO TAKE + THE LAST MATCH. + + LET'S FLIP A COIN TO SEE WHO GOES FIRST. + IF IT COMES UP HEADS, I WILL WIN THE TOSS. + """; + + public static final String HEADS = """ + HEADS! I WIN! HA! HA! + PREPARE TO LOSE, MEATBALL-NOSE!! + + I TAKE 2 MATCHES + """; + + public static final String TAILS = """ + TAILS! YOU GO FIRST. + """; + + public static final String MATCHES_LEFT = """ + THE NUMBER OF MATCHES IS NOW %d + + YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES. + """; + + public static final String REMOVE_MATCHES_QUESTION = "HOW MANY DO YOU WISH TO REMOVE? "; + + public static final String REMAINING_MATCHES = """ + THERE ARE NOW %d MATCHES REMAINING. + """; + + public static final String INVALID = """ + VERY FUNNY! DUMMY! + DO YOU WANT TO PLAY OR GOOF AROUND? + NOW, HOW MANY MATCHES DO YOU WANT? + """; + + public static final String WIN = """ + YOU WON, FLOPPY EARS ! + THINK YOU'RE PRETTY SMART ! + LETS PLAY AGAIN AND I'LL BLOW YOUR SHOES OFF !! + """; + + public static final String CPU_TURN = """ + MY TURN ! I REMOVE %d MATCHES. + """; + + public static final String LOSE = """ + YOU POOR BOOB! YOU TOOK THE LAST MATCH! I GOTCHA!! + HA ! HA ! I BEAT YOU !!! + + GOOD BYE LOSER! + """; +} diff --git a/93_23_Matches/java/TwentyThreeMatches.java b/93_23_Matches/java/TwentyThreeMatches.java index 46b12793..f0c9836a 100644 --- a/93_23_Matches/java/TwentyThreeMatches.java +++ b/93_23_Matches/java/TwentyThreeMatches.java @@ -1,163 +1,79 @@ +import java.util.Random; import java.util.Scanner; -import java.lang.Math; -/** - * Game of 23 Matches - *

- * Based on the BASIC game of 23 Matches here - * https://github.com/coding-horror/basic-computer-games/blob/main/93%2023%20Matches/23matches.bas - *

- * 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. - * - * Converted from BASIC to Java by Darren Cardenas. - */ - -public class TwentyThreeMatches { +public class TwentyThreeMatches { - private static final int MATCH_COUNT_START = 23; + private static final int MATCH_COUNT_START = 23; + private static final Random RAND = new Random(); + private final Scanner scan = new Scanner(System.in); - private static final int HEADS = 1; - - private final Scanner scan; // For user input - - public TwentyThreeMatches() { - - scan = new Scanner(System.in); - - } // End of constructor TwentyThreeMatches + public void startGame() { + //Initialize values + int cpuRemoves = 0; + int matchesLeft = MATCH_COUNT_START; + int playerRemoves = 0; - public void play() { - - showIntro(); - startGame(); - - } // End of method play - - private static void showIntro() { - - System.out.println(" ".repeat(30) + "23 MATCHES"); - System.out.println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - System.out.println("\n\n"); + //Flip coin and decide who goes first. + CoinSide coinSide = flipCoin(); + if (coinSide == CoinSide.HEADS) { + System.out.println(Messages.HEADS); + matchesLeft -= 2; + } else { + System.out.println(Messages.TAILS); + } - System.out.println(" THIS IS A GAME CALLED '23 MATCHES'."); - System.out.println(""); - System.out.println("WHEN IT IS YOUR TURN, YOU MAY TAKE ONE, TWO, OR THREE"); - System.out.println("MATCHES. THE OBJECT OF THE GAME IS NOT TO HAVE TO TAKE"); - System.out.println("THE LAST MATCH."); - System.out.println(""); - System.out.println("LET'S FLIP A COIN TO SEE WHO GOES FIRST."); - System.out.println("IF IT COMES UP HEADS, I WILL WIN THE TOSS."); - System.out.println(""); - - } // End of method showIntro - - private void startGame() { + // Game loop + while (true) { + //Show matches left if CPU went first or Player already removed matches + if (coinSide == CoinSide.HEADS) { + System.out.format(Messages.MATCHES_LEFT, matchesLeft); + } + coinSide = CoinSide.HEADS; - int coinSide = (int) (3 * Math.random()); - int cpuRemoves = 0; - int matchesLeft = MATCH_COUNT_START; - int playerRemoves = 0; - - if (coinSide == HEADS) { - - System.out.println("HEADS! I WIN! HA! HA!"); - System.out.println("PREPARE TO LOSE, MEATBALL-NOSE!!"); - System.out.println(""); - System.out.println("I TAKE 2 MATCHES"); - - matchesLeft -= 2; - - } else { - - System.out.println("TAILS! YOU GO FIRST. "); - System.out.println(""); - + // Player removes matches + System.out.println(Messages.REMOVE_MATCHES_QUESTION); + playerRemoves = turnOfPlayer(); + matchesLeft -= playerRemoves; + System.out.format(Messages.REMAINING_MATCHES, matchesLeft); + + // If 1 match is left, the CPU has to take it. You win! + if (matchesLeft <= 1) { + System.out.println(Messages.WIN); + return; + } + + // CPU removes matches + // At least two matches are left, because win condition above was not triggered. + if (matchesLeft <= 4) { + cpuRemoves = matchesLeft - 1; + } else { + cpuRemoves = 4 - playerRemoves; + } + System.out.format(Messages.CPU_TURN, cpuRemoves); + matchesLeft -= cpuRemoves; + + // If 1 match is left, the Player has to take it. You lose! + if (matchesLeft <= 1) { + System.out.println(Messages.LOSE); + return; + } + } } - // Begin outer while loop - while (true) { - - if (coinSide == HEADS) { - - System.out.println("THE NUMBER OF MATCHES IS NOW " + matchesLeft); - System.out.println(""); - System.out.println("YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES."); - - } - - coinSide = HEADS; + private CoinSide flipCoin() { + return RAND.nextBoolean() ? CoinSide.HEADS : CoinSide.TAILS; + } - System.out.print("HOW MANY DO YOU WISH TO REMOVE? "); - - // Begin match removal while loop - while (true) { - - playerRemoves = scan.nextInt(); - - // Handle invalid entries - if ((playerRemoves > 3) || (playerRemoves <= 0)) { - - System.out.println("VERY FUNNY! DUMMY!"); - System.out.println("DO YOU WANT TO PLAY OR GOOF AROUND?"); - System.out.print("NOW, HOW MANY MATCHES DO YOU WANT? "); - continue; - + private int turnOfPlayer() { + while (true) { + int playerRemoves = scan.nextInt(); + // Handle invalid entries + if ((playerRemoves > 3) || (playerRemoves <= 0)) { + System.out.println(Messages.INVALID); + continue; + } + return playerRemoves; } - - break; - - } // End match removal while loop - - matchesLeft -= playerRemoves; - - System.out.println("THERE ARE NOW " + matchesLeft + " MATCHES REMAINING."); - - // Win condition - if (matchesLeft <= 1) { - - // Win condition - System.out.println("YOU WON, FLOPPY EARS !"); - System.out.println("THINK YOU'RE PRETTY SMART !"); - System.out.println("LETS PLAY AGAIN AND I'LL BLOW YOUR SHOES OFF !!"); - System.out.println(""); - return; - - } else if ((matchesLeft >= 2) && (matchesLeft <= 4)) { - - cpuRemoves = matchesLeft - 1; - - } else { - - cpuRemoves = 4 - playerRemoves; - - } - - System.out.println("MY TURN ! I REMOVE " + cpuRemoves + " MATCHES"); - - matchesLeft -= cpuRemoves; + } - // Lose condition - if (matchesLeft <= 1) { - - System.out.println(""); - System.out.println("YOU POOR BOOB! YOU TOOK THE LAST MATCH! I GOTCHA!!"); - System.out.println("HA ! HA ! I BEAT YOU !!!"); - System.out.println(""); - System.out.println("GOOD BYE LOSER!"); - return; - - } - - } // End outer while loop - - } // End of method startGame - - public static void main(String[] args) { - - TwentyThreeMatches game = new TwentyThreeMatches(); - game.play(); - - } // End of method main - -} // End of class TwentyThreeMatches +} diff --git a/93_23_Matches/java/TwentyThreeMatchesGame.java b/93_23_Matches/java/TwentyThreeMatchesGame.java new file mode 100644 index 00000000..01735a91 --- /dev/null +++ b/93_23_Matches/java/TwentyThreeMatchesGame.java @@ -0,0 +1,24 @@ +/** + * Game of 23 Matches + *

+ * Based on the BASIC game of 23 Matches here + * https://github.com/coding-horror/basic-computer-games/blob/main/93%2023%20Matches/23matches.bas + *

+ * 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. + *

+ * Converted from BASIC to Java by Darren Cardenas. + */ +public class TwentyThreeMatchesGame { + + public static void main(String[] args) { + showIntro(); + TwentyThreeMatches game = new TwentyThreeMatches(); + game.startGame(); + } + + private static void showIntro() { + System.out.println(Messages.INTRO); + } + +} From 14b66215e446025740ca65fda3f7ab03013357ff Mon Sep 17 00:00:00 2001 From: Moritz Hamann Date: Sat, 1 Jan 2022 19:20:35 +0000 Subject: [PATCH 456/749] Python solution for 50: Horserace Avoided any dictionary types, since those are not available in the original BASIC version. This makes it slightly less idiomatic. Tried my best to keep it as close to the original as possible. Also horses are enumerated from 0, rather than from 1 as in the original implementation (if needed this can easily be adjusted). --- 50_Horserace/python/horserace.py | 278 +++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 50_Horserace/python/horserace.py diff --git a/50_Horserace/python/horserace.py b/50_Horserace/python/horserace.py new file mode 100644 index 00000000..cf7c266e --- /dev/null +++ b/50_Horserace/python/horserace.py @@ -0,0 +1,278 @@ +import random +import math +import time + +def basic_print(*zones, **kwargs): + """Simulates the PRINT command from BASIC to some degree. + Supports `printing zones` if given multiple arguments.""" + + line = "" + if len(zones) == 1: + line = str(zones[0]) + else: + line = "".join(["{:<14}".format(str(zone)) for zone in zones]) + identation = kwargs.get("indent", 0) + end = kwargs.get("end", "\n") + print(" " * identation + line, end=end) + + +def basic_input(prompt, type_conversion=None): + """BASIC INPUT command with optional type conversion""" + + while True: + try: + inp = input(f"{prompt}? ") + if type_conversion is not None: + inp = type_conversion(inp) + break + except ValueError: + basic_print("INVALID INPUT!") + return inp + + +# horse names do not change over the program, therefore making it a global. +# throught the game, the ordering of the horses is used to indentify them +HORSE_NAMES = [ + "JOE MAW", + "L.B.J.", + "MR.WASHBURN", + "MISS KAREN", + "JOLLY", + "HORSE", + "JELLY DO NOT", + "MIDNIGHT" +] + + +def introduction(): + """Print the introduction, and optional the instructions""" + + basic_print("HORSERACE", indent=31) + basic_print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", indent=15) + basic_print("\n\n") + basic_print("WELCOME TO SOUTH PORTLAND HIGH RACETRACK") + basic_print(" ...OWNED BY LAURIE CHEVALIER") + y_n = basic_input("DO YOU WANT DIRECTIONS") + + # if no instructions needed, return + if y_n.upper() == "NO": + return + + basic_print("UP TO 10 MAY PLAY. A TABLE OF ODDS WILL BE PRINTED. YOU") + basic_print("MAY BET ANY + AMOUNT UNDER 100000 ON ONE HORSE.") + basic_print("DURING THE RACE, A HORSE WILL BE SHOWN BY ITS") + basic_print("NUMBER. THE HORSES RACE DOWN THE PAPER!") + basic_print("") + + +def setup_players(): + """Gather the number of players and their names""" + + # ensure we get an integer value from the user + number_of_players = basic_input("HOW MANY WANT TO BET", int) + + # for each user query their name and return the list of names + player_names = [] + basic_print("WHEN ? APPEARS,TYPE NAME") + for _ in range(number_of_players): + player_names.append(basic_input("")) + return player_names + + +def setup_horses(): + """Generates random odds for each horse. Returns a list of + odds, indexed by the order of the global HORSE_NAMES.""" + + odds = [random.randrange(1, 10) for _ in HORSE_NAMES] + total = sum(odds) + + # rounding odds to two decimals for nicer output, + # this is not in the origin implementation + return [round(total/odd, 2) for odd in odds] + + +def print_horse_odds(odds): + """Print the odds for each horse""" + + basic_print("") + for i in range(len(HORSE_NAMES)): + basic_print(HORSE_NAMES[i], i, f"{odds[i]}:1") + basic_print("") + + +def get_bets(player_names): + """For each player, get the number of the horse to bet on, + as well as the amount of money to bet""" + + basic_print("--------------------------------------------------") + basic_print("PLACE YOUR BETS...HORSE # THEN AMOUNT") + + bets = [] + for name in player_names: + horse = basic_input(name, int) + amount = None + while amount is None: + amount = basic_input("", float) + if amount < 1 or amount >= 100000: + basic_print(" YOU CAN'T DO THAT!") + amount = None + bets.append((horse, amount)) + + basic_print("") + + return bets + + +def get_distance(odd): + """Advances a horse during one step of the racing simulation. + The amount travelled is random, but scaled by the odds of the horse""" + + d = random.randrange(1,100) + s = math.ceil(odd) + if d < 10: + return 1 + elif d < s + 17: + return 2 + elif d < s + 37: + return 3 + elif d < s + 57: + return 4 + elif d < s + 77: + return 5 + elif d < s + 77: + return 5 + elif d < s + 92: + return 6 + else: + return 7 + + +def print_race_state(total_distance, race_pos): + """Outputs the current state/stop of the race. + Each horse is placed according to the distance they have travelled. In + case some horses travelled the same distance, their numbers are printed + on the same name""" + + # we dont want to modify the `race_pos` list, since we need + # it later. Therefore we generating an interator from the list + race_pos_iter = iter(race_pos) + + # race_pos is stored by last to first horse in the race. + # we get the next horse we need to print out + next_pos = next(race_pos_iter) + + # start line + basic_print("XXXXSTARTXXXX") + + # print all 28 lines/unit of the race course + for l in range(28): + + # ensure we still have a horse to print and if so, check if the + # next horse to print is not the current line + # needs iteration, since multiple horses can share the same line + while next_pos is not None and l == total_distance[next_pos]: + basic_print(f"{next_pos} ", end="") + next_pos = next(race_pos_iter, None) + else: + # if no horses are left to print for this line, print a new line + basic_print("") + + # finish line + basic_print("XXXXFINISHXXXX") + + +def simulate_race(odds): + num_horses = len(HORSE_NAMES) + + # in spirit of the original implementation, using two arrays to + # track the total distance travelled, and create an index from + # race position -> horse index + total_distance = [0] * num_horses + + # race_pos maps from the position in the race, to the index of the horse + # it will later be sorted from last to first horse, based on the + # distance travelled by each horse. + # e.g. race_pos[0] => last horse + # race_pos[-1] => winning horse + race_pos = list(range(num_horses)) + + basic_print("\n1 2 3 4 5 6 7 8") + + while True: + + # advance each horse by a random amount + for i in range(num_horses): + total_distance[i] += get_distance(odds[i]) + + # bubble sort race_pos based on total distance travelled + # in the original implementation, race_pos is reset for each + # simulation step, so we keep this behaviour here + race_pos = list(range(num_horses)) + for l in range(num_horses): + for i in range(num_horses-1-l): + if total_distance[race_pos[i]] < total_distance[race_pos[i+1]]: + continue + race_pos[i], race_pos[i+1] = race_pos[i+1], race_pos[i] + + # print current state of the race + print_race_state(total_distance, race_pos) + + # goal line is defined as 28 units from start + # check if the winning horse is already over the finish line + if total_distance[race_pos[-1]] >= 28: + return race_pos + + # this was not in the original BASIC implementation, but it makes the + # race visualization a nice animation (if the terminal size is set to 31 rows) + time.sleep(1) + + +def print_race_results(race_positions, odds, bets, player_names): + """Print the race results, as well as the winnings of each player""" + + # print the race positions first + basic_print("THE RACE RESULTS ARE:") + position = 1 + for horse_idx in reversed(race_positions): + line = f"{position} PLACE HORSE NO. {horse_idx} AT {odds[horse_idx]}:1" + basic_print("") + basic_print(line) + position += 1 + + # followed by the amount the players won + winning_horse_idx = race_positions[-1] + for idx, name in enumerate(player_names): + (horse, amount) = bets[idx] + if horse == winning_horse_idx: + basic_print("") + basic_print(f"{name} WINS ${amount * odds[winning_horse_idx]}") + + +def main_loop(player_names, horse_odds): + """Main game loop""" + + while True: + print_horse_odds(horse_odds) + bets = get_bets(player_names) + final_race_positions = simulate_race(horse_odds) + print_race_results(final_race_positions, horse_odds, bets, player_names) + + basic_print("DO YOU WANT TO BET ON THE NEXT RACE ?") + one_more = basic_input("YES OR NO") + if one_more.upper() != "YES": + break + + +def main(): + # introduction, player names and horse odds are only generated once + introduction() + player_names = setup_players() + horse_odds = setup_horses() + + # main loop of the game, the player can play multiple races, with the + # same odds + main_loop(player_names, horse_odds) + + +if __name__ == "__main__": + main() \ No newline at end of file From 88b964b9ae25b8fa604c0ad5ae55a19c1314e081 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Sat, 1 Jan 2022 16:03:26 -0500 Subject: [PATCH 457/749] Improve Acey Ducey JavaScript port Notable changes: * Use informative variable names instead of q, a, b, m, and c * Use a lookup table instead of chained ifs for face cards * Refactor I/O helpers into a separate file * Refactor random card logic into its own function * Support any case for "yes" input * Add a few comments to non-obvious parts of the game logic * Insert "HERE IS THE CARD WE DREW:" into the output since just printing the card was pretty confusing * Make indentation uniform * Make bracing style uniform * Use conventional JavaScript camelCasing * Use top-level await in a module instead of a main() function * Clean up the HTML shell page for modern best practices (including a mobile-friendly viewport) --- 01_Acey_Ducey/javascript/aceyducey.html | 12 +- 01_Acey_Ducey/javascript/aceyducey.js | 207 ++++++++++-------------- 01_Acey_Ducey/javascript/io.js | 29 ++++ 3 files changed, 120 insertions(+), 128 deletions(-) create mode 100644 01_Acey_Ducey/javascript/io.js diff --git a/01_Acey_Ducey/javascript/aceyducey.html b/01_Acey_Ducey/javascript/aceyducey.html index 991e3b5c..e526c3df 100644 --- a/01_Acey_Ducey/javascript/aceyducey.html +++ b/01_Acey_Ducey/javascript/aceyducey.html @@ -1,9 +1,7 @@ - - + + + ACEY DUCEY - - +


-
-
-
+
diff --git a/01_Acey_Ducey/javascript/aceyducey.js b/01_Acey_Ducey/javascript/aceyducey.js
index d0983443..6c31d77c 100644
--- a/01_Acey_Ducey/javascript/aceyducey.js
+++ b/01_Acey_Ducey/javascript/aceyducey.js
@@ -1,135 +1,100 @@
-// ACEY DUCEY
-//
-// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
-//
+import { readLine, print, spaces } from "./io.js";
 
-function print(str)
-{
-    document.getElementById("output").appendChild(document.createTextNode(str));
+const minFaceCard = 11;
+const faceCards = {
+  11: "JACK",
+  12: "QUEEN",
+  13: "KING",
+  14: "ACE"
+};
+
+function randomCard() {
+  return Math.floor(Math.random() * 13 + 2);
 }
 
-function input()
-{
-    var input_element;
-    var input_str;
-    
-    return new Promise(function (resolve) {
-                       input_element = document.createElement("INPUT");
-                       
-                       print("? ");
-                       input_element.setAttribute("type", "text");
-                       input_element.setAttribute("length", "50");
-                       document.getElementById("output").appendChild(input_element);
-                       input_element.focus();
-                       input_str = undefined;
-                       input_element.addEventListener("keydown", function (event) {
-                                                      if (event.keyCode == 13) {
-                                                      input_str = input_element.value;
-                                                      document.getElementById("output").removeChild(input_element);
-                                                      print(input_str);
-                                                      print("\n");
-                                                      resolve(input_str);
-                                                      }
-                                                      });
-                       });
+function printCard(card) {
+  if (card < minFaceCard) {
+    print(card);
+  } else {
+    print(faceCards[card]);
+  }
+  print("\n");
 }
 
-function tab(space)
-{
-    var str = "";
-    while (space-- > 0)
-        str += " ";
-    return str;
-}
-
-print(tab(26) + "ACEY DUCEY CARD GAME\n");
-print(tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n");
-print("\n");
-print("\n");
+print(spaces(26) + "ACEY DUCEY CARD GAME\n");
+print(spaces(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n\n");
 print("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER\n");
 print("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP\n");
 print("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING\n");
 print("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE\n");
 print("A VALUE BETWEEN THE FIRST TWO.\n");
-print("IF YOU DO NOT WANT TO BET, INPUT A 0\n");
+print("IF YOU DO NOT WANT TO BET, INPUT '0'\n");
 
-function show_card(card)
-{
-    if (card < 11)
-        print(card + "\n");
-    else if (card == 11)
-        print("JACK\n");
-    else if (card == 12)
-        print("QUEEN\n");
-    else if (card == 13)
-        print("KING\n");
-    else
-        print("ACE\n");
-}
+let currentMoney = 100;
+while (true) {
+  print(`YOU NOW HAVE ${currentMoney} DOLLARS.\n\n`);
 
-// Main program
-async function main()
-{
-    q = 100;
-    while (1) {
-        print("YOU NOW HAVE " + q + " DOLLARS.\n");
-        print("\n");
-        
-        do {
-            print("HERE ARE YOUR NEXT TWO CARDS: \n");
-            do {
-                a = Math.floor(Math.random() * 13 + 2);
-                b = Math.floor(Math.random() * 13 + 2);
-            } while (a >= b) ;
-            show_card(a);
-            show_card(b);
-            print("\n");
-            while (1) {
-                print("\n");
-                print("WHAT IS YOUR BET");
-                m = parseInt(await input());
-                if (m > 0) {
-                    if (m > q) {
-                        print("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.\n");
-                        print("YOU HAVE ONLY " + q + "DOLLARS TO BET.\n");
-                        continue;
-                    }
-                    break;
-                }
-                m = 0;
-                print("CHICKEN!!\n");
-                print("\n");
-                break;
-            }
-        } while (m == 0) ;
-        c = Math.floor(Math.random() * 13 + 2);
-        show_card(c);
-        if (c > a && c < b) {
-            print("YOU WIN!!!\n");
-            q = q + m;
-        } else {
-            print("SORRY, YOU LOSE\n");
-            if (m >= q) {
-                print("\n");
-                print("\n");
-                print("SORRY, FRIEND, BUT YOU BLEW YOUR WAD.\n");
-                print("\n");
-                print("\n");
-                print("TRY AGAIN (YES OR NO)");
-                a = await input();
-                print("\n");
-                print("\n");
-                if (a == "YES") {
-                    q = 100;
-                } else {
-                    print("O.K., HOPE YOU HAD FUN!");
-                    break;
-                }
-            } else {
-                q = q - m;
-            }
+  let card1, card2, currentBet;
+  do {
+    print("HERE ARE YOUR NEXT TWO CARDS: \n");
+    [card1, card2] = [randomCard(), randomCard()];
+
+    // Ensure we always show cards in order of lowest to highest, and we never
+    // get two of the same card.
+    do {
+      card1 = randomCard();
+      card2 = randomCard();
+    } while (card1 >= card2);
+
+    printCard(card1);
+    printCard(card2);
+    print("\n");
+
+    while (true) {
+      print("\nWHAT IS YOUR BET? ");
+      currentBet = parseInt(await readLine(), 10);
+
+      if (currentBet > 0) {
+        if (currentBet > currentMoney) {
+          print("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.\n");
+          print(`YOU HAVE ONLY ${currentMoney} DOLLARS TO BET.\n`);
+          continue;
         }
-    }
-}
+        break;
+      }
 
-main();
+      // Invalid bet value. Output an error message and reset to undefined to
+      // restart the loop with new cards.
+      currentBet = undefined;
+      print("CHICKEN!!\n");
+      print("\n");
+      break;
+    }
+  } while (currentBet === undefined);
+
+  const actualCard = randomCard();
+  print("\n\nHERE IS THE CARD WE DREW:\n")
+  printCard(actualCard);
+  print("\n\n");
+
+  if (actualCard > card1 && actualCard < card2) {
+    print("YOU WIN!!!\n");
+    currentMoney += currentBet;
+  } else {
+    print("SORRY, YOU LOSE\n");
+    if (currentBet < currentMoney) {
+      currentMoney -= currentBet;
+    } else {
+      print("\n\nSORRY, FRIEND, BUT YOU BLEW YOUR WAD.\n\n\n");
+      print("TRY AGAIN (YES OR NO)");
+      const tryAgain = await readLine();
+      print("\n\n");
+      if (tryAgain.toLowerCase() === "yes") {
+        currentMoney = 100;
+      } else {
+        print("O.K., HOPE YOU HAD FUN!");
+        break;
+      }
+    }
+  }
+}
diff --git a/01_Acey_Ducey/javascript/io.js b/01_Acey_Ducey/javascript/io.js
new file mode 100644
index 00000000..a9211e9c
--- /dev/null
+++ b/01_Acey_Ducey/javascript/io.js
@@ -0,0 +1,29 @@
+const outputEl = document.querySelector("#output");
+
+export function print(string) {
+  outputEl.append(string);
+}
+
+export function readLine() {
+  return new Promise(resolve => {
+    const inputEl = document.createElement("input");
+    outputEl.append(inputEl);
+    inputEl.focus();
+
+    inputEl.addEventListener("keydown", event => {
+      if (event.key === "Enter") {
+        const result = inputEl.value;
+        inputEl.remove();
+
+        print(result);
+        print("\n");
+
+        resolve(result);
+      }
+    });
+  });
+}
+
+export function spaces(numberOfSpaces) {
+  return " ".repeat(numberOfSpaces);
+}

From 73e3b4be2d550cdaa7ae11e6b1a589149a78acdd Mon Sep 17 00:00:00 2001
From: Jeff Atwood 
Date: Sat, 1 Jan 2022 13:20:35 -0800
Subject: [PATCH 458/749] Update README.md

---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index d481611c..266aaac8 100644
--- a/README.md
+++ b/README.md
@@ -42,3 +42,5 @@ Feel free to begin converting these classic games into the above list of modern,
 ### Have fun!
 
 Thank you for taking part in this project to update a classic programming book -- one of the most influential programming books in computing history -- for 2022 and beyond!
+
+NOTE: per [the official blog post announcement](https://blog.codinghorror.com/updating-the-single-most-influential-book-of-the-basic-era/), I will be **donating $5 for each contributed program in the 8 agreed upon languages to [Girls Who Code](https://girlswhocode.com/)**.

From 5e0f7cf9ad8bde9b91c07791617645096b6dfcff Mon Sep 17 00:00:00 2001
From: bmshipe 
Date: Sat, 1 Jan 2022 17:05:51 -0600
Subject: [PATCH 459/749] C# implementation of Bullseye

---
 18_Bullseye/csharp/Bullseye.csproj |  10 ++
 18_Bullseye/csharp/Bullseye.sln    |  22 +++
 18_Bullseye/csharp/BullseyeGame.cs | 237 +++++++++++++++++++++++++++++
 18_Bullseye/csharp/Player.cs       |  28 ++++
 18_Bullseye/csharp/Program.cs      |  14 ++
 5 files changed, 311 insertions(+)
 create mode 100644 18_Bullseye/csharp/Bullseye.csproj
 create mode 100644 18_Bullseye/csharp/Bullseye.sln
 create mode 100644 18_Bullseye/csharp/BullseyeGame.cs
 create mode 100644 18_Bullseye/csharp/Player.cs
 create mode 100644 18_Bullseye/csharp/Program.cs

diff --git a/18_Bullseye/csharp/Bullseye.csproj b/18_Bullseye/csharp/Bullseye.csproj
new file mode 100644
index 00000000..74abf5c9
--- /dev/null
+++ b/18_Bullseye/csharp/Bullseye.csproj
@@ -0,0 +1,10 @@
+
+
+  
+    Exe
+    net6.0
+    enable
+    enable
+  
+
+
diff --git a/18_Bullseye/csharp/Bullseye.sln b/18_Bullseye/csharp/Bullseye.sln
new file mode 100644
index 00000000..2a65a449
--- /dev/null
+++ b/18_Bullseye/csharp/Bullseye.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bullseye", "Bullseye.csproj", "{04C164DB-594F-41C4-BC0E-0A203A5536C7}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{04C164DB-594F-41C4-BC0E-0A203A5536C7}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/18_Bullseye/csharp/BullseyeGame.cs b/18_Bullseye/csharp/BullseyeGame.cs
new file mode 100644
index 00000000..58c9799d
--- /dev/null
+++ b/18_Bullseye/csharp/BullseyeGame.cs
@@ -0,0 +1,237 @@
+namespace Bullseye
+{
+    /// 
+    /// Class encompassing the game
+    /// 
+    public class BullseyeGame
+    {
+        private readonly List _players;
+
+        // define a constant for the winning score so that it is
+        // easy to change again in the future
+        private const int WinningScore = 200;
+
+        public BullseyeGame()
+        {
+            // create the initial list of players; list is empty, but
+            // the setup of the game will add items to this list
+            _players = new List();
+        }
+
+        public void Run()
+        {
+            PrintIntroduction();
+
+            SetupGame();
+
+            PlayGame();
+
+            PrintResults();
+        }
+
+        private void SetupGame()
+        {
+            // First, allow the user to enter how many players are going
+            // to play. This could be weird if the user enters negative
+            // numbers, words, or too many players, so there are some
+            // extra checks on the input to make sure the user didn't do
+            // anything too crazy. Loop until the user enters valid input.
+            bool validPlayerCount;
+            int playerCount;
+            do
+            {
+                Console.WriteLine();
+                Console.Write("HOW MANY PLAYERS? ");
+                string? input = Console.ReadLine();
+
+                // assume the user has entered something incorrect - the
+                // next steps will validate the input
+                validPlayerCount = false;
+
+                if (Int32.TryParse(input, out playerCount))
+                {
+                    if (playerCount > 0 && playerCount <= 20)
+                    {
+                        validPlayerCount = true;
+                    }
+                    else
+                    {
+                        Console.WriteLine("YOU MUST ENTER A NUMBER BETWEEN 1 AND 20!");
+                    }
+                }
+                else
+                {
+                    Console.WriteLine("YOU MUST ENTER A NUMBER");
+                }
+
+            }
+            while (!validPlayerCount);
+
+            // Next, allow the user to enter names for the players; as each
+            // name is entered, create a Player object to track the name
+            // and their score, and save the object to the list in this class
+            // so the rest of the game has access to the set of players
+            for (int i = 0; i < playerCount; i++)
+            {
+                string? playerName = String.Empty;
+                do
+                {
+                    Console.Write($"NAME OF PLAYER #{i+1}? ");
+                    playerName = Console.ReadLine();
+
+                    // names can be any sort of text, so allow whatever the user
+                    // enters as long as it isn't a blank space
+                }
+                while (String.IsNullOrWhiteSpace(playerName));
+
+                _players.Add(new Player(playerName));
+            }
+        }
+
+        private void PlayGame()
+        {
+            Random random = new Random(DateTime.Now.Millisecond);
+
+            int round = 0;
+            bool isOver = false;
+            do
+            {
+                // starting a new round, increment the counter
+                round++;
+                Console.WriteLine($"ROUND {round}");
+                Console.WriteLine("--------------");
+
+                foreach (Player player in _players)
+                {
+                    // ask the user how they want to throw
+                    Console.Write($"{player.Name.ToUpper()}'S THROW: ");
+                    string? input = Console.ReadLine();
+
+                    // based on the input, figure out the probabilities
+                    int[] probabilities;
+                    switch (input)
+                    {
+                        case "1":
+                        {
+                            probabilities = new int[] { 65, 55, 50, 50 };
+                            break;
+                        }
+                        case "2":
+                        {
+                            probabilities = new int[] { 99, 77, 43, 1 };
+                            break;
+                        }
+                        case "3":
+                        {
+                            probabilities = new int[] { 95, 75, 45, 5 };
+                            break;
+                        }
+                        default:
+                        {
+                            // in case the user types something bad, pretend it's
+                            // as if they tripped over themselves while throwing
+                            // the dart - they'll either hit a bullseye or completely
+                            // miss
+                            probabilities = new int[] { 95, 95, 95, 95 };
+                            Console.Write("TRIP! ");
+                            break;
+                        }
+                    }
+
+
+                    // Next() returns a number in the range: min <= num < max, so specify 101
+                    // as the maximum so that 100 is a number that could be returned
+                    int chance = random.Next(0, 101);
+
+                    if (chance > probabilities[0])
+                    {
+                        player.Score += 40;
+                        Console.WriteLine("BULLSEYE!!  40 POINTS!");
+                    }
+                    else if (chance > probabilities[1])
+                    {
+                        player.Score += 30;
+                        Console.WriteLine("30-POINT ZONE!");
+                    }
+                    else if (chance > probabilities[2])
+                    {
+                        player.Score += 20;
+                        Console.WriteLine("20-POINT ZONE");
+                    }
+                    else if (chance > probabilities[3])
+                    {
+                        player.Score += 10;
+                        Console.WriteLine("WHEW!  10 POINTS.");
+                    }
+                    else
+                    {
+                        // missed it
+                        Console.WriteLine("MISSED THE TARGET!  TOO BAD.");
+                    }
+
+                    // check to see if the player has won - if they have, then
+                    // break out of the loops
+                    if (player.Score > WinningScore)
+                    {
+                        Console.WriteLine();
+                        Console.WriteLine("WE HAVE A WINNER!!");
+                        Console.WriteLine($"{player.Name.ToUpper()} SCORED {player.Score} POINTS.");
+                        Console.WriteLine();
+
+                        isOver = true; // out of the do/while round loop
+                        break; // out of the foreach (player) loop
+                    }
+
+                    Console.WriteLine();
+                }
+            }
+            while (!isOver);
+        }
+
+        private void PrintResults()
+        {
+            // For bragging rights, print out all the scores, but sort them
+            // by who had the highest score
+            var sorted = _players.OrderByDescending(p => p.Score);
+
+            // padding is used to get things to line up nicely - the results
+            // should look something like:
+            //      PLAYER       SCORE
+            //      Bravo          210
+            //      Charlie         15
+            //      Alpha            1
+            Console.WriteLine("PLAYER       SCORE");
+            foreach (var player in sorted)
+            {
+                Console.WriteLine($"{player.Name.PadRight(12)} {player.Score.ToString().PadLeft(5)}");
+            }
+
+            Console.WriteLine();
+            Console.WriteLine("THANKS FOR THE GAME.");
+        }
+
+        private void PrintIntroduction()
+        {
+            Console.WriteLine(Title);
+            Console.WriteLine();
+            Console.WriteLine(Introduction);
+            Console.WriteLine();
+            Console.WriteLine(Operations);
+        }
+
+        private const string Title = @"
+                    BULLSEYE
+    CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY";
+
+        private const string Introduction = @"
+IN THIS GAME, UP TO 20 PLAYERS THROW DARTS AT A TARGET
+WITH 10, 20, 30, AND 40 POINT ZONES.  THE OBJECTIVE IS
+TO GET 200 POINTS.";
+
+        private const string Operations = @"
+THROW   DESCRIPTION         PROBABLE SCORE
+  1     FAST OVERARM        BULLSEYE OR COMPLETE MISS
+  2     CONTROLLED OVERARM  10, 20, OR 30 POINTS
+  3     UNDERARM            ANYTHING";
+    }
+}
diff --git a/18_Bullseye/csharp/Player.cs b/18_Bullseye/csharp/Player.cs
new file mode 100644
index 00000000..4d18fd43
--- /dev/null
+++ b/18_Bullseye/csharp/Player.cs
@@ -0,0 +1,28 @@
+namespace Bullseye
+{
+    /// 
+    /// Object to track the name and score of a player
+    /// 
+    public class Player
+    {
+        /// 
+        /// Creates a play with the given name
+        /// 
+        /// Name of the player
+        public Player(string name)
+        {
+            Name = name;
+            Score = 0;
+        }
+
+        /// 
+        /// Name of the player
+        /// 
+        public string Name { get; private set; }
+
+        /// 
+        /// Current score of the player
+        /// 
+        public int Score { get; set; }
+    }
+}
diff --git a/18_Bullseye/csharp/Program.cs b/18_Bullseye/csharp/Program.cs
new file mode 100644
index 00000000..1e4316ef
--- /dev/null
+++ b/18_Bullseye/csharp/Program.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Bullseye
+{
+    public static class Program
+    {
+        // Entry point to the application; create an instance of the
+        // game class and call Run()
+        public static void Main(string[] args)
+        {
+            new BullseyeGame().Run();
+        }
+    }
+}

From 6935e24ae38d9faff890e4c2b83317360795aa3e Mon Sep 17 00:00:00 2001
From: doctorgraphics <10650289+doctorgraphics@users.noreply.github.com>
Date: Sat, 1 Jan 2022 15:20:20 -0800
Subject: [PATCH 460/749] Update aceyducey.py

Correct misspelled word "assement" to "assessment"  on line 177
---
 01_Acey_Ducey/python/aceyducey.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/01_Acey_Ducey/python/aceyducey.py b/01_Acey_Ducey/python/aceyducey.py
index 9aaef681..87147181 100644
--- a/01_Acey_Ducey/python/aceyducey.py
+++ b/01_Acey_Ducey/python/aceyducey.py
@@ -174,7 +174,7 @@ print("OK Hope you had fun\n")
 #
 #   Give the user the ability to quit the game, perhaps
 #   by typing "quit" instead of making a bet.  Provide a
-#   final assement based on how much of the original
+#   final assessment based on how much of the original
 #   bankroll they have left.
 #
 #   Or have the game run for a set number of rounds or

From d6f9b8c68a077d9cb604ea6dbbbe4766bb80e17b Mon Sep 17 00:00:00 2001
From: ericries 
Date: Sat, 1 Jan 2022 17:04:12 -0800
Subject: [PATCH 461/749] Add files via upload

simple Python implementation of Tower - apologies for any errors, I only had a minute to dash this off
---
 tower.py | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)
 create mode 100644 tower.py

diff --git a/tower.py b/tower.py
new file mode 100644
index 00000000..72c67a61
--- /dev/null
+++ b/tower.py
@@ -0,0 +1,159 @@
+import sys
+
+class Disk:
+    def __init__(self, size):
+        self.__size = size
+
+    def size(self):
+        return self.__size
+
+    def print(self):
+        print("[ %s ]" % self.size())
+
+class Tower:
+    def __init__(self):
+        self.__disks = []
+
+    def empty(self):
+        return len(self.__disks) == 0
+
+    def top(self):
+        if self.empty():
+            return None
+        else:
+            return self.__disks[-1]
+
+    def add(self, disk):
+        if not self.empty():
+            t = self.top()
+            if disk.size() > t.size():
+                raise Exception("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE, IT MIGHT CRUSH IT!")
+        self.__disks.append(disk)
+
+    def pop(self):
+        if self.empty():
+            raise Exception("empty pop")
+        return self.__disks.pop()
+
+    def print(self):
+        r = "Needle: [%s]" % (", ".join([str(x.size()) for x in self.__disks]))
+        print(r)
+
+
+
+print("""
+IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
+3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
+7 THE NEXT, AND SO ON, UP TO 15.  IF YOU DO THE PUZZLE WITH
+2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15.  WITH 3 DISKS
+THE CODE NAMES WOULD BE 11, 13 AND 15, ETC.  THE NEEDLES
+ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3.  WE WILL
+START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
+TO NEEDLE 3.
+
+GOOD LUCK!
+
+""")
+
+
+
+
+class Game:
+    def __init__(self):
+        self.__sizes = [3, 5, 7]  # ,9,11,13,15]
+        self.__sizes.sort()
+
+        self.__towers = []
+        self.__moves = 0
+        self.__towers = [Tower(), Tower(), Tower()]
+        self.__sizes.reverse()
+        for size in self.__sizes:
+            disk = Disk(size)
+            self.__towers[0].add(disk)
+
+    def winner(self):
+        return self.__towers[0].empty() and self.__towers[1].empty()
+
+    def print(self):
+        for t in self.__towers:
+            t.print()
+
+    def moves(self):
+        return self.__moves
+
+    def which_disk(self):
+        w = int(input("WHICH DISK WOULD YOU LIKE TO MOVE\n"))
+        if w in self.__sizes:
+            return w
+        else:
+            raise Exception()
+
+    def pick_disk(self):
+        which = None
+        while which is None:
+            try:
+                which = self.which_disk()
+            except:
+                print("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.\n")
+
+        valids = [t for t in self.__towers if t.top() and t.top().size() == which]
+        assert len(valids) in (0, 1)
+        if not valids:
+            print("THAT DISK IS BELOW ANOTHER ONE.  MAKE ANOTHER CHOICE.\n")
+            return None
+        else:
+            assert valids[0].top().size() == which
+            return valids[0]
+
+    def which_tower(self):
+        try:
+            needle = int(input("PLACE DISK ON WHICH NEEDLE\n"))
+            tower = self.__towers[needle - 1]
+        except:
+            print("I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME.  BUT WATCH IT,\nI ONLY ALLOW ONE MISTAKE.\n")
+            return None
+        else:
+            return tower
+
+    def take_turn(self):
+        from_tower = None
+        while from_tower is None:
+            from_tower = self.pick_disk()
+
+        to_tower = self.which_tower()
+        if not to_tower:
+            to_tower = self.which_tower()
+
+        if not to_tower:
+            print("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN.\nBYE BYE, BIG SHOT.\n")
+            sys.exit(0)
+
+        disk = from_tower.pop()
+        try:
+            to_tower.add( disk )
+            self.__moves += 1
+        except Exception as err:
+            print(err)
+            from_tower.add(disk)
+
+game = Game()
+while True:
+    game.print()
+
+    game.take_turn()
+
+    if game.winner():
+        print("CONGRATULATIONS!!\nYOU HAVE PERFORMED THE TASK IN %s MOVES.\n" % game.moves())
+        while True:
+            yesno = input("TRY AGAIN (YES OR NO)\n")
+            if yesno.upper() == "YES":
+                game = Game()
+                break
+            elif yesno.upper() == "NO":
+                print("THANKS FOR THE GAME!\n")
+                sys.exit(0)
+            else:
+                print("'YES' OR 'NO' PLEASE\n")
+    elif game.moves() > 128:
+        print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
+        sys.exit(0)
\ No newline at end of file

From 5e2647682f1fde87702de7ea4f9786143172e47f Mon Sep 17 00:00:00 2001
From: ericries 
Date: Sat, 1 Jan 2022 17:05:56 -0800
Subject: [PATCH 462/749] Add files via upload

Simple python implementation. Apologies for any errors, I only had a minute to whip this up
---
 90_Tower/python/tower.py | 159 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)
 create mode 100644 90_Tower/python/tower.py

diff --git a/90_Tower/python/tower.py b/90_Tower/python/tower.py
new file mode 100644
index 00000000..72c67a61
--- /dev/null
+++ b/90_Tower/python/tower.py
@@ -0,0 +1,159 @@
+import sys
+
+class Disk:
+    def __init__(self, size):
+        self.__size = size
+
+    def size(self):
+        return self.__size
+
+    def print(self):
+        print("[ %s ]" % self.size())
+
+class Tower:
+    def __init__(self):
+        self.__disks = []
+
+    def empty(self):
+        return len(self.__disks) == 0
+
+    def top(self):
+        if self.empty():
+            return None
+        else:
+            return self.__disks[-1]
+
+    def add(self, disk):
+        if not self.empty():
+            t = self.top()
+            if disk.size() > t.size():
+                raise Exception("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE, IT MIGHT CRUSH IT!")
+        self.__disks.append(disk)
+
+    def pop(self):
+        if self.empty():
+            raise Exception("empty pop")
+        return self.__disks.pop()
+
+    def print(self):
+        r = "Needle: [%s]" % (", ".join([str(x.size()) for x in self.__disks]))
+        print(r)
+
+
+
+print("""
+IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
+3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
+7 THE NEXT, AND SO ON, UP TO 15.  IF YOU DO THE PUZZLE WITH
+2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15.  WITH 3 DISKS
+THE CODE NAMES WOULD BE 11, 13 AND 15, ETC.  THE NEEDLES
+ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3.  WE WILL
+START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
+TO NEEDLE 3.
+
+GOOD LUCK!
+
+""")
+
+
+
+
+class Game:
+    def __init__(self):
+        self.__sizes = [3, 5, 7]  # ,9,11,13,15]
+        self.__sizes.sort()
+
+        self.__towers = []
+        self.__moves = 0
+        self.__towers = [Tower(), Tower(), Tower()]
+        self.__sizes.reverse()
+        for size in self.__sizes:
+            disk = Disk(size)
+            self.__towers[0].add(disk)
+
+    def winner(self):
+        return self.__towers[0].empty() and self.__towers[1].empty()
+
+    def print(self):
+        for t in self.__towers:
+            t.print()
+
+    def moves(self):
+        return self.__moves
+
+    def which_disk(self):
+        w = int(input("WHICH DISK WOULD YOU LIKE TO MOVE\n"))
+        if w in self.__sizes:
+            return w
+        else:
+            raise Exception()
+
+    def pick_disk(self):
+        which = None
+        while which is None:
+            try:
+                which = self.which_disk()
+            except:
+                print("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.\n")
+
+        valids = [t for t in self.__towers if t.top() and t.top().size() == which]
+        assert len(valids) in (0, 1)
+        if not valids:
+            print("THAT DISK IS BELOW ANOTHER ONE.  MAKE ANOTHER CHOICE.\n")
+            return None
+        else:
+            assert valids[0].top().size() == which
+            return valids[0]
+
+    def which_tower(self):
+        try:
+            needle = int(input("PLACE DISK ON WHICH NEEDLE\n"))
+            tower = self.__towers[needle - 1]
+        except:
+            print("I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME.  BUT WATCH IT,\nI ONLY ALLOW ONE MISTAKE.\n")
+            return None
+        else:
+            return tower
+
+    def take_turn(self):
+        from_tower = None
+        while from_tower is None:
+            from_tower = self.pick_disk()
+
+        to_tower = self.which_tower()
+        if not to_tower:
+            to_tower = self.which_tower()
+
+        if not to_tower:
+            print("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN.\nBYE BYE, BIG SHOT.\n")
+            sys.exit(0)
+
+        disk = from_tower.pop()
+        try:
+            to_tower.add( disk )
+            self.__moves += 1
+        except Exception as err:
+            print(err)
+            from_tower.add(disk)
+
+game = Game()
+while True:
+    game.print()
+
+    game.take_turn()
+
+    if game.winner():
+        print("CONGRATULATIONS!!\nYOU HAVE PERFORMED THE TASK IN %s MOVES.\n" % game.moves())
+        while True:
+            yesno = input("TRY AGAIN (YES OR NO)\n")
+            if yesno.upper() == "YES":
+                game = Game()
+                break
+            elif yesno.upper() == "NO":
+                print("THANKS FOR THE GAME!\n")
+                sys.exit(0)
+            else:
+                print("'YES' OR 'NO' PLEASE\n")
+    elif game.moves() > 128:
+        print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
+        sys.exit(0)
\ No newline at end of file

From fb7b7ffe0e7eea768951e31a3e876149f86803bf Mon Sep 17 00:00:00 2001
From: ericries 
Date: Sat, 1 Jan 2022 17:08:10 -0800
Subject: [PATCH 463/749] Delete tower.py

---
 tower.py | 159 -------------------------------------------------------
 1 file changed, 159 deletions(-)
 delete mode 100644 tower.py

diff --git a/tower.py b/tower.py
deleted file mode 100644
index 72c67a61..00000000
--- a/tower.py
+++ /dev/null
@@ -1,159 +0,0 @@
-import sys
-
-class Disk:
-    def __init__(self, size):
-        self.__size = size
-
-    def size(self):
-        return self.__size
-
-    def print(self):
-        print("[ %s ]" % self.size())
-
-class Tower:
-    def __init__(self):
-        self.__disks = []
-
-    def empty(self):
-        return len(self.__disks) == 0
-
-    def top(self):
-        if self.empty():
-            return None
-        else:
-            return self.__disks[-1]
-
-    def add(self, disk):
-        if not self.empty():
-            t = self.top()
-            if disk.size() > t.size():
-                raise Exception("YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE, IT MIGHT CRUSH IT!")
-        self.__disks.append(disk)
-
-    def pop(self):
-        if self.empty():
-            raise Exception("empty pop")
-        return self.__disks.pop()
-
-    def print(self):
-        r = "Needle: [%s]" % (", ".join([str(x.size()) for x in self.__disks]))
-        print(r)
-
-
-
-print("""
-IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
-3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
-7 THE NEXT, AND SO ON, UP TO 15.  IF YOU DO THE PUZZLE WITH
-2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15.  WITH 3 DISKS
-THE CODE NAMES WOULD BE 11, 13 AND 15, ETC.  THE NEEDLES
-ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3.  WE WILL
-START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
-TO NEEDLE 3.
-
-GOOD LUCK!
-
-""")
-
-
-
-
-class Game:
-    def __init__(self):
-        self.__sizes = [3, 5, 7]  # ,9,11,13,15]
-        self.__sizes.sort()
-
-        self.__towers = []
-        self.__moves = 0
-        self.__towers = [Tower(), Tower(), Tower()]
-        self.__sizes.reverse()
-        for size in self.__sizes:
-            disk = Disk(size)
-            self.__towers[0].add(disk)
-
-    def winner(self):
-        return self.__towers[0].empty() and self.__towers[1].empty()
-
-    def print(self):
-        for t in self.__towers:
-            t.print()
-
-    def moves(self):
-        return self.__moves
-
-    def which_disk(self):
-        w = int(input("WHICH DISK WOULD YOU LIKE TO MOVE\n"))
-        if w in self.__sizes:
-            return w
-        else:
-            raise Exception()
-
-    def pick_disk(self):
-        which = None
-        while which is None:
-            try:
-                which = self.which_disk()
-            except:
-                print("ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13, OR 15.\n")
-
-        valids = [t for t in self.__towers if t.top() and t.top().size() == which]
-        assert len(valids) in (0, 1)
-        if not valids:
-            print("THAT DISK IS BELOW ANOTHER ONE.  MAKE ANOTHER CHOICE.\n")
-            return None
-        else:
-            assert valids[0].top().size() == which
-            return valids[0]
-
-    def which_tower(self):
-        try:
-            needle = int(input("PLACE DISK ON WHICH NEEDLE\n"))
-            tower = self.__towers[needle - 1]
-        except:
-            print("I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME.  BUT WATCH IT,\nI ONLY ALLOW ONE MISTAKE.\n")
-            return None
-        else:
-            return tower
-
-    def take_turn(self):
-        from_tower = None
-        while from_tower is None:
-            from_tower = self.pick_disk()
-
-        to_tower = self.which_tower()
-        if not to_tower:
-            to_tower = self.which_tower()
-
-        if not to_tower:
-            print("I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN.\nBYE BYE, BIG SHOT.\n")
-            sys.exit(0)
-
-        disk = from_tower.pop()
-        try:
-            to_tower.add( disk )
-            self.__moves += 1
-        except Exception as err:
-            print(err)
-            from_tower.add(disk)
-
-game = Game()
-while True:
-    game.print()
-
-    game.take_turn()
-
-    if game.winner():
-        print("CONGRATULATIONS!!\nYOU HAVE PERFORMED THE TASK IN %s MOVES.\n" % game.moves())
-        while True:
-            yesno = input("TRY AGAIN (YES OR NO)\n")
-            if yesno.upper() == "YES":
-                game = Game()
-                break
-            elif yesno.upper() == "NO":
-                print("THANKS FOR THE GAME!\n")
-                sys.exit(0)
-            else:
-                print("'YES' OR 'NO' PLEASE\n")
-    elif game.moves() > 128:
-        print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
-        sys.exit(0)
\ No newline at end of file

From c2dc4c8b38977849ac3c933e1946c8c5ca09f628 Mon Sep 17 00:00:00 2001
From: LukasMurdock 
Date: Sat, 1 Jan 2022 20:09:24 -0500
Subject: [PATCH 464/749] update acey_ducey

---
 01_Acey_Ducey/javascript/.prettierrc.json |   6 +
 01_Acey_Ducey/javascript/aceyducey.html   |   8 +-
 01_Acey_Ducey/javascript/aceyducey.js     | 284 +++++++++++++++-------
 01_Acey_Ducey/javascript/io.js            |  29 ---
 01_Acey_Ducey/javascript/util.js          |  67 +++++
 5 files changed, 277 insertions(+), 117 deletions(-)
 create mode 100644 01_Acey_Ducey/javascript/.prettierrc.json
 delete mode 100644 01_Acey_Ducey/javascript/io.js
 create mode 100644 01_Acey_Ducey/javascript/util.js

diff --git a/01_Acey_Ducey/javascript/.prettierrc.json b/01_Acey_Ducey/javascript/.prettierrc.json
new file mode 100644
index 00000000..f9148847
--- /dev/null
+++ b/01_Acey_Ducey/javascript/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+    "trailingComma": "es5",
+    "tabWidth": 4,
+    "semi": true,
+    "singleQuote": true
+}
diff --git a/01_Acey_Ducey/javascript/aceyducey.html b/01_Acey_Ducey/javascript/aceyducey.html
index e526c3df..61c362a7 100644
--- a/01_Acey_Ducey/javascript/aceyducey.html
+++ b/01_Acey_Ducey/javascript/aceyducey.html
@@ -1,7 +1,7 @@
 
-
-
+
+
 ACEY DUCEY
 
-

-
+

+
diff --git a/01_Acey_Ducey/javascript/aceyducey.js b/01_Acey_Ducey/javascript/aceyducey.js
index 6c31d77c..61525a3d 100644
--- a/01_Acey_Ducey/javascript/aceyducey.js
+++ b/01_Acey_Ducey/javascript/aceyducey.js
@@ -1,100 +1,216 @@
-import { readLine, print, spaces } from "./io.js";
+// UTILITY VARIABLES
 
-const minFaceCard = 11;
-const faceCards = {
-  11: "JACK",
-  12: "QUEEN",
-  13: "KING",
-  14: "ACE"
-};
+// By default:
+// — Browsers have a window object
+// — Node.js does not
+// Checking for an undefined window object is a loose check
+// to enable browser and Node.js support
+const isRunningInBrowser = typeof window !== 'undefined';
 
-function randomCard() {
-  return Math.floor(Math.random() * 13 + 2);
+// To easily validate input strings with utility functions
+const validLowerCaseYesStrings = ['yes', 'y'];
+const validLowerCaseNoStrings = ['no', 'n'];
+const validLowerCaseYesAndNoStrings = [
+    ...validLowerCaseYesStrings,
+    ...validLowerCaseNoStrings,
+];
+// UTILITY VARIABLES
+
+// Function to get a random number (card) 2-14 (ACE is 14)
+function getRandomCard() {
+    // In our game, the value of ACE is greater than face cards;
+    // instead of having the value of ACE be 1, we’ll have it be 14.
+    // So, we want to shift the range of random numbers from 1-13 to 2-14
+    let min = 2;
+    let max = 14;
+    // Return random integer between two values, inclusive
+    return Math.floor(Math.random() * (max - min + 1) + min);
 }
 
-function printCard(card) {
-  if (card < minFaceCard) {
-    print(card);
-  } else {
-    print(faceCards[card]);
-  }
-  print("\n");
+function getGameCards() {
+    let cardOne = getRandomCard();
+    let cardTwo = getRandomCard();
+    let cardThree = getRandomCard();
+    // We want:
+    // 1. cardOne and cardTwo to be different cards
+    // 2. cardOne to be lower than cardTwo
+    // So, while cardOne is greater than or equal two cardTwo
+    // we will continue to generate random cards.
+    while (cardOne >= cardTwo) {
+        cardOne = getRandomCard();
+        cardTwo = getRandomCard();
+    }
+    return [cardOne, cardTwo, cardThree];
 }
 
-print(spaces(26) + "ACEY DUCEY CARD GAME\n");
-print(spaces(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n\n");
-print("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER\n");
-print("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP\n");
-print("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING\n");
-print("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE\n");
-print("A VALUE BETWEEN THE FIRST TWO.\n");
-print("IF YOU DO NOT WANT TO BET, INPUT '0'\n");
+// Function to get card value
+function getCardValue(card) {
+    let faceOrAce = {
+        11: 'JACK',
+        12: 'QUEEN',
+        13: 'KING',
+        14: 'ACE',
+    };
+    // If card value matches a key in faceOrAce, use faceOrAce value;
+    // Else, return undefined and handle with the Nullish Coalescing Operator (??)
+    // and default to card value.
+    let cardValue = faceOrAce[card] ?? card;
+    return cardValue;
+}
 
-let currentMoney = 100;
-while (true) {
-  print(`YOU NOW HAVE ${currentMoney} DOLLARS.\n\n`);
+print(spaces(26) + 'ACEY DUCEY CARD GAME');
+print(spaces(15) + 'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n\n');
+print('ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER');
+print('THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP');
+print('YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING');
+print('ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE');
+print('A VALUE BETWEEN THE FIRST TWO.');
+print("IF YOU DO NOT WANT TO BET, INPUT '0'");
 
-  let card1, card2, currentBet;
-  do {
-    print("HERE ARE YOUR NEXT TWO CARDS: \n");
-    [card1, card2] = [randomCard(), randomCard()];
+main();
 
-    // Ensure we always show cards in order of lowest to highest, and we never
-    // get two of the same card.
-    do {
-      card1 = randomCard();
-      card2 = randomCard();
-    } while (card1 >= card2);
-
-    printCard(card1);
-    printCard(card2);
-    print("\n");
+async function main() {
+    let bet;
+    let availableDollars = 100;
 
+    // Loop game forever
     while (true) {
-      print("\nWHAT IS YOUR BET? ");
-      currentBet = parseInt(await readLine(), 10);
+        let [cardOne, cardTwo, cardThree] = getGameCards();
 
-      if (currentBet > 0) {
-        if (currentBet > currentMoney) {
-          print("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.\n");
-          print(`YOU HAVE ONLY ${currentMoney} DOLLARS TO BET.\n`);
-          continue;
+        print(`YOU NOW HAVE ${availableDollars} DOLLARS.\n`);
+
+        print('HERE ARE YOUR NEXT TWO CARDS: ');
+        print(getCardValue(cardOne));
+        print(getCardValue(cardTwo));
+        print('');
+
+        // Loop until receiving a valid bet
+        let validBet = false;
+        while (!validBet) {
+            print('\nWHAT IS YOUR BET? ');
+            bet = parseInt(await input(), 10);
+            let minimumRequiredBet = 0;
+            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('');
+            }
         }
-        break;
-      }
 
-      // Invalid bet value. Output an error message and reset to undefined to
-      // restart the loop with new cards.
-      currentBet = undefined;
-      print("CHICKEN!!\n");
-      print("\n");
-      break;
+        print('\n\nHERE IS THE CARD WE DREW: ');
+        print(getCardValue(cardThree));
+
+        // Determine if player won or lost
+        if (cardThree > cardOne && cardThree < cardTwo) {
+            print('YOU WIN!!!');
+            availableDollars = availableDollars + bet;
+        } else {
+            print('SORRY, YOU LOSE');
+
+            if (bet >= availableDollars) {
+                print('');
+                print('');
+                print('SORRY, FRIEND, BUT YOU BLEW YOUR WAD.');
+                print('');
+                print('');
+                print('TRY AGAIN (YES OR NO)');
+
+                let tryAgainInput = await input();
+
+                print('');
+                print('');
+
+                if (isValidYesNoString(tryAgainInput)) {
+                    availableDollars = 100;
+                } else {
+                    print('O.K., HOPE YOU HAD FUN!');
+                    break;
+                }
+            } else {
+                availableDollars = availableDollars - bet;
+            }
+        }
     }
-  } while (currentBet === undefined);
-
-  const actualCard = randomCard();
-  print("\n\nHERE IS THE CARD WE DREW:\n")
-  printCard(actualCard);
-  print("\n\n");
-
-  if (actualCard > card1 && actualCard < card2) {
-    print("YOU WIN!!!\n");
-    currentMoney += currentBet;
-  } else {
-    print("SORRY, YOU LOSE\n");
-    if (currentBet < currentMoney) {
-      currentMoney -= currentBet;
-    } else {
-      print("\n\nSORRY, FRIEND, BUT YOU BLEW YOUR WAD.\n\n\n");
-      print("TRY AGAIN (YES OR NO)");
-      const tryAgain = await readLine();
-      print("\n\n");
-      if (tryAgain.toLowerCase() === "yes") {
-        currentMoney = 100;
-      } else {
-        print("O.K., HOPE YOU HAD FUN!");
-        break;
-      }
-    }
-  }
 }
+
+// UTILITY FUNCTIONS
+function isValidYesNoString(string) {
+    return validLowerCaseYesAndNoStrings.includes(string.toLowerCase());
+}
+
+function isValidYesString(string) {
+    return validLowerCaseYesStrings.includes(string.toLowerCase());
+}
+
+function isValidNoString(string) {
+    return validLowerCaseNoStrings.includes(string.toLowerCase());
+}
+
+function print(string) {
+    if (isRunningInBrowser) {
+        // Adds trailing newline to match console.log behavior
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string + '\n'));
+    } else {
+        console.log(string);
+    }
+}
+
+function input() {
+    if (isRunningInBrowser) {
+        // Accept input from the browser DOM input
+        return new Promise((resolve) => {
+            const outputElement = document.querySelector('#output');
+            const inputElement = document.createElement('input');
+            outputElement.append(inputElement);
+            inputElement.focus();
+
+            inputElement.addEventListener('keydown', (event) => {
+                if (event.key === 'Enter') {
+                    const result = inputElement.value;
+                    inputElement.remove();
+                    print(result);
+                    print('');
+                    resolve(result);
+                }
+            });
+        });
+    } else {
+        // Accept input from the command line in Node.js
+        // See: https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs
+        return new Promise(function (resolve) {
+            const readline = require('readline').createInterface({
+                input: process.stdin,
+                output: process.stdout,
+            });
+            readline.question('', function (input) {
+                resolve(input);
+                readline.close();
+            });
+        });
+    }
+}
+
+function printInline(string) {
+    if (isRunningInBrowser) {
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string));
+    } else {
+        process.stdout.write(string);
+    }
+}
+
+function spaces(numberOfSpaces) {
+    return ' '.repeat(numberOfSpaces);
+}
+
+// UTILITY FUNCTIONS
diff --git a/01_Acey_Ducey/javascript/io.js b/01_Acey_Ducey/javascript/io.js
deleted file mode 100644
index a9211e9c..00000000
--- a/01_Acey_Ducey/javascript/io.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const outputEl = document.querySelector("#output");
-
-export function print(string) {
-  outputEl.append(string);
-}
-
-export function readLine() {
-  return new Promise(resolve => {
-    const inputEl = document.createElement("input");
-    outputEl.append(inputEl);
-    inputEl.focus();
-
-    inputEl.addEventListener("keydown", event => {
-      if (event.key === "Enter") {
-        const result = inputEl.value;
-        inputEl.remove();
-
-        print(result);
-        print("\n");
-
-        resolve(result);
-      }
-    });
-  });
-}
-
-export function spaces(numberOfSpaces) {
-  return " ".repeat(numberOfSpaces);
-}
diff --git a/01_Acey_Ducey/javascript/util.js b/01_Acey_Ducey/javascript/util.js
new file mode 100644
index 00000000..418eff40
--- /dev/null
+++ b/01_Acey_Ducey/javascript/util.js
@@ -0,0 +1,67 @@
+// By default:
+// — Browsers have a window object
+// — Node.js does not
+// Checking for an undefined window object is a loose check
+// to enable browser and Node.js support
+const isRunningInBrowser = typeof window !== 'undefined';
+
+const outputElement = document.querySelector('#output');
+
+function print(string) {
+    if (isRunningInBrowser) {
+        // Adds trailing newline to match console.log behavior
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string + '\n'));
+    } else {
+        console.log(string);
+    }
+}
+
+function input() {
+    if (isRunningInBrowser) {
+        // Accept input from the browser DOM input
+        return new Promise((resolve) => {
+            const inputEl = document.createElement('input');
+            outputElement.append(inputEl);
+            inputEl.focus();
+
+            inputEl.addEventListener('keydown', (event) => {
+                if (event.key === 'Enter') {
+                    const result = inputEl.value;
+                    inputEl.remove();
+                    print(result);
+                    print('');
+                    resolve(result);
+                }
+            });
+        });
+    } else {
+        // Accept input from the command line in Node.js
+        // See: https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs
+        return new Promise(function (resolve) {
+            const readline = require('readline').createInterface({
+                input: process.stdin,
+                output: process.stdout,
+            });
+            readline.question('', function (input) {
+                resolve(input);
+                readline.close();
+            });
+        });
+    }
+}
+
+function printInline(string) {
+    if (isRunningInBrowser) {
+        document
+            .getElementById('output')
+            .appendChild(document.createTextNode(string));
+    } else {
+        process.stdout.write(string);
+    }
+}
+
+function spaces(numberOfSpaces) {
+    return ' '.repeat(numberOfSpaces);
+}

From 437b4c29205c2a5eb5a338215eeb9a5207130e1d Mon Sep 17 00:00:00 2001
From: ericries 
Date: Sat, 1 Jan 2022 17:26:04 -0800
Subject: [PATCH 465/749] Update tower.py

easier debugging with fewer disks
---
 90_Tower/python/tower.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/90_Tower/python/tower.py b/90_Tower/python/tower.py
index 72c67a61..5e4a25b7 100644
--- a/90_Tower/python/tower.py
+++ b/90_Tower/python/tower.py
@@ -60,7 +60,10 @@ GOOD LUCK!
 
 class Game:
     def __init__(self):
-        self.__sizes = [3, 5, 7]  # ,9,11,13,15]
+        # use fewer sizes to make debugging easier
+        # self.__sizes = [3, 5, 7]  # ,9,11,13,15]
+        self.__sizes = [3, 5, 7, 9, 11, 13, 15]
+        
         self.__sizes.sort()
 
         self.__towers = []
@@ -156,4 +159,4 @@ while True:
                 print("'YES' OR 'NO' PLEASE\n")
     elif game.moves() > 128:
         print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
-        sys.exit(0)
\ No newline at end of file
+        sys.exit(0)

From 5c994e95621220a4caf31a22e8a33cf1bbccc934 Mon Sep 17 00:00:00 2001
From: LukasMurdock 
Date: Sat, 1 Jan 2022 20:45:19 -0500
Subject: [PATCH 466/749] typos

---
 01_Acey_Ducey/javascript/aceyducey.js |  6 +--
 01_Acey_Ducey/javascript/util.js      | 67 ---------------------------
 2 files changed, 3 insertions(+), 70 deletions(-)
 delete mode 100644 01_Acey_Ducey/javascript/util.js

diff --git a/01_Acey_Ducey/javascript/aceyducey.js b/01_Acey_Ducey/javascript/aceyducey.js
index 61525a3d..8bf5e9e1 100644
--- a/01_Acey_Ducey/javascript/aceyducey.js
+++ b/01_Acey_Ducey/javascript/aceyducey.js
@@ -27,14 +27,14 @@ function getRandomCard() {
     return Math.floor(Math.random() * (max - min + 1) + min);
 }
 
-function getGameCards() {
+function newGameCards() {
     let cardOne = getRandomCard();
     let cardTwo = getRandomCard();
     let cardThree = getRandomCard();
     // We want:
     // 1. cardOne and cardTwo to be different cards
     // 2. cardOne to be lower than cardTwo
-    // So, while cardOne is greater than or equal two cardTwo
+    // So, while cardOne is greater than or equal too cardTwo
     // we will continue to generate random cards.
     while (cardOne >= cardTwo) {
         cardOne = getRandomCard();
@@ -75,7 +75,7 @@ async function main() {
 
     // Loop game forever
     while (true) {
-        let [cardOne, cardTwo, cardThree] = getGameCards();
+        let [cardOne, cardTwo, cardThree] = newGameCards();
 
         print(`YOU NOW HAVE ${availableDollars} DOLLARS.\n`);
 
diff --git a/01_Acey_Ducey/javascript/util.js b/01_Acey_Ducey/javascript/util.js
deleted file mode 100644
index 418eff40..00000000
--- a/01_Acey_Ducey/javascript/util.js
+++ /dev/null
@@ -1,67 +0,0 @@
-// By default:
-// — Browsers have a window object
-// — Node.js does not
-// Checking for an undefined window object is a loose check
-// to enable browser and Node.js support
-const isRunningInBrowser = typeof window !== 'undefined';
-
-const outputElement = document.querySelector('#output');
-
-function print(string) {
-    if (isRunningInBrowser) {
-        // Adds trailing newline to match console.log behavior
-        document
-            .getElementById('output')
-            .appendChild(document.createTextNode(string + '\n'));
-    } else {
-        console.log(string);
-    }
-}
-
-function input() {
-    if (isRunningInBrowser) {
-        // Accept input from the browser DOM input
-        return new Promise((resolve) => {
-            const inputEl = document.createElement('input');
-            outputElement.append(inputEl);
-            inputEl.focus();
-
-            inputEl.addEventListener('keydown', (event) => {
-                if (event.key === 'Enter') {
-                    const result = inputEl.value;
-                    inputEl.remove();
-                    print(result);
-                    print('');
-                    resolve(result);
-                }
-            });
-        });
-    } else {
-        // Accept input from the command line in Node.js
-        // See: https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs
-        return new Promise(function (resolve) {
-            const readline = require('readline').createInterface({
-                input: process.stdin,
-                output: process.stdout,
-            });
-            readline.question('', function (input) {
-                resolve(input);
-                readline.close();
-            });
-        });
-    }
-}
-
-function printInline(string) {
-    if (isRunningInBrowser) {
-        document
-            .getElementById('output')
-            .appendChild(document.createTextNode(string));
-    } else {
-        process.stdout.write(string);
-    }
-}
-
-function spaces(numberOfSpaces) {
-    return ' '.repeat(numberOfSpaces);
-}

From f0327b7615a5ceacee962b0b99ecc24fe99bbd29 Mon Sep 17 00:00:00 2001
From: Matthew Kuehn 
Date: Sat, 1 Jan 2022 20:02:28 -0600
Subject: [PATCH 467/749] Fix spelling and grammar.

---
 59_Lunar_LEM_Rocket/javascript/lem.js | 8 ++++----
 96_Word/javascript/word.js            | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/59_Lunar_LEM_Rocket/javascript/lem.js b/59_Lunar_LEM_Rocket/javascript/lem.js
index 4f5ffd30..68bab1cf 100644
--- a/59_Lunar_LEM_Rocket/javascript/lem.js
+++ b/59_Lunar_LEM_Rocket/javascript/lem.js
@@ -12,10 +12,10 @@ function input()
 {
     var input_element;
     var input_str;
-    
+
     return new Promise(function (resolve) {
                        input_element = document.createElement("INPUT");
-                       
+
                        print("? ");
                        input_element.setAttribute("type", "text");
                        input_element.setAttribute("length", "50");
@@ -112,13 +112,13 @@ async function main()
             print("\n");
             print("WHICH SYSTEM OF MEASUREMENT DO YOU PREFER?\n");
             print(" 1=METRIC     0=ENGLISH\n");
-            print("ENTER THE APPROPIATE NUMBER");
+            print("ENTER THE APPROPRIATE NUMBER");
         }
         while (1) {
             k = parseInt(await input());
             if (k == 0 || k == 1)
                 break;
-            print("ENTER THE APPROPIATE NUMBER");
+            print("ENTER THE APPROPRIATE NUMBER");
         }
         if (k == 1) {
             z = 1852.8;
diff --git a/96_Word/javascript/word.js b/96_Word/javascript/word.js
index 6e5acf50..4df5d3fd 100644
--- a/96_Word/javascript/word.js
+++ b/96_Word/javascript/word.js
@@ -12,10 +12,10 @@ function input()
 {
     var input_element;
     var input_str;
-    
+
     return new Promise(function (resolve) {
                        input_element = document.createElement("INPUT");
-                       
+
                        print("? ");
                        input_element.setAttribute("type", "text");
                        input_element.setAttribute("length", "50");
@@ -61,7 +61,7 @@ async function main()
     print("\n");
     print("\n");
     print("I AM THINKING OF A WORD -- YOU GUESS IT.  I WILL GIVE YOU\n");
-    print("CLUE TO HELP YO GET IT.  GOOD LUCK!!\n");
+    print("CLUES TO HELP YOU GET IT.  GOOD LUCK!!\n");
     print("\n");
     print("\n");
     while (1) {

From 355ac8ec8e3a356c59289e335a08d6fadd5a7c2c Mon Sep 17 00:00:00 2001
From: John Long 
Date: Sat, 1 Jan 2022 20:45:20 -0800
Subject: [PATCH 468/749] Add Kotlin for Tic-Tac-Toe

---
 89_Tic-Tac-Toe/kotlin/Board.kt      | 80 ++++++++++++++++++++++++
 89_Tic-Tac-Toe/kotlin/README.md     |  3 +
 89_Tic-Tac-Toe/kotlin/TicTacToe2.kt | 96 +++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+)
 create mode 100644 89_Tic-Tac-Toe/kotlin/Board.kt
 create mode 100644 89_Tic-Tac-Toe/kotlin/README.md
 create mode 100644 89_Tic-Tac-Toe/kotlin/TicTacToe2.kt

diff --git a/89_Tic-Tac-Toe/kotlin/Board.kt b/89_Tic-Tac-Toe/kotlin/Board.kt
new file mode 100644
index 00000000..287a8d37
--- /dev/null
+++ b/89_Tic-Tac-Toe/kotlin/Board.kt
@@ -0,0 +1,80 @@
+/**
+ * @author John Long based on Java by Ollie Hensman-Crook
+ */
+
+enum class Player(val char: Char) {
+    X('X'),
+    O('O')
+}
+
+class Board {
+    // Initialize an array of size nine with all values set to null
+    private var boxes: Array = arrayOfNulls(9)
+
+    /**
+     * Place 'X' or 'O' on the board position passed
+     * @param position
+     * @param player
+     */
+    fun setArr(position: Int, player: Player) {
+        boxes[position - 1] = player
+    }
+
+    fun printBoard() {
+        System.out.format(
+            """
+  %c !  %c !  %c
+----+----+----
+  %c !  %c !  %c
+----+----+----
+  %c !  %c !  %c
+""",
+            // converts each box to a char and then passes them in order to format
+            // If the person is unassigned, use a space ' '
+     *(boxes.map{it?.char ?: ' '}.toTypedArray()))
+    }
+
+    /**
+     * @param x
+     * @return the value of the char at a given position
+     */
+    fun getBoardValue(x: Int): Player? {
+        return boxes[x - 1]
+    }
+
+    private val winningCombos = listOf(
+        // horizontal
+        listOf(0,1,2),
+        listOf(3,4,5),
+        listOf(6,7,8),
+        // diagonal
+        listOf(0,4,8),
+        listOf(2,4,6),
+        // vertical
+        listOf(0,3,6),
+        listOf(1,4,7),
+        listOf(2,5,8)
+    )
+    /**
+     * Go through the board and check for win
+     * @param player
+     * @return whether a win has occurred
+     */
+    fun isWinFor(player: Player): Boolean {
+        // Check if any winningCombos have all their boxes set to player
+        return winningCombos.any{ combo ->
+            combo.all { boxes[it] == player }
+        }
+    }
+
+    fun isDraw(): Boolean {
+        return !isWinFor(Player.X) && !isWinFor(Player.O) && boxes.all { it != null }
+    }
+
+    /**
+     * Reset the board
+     */
+    fun clear() {
+        boxes = arrayOfNulls(9)
+    }
+}
\ No newline at end of file
diff --git a/89_Tic-Tac-Toe/kotlin/README.md b/89_Tic-Tac-Toe/kotlin/README.md
new file mode 100644
index 00000000..f43a5b70
--- /dev/null
+++ b/89_Tic-Tac-Toe/kotlin/README.md
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Kotlin](https://kotlinlang.org/)
diff --git a/89_Tic-Tac-Toe/kotlin/TicTacToe2.kt b/89_Tic-Tac-Toe/kotlin/TicTacToe2.kt
new file mode 100644
index 00000000..389174f0
--- /dev/null
+++ b/89_Tic-Tac-Toe/kotlin/TicTacToe2.kt
@@ -0,0 +1,96 @@
+import java.util.Random
+import kotlin.system.exitProcess
+
+/**
+ * @author John Long based on Java from Ollie Hensman-Crook
+ */
+private val compChoice = Random()
+private val gameBoard = Board()
+
+fun main() {
+    println("              TIC-TAC-TOE")
+    println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    println("\nTHE BOARD IS NUMBERED: ")
+    println(" 1  2  3\n 4  5  6\n 7  8  9\n")
+    while (true) {
+        // Let the player choose whether to be X or O (Player.X or Player.O)
+        val (human, computer) = readXOrO()
+        while (true) {
+            // Get a valid move from the user and then move there
+            val validMoveIndex = readValidMove()
+            gameBoard.setArr(validMoveIndex, human)
+            gameBoard.printBoard()
+
+            // Computer randomly fills a square (if the game isn't already over)
+            // This uses Kotlin's null handling and will only set the board
+            // if validRandomMove returned a non-null value
+            validRandomMove()?.let {
+                gameBoard.setArr(it, computer)
+                gameBoard.printBoard()
+            }
+
+            // if there is a win print if player won or the computer won and ask if they
+            // want to play again
+            when {
+                gameBoard.isWinFor(human) -> {
+                    checkPlayAgain("YOU WIN")
+                    break
+                }
+                gameBoard.isWinFor(computer) -> {
+                    checkPlayAgain("YOU LOSE")
+                    break
+                }
+                gameBoard.isDraw() -> {
+                    checkPlayAgain("DRAW")
+                    break
+                }
+            }
+        }
+    }
+}
+
+private fun checkPlayAgain(result: String) {
+    println("$result, PLAY AGAIN? (Y/N)")
+    gameBoard.clear()
+    if (!readYesOrNo()) exitProcess(0)
+}
+
+private fun readYesOrNo(): Boolean {
+    while (true) {
+        when (readLine()?.get(0)?.uppercaseChar()) {
+            'Y' -> return true
+            'N' -> return false
+            else -> println("THAT'S NOT 'Y' OR 'N', TRY AGAIN")
+        }
+    }
+}
+
+private fun validRandomMove(): Int? {
+    if (gameBoard.isDraw() || gameBoard.isWinFor(Player.O) || gameBoard.isWinFor(Player.X)) return null
+    println("THE COMPUTER MOVES TO")
+    // keep generating a random value until we find one that is null (unset)
+    return generateSequence { 1 + compChoice.nextInt(9) }.first { gameBoard.getBoardValue(it) == null }
+}
+
+private fun readValidMove(): Int {
+    println("WHERE DO YOU MOVE")
+    while (true) {
+        val input = readln().toIntOrNull()
+        if (input != null && gameBoard.getBoardValue(input) == null) {
+            return input
+        } else {
+            println("INVALID INPUT, TRY AGAIN")
+        }
+    }
+}
+
+private fun readXOrO(): Pair {
+    println("DO YOU WANT 'X' OR 'O'")
+    while (true) {
+        when (readln()[0].uppercaseChar()) {
+            'X' -> return Player.X to Player.O
+            'O' -> return Player.O to Player.X
+            else -> println("THAT'S NOT 'X' OR 'O', TRY AGAIN")
+        }
+    }
+}

From 39ba8f21a6a26b1c3f6f43d3e2c83f05eef32b46 Mon Sep 17 00:00:00 2001
From: John Long 
Date: Sat, 1 Jan 2022 21:21:39 -0800
Subject: [PATCH 469/749] Kotlin version of HiLow

---
 47_Hi-Lo/kotlin/HiLo.kt   | 50 +++++++++++++++++++++++++++++++++++++++
 47_Hi-Lo/kotlin/README.md |  3 +++
 2 files changed, 53 insertions(+)
 create mode 100644 47_Hi-Lo/kotlin/HiLo.kt
 create mode 100644 47_Hi-Lo/kotlin/README.md

diff --git a/47_Hi-Lo/kotlin/HiLo.kt b/47_Hi-Lo/kotlin/HiLo.kt
new file mode 100644
index 00000000..7c4b6b65
--- /dev/null
+++ b/47_Hi-Lo/kotlin/HiLo.kt
@@ -0,0 +1,50 @@
+
+fun main() {
+    println(introText)
+    var winnings = 0
+    do {
+        winnings += playGame()
+        println("YOUR TOTAL WINNINGS ARE NOW $winnings DOLLARS")
+    } while(playAgain())
+    
+    println("SO LONG.  HOPE YOU ENJOYED YOURSELF!!!")
+}
+
+fun playGame():Int {
+    val amount = (1..100).random()
+    repeat(6) {
+        println("YOUR GUESS")
+        val guess = readln().toInt()
+        when {
+            guess == amount -> {
+                println("GOT IT!!!!!!!! YOU WIN $amount DOLLARS.")
+                return amount
+            }
+            guess > amount -> println("YOUR GUESS IS TOO HIGH")
+            else -> println("YOUR GUESS IS TOO LOW")
+        }
+    }
+    println("YOU BLEW IT...TOO BAD...THE NUMBER WAS $amount")
+    return 0
+}
+
+fun playAgain():Boolean {
+    println("PLAY AGAIN (YES OR NO)")
+    return readLine()?.uppercase() == "YES"
+}
+
+
+val introText = """
+    HI LO
+    CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY
+    
+    
+    THIS IS THE GAME OF HI LO.
+    
+    YOU WILL HAVE 6 TRIES TO GUESS THE AMOUNT OF MONEY IN THE
+    HI LO JACKPOT, WHICH IS BETWEEN 1 AND 100 DOLLARS.  IF YOU
+    GUESS THE AMOUNT, YOU WIN ALL THE MONEY IN THE JACKPOT!
+    THEN YOU GET ANOTHER CHANCE TO WIN MORE MONEY.  HOWEVER,
+    IF YOU DO NOT GUESS THE AMOUNT, THE GAME ENDS
+
+""".trimIndent()
\ No newline at end of file
diff --git a/47_Hi-Lo/kotlin/README.md b/47_Hi-Lo/kotlin/README.md
new file mode 100644
index 00000000..f43a5b70
--- /dev/null
+++ b/47_Hi-Lo/kotlin/README.md
@@ -0,0 +1,3 @@
+Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
+
+Conversion to [Kotlin](https://kotlinlang.org/)

From 07aab1b4913dd2f18c41db7bda0d1d36dfbef09f Mon Sep 17 00:00:00 2001
From: Pat Ludwig 
Date: Sat, 1 Jan 2022 23:33:18 -0600
Subject: [PATCH 470/749] Add perl version of Change

Used my own "perlified" logic instead of the original.
Added proper handling of plurals, other than that the
text should be identical
---
 22_Change/perl/change.pl | 68 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
 create mode 100755 22_Change/perl/change.pl

diff --git a/22_Change/perl/change.pl b/22_Change/perl/change.pl
new file mode 100755
index 00000000..51813cd8
--- /dev/null
+++ b/22_Change/perl/change.pl
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+
+use v5.24; # for say and use strict
+use warnings;
+
+sub get_pennies {
+  my $query = shift;
+
+  print "$query? ";
+  my $in = <>;
+  chomp $in;
+  $in =~ /([\d.]+)/; # the first match of digits and decimal points
+  return int( $1 * 100 );
+}
+
+sub make_change {
+  my $change = shift;
+
+  state %change_options = (
+    'Penny' => { value => 1, plural => 'Pennies' },
+    'Nickel' => { value => 5 },
+    'Dime' => { value => 10 },
+    'Quarter' => { value => 25 },
+    'One Half Dollar' => { value => 50 },
+    'One Dollar Bill' => { value => 100 * 1 },
+    'Five Dollar Bill' => { value => 100 * 5 },
+    '10 Dollar Bill' => { value => 100 * 10 },
+  );
+
+  foreach my $unit ( sort { $change_options{$b}->{value} <=> $change_options{$a}->{value} } keys %change_options ) {
+    my $value = $change_options{$unit}->{value};
+    next if $value > $change;
+    my $number = int( $change / $value );
+    if ( $number > 1 ) {
+      $unit = exists $change_options{$unit}->{plural} ? $change_options{$unit}->{plural} : "${unit}s";
+    }
+    say "$number $unit";
+    $change -= $number * $value;
+  }
+}
+
+print <<'__END_OF_INTRO';
+                              Change
+               Creative Computing  Morristown, New Jersey
+
+
+I, Your friendly microcomputer, will determine
+the correct change for items costing up to $100.
+
+
+__END_OF_INTRO
+
+while ( 1 ) {
+  my $cost = get_pennies( 'Cost of item' );
+  my $payment = get_pennies( 'Amount of payment');
+
+  my $change = $payment - $cost;
+  my $change_formatted = sprintf( "%.2f", $change / 100 );
+  if ( $change == 0 ) {
+    say 'Correct amount, thank you.';
+  } elsif ( $change < 0 ) {
+    say 'Sorry, you have short-changed me $', abs($change_formatted);
+  } else {
+    say 'Your change, $', $change_formatted;
+    make_change( $change );
+    say "Thank you, come again\n\n";
+  }
+}

From c8577707a18de2ea30f79d425ae0ccd821a7801c Mon Sep 17 00:00:00 2001
From: Pat Ludwig 
Date: Sun, 2 Jan 2022 00:25:54 -0600
Subject: [PATCH 471/749] Don't give away the answer

- remove correct answer from prompt
- matched leading spacing to original
- fixed original misspelling of how
- moved file into perl subdirectory
- fixed randomization of acid quanity to 1-50
  instead of 0-49
- fixed indenting issues
---
 .../{perlchemist.pl => perl/chemist.pl}       | 24 +++++++++----------
 1 file changed, 12 insertions(+), 12 deletions(-)
 rename 24_Chemist/{perlchemist.pl => perl/chemist.pl} (50%)

diff --git a/24_Chemist/perlchemist.pl b/24_Chemist/perl/chemist.pl
similarity index 50%
rename from 24_Chemist/perlchemist.pl
rename to 24_Chemist/perl/chemist.pl
index 01ed9f02..9f75bfac 100755
--- a/24_Chemist/perlchemist.pl
+++ b/24_Chemist/perl/chemist.pl
@@ -8,30 +8,30 @@ print "THE FICTITIOUS CHECMICAL KRYPTOCYANIC ACID CAN ONLY BE\n";
 print "DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID.\n";
 print "IF ANY OTHER RATIO IS ATTEMPTED, THE ACID BECOMES UNSTABLE\n";
 print "AND SOON EXPLODES. GIVEN THE AMOUNT OF ACID, YOU MUST\n";
-print "DECIDE WHO MUCH WATER TO ADD FOR DILUTION. IF YOU MISS\n";
+print "DECIDE HOW MUCH WATER TO ADD FOR DILUTION. IF YOU MISS\n";
 print "YOU FACE THE CONSEQUENCES.\n";
 
 my $T=0;
 while ($T<9) {
-	my $A= int(rand(1)*50);
+	my $A= int(rand(50) + 1);
 	my $W= 7*$A/3;
-	print "$A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER ($W)";
-	print "? "; chomp(my $R = );
+	print " $A LITERS OF KRYPTOCYANIC ACID. HOW MUCH WATER? ";
+	chomp(my $R = );
 	my $D= abs($W-$R);
 	if ($D>$W/20) {
-		print " SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
-		print " OF QUIVERING PROTOPLASM!\n";
-		print " HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
+		print "SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB\n";
+		print "OF QUIVERING PROTOPLASM!\n";
+		print "HOWEVER, YOU MAY TRY AGAIN WITH ANOTHER LIFE.\n";
 		print "\n";
 		$T++;
-		} else {
-		print " GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
+	} else {
+		print "GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n";
 		print "\n";
-		}
 	}
+}
 
-print " YOUR 9 LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR\n";
-print " YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.\n";
+print "YOUR 9 LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR\n";
+print "YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.\n";
 exit;
 
 

From c3e1f309b92652eff93c5d688b2b7c7effcacb15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20Brox=20R=C3=B8st?= 
Date: Sun, 2 Jan 2022 12:20:27 +0100
Subject: [PATCH 472/749] Added Python 3 version of 29, craps.

---
 29_Craps/python/craps.py | 79 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)
 create mode 100644 29_Craps/python/craps.py

diff --git a/29_Craps/python/craps.py b/29_Craps/python/craps.py
new file mode 100644
index 00000000..38faeed3
--- /dev/null
+++ b/29_Craps/python/craps.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+"""This game simulates the games of craps played according to standard Nevada craps table rules.
+
+That is:
+
+1. A 7 or 11 on the first roll wins
+2. A 2, 3, or 12 on the first roll loses
+3. Any other number rolled becomes your "point." You continue to roll; if you get your point you win. If you
+   roll a 7, you lose and the dice change hands when this happens.
+
+This version of craps was modified by Steve North of Creative Computing. It is based on an original which
+appeared one day one a computer at DEC.
+"""
+from random import randint
+
+
+def throw_dice():
+    return randint(1, 6) + randint(1, 6)
+
+
+print(" " * 33 + "Craps")
+print(" " * 15 + "Creative Computing  Morristown, New Jersey")
+print()
+print()
+print()
+
+winnings = 0
+print("2,3,12 are losers; 4,5,6,8,9,10 are points; 7,11 are natural winners.")
+
+play_again = True
+while play_again:
+    wager = int(input("Input the amount of your wager: "))
+
+    print("I will now throw the dice")
+    roll_1 = throw_dice()
+
+    if roll_1 in [7, 11]:
+        print(f"{roll_1} - natural.... a winner!!!!")
+        print(f"{roll_1} pays even money, you win {wager} dollars")
+        winnings += wager
+    elif roll_1 == 2:
+        print(f"{roll_1} - snake eyes.... you lose.")
+        print(f"You lose {wager} dollars")
+        winnings -= wager
+    elif roll_1 in [3, 12]:
+        print(f"{roll_1} - craps.... you lose.")
+        print(f"You lose {wager} dollars")
+        winnings -= wager
+    else:
+        print(f"{roll_1} is the point. I will roll again")
+        roll_2 = 0
+        while roll_2 not in [roll_1, 7]:
+            roll_2 = throw_dice()
+            if roll_2 == 7:
+                print(f"{roll_2} - craps. You lose.")
+                print(f"You lose $ {wager}")
+                winnings -= wager
+            elif roll_2 == roll_1:
+                print(f"{roll_1} - a winner.........congrats!!!!!!!!")
+                print(f"{roll_1} at 2 to 1 odds pays you...let me see... {2 * wager} dollars")
+                winnings += 2 * wager
+            else:
+                print(f"{roll_2} - no point. I will roll again")
+
+    m = input("  If you want to play again print 5 if not print 2: ")
+    if winnings < 0:
+        print(f"You are now under ${-winnings}")
+    elif winnings > 0:
+        print(f"You are now ahead ${winnings}")
+    else:
+        print("You are now even at 0")
+    play_again = (m == "5")
+
+if winnings < 0:
+    print(f"Too bad, you are in the hole. Come again.")
+elif winnings > 0:
+    print(f"Congratulations---you came out a winner. Come again.")
+else:
+    print(f"Congratulations---you came out even, not bad for an amateur")

From 65a86f7d6da8b9ee9491690a1ecc5e978048e813 Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 13:04:39 +0100
Subject: [PATCH 473/749] Added Header

---
 22_Change/csharp/Change.csproj |  8 ++++++++
 22_Change/csharp/Change.sln    | 25 +++++++++++++++++++++++++
 22_Change/csharp/Program.cs    | 25 +++++++++++++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 22_Change/csharp/Change.csproj
 create mode 100644 22_Change/csharp/Change.sln
 create mode 100644 22_Change/csharp/Program.cs

diff --git a/22_Change/csharp/Change.csproj b/22_Change/csharp/Change.csproj
new file mode 100644
index 00000000..1d2d39a9
--- /dev/null
+++ b/22_Change/csharp/Change.csproj
@@ -0,0 +1,8 @@
+
+
+  
+    Exe
+    net5.0
+  
+
+
diff --git a/22_Change/csharp/Change.sln b/22_Change/csharp/Change.sln
new file mode 100644
index 00000000..c0f2e5e8
--- /dev/null
+++ b/22_Change/csharp/Change.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.810.16
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Change", "Change.csproj", "{AE094667-8496-4ECF-8B42-B1648EE26073}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{AE094667-8496-4ECF-8B42-B1648EE26073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AE094667-8496-4ECF-8B42-B1648EE26073}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AE094667-8496-4ECF-8B42-B1648EE26073}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AE094667-8496-4ECF-8B42-B1648EE26073}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {65684CBD-CD74-46AF-8E9E-0F69DCF72697}
+	EndGlobalSection
+EndGlobal
diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
new file mode 100644
index 00000000..c8adbeac
--- /dev/null
+++ b/22_Change/csharp/Program.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Change
+{
+    class Program
+    {
+        static void Header()
+        {
+            Console.WriteLine("Change".PadLeft(33));
+            Console.WriteLine("Creative Computing Morristown, New Jersey".PadLeft(15));
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine();
+            Console.WriteLine("I, your friendly microcomputer, will determine\n"
+            + "the correct change for items costing up to $100.");
+            Console.WriteLine();
+            Console.WriteLine();
+        }
+
+        static void Main(string[] args)
+        {
+            Header();
+        }
+    }
+}

From 6c0b0da270d7da4b8e9532f6837c65b74e60dd94 Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 13:29:27 +0100
Subject: [PATCH 474/749] Added GetInput

---
 22_Change/csharp/Program.cs | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
index c8adbeac..2c28ea99 100644
--- a/22_Change/csharp/Program.cs
+++ b/22_Change/csharp/Program.cs
@@ -17,9 +17,43 @@ namespace Change
             Console.WriteLine();
         }
 
+        static (bool, double) GetInput()
+        {
+            Console.WriteLine("Cost of item? ");
+            var priceString = Console.ReadLine();
+            if (!double.TryParse(priceString, out double price))
+            {
+                Console.WriteLine($"{priceString} isn't a number!");
+                return (false, 0);
+            }
+
+            Console.WriteLine("Amount of payment? ");
+            var paymentString = Console.ReadLine();
+            if (!double.TryParse(paymentString, out double payment))
+            {
+                Console.WriteLine($"{paymentString} isn't a number!");
+                return (false, 0);
+            }
+
+            return (true, payment - price);
+        }
+
         static void Main(string[] args)
         {
             Header();
+
+            while (true)
+            {
+                (bool result, double change) = GetInput();
+                if (!result)
+                    continue;
+
+                if (change == 0)
+                {
+                    Console.WriteLine("Correct amount, thank you!");
+                    continue;
+                }
+            }
         }
     }
 }

From d530794947e6341b72d155a80d014351f19231c1 Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 14:08:49 +0100
Subject: [PATCH 475/749] Added PrintChange

---
 22_Change/csharp/Program.cs | 65 ++++++++++++++++++++++++++++++++++---
 1 file changed, 60 insertions(+), 5 deletions(-)

diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
index 2c28ea99..b45e5114 100644
--- a/22_Change/csharp/Program.cs
+++ b/22_Change/csharp/Program.cs
@@ -17,14 +17,14 @@ namespace Change
             Console.WriteLine();
         }
 
-        static (bool, double) GetInput()
+        static (bool status, double price, double payment) GetInput()
         {
             Console.WriteLine("Cost of item? ");
             var priceString = Console.ReadLine();
             if (!double.TryParse(priceString, out double price))
             {
                 Console.WriteLine($"{priceString} isn't a number!");
-                return (false, 0);
+                return (false, 0, 0);
             }
 
             Console.WriteLine("Amount of payment? ");
@@ -32,10 +32,53 @@ namespace Change
             if (!double.TryParse(paymentString, out double payment))
             {
                 Console.WriteLine($"{paymentString} isn't a number!");
-                return (false, 0);
+                return (false, 0, 0);
             }
 
-            return (true, payment - price);
+            return (true, price, payment);
+        }
+
+        static void PrintChange(double change)
+        {
+            var tens = (int)(change / 10);
+            if (tens > 0)
+                Console.WriteLine($"{tens} ten dollar bill(s)");
+
+            var temp = change - (tens * 10);
+            var fives = (int)(temp / 5);
+            if (fives > 0)
+                Console.WriteLine($"{fives} five dollar bill(s)");
+
+            temp -= fives * 5;
+            var ones = (int)temp;
+            if (ones > 0)
+                Console.WriteLine($"{ones} one dollar bill(s)");
+
+            temp -= ones;
+            var cents = temp * 100;
+            var half = (int)(cents / 50);
+            if (half > 0)
+                Console.WriteLine($"{half} one half dollar(s)");
+
+            temp = cents - (half * 50);
+            var quarters = (int)(temp / 25);
+            if (quarters > 0)
+                Console.WriteLine($"{quarters} quarter(s)");
+
+            temp -= quarters * 25;
+            var dimes = (int)(temp / 10);
+            if (dimes > 0)
+                Console.WriteLine($"{dimes} dime(s)");
+
+            temp -= dimes * 10;
+            var nickels = (int)(temp / 5);
+            if (nickels > 0)
+                Console.WriteLine($"{nickels} nickel(s)");
+
+            temp -= nickels * 5;
+            var pennys = (int)(temp + 0.5);
+            if (pennys > 0)
+                Console.WriteLine($"{pennys} penny(s)");
         }
 
         static void Main(string[] args)
@@ -44,15 +87,27 @@ namespace Change
 
             while (true)
             {
-                (bool result, double change) = GetInput();
+                (bool result, double price, double payment) = GetInput();
                 if (!result)
                     continue;
 
+                var change = payment - price;
                 if (change == 0)
                 {
                     Console.WriteLine("Correct amount, thank you!");
                     continue;
                 }
+
+                if (change < 0)
+                {
+                    Console.WriteLine($"Sorry, you have short-changed me ${price - payment}!");
+                    continue;
+                }
+
+                Console.WriteLine($"Your change ${change:N2}");
+                PrintChange(change);
+                Console.WriteLine("Thank you, come again!");
+                Console.WriteLine();
             }
         }
     }

From 835adc571c68cf9b828ea7e81bdc4749d7d844a2 Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 14:22:37 +0100
Subject: [PATCH 476/749] Format

---
 22_Change/csharp/Program.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
index b45e5114..3b609d9d 100644
--- a/22_Change/csharp/Program.cs
+++ b/22_Change/csharp/Program.cs
@@ -100,7 +100,7 @@ namespace Change
 
                 if (change < 0)
                 {
-                    Console.WriteLine($"Sorry, you have short-changed me ${price - payment}!");
+                    Console.WriteLine($"Sorry, you have short-changed me ${price - payment:N2}!");
                     continue;
                 }
 

From 534fa866bdbb927c09861d87e2a9748ccc1c5335 Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 14:29:11 +0100
Subject: [PATCH 477/749] Added some descriptions

---
 22_Change/csharp/Program.cs | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
index 3b609d9d..b57e45e3 100644
--- a/22_Change/csharp/Program.cs
+++ b/22_Change/csharp/Program.cs
@@ -4,6 +4,9 @@ namespace Change
 {
     class Program
     {
+        /// 
+        /// Prints header.
+        /// 
         static void Header()
         {
             Console.WriteLine("Change".PadLeft(33));
@@ -17,6 +20,14 @@ namespace Change
             Console.WriteLine();
         }
 
+        /// 
+        /// Gets user input for price and payment.
+        /// 
+        /// 
+        /// False if any input can't be parsed to double. Price and payment returned would be 0.
+        /// True if it was possible to parse inputs into doubles. Price and payment returned 
+	    /// would be as provided by the user.
+	    /// 
         static (bool status, double price, double payment) GetInput()
         {
             Console.WriteLine("Cost of item? ");
@@ -38,6 +49,10 @@ namespace Change
             return (true, price, payment);
         }
 
+        /// 
+        /// Prints bills and coins for given change.
+        /// 
+        /// 
         static void PrintChange(double change)
         {
             var tens = (int)(change / 10);

From 64682e704cf5f4bc9fa26eacf46795b3bd125b28 Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 14:36:33 +0100
Subject: [PATCH 478/749] Spelling

---
 22_Change/csharp/Program.cs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
index b57e45e3..b7496b0f 100644
--- a/22_Change/csharp/Program.cs
+++ b/22_Change/csharp/Program.cs
@@ -91,9 +91,9 @@ namespace Change
                 Console.WriteLine($"{nickels} nickel(s)");
 
             temp -= nickels * 5;
-            var pennys = (int)(temp + 0.5);
-            if (pennys > 0)
-                Console.WriteLine($"{pennys} penny(s)");
+            var pennies = (int)(temp + 0.5);
+            if (pennies > 0)
+                Console.WriteLine($"{pennies} penny(s)");
         }
 
         static void Main(string[] args)

From b27ee11d0076687d4462312076516e6e8093d3ef Mon Sep 17 00:00:00 2001
From: Piotr Czajkowski 
Date: Sun, 2 Jan 2022 14:50:51 +0100
Subject: [PATCH 479/749] Input closer to original

---
 22_Change/csharp/Program.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/22_Change/csharp/Program.cs b/22_Change/csharp/Program.cs
index b7496b0f..12804731 100644
--- a/22_Change/csharp/Program.cs
+++ b/22_Change/csharp/Program.cs
@@ -30,7 +30,7 @@ namespace Change
 	    /// 
         static (bool status, double price, double payment) GetInput()
         {
-            Console.WriteLine("Cost of item? ");
+            Console.Write("Cost of item? ");
             var priceString = Console.ReadLine();
             if (!double.TryParse(priceString, out double price))
             {
@@ -38,7 +38,7 @@ namespace Change
                 return (false, 0, 0);
             }
 
-            Console.WriteLine("Amount of payment? ");
+            Console.Write("Amount of payment? ");
             var paymentString = Console.ReadLine();
             if (!double.TryParse(paymentString, out double payment))
             {

From 83458c428e2bc36cf5a245469e9613d68ab5a109 Mon Sep 17 00:00:00 2001
From: mattbloke99 
Date: Sun, 2 Jan 2022 14:21:30 +0000
Subject: [PATCH 480/749] Train game with tests

---
 91_Train/csharp/Train/Train.sln               | 31 +++++++
 91_Train/csharp/Train/Train/TrainGame.cs      | 93 +++++++++++++++++++
 91_Train/csharp/Train/Train/TrainGame.csproj  |  8 ++
 .../TrainTests/TrainTests/TrainGameTests.cs   | 53 +++++++++++
 .../TrainTests/TrainTests/TrainTests.csproj   | 26 ++++++
 5 files changed, 211 insertions(+)
 create mode 100644 91_Train/csharp/Train/Train.sln
 create mode 100644 91_Train/csharp/Train/Train/TrainGame.cs
 create mode 100644 91_Train/csharp/Train/Train/TrainGame.csproj
 create mode 100644 91_Train/csharp/TrainTests/TrainTests/TrainGameTests.cs
 create mode 100644 91_Train/csharp/TrainTests/TrainTests/TrainTests.csproj

diff --git a/91_Train/csharp/Train/Train.sln b/91_Train/csharp/Train/Train.sln
new file mode 100644
index 00000000..7735a737
--- /dev/null
+++ b/91_Train/csharp/Train/Train.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31129.286
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainGame", "Train\TrainGame.csproj", "{42617537-4E7C-4082-A17B-7F18DFA04C35}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainTests", "..\TrainTests\TrainTests\TrainTests.csproj", "{7C740A47-99C6-44E1-BDEE-140086BCFE8B}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{42617537-4E7C-4082-A17B-7F18DFA04C35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{42617537-4E7C-4082-A17B-7F18DFA04C35}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{42617537-4E7C-4082-A17B-7F18DFA04C35}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{42617537-4E7C-4082-A17B-7F18DFA04C35}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7C740A47-99C6-44E1-BDEE-140086BCFE8B}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {919F73B8-DE34-4992-9B05-E1FEC2D2F7C6}
+	EndGlobalSection
+EndGlobal
diff --git a/91_Train/csharp/Train/Train/TrainGame.cs b/91_Train/csharp/Train/Train/TrainGame.cs
new file mode 100644
index 00000000..98e0db68
--- /dev/null
+++ b/91_Train/csharp/Train/Train/TrainGame.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Linq;
+
+namespace Train
+{
+    public class TrainGame
+    {
+        private Random Rnd { get; } = new Random();
+        private readonly int ALLOWED_PERCENTAGE_DIFFERENCE = 5;
+
+        static void Main()
+        {
+            TrainGame train = new TrainGame();
+            train.GameLoop();
+        }
+
+        public void GameLoop()
+        {
+            DisplayIntroText();
+
+            do
+            {
+                PlayGame();
+            } while (TryAgain());
+        }
+
+        private void PlayGame()
+        {
+            int carSpeed = (int)GenerateRandomNumber(40, 25);
+            int timeDifference = (int)GenerateRandomNumber(5, 15);
+            int trainSpeed = (int)GenerateRandomNumber(20, 19);
+
+            Console.WriteLine($"A CAR TRAVELING {carSpeed} MPH CAN MAKE A CERTAIN TRIP IN");
+            Console.WriteLine($"{timeDifference} HOURS LESS THAN A TRAIN TRAVELING AT {trainSpeed} MPH");
+            Console.WriteLine("HOW LONG DOES THE TRIP TAKE BY CAR?");
+
+            double userInputCarJourneyDuration = double.Parse(Console.ReadLine());
+            double actualCarJourneyDuration = CalculateCarJourneyDuration(carSpeed, timeDifference, trainSpeed);
+            int percentageDifference = CalculatePercentageDifference(userInputCarJourneyDuration, actualCarJourneyDuration);
+
+            if (IsWithinAllowedDifference(percentageDifference, ALLOWED_PERCENTAGE_DIFFERENCE))
+            {
+                Console.WriteLine($"GOOD! ANSWER WITHIN {percentageDifference} PERCENT.");
+            }
+            else
+            {
+                Console.WriteLine($"SORRY.  YOU WERE OFF BY {percentageDifference} PERCENT.");
+            }
+            Console.WriteLine($"CORRECT ANSWER IS {actualCarJourneyDuration} HOURS.");
+        }
+
+        public static bool IsWithinAllowedDifference(int percentageDifference, int allowedDifference)
+        {
+            return percentageDifference <= allowedDifference;
+        }
+
+        private static int CalculatePercentageDifference(double userInputCarJourneyDuration, double carJourneyDuration)
+        {
+            return (int)(Math.Abs((carJourneyDuration - userInputCarJourneyDuration) * 100 / userInputCarJourneyDuration) + .5);
+        }
+
+        public static double CalculateCarJourneyDuration(double carSpeed, double timeDifference, double trainSpeed)
+        {
+            return timeDifference * trainSpeed / (carSpeed - trainSpeed);
+        }
+
+        public double GenerateRandomNumber(int baseSpeed, int multiplier)
+        {
+            return multiplier * Rnd.NextDouble() + baseSpeed;
+        }
+
+        private bool TryAgain()
+        {
+            Console.WriteLine("ANOTHER PROBLEM (YES OR NO)? ");
+            return IsInputYes(Console.ReadLine());
+        }
+
+        public static bool IsInputYes(string consoleInput)
+        {
+            var options = new string[] { "Y", "YES" };
+            return options.Any(o => o.Equals(consoleInput, StringComparison.CurrentCultureIgnoreCase));
+        }
+
+        private void DisplayIntroText()
+        {
+            Console.WriteLine("TRAIN");
+            Console.WriteLine("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+            Console.WriteLine();
+            Console.WriteLine("TIME - SPEED DISTANCE EXERCISE");
+            Console.WriteLine();
+        }
+    }
+}
diff --git a/91_Train/csharp/Train/Train/TrainGame.csproj b/91_Train/csharp/Train/Train/TrainGame.csproj
new file mode 100644
index 00000000..c73e0d16
--- /dev/null
+++ b/91_Train/csharp/Train/Train/TrainGame.csproj
@@ -0,0 +1,8 @@
+
+
+  
+    Exe
+    netcoreapp3.1
+  
+
+
diff --git a/91_Train/csharp/TrainTests/TrainTests/TrainGameTests.cs b/91_Train/csharp/TrainTests/TrainTests/TrainGameTests.cs
new file mode 100644
index 00000000..a9804283
--- /dev/null
+++ b/91_Train/csharp/TrainTests/TrainTests/TrainGameTests.cs
@@ -0,0 +1,53 @@
+using Train;
+using Xunit;
+
+namespace TrainTests
+{
+    public class TrainGameTests
+    {
+        [Fact]
+        public void MiniumRandomNumber()
+        {
+            TrainGame game = new TrainGame();
+            Assert.True(game.GenerateRandomNumber(10, 10) >= 10);
+        }
+
+        [Fact]
+        public void MaximumRandomNumber()
+        {
+            TrainGame game = new TrainGame();
+            Assert.True(game.GenerateRandomNumber(10, 10) <= 110);
+        }
+
+        [Fact]
+        public void IsInputYesWhenY()
+        {
+            Assert.True(TrainGame.IsInputYes("y"));
+        }
+
+        [Fact]
+        public void IsInputYesWhenNotY()
+        {
+            Assert.False(TrainGame.IsInputYes("a"));
+        }
+
+        [Fact]
+        public void CarDurationTest()
+        {
+            Assert.Equal(1, TrainGame.CalculateCarJourneyDuration(30, 1, 15) );
+        }
+
+        [Fact]
+        public void IsWithinAllowedDifference()
+        {
+            Assert.True(TrainGame.IsWithinAllowedDifference(5,5));
+        }
+
+
+        [Fact]
+        public void IsNotWithinAllowedDifference()
+        {
+            Assert.False(TrainGame.IsWithinAllowedDifference(6, 5));
+        }
+    }
+}
diff --git a/91_Train/csharp/TrainTests/TrainTests/TrainTests.csproj b/91_Train/csharp/TrainTests/TrainTests/TrainTests.csproj
new file mode 100644
index 00000000..a8de6dde
--- /dev/null
+++ b/91_Train/csharp/TrainTests/TrainTests/TrainTests.csproj
@@ -0,0 +1,26 @@
+
+
+  
+    netcoreapp3.1
+
+    false
+  
+
+  
+    
+    
+    
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+      all
+    
+    
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+      all
+    
+  
+
+  
+    
+  
+
+

From daea544c5f3ef1ee496617de7b7cd0193107df92 Mon Sep 17 00:00:00 2001
From: aviyam 
Date: Sun, 2 Jan 2022 17:14:56 +0200
Subject: [PATCH 481/749] AceyDucey in python, OO implementation. More verbose
 then original game with a 'what would have happened' addition.

---
 01_Acey_Ducey/python/acey_ducey_oo.py | 125 ++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)
 create mode 100644 01_Acey_Ducey/python/acey_ducey_oo.py

diff --git a/01_Acey_Ducey/python/acey_ducey_oo.py b/01_Acey_Ducey/python/acey_ducey_oo.py
new file mode 100644
index 00000000..d8b7c752
--- /dev/null
+++ b/01_Acey_Ducey/python/acey_ducey_oo.py
@@ -0,0 +1,125 @@
+#
+# AceyDuchy
+#
+# From: BASIC Computer Games (1978)
+#       Edited by David Ahl
+#
+# "The original BASIC program author was Bill Palmby
+#  of Prairie View, Illinois."
+#
+# Python port by Aviyam Fischer, 2022
+#
+######################################################
+
+class Card:
+    def __init__(self, suit, rank):
+        self.suit = suit
+        self.rank = rank
+
+    def __str__(self):
+        r = self.rank
+        if r == 11:
+            r = 'J'
+        elif r == 12:
+            r = 'Q'
+        elif r == 13:
+            r = 'K'
+        elif r == 14:
+            r = 'A'
+        return f'{r}{self.suit}'
+
+
+class Deck:
+    def __init__(self):
+        self.cards = []
+        self.build()
+
+    def build(self):
+        for suit in ['\u2665', '\u2666', '\u2663', '\u2660']:
+            for rank in range(1, 14):
+                self.cards.append(Card(suit, rank))
+
+    def shuffle(self):
+        import random
+        random.shuffle(self.cards)
+
+    def deal(self):
+        return self.cards.pop()
+
+
+class Game:
+    def __init__(self):
+        self.deck = Deck()
+        self.deck.shuffle()
+        self.card_a = self.deck.deal()
+        self.card_b = self.deck.deal()
+        self.money = 100
+        self.not_done = True
+
+    def play(self):
+        while self.not_done:
+            while self.money > 0:
+                card_a = self.card_a
+                card_b = self.card_b
+
+                if card_a.rank > card_b.rank:
+                    card_a, card_b = card_b, card_a
+
+                if card_a.rank == card_b.rank:
+                    self.card_b = self.deck.deal()
+                    card_b = self.card_b
+
+                print(f'You have:\t ${self.money} ')
+                print(f'Your cards:\t {card_a} {card_b}')
+
+                bet = int(input('What is your bet? '))
+                player_card = self.deck.deal()
+                if 0 < bet <= self.money:
+
+                    print(f'Your deal:\t {player_card}')
+                    if card_a.rank < player_card.rank < card_b.rank:
+                        print('You Win!')
+                        self.money += bet
+                    else:
+                        print('You Lose!')
+                        self.money -= bet
+                        self.not_done = False
+                else:
+                    print('Chicken!')
+                    print(f'Your deal should have been: {player_card}')
+                    if card_a.rank < player_card.rank < card_b.rank:
+                        print(f'You could have won!')
+                    else:
+                        print(f'You would lose, so it was wise of you to chicken out!')
+
+                    self.not_done = False
+                    break
+
+                if len(self.deck.cards) <= 1:
+                    print('You ran out of cards. Game over.')
+                    self.not_done = False
+                    break
+
+        if self.money == 0:
+            self.not_done = False
+
+
+if __name__ == '__main__':
+    print(''' 
+    Acey Ducey is a card game where you play against the computer.
+    The Dealer(computer) will deal two cards facing up.
+    You have an option to bet or not bet depending on whether or not you 
+    feel the card will have a value between the first two.
+    If you do not want to bet input a 0
+    ''')
+    GAME_OVER = False
+
+    while not GAME_OVER:
+        game = Game()
+        game.play()
+        print(f'You have ${game.money} left')
+        print('Would you like to play again? (y/n)')
+        if input() == 'n':
+            GAME_OVER = True
+
+    print('\nThanks for playing!')

From 72874ef47f600f98dd07bf11ef69303379545f5a Mon Sep 17 00:00:00 2001
From: Jan Jitse 
Date: Sun, 2 Jan 2022 16:33:13 +0100
Subject: [PATCH 482/749] Implement FlipFlop in Python

---
 36_Flip_Flop/python/flipflop.py | 129 ++++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)
 create mode 100644 36_Flip_Flop/python/flipflop.py

diff --git a/36_Flip_Flop/python/flipflop.py b/36_Flip_Flop/python/flipflop.py
new file mode 100644
index 00000000..9b6e2323
--- /dev/null
+++ b/36_Flip_Flop/python/flipflop.py
@@ -0,0 +1,129 @@
+# Flip Flop
+#
+# The object of this game is to change a row of ten X's
+# X X X X X X X X X X
+# to a row of ten O's:
+# O O O O O O O O O O
+# by typing in a number corresponding
+# to the position of an "X" in the line. On
+# some numbers one position will
+# change while on other numbers, two
+# will change. For example, inputting a 3
+# may reverse the X and O in position 3,
+# but it might possibly reverse some
+# other position too! You ought to be able
+# to change all 10 in 12 or fewer
+# moves. Can you figure out a good win-
+# ning strategy?
+# To reset the line to all X's (same
+# game), type 0 (zero). To start a new
+# game at any point, type 11.
+# The original author of this game was
+# Michael Kass of New Hyde Park, New
+# York.
+import random
+import math
+from typing import Callable, List, Tuple
+
+flip_dict = {"X": "O", "O": "X"}
+
+
+def flip_bits(
+    row: List[str], m: int, n: int, r_function: Callable[[int], float]
+) -> Tuple[List[str], int]:
+    """
+    Function that flips the positions at the computed steps
+    """
+    while m == n:
+        r = r_function(n)
+        n = r - int(math.floor(r))
+        n = int(10 * n)
+        if row[n] == "X":
+            row[n] = "O"
+            break
+        elif row[n] == "O":
+            row[n] = "X"
+    return row, n
+
+
+def print_instructions():
+    print(" " * 32 + "FLIPFLOP")
+    print(" " * 15 + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+    print("\n" * 2)
+    print("THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:\n")
+    print("X X X X X X X X X X\n")
+    print("TO THIS:\n")
+    print("O O O O O O O O O O\n")
+    print("BY TYPING TH NUMBER CORRESPONDING TO THE POSITION OF THE")
+    print("LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON")
+    print("OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0")
+    print("(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE ")
+    print("11 (ELEVEN).\n")
+
+
+def main():
+    q = random.random()
+
+    print("HERE IS THE STARTING LINE OF X'S.\n")
+    # We add an extra 0-th item because this sometimes is set to something
+    # but we never check what it is for completion of the puzzle
+    row = [""] + ["X"] * 10
+    counter_turns = 0
+    n = -1
+    legal_move = True
+    while row[1:] != ["O"] * 10:
+        if legal_move:
+            print(" ".join([str(i) for i in range(1, 11)]))
+            print(" ".join(row[1:]) + "\n")
+        m = input("INPUT THE NUMBER\n")
+        try:
+            m = int(m)
+            if m > 11 or m < 0:
+                raise ValueError()
+        except ValueError:
+            print("ILLEGAL ENTRY--TRY AGAIN")
+            legal_move = False
+            continue
+        legal_move = True
+        if m == 11:
+            # completely reset the puzzle
+            counter_turns = 0
+            row = [""] + ["X"] * 10
+            q = random.random()
+            continue
+        elif m == 0:
+            # reset the board, but not the counter or the random number
+            row = [""] + ["X"] * 10
+        elif m == n:
+            row[n] = flip_dict[row[n]]
+            r_function = lambda n_t: 0.592 * (1 / math.tan(q / n_t + q)) / math.sin(
+                n_t * 2 + q
+            ) - math.cos(n_t)
+            row, n = flip_bits(row, m, n, r_function)
+        else:
+            n = m
+            row[n] = flip_dict[row[n]]
+            r_function = lambda n_t: (
+                math.tan(q + n_t / q - n_t)
+                - math.sin(n_t * 2 + q)
+                + 336 * math.sin(8 * n_t)
+            )
+            row, n = flip_bits(row, m, n, r_function)
+
+        counter_turns += 1
+        print()
+
+    if counter_turns <= 12:
+        print(f"VERY GOOD. YOU GUESSED IT IN ONLY {counter_turns} GUESSES.")
+    else:
+        print(f"TRY HARDER NEXT TIME. IT TOOK YOU {counter_turns} GUESSES.")
+    return
+
+
+if __name__ == "__main__":
+    print_instructions()
+
+    another = ""
+    while another != "NO":
+        main()
+        another = input("DO YOU WANT TO TRY ANOTHER PUZZLE\n")

From 7605116b06260aeaf0f2ae57ae418cbccc7da639 Mon Sep 17 00:00:00 2001
From: James Allenspach 
Date: Sun, 2 Jan 2022 10:14:23 -0600
Subject: [PATCH 483/749] Initial commit

---
 05_Bagels/perl/bagels.pl | 196 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 196 insertions(+)
 create mode 100755 05_Bagels/perl/bagels.pl

diff --git a/05_Bagels/perl/bagels.pl b/05_Bagels/perl/bagels.pl
new file mode 100755
index 00000000..92318e13
--- /dev/null
+++ b/05_Bagels/perl/bagels.pl
@@ -0,0 +1,196 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# global variable declaration (just the user's score)
+my($Y) = 0;
+
+
+# yes_input is a subroutine that returns a true value
+# if the first character of the user's input from STDIN
+# is a 'Y' (checking case-insensitively via regex)
+sub yes_input {
+    chomp(my $A = );
+    return $A =~ m/^Y/i;
+}
+
+# Main code starts here.
+# 
+# Provide instructions if requested 
+
+print ' 'x32; print "Bagels\n";
+print ' 'x14; print "Creative Computing  Morristown, New Jersey\n\n";
+
+print "Would you like the rules (yes or no)? ";
+if (yes_input()) {
+
+    # Print out the instructions using a here doc
+    # (useful for large blocks of text)
+    print <);
+
+            # Use a regex to check if the user entered three digits,
+            # and complain if they did not.
+            if ($A !~ m{^(\d)(\d)(\d)$}) {
+                print "What?\n";
+                # Program execution will now pass through the rest
+                # of the logic below and loop back to the start 
+                # of the CHECK loop.
+            } else {
+
+                # As a side effect of the regex match above, the 
+                # $1, $2, and $3 variables are each of the digits
+                # of the user's guess. Perl treats numbers and
+                # strings interchangably, so we will not have to
+                # use the ASC() conversion functions required 
+                # by the BASIC program.
+                my @B = ($1,$2,$3);
+
+                # Check for duplicate digits in the user's guess
+                if ($B[0] == $B[1] || $B[0] == $B[2] || $B[1] == $B[2]) {
+                    print "Oh, I forgot to tell you that the number I have in mind\n";
+                    print "has no two digits the same.\n";
+                    # Again, no further action is required here
+                    # because we want to loop back to the start
+                    # of the CHECK loop.
+                } else {
+
+                    # This code block is the actual game logic, so
+                    # it's executed only if the user's input has
+                    # passed all the above checks.
+                    my($C,$D);
+                    $C = 0; $D = 0;
+
+                    # As a replacement for the original BASIC logic,
+                    # this for loop works over an anonymous array of
+                    # pairs of digits to compare the computer's and
+                    # the user's digits to see how many similar ones
+                    # there are. Keep in mind that Perl arrays are
+                    # zero-indexed, so we're comparing items numbered
+                    # 0, 1, and 2, instead of 1, 2, and 3 in BASIC.
+
+                    for my $PAIR ( [0,1], [1,0], [1,2], [2,1], [0,2], [2,0] ) {
+                        if ($A[$PAIR->[0]] == $B[$PAIR->[1]]) {
+                            ++$C;
+                        }
+                    }
+
+                    # Check for digits that are correctly guessed
+                    for my $i (0..2) {
+                        if ($A[$i] == $B[$i]) {
+                            ++$D;
+                        }
+                    }
+
+                    # If the user guessed all 3 digits they get
+                    # a point, and the 'PLAY' loop is restarted
+                    # (see the 'continue' loop below)
+                    if ($D == 3) {
+                        print "You got it!!!\n\n";
+                        ++$Y;
+                        next PLAY;
+                    }
+
+                    # Print out the clues. The 'x' operator
+                    # prints out the string the indicated number
+                    # of times. The "BAGELS" line uses Perl's 
+                    # ternary operator to print the word if 
+                    # the expression ($C + $D) is equal to 0.
+
+                    printf("%s%s%s\n", 
+                        "PICO " x$C,
+                        "FERMI "x$D,
+                        ($C+$D==0 ? "BAGELS" : '')
+                    );
+
+                    # Program execution leaves the CHECK loop and
+                    # goes to the next iteration of the $i loop.
+                    last CHECK;
+
+                } # end of game logic else block
+            } # end of regex match else block
+
+            # If program execution reaches this particular point,
+            # then the user's input has not been accepted (the 
+            # only ways out of this loop are the "next PLAY" statement
+            # when the user wins, and the "last CHECK" statement
+            # when the user's input is successfully parsed).
+            # So the program execution goes back to the top of the 
+            # CHECK loop, printing the request for user input
+            # again.
+
+        } # end of CHECK loop
+
+        # This location is reached by the "last CHECK" statement,
+        # and it's another execution of the $i loop.
+
+    } # end of $i loop
+
+    # If program execution reaches here, the user has guessed 20
+    # times and not won.
+
+    print "Oh well.\n";
+    printf("That's twenty guesses. My number was %s\n", join('',@A));
+
+} # end of the PLAY loop
+
+# This 'continue' block is executed before the conditional part of the
+# PLAY loop is evaluated, so we can ask if the user wants another game
+# (i.e., if we should restart the PLAY loop).
+
+continue {
+
+    # This 'continue' loop is reached either when the PLAY loop has completed
+    # or via the 'next PLAY' statement when the user wins a game. In either
+    # case we ask if the player wants to go again, and use the 'last' 
+    # statement to exit the loop if the response is not yes.
+    print "Play again (yes or no) ? ";
+    last unless yes_input();
+}
+
+# And as in the original BASIC program, print out
+# the user's score only if it is > 0.
+printf("A %d point bagels buff!\n", $Y) if $Y > 0;
+print "Hope you had fun.  Bye.\n";

From e37cad9ae3893b68797901fea888848790fed672 Mon Sep 17 00:00:00 2001
From: James Allenspach 
Date: Sun, 2 Jan 2022 10:18:35 -0600
Subject: [PATCH 484/749] Modified comment

---
 05_Bagels/perl/bagels.pl | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/05_Bagels/perl/bagels.pl b/05_Bagels/perl/bagels.pl
index 92318e13..739ded0e 100755
--- a/05_Bagels/perl/bagels.pl
+++ b/05_Bagels/perl/bagels.pl
@@ -16,12 +16,11 @@ sub yes_input {
 }
 
 # Main code starts here.
-# 
-# Provide instructions if requested 
 
 print ' 'x32; print "Bagels\n";
 print ' 'x14; print "Creative Computing  Morristown, New Jersey\n\n";
 
+# Provide instructions if requested 
 print "Would you like the rules (yes or no)? ";
 if (yes_input()) {
 

From ad170ac3c2644d63c3266ddad97308449327798b Mon Sep 17 00:00:00 2001
From: Rifat Nabi 
Date: Mon, 3 Jan 2022 02:59:09 +1100
Subject: [PATCH 485/749] Fix duplicate card bug

---
 01_Acey_Ducey/ruby/aceyducey.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/01_Acey_Ducey/ruby/aceyducey.rb b/01_Acey_Ducey/ruby/aceyducey.rb
index b9648ef8..3d49754a 100644
--- a/01_Acey_Ducey/ruby/aceyducey.rb
+++ b/01_Acey_Ducey/ruby/aceyducey.rb
@@ -56,9 +56,9 @@ while true # Game loop
   puts
   puts "HERE ARE YOUR NEXT TWO CARDS:"
 
-  # Randomly draw two cards from 2 to 14 and make sure the first card is lower in value than the second
+  # Randomly draw two cards and make sure the first card is lower in value than the second
   # Using array destructuring, this sorted array can be assigned to `first_card` and `second_card`
-  first_card, second_card = [rand(2..14), rand(2..14)].sort
+  first_card, second_card = (2...14).to_a.shuffle.pop(2).sort
 
   # Helper method to convert a numeric card into a String for printing
   def card_name(card)

From 49a342e2bf9c9b9627567b091b38ba0f0df93bd6 Mon Sep 17 00:00:00 2001
From: Tom Wyant 
Date: Sun, 2 Jan 2022 13:30:14 -0500
Subject: [PATCH 486/749] Perl port of 96_Word.

---
 96_Word/perl/word.pl | 169 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)
 create mode 100755 96_Word/perl/word.pl

diff --git a/96_Word/perl/word.pl b/96_Word/perl/word.pl
new file mode 100755
index 00000000..5369cc71
--- /dev/null
+++ b/96_Word/perl/word.pl
@@ -0,0 +1,169 @@
+#!/usr/bin/env perl
+
+use 5.010;      # To get 'state' and 'say'
+
+use strict;     # Require explicit declaration of variables
+use warnings;   # Enable optional compiler warnings
+
+use English;    # Use more friendly names for Perl's magic variables
+use Term::ReadLine;     # Prompt and return user input
+
+our $VERSION = '0.000_01';
+
+print <<'EOD';
+                                 WORD
+               Creative Computing  Morristown, New Jersey
+
+
+
+I am thinking of a word -- you guess it.  I will give you
+clues to help you get it.  Good luck!!
+
+
+EOD
+
+# Read the content of __DATA__, remove the trailing newlines, and store
+# each line into @words. Stop at __END__, since Perl does not see this
+# as an end-of-file.
+my @words;
+while (  ) {
+    chomp;
+    last if $ARG eq '__END__';
+    push @words, lc $ARG;   # Normalize case to lower.
+}
+
+# This loop represents an actual game. We execute it until the player
+# does something that makes us explicitly break out.
+while ( 1 ) {
+    print <<'EOD';
+
+
+You are starting a new game ...
+EOD
+
+    # Choose a random target word. The rand() function returns a number
+    # from 0 to its argument, and coerces its argument to a scalar. In
+    # scalar context, an array evaluates to the number of elements it
+    # contains.
+    my $target = $words[ rand @words ];
+
+    # We generalize the code by using the actual length of the target.
+    my $target_length = length $target;
+
+    my $count = 0;      # Number of guesses
+
+    # Make an array of the individual letters in the target. We will
+    # iterate over this to determine matching letters.
+    my @target_array = split qr<>, $target;
+
+    # Make a hash of those letters. We will use this to determine common
+    # letters. Any true value will do for the value of the hash. By
+    # making use of this hash we avoid the nested loops of the original
+    # BASIC program.
+    my %target_hash = map { $ARG => 1 } @target_array;
+
+    # We keep prompting the player until we get a response that causes
+    # us to break out of the loop.
+    while ( 1 ) {
+
+        # Create the readline object. The state keyword means the
+        # variable is only initialized once, no matter how many times
+        # execution passes this point.
+        state $term = Term::ReadLine->new( 'word' );
+
+        # Read the next guess. A return of undef means end-of-file.
+        my $guess = $term->readline( "Guess a $target_length letter word: " );
+        exit unless defined $guess;
+
+        last if $guess eq '?';  # A question mark means we give up
+        if ( length( $guess ) != $target_length ) {
+            # Wrong length. Ask again.
+            say "You must guess a $target_length letter word.  Try again.";
+            redo;       # Redo the innermost loop
+        }
+
+        $guess = lc $guess;     # Lower-case the guess
+        $count++;       # Count another guess
+
+        if ( $guess eq $target ) {
+            # We guessed the word.
+            say "You have guessed the word. It took $count guesses!";
+            my $answer = $term->readline( 'Want to play again? [y/N]: ');
+            exit unless defined $guess; # End of file
+            exit unless $guess =~ m/ \A y /smxi;
+            last;       # Exit the innermost loop.
+        }
+
+        my @common_letters; # Letters common to guess and target
+        my $match = '-' x length $target;   # Assume no matches
+        my $inx = 0;    # Iterator
+        foreach my $letter ( split qr<>, $guess ) {
+            if ( $target_hash{$letter} ) {
+                # If the letter is in the hash, it occurs in the target
+                push @common_letters, $letter;
+                # If it is at the current position in the target, it is
+                # an actual match.
+                $target_array[$inx] eq $letter
+                    and substr $match, $inx, 1, $letter;
+            }
+            $inx++;
+        }
+
+        say 'There were ', scalar @common_letters,
+            ' matches and the common letters were... ', @common_letters;
+        say "From the exact letter matches, you know................ $match";
+        say '';
+        say q;
+        redo;
+    }
+
+}
+__DATA__
+dinky
+smoke
+water
+grass
+train
+might
+first
+candy
+champ
+would
+clump
+dopey
+__END__
+
+=head1 TITLE
+
+word.pl - Play the game 'word' from Basic Computer Games
+
+=head1 SYNOPSIS
+
+ word.pl
+
+=head1 DETAILS
+
+This Perl script is a port of C, which is the 96th entry in Basic
+Computer Games.
+
+=head1 PORTED BY
+
+Thomas R. Wyant, III F
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2022 by Thomas R. Wyant, III
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl 5.10.0. For more details, see the Artistic
+License 1.0 at
+L, and/or the
+Gnu GPL at L.
+
+This program is distributed in the hope that it will be useful, but
+without any warranty; without even the implied warranty of
+merchantability or fitness for a particular purpose.
+
+=cut
+
+# ex: set expandtab tabstop=4 textwidth=72 :

From 0843025ea88abb559187b9cb71f0c6ce1e367cfc Mon Sep 17 00:00:00 2001
From: Erik Heemskerk 
Date: Sun, 2 Jan 2022 19:44:06 +0100
Subject: [PATCH 487/749] Add C# version of Awari

---
 04_Awari/csharp/Game.cs       | 264 ++++++++++++++++++++++++++++++++++
 04_Awari/csharp/Program.cs    |  98 +++++++++++++
 04_Awari/csharp/csharp.csproj |  11 ++
 3 files changed, 373 insertions(+)
 create mode 100644 04_Awari/csharp/Game.cs
 create mode 100644 04_Awari/csharp/Program.cs
 create mode 100644 04_Awari/csharp/csharp.csproj

diff --git a/04_Awari/csharp/Game.cs b/04_Awari/csharp/Game.cs
new file mode 100644
index 00000000..8a673dea
--- /dev/null
+++ b/04_Awari/csharp/Game.cs
@@ -0,0 +1,264 @@
+namespace Awari;
+
+public class Game
+{
+    public int[] PlayerPits => _beans[0..6];
+    public int[] ComputerPits => _beans[7..13];
+    public int PlayerHome => _beans[_playerHome];
+    public int ComputerHome => _beans[_computerHome];
+
+    private bool IsDone =>
+        PlayerPits.All(b => b == 0) // if all the player's pits are empty
+     || ComputerPits.All(b => b == 0); // or if all the computer's pits are empty
+
+    public GameState State { get; private set; }
+
+    public void Reset()
+    {
+        State = GameState.PlayerMove;
+
+        Array.Fill(_beans, _initialPitValue);
+        _beans[_playerHome] = 0;
+        _beans[_computerHome] = 0;
+
+        _moveCount = 0;
+        _notWonGameMoves[^1] = 0;
+    }
+
+    public bool IsLegalPlayerMove(int move) =>
+        move is > 0 and < 7
+     && _beans[move - 1] > 0; // arrays are zero-based, but moves are one-based
+
+    public void PlayerMove(int move) => MoveAndRegister(move - 1, _playerHome);
+
+    public List ComputerTurn()
+    {
+        // keep a list of moves made by the computer in a single turn (1 or 2)
+        List moves = new();
+
+        moves.Add(ComputerMove()); // ComputerMove() returns the move made
+
+        // only if a second move is possible, do it
+        if (State == GameState.ComputerSecondMove)
+            moves.Add(ComputerMove());
+
+        return moves;
+    }
+
+    public GameOutcome GetOutcome()
+    {
+        if (State != GameState.Done)
+            throw new InvalidOperationException("Game is not yet done.");
+
+        int difference = _beans[_playerHome] - _beans[_computerHome];
+        var winner = difference switch
+        {
+            < 0 => GameWinner.Computer,
+            0 => GameWinner.Draw,
+            > 0 => GameWinner.Player,
+        };
+
+        return new GameOutcome(winner, Math.Abs(difference));
+    }
+
+    private void MoveAndRegister(int pit, int homePosition)
+    {
+        int lastMovedBean = Move(_beans, pit, homePosition);
+
+        // encode moves by player and computer into a 'base 6' number
+        // e.g. if the player moves 5, the computer moves 2, and the player moves 4,
+        // that would be encoded as ((5 * 6) * 6) + (2 * 6) + 4 = 196
+        if (pit > 6) pit -= 7;
+        _moveCount++;
+        if (_moveCount < 9)
+            _notWonGameMoves[^1] = _notWonGameMoves[^1] * 6 + pit;
+
+        // determine next state based on current state, whether the game's done, and whether the last moved bean moved
+        // into the player's home position
+        State = (State, IsDone, lastMovedBean == homePosition) switch
+        {
+            (_, true, _) => GameState.Done,
+            (GameState.PlayerMove, _, true) => GameState.PlayerSecondMove,
+            (GameState.PlayerMove, _, false) => GameState.ComputerMove,
+            (GameState.PlayerSecondMove, _, _) => GameState.ComputerMove,
+            (GameState.ComputerMove, _, true) => GameState.ComputerSecondMove,
+            (GameState.ComputerMove, _, false) => GameState.PlayerMove,
+            (GameState.ComputerSecondMove, _, _) => GameState.PlayerMove,
+            _ => throw new InvalidOperationException("Unexpected game state"),
+        };
+
+        // do some bookkeeping if the game is done, but not won by the computer
+        if (State == GameState.Done
+         && _beans[_playerHome] >= _beans[_computerHome])
+            // add an entry for the next game
+            _notWonGameMoves.Add(0);
+    }
+
+    private static int Move(int[] beans, int pit, int homePosition)
+    {
+        int beansToMove = beans[pit];
+        beans[pit] = 0;
+
+        // add the beans that were in the pit to other pits, moving clockwise around the board
+        for (; beansToMove >= 1; beansToMove--)
+        {
+            // wrap around if pit exceeds 13
+            pit = (pit + 1) % 14;
+
+            beans[pit]++;
+        }
+
+        if (beans[pit] == 1 // if the last bean was sown in an empty pit
+         && pit is not _playerHome and not _computerHome // which is not either player's home
+         && beans[12 - pit] != 0) // and the pit opposite is not empty
+        {
+            // move the last pit sown and the _beans in the pit opposite to the player's home
+            beans[homePosition] = beans[homePosition] + beans[12 - pit] + 1;
+            beans[pit] = 0;
+            beans[12 - pit] = 0;
+        }
+
+        return pit;
+    }
+
+    private int ComputerMove()
+    {
+        int move = DetermineComputerMove();
+        MoveAndRegister(move, homePosition: _computerHome);
+
+        // the result is only used to return it to the application, so translate it from an array index (between 7 and
+        // 12) to a pit number (between 1 and 6)
+        return move - 6;
+    }
+
+    private int DetermineComputerMove()
+    {
+        int bestScore = -99;
+        int move = 0;
+
+        // for each of the computer's possible moves, simulate them to calculate a score and pick the best one
+        for (int j = 7; j < 13; j++)
+        {
+            if (_beans[j] <= 0)
+                continue;
+
+            int score = SimulateMove(j);
+
+            if (score >= bestScore)
+            {
+                move = j;
+                bestScore = score;
+            }
+        }
+
+        return move;
+    }
+
+    private int SimulateMove(int move)
+    {
+        // make a copy of the current state, so we can safely mess with it
+        var hypotheticalBeans = new int[14];
+        _beans.CopyTo(hypotheticalBeans, 0);
+
+        // simulate the move in our copy
+        Move(hypotheticalBeans, move, homePosition: _computerHome);
+
+        // determine the 'best' move the player could make after this (best for them, not for the computer)
+        int score = ScoreBestNextPlayerMove(hypotheticalBeans);
+
+        // score this move by calculating how far ahead we would be after the move, and subtracting the player's next
+        // move score
+        score = hypotheticalBeans[_computerHome] - hypotheticalBeans[_playerHome] - score;
+
+        // have we seen the current set of moves before in a drawn/lost game? after 8 moves it's unlikely we'll find any
+        // matches, since games will have diverged. also we don't have space to store that many moves.
+        if (_moveCount < 8)
+        {
+            int translatedMove = move - 7;  // translate from 7 through 12 to 0 through 5
+
+            // if the first two moves in this game were 1 and 2, and this hypothetical third move would be a 3,
+            // movesSoFar would be (1 * 36) + (2 * 6) + 3 = 51
+            int movesSoFar = _notWonGameMoves[^1] * 6 + translatedMove;
+
+            // since we store moves as a 'base 6' number, we need to divide stored moves by a power of 6
+            // let's say we've a stored lost game where the moves were, in succession, 1 through 8, the value stored
+            // would be:
+            // 8 + (7 * 6) + (6 * 36) + (5 * 216) + (4 * 1296) + (3 * 7776) + (2 * 46656) + (1 * 279936) = 403106
+            // to figure out the first three moves, we'd need to divide by 7776, resulting in 51.839...
+            double divisor = Math.Pow(6.0, 7 - _moveCount);
+
+            foreach (int previousGameMoves in _notWonGameMoves)
+                // if this combination of moves so far ultimately resulted in a draw/loss, give it a lower score
+                // note that this can happen multiple times
+                if (movesSoFar == (int) (previousGameMoves / divisor + 0.1))
+                    score -= 2;
+        }
+
+        return score;
+    }
+
+    private static int ScoreBestNextPlayerMove(int[] hypotheticalBeans)
+    {
+        int bestScore = 0;
+
+        for (int i = 0; i < 6; i++)
+        {
+            if (hypotheticalBeans[i] <= 0)
+                continue;
+
+            int score = ScoreNextPlayerMove(hypotheticalBeans, i);
+
+            if (score > bestScore)
+                bestScore = score;
+        }
+
+        return bestScore;
+    }
+
+    private static int ScoreNextPlayerMove(int[] hypotheticalBeans, int move)
+    {
+        // figure out where the last bean will land
+        int target = hypotheticalBeans[move] + move;
+        int score = 0;
+
+        // if it wraps around, that means the player is adding to his own pits, which is good
+        if (target > 13)
+        {
+            // prevent overrunning the number of pits we have
+            target %= 14;
+            score = 1;
+        }
+
+        // if the player's move ends up in an empty pit, add the value of the pit on the opposite side to the score
+        if (hypotheticalBeans[target] == 0 && target is not _playerHome and not _computerHome)
+            score += hypotheticalBeans[12 - target];
+
+        return score;
+    }
+
+    private const int _playerHome = 6;
+    private const int _computerHome = 13;
+    private const int _initialPitValue = 3;
+
+    private readonly int[] _beans = new int[14];
+    private readonly List _notWonGameMoves = new() { 0 };    // not won means draw or lose
+    private int _moveCount;
+}
+
+public enum GameState
+{
+    PlayerMove,
+    PlayerSecondMove,
+    ComputerMove,
+    ComputerSecondMove,
+    Done,
+}
+
+public enum GameWinner
+{
+    Player,
+    Computer,
+    Draw,
+}
+
+public record struct GameOutcome(GameWinner Winner, int Difference);
\ No newline at end of file
diff --git a/04_Awari/csharp/Program.cs b/04_Awari/csharp/Program.cs
new file mode 100644
index 00000000..750787e7
--- /dev/null
+++ b/04_Awari/csharp/Program.cs
@@ -0,0 +1,98 @@
+using Awari;
+
+Console.WriteLine(Tab(34) + "AWARI");
+Console.WriteLine(Tab(15) + "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
+
+Game game = new();
+
+while (true)
+{
+    game.Reset();
+    DisplayGame();
+
+    while (game.State != GameState.Done)
+    {
+        switch (game.State)
+        {
+            case GameState.PlayerMove:
+                PlayerMove(second: false);
+                break;
+            case GameState.PlayerSecondMove:
+                PlayerMove(second: true);
+                break;
+            case GameState.ComputerMove:
+                ComputerTurn();
+                break;
+        }
+
+        DisplayGame();
+    }
+
+    var outcome = game.GetOutcome();
+
+    string outcomeLabel =
+        outcome.Winner switch
+        {
+            GameWinner.Computer => $"I WIN BY {outcome.Difference} POINTS",
+            GameWinner.Draw => "DRAWN GAME",
+            GameWinner.Player => $"YOU WIN BY {outcome.Difference} POINTS",
+            _ => throw new InvalidOperationException($"Unexpected winner {outcome.Winner}."),
+        };
+    Console.WriteLine(outcomeLabel);
+    Console.WriteLine();
+}
+
+void DisplayGame()
+{
+    // display the computer's pits
+    Console.Write("   ");
+    foreach (var pit in game.ComputerPits.Reverse())
+        Console.Write($"{pit,2} ");
+    Console.WriteLine();
+
+    // display both homes
+    Console.WriteLine($"{game.ComputerHome,2}{Tab(19)}{game.PlayerHome,2}");
+
+    // display the player's pits
+    Console.Write("   ");
+    foreach (var pit in game.PlayerPits)
+        Console.Write($"{pit,2} ");
+    Console.WriteLine();
+
+    Console.WriteLine();
+}
+
+void PlayerMove(bool second = false)
+{
+    int move = GetMove(second);
+    game.PlayerMove(move);
+}
+
+int GetMove(bool second)
+{
+    string prompt = second ? "AGAIN? " : "YOUR MOVE? ";
+
+    while (true)
+    {
+        Console.Write(prompt);
+
+        string input = Console.ReadLine() ?? "";
+
+        // input must be a number between 1 and 6, and the pit must have > 0 beans
+        if (int.TryParse(input, out int move)
+         && game.IsLegalPlayerMove(move))
+            return move;
+
+        Console.WriteLine("ILLEGAL MOVE");
+    }
+}
+
+void ComputerTurn()
+{
+    var moves = game.ComputerTurn();
+    string movesString = string.Join(",", moves);
+
+    Console.WriteLine($"MY MOVE IS {movesString}");
+}
+
+string Tab(int n) => new(' ', n);
\ No newline at end of file
diff --git a/04_Awari/csharp/csharp.csproj b/04_Awari/csharp/csharp.csproj
new file mode 100644
index 00000000..6bf2a525
--- /dev/null
+++ b/04_Awari/csharp/csharp.csproj
@@ -0,0 +1,11 @@
+
+
+  
+    Exe
+    net6.0
+    enable
+    enable
+    Awari
+  
+
+

From 6fcff28bcc54b68448310b226c9234d39af21b32 Mon Sep 17 00:00:00 2001
From: eries2 
Date: Sun, 2 Jan 2022 10:50:22 -0800
Subject: [PATCH 488/749] added a beter pretty print for each tower. helped my
 7yo visualize what was going on

---
 90_Tower/python/tower_test.py | 49 +++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 90_Tower/python/tower_test.py

diff --git a/90_Tower/python/tower_test.py b/90_Tower/python/tower_test.py
new file mode 100644
index 00000000..a7023a0f
--- /dev/null
+++ b/90_Tower/python/tower_test.py
@@ -0,0 +1,49 @@
+import unittest
+import tower
+
+class MyTestCase(unittest.TestCase):
+    def test_something(self):
+        t = tower.Tower()
+        self.assertTrue(t.empty())
+
+        d = tower.Disk(3)
+        t.add(d)
+        self.assertFalse(t.empty())
+
+        d5 = tower.Disk(5)
+        self.assertRaises(Exception, t.add, d5)
+        self.assertFalse(t.empty())
+
+    def test_oksize(self):
+        t = tower.Tower()
+        self.assertTrue(t.empty())
+
+        d5 = tower.Disk(5)
+        t.add(d5)
+        self.assertFalse(t.empty())
+
+        d3 = tower.Disk(3)
+        t.add(d3)
+        self.assertFalse(t.empty())
+
+        self.assertEqual(t.top(), d3)
+        self.assertEqual(t.pop(), d3)
+        self.assertEqual(t.pop(), d5)
+
+    def test_game(self):
+        g = tower.Game()
+        self.assertEqual(g.moves(), 0)
+        self.assertFalse(g.winner())
+
+    def test_format(self):
+        t = tower.Tower()
+        d3 = tower.Disk(3)
+        d5 = tower.Disk(5)
+        t.add(d5)
+        t.add(d3)
+
+        f = t.vertical_format(6, 3)
+        self.assertEqual(f, ['      ', '[ 3 ] ', '[ 5 ] '])
+
+if __name__ == '__main__':
+    unittest.main()

From b2f04257cca27e87ec66cc443cf80c9227c05b77 Mon Sep 17 00:00:00 2001
From: Anachostic 
Date: Sun, 2 Jan 2022 14:00:05 -0500
Subject: [PATCH 489/749] VB.NET version of Acey-Ducey

---
 01_Acey_Ducey/vbnet/AceyDucy.sln             |  25 +++
 01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj |   9 +
 01_Acey_Ducey/vbnet/AceyDucy/Program.vb      | 178 +++++++++++++++++++
 3 files changed, 212 insertions(+)
 create mode 100644 01_Acey_Ducey/vbnet/AceyDucy.sln
 create mode 100644 01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj
 create mode 100644 01_Acey_Ducey/vbnet/AceyDucy/Program.vb

diff --git a/01_Acey_Ducey/vbnet/AceyDucy.sln b/01_Acey_Ducey/vbnet/AceyDucy.sln
new file mode 100644
index 00000000..881d7c9c
--- /dev/null
+++ b/01_Acey_Ducey/vbnet/AceyDucy.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AceyDucy", "AceyDucy\AceyDucy.vbproj", "{37496710-B458-4502-ADCB-4C57203866F9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{37496710-B458-4502-ADCB-4C57203866F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{37496710-B458-4502-ADCB-4C57203866F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{37496710-B458-4502-ADCB-4C57203866F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{37496710-B458-4502-ADCB-4C57203866F9}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {C01D9DAE-644C-455F-8365-E14E49074BC3}
+	EndGlobalSection
+EndGlobal
diff --git a/01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj b/01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj
new file mode 100644
index 00000000..98a07001
--- /dev/null
+++ b/01_Acey_Ducey/vbnet/AceyDucy/AceyDucy.vbproj
@@ -0,0 +1,9 @@
+
+
+  
+    Exe
+    AceyDucy
+    net6.0
+  
+
+
diff --git a/01_Acey_Ducey/vbnet/AceyDucy/Program.vb b/01_Acey_Ducey/vbnet/AceyDucy/Program.vb
new file mode 100644
index 00000000..bfa518ca
--- /dev/null
+++ b/01_Acey_Ducey/vbnet/AceyDucy/Program.vb
@@ -0,0 +1,178 @@
+Imports System
+
+''' 
+''' This is a modern adapation of Acey Ducey from BASIC Computer Games.
+''' 
+''' The structural changes primarily consist of replacing the many GOTOs with
+''' Do/Loop constructs to force the continual execution of the program.
+''' 
+''' Because modern Basic allows multi-line If/Then blocks, many GOTO jumps were
+''' able to be eliminated and the logic was able to be moved to more relevant areas,
+''' For example, the increment/decrement of the player's balance could be in the same
+''' area as the notification of win/loss.
+''' 
+''' Some modern improvements were added, primarily the inclusion of a function, which
+''' eliminated a thrice-repeated block of logic to display the card value.  The archaic
+''' RND function is greatly simplified with the .NET Framework's Random class.
+''' 
+''' Elementary comments are provided for non-programmers or novices.
+''' 
+Module Program
+    Sub Main(args As String())
+        ' These are the variables that will hold values during the program's execution
+        Dim input As String
+        Dim rnd As New Random ' You can create a new instance of an object during declaration
+        Dim currentBalance As Integer = 100 ' You can set a initial value at declaration
+        Dim currentWager As Integer
+        Dim cardA, cardB, cardC As Integer ' You can specify multiple variables of the same type in one declaration statement
+
+        ' Display the opening title and instructions
+        ' Use a preceding $ to insert calculated values within the string using {}
+        Console.WriteLine($"{Space((Console.WindowWidth \ 2) - 10)}ACEY DUCEY CARD GAME")
+        Console.WriteLine($"{Space((Console.WindowWidth \ 2) - 21)}CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY")
+        Console.WriteLine("")
+        Console.WriteLine("")
+        Console.WriteLine("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER")
+        Console.WriteLine("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP")
+        Console.WriteLine("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING")
+        Console.WriteLine("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE")
+        Console.WriteLine("A VALUE BETWEEN THE FIRST TWO.")
+        Console.WriteLine("IF YOU DO NOT WANT TO BET, INPUT A 0")
+
+        Do ' This loop continues as long as the player wants to keep playing
+
+            Do ' This loop continues as long as the player has money to play
+
+                Console.WriteLine("")
+                Console.WriteLine($"YOU NOW HAVE {currentBalance} DOLLARS.")
+                Console.WriteLine("")
+
+                Console.WriteLine("HERE ARE YOUR NEXT TWO CARDS:")
+
+                ' We need to ensure that card B is a higher value for our later comparison,
+                ' so we will loop until we have two cards that meet this criteria
+                Do
+                    cardA = rnd.Next(2, 14)
+                    cardB = rnd.Next(2, 14)
+
+                Loop While cardA > cardB
+
+                ' We use a function to display the text value of the numeric card value
+                ' because we do this 3 times and a function reduces repetition of code
+                Console.WriteLine(DisplayCard(cardA))
+                Console.WriteLine(DisplayCard(cardB))
+
+                Do ' This loop continues until the player provides a valid wager value
+                    Console.WriteLine("")
+                    Console.WriteLine("WHAT IS YOUR BET")
+
+                    currentWager = 0
+                    input = Console.ReadLine
+
+                    ' Any input from the console is a string, but we require a number. 
+                    ' Test the input to make sure it is a numeric value.
+                    If Integer.TryParse(input, currentWager) Then
+                        ' Test to ensure the player has not wagered more than their balance
+                        If currentWager > currentBalance Then
+                            Console.WriteLine("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.")
+                            Console.WriteLine($"YOU HAVE ONLY {currentBalance} DOLLARS TO BET.")
+
+                        Else
+                            ' The player has provided a numeric value that is less/equal to their balance, 
+                            ' exit the loop and continue play
+                            Exit Do
+
+                        End If ' check player balance
+
+                    End If ' check numeric input
+
+                Loop ' wager loop
+
+                ' If the player is wagering, draw the third card, otherwise, mock them.
+                If currentWager > 0 Then
+                    cardC = rnd.Next(2, 14)
+
+                    Console.WriteLine(DisplayCard(cardC))
+
+                    ' The effort we made to have two cards in numeric order earlier makes this check easier,
+                    ' otherwise we would have to have a second check in the opposite direction
+                    If cardC < cardA OrElse cardC >= cardB Then
+                        Console.WriteLine("SORRY, YOU LOSE")
+                        currentBalance -= currentWager ' Shorthand code to decrement a number (currentBalance=currentBalance - currentWager)
+
+                    Else
+                        Console.WriteLine("YOU WIN!!!")
+                        currentBalance += currentWager ' Shorthand code to increment a number (currentBalance=currentBalance + currentWager)
+
+                    End If
+
+                Else
+                    Console.WriteLine("CHICKEN!!")
+                    Console.WriteLine("")
+
+                End If
+
+            Loop While currentBalance > 0 ' loop as long as the player has money
+
+            ' At this point, the player has no money (currentBalance=0).  Inform them of such.
+            Console.WriteLine("")
+            Console.WriteLine("SORRY, FRIEND, BUT YOU BLEW YOUR WAD.")
+            Console.WriteLine("")
+            Console.WriteLine("")
+
+            ' We will loop to ensure the player provides some answer.
+            Do
+                Console.WriteLine("TRY AGAIN (YES OR NO)")
+                Console.WriteLine("")
+
+                input = Console.ReadLine
+
+            Loop While String.IsNullOrWhiteSpace(input)
+
+            ' We will assume that the player wants to play again only if they answer yes.
+            ' (yeah and ya are valid as well, because we only check the first letter)
+            If input.Substring(0, 1).Equals("y", StringComparison.CurrentCultureIgnoreCase) Then ' This allows upper and lower case to be entered.
+                currentBalance = 100 ' Reset the players balance before restarting
+
+            Else
+                ' Exit the outer loop which will end the game.
+                Exit Do
+
+            End If
+
+        Loop ' The full game loop
+
+        Console.WriteLine("O.K., HOPE YOU HAD FUN!")
+
+    End Sub
+
+    ' This function is called for each of the 3 cards used in the game.
+    ' The input and the output are both consistent, making it a good candidate for a function.
+    Private Function DisplayCard(value As Integer) As String
+        ' We check the value of the input and run a block of code for whichever
+        ' evaluation matches
+        Select Case value
+            Case 2 To 10 ' Case statements can be ranges of values, also multiple values (Case 2,3,4,5,6,7,8,9,10)
+                Return value.ToString
+
+            Case 11
+                Return "JACK"
+
+            Case 12
+                Return "QUEEN"
+
+            Case 13
+                Return "KING"
+
+            Case 14
+                Return "ACE"
+
+        End Select
+
+        ' Although we have full knowledge of the program and never plan to send an invalid
+        ' card value, it's important to provide a message for the next developer who won't
+        Throw New ArgumentOutOfRangeException("Card value must be between 2 and 14")
+
+    End Function
+
+End Module

From 50fb79af84e1397197bfa7c2edc3c87b18b1d6d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= 
Date: Sun, 2 Jan 2022 19:03:03 +0000
Subject: [PATCH 490/749] Add Perl version of 45_Hello

---
 45_Hello/perl/hello.pl | 136 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 45_Hello/perl/hello.pl

diff --git a/45_Hello/perl/hello.pl b/45_Hello/perl/hello.pl
new file mode 100644
index 00000000..53590595
--- /dev/null
+++ b/45_Hello/perl/hello.pl
@@ -0,0 +1,136 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print ' ' x 33 . "HELLO\n";
+print ' ' x 15 . "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n";
+print "\n\n\n";
+
+print "HELLO.  MY NAME IS CREATIVE COMPUTER.\n\n\n";
+print "WHAT'S YOUR NAME?\n";
+chomp( my $N = uc  );
+
+print "\nHI THERE, $N, ARE YOU ENJOYING YOURSELF HERE?\n";
+
+GREET:
+{
+    chomp( my $B = uc  );
+    print "\n";
+
+    if ( $B eq 'YES' ) {
+        print "I'M GLAD TO HEAR THAT, $N.\n\n";
+    }
+    elsif ( $B eq 'NO' ) {
+        print "OH, I'M SORRY TO HEAR THAT, $N. MAYBE WE CAN\n";
+        print "BRIGHTEN UP YOUR VISIT A BIT.\n";
+    }
+    else {
+        print "$N, I DON'T UNDERSTAND YOUR ANSWER OF '$B'.\n";
+        print "PLEASE ANSWER 'YES' OR 'NO'.  DO YOU LIKE IT HERE?\n";
+        redo GREET;
+    }
+}
+
+print "\nSAY, $N, I CAN SOLVE ALL KINDS OF PROBLEMS EXCEPT\n";
+print "THOSE DEALING WITH GREECE.  WHAT KIND OF PROBLEMS DO\n";
+print "YOU HAVE (ANSWER SEX, HEALTH, MONEY, OR JOB)?\n";
+
+ADVICE:
+{
+    chomp( my $C = uc  );
+    print "\n";
+
+    if ( $C eq 'SEX' ) {
+        print "IS YOUR PROBLEM TOO MUCH OR TOO LITTLE?\n";
+
+        SEX:
+        {
+            chomp( my $D = uc  );
+            print "\n";
+
+            if ( $D eq 'TOO MUCH' ) {
+                print "YOU CALL THAT A PROBLEM?!!  I SHOULD HAVE SUCH PROBLEMS!\n";
+                print "IF IT BOTHERS YOU, $N, TAKE A COLD SHOWER.\n";
+            }
+            elsif ( $D eq 'TOO LITTLE' ) {
+                print "WHY ARE YOU HERE IN SUFFERN, $N?  YOU SHOULD BE\n";
+                print "IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME\n";
+                print "REAL ACTION.\n";
+            }
+            else {
+                print "DON'T GET ALL SHOOK, $N, JUST ANSWER THE QUESTION\n";
+                print "WITH 'TOO MUCH' OR 'TOO LITTLE'.  WHICH IS IT?\n";
+                redo SEX;
+            }
+        }
+    }
+    elsif ( $C eq 'HEALTH' ) {
+        print "MY ADVICE TO YOU $N IS:\n";
+        print "     1.  TAKE TWO ASPRIN\n";
+        print "     2.  DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)\n";
+        print "     3.  GO TO BED (ALONE)\n";
+    }
+    elsif ( $C eq 'MONEY' ) {
+        print "SORRY, $N, I'M BROKE TOO.  WHY DON'T YOU SELL\n";
+        print "ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING\n";
+        print "SO YOU WON'T NEED SO MUCH MONEY?\n";
+    }
+    elsif ( $C eq 'JOB' ) {
+        print "I CAN SYMPATHIZE WITH YOU $N.  I HAVE TO WORK\n";
+        print "VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES\n";
+        print "REALLY BEAT ON MY KEYBOARD.  MY ADVICE TO YOU, $N,\n";
+        print "IS TO OPEN A RETAIL COMPUTER STORE.  IT'S GREAT FUN.\n";
+    }
+    else {
+        print "OH, $N, YOUR ANSWER OF '$C' IS GREEK TO ME.\n";
+    }
+
+    MORE:
+    {
+        print "\nANY MORE PROBLEMS YOU WANT SOLVED, $N?\n";
+        chomp( my $E = uc  );
+        print "\n";
+
+        if ( $E eq 'YES' ) {
+            print "WHAT KIND (SEX, MONEY, HEALTH, JOB)?\n";
+            redo ADVICE;
+        }
+        elsif ( $E eq 'NO' ) {
+            print "\nTHAT WILL BE \$5.00 FOR THE ADVICE, $N.\n";
+            print "PLEASE LEAVE THE MONEY ON THE TERMINAL.\n";
+        }
+        else {
+            print "JUST A SIMPLE 'YES' OR 'NO' PLEASE, $N.\n";
+            redo MORE;
+        }
+    }
+
+    sleep 2;
+    print "\n\n\n";
+
+    MONEY:
+    {
+        print "DID YOU LEAVE THE MONEY?\n";
+        chomp( my $G = uc  );
+        print "\n";
+
+        if ( $G eq 'YES' ) {
+            print "HEY, $N??? YOU LEFT NO MONEY AT ALL!\n";
+            print "YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING.\n";
+            print "\nWHAT A RIP OFF, $N!!!\n\n";
+        }
+        elsif ( $G eq 'NO' ) {
+            print "THAT'S HONEST, $N, BUT HOW DO YOU EXPECT\n";
+            print "ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENTS\n";
+            print "DON'T PAY THEIR BILLS?\n";
+        }
+        else {
+            print "YOUR ANSWER OF '$G' CONFUSES ME, $N.\n";
+            print "PLEASE RESPOND WITH 'YES' OR 'NO'.\n";
+            redo MONEY;
+        }
+
+        print "\nTAKE A WALK, $N.\n\n\n";
+    }
+}

From 412dc556d660127af8ad00a71124c5752a958077 Mon Sep 17 00:00:00 2001
From: Martin VanWinkle III 
Date: Sun, 2 Jan 2022 14:19:09 -0500
Subject: [PATCH 491/749] 31_Depth_Charge/ruby

---
 31_Depth_Charge/ruby/.editorconfig  |  69 +++++++++
 31_Depth_Charge/ruby/depthcharge.rb | 211 ++++++++++++++++++++++++++++
 2 files changed, 280 insertions(+)
 create mode 100644 31_Depth_Charge/ruby/.editorconfig
 create mode 100755 31_Depth_Charge/ruby/depthcharge.rb

diff --git a/31_Depth_Charge/ruby/.editorconfig b/31_Depth_Charge/ruby/.editorconfig
new file mode 100644
index 00000000..9d7e93d0
--- /dev/null
+++ b/31_Depth_Charge/ruby/.editorconfig
@@ -0,0 +1,69 @@
+# EditorConfig is awesome: https://EditorConfig.org
+# .editorconfig
+
+# Please see doc/developer_notes.md
+# If you find anything egregious or missing, please consider submitting a pull request
+# to https://github.com/theias/ias_package_shell
+
+
+# top-most EditorConfig file
+root = true
+
+# Sensible defaults for everything
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+
+# JavaScript
+[**.js]
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+
+# Ruby
+[**.rb]
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Python
+[**.py]
+charset = utf-8
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+
+# Perl
+[**.pl]
+charset = utf-8
+insert_final_newline = true
+[**.pm]
+charset = utf-8
+insert_final_newline = true
+
+# PHP
+[**.php]
+charset = utf-8
+indent_size = 4
+indent_style = space
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+# Makefiles
+[Makefile]
+indent_style = tab
+
+[**.gmk]
+indent_style = tab
+
+# Configuration Files
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
+
+# Diff files
+[*.{diff,patch}]
+trim_trailing_whitespace = false
diff --git a/31_Depth_Charge/ruby/depthcharge.rb b/31_Depth_Charge/ruby/depthcharge.rb
new file mode 100755
index 00000000..5ba36ba6
--- /dev/null
+++ b/31_Depth_Charge/ruby/depthcharge.rb
@@ -0,0 +1,211 @@
+#!/usr/bin/ruby
+
+class DepthCharge
+
+  def run_game
+    output_title()
+    while true
+      printf("----------\n")
+      print_instructions()
+      setup_game()
+      printf("\n")
+      game_loop()
+      break if ! get_input_another_game()
+    end
+
+    # 420 PRINT "OK.  HOPE YOU ENJOYED YOURSELF." : GOTO 600
+    printf("OK.  HOPE YOU ENJOYED YOURSELF.\n")
+  end
+
+  def output_title
+    printf("--- DEPTH CHARGE ---\n")
+    printf("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY\n")
+    printf("\n")
+  end
+
+  def get_input_y_or_n(message)
+    while true
+      print(message)
+
+      value = gets.chomp
+
+      if (value == 'Y' || value == 'y')
+        return true
+      elsif value == 'N' || value == 'n'
+        return false
+      end
+
+      printf("PLEASE ENTER Y/y OR N/n...\n\n")
+    end
+  end
+
+  def get_input_positive_integer(message)
+
+    while true
+      print(message)
+      value = gets.chomp
+      if (value == 'd')
+        debug_game()
+        next
+      end
+
+      the_input = Integer(value) rescue nil
+
+      if the_input == nil || the_input < 0
+        printf("PLEASE ENTER A POSITIVE NUMBER\n\n")
+        next
+
+      end
+
+      return the_input
+    end
+  end
+
+  def get_search_area_dimension
+    # 20 INPUT "DIMENSION OF SEARCH AREA";G: PRINT
+    @search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ")
+    # 30 N=INT(LOG(G)/LOG(2))+1
+
+    @num_tries = Integer(
+      Math.log(@search_area_dimension)/Math.log(2)
+    )
+
+  end
+
+  def print_instructions
+    # 40 PRINT "YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER"
+    # 50 PRINT "AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE.  YOUR"
+    # 60 PRINT "MISSION IS TO DESTROY IT.  YOU HAVE";N;"SHOTS."
+    # 70 PRINT "SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A"
+    # 80 PRINT "TRIO OF NUMBERS -- THE FIRST TWO ARE THE"
+    # 90 PRINT "SURFACE COORDINATES; THE THIRD IS THE DEPTH."
+    # 100 PRINT : PRINT "GOOD LUCK !": PRINT
+    printf( <<~INSTRUCTIONS
+YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER
+AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE.  YOUR
+MISSION IS TO DESTROY IT.
+
+SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A
+TRIO OF NUMBERS -- THE FIRST TWO ARE THE
+SURFACE COORDINATES (X, Y):
+     WEST < X < EAST
+    SOUTH < Y < NORTH
+
+THE THIRD IS THE DEPTH (Z):
+  SHALLOW < Z < DEEP
+
+GOOD LUCK !
+
+    INSTRUCTIONS
+    )
+  end
+
+  def debug_game
+    printf("@enemy_x: %d\n", @enemy_x)
+    printf("@enemy_y: %d\n", @enemy_y)
+    printf("@enemy_z: %d\n", @enemy_z)
+    printf("@num_tries: %d\n", @num_tries)
+    printf("@trial: %d\n", @trial)
+    printf("\n")
+  end
+
+  def setup_game
+    get_search_area_dimension()
+    setup_enemy()
+  end
+
+  def setup_enemy
+    # 110 A=INT(G*RND(1)) : B=INT(G*RND(1)) : C=INT(G*RND(1))
+    @enemy_x = rand(1..@search_area_dimension)
+    @enemy_y = rand(1..@search_area_dimension)
+    @enemy_z = rand(1..@search_area_dimension)
+    end
+
+  def game_loop
+    # 120 FOR D=1 TO N : PRINT : PRINT "TRIAL #";D; : INPUT X,Y,Z
+    for @trial in 1..@num_tries do
+      output_game_status()
+
+      @shot_x = get_input_positive_integer("X: ")
+      @shot_y = get_input_positive_integer("Y: ")
+      @shot_z = get_input_positive_integer("Z: ")
+
+      # 130 IF ABS(X-A)+ABS(Y-B)+ABS(Z-C)=0 THEN 300
+      if (
+        (@enemy_x - @shot_x).abs \
+        + (@enemy_y - @shot_y).abs \
+        + (@enemy_z - @shot_z).abs \
+        == 0
+      )
+        you_win()
+        return
+      else
+        # 140 GOSUB 500 : PRINT : NEXT D
+        missed_shot()
+      end
+    end
+
+    printf("\n")
+
+    you_lose()
+
+  end
+
+  def output_game_status
+    printf("YOU HAVE %d SHOTS REMAINING.\n", @num_tries - @trial + 1)
+    printf("TRIAL \#%d\n", @trial)
+  end
+  def you_win
+    printf("B O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial )
+  end
+  def missed_shot
+    missed_directions = []
+
+    # 530 IF X>A THEN PRINT "EAST";
+    # 540 IF X
@enemy_x + missed_directions.push('TOO FAR EAST') + elsif @shot_x < @enemy_x + missed_directions.push('TOO FAR WEST') + end + + # 510 IF Y>B THEN PRINT "NORTH"; + # 520 IF Y @enemy_y + missed_directions.push('TOO FAR NORTH') + elsif @shot_y < @enemy_y + missed_directions.push('TOO FAR SOUTH') + end + + # 560 IF Z>C THEN PRINT " TOO LOW." + # 570 IF Z @enemy_z + missed_directions.push('TOO DEEP') + elsif @shot_z < @enemy_z + missed_directions.push('TOO SHALLOW') + end + + # 500 PRINT "SONAR REPORTS SHOT WAS "; + printf("SONAR REPORTS SHOT WAS: \n") + printf("%s\n", "\t" + missed_directions.join("\n\t")) + # 550 IF Y<>B OR X<>A THEN PRINT " AND"; + # 590 RETURN + end + + def you_lose + # You took too long! + printf("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!\n") + printf("THE SUBMARINE WAS AT %d %d %d\n", @enemy_x, @enemy_y, @enemy_z) + + end + + def get_input_another_game + # 400 PRINT : PRINT: INPUT "ANOTHER GAME (Y OR N)";A$ + return get_input_y_or_n("ANOTHER GAME (Y OR N): ") + # 410 IF A$="Y" THEN 100 + end +end + +game = DepthCharge.new +game.run_game() From d2dc09591d9445854f6fa5d550d095573a54a645 Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Sun, 2 Jan 2022 13:38:49 -0600 Subject: [PATCH 492/749] Add 85_Synonym perl version Uses List::Util to handle all of the array manipulation which is standard in the perl core. --- 85_Synonym/perl/README.md | 4 +++ 85_Synonym/perl/synonym.pl | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100755 85_Synonym/perl/synonym.pl diff --git a/85_Synonym/perl/README.md b/85_Synonym/perl/README.md index e69c8b81..f947aea0 100644 --- a/85_Synonym/perl/README.md +++ b/85_Synonym/perl/README.md @@ -1,3 +1,7 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Perl](https://www.perl.org/) + +I used List::Util to do all the heavy work to show that perl can handle all the various +array functions. It would be interesting to see a version that handled all of this +manually as there ended up being very little code left in this program. diff --git a/85_Synonym/perl/synonym.pl b/85_Synonym/perl/synonym.pl new file mode 100755 index 00000000..37f32366 --- /dev/null +++ b/85_Synonym/perl/synonym.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +use v5.32; # for sample from List::Util, also includes 'use strict' +use warnings; # always a good idea + +use List::Util qw/ any sample shuffle /; # Rather than write our own utilities, use the built in ones + +my @correct = qw/ Right Correct Fine Good! Check /; + +# lowercase all words here +my @synonyms = ( + [ qw/ first start beginning onset initial / ], + [ qw/ similar alike same like resembling / ], + [ qw/ model pattern prototype standard criterion /], + [ qw/ small insignificant little tiny minute /], + [ qw/ stop halt stay arrest check standstill /], + [ qw/ house dwelling residense domicile lodging habitation /], + [ qw/ pit hole hollow well gulf chasm abyss /], + [ qw/ push shove thrust prod poke butt press /], + [ qw/ red rouge scarlet crimson flame ruby /], + [ qw/ pain suffering hurt misery distress ache discomfort /], +); + +print <<__END_OF_INTRO; + Synonym + Creative Computing Morristown, New Jersey + + + +A synonym of a word means another word in the English +language which has the same or very nearly the same meaning +I choose a word -- you type a synonym. +If you can't think of a synonym, type the word 'HELP' +and I will tell you a synonym. + +__END_OF_INTRO + +foreach my $drill ( shuffle @synonyms ) { + my $word = $drill->[0]; + my @answers = $drill->@[1 .. $drill->$#*]; + print " What is a synonym of $word? "; + my $response = <>; + chomp $response; + $response = lc $response; + + if ( $response eq 'help' ) { + say "**** A synonym of $word is ", sample(1, @answers); + redo; + } elsif ( not any { $response eq $_ } @answers ) { + say ' Try again.'; + redo; + } else { + say sample 1, @correct; + } +} + +say "\nSynonym drill completed."; + From edefbcea44b0791d090a35db58eebfac3ecc1d4e Mon Sep 17 00:00:00 2001 From: Andy Hardin <12464376+ahardin13@users.noreply.github.com> Date: Sun, 2 Jan 2022 15:55:47 -0500 Subject: [PATCH 493/749] Created C# slots.csx --- 80_Slots/csharp/README.md | 15 +++ 80_Slots/csharp/slots.csx | 190 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 80_Slots/csharp/slots.csx diff --git a/80_Slots/csharp/README.md b/80_Slots/csharp/README.md index 4daabb5c..4983614c 100644 --- a/80_Slots/csharp/README.md +++ b/80_Slots/csharp/README.md @@ -1,3 +1,18 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/) + +This C# implementation of slots was done using a [C# script](https://github.com/filipw/dotnet-script). + +# Required +[.NET Core SDK (i.e., .NET 6.0)](https://dotnet.microsoft.com/en-us/download) + +Install dotnet-script. On the command line run: +``` +dotnet tool install -g dotnet-script +``` + +# Run +``` +dotnet script .\slots.csx +``` \ No newline at end of file diff --git a/80_Slots/csharp/slots.csx b/80_Slots/csharp/slots.csx new file mode 100644 index 00000000..80a99a7e --- /dev/null +++ b/80_Slots/csharp/slots.csx @@ -0,0 +1,190 @@ +Print("SLOTS"); +Print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); +Print(); Print(); Print(); +Print("YOU ARE IN THE H&M CASINO,IN FRONT OF ONE OF OUR"); +Print("ONE-ARM BANDITS. BET FROM $1 TO $100."); +Print("TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET."); + +var _standings = 0; + +var play = true; +while(play) +{ + Play(); + play = PlayAgain(); +} + +Done(); + +public void Play() +{ + var bet = GetBet(); + Print(); + Ring(); + + var random = new Random(); + var x = GetSlot(); + var y = GetSlot(); + var z = GetSlot(); + + Print(); + Print($"{x.ToString()} {y.ToString()} {z.ToString()}"); + + if(x == y && x == z) + { + if(z == Slot.BAR) + { + // BAR BAR BAR + Print(); + Print("***JACKPOT***"); + Print("YOU WON!"); + _standings = (100*bet) + bet + _standings; + } + else + { + Print(); + Print("**TOP DOLLAR**"); + Print("YOU WON!"); + _standings = (10*bet) + bet + _standings; + } + } + else if(x == y) + { + if(y == Slot.BAR) + { + DoubleBar(bet); + } + else + { + Double(bet); + } + } + else if(x == z) + { + if(z == Slot.BAR) + { + DoubleBar(bet); + } + else + { + Lost(bet); + } + } + else if(y == z) + { + if(z == Slot.BAR) + { + DoubleBar(bet); + } + else + { + Double(bet); + } + } + else + { + Lost(bet); + } + + Print($"YOUR STANDINGS ARE ${_standings}"); +} + +public bool PlayAgain() +{ + Console.Write("AGAIN? (Y) "); + var playAgain = Console.ReadKey(true); + Print(); + return playAgain.Key == ConsoleKey.Y || playAgain.Key == ConsoleKey.Enter; +} + +public void Done() +{ + Print(); + if(_standings < 0) + { + Print("PAY UP! PLEASE LEAVE YOUR MONEY ON THE TERMINAL."); + } + else if (_standings == 0) + { + Print("HEY, YOU BROKE EVEN."); + } + else + { + Print("COLLECT YOUR WINNINGS FROM THE H&M CASHIER"); + } +} + +// Prints the text provided. Default is a blank line +public void Print(string line = "") +{ + Console.WriteLine(line); +} + +public int GetBet() +{ + Print(); + Console.Write("YOUR BET "); + var betInput = ReadLine(); + int bet; + var inputValid = int.TryParse(betInput, out bet); + if (!inputValid) + { + Print("NUMBER EXPECTED - RETRY"); + return GetBet(); + } + + if(bet > 100) + { + Print("HOUSE LIMITS ARE $100"); + inputValid = false; + } + else if(bet < 1) + { + Print("MINIMUM BET IS $1"); + inputValid = false; + } + + return inputValid ? bet : GetBet(); +} + +public enum Slot { BAR, BELL, ORANGE, LEMON, PLUM, CHERRY }; + +public Slot GetSlot() +{ + var rand = new Random(); + var num = rand.Next(0, 5); + return (Slot)num; +} + +public void DoubleBar(int bet) +{ + Print(); + Print("*DOUBLE BAR*"); + Print("YOU WON!"); + _standings = (5*bet) + bet + _standings; +} + +public void Double(int bet) +{ + Print(); + Print("DOUBLE!!"); + Print("YOU WON!"); + _standings = (2*bet) + bet + _standings; +} + +public void Lost(int bet) +{ + Print(); + Print("YOU LOST."); + _standings = _standings - bet; +} + +public void Ring() +{ + for(int i = 1; i <= 10; i++) + { + // https://stackoverflow.com/a/321148/1497 + Console.Beep(); + // Console.Beep(800, 501 - (i * 50)); // Uncomment for a fancier bell + } +} \ No newline at end of file From ee610c730ddfc6ffc0759b45ea384b6936198a25 Mon Sep 17 00:00:00 2001 From: Andy Hardin <12464376+ahardin13@users.noreply.github.com> Date: Sun, 2 Jan 2022 15:57:59 -0500 Subject: [PATCH 494/749] Added newline --- 80_Slots/csharp/slots.csx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/80_Slots/csharp/slots.csx b/80_Slots/csharp/slots.csx index 80a99a7e..b812d942 100644 --- a/80_Slots/csharp/slots.csx +++ b/80_Slots/csharp/slots.csx @@ -187,4 +187,4 @@ public void Ring() Console.Beep(); // Console.Beep(800, 501 - (i * 50)); // Uncomment for a fancier bell } -} \ No newline at end of file +} From f7231859ec9f25fd8cf464304fdc49e6a6acf7da Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Sun, 2 Jan 2022 16:42:32 -0500 Subject: [PATCH 495/749] Port War to Perl. --- 94_War/perl/war.pl | 153 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100755 94_War/perl/war.pl diff --git a/94_War/perl/war.pl b/94_War/perl/war.pl new file mode 100755 index 00000000..367a1185 --- /dev/null +++ b/94_War/perl/war.pl @@ -0,0 +1,153 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use Getopt::Long 2.33 qw{ :config auto_version }; +use List::Util qw{ shuffle }; +use Pod::Usage; +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +my %opt; + +GetOptions( \%opt, + qw{ unicode! }, + help => sub { pod2usage( { -verbose => 2 } ) }, +) or pod2usage( { -verbose => 0 } ); + +my @cards; +my $current_rank_value = 1; +my %rank_value; +my @suits = $opt{unicode} ? + ( map { chr } 0x2660 .. 0x2663 ) : + ( qw{ S H D C } ); +foreach my $rank ( ( 2 .. 10 ), qw{ J Q K A } ) { + $rank_value{$rank} = $current_rank_value++; + foreach my $suit ( @suits ) { + push @cards, "$suit-$rank"; + } +} + +$opt{unicode} + and binmode STDOUT, ':encoding(utf-8)'; + +@cards = shuffle( @cards ); + +print <<'EOD'; + WAR + Creative Computing Morristown, New Jersey + + + +This is the card game of War. Each card is given by suit-# +EOD + +# Create the readline object. +state $term = Term::ReadLine->new( 'word' ); + +my $resp = $term->readline( + "as $suits[0]-7 for Spade 7. Do you want directions? [y/N]: " ); +exit unless defined $resp; +if ( $resp =~ m/ \A y /smxi ) { + print <<'EOD'; +The computer gives you and it a 'card'. The higher card +(numerically) wins. The game ends when you choose not to +continue or when you have finished the pack. + +EOD +} + +my $your_score = my $computer_score = 0; + +while ( 1 ) { + my ( $you, $computer ) = splice @cards, 0, 2; + say ''; + say "You: $you; computer: $computer"; + my $result = $rank_value{ substr $you, 2 } <=> + $rank_value{ substr $computer, 2 }; + if ( $result < 0 ) { + $computer_score++; + say "The computer wins!!! ", + "You have $your_score and the computer has $computer_score"; + } elsif ( $result > 0 ) { + $your_score++; + say "You win. ", + "You have $your_score and the computer has $computer_score"; + } else { + say 'Tie. No score change.'; + } + + last unless @cards; + + $resp = $term->readline( 'Do you want to continue? [Y/n]: ' ); + last unless defined $resp; + last if $resp =~ m/ \A n /smxi; +} + +say "We have run out of cards. ", + "Final score: you: $your_score; the computer: $computer_score" + unless @cards; +say ''; +say 'Thanks for playing. It was fun.'; +__END__ + +=head1 TITLE + +war.pl - Play the game 'War' from Basic Computer Games + +=head1 SYNOPSIS + + war.pl + war.pl --help + war.pl --version + +=head1 OPTIONS + +=head2 --help + +This option displays the documentation for this script. The script then +exits. + +=head2 --unicode + +If this Boolean option is asserted, the suits are designated by their +Unicode glyphs rather than by ASCII letters. For these to display +properly your terminal must properly interpret Unicode. + +The default is C<--no-unicode>. + +=head2 --version + +This option displays the version of this script. The script then exits. + +=head1 DETAILS + +This Perl script is a port of C, which is the 94th entry in Basic +Computer Games. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From ede6acee55f7f2ba6bc2705a4751da7d33befb68 Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Sun, 2 Jan 2022 16:41:07 -0600 Subject: [PATCH 496/749] 82_Stars perl implementation --- 82_Stars/perl/stars.pl | 56 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100755 82_Stars/perl/stars.pl diff --git a/82_Stars/perl/stars.pl b/82_Stars/perl/stars.pl new file mode 100755 index 00000000..6c1b5392 --- /dev/null +++ b/82_Stars/perl/stars.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl + +use v5.11; # for say and use strict +use warnings; + +my $MAX_NUMBER = 100; +my $MAX_GUESSES = 7; + +print<<__END_OF_INTRO; + Stars + Creative Computing Morristown, New Jersey + + + +__END_OF_INTRO + +print "Do you want instructions? "; +chomp( my $answer = <> ); +if ( $answer !~ /^N/i ) { + print<<__END_OF_INSTRUCTIONS; +I am thinking of a whole number from 1 to $MAX_NUMBER +Try to guess my number. After you guess, I +will type one or more stars (*). The more +stars I type, the closer you are to my number. +One star (*) means far away, seven stars (*******) +means really close! You get $MAX_GUESSES guesses. +__END_OF_INSTRUCTIONS +} + + +while (1) { + my $number_to_guess = int(rand($MAX_NUMBER) + 1); + say "\n\nOK, I am thinking of a number, start guessing."; + + my $guess_number = 1; + while ( $guess_number <= $MAX_GUESSES ) { + print "\nYour Guess? "; + chomp( my $guess = <> ); + last if $guess == $number_to_guess; + $guess_number++; + my $difference = abs $guess - $number_to_guess; + print '*' if $difference < 2; + print '*' if $difference < 4; + print '*' if $difference < 8; + print '*' if $difference < 16; + print '*' if $difference < 32; + print '*' if $difference < 64; + print "*\n"; + } + if ( $guess_number > $MAX_GUESSES ) { # didn't guess + say "\nSorry, that's $MAX_GUESSES guesses, number was $number_to_guess"; + } else { # winner! + say '*' x 50, '!!!'; + say "You got it in $guess_number guesses!!! Let's play again..."; + } +} From 1c6984aa6935ef33026a540e0f7adff70fce1d97 Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Sun, 2 Jan 2022 18:19:53 -0500 Subject: [PATCH 497/749] MathDice in perl A version of MathDice written in perl --- 61_Math_Dice/perl/mathdice.pl | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 61_Math_Dice/perl/mathdice.pl diff --git a/61_Math_Dice/perl/mathdice.pl b/61_Math_Dice/perl/mathdice.pl new file mode 100644 index 00000000..f5a92459 --- /dev/null +++ b/61_Math_Dice/perl/mathdice.pl @@ -0,0 +1,121 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +&main; + +# Main subroutine + +sub main { + &print_intro; + while (1==1) { + &game_play; #function that actually plays the game + } +} + +sub game_play { + my $num = 0; + my $sum = 0; + my $tries = 0; + until ($num == 2) { # there are 2 dice rolls so we do it until the num equals 2 + $num++; + my $roll = 1+int rand(6); # getting a random number between 1 and 6 + &print_dice($roll); # function call to print out the dice + $sum = $sum + $roll; # keeping track of the summary + #print "Sum: $sum Roll: $roll\n"; + if ($num == 1) { + print " +\n"; # if its the first roll then print an addition sign + } + if ($num == 2) { + print " =\n"; # if its the second roll print the equals sign and wait for an answer + my $answer = ; + chomp($answer); + if ($answer == 0) { + die "You input '0', Thanks for playing!\n"; + } + elsif ($answer == $sum) { + print "RIGHT!\nTHE DICE ROLL AGAIN\n"; + } + else { # code execution if they don't get the right answer + print "NO,COUNT THE SPOTS AND GIVE ANOTHER ANSWER\n"; + $answer = ; + chomp($answer); + if ($answer == $sum){ + print "RIGHT!\nTHE DICE ROLL AGAIN\n"; + } + else { + print "N0, THE ANSWER IS $sum\n"; + } + + } + } + } +} + +sub print_dice { + my $roll = shift; + print " -----\n"; + if ($roll == 1) { + &print_blank; + &print_one_mid; + &print_blank; + } + if ($roll == 2) { + &print_one_left; + &print_blank; + &print_one_right; + } + if ($roll == 3) { + &print_one_left; + &print_one_mid; + &print_one_right; + } + if ($roll == 4) { + &print_two; + &print_blank; + &print_two; + } + if ($roll == 5) { + &print_two; + &print_one_mid; + &print_two; + } + if ($roll == 6) { + &print_two; + &print_two; + &print_two; + } + print " -----\n"; +} + +sub print_one_left { + print "I * I\n"; +} + +sub print_one_mid { + print "I * I\n"; +} + +sub print_one_right { + print "I * I\n"; +} + +sub print_two { + print "I * * I\n"; +} + +sub print_blank { + print "I I\n"; +} + +sub print_intro { + my $spaces = " "x31; + print "$spaces MATH DICE\n"; + $spaces = " "x15; + print "$spaces CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; + print "THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE.\n"; + print "WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION\n"; + print "MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY.\n"; + print "TO CONCLUDE THE LESSON, TYPE '0' AS YOUR ANSWER.\n\n\n"; +} From e8ec059b498d1b7d67cb449bba5fb7aff70a8617 Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Mon, 3 Jan 2022 00:21:00 +0100 Subject: [PATCH 498/749] Fix minor typo in Basic source of Acey-Ducey. As compared to the printed version. --- 01_Acey_Ducey/aceyducey.bas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01_Acey_Ducey/aceyducey.bas b/01_Acey_Ducey/aceyducey.bas index 2c8b1c3b..0b6f72db 100644 --- a/01_Acey_Ducey/aceyducey.bas +++ b/01_Acey_Ducey/aceyducey.bas @@ -10,7 +10,7 @@ 80 PRINT"IF YOU DO NOT WANT TO BET, INPUT A 0" 100 N=100 110 Q=100 -120 PRINT "YOU NOW HAVE";Q;"DOLLARS." +120 PRINT "YOU NOW HAVE ";Q;" DOLLARS." 130 PRINT 140 GOTO 260 210 Q=Q+M From b3b460779e33809cfefa89f96243609cacacbc8c Mon Sep 17 00:00:00 2001 From: Josh Gribbon Date: Sun, 2 Jan 2022 18:50:20 -0500 Subject: [PATCH 499/749] Move folder for consistency --- {90 Tower => 90_Tower}/csharp/Tower.sln | 0 {90 Tower => 90_Tower}/csharp/Tower/Game.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/Models/Needle.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/Models/Towers.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/Program.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/Congratulations.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskCountPrompt.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskCountQuit.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskCountRetry.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskNotInPlay.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskPrompt.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskQuit.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskRetry.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskUnavailable.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/IllegalMove.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/Instructions.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/Intro.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/NeedlePrompt.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/NeedleQuit.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/NeedleRetry.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/PlayAgainPrompt.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/Strings.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/TaskFinished.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/Thanks.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/Title.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/TooManyMoves.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Resources/YesNoPrompt.txt | 0 {90 Tower => 90_Tower}/csharp/Tower/Tower.csproj | 0 {90 Tower => 90_Tower}/csharp/Tower/UI/Input.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/UI/Prompt.cs | 0 {90 Tower => 90_Tower}/csharp/Tower/UI/TowerDisplay.cs | 0 31 files changed, 0 insertions(+), 0 deletions(-) rename {90 Tower => 90_Tower}/csharp/Tower.sln (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Game.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Models/Needle.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Models/Towers.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Program.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/Congratulations.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskCountPrompt.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskCountQuit.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskCountRetry.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskNotInPlay.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskPrompt.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskQuit.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskRetry.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/DiskUnavailable.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/IllegalMove.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/Instructions.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/Intro.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/NeedlePrompt.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/NeedleQuit.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/NeedleRetry.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/PlayAgainPrompt.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/Strings.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/TaskFinished.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/Thanks.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/Title.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/TooManyMoves.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Resources/YesNoPrompt.txt (100%) rename {90 Tower => 90_Tower}/csharp/Tower/Tower.csproj (100%) rename {90 Tower => 90_Tower}/csharp/Tower/UI/Input.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/UI/Prompt.cs (100%) rename {90 Tower => 90_Tower}/csharp/Tower/UI/TowerDisplay.cs (100%) diff --git a/90 Tower/csharp/Tower.sln b/90_Tower/csharp/Tower.sln similarity index 100% rename from 90 Tower/csharp/Tower.sln rename to 90_Tower/csharp/Tower.sln diff --git a/90 Tower/csharp/Tower/Game.cs b/90_Tower/csharp/Tower/Game.cs similarity index 100% rename from 90 Tower/csharp/Tower/Game.cs rename to 90_Tower/csharp/Tower/Game.cs diff --git a/90 Tower/csharp/Tower/Models/Needle.cs b/90_Tower/csharp/Tower/Models/Needle.cs similarity index 100% rename from 90 Tower/csharp/Tower/Models/Needle.cs rename to 90_Tower/csharp/Tower/Models/Needle.cs diff --git a/90 Tower/csharp/Tower/Models/Towers.cs b/90_Tower/csharp/Tower/Models/Towers.cs similarity index 100% rename from 90 Tower/csharp/Tower/Models/Towers.cs rename to 90_Tower/csharp/Tower/Models/Towers.cs diff --git a/90 Tower/csharp/Tower/Program.cs b/90_Tower/csharp/Tower/Program.cs similarity index 100% rename from 90 Tower/csharp/Tower/Program.cs rename to 90_Tower/csharp/Tower/Program.cs diff --git a/90 Tower/csharp/Tower/Resources/Congratulations.txt b/90_Tower/csharp/Tower/Resources/Congratulations.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/Congratulations.txt rename to 90_Tower/csharp/Tower/Resources/Congratulations.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskCountPrompt.txt b/90_Tower/csharp/Tower/Resources/DiskCountPrompt.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskCountPrompt.txt rename to 90_Tower/csharp/Tower/Resources/DiskCountPrompt.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskCountQuit.txt b/90_Tower/csharp/Tower/Resources/DiskCountQuit.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskCountQuit.txt rename to 90_Tower/csharp/Tower/Resources/DiskCountQuit.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskCountRetry.txt b/90_Tower/csharp/Tower/Resources/DiskCountRetry.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskCountRetry.txt rename to 90_Tower/csharp/Tower/Resources/DiskCountRetry.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskNotInPlay.txt b/90_Tower/csharp/Tower/Resources/DiskNotInPlay.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskNotInPlay.txt rename to 90_Tower/csharp/Tower/Resources/DiskNotInPlay.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskPrompt.txt b/90_Tower/csharp/Tower/Resources/DiskPrompt.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskPrompt.txt rename to 90_Tower/csharp/Tower/Resources/DiskPrompt.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskQuit.txt b/90_Tower/csharp/Tower/Resources/DiskQuit.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskQuit.txt rename to 90_Tower/csharp/Tower/Resources/DiskQuit.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskRetry.txt b/90_Tower/csharp/Tower/Resources/DiskRetry.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskRetry.txt rename to 90_Tower/csharp/Tower/Resources/DiskRetry.txt diff --git a/90 Tower/csharp/Tower/Resources/DiskUnavailable.txt b/90_Tower/csharp/Tower/Resources/DiskUnavailable.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/DiskUnavailable.txt rename to 90_Tower/csharp/Tower/Resources/DiskUnavailable.txt diff --git a/90 Tower/csharp/Tower/Resources/IllegalMove.txt b/90_Tower/csharp/Tower/Resources/IllegalMove.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/IllegalMove.txt rename to 90_Tower/csharp/Tower/Resources/IllegalMove.txt diff --git a/90 Tower/csharp/Tower/Resources/Instructions.txt b/90_Tower/csharp/Tower/Resources/Instructions.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/Instructions.txt rename to 90_Tower/csharp/Tower/Resources/Instructions.txt diff --git a/90 Tower/csharp/Tower/Resources/Intro.txt b/90_Tower/csharp/Tower/Resources/Intro.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/Intro.txt rename to 90_Tower/csharp/Tower/Resources/Intro.txt diff --git a/90 Tower/csharp/Tower/Resources/NeedlePrompt.txt b/90_Tower/csharp/Tower/Resources/NeedlePrompt.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/NeedlePrompt.txt rename to 90_Tower/csharp/Tower/Resources/NeedlePrompt.txt diff --git a/90 Tower/csharp/Tower/Resources/NeedleQuit.txt b/90_Tower/csharp/Tower/Resources/NeedleQuit.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/NeedleQuit.txt rename to 90_Tower/csharp/Tower/Resources/NeedleQuit.txt diff --git a/90 Tower/csharp/Tower/Resources/NeedleRetry.txt b/90_Tower/csharp/Tower/Resources/NeedleRetry.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/NeedleRetry.txt rename to 90_Tower/csharp/Tower/Resources/NeedleRetry.txt diff --git a/90 Tower/csharp/Tower/Resources/PlayAgainPrompt.txt b/90_Tower/csharp/Tower/Resources/PlayAgainPrompt.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/PlayAgainPrompt.txt rename to 90_Tower/csharp/Tower/Resources/PlayAgainPrompt.txt diff --git a/90 Tower/csharp/Tower/Resources/Strings.cs b/90_Tower/csharp/Tower/Resources/Strings.cs similarity index 100% rename from 90 Tower/csharp/Tower/Resources/Strings.cs rename to 90_Tower/csharp/Tower/Resources/Strings.cs diff --git a/90 Tower/csharp/Tower/Resources/TaskFinished.txt b/90_Tower/csharp/Tower/Resources/TaskFinished.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/TaskFinished.txt rename to 90_Tower/csharp/Tower/Resources/TaskFinished.txt diff --git a/90 Tower/csharp/Tower/Resources/Thanks.txt b/90_Tower/csharp/Tower/Resources/Thanks.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/Thanks.txt rename to 90_Tower/csharp/Tower/Resources/Thanks.txt diff --git a/90 Tower/csharp/Tower/Resources/Title.txt b/90_Tower/csharp/Tower/Resources/Title.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/Title.txt rename to 90_Tower/csharp/Tower/Resources/Title.txt diff --git a/90 Tower/csharp/Tower/Resources/TooManyMoves.txt b/90_Tower/csharp/Tower/Resources/TooManyMoves.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/TooManyMoves.txt rename to 90_Tower/csharp/Tower/Resources/TooManyMoves.txt diff --git a/90 Tower/csharp/Tower/Resources/YesNoPrompt.txt b/90_Tower/csharp/Tower/Resources/YesNoPrompt.txt similarity index 100% rename from 90 Tower/csharp/Tower/Resources/YesNoPrompt.txt rename to 90_Tower/csharp/Tower/Resources/YesNoPrompt.txt diff --git a/90 Tower/csharp/Tower/Tower.csproj b/90_Tower/csharp/Tower/Tower.csproj similarity index 100% rename from 90 Tower/csharp/Tower/Tower.csproj rename to 90_Tower/csharp/Tower/Tower.csproj diff --git a/90 Tower/csharp/Tower/UI/Input.cs b/90_Tower/csharp/Tower/UI/Input.cs similarity index 100% rename from 90 Tower/csharp/Tower/UI/Input.cs rename to 90_Tower/csharp/Tower/UI/Input.cs diff --git a/90 Tower/csharp/Tower/UI/Prompt.cs b/90_Tower/csharp/Tower/UI/Prompt.cs similarity index 100% rename from 90 Tower/csharp/Tower/UI/Prompt.cs rename to 90_Tower/csharp/Tower/UI/Prompt.cs diff --git a/90 Tower/csharp/Tower/UI/TowerDisplay.cs b/90_Tower/csharp/Tower/UI/TowerDisplay.cs similarity index 100% rename from 90 Tower/csharp/Tower/UI/TowerDisplay.cs rename to 90_Tower/csharp/Tower/UI/TowerDisplay.cs From 7e3304c907635ac2424737ca91e2c94d09c5e336 Mon Sep 17 00:00:00 2001 From: LukasMurdock Date: Sun, 2 Jan 2022 19:06:19 -0500 Subject: [PATCH 500/749] add 1-16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 16:Bug “If you elect to see all the pictures, this program has the ability of consuming well over six feet of terminal paper per run. We can only suggest recycling the paper by using the other side.” --- 01_Acey_Ducey/README.md | 13 +++++++++++-- 02_Amazing/README.md | 11 +++++++++-- 03_Animal/README.md | 17 ++++++++++++++++- 04_Awari/README.md | 33 ++++++++++++++++++++++++++++++++- 05_Bagels/README.md | 15 ++++++++++++++- 06_Banner/README.md | 9 ++++++++- 07_Basketball/README.md | 25 ++++++++++++++++++++++++- 08_Batnum/README.md | 17 +++++++++++++++-- 09_Battle/README.md | 22 +++++++++++++++++++++- 10_Blackjack/README.md | 13 +++++++++++-- 11_Bombardment/README.md | 13 +++++++++++-- 12_Bombs_Away/README.md | 11 +++++++++-- 13_Bounce/README.md | 13 +++++++++++-- 14_Bowling/README.md | 15 +++++++++++++-- 15_Boxing/README.md | 13 +++++++++++-- 16_Bug/README.md | 15 +++++++++++++-- 16 files changed, 229 insertions(+), 26 deletions(-) diff --git a/01_Acey_Ducey/README.md b/01_Acey_Ducey/README.md index 071a80e3..3434eb8e 100644 --- a/01_Acey_Ducey/README.md +++ b/01_Acey_Ducey/README.md @@ -1,7 +1,16 @@ ### Acey Ducey -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=2 +This is a simulation of the Acey Ducey card game. In the game, the dealer (the computer) deals two cards face up. You have an option to bet or not to bet depending on whether or not you feel the next card dealt will have a value between the first two. + +Your initial money is set to $100; you may want to alter this value if you want to start with more or less than $100. The game keeps going on until you lose all your money or interrupt the program. + +The original program author was Bill Palmby of Prairie View, Illinois. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=2) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=17) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/02_Amazing/README.md b/02_Amazing/README.md index 1e646723..8f7b271b 100644 --- a/02_Amazing/README.md +++ b/02_Amazing/README.md @@ -1,7 +1,14 @@ ### Amazing -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=3 +This program will print out a different maze every time it is run and guarantees only one path through. You can choose the dimensions of the maze — i.e. the number of squares wide and long. + +The original program author was Jack Hauber of Windsor, Connecticut. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=3) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=18) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/03_Animal/README.md b/03_Animal/README.md index 69256d87..defaa735 100644 --- a/03_Animal/README.md +++ b/03_Animal/README.md @@ -1,7 +1,22 @@ ### Animal +Unlike other computer games in which the computer picks a number or letter and you must guess what it is, in this game _you_ think of an animal and the _computer_ asks you questions and tries to guess the name of your animal. If the computer guesses incorrectly, it will ask you for a question that differentiates the animal you were thinking of. In this way the computer “learns” new animals. Questions to differentiate new animals should be input without a question mark. + +This version of the game does not have a SAVE feature. If your system allows, you may modify the program to save and reload the array when you want to play the game again. This way you can save what the computer learns over a series of games. + +At any time if you reply “LIST” to the question “ARE YOU THINKING OF AN ANIMAL,” the computer will tell you all the animals it knows so far. + +The program starts originally by knowing only FISH and BIRD. As you build up a file of animals you should use broad, general questions first and then narrow down to more specific ones with later animals. For example, if an elephant was to be your first animal, the computer would ask for a question to distinguish an elephant from a bird. Naturally, there are hundreds of possibilities, however, if you plan to build a large file of animals a good question would be “IS IT A MAMMAL.” + +This program can be easily modified to deal with categories of things other than animals by simply modifying the initial data and the dialogue references to animals. In an educational environment, this would be a valuable program to teach the distinguishing characteristics of many classes of objects — rock formations, geography, marine life, cell structures, etc. + +Originally developed by Arthur Luehrmann at Dartmouth College, Animal was subsequently shortened and modified by Nathan Teichholtz at DEC and Steve North at Creative Computing. + +--- + As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=4 +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=4) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=19) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/04_Awari/README.md b/04_Awari/README.md index 9356db80..a4b4d2da 100644 --- a/04_Awari/README.md +++ b/04_Awari/README.md @@ -1,7 +1,38 @@ ### Awari +Awari is an ancient African game played with seven sticks and thirty-six stones or beans laid out as shown above. The board is divided into six compartments or pits on each side. In addition, there are two special home pits at the ends. + +A move is made by taking all the beans from any (non-empty) pit on your own side. Starting from the pit to the right of this one, these beans are ‘sown’ one in each pit working around the board anticlockwise. + +A turn consists of one or two moves. If the last bean of your move is sown in your own home you may take a second move. + +If the last bean sown in a move lands in an empty pit, provided that the opposite pit is not empty, all the beans in the opposite pit, together with the last bean sown are ‘captured’ and moved to the player’s home. + +When either side is empty, the game is finished. The player with the most beans in his home has won. + +In the computer version, the board is printed as 14 numbers representing the 14 pits. + +``` + 3 3 3 3 3 3 +0 0 + 3 3 3 3 3 3 +``` + +The pits on your (lower) side are numbered 1-6 from left to right. The pits on my (the computer’s) side are numbered from my left (your right). + +To make a move you type in the number of a pit. If the last bean lands in your home, the computer types ‘AGAIN?’ and then you type in your second move. + +The computer’s move is typed, followed by a diagram of the board in its new state. The computer always offers you the first move. This is considered to be a slight advantage. + +There is a learning mechanism in the program that causes the play of the computer to improve as it playes more games. + +The original version of Awari is adopted from one originally written by Geoff Wyvill of Bradford, Yorkshire, England. + +--- + As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=6 +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=6) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=21) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/05_Bagels/README.md b/05_Bagels/README.md index e550e084..51d324bb 100644 --- a/05_Bagels/README.md +++ b/05_Bagels/README.md @@ -1,7 +1,20 @@ ### Bagels +In this game, the computer picks a 3-digit secret number using the digits 0 to 9 and you attempt to guess what it is. You are allowed up to twenty guesses. No digit is repeated. After each guess the computer will give you clues about your guess as follows: + +- PICO One digit is correct, but in the wrong place +- FERMI One digit is in the correct place +- BAGELS No digit is correct + +You will learn to draw inferences from the clues and, with practice, you’ll learn to improve your score. There are several good strategies for playing Bagels. After you have found a good strategy, see if you can improve it. Or try a different strategy altogether to see if it is any better. While the program allows up to twenty guesses, if you use a good strategy it should not take more than eight guesses to get any number. + +The original authors of this program are D. Resek and P. Rowe of the Lawrence Hall of Science, Berkeley, California. + +--- + As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=9 +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=9) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=21) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/06_Banner/README.md b/06_Banner/README.md index ac26214e..960b76cb 100644 --- a/06_Banner/README.md +++ b/06_Banner/README.md @@ -1,7 +1,14 @@ ### Banner +This program creates a large banner on a terminal of any message you input. The letters may be any dimension of you wish although the letter height plus distance from left-hand side should not exceed 6 inches. Experiment with the height and width until you get a pleasing effect on whatever terminal you are using. + +This program was written by Leonard Rosendust of Brooklyn, New York. + +--- + As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=10 +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=10) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=25) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/07_Basketball/README.md b/07_Basketball/README.md index ef44f631..158cba43 100644 --- a/07_Basketball/README.md +++ b/07_Basketball/README.md @@ -1,7 +1,30 @@ ### Basketball +This program simulates a game of basketball between Dartmouth College and an opponent of your choice. You are the Dartmouth captain and control the type of shot and defense during the course of the game. + +There are four types of shots: +1. Long Jump Shot (30ft) +2. Short Jump Shot (15ft) +3. Lay Up +4. Set Shot + +Both teams use the same defense, but you may call it: +- Enter (6): Press +- Enter (6.5): Man-to-man +- Enter (7): Zone +- Enter (7.5): None + +To change defense, type “0” as your next shot. + +Note: The game is biased slightly in favor of Dartmouth. The average probability of a Dartmouth shot being good is 62.95% compared to a probability of 61.85% for their opponent. (This makes the sample run slightly remarkable in that Cornell won by a score of 45 to 42 Hooray for the Big Red!) + +Charles Bacheller of Dartmouth College was the original author of this game. + +--- + As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=12 +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=12) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=27) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/08_Batnum/README.md b/08_Batnum/README.md index 4590dcf8..e5b4db83 100644 --- a/08_Batnum/README.md +++ b/08_Batnum/README.md @@ -1,7 +1,20 @@ ### Batnum -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=14 +The game starts with an imaginary pile of objects, coins for example. You and your opponent (the computer) alternately remove objects from the pile. You specify in advance the minimum and maximum number of objects that can be taken on each turn. You also specify in advance how winning is defined: +1. To take the last object +2. To avoid taking the last object + +You may also determine whether you or the computer go first. + +The strategy of this game is based on modulo arithmetic. If the maximum number of objects a player may remove in a turn is M, then to gain a winning position a player at the end of his turn must leave a stack of 1 modulo (M+1) coins. If you don’t understand this, play the game 23 Matches first, then BATNUM, and have fun! + +BATNUM is a generalized version of a great number of manual remove-the-object games. The original computer version was written by one of the two originators of the BASIC language, John Kemeny of Dartmouth College. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=14) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=29) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/09_Battle/README.md b/09_Battle/README.md index 0f5ada08..815cacd2 100644 --- a/09_Battle/README.md +++ b/09_Battle/README.md @@ -1,7 +1,27 @@ ### Battle +BATTLE is based on the popular game Battleship which is primarily played to familiarize people with the location and designation of points on a coordinate plane. + +BATTLE first randomly sets up the bad guy’s fleet disposition on a 6 by 6 matrix or grid. The fleet consists of six ships: +- Two destroyers (ships number 1 and 2) which are two units long +- Two cruisers (ships number 3 and 4) which are three units long +- Two aircraft carriers (ships number 5 and 6) which are four units long + +The program then prints out this fleet disposition in a coded or disguised format (see the sample computer print-out). You then proceed to sink the various ships by typing in the coordinates (two digits. each from 1 to 6, separated by a comma) of the place where you want to drop a bomb, if you’ll excuse the expression. The computer gives the appropriate response (splash, hit, etc.) which you should record on a 6 by 6 matrix. You are thus building a representation of the actual fleet disposition which you will hopefully use to decode the coded fleet disposition printed out by the computer. Each time a ship is sunk, the computer prints out which ships have been sunk so far and also gives you a “SPLASH/HIT RATIO.” + +The first thing you should learn is how to locate and designate positions on the matrix, and specifically the difference between “3,4” and “4,3.” Our method corresponds to the location of points on the coordinate plane rather than the location of numbers in a standard algebraic matrix: the first number gives the column counting from left to right and the second number gives the row counting from bottom to top. + +The second thing you should learn about is the splash/hit ratio. “What is a ratio?” A good reply is “It’s a fraction or quotient.” Specifically, the spash/hit ratio is the number of splashes divided by the number of hits. If you had 9 splashes and 15 hits, the ratio would be 9/15 or 3/5, both of which are correct. The computer would give this splash/hit ratio as .6. + +The main objective and primary education benefit of BATTLE comes from attempting to decode the bas guys’ fleet disposition code. To do this, you must make a comparison between the coded matrix and the actual matrix which you construct as you play the game. + +The original author of both the program and these descriptive notes is Ray Westergard of Lawrence Hall of Science, Berkeley, California. + +--- + As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=15 +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=15) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=30) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/10_Blackjack/README.md b/10_Blackjack/README.md index 3b3466bd..43cf263c 100644 --- a/10_Blackjack/README.md +++ b/10_Blackjack/README.md @@ -1,7 +1,16 @@ ### Blackjack -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=18 +This is a simulation of the card game of Blackjack or 21, Las Vegas style. This rather comprehensive version allows for up to seven players. On each hand a player may get another card (a hit), stand, split a hand in the event two identical cards were received or double down. Also, the dealer will ask for an insurance bet if he has an exposed ace. + +Cards are automatically reshuffled as the 51st card is reached. For greater realism, you may wish to change this to the 41st card. Actually, fanatical purists will want to modify the program so it uses three decks of cards instead of just one. + +This program originally surfaced at Digital Equipment Corp.; the author is unknown. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=18) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=33) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/11_Bombardment/README.md b/11_Bombardment/README.md index 6b4f6468..4ab31b05 100644 --- a/11_Bombardment/README.md +++ b/11_Bombardment/README.md @@ -1,7 +1,16 @@ ### Bombardment -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=22 +BOMBARDMENT is played on two, 5x5 grids or boards with 25 outpost locations numbered 1 to 25. Both you and the computer have four platoons of troops that can be located at any four outposts on your respective grids. + +At the start of the game, you locate (or hide) your four platoons on your grid. The computer does the same on it’s grid. You then take turns firing missiles or bombs at each other’s outposts trying to destroy all four platoons. The one who finds all four opponents’ platoons first, wins. + +This program was slightly modified from the original written by Martin Burdash of Parlin, New Jersey. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=22) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=37) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/12_Bombs_Away/README.md b/12_Bombs_Away/README.md index 1cdb7212..0baa3558 100644 --- a/12_Bombs_Away/README.md +++ b/12_Bombs_Away/README.md @@ -1,7 +1,14 @@ ### Bombs Away -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=24 +In this program, you fly a World War II bomber for one of the four protagonists of the war. You then pick your target or the type of plane you are flying. Depending on your flying experience and the quality of enemy defenders, you then may accomplish your mission, get shot down, or make it back through enemy fire. In any case, you get a change to fly again. + +David Ahl modified the original program which was created by David Sherman while a student at Curtis Jr. High School, Sudbury, Massachusetts. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=24) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=39) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/13_Bounce/README.md b/13_Bounce/README.md index cf17c363..396b534d 100644 --- a/13_Bounce/README.md +++ b/13_Bounce/README.md @@ -1,7 +1,16 @@ ### Bounce -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=25 +This program plots a bouncing ball. Most computer plots run along the paper in the terminal (top to bottom); however, this plot is drawn horizontally on the paper (left to right). + +You may specify the initial velocity of the ball and the coefficient of elasticity of the ball (a superball is about 0.85 — other balls are much less). You also specify the time increment to be used in “strobing” the flight of the ball. In other words, it is as though the ball is thrown up in a darkened room and you flash a light at fixed time intervals and photograph the progress of the ball. + +The program was originally written by Val Skalabrin while he was at DEC. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=25) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=40) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/14_Bowling/README.md b/14_Bowling/README.md index 0270868b..99a7fade 100644 --- a/14_Bowling/README.md +++ b/14_Bowling/README.md @@ -1,7 +1,18 @@ ### Bowling -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=26 +This is a simulated bowling game for up to four players. You play 10 frames. To roll the ball, you simply type “ROLL.” After each roll, the computer will show you a diagram of the remaining pins (“0” means the pin is down, “+” means it is still standing), and it will give you a roll analysis: +- GUTTER +- STRIKE +- SPARE +- ERROR (on second ball if pins still standing) + +Bowling was written by Paul Peraino while a student at Woodrow Wilson High School, San Francisco, California. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=26) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=41) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/15_Boxing/README.md b/15_Boxing/README.md index 380dd047..e3440676 100644 --- a/15_Boxing/README.md +++ b/15_Boxing/README.md @@ -1,7 +1,16 @@ ### Boxing -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=28 +This program simulates a three-round Olympic boxing match. The computer coaches one of the boxers and determines his punches and defences, while you do the same for your boxer. At the start of the match, you may specify your man’s best punch and his vulnerability. + +There are approximately seven major punches per round, although this may be varied. The best out if three rounds wins. + +Jesse Lynch of St. Paul, Minnesota created this program. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=28) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=43) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/16_Bug/README.md b/16_Bug/README.md index 2ce4c19a..136123ce 100644 --- a/16_Bug/README.md +++ b/16_Bug/README.md @@ -1,7 +1,18 @@ ### Bug -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=30 +The object of this game is to finish your drawing of a bug before the computer finishes. + +You and the computer roll a die alternately with each number standing for a part of the bug. You must add the parts in the right order; in other words, you cannot have a neck until you have a body, you cannot have a head until you have a neck, and so on. After each new part has been added, you have the option of seeing pictures of the two bugs. + +If you elect to see all the pictures, this program has the ability of consuming well over six feet of terminal paper per run. We can only suggest recycling the paper by using the other side. + +Brian Leibowitz wrote this program while in the 7th grade at Harrison Jr-Se High School in Harrison, New York. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=30) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=45) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html From 48522ba27d7fa7ba2a55684126743af66feb1883 Mon Sep 17 00:00:00 2001 From: John Long Date: Sun, 2 Jan 2022 16:26:25 -0800 Subject: [PATCH 501/749] Add Kotlin version of Animal Animal fascinated me as a kid. I wrote a version in Modula-2 for a Junior High School project. Didn't realize at the time I was studying binary trees. --- 03_Animal/kotlin/Animal.kt | 119 +++++++++++++++++++++++++++++++++++++ 03_Animal/kotlin/README.md | 3 + 2 files changed, 122 insertions(+) create mode 100644 03_Animal/kotlin/Animal.kt create mode 100644 03_Animal/kotlin/README.md diff --git a/03_Animal/kotlin/Animal.kt b/03_Animal/kotlin/Animal.kt new file mode 100644 index 00000000..bac9af08 --- /dev/null +++ b/03_Animal/kotlin/Animal.kt @@ -0,0 +1,119 @@ +/** + * ANIMAL + * + * + * Converted from BASIC to Kotlin by John Long (@patimen) + * + * Animal is basically a perfect example of a binary tree. Implement it + * as such, with the QuestionNode either having an answer if it is a terminal node + * or a Question + */ + +fun main() { + printIntro() + val rootQuestionNode = + QuestionOrAnswer(question = Question("DOES IT SWIM", QuestionOrAnswer("FISH"), QuestionOrAnswer("BIRD"))) + while (true) { + val choice = ask("ARE YOU THINKING OF AN ANIMAL") + when { + choice == "LIST" -> printKnownAnimals(rootQuestionNode) + choice.startsWith("Q") -> return + choice.startsWith("Y") -> { + // A wrong answer means it's a new animal! + val wrongAnswer = rootQuestionNode.getWrongAnswer() + if (wrongAnswer == null) { + // The computer got the right answer! + println("WHY NOT TRY ANOTHER ANIMAL?") + } else { + // Get a new question to ask next time + wrongAnswer.askForInformationAndSave() + } + } + } + } +} + +// Takes care of asking a question (on the same line) and getting +// an answer or a blank string +fun ask(question: String): String { + print("$question? ") + return readLine()?.uppercase() ?: "" +} + +// Special case for a "yes or no" question, returns true of yes +fun askYesOrNo(question: String): Boolean { + return generateSequence { + print("$question? ") + readLine() + }.firstNotNullOf { yesOrNo(it) } +} + +// If neither Y (true) or N (false), return null, so the above sequence +// will just keep executing until it gets the answer +private fun yesOrNo(string: String): Boolean? = + when (string.uppercase().firstOrNull()) { + 'Y' -> true + 'N' -> false + else -> null + } + +private fun printKnownAnimals(question: QuestionOrAnswer) { + println("\nANIMALS I ALREADY KNOW ARE:") + val animals = question.getAnswers().chunked(4) + animals.forEach { line -> + // The '*' in front of line.toTypedArray() "spreads" the array as a list of parameters instead + System.out.printf("%-15s".repeat(line.size), *line.toTypedArray()) + println() + } +} + +private fun printIntro() { + println(" ANIMAL") + println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + println("\n\n") + println("PLAY 'GUESS THE ANIMAL'") + println("\n") + println("THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.") +} + +class QuestionOrAnswer(private var answer: String? = null, var question: Question? = null) { + fun getAnswers(): List = answer?.let { listOf(it) } ?: question!!.getAnswers() + fun getWrongAnswer(): QuestionOrAnswer? { + if (answer != null) { + // "takeUnless" will return null if the answer is "yes". In this case + // we will return the "wrong answer", aka the terminal answer that was incorrect + return this.takeUnless { askYesOrNo("IS IT A $answer") } + } + return question?.getWrongAnswer() + } + + fun askForInformationAndSave() { + //Failed to get it right and ran out of questions + //Let's ask the user for the new information + val newAnimal = ask("THE ANIMAL YOU WERE THINKING OF WAS A") + val newQuestion = ask("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A \n$newAnimal FROM A $answer\n") + val newAnswer = askYesOrNo("FOR A $newAnimal THE ANSWER WOULD BE") + + val trueAnswer = if (newAnswer) newAnimal else answer + val falseAnswer = if (newAnswer) answer else newAnimal + // Replace our answer with null and set the question with the data we just got + // This makes it a question instead of an answer + this.answer = null + this.question = Question(newQuestion, QuestionOrAnswer(trueAnswer), QuestionOrAnswer(falseAnswer)) + } +} + +class Question( + private val question: String, + private val trueAnswer: QuestionOrAnswer, + private val falseAnswer: QuestionOrAnswer +) { + fun getAnswers(): List = trueAnswer.getAnswers() + falseAnswer.getAnswers() + + fun getWrongAnswer(): QuestionOrAnswer? = + if (askYesOrNo(question)) { + trueAnswer.getWrongAnswer() + } else { + falseAnswer.getWrongAnswer() + } +} diff --git a/03_Animal/kotlin/README.md b/03_Animal/kotlin/README.md new file mode 100644 index 00000000..f43a5b70 --- /dev/null +++ b/03_Animal/kotlin/README.md @@ -0,0 +1,3 @@ +Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) + +Conversion to [Kotlin](https://kotlinlang.org/) From 436f904abfd74af8f9faa775ce4f60932d47f63c Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Sun, 2 Jan 2022 18:31:50 -0600 Subject: [PATCH 502/749] Adjust spacing to match original Various minor tweaks --- 61_Math_Dice/perl/mathdice.pl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/61_Math_Dice/perl/mathdice.pl b/61_Math_Dice/perl/mathdice.pl index f5a92459..4a2b6f6e 100644 --- a/61_Math_Dice/perl/mathdice.pl +++ b/61_Math_Dice/perl/mathdice.pl @@ -25,24 +25,25 @@ sub game_play { $sum = $sum + $roll; # keeping track of the summary #print "Sum: $sum Roll: $roll\n"; if ($num == 1) { - print " +\n"; # if its the first roll then print an addition sign + print "\n +\n\n"; # if its the first roll then print an addition sign } if ($num == 2) { - print " =\n"; # if its the second roll print the equals sign and wait for an answer + print " =? "; # if its the second roll print the equals sign and wait for an answer my $answer = ; chomp($answer); if ($answer == 0) { die "You input '0', Thanks for playing!\n"; } elsif ($answer == $sum) { - print "RIGHT!\nTHE DICE ROLL AGAIN\n"; + print "RIGHT!\n\nTHE DICE ROLL AGAIN\n\n"; } else { # code execution if they don't get the right answer print "NO,COUNT THE SPOTS AND GIVE ANOTHER ANSWER\n"; + print " =? "; $answer = ; chomp($answer); if ($answer == $sum){ - print "RIGHT!\nTHE DICE ROLL AGAIN\n"; + print "RIGHT!\n\nTHE DICE ROLL AGAIN\n\n"; } else { print "N0, THE ANSWER IS $sum\n"; From 90b0abe4c601fb46b3e284ed7b738353ea675885 Mon Sep 17 00:00:00 2001 From: Chris Aitchison Date: Mon, 3 Jan 2022 11:52:17 +1100 Subject: [PATCH 503/749] Add Ruby implementation of Rock Scissors Paper --- 74_Rock_Scissors_Paper/ruby/rockscissors.rb | 80 +++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 74_Rock_Scissors_Paper/ruby/rockscissors.rb diff --git a/74_Rock_Scissors_Paper/ruby/rockscissors.rb b/74_Rock_Scissors_Paper/ruby/rockscissors.rb new file mode 100644 index 00000000..9b24ac9a --- /dev/null +++ b/74_Rock_Scissors_Paper/ruby/rockscissors.rb @@ -0,0 +1,80 @@ +SCREEN_WIDTH = 72 + +MOVE_WORDS = { + 1 => 'PAPER', + 2 => 'SCISSORS', + 3 => 'ROCK' +} + +WIN_TABLE = { + 1 => 3, + 2 => 1, + 3 => 2 +} + +def center_text(text) + text.rjust((SCREEN_WIDTH / 2) + (text.size / 2)) +end + +def ask_for_number_of_games + loop do + puts "HOW MANY GAMES" + response = STDIN.gets.to_i + return response if response > 0 and response < 11 + puts "SORRY, BUT WE AREN'T ALLOWED TO PLAY THAT MANY." + end +end + +def ask_for_human_move + loop do + puts "3=ROCK...2=SCISSORS...1=PAPER" + puts "1...2...3...WHAT'S YOUR CHOICE" + response = STDIN.gets.to_i + return response if [1,2,3].include?(response) + puts "INVALID" + end +end + +def calculate_result(human_move, computer_move) + return 'TIE' if human_move == computer_move + return 'WIN' if WIN_TABLE[human_move] == computer_move + 'LOSE' +end + +puts center_text('GAME OF ROCK, SCISSORS, PAPER') +puts center_text('CREATIVE COMPUTING MORRISTOWN, NEW JERSEY') +puts +puts +puts + +number_of_games = ask_for_number_of_games +games_won = 0 +games_lost = 0 + +number_of_games.times do |game_number| + puts + puts "GAME NUMBER #{game_number + 1}" + computer_move = rand(3) + 1 + human_move = ask_for_human_move + puts "THIS IS MY CHOICE..." + puts "...#{MOVE_WORDS[computer_move]}" + + case calculate_result(human_move, computer_move) + when 'WIN' + puts "YOU WIN!!!" + games_won += 1 + when 'TIE' + puts "TIE GAME. NO WINNER." + when 'LOSE' + puts "WOW! I WIN!!!" + games_lost = games_lost += 1 + end +end + +puts +puts "HERE IS THE FINAL GAME SCORE:" +puts "I HAVE WON #{games_lost} GAME(S)." +puts "YOU HAVE WON #{games_won} GAME(S)." +puts "AND #{number_of_games - (games_lost + games_won)} GAME(S) ENDED IN A TIE." +puts "THANKS FOR PLAYING!!" + From d6446929121c7fc05cfc7e2c4e2e168205d648bd Mon Sep 17 00:00:00 2001 From: Alaa Sarhan Date: Sun, 2 Jan 2022 08:13:52 +0100 Subject: [PATCH 504/749] implement the 13th game - Bounce in ruby --- 13_Bounce/ruby/bounce.rb | 181 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 13_Bounce/ruby/bounce.rb diff --git a/13_Bounce/ruby/bounce.rb b/13_Bounce/ruby/bounce.rb new file mode 100644 index 00000000..97c42999 --- /dev/null +++ b/13_Bounce/ruby/bounce.rb @@ -0,0 +1,181 @@ +## Global constants + +# Gravity accelaration (F/S^2) ~= 32 +G = 32 + +# Used to indent the plotting of ball positions +# so that the height digits don't affect +# where we start plotting ball positions +BALL_PLOT_INDENT = "\t" + +# The deviation between current plotted height and the actual +# height of the ball that we will accept to plot the ball in +# that plotted height +BALL_PLOT_DEVIATION = 0.25 + +# The step we will take as we move down vertically while +# plotting ball positions +BALL_PLOT_HEIGHT_STEP = 0.5 + + +## Helper functions + +# Calculates the bounce speed (up) of the ball for a given +# bounce number and coefficient +def calc_velocity_for_bounce(v0, bounce, coefficient) + v = v0 * coefficient**bounce +end + +# Check https://physics.stackexchange.com/a/333436 for nice explanation +def calc_bounce_total_time(v0, bounce, coefficient) + v = calc_velocity_for_bounce(v0, bounce, coefficient) + t = 2 * v / G +end + +# Check https://physics.stackexchange.com/a/333436 for nice explanation +def calc_ball_height(v0, bounce, coefficient, t) + v = calc_velocity_for_bounce(v0, bounce, coefficient) + h = v * t - 0.5 * G * t**2 +end + +def heighest_position_in_next_bounce(time_in_bounce, i) + time_in_next_bounce = time_in_bounce[i+1] + return -1 if time_in_next_bounce.nil? + return calc_ball_height(v0, i, c, time_in_next_bounce / 2) unless time_in_next_bounce.nil? +end + +def intro + puts <<~INSTRUCTIONS + BOUNCE + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY + OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF + ELASTICITY OF THE BALL. PLEASE USE A DECIMAL FRACTION + COEFFICIENCY (LESS THAN 1). + + YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN + 'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY). + INSTRUCTIONS +end + + +## Plottin functions + +def plot_header + puts + puts "FEET" +end + +def plot_bouncing_ball(strobbing_time, v0, c) + ## Initializing helper values + + # How many bounces we want to plot + # original BASIC version is 70 / (V / (16 * S2)) + # 70 is assumed to be an arbitrary number higher than 2G and 16 is 1/2G + bounces_to_plot = (G**2 / (v0 / strobbing_time)).to_i + + # Holds the total time the ball spends in the air in every bounce + time_in_bounce = bounces_to_plot.times.map { |i| calc_bounce_total_time v0, i, c } + + plot_width = 0 + + # Calculate the highest position for the ball after the very first bounce + plot_y = (calc_ball_height(v0, 0, c, v0/G) + 0.5).to_i + + while plot_y >= 0 do + # We will print only whole-number heights + print plot_y.to_i if plot_y.to_i === plot_y + + print BALL_PLOT_INDENT + + bounces_to_plot.times { |i| + (0..time_in_bounce[i]).step(strobbing_time) { |t| + ball_pos = calc_ball_height v0, i, c, t + + # If the ball is within the acceptable deviation + # from the current height, we will plot it + if (plot_y - ball_pos).abs <= BALL_PLOT_DEVIATION then + print "0" + else + print " " + end + + # Increment the plot width when we are plotting height = 0 + # which will definitely be the longest since it never gets + # skipped by line 98 + plot_width += 1 if plot_y == 0 + } + + if heighest_position_in_next_bounce(time_in_bounce, i) < plot_y then + # If we got no more ball positions at or above current height, we can skip + # the rest of the bounces and move down to the next height to plot + puts + break + end + } + + plot_y -= BALL_PLOT_HEIGHT_STEP + end + + # Return plot_width to be used by the plot_footer + plot_width +end + +def plot_footer (plot_width, strobbing_time) + # Dotted separator line + puts + print BALL_PLOT_INDENT + (plot_width).times { |_| print "." } + puts + + # Time values line + print BALL_PLOT_INDENT + points_in_sec = (1 / strobbing_time).to_i + plot_width.times { |i| + if i % points_in_sec == 0 then + print (i / points_in_sec).to_i + else + print " " + end + } + puts + + # Time unit line + print BALL_PLOT_INDENT + (plot_width / 2 - 4).to_i.times { |_| print " " } + puts "SECONDS" + puts +end + +def game_loop + # Read strobing, velocity and coefficient parameters from user input + puts "TIME INCREMENT (SEC)" + strobbing_time = gets.to_f + + puts "VELOCITY (FPS)" + v0 = gets.to_f + + puts "COEFFICIENT" + c = gets.to_f + + ## Plotting + plot_header + + plot_width = plot_bouncing_ball strobbing_time, v0, c + + plot_footer plot_width, strobbing_time +end + +## Entry point +begin + intro + while true + game_loop + end +rescue SystemExit, Interrupt + exit +rescue => exception + p exception +end \ No newline at end of file From 3f42a1b4d63f18cb927a3a08ffce8b5900171058 Mon Sep 17 00:00:00 2001 From: Alaa Sarhan Date: Mon, 3 Jan 2022 02:06:08 +0100 Subject: [PATCH 505/749] add newline eof --- 13_Bounce/ruby/bounce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/13_Bounce/ruby/bounce.rb b/13_Bounce/ruby/bounce.rb index 97c42999..9740509d 100644 --- a/13_Bounce/ruby/bounce.rb +++ b/13_Bounce/ruby/bounce.rb @@ -178,4 +178,4 @@ rescue SystemExit, Interrupt exit rescue => exception p exception -end \ No newline at end of file +end From 807d6e5bf53f5b216f8d24874f08a40e6731a3d3 Mon Sep 17 00:00:00 2001 From: Alaa Sarhan Date: Mon, 3 Jan 2022 02:15:59 +0100 Subject: [PATCH 506/749] fix missing parameters --- 13_Bounce/ruby/bounce.rb | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/13_Bounce/ruby/bounce.rb b/13_Bounce/ruby/bounce.rb index 9740509d..339c7851 100644 --- a/13_Bounce/ruby/bounce.rb +++ b/13_Bounce/ruby/bounce.rb @@ -38,7 +38,7 @@ def calc_ball_height(v0, bounce, coefficient, t) h = v * t - 0.5 * G * t**2 end -def heighest_position_in_next_bounce(time_in_bounce, i) +def heighest_position_in_next_bounce(time_in_bounce, v0, i, c) time_in_next_bounce = time_in_bounce[i+1] return -1 if time_in_next_bounce.nil? return calc_ball_height(v0, i, c, time_in_next_bounce / 2) unless time_in_next_bounce.nil? @@ -82,11 +82,12 @@ def plot_bouncing_ball(strobbing_time, v0, c) plot_width = 0 # Calculate the highest position for the ball after the very first bounce - plot_y = (calc_ball_height(v0, 0, c, v0/G) + 0.5).to_i + plotted_height = (calc_ball_height(v0, 0, c, v0/G) + 0.5).to_i - while plot_y >= 0 do + ## Plotting bouncing ball + while plotted_height >= 0 do # We will print only whole-number heights - print plot_y.to_i if plot_y.to_i === plot_y + print plotted_height.to_i if plotted_height.to_i === plotted_height print BALL_PLOT_INDENT @@ -96,7 +97,7 @@ def plot_bouncing_ball(strobbing_time, v0, c) # If the ball is within the acceptable deviation # from the current height, we will plot it - if (plot_y - ball_pos).abs <= BALL_PLOT_DEVIATION then + if (plotted_height - ball_pos).abs <= BALL_PLOT_DEVIATION then print "0" else print " " @@ -105,10 +106,10 @@ def plot_bouncing_ball(strobbing_time, v0, c) # Increment the plot width when we are plotting height = 0 # which will definitely be the longest since it never gets # skipped by line 98 - plot_width += 1 if plot_y == 0 + plot_width += 1 if plotted_height == 0 } - if heighest_position_in_next_bounce(time_in_bounce, i) < plot_y then + if heighest_position_in_next_bounce(time_in_bounce, v0, i, c) < plotted_height then # If we got no more ball positions at or above current height, we can skip # the rest of the bounces and move down to the next height to plot puts @@ -116,7 +117,7 @@ def plot_bouncing_ball(strobbing_time, v0, c) end } - plot_y -= BALL_PLOT_HEIGHT_STEP + plotted_height -= BALL_PLOT_HEIGHT_STEP end # Return plot_width to be used by the plot_footer @@ -160,7 +161,7 @@ def game_loop puts "COEFFICIENT" c = gets.to_f - ## Plotting + # Plotting plot_header plot_width = plot_bouncing_ball strobbing_time, v0, c @@ -168,7 +169,9 @@ def game_loop plot_footer plot_width, strobbing_time end -## Entry point + +## Game entry point + begin intro while true From e2d2cfcc8449cba7fe86c7ba44238d5d0fc8d817 Mon Sep 17 00:00:00 2001 From: Josh Gribbon Date: Sun, 2 Jan 2022 20:55:24 -0500 Subject: [PATCH 507/749] Add script to find missing implementations --- find-missing-implementations.js | 85 +++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 find-missing-implementations.js diff --git a/find-missing-implementations.js b/find-missing-implementations.js new file mode 100644 index 00000000..04cf3f84 --- /dev/null +++ b/find-missing-implementations.js @@ -0,0 +1,85 @@ +/** + * Program to find games that are missing solutions in a given language + * + * Scan each game folder, check for a folder for each language, and also make + * sure there's at least one file of the expected extension and not just a + * readme or something + */ + +const fs = require("fs"); +const glob = require("glob"); + +// relative path to the repository root +const ROOT_PATH = "."; + +const languages = [ + { name: "csharp", extension: "cs" }, + { name: "java", extension: "java" }, + { name: "javascript", extension: "js" }, + { name: "pascal", extension: "pas" }, + { name: "perl", extension: "pl" }, + { name: "python", extension: "py" }, + { name: "ruby", extension: "rb" }, + { name: "vbnet", extension: "vb" }, +]; + +const getFilesRecursive = async (path, extension) => { + return new Promise((resolve, reject) => { + glob(`${path}/**/*.${extension}`, (err, matches) => { + if (err) { + reject(err); + } + resolve(matches); + }); + }); +}; + +const getPuzzleFolders = () => { + return fs + .readdirSync(ROOT_PATH, { withFileTypes: true }) + .filter((dirEntry) => dirEntry.isDirectory()) + .filter((dirEntry) => ![".git", "node_modules"].includes(dirEntry.name)) + .map((dirEntry) => dirEntry.name); +}; + +(async () => { + let missingGames = {}; + let missingLanguageCounts = {}; + const puzzles = getPuzzleFolders(); + for (const puzzle of puzzles) { + for (const { name: language, extension } of languages) { + const files = await getFilesRecursive( + `${ROOT_PATH}/${puzzle}/${language}`, + extension + ); + if (files.length === 0) { + if (!missingGames[puzzle]) { + missingGames[puzzle] = []; + } + if (!missingLanguageCounts[language]) { + missingLanguageCounts[language] = 0; + } + missingGames[puzzle].push(language); + missingLanguageCounts[language]++; + } + } + } + const missingCount = Object.values(missingGames).flat().length; + if (missingCount === 0) { + console.log("All games have solutions for all languages"); + } else { + console.log(`Missing ${missingCount} implementations:`); + + console.log(`\nMissing languages by game:`); + for (const [puzzle, languages] of Object.entries(missingGames)) { + console.log(`${puzzle}: ${languages.join(", ")}`); + } + + console.log(`\nBy language:`); + for (const [language, count] of Object.entries(missingLanguageCounts)) { + console.log(`${language}: ${count} missing`); + } + } +})(); + +return; From 3fd1d6b0af88b84d295a14205709315de5369a8b Mon Sep 17 00:00:00 2001 From: Toby Donaldson Date: Sun, 2 Jan 2022 22:57:42 -0800 Subject: [PATCH 508/749] added evenwins.py --- 35_Even_Wins/python/evenwins.py | 206 ++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 35_Even_Wins/python/evenwins.py diff --git a/35_Even_Wins/python/evenwins.py b/35_Even_Wins/python/evenwins.py new file mode 100644 index 00000000..fba20024 --- /dev/null +++ b/35_Even_Wins/python/evenwins.py @@ -0,0 +1,206 @@ +# evenwins.py + +# +# This version of evenwins.bas based on game decscription and does *not* +# follow the source. The computer chooses marbles at random. +# +# For simplicity, global variables are used to store the game state. +# A good exercise would be to replace this with a class. +# +# The code is not short, but hopefully it is easy for beginners to understand +# and modify. +# +# Infinite loops of the style "while True:" are used to simplify some of the +# code. The "continue" keyword is used in a few places to jump back to the top +# of the loop. The "return" keyword is also used to break out of functions. +# This is generally considered poor style, but in this case it simplifies the +# code and makes it easier to read (at least in my opinion). A good exercise +# would be to remove these infinite loops, and uses of continue, to follow a +# more structured style. +# + +import random + +# global variables +marbles_in_middle = -1 +human_marbles = -1 +computer_marbles = -1 +whose_turn = '' + +# Only called during development for serious errors that are due to mistakes +# in the program. Should never be called during a regular game. +def serious_error(msg): + print('serious_error: ' + msg) + exit(1) + +def welcome_screen(): + print('Welcome to Even Wins!') + print('Based on evenwins.bas from Creative Computing') + print() + print('Even Wins is a two-person game. You start with') + print('27 marbles in the middle of the table.') + print() + print('Players alternate taking marbles from the middle.') + print('A player can take 1 to 4 marbles on their turn, and') + print('turns cannot be skipped. The game ends when there are') + print('no marbles left, and the winner is the one with an even') + print('number of marbles.') + print() + +def marbles_str(n): + if n == 1: return '1 marble' + return f'{n} marbles' + +def choose_first_player(): + global whose_turn + while True: + ans = input('Do you want to play first? (y/n) --> ') + if ans == 'y': + whose_turn = 'human' + return + elif ans == 'n': + whose_turn = 'computer' + return + else: + print() + print('Please enter "y" if you want to play first,') + print('or "n" if you want to play second.') + print() + +def next_player(): + global whose_turn + if whose_turn == 'human': + whose_turn = 'computer' + elif whose_turn == 'computer': + whose_turn = 'human' + else: + serious_error(f'play_game: unknown player {whose_turn}') + +# Converts a string s to an int, if possible. +def to_int(s): + try: + n = int(s) + return True, n + except: + return False, 0 + +def print_board(): + global marbles_in_middle + global human_marbles + global computer_marbles + print() + print(f' marbles in the middle: {marbles_in_middle} ' + marbles_in_middle*'*') + print(f' # marbles you have: {human_marbles}') + print(f'# marbles computer has: {computer_marbles}') + print() + +def human_turn(): + global marbles_in_middle + global human_marbles + + # get number in range 1 to min(4, marbles_in_middle) + max_choice = min(4, marbles_in_middle) + print("It's your turn!") + while True: + s = input(f'Marbles to take? (1 - {max_choice}) --> ') + ok, n = to_int(s) + if not ok: + print() + print(f' Please enter a whole number from 1 to {max_choice}') + print() + continue + if n < 1: + print() + print(' You must take at least 1 marble!') + print() + continue + if n > max_choice: + print() + print(f' You can take at most {marbles_str(max_choice)}') + print() + continue + print() + print(f'Okay, taking {marbles_str(n)} ...') + marbles_in_middle -= n + human_marbles += n + return + +def game_over(): + global marbles_in_middle + global human_marbles + global computer_marbles + print() + print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + print('!! All the marbles are taken: Game Over!') + print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + print() + print_board() + if human_marbles % 2 == 0: + print('You are the winner! Congratulations!') + else: + print('The computer wins: all hail mighty silicon!') + print('') + +def computer_turn(): + global marbles_in_middle + global computer_marbles + + print("It's the computer's turn ...") + max_choice = min(4, marbles_in_middle) + + # choose at random + n = random.randint(1, max_choice) + print(f'Computer takes {marbles_str(n)} ...') + marbles_in_middle -= n + computer_marbles += n + +def play_game(): + global marbles_in_middle + global human_marbles + global computer_marbles + + # initialize the game state + marbles_in_middle = 27 + human_marbles = 0 + computer_marbles = 0 + print_board() + + while True: + if marbles_in_middle == 0: + game_over() + return + elif whose_turn == 'human': + human_turn() + print_board() + next_player() + elif whose_turn == 'computer': + computer_turn() + print_board() + next_player() + else: + serious_error(f'play_game: unknown player {whose_turn}') + +def main(): + global whose_turn + + welcome_screen() + + while True: + choose_first_player() + play_game() + + # ask if the user if they want to play again + print() + again = input('Would you like to play again? (y/n) --> ') + if again == 'y': + print() + print("Ok, let's play again ...") + print() + else: + print() + print('Ok, thanks for playing ... goodbye!') + print() + return + +if __name__ == '__main__': + main() From bd6c6ead8dae6eb9e63b92f0cfec7c54bb25d802 Mon Sep 17 00:00:00 2001 From: John Long Date: Sun, 2 Jan 2022 23:02:01 -0800 Subject: [PATCH 509/749] Add Kotlin to War --- 94_War/kotlin/README.md | 3 ++ 94_War/kotlin/War.kt | 108 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 94_War/kotlin/README.md create mode 100644 94_War/kotlin/War.kt diff --git a/94_War/kotlin/README.md b/94_War/kotlin/README.md new file mode 100644 index 00000000..f43a5b70 --- /dev/null +++ b/94_War/kotlin/README.md @@ -0,0 +1,3 @@ +Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) + +Conversion to [Kotlin](https://kotlinlang.org/) diff --git a/94_War/kotlin/War.kt b/94_War/kotlin/War.kt new file mode 100644 index 00000000..0b8b9ee3 --- /dev/null +++ b/94_War/kotlin/War.kt @@ -0,0 +1,108 @@ +/** + * Converted FROM BASIC to Kotlin by John Long, with hints from the Java by Nahid Mondol. + * + */ + +val suits = listOf("S", "H", "C", "D") +val ranks = listOf("2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A") + +// Create the deck programmatically +val fullDeck = suits.flatMap { suit -> + ranks.map { rank -> + Card(suit, rank) + } +} + +class Card(private val suit: String, private val rank: String) { + // Allow comparison of cards to each other + operator fun compareTo(other: Card): Int = this.rankValue.compareTo(other.rankValue) + // We can figure relative rank by the order in the ranks value + private val rankValue: Int = ranks.indexOf(rank) + override fun toString(): String = "$suit-$rank" +} + +fun main() { + introMessage() + showDirectionsBasedOnInput() + playGame() + println("THANKS FOR PLAYING. IT WAS FUN.") +} + +private fun introMessage() { + println("\t WAR") + println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + println("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#") + print("AS S-7 FOR SPADE 7. DO YOU WANT DIRECTIONS? ") +} + +private fun showDirectionsBasedOnInput() { + if (getYesOrNo()) { + println("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD") + println("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO ") + println("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n") + } +} + +// Stay in loop until player chooses an option, then return "true" for yes or "false" for no +private fun getYesOrNo() = generateSequence { readln() }.firstNotNullOf { it.asYesOrNo } + +// Since this returns null for an incorrect value, above firstNotNullOf will keep looping until +// we get something valid +private val String.asYesOrNo: Boolean? + get() = + when (this.lowercase()) { + "yes" -> true + "no" -> false + else -> { + println("YES OR NO, PLEASE. ") + null + } + } + + +private fun playGame() { + // Shuffle the deck than break it into 26 pairs + val pairs = fullDeck.shuffled().chunked(2) + val score = Score(0, 0) + val lastPlayerCard = pairs.last().first() + // We use "destructuring" to extract the pair of cards directly to a variable here + pairs.forEach { (playerCard, computerCard) -> + println("YOU: $playerCard\tCOMPUTER: $computerCard") + when { + playerCard > computerCard -> score.playerWins() + computerCard > playerCard -> score.computerWins() + else -> println("TIE. NO SCORE CHANGE.") + } + // Doesn't make sense to ask to continue if we have no more cards left to deal + if (playerCard != lastPlayerCard) { + println("DO YOU WANT TO CONTINUE") + if (!getYesOrNo()) { + return + } + } + } + score.printFinalScore() + return +} + + +class Score(private var player: Int, private var computer: Int) { + fun playerWins() { + player++ + printScore("YOU WIN.") + } + + fun computerWins() { + computer++ + printScore("THE COMPUTER WINS!!!") + } + + private fun printScore(text: String) { + println("$text YOU HAVE $player AND THE COMPUTER HAS $computer") + } + + // Only print if you go through the whole deck + fun printFinalScore() { + println("WE HAVE RUN OUT OF CARDS. FINAL SCORE: YOU: $player THE COMPUTER:$computer") + } +} From 76c5e1e995e71c12508e7417c7a8ce72cc446a84 Mon Sep 17 00:00:00 2001 From: LukasMurdock Date: Mon, 3 Jan 2022 02:13:21 -0500 Subject: [PATCH 510/749] add 17-96 --- 17_Bullfight/README.md | 22 +++++++- 18_Bullseye/README.md | 33 ++++++++++- 19_Bunny/README.md | 5 +- 20_Buzzword/README.md | 11 +++- 21_Calendar/README.md | 20 ++++++- 22_Change/README.md | 9 ++- 23_Checkers/README.md | 13 ++++- 24_Chemist/README.md | 11 +++- 25_Chief/README.md | 13 ++++- 26_Chomp/README.md | 13 ++++- 27_Civil_War/README.md | 15 ++++- 28_Combat/README.md | 13 ++++- 29_Craps/README.md | 16 +++++- 30_Cube/README.md | 11 +++- 31_Depth_Charge/README.md | 13 ++++- 32_Diamond/README.md | 11 +++- 33_Dice/README.md | 18 +++++- 34_Digits/README.md | 14 ++++- 35_Even_Wins/README.md | 15 ++++- 36_Flip_Flop/README.md | 25 ++++++++- 37_Football/README.md | 15 ++++- 38_Fur_Trader/README.md | 13 ++++- 39_Golf/README.md | 12 +++- 40_Gomoko/README.md | 13 ++++- 41_Guess/README.md | 13 ++++- 42_Gunner/README.md | 13 ++++- 43_Hammurabi/README.md | 19 ++++++- 44_Hangman/README.md | 23 +++++++- 45_Hello/README.md | 13 ++++- 46_Hexapawn/README.md | 13 ++++- 47_Hi-Lo/README.md | 18 +++++- 48_High_IQ/README.md | 13 ++++- 49_Hockey/README.md | 13 ++++- 50_Horserace/README.md | 11 +++- 51_Hurkle/README.md | 13 ++++- 52_Kinema/README.md | 16 +++++- 53_King/README.md | 15 ++++- 54_Letter/README.md | 11 +++- 55_Life/README.md | 32 ++++++++++- 56_Life_for_Two/README.md | 41 +++++++++++++- 57_Literature_Quiz/README.md | 11 +++- 58_Love/README.md | 11 +++- 59_Lunar_LEM_Rocket/README.md | 21 ++++++- 60_Mastermind/README.md | 26 ++++++++- 61_Math_Dice/README.md | 11 +++- 62_Mugwump/README.md | 15 ++++- 63_Name/README.md | 11 +++- 64_Nicomachus/README.md | 15 ++++- 65_Nim/README.md | 24 +++++++- 66_Number/README.md | 11 +++- 67_One_Check/README.md | 26 ++++++++- 68_Orbit/README.md | 54 +++++++++++++++++- 69_Pizza/README.md | 13 ++++- 70_Poetry/README.md | 26 ++++++++- 71_Poker/README.md | 13 ++++- 72_Queen/README.md | 13 ++++- 73_Reverse/README.md | 28 +++++++++- 74_Rock_Scissors_Paper/README.md | 18 +++++- 75_Roulette/README.md | 13 ++++- 76_Russian_Roulette/README.md | 11 +++- 77_Salvo/README.md | 22 +++++++- 78_Sine_Wave/README.md | 9 ++- 79_Slalom/README.md | 13 ++++- 80_Slots/README.md | 15 ++++- 81_Splat/README.md | 13 ++++- 82_Stars/README.md | 13 ++++- 83_Stock_Market/README.md | 13 ++++- 84_Super_Star_Trek/README.md | 96 +++++++++++++++++++++++++++++++- 85_Synonym/README.md | 19 ++++++- 86_Target/README.md | 13 ++++- 87_3-D_Plot/README.md | 13 ++++- 89_Tic-Tac-Toe/README.md | 22 +++++++- 90_Tower/README.md | 17 +++++- 91_Train/README.md | 13 ++++- 92_Trap/README.md | 16 +++++- 93_23_Matches/README.md | 15 ++++- 94_War/README.md | 11 +++- 95_Weekday/README.md | 13 ++++- 96_Word/README.md | 13 ++++- 79 files changed, 1201 insertions(+), 160 deletions(-) diff --git a/17_Bullfight/README.md b/17_Bullfight/README.md index c666ea37..d31bc4e2 100644 --- a/17_Bullfight/README.md +++ b/17_Bullfight/README.md @@ -1,7 +1,25 @@ ### Bullfight -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=32 +In this simulated bullfight, you are the matador — i.e., the one with the principle role and the one who must kill the bull or be killed (or run from the ring). + +On each pass of the bull, you may try: +- 0: Veronica (dangerous inside move of the cape) +- 1: Less dangerous outside move of the cape +- 2: Ordinary swirl of the cape + +Or you may try to kill the bull: +- 4: Over the horns +- 5: In the chest + +The crowd will determine what award you deserve, posthumously if necessary. The braver you are, the better the reward you receive. It’s nice to stay alive too. The better the job the picadores and toreadores do, the better your chances. + +David Sweet of Dartmouth wrote the original version of this program. It was then modified by students at Lexington High School and finally by Steve North of Creative Computing. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=32) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=47) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/18_Bullseye/README.md b/18_Bullseye/README.md index 789ad793..0c42872e 100644 --- a/18_Bullseye/README.md +++ b/18_Bullseye/README.md @@ -1,7 +1,36 @@ ### Bullseye -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=34 +In this game, up to 20 players throw darts at a target with 10-, 20-, 30-, and 40-point zones. The objective is to get 200 points. + +You have a choice of three methods of throwing: + +| Throw | Description | Probable Score | +|-------|--------------------|---------------------------| +| 1 | Fast overarm | Bullseye or complete miss | +| 2 | Controlled overarm | 10, 20, or 30 points | +| 3 | Underarm | Anything | + +You will find after playing a while that different players will swear by different strategies. However, considering the expected score per throw by always using throw 3: + +| Score (S) | Probability (P) | S x P | +|-----------|-----------------|-------| +| 40 | 1.00-.95 = .05 | 2 | +| 30 | .95-.75 = .20 | 6 | +| 30 | .75-.45 = .30 | 6 | +| 10 | .45-.05 = .40 | 4 | +| 0 | .05-.00 = .05 | 0 | + +Expected score per throw = 18 + +Calculate the expected score for the other throws and you may be surprised! + +The program was written by David Ahl of Creative Computing. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=34) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=49) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/19_Bunny/README.md b/19_Bunny/README.md index 4df27297..8d980287 100644 --- a/19_Bunny/README.md +++ b/19_Bunny/README.md @@ -1,7 +1,8 @@ ### Bunny -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=35 +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=35) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=50) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/20_Buzzword/README.md b/20_Buzzword/README.md index 034d7e5f..22e76f6f 100644 --- a/20_Buzzword/README.md +++ b/20_Buzzword/README.md @@ -1,7 +1,14 @@ ### Buzzword -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=36 +This program is an invaluable aid for preparing speeches and briefings about educational technology. This buzzword generator provides sets of three highly-acceptable words to work into your material. Your audience will never know that the phrases don’t really mean much of anything because they sound so great! Full instructions for running are given in the program. + +This version of Buzzword was written by David Ahl. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=36) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=51) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/21_Calendar/README.md b/21_Calendar/README.md index b6198acc..5a93d50d 100644 --- a/21_Calendar/README.md +++ b/21_Calendar/README.md @@ -1,7 +1,23 @@ ### Calendar -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=37 +This program prints out a calendar for any year. You must specify the starting day of the week of the year: +- 0: Sunday +- -1: Monday +- -2: Tuesday +- -3: Wednesday +- -4: Thursday +- -5: Friday +- -6: Saturday + +You can determine this by using the program WEEKDAY. You must also make two changes for leap years. The program listing describes the necessary changes. Running the program produces a nice 12-month calendar. + +The program was written by Geoffrey Chase of the Abbey, Portsmouth, Rhode Island. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=37) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=52) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/22_Change/README.md b/22_Change/README.md index 1a0f1297..840714a4 100644 --- a/22_Change/README.md +++ b/22_Change/README.md @@ -1,7 +1,12 @@ ### Change -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=39 +In this program, the computer pretends it is the cashier at your friendly neighborhood candy store. You tell it the cost of the item(s) you are buying, the amount of your payment, and it will automatically (!) determine your correct change. Aren’t machines wonderful? Dennis Lunder of People’s Computer Company wrote this program. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=39) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=54) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/23_Checkers/README.md b/23_Checkers/README.md index 0a3c57a2..d6936ea9 100644 --- a/23_Checkers/README.md +++ b/23_Checkers/README.md @@ -1,7 +1,16 @@ ### Checkers -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=40 +This program plays checkers. The pieces played by the computer are marked with an “X”, yours are marked “O”. A move is made by specifying the coordinates of the piece to be moved (X, Y). Home (0,0) is in the bottom left and X specifies distance to the right of home (i.e., column) and Y specifies distance above home (i.e. row). You then specify where you wish to move to. + +THe original version of the program by Alan Segal was not able to recognize (or permit) a double or triple jump. If you tried one, it was likely that your piece would disappear altogether! + +Steve North of Creative Computing rectified this problem and Lawrence Neal contributed modifications to allow the program to tell which player has won the game. The computer does not play a particularly good game but we leave it to _you_ to improve that. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=40) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=55) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/24_Chemist/README.md b/24_Chemist/README.md index afd39752..95db3f66 100644 --- a/24_Chemist/README.md +++ b/24_Chemist/README.md @@ -1,7 +1,14 @@ ### Chemist -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=42 +The fictitious chemical, kryptocyanic acid, can only be diluted by the ratio of 7 parts water to 3 parts acid. Any other ratio causes an unstable compound which soon explodes. Given an amount of acid, you must determine how much water to add to the dilution. If you’re more than 5% off, you lose one of your nine lives. The program continues to play until you lose all nine lives or until it is interrupted. + +It was originally written by Wayne Teeter of Ridgecrest, California. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=42) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=57) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/25_Chief/README.md b/25_Chief/README.md index f90a7121..5cb044c0 100644 --- a/25_Chief/README.md +++ b/25_Chief/README.md @@ -1,7 +1,16 @@ ### Chief -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=43 +In the words of the program author, John Graham, “CHIEF is designed to give people (mostly kids) practice in the four operations (addition, multiplication, subtraction, and division). + +It does this while giving people some fun. And then, if the people are wrong, it shows them how they should have done it. + +CHIEF was written by John Graham of Upper Brookville, New York. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=43) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=58) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/26_Chomp/README.md b/26_Chomp/README.md index 3774589a..e9a8b5ce 100644 --- a/26_Chomp/README.md +++ b/26_Chomp/README.md @@ -1,7 +1,16 @@ ### Chomp -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=44 +This program is an adaptation of a mathematical game originally described by Martin Gardner in the January 1973 issue of _Scientific American_. Up to a 9x9 grid is set up by you with the upper left square in a poison square. This grid is the cookie. Players alternately chomp away at the cookie from the lower right. To take a chomp, input a row and column number of one of the squares remaining on the cookie. All of the squares below and to the right of that square, including that square, disappear. + +Any number of people can play — the computer is only the moderator; it is not a player. Two-person strategies are interesting to work out but strategies when three or more people are playing are the real challenge. + +The computer version of the game was written by Peter Sessions of People’s Computer Company. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=44) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=59) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/27_Civil_War/README.md b/27_Civil_War/README.md index 9f3e4126..17d6816f 100644 --- a/27_Civil_War/README.md +++ b/27_Civil_War/README.md @@ -1,7 +1,18 @@ ### Civil War -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=46 +This simulation is based on 14 battles in the Civil War. Facts and figures are based on the actual occurrence. If you follow the same strategy used in the actual battle, the results will be the same. Generally, this is a good strategy since the generals in the Civil War were fairly good military strategists. However, you can frequently outperform the Civil War generals, particularly in cases where they did not have good enemy intelligence and consequently followed a poor course of action. Naturally, it helps to know your Civil War history, although the computer gives yuo the rudiments. + +After each of the 14 battles, your casualties are compared to the actual casualties of the battle, and you are told whether you win or lose the battle. + +You may play Civil War alone in which case the program simulates the Union general. Or two players may play in which case the computer becomes the moderator. + +Civil War was written in 1968 by three Students in Lexington High School, Massachusetts: L. Cram, L. Goodie, and D. Hibbard. It was modified into a 2-player game by G. Paul and R. Hess of TIES, St. Paul, Minnesota. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=46) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=61) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/28_Combat/README.md b/28_Combat/README.md index cc4be30a..32b2af65 100644 --- a/28_Combat/README.md +++ b/28_Combat/README.md @@ -1,7 +1,16 @@ ### Combat -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=50 +In this game, you are fighting a small-scale war with the computer. You have 72,000 troops which you first ust distribute among your Army, Navy, and Air Force. You may distribute them in any way you choose as long as you don’t use more than 72,000. + +You then attack your opponent (the computer) and input which service and the number of men you wish to use. The computer then tells you the outcome of the battle, gives you the current statistics and allows you to determine your next move. + +After the second battle, it is decided from the total statistics whether you win or lose or if a treaty is signed. + +This program was created by Bob Dores of Milton, Massachusetts. + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=50) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=65) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/29_Craps/README.md b/29_Craps/README.md index 673957f4..7372b99f 100644 --- a/29_Craps/README.md +++ b/29_Craps/README.md @@ -1,7 +1,19 @@ ### Craps -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=52 +This game simulates the game of craps played according to standard Nevada craps table rules. That is: +1. A 7 or 11 on the first roll wins +2. A 2, 3, or 12 on the first roll loses +3. Any other number rolled becomes your “point.” + - You continue to roll, if you get your point, you win. + - If you roll a 7, you lose and the dice change hands when this happens. + +This version of craps was modified by Steve North of Creative Computing. It is based on an original which appeared one day on a computer at DEC. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=52) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=67) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/30_Cube/README.md b/30_Cube/README.md index 067606e3..41973db1 100644 --- a/30_Cube/README.md +++ b/30_Cube/README.md @@ -1,7 +1,14 @@ ### Cube -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=53 +CUBE is a game played on the facing sides of a cube with a side dimension of 2. A location is designated by three numbers — e.g., 1, 2, 1. The object is to travel from 1, 1, 1 to 3, 3, 3 by moving one horizontal or vertical (not diagonal) square at a time without striking one of 5 randomly placed landmines. You are staked to $500; prior to each play of the game you may make a wager whether you will reach your destination. You lose if you hit a mine or try to make an illegal move — i.e., change more than one digit from your previous position. + +Cube was created by Jerimac Ratliff of Fort Worth, Texas. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=53) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=68) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/31_Depth_Charge/README.md b/31_Depth_Charge/README.md index 4c11da12..1a0ed7a4 100644 --- a/31_Depth_Charge/README.md +++ b/31_Depth_Charge/README.md @@ -1,7 +1,16 @@ ### Depth Charge -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=55 +In this program you are captain of the destroyer USS Computer. An enemy submarine has been causing trouble and your mission is to destroy it. You may select the seize of the “cube” of water you wish to search in. The computer then determines how many depth charges you get to destroy the submarine. + +Each depth charge is exploded by you specifying a trio of numbers; the first two are the surface coordinates (X,Y), the third is the depth. After each depth charge, your sonar observer will tell you where the explosion was relative to the submarine. + +Dana Noftle wrote this program while a student at Acton High School, Acton, Massachusetts. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=55) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=70) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/32_Diamond/README.md b/32_Diamond/README.md index 36bdb9e2..1f155ba3 100644 --- a/32_Diamond/README.md +++ b/32_Diamond/README.md @@ -1,7 +1,14 @@ ### Diamond -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=56 +This program fills an 8.5x11 piece of paper with diamonds (plotted on a hard-copy terminal, of course). The program asks for an odd number to be input in the range 5 to 31. The diamonds printed will be this number of characters high and wide. The number of diamonds across the page will vary from 12 for 5-character wide diamonds to 1 for a diamond 31-characters wide. You can change the content of the pattern if you wish. + +The program was written by David Ahl of Creative Computing. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=56) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=71) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/33_Dice/README.md b/33_Dice/README.md index 27cc7029..71406a01 100644 --- a/33_Dice/README.md +++ b/33_Dice/README.md @@ -1,7 +1,21 @@ ### Dice -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=57 +Not exactly a game, this program simulates rolling a pair of dice a large number of times and prints out the frequency distribution. You simply input the number of rolls. It is interesting to see how many rolls are necessary to approach the theoretical distribution: + +| | | | +|---|------|------------| +| 2 | 1/36 | 2.7777...% | +| 3 | 2/36 | 5.5555...% | +| 4 | 3/36 | 8.3333...% | +etc. + +Daniel Freidus wrote this program while in the seventh grade at Harrison Jr-Sr High School, Harrison, New York. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=57) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=72) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/34_Digits/README.md b/34_Digits/README.md index e2cf78a9..b1c96819 100644 --- a/34_Digits/README.md +++ b/34_Digits/README.md @@ -1,7 +1,17 @@ ### Digits -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=58 +The player writes down a set of 30 numbers (0, 1, or 2) at random prior to playing the game. The computer program, using pattern recognition techniques, attempts to guess the next number in your list. + +The computer asks for 10 numbers at a time. It always guesses first and then examines the next number to see if it guessed correctly. By pure luck (or chance or probability), the computer ought to be right 10 times. It is uncanny how much better it generally does than that! + +This program originated at Dartmouth; original author unknown. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=58) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=73) + Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/35_Even_Wins/README.md b/35_Even_Wins/README.md index 71c7d18e..9db7654b 100644 --- a/35_Even_Wins/README.md +++ b/35_Even_Wins/README.md @@ -1,7 +1,18 @@ ### Even Wins -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=60 +This is a game between you and the computer. To play, an odd number of objects (marbles, chips, matches) are placed in a row. You take turns with the computer picking up between one and four objects each turn. The game ends when there are no objects left, and the winner is the one with an even number of objects picked up. + +Two versions of this game are included. While to the player they appear similar, the programming approach is quite different. EVEN WINS, the first version, is deterministic — i.e., the computer plays by fixed, good rules and is impossible to beat if you don’t know how to play the game. It always starts with 27 objects, although you may change this. + +The second version, GAME OF EVEN WINS, is much more interesting because the computer starts out only knowing the rules of the game. Using simple techniques of artificial intelligence (cybernetics), the computer gradually learns to play this game from its mistakes until it plays a very good game. After 20 games, the computer is a challenge to beat. Variation in the human’s style of play seems to make the computer learn more quickly. If you plot the learning curve of this program, it closely resembles classical human learning curves from psychological experiments. + +Eric Peters at DEC wrote the GAME OF EVEN WINS. The original author of EVEN WINS is unknown. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=60) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=75) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/36_Flip_Flop/README.md b/36_Flip_Flop/README.md index 689e6f7a..5f32111d 100644 --- a/36_Flip_Flop/README.md +++ b/36_Flip_Flop/README.md @@ -1,7 +1,28 @@ ### Flip Flop -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=63 +The object of this game is to change a row of ten X’s + +``` +X X X X X X X X X X +``` + +to a row of ten 0’s + +``` +0 0 0 0 0 0 0 0 0 0 +``` + +by typing in a number corresponding to the position of an “X” in the line. On some numbers one position will change while on other numbers, two will change. For example, inputting a 3 may reverse the X and 0 in position 3, but it might possibly reverse some of other position too! You ought to be able to change all 10 in 12 or fewer moves. Can you figure out a good winning strategy? + +To reset the line to all X’s (same game), type 0 (zero). To start a new game at any point, type 11. + +The original author of this game was Micheal Kass of New Hyde Park, New York. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=63) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=78) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/37_Football/README.md b/37_Football/README.md index ccfe99e3..7f791861 100644 --- a/37_Football/README.md +++ b/37_Football/README.md @@ -1,7 +1,18 @@ ### Football -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=64 +Football is probably the most popular simulated sports game. I have seen some people play to elect to play computerized football in preference to watching a football game on television. + +Two versions of football are presented. The first is somewhat “traditional” in that you, the player, are playing against the computer. You have a choice of seven offensive plays. On defense the computer seems to play a zone defence, but you have no choice of plays. The computer program presents the necessary rules as you play, and it is also the referee and determines penalties when an infraction is committed. FTBALL was written by John Kemeny at Dartmouth. + +IN the second version of football, the computer referees a game played between two human players. Each player gets a list of twenty plays with a code value for each one. This list should be kept confidential from your opponent. The codes can be changes in data. All twenty plays are offensive; a defensive play is specified by defending against a type of offensive play. A defense is good for other similar types of plays, for example, a defense against a flare pass is very good against a screen pass but much less good against a half-back option. + +This game was originally written by Raymond Miseyka of Butler, Pennsylvania. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=64) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=79) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/38_Fur_Trader/README.md b/38_Fur_Trader/README.md index 503c089b..676b605b 100644 --- a/38_Fur_Trader/README.md +++ b/38_Fur_Trader/README.md @@ -1,7 +1,16 @@ ### Fur Trader -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=69 +You are the leader of a French fur trading expedition in 1776 leaving the Ontario area to sell furs and get supplies for the next year. You have a choice of three forts at which you may trade. The cost of supplies and the amount you recieve for your furs will depend upon the fort you choose. You also specify what types of furs that you have to trade. + +The game goes on and on until you elect to trade no longer. + +Author of the program is Dan Bachor, University of Calgary, Alberta, Canada. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=69) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=84) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/39_Golf/README.md b/39_Golf/README.md index a2292d02..28da3594 100644 --- a/39_Golf/README.md +++ b/39_Golf/README.md @@ -1,7 +1,15 @@ ### Golf -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=71 +This is a single player golf game. In other words it’s you against the golf course (the computer). The program asks for your handicap (maximum of 30) and your area of difficulty. You have a bag of 29 clubs plus a putter. On the course you have to contend with rough, trees, on and off fairway, sand traps, and water hazards. In addition, you can hook, slice, go out of bounds, or hit too far. On putting, you determine the potency factor (or percent of swing). Until you get the swing of the game (no pun intended), you’ll probably was to use a fairly high handicap. + +Steve North of Creative Computing modified the original version of this game, the author of which is unknown. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=71) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=86) + Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/40_Gomoko/README.md b/40_Gomoko/README.md index 3f32ea2a..9b6ad6b6 100644 --- a/40_Gomoko/README.md +++ b/40_Gomoko/README.md @@ -1,7 +1,16 @@ ### Gomoko -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=74 +GOMOKO or GOMOKU is a traditional game of the Orient. It is played by two people on a board of intersecting lines (19 left-to-right lines, 19 top-to-bottom lines, 361 intersections in all). Players take turns. During his turn, a player may cover one intersection with a marker; (one player uses white markers; the other player uses black markers). The object of the game is to get five adjacent markers in a row, horizontally, vertically or along either diagonal. + +Unfortunately, this program does not make the computer a very good player. It does not know when you are about to win or even who has won. But some of its moves may surprise you. + +The original author of this program is Peter Sessions of People’s Computer Company. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=74) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=89) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/41_Guess/README.md b/41_Guess/README.md index e9876af9..cb041db7 100644 --- a/41_Guess/README.md +++ b/41_Guess/README.md @@ -1,7 +1,16 @@ ### Guess -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=75 +In Program GUESS, the computer chooses a random integer between 0 and any limit you set. You must then try to guess the number the computer has chosen using the clues provided by the computer. + +You should be able to guess the number in one less than the number of digits needed to represent the number in binary notation — i.e., in base 2. This ought to give you a clue as to the optimum search technique. + +GUESS converted from the original program in FOCAL which appeared in the book “Computers in the Classroom” by Walt Koetke of Lexington High School, Lexington, Massachusetts. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=75) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=90) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/42_Gunner/README.md b/42_Gunner/README.md index 4969ff20..0621ec54 100644 --- a/42_Gunner/README.md +++ b/42_Gunner/README.md @@ -1,7 +1,16 @@ ### Gunner -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=77 +GUNNER allows you to adjust the fire of a field artillery weapon to hit a stationary target. You specify the number of degrees of elevation of your weapon; 45 degrees provides maximum range with values under or over 45 degrees providing less range. + +You get up to five shots to destroy the enemy before he destroys you. Gun range varies between 20,000 and 60,000 yards and burst radius is 100 yards. You must specify elevation within approximately 0.2 degrees to get a hit. + +Tom Kloos of the Oregon Museum of Science and Industry in Portland, Oregon originally wrote GUNNER. Extensive modifications were added by David Ahl. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=77) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=92) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/43_Hammurabi/README.md b/43_Hammurabi/README.md index 22378ac0..c92b7ee3 100644 --- a/43_Hammurabi/README.md +++ b/43_Hammurabi/README.md @@ -1,7 +1,22 @@ ### Hammurabi -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=78 +In this game you direct the administrator of Sumeria, Hammurabi, how to manage the city. The city initially has 1,000 acres, 100 people and 3,000 bushels of grain in storage. + +You may buy and sell land with your neighboring city-states for bushels of grain — the price will vary between 17 and 26 bushels per acre. You also must use grain to feed your people and as seed to plant the next year’s crop. + +You will quickly find that a certain number of people can only tend a certain amount of land and that people starve if they are not fed enough. You also have the unexpected to contend with such as a plague, rats destroying stored grain, and variable harvests. + +You will also find that managing just the few resources in this game is not a trivial job over a period of say ten years. The crisis of population density rears its head very rapidly. + +This program was originally written in Focal at DEC; author unknown. David Ahl converted it to BASIC and added the 10-year performance assessment. If you wish to change any of the factors, the extensive remarks in the program should make modification fairly straightforward. + +Note for trivia buffs: somewhere along the line an m was dropped out of the spelling of Hammurabi in hte Ahl version of the computer program. This error has spread far and wide until a generation of students now think that Hammurabi is the incorrect spelling. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=78) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=93) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/44_Hangman/README.md b/44_Hangman/README.md index e44b0c0a..ee533251 100644 --- a/44_Hangman/README.md +++ b/44_Hangman/README.md @@ -1,7 +1,26 @@ ### Hangman -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=80 +This is a simulation of the word guessing game, hangman. The computer picks a word, tells you how many letters in the word it has picked and then you guess a letter in the word. If you are right, the computer tells you where that letter belongs; if your letter is wrong, the computer starts to hang you. You get ten guesses before you are completely hanged: +1. Head +2. Body +3. Right Arm +4. Left Arm +5. Right Leg +6. Left Leg +7. Right Hand +8. Left Hand +9. Right Foot +10. Left Foot + +You may add words in Data statements; however if you do, you must also change the random word selector. + +David Ahl modified this program into its current form from the one created by Kenneth Aupperle of Melville, New York. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=80) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=95) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/45_Hello/README.md b/45_Hello/README.md index 7c72beca..117db0ce 100644 --- a/45_Hello/README.md +++ b/45_Hello/README.md @@ -1,7 +1,16 @@ ### Hello -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=82 +This is a sample of one of the great number of conversational programs. In a sense, it is like a CAI program except that its responses are just good fun. Whenever a computer is exhibited at a convention or conference with people that have not used a computer before, the conversational programs seem to get the first activity. + +In this particular program, the computer dispenses advice on various problems such as sex. health, money, or job. + +David Ahl is the author of HELLO. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=82) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=97) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/46_Hexapawn/README.md b/46_Hexapawn/README.md index 6380a1b3..0197fa14 100644 --- a/46_Hexapawn/README.md +++ b/46_Hexapawn/README.md @@ -1,7 +1,16 @@ ### Hexapawn -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=83 +The game of Hexapawn and a method to learn a strategy for playing the game was described in Martin Gardner’s “Mathematical Games” column in the March 1962 issue of _Scientific American_. The method described in the article was for a hypothetical learning machine composed of match boxes and colored beads. This has been generalized in the program HEX. + +The program learns by elimination of bad moves. All positions encountered by the program and acceptable moves from them are stored in an array. When the program encounters an unfamiliar position, the position and all legal moves from it are added to the list. If the program loses a game, it erases the move that led to defeat. If it hits a position from which all moves have been deleted (they all led to defeat), it erases the move that got it there and resigns. Eventually, the program learns to play extremely well and, indeed, is unbeatable. The learning strategy could be adopted to other simple games with a finite number of moves (tic-tac-toe, small board checkers, or other chess-based games). + +The original version of this program was written by R.A. Kaapke. It was subsequently modified by Jeff Dalton and finally by Steve North of Creative Computing. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=83) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=98) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/47_Hi-Lo/README.md b/47_Hi-Lo/README.md index cf2f93be..7fb37221 100644 --- a/47_Hi-Lo/README.md +++ b/47_Hi-Lo/README.md @@ -1,7 +1,21 @@ ### Hi-Lo -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=85 +This game is an adaptation of the game GUESS; however, instead of just guessing a number between 1 and 100, in this game you win dollars when you guess the number. The directions, in the words of the author, are as follows: +1. There is an amount of money, between one and one hundred dollars, in the “HI-LO” jackpot. +2. You will have six chances in which to guess the amount of money in the jackpot. +3. After each guess, the computer will tell whether the guess was too high or too low. +4. If the correct amount of money is not guessed after six chances, the computer will print the amount in the jackpot. +5. If the correct amount of money is guessed within the six chance limit, the computer will register this amount. +6. After each sequence of guesses, you have the choice of playing again or ending the program. If a new game is played, a new amount of money will constitute the jackpot. +7. If youwin more than once, then your earnings are totalled. + +The author is Dean ALtman of Fort Worth, Texas. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=85) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=100) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/48_High_IQ/README.md b/48_High_IQ/README.md index 3da523da..7dee9c95 100644 --- a/48_High_IQ/README.md +++ b/48_High_IQ/README.md @@ -1,7 +1,16 @@ ### High IQ -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=86 +This is a computerized version of an old European solitaire game of logic. The game starts with a pegboard shaped like a cross having pegs in every hole but the center. The object is to remove all 32 pegs, or as many as possible, by jumping into an empty hole, then removing the jumped peg. + +There are several different winning strategies for playing, and of course, each strategy can be played eight different ways on the board. Can you find a consistent winner? + +Charles Lund wrote this game while at The American School in The Hague, Netherlands. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=86) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=101) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/49_Hockey/README.md b/49_Hockey/README.md index 8d83017d..41e6950e 100644 --- a/49_Hockey/README.md +++ b/49_Hockey/README.md @@ -1,7 +1,16 @@ ### Hockey -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=88 +This is a simulation of a ice hockey game. The computer, in this case, moderates and referees the pay between two human opponents. Of course, one person could play both sides. + +The program asks for team names, player names, and even the name of the referee. Four types of shot are permitted and a shot may be aimed at one of four areas. You are also asked about passing. The game is very comprehensive with lots of action, face offs, blocks, passes, 4 on 2 situations, and so on. Unfortunately there are no penalties. + +The original author is Robert Puopolo; modifications by Steve North of Creative Computing. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=88) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=103) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/50_Horserace/README.md b/50_Horserace/README.md index ce781ffd..00e24df5 100644 --- a/50_Horserace/README.md +++ b/50_Horserace/README.md @@ -1,7 +1,14 @@ ### Horserace -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=92 +This program simulates a one-mile horse race for three-year old throughbreds. Up to ten people may place bets on the race up to $10,000 each. However, you may only bet to win. You place your bet by inputting the number of the horse, a comma, and the amount of your bet. The computer then shows the position of the horses at seven points around the track and at the finish. Payoffs and winnings are shown at the end. + +The program was written by Laurie Chevalier while a student at South Portland High School. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=92) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=107) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/51_Hurkle/README.md b/51_Hurkle/README.md index 1a13ac8e..0204e405 100644 --- a/51_Hurkle/README.md +++ b/51_Hurkle/README.md @@ -1,7 +1,16 @@ ### Hurkle -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=94 +Hurkle? A Hurkle is a happy beast and lives in another galaxy on a planet named Lirht that has three moons. Hurkle are favorite pets of the Gwik, the dominant race of Lihrt and … well, to find out more, read “The Hurkle is a Happy Beast,” a story in the book _A Way Home_ by Theodore Sturgeon. + +In this program a shy hurkle is hiding on a 10 by 10 grid. Homebase is point 0,0 in the _Southwest_ corner. Your guess as to the gridpoint where the hurkle is hiding should be a pair of whole numbers, separated by a comma. After each try, the computer will tell you the approximate direction to go look for the Hurkle. You get five guesses to find him; you may change this number, although four guesses is actually enough. + +This program was written by Bob Albrecht of People’s Computer Company. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=94) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=109) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/52_Kinema/README.md b/52_Kinema/README.md index d3c74687..31a69199 100644 --- a/52_Kinema/README.md +++ b/52_Kinema/README.md @@ -1,7 +1,19 @@ ### Kinema -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=95 +This program tests your fundamental knowledge of kinematics. It presents a simple problem: a ball is thrown straight up into the air at some random velocity. You then must answer three questions about the flight of the ball: +1. How high will it go? +2. How long until it returns to earth? +3. What will be its velocity after a random number of seconds? + +The computer evaluates your performance; within 15% of the correct answer is considered close enough. After each run, the computer gives you another problem until you interrupt it. + +KINEMA was shorted from the original Huntington Computer Project Program, KINERV, by Richard Pav of Patchogue High School, Patchogue, New York. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=95) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=110) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/53_King/README.md b/53_King/README.md index cf570189..eb0ba8ab 100644 --- a/53_King/README.md +++ b/53_King/README.md @@ -1,7 +1,18 @@ ### King -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=96 +This is one of the most comprehensive, difficult, and interesting games. (If you’ve never played one of these games, start with HAMMURABI.) + +In this game, you are Premier of Setats Detinu, a small communist island 30 by 70 miles long. Your job is to decide upon the budget of your country and distribute money to your country from the communal treasury. + +The money system is Rollods; each person needs 100 Rallods per year to survive. Your country’s income comes from farm produce and tourists visiting your magnificent forests, hunting, fishing, etc. Part of your land is farm land but it also has an excellent mineral content and may be sold to foreign industry for strip mining. Industry import and support their own workers. Crops cost between 10 and 15 Rallods per square mile to plant, cultivate, and harvest. Your goal is to complete an eight-year term of office without major mishap. A word of warning: it isn’t easy! + +The author of this program is James A. Storer who wrote it while a student at Lexington High School. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=96) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=111) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/54_Letter/README.md b/54_Letter/README.md index eef18d38..fab67494 100644 --- a/54_Letter/README.md +++ b/54_Letter/README.md @@ -1,7 +1,14 @@ ### Letter -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=99 +LETTER is similar to the game GUESS in which you guess a number chosen by the computer; in this program, the computer picks a random letter of the alphabet and you must guess which one it is using the clues provided as you go along. It should not take you more than five guesses to get the mystery letter. + +The program which appears here is loosely based on the original written by Bob Albrect of People’s Computer Company. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=99) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=114) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/55_Life/README.md b/55_Life/README.md index e6a2b702..149bf25d 100644 --- a/55_Life/README.md +++ b/55_Life/README.md @@ -1,7 +1,35 @@ ### Life -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=100 +The Game of Life was originally described in _Scientific American_, October 1970, in an article by Martin Gardner. The game itself was originated by John Conway of Gonville and Caius College, University of Cambridge England. + +In the “manual” game, organisms exist in the form of counters (chips or checkers) on a large checkerboard and die or reproduce according to some simple genetic rules. Conway’s criteria for choosing his genetic laws were carefully delineated as follows: +1. There should be no initial pattern for which there is a simple proof that the population can grow without limit. +2. There should be simple initial patterns that apparently do grow without limit. +3. There should be simple initial patterns that grow and change for a considerable period of time before coming to an end in three possible ways: + 1. Fading away completely (from overcrowding or from becoming too sparse) + 2. Settling into a stable configuration that remains unchanged thereafter + 3. Entering an oscillating phase in which they repeat an endless cycle of two or more periods + +In brief, the rules should be such as to make the behavior of the population relatively unpredictable. Conway’s genetic laws are delightfully simple. First note that each cell of the checkerboard (assumed to be an infinite plane) has eight neighboring cells, four adjacent orthogonally, four adjacent diagonally. The rules are: +1. Survivals. Every counter with two or three neighboring counters survives for the next generation. +2. Deaths. Each counter with four or more neighbors dies (is removed) from overpopulation. Every counter with one neighbor or none dies from isolation. +3. Births. Each empty cell adjacent to exactly three neighbors — no more — is a birth cell. A counter is placed on it at the next move. + +It is important to understand that all births and deaths occur simultaneously. Together they constitute a single generation or, as we shall call it, a “move” in the complete “life history” of the initial configuration. + +You will find the population constantly undergoing unusual, sometimes beautiful and always unexpected change. In a few cases the society eventually dies out (all counters vanishing), although this may not happen until after a great many generations. Most starting patterns either reach stable figures — Conway calls them “still lifes” — that cannot change or patterns that oscillate forever. Patterns with no initial symmetry tend to become symmetrical. Once this happens the symmetry cannot be lost, although it may increase in richness. + +Conway used a DEC PDP-7 with a graphic display to observe long-lived populations. You’ll probably find this more enjoyable to watch on a CRT than a hard-copy terminal. + +Since MITS 8K BASIC does not have LINE INPUT, to enter leading blanks in the patter, type a “.” at the start of the line. This will be converted to a space by BASIC, but it permits you to type leading spaces. Typing DONE indicates that you are finished entering the pattern. See sample run. + +Clark Baker of Project DELTA originally wrote this version of LIFE which was further modified by Steve North of Creative Computing. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=100) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=115) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/56_Life_for_Two/README.md b/56_Life_for_Two/README.md index 34030043..d880653d 100644 --- a/56_Life_for_Two/README.md +++ b/56_Life_for_Two/README.md @@ -1,7 +1,44 @@ ### Life for Two -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=102 +LIFE-2 is based on Conway’s game of Life. You must be familiar with the rules of LIFE before attempting to play LIFE-2. + +There are two players; the game is played on a 5x5 board and each player has a symbol to represent his own pieces of ‘life.’ Live cells belonging to player 1 are represented by `*` and live cells belonging to player 2 are represented by the symbol `#`. + +The # and * are regarded as the same except when deciding whether to generate a live cell. An empty cell having two `#` and one `*` for neighbors will generate a `#`, i.e. the live cell generated belongs to the player who has the majority of the 3 live cells surrounding the empty cell where life is to be generated, for example: + +| | 1 | 2 | 3 | 4 | 5 | +|:-:|:-:|:-:|:-:|:-:|:-:| +| 1 | | | | | | +| 2 | | | * | | | +| 3 | | | | # | | +| 4 | | | # | | | +| 5 | | | | | | + +A new cell will be generated at (3,3) which will be a `#` since there are two `#` and one `*` surrounding. The board will then become: + +| | 1 | 2 | 3 | 4 | 5 | +|:-:|:-:|:-:|:-:|:-:|:-:| +| 1 | | | | | | +| 2 | | | | | | +| 3 | | | # | # | | +| 4 | | | | | | +| 5 | | | | | | + +On the first most each player positions 3 pieces of life on the board by typing in the co-ordinates of the pieces. (In the event of the same cell being chosen by both players that cell is left empty.) + +The board is then adjusted to the next generation and printed out. + +On each subsequent turn each player places one piece on the board, the object being to annihilate his opponent’s pieces. The board is adjusted for the next generation and printed out after both players have entered their new piece. + +The game continues until one player has no more live pieces. The computer will then print out the board and declare the winner. + +The idea for this game, the game itself, and the above write-up were written by Brian Wyvill of Bradford University in Yorkshire, England. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=102) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=117) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/57_Literature_Quiz/README.md b/57_Literature_Quiz/README.md index 54605904..2e55251f 100644 --- a/57_Literature_Quiz/README.md +++ b/57_Literature_Quiz/README.md @@ -1,7 +1,14 @@ ### Literature Quiz -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=104 +This is a simple CAI-type program which presents four multiple-choice questions from children’s literature. Running the program is self-explanatory. + +The program was written by Pamela McGinley while at DEC. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=104) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=117) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/58_Love/README.md b/58_Love/README.md index 35fb6f7d..1b2431aa 100644 --- a/58_Love/README.md +++ b/58_Love/README.md @@ -1,7 +1,14 @@ ### Love -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=105 +This program is designed to reproduce Robert Indiana’s great art work “Love” with a message of your choice up to 60 characters long. + +The love program was created by David Ahl. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=105) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=120) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/59_Lunar_LEM_Rocket/README.md b/59_Lunar_LEM_Rocket/README.md index eced07e0..9d1890ac 100644 --- a/59_Lunar_LEM_Rocket/README.md +++ b/59_Lunar_LEM_Rocket/README.md @@ -1,7 +1,24 @@ ### Lunar LEM Rocket -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=106 +This game in its many different versions and names (ROCKET, LUNAR, LEM, and APOLLO) is by far and away the single most popular computer game. It exists in various versions that start you anywhere from 500 feet to 200 miles away from the moon, or other planets, too. Some allow the control of directional stabilization rockets and/or the retro rocket. The three versions presented here represent the most popular of the many variations. + +In most versions of this game, the temptation is to slow up too soon and then have no fuel left for the lower part of the journey. This, of course, is disastrous (as you will find out when you land your own capsule)! + +LUNAR was originally in FOCAL by Jim Storer while a student at Lexington High School and subsequently converted to BASIC by David Ahl. ROCKET was written by Eric Peters at DEC and LEM by William Labaree II of Alexandria, Virginia. + +In this program, you set the burn rate of the retro rockets (pounds of fuel per second) every 10 seconds and attempt to achieve a soft landing on the moon. 200 lbs/sec really puts the brakes on, and 0 lbs/sec is free fall. Ignition occurs a 8 lbs/sec, so _do not_ use burn rates between 1 and 7 lbs/sec. To make the landing more of a challenge, but more closely approximate the real Apollo LEM capsule, you should make the available fuel at the start (N) equal to 16,000 lbs, and the weight of the capsule (M) equal to 32,500 lbs. + +#### LEM +This is the most comprehensive of the three versions and permits you to control the time interval of firing, the thrust, and the attitude angle. It also allows you to work in the metric or English system of measurement. The instructions in the program dialog are very complete, so you shouldn’t have any trouble. + +#### ROCKET +In this version, you start 500 feet above the lunar surface and control the burn rate in 1-second bursts. Each unit of fuel slows your descent by 1 ft/sec. The maximum thrust of your engine is 30 ft/sec/sec. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=106) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=121) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/60_Mastermind/README.md b/60_Mastermind/README.md index d78cf527..e9bf1c3c 100644 --- a/60_Mastermind/README.md +++ b/60_Mastermind/README.md @@ -1,7 +1,29 @@ ### MasterMind -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=110 +In that Match-April 1976 issue of _Creative_ we published a computerized version of Master Mind, a logic game. Master Mind is played by two people—one is called the code-maker; the other, the code-breaker. At the beginning of the game the code-maker forms a code, or combination of colored pegs. He hides these from the code-breaker. The code-breaker then attempts to deduce the code, by placing his own guesses, one at a time, on the board. After he makes a guess (by placing a combination of colored pegs on the board) the code-maker then gives the code-breaker clues to indicate how close the guess was to the code. For every peg in the guess that’s the right color but not in the right position, the code-breaker gets a white peg. Note that these black and white pegs do not indicate _which_ pegs in the guess are correct, but merely that they exist. For example, if the code was: +``` +Yellow Red Red Green +``` + +and my guess was +``` +Red Red Yellow Black +``` +I would receive two white pegs and one black peg for the guess. I wouldn’t know (except by comparing previous guesses) which one of the pegs in my guess was the right color in the right position. + +Many people have written computer programs to play Master Mind in the passive role, i.e., the computer is the code maker and the human is the code-breaker. This is relatively trivial; the challenge is writing a program that can also play actively as a code-breaker. + +Actually, the task of getting the computer to deduce the correct combination is not at all difficult. Imagine, for instance, that you made a list of all possible codes. To begin, you select a guess from your list at random. Then, as you receive clues, you cross off from the list those combinations which you know are impossible. For example if your guess is Red Red Green Green and you receive no pegs, then you know that any combination containing either a red or a green peg is impossible and may be crossed of the list. The process is continued until the correct solution is reached or there are no more combinations left on the list (in which case you know that the code-maker made a mistake in giving you the clues somewhere). + +Note that in this particular implementation, we never actually create a list of the combinations, but merely keep track of which ones (in sequential order) may be correct. Using this system, we can easily say that the 523rd combination may be correct, but to actually produce the 523rd combination we have to count all the way from the first combination (or the previous one, if it was lower than 523). Actually, this problem could be simplified to a conversion from base 10 to base (number of colors) and then adjusting the values used in the MID$ function so as not to take a zeroth character from a string if you want to experiment. We did try a version that kept an actual list of all possible combinations (as a string array), which was significantly faster than this version, but which ate tremendous amounts of memory. + +At the beginning of this game, you input the number of colors and number of positions you wish to use (which will directly affect the number of combinations) and the number of rounds you wish to play. While you are playing as the code-breaker, you may type BOARD at any time to get a list of your previous guesses and clues, and QUIT to end the game. Note that this version uses string arrays, but this is merely for convenience and can easily be converted for a BASIC that has no string arrays as long as it has a MID$ function. This is because the string arrays are one-dimensional, never exceed a length greater than the number of positions and the elements never contain more than one character. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=110) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=125) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/61_Math_Dice/README.md b/61_Math_Dice/README.md index f6285a11..a24c9dbe 100644 --- a/61_Math_Dice/README.md +++ b/61_Math_Dice/README.md @@ -1,7 +1,14 @@ ### Math Dice -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=113 +The program presents pictorial drill on addition facts using printed dice with no reading involved. It is good for beginning addition, since the answer can be derived from counting spots on the dice as well as by memorizing math facts or awareness of number concepts. It is especially effective run on a CRT terminal. + +It was originally written by Jim Gerrish, a teacher at the Bernice A. Ray School in Hanover, New Hampshire. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=113) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=128) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/62_Mugwump/README.md b/62_Mugwump/README.md index 421f0112..c67037f2 100644 --- a/62_Mugwump/README.md +++ b/62_Mugwump/README.md @@ -1,7 +1,18 @@ ### Mugwump -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=114 +Your objective in this game is to find the four Mugwumps hiding on various squares of a 10 by 10 grid. Homebase (lower left) is position (0,0) and a guess is a pair of whole numbers (0 to 9), separated by commas. The first number is the number of units to the right of homebase and the second number is the distance above homebase. + +You get ten guesses to locate the four Mugwumps; after each guess, the computer tells you how close you are to each Mugwump. Playing the game with the aid of graph paper and a compass should allow you to find all the Mugwumps in six or seven moves using triangulation similar to Loran radio navigation. + +If you want to make the game somewhat more difficult, you can print the distance to each Mugwump either rounded or truncated to the nearest integer. + +This program was modified slightly by Bob Albrecht of People’s Computer Company. It was originally written by students of Bud Valenti of Project SOLO in Pittsburg, Pennsylvania. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=114) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=129) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/63_Name/README.md b/63_Name/README.md index daa110c1..a3744cdd 100644 --- a/63_Name/README.md +++ b/63_Name/README.md @@ -1,7 +1,14 @@ ### Name -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=116 +NAME is a silly little ice-breaker to get a relationship going between a computer and a shy human. The sorting algorithm used is highly inefficient — as any reader of _Creative Computing_ will recognize, this is the worst possible sort for speed. But the program is good fun and that’s what counts here. + +NAME was originall written by Geoffry Chase of the Abbey, Portsmouth, Rhode Island. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=116) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=131) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/64_Nicomachus/README.md b/64_Nicomachus/README.md index f54f600e..bbe911fc 100644 --- a/64_Nicomachus/README.md +++ b/64_Nicomachus/README.md @@ -1,7 +1,18 @@ ### Nicomachus -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=117 +One of the most ancient forms of arithmetic puzzle is sometimes referred to as a “boomerang.” At some time, everyone has been asked to “think of a number,” and, after going through some process of private calculation, to state the result, after which the questioner promptly tells you the number you originally thought of. There are hundreds of varieties of this puzzle. + +The oldest recorded example appears to be that given in _Arithmetica_ of Nicomachus, who died about the year 120. He tells you to think of any whole number between 1 and 100 and divide it successfully by 3, 5, and 7, telling him the remainder in each case. On receiving this information, he promptly discloses the number you thought of. + +Can you discover a simple method of mentally performing this feat? If not, you can see how the ancient mathematician did it by looking at this program. + +Nicomachus was written by David Ahl. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=117) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=132) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/65_Nim/README.md b/65_Nim/README.md index a47d44e4..867f641d 100644 --- a/65_Nim/README.md +++ b/65_Nim/README.md @@ -1,7 +1,27 @@ ### Nim -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=118 +NIM is one of the oldest two-person games known to man; it is believed to have originated in ancient China. The name, which was coined by the first mathematician to analyze it, comes from an archaic English verb which means to steal or to take away. Objects are arranged in rows between the two opponents as in the following example: +| | | | +|---------|-------|-----------| +| XXXXXXX | Row 1 | 7 Objects | +| XXXXX | Row 2 | 5 Objects | +| XXX | Row 3 | 3 Objects | +| X | Row 4 | 1 Object | + +Opponents take turns removing objects until there are none left. The one who picks up the last object wins. The moves are made according to the following rules: +1. On any given turn only objects from one row may be removed. There is no restriction on which row or on how many objects you remove. Of course, you cannot remove more than are in the row. +2. You cannot skip a move or remove zero objects. + +The winning strategy can be mathematically defined, however, rather than presenting it here, we’d rather let you find it on your own. HINT: Play a few games with the computer and mark down on a piece of paper the number of objects in each stack (in binary!) after each move. Do you see a pattern emerging? + +This game of NIM is from Dartmouth College and allows you to specify any starting size for the four piles and also a win option. To play traditional NIM, you would simply specify 7,5,3 and 1, and win option 1. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=118) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=133) + Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/66_Number/README.md b/66_Number/README.md index 8eb2e9b5..47a9b5cb 100644 --- a/66_Number/README.md +++ b/66_Number/README.md @@ -1,7 +1,14 @@ ### Number -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=121 +In contrast to other number guessing games where you keep guessing until you get the random number selected by the computer (GUESS, TRAP, STARS, etc.), in this game you only get one guess per play and you gain or lose points depending upon how close your guess is to the random number selected by the computer. You occasionally get a jackpot which will double your point count. You win when you get 500 points. + +Tom Adametx wrote this program while a student at Curtis Junior High School in Sudbury, Massachusetts. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=121) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=136) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/67_One_Check/README.md b/67_One_Check/README.md index 0e703692..b3522e15 100644 --- a/67_One_Check/README.md +++ b/67_One_Check/README.md @@ -1,7 +1,29 @@ ### One Check -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=122 +In this game or puzzle, 48 checkers are placed on the two outside spaces of a standard 64-square checkerboard as shown: + +| | | | | | | | | +|---|---|---|---|---|---|---|---| +| ● | ● | ● | ● | ● | ● | ● | ● | +| ● | ● | ● | ● | ● | ● | ● | ● | +| ● | ● | | | | | ● | ● | +| ● | ● | | | | | ● | ● | +| ● | ● | | | | | ● | ● | +| ● | ● | | | | | ● | ● | +| ● | ● | ● | ● | ● | ● | ● | ● | +| ● | ● | ● | ● | ● | ● | ● | ● | + +The object is to remove as many checkers as possible by diagonal jumps (as in standard checkers). + +It is easy to remove 30 to 39 checkers, a challenge to remove 40 to 44, and a substantial feat to remove 45 to 47. + +The program was created and written by David Ahl. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=122) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=137) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/68_Orbit/README.md b/68_Orbit/README.md index 3d7a04cb..df49852b 100644 --- a/68_Orbit/README.md +++ b/68_Orbit/README.md @@ -1,7 +1,57 @@ ### Orbit -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=124 +ORBIT challenges you to visualize spacial positions in polar coordinates. The object is to detonate a Photon explosive within a certain distance of a germ laden Romulan spaceship. This ship is orbiting a planet at a constant altitude and orbital rate (degrees/hour). The location of the ship is hidden by a device that renders the ship invisible, but after each bomb you are told how close to the enemy ship your bomb exploded. The challenge is to hit an invisible moving target with a limited number of shots. + +The planet can be replaced by a point at its center (called the origin); then the ship’s position can be given as a distance form the origin and an angle between its position and the eastern edge of the planet. + +``` +direction +of orbit < ^ ship + \ ╱ + \ ╱ < + |╱ \ + ╱ \ + ╱ \ + ╱ | angle + ╱ / + ╱ / + ╱ / + ╱——————————————————— E + +``` + +The distance of the bomb from the ship is computed using the law of consines. The law of cosines states: + +``` +D = SQUAREROOT( R**2+D1**2+R*D1*COS(A-A1) ) +``` + +Where D is the distance between the ship and the bomb, R is the altitude of the ship, D1 is the altitude of the bomb, and A-A1 is the angle between the ship and the bomb. + + +``` + bomb < + ╲ ^ ship + ╲ ╱ + ╲ ╱ < + ╲ ╱ \ + D1 ╲ ╱ \ + ╲ R ╱ \ + ╲ A1 ╱ | A + ╲⌄——— ◝╱ / + ╲ ╱ \ / + ╲ ╱ \ / + ╲╱───────────────────── E + +``` + +ORBIT was originally called SPACE WAR and was written by Jeff Lederer of Project SOLO Pittsburgh, Pennsylvania. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=124) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=139) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/69_Pizza/README.md b/69_Pizza/README.md index fc83503a..671e7237 100644 --- a/69_Pizza/README.md +++ b/69_Pizza/README.md @@ -1,7 +1,16 @@ ### Pizza -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=126 +In this game, you take orders for pizzas from people living in Hyattsville. Armed with a map of the city, you must then tell your delivery boy the address where the pizza is to be delivered. If the pizza is delivered to the correct address, the customer phones you and thanks you; if not, you must give the driver the correct address until the pizza gets delivered. + +Some interesting modifications suggest themselves for this program such as pizzas getting cold after two incorrect delivery attempts or taking three or more orders at a time and figuring out the shortest delivery route. Send us your modifications! + +This program seems to have surfaced originally at the University of Georgia in Athens, Georgia. The author is unknown. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=126) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=141) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/70_Poetry/README.md b/70_Poetry/README.md index fe3c0ea8..b04bb915 100644 --- a/70_Poetry/README.md +++ b/70_Poetry/README.md @@ -1,7 +1,29 @@ ### Poetry -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=128 +This program produces random verse which might loosely be considered in the Japanese Haiku style. It uses 20 phrases in four groups of five phrases each and generally cycles through the groups in order. It inserts commas (random — 19% of the time), indentation (random — 22% of the time), and starts new paragraphs (18% probability but at least once every 20 phrases). + +The phrases in POETRY are somewhat suggestive of Edgar Allen Poe. Try it with phrases from computer technology, from love and romance, from four-year-old children, or from some other project. Send us the output. + +Here are some phrases from nature to try: +``` +Carpet of ferns Mighty Oaks +Morning dew Grace and beauty +Tang of dawn Silently singing +Swaying pines Nature speaking + +Entrances me Untouched, unspoiled +Soothing me Shades of green +Rustling leaves Tranquility +Radiates calm …so peaceful +``` + +The original author of this program is unknown. It was modified and reworked by Jim Bailey, Peggy Ewing, and Dave Ahl at DEC. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=128) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=143) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/71_Poker/README.md b/71_Poker/README.md index b5f7bc83..1bad96d6 100644 --- a/71_Poker/README.md +++ b/71_Poker/README.md @@ -1,7 +1,16 @@ ### Poker -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=129 +You and the computer are opponents in this game of draw poker. At the start of the game, each player is given $200. The game ends when either player runs out of money, although if you go broke the computer will offer to buy back your wristwatch or diamond tie tack. + +The computer opens the betting before the draw; you open the betting after the draw. If you don’t have a hand that’s worth anything and you want to fold, bet 0. Prior to the draw, to check the draw, you may bet .5. Of course, if the computer has made a bet, you must match it in order to draw or, if you have a good hand, you may raise the bet at any time. + +The author is A. Christopher Hall of Trinity College, Hartford, Connecticut. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=129) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=144) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/72_Queen/README.md b/72_Queen/README.md index 44ec90bb..dc62cb59 100644 --- a/72_Queen/README.md +++ b/72_Queen/README.md @@ -1,7 +1,16 @@ ### Queen -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=133 +This game is based on the permissible moves of the chess queen — i.e., along any vertical, horizontal, or diagonal. In this game, the queen can only move to the left, down, and diagonally down to the left. + +The object of the game is to place the queen (one only) in the lower left-hand square (no. 158), by alternating moves between you and the computer. The 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 the right-hand column. That is your first move. The computer is beatable, but it takes some figuring. See if you can devise a winning strategy. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=133) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=148) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/73_Reverse/README.md b/73_Reverse/README.md index 68d83b47..a753e8a8 100644 --- a/73_Reverse/README.md +++ b/73_Reverse/README.md @@ -1,7 +1,31 @@ ### Reverse -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=135 +The game of REVERSE requires you to arrange a list of numbers in numerical order from left to right. To move, you tell the computer how many numbers (counting from the left) to reverse. For example, if the current list is: +``` + 2 3 4 5 1 6 7 8 9 +``` + +and you reverse 4, the result will be: +``` + 5 4 3 2 1 6 7 8 9 +``` +Now if you reverse 5, you win! + +There are many ways to beat the game, but approaches tend to be either algorithmic or heuristic. The game thus offers the player a chance to play with these concepts in a practical (rather than theoretical) context. + +An algorithmic approach guarantees a solution in a predictable number of moves, given the number of items in the list. For example, one method guarantees a solution in 2N - 3 moves when teh list contains N numbers. The essence of an algorithmic approach is that you know in advance what your next move will be. Once could easily program a computer to do this. + +A heuristic approach takes advantage of “partial orderings” in the list at any moment. Using this type of approach, your next move is dependent on the way the list currently appears. This way of solving the problem does not guarantee a solution in a predictable number of moves, but if you are lucky and clever, you may come out ahead of the algorithmic solutions. One could not so easily program this method. + +In practice, many players adopt a “mixed” strategy, with both algorithmic and heuristic features. Is this better than either “pure” strategy? + +The program was created by Peter Sessions of People’s Computer Company and the notes above adapted from his original write-up. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=135) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=150) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/74_Rock_Scissors_Paper/README.md b/74_Rock_Scissors_Paper/README.md index 602dd15b..1b9fa865 100644 --- a/74_Rock_Scissors_Paper/README.md +++ b/74_Rock_Scissors_Paper/README.md @@ -1,7 +1,21 @@ ### Rock, Scissors, Paper -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=137 +Remember the game of rock-scissors-paper. You and your opponent make a motion three times with your fists and then either show: +- a flat hand (paper) +- fist (rock) +- two fingers (scissors) + +Depending upon what is shown, the game is a tie (both show the same) or one person wins. Paper wraps up rock, so it wins. Scissors cut paper, so they win. And rock breaks scissors, so it wins. + +In this computerized version of rock-scissors-paper, you can play up to ten games vs. the computer. + +Charles Lund wrote this game while at the American School in The Hague, Netherlands. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=137) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=152) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/75_Roulette/README.md b/75_Roulette/README.md index f652ee9e..51719248 100644 --- a/75_Roulette/README.md +++ b/75_Roulette/README.md @@ -1,7 +1,16 @@ ### Roulette -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=138 +This game simulates an American Roulette wheel; “American” because it has 38 number compartments (1 to 36, 0 and 00). The European wheel has 37 numbers (1 to 36 and 0). The Bahamas, Puerto Rico, and South American countries are slowly switching to the American wheel because it gives the house a bigger percentage. Odd and even numbers alternate around the wheel, as do red and black. The layout of the wheel insures a highly random number pattern. In fact, roulette wheels are sometimes used to generate tables of random numbers. + +In this game, you may bet from $5 to $500 and you may bet on red or black, odd or even, first or second 18 numbers, a column, or single number. You may place any number of bets on each spin of the wheel. + +There is no long-range winning strategy for playing roulette. However, a good strategy is that of “doubling.” First spin, bet $1 on an even/odds bet (odd, even, red, or black). If you lose, double your bet again to $2. If you lose again, double to $4. Continue to double until you win (i.e, you break even on a losing sequence). As soon as you win, bet $1 again, and after every win, bet $1. Do not ever bet more than $1 unless you are recuperating losses by doubling. Do not ever bet anything but the even odds bets. Good luck! + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=138) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=153) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/76_Russian_Roulette/README.md b/76_Russian_Roulette/README.md index 3385adc8..cf1b64fc 100644 --- a/76_Russian_Roulette/README.md +++ b/76_Russian_Roulette/README.md @@ -1,7 +1,14 @@ ### Russian Roulette -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=141 +In this game, you are given by the computer a revolver loaded with one bullet and five empty chambers. You spin the chamber and pull the trigger by inputting a “1,” or, if you want to quit, input a “2.” You win if you play ten times and are still alive. + +Tom Adametx wrote this program while a student at Curtis Jr. High School in Sudbury, Massachusetts. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=141) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=153) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/77_Salvo/README.md b/77_Salvo/README.md index 82f8a5e2..fbf938ca 100644 --- a/77_Salvo/README.md +++ b/77_Salvo/README.md @@ -1,7 +1,25 @@ ### Salvo -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=142 +The rules are _not_ explained by the program, so read carefully this description by Larry Siegel, the program author. + +SALVO is played on a 10x10 grid or board using an x,y coordinate system. The player has 4 ships: +- battleship (5 squares) +- cruiser (3 squares) +- two destroyers (2 squares each) + +The ships may be placed horizontally, vertically, or diagonally and must not overlap. The ships do not move during the game. + +As long as any square of a battleship still survives, the player is allowed three shots, for a cruiser 2 shots, and for each destroyer 1 shot. Thus, at the beginning of the game the player has 3+2+1+1=7 shots. The players enters all of his shots and the computer tells what was hit. A shot is entered by its grid coordinates, x,y. The winner is the one who sinks all of the opponents ships. + +Important note: Your ships are located and the computer’s ships are located on 2 _separate_ 10x10 boards. + +Author of the program is Lawrence Siegel of Shaker Heights, Ohio. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=142) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=157) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/78_Sine_Wave/README.md b/78_Sine_Wave/README.md index f78ccccf..c38234a2 100644 --- a/78_Sine_Wave/README.md +++ b/78_Sine_Wave/README.md @@ -1,7 +1,12 @@ ### Sine Wave -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=146 +Did you ever go to a computer show and see a bunch of CRT terminals just sitting there waiting forlornly for someone to give a demo on them. It was one of those moments when I was at DEC that I decided there should be a little bit of background activity. And why not plot with words instead of the usual X’s? Thus SINE WAVE was born and lives on in dozens on different versions. At least those CRTs don’t look so lifeless anymore. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=146) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=161) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/79_Slalom/README.md b/79_Slalom/README.md index 49935ea1..7e46e3a5 100644 --- a/79_Slalom/README.md +++ b/79_Slalom/README.md @@ -1,7 +1,16 @@ ### Slalom -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=147 +This game simulates a slalom run down a course with one to 25 gates. The user picks the number of gates and has some control over his speed down the course. + +If you’re not a skier, here’s your golden opportunity to try it with minimal risk. If you are a skier, here’s something to do while your leg is in a cast. + +SLALOM was written by J. Panek while a student at Dartmouth College. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=147) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=162) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/80_Slots/README.md b/80_Slots/README.md index 1b4a1987..952fa03e 100644 --- a/80_Slots/README.md +++ b/80_Slots/README.md @@ -1,7 +1,18 @@ ### Slots -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=149 +The slot machine or one-arm bandit is a mechanical device that will absorb coins just about as fast as you can feed it. After inserting a coin, you pull a handle that sets three independent reels spinning. If the reels stop with certain symbols appearing in the pay line, you get a certain payoff. The original slot machine, called the Liberty Bell, was invented in 1895 by Charles Fey in San Francisco. Fey refused to sell or lease the manufacturing rights, so H.S. Mills in Chicago built a similar, but much improved machine called the Operators Bell. This has survived nearly unchanged to today. + +On the Operators Bell and other standard slot machines, there are 20 symbols on each wheel but they are not distributed evenly among the objects (cherries, bar, apples, etc.). Of the 8,000 passible combinations, the expected payoff (to the player) is 7,049 or $89.11 for every $100.00 put in, one of the lowest expected payoffs in all casino games. + +In the program here, the payoff is considerably more liberal; indeed it appears to favor the player by 11% — i.e., an expected payoff of $111 for each $100 bet. + +The program was originally written by Fred Mirabella and Bob Harper. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=149) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=164) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/81_Splat/README.md b/81_Splat/README.md index 4b4161ef..24631217 100644 --- a/81_Splat/README.md +++ b/81_Splat/README.md @@ -1,7 +1,16 @@ ### Splat -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=151 +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. + +The computer then tells you the height you’re 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. + +John Yegge created this program while at the Oak Ridge Associated Universities. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=151) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=166) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/82_Stars/README.md b/82_Stars/README.md index cc6c3171..ff067975 100644 --- a/82_Stars/README.md +++ b/82_Stars/README.md @@ -1,7 +1,16 @@ ### Stars -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=153 +In this game, the computer selects a random number from 1 to 100 (or any value you set). You try to guess the number and the computer gives you clues to tell you how close you’re getting. One star (\*) means you’re far away from the number; seven stars (\*\*\*\*\*\*\*) means you’re really close. You get 7 guesses. + +On the surface this game is similar to GUESS; however, the guessing strategy is quite different. See if you can come up with one or more approaches to finding the mystery number. + +Bob Albrecht of People’s Computer Company created this game. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=153) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=166) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/83_Stock_Market/README.md b/83_Stock_Market/README.md index 6b963c2f..65447e1f 100644 --- a/83_Stock_Market/README.md +++ b/83_Stock_Market/README.md @@ -1,7 +1,16 @@ ### Stock Market -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=154 +This program “plays” the stock market. You will be given $10,000 and may buy or sell stocks. Stock prices and trends are generated randomly; therefore, this model does not represent exactly what happens on the exchange. (Depending upon your point of view, you may feel this is quite a good representation!) + +Every trading day, a table of stocks, their prices, and number of shares in your portfolio is printed. Following this, the initials of each stock are printed followed by a question mark. You indicate your transaction in number of shares — a positive number to buy, negative to sell, or 0 to do no trading. A brokerage fee of 1% is charges on all transactions (a bargain!). Note: Even if the value of a stock drops to zero, it may rebound again — then again, it may not. + +This program was created by D. Pessel, L. Braun, and C. Losik of the Huntington Computer Project at SUNY, Stony Brook, N.Y. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=154) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=166) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/84_Super_Star_Trek/README.md b/84_Super_Star_Trek/README.md index 495ce9ae..4a96f528 100644 --- a/84_Super_Star_Trek/README.md +++ b/84_Super_Star_Trek/README.md @@ -1,7 +1,98 @@ ### Super Star Trek -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=157 +#### Brief History +Many versions of Star Trek have been kicking around various college campuses since the late sixties. I recall playing one at Carnegie-Mellon Univ. in 1967 or 68, and a very different one at Berkeley. However, these were a far cry from the one written by Mike Mayfield of Centerline Engineering and/or Custom Data. This was written for an HP2000C and completed in October 1972. It became the “standard” Star Trek in February 1973 when it was put in the HP contributed program library and onto a number of HP Data Center machines. + +In the summer of 1973, I converted the HP version to BASIC-PLUS for DEC’s RSTS-11 compiler and added a few bits and pieces while I was at it. Mary Cole at DEC contributed enormously to this task too. Later that year I published it under the name SPACWE (Space War — in retrospect, an incorrect name) in my book _101 Basic Computer Games_.It is difficult today to find an interactive computer installation that does not have one of these versions of Star Trek available. + +#### Quadrant Nomenclature +Recently, certain critics have professed confusion as to the origin on the “quadrant” nomenclature used on all standard CG (Cartesian Galactic) maps. Naturally, for anyone with the remotest knowledge of history, no explanation is necessary; however, the following synopsis should suffice for the critics: + +As everybody schoolboy knows, most of the intelligent civilizations in the Milky Way had originated galactic designations of their own choosing well before the Third Magellanic Conference, at which the so-called “2⁶ Agreement” was reached. In that historic document, the participant cultures agreed, in all two-dimensional representations of the galaxy, to specify 64 major subdivisions, ordered as an 8 x 8 matrix. This was partially in deference to the Earth culture (which had done much in the initial organization of the Federation), whose century-old galactic maps had landmarks divided into four “quadrants,” designated by ancient “Roman Numerals” (the origin of which has been lost). + +To this day, the official logs of starships originating on near-Earth starbases still refer to the major galactic areas as “quadrants.” + +The relation between the Historical and Standard nomenclatures is shown in the simplified CG map below. + +| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +|---|--------------|----|-----|----|------------|----|-----|----| +| 1 | ANTARES | | | | SIRIUS | | | | +| | I | II | III | IV | I | | III | IV | +| 2 | RIGEL | | | | DENEB | | | | +| | I | II | III | IV | I | II | III | IV | +| 3 | PROCYON | | | | CAPELLA | | | | +| | I | II | III | IV | I | II | III | IV | +| 4 | VEGA | | | | BETELGUESE | | | | +| | I | II | III | IV | I | II | III | IV | +| 5 | CANOPUS | | | | ALDEBARA | | | | +| | I | II | III | IV | I | II | III | IV | +| 6 | ALTAIR | | | | REGULUS | | | | +| | I | II | III | IV | I | II | III | IV | +| 7 | SAGITTARIOUS | | | | ARCTURUS | | | | +| | I | II | III | IV | I | II | III | IV | +| 8 | POLLUX | | | | SPICA | | | | +| | I | II | III | IV | I | II | III | IV | + +#### Super Star Trek† Rules and Notes +1. OBJECTIVE: You are Captain of the starship “Enterprise”† with a mission to seek and destroy a fleet of Klingon† warships (usually about 17) which are menacing the United Federation of Planets.† You have a specified number of stardates in which to complete your mission. You also have two or three Federation Starbases† for resupplying your ship. + +2. You will be assigned a starting position somewhere in the galaxy. The galaxy is divided into an 8 x 8 quadrant grid. The astronomical name of a quadrant is called out upon entry into a new region. (See “Quadrant Nomenclature.”) Each quadrant is further divided into an 8 x 8 section grid. + +3. On a section diagram, the following symbols are used: + - `<*>` Enterprise + - `†††` Klingon + - `>!<` Starbase + - `*` Star + +4. You have eight commands available to you (A detailed description of each command is given in the program instructions.) + - `NAV` Navigate the Starship by setting course and warp engine speed. + - `SRS` Short-range sensor scan (one quadrant) + - `LRS` Long-range sensor scan (9 quadrants) + - `PHA` Phaser† control (energy gun) + - `TOR` Photon torpedo control + - `SHE` Shield control (protects against phaser fire) + - `DAM` Damage and state-of-repair report + - `COM` Call library computer + +5. Library computer options are as follows (more complete descriptions are in program instructions): + - `0` Cumulative galactic report + - `1` Status report + - `2` Photon torpedo course data + - `3` Starbase navigation data + - `4` Direction/distance calculator + - `5` Quadrant nomenclature map + +6. Certain reports on the ship’s status are made by officers of the Enterprise who appears on the original TV Show—Spock,† Scott,† Uhura,† Chekov,† etc. + +7. Klingons are non-stationary within their quadrants. If you try to maneuver on them, they will move and fire on you. + +8. Firing and damage notes: + - Phaser fire diminishes with increased distance between combatants. + - If a Klingon zaps you hard enough (relative to your shield strength) he will generally cause damage to some part of your ship with an appropriate “Damage Control” report resulting. + - If you don’t zap a Klingon hard enough (relative to his shield strength) you won’t damage him at all. Your sensors will tell the story. + - Damage control will let you know when out-of-commission devices have been completely repaired. + +9. Your engines will automatically shit down if you should attempt to leave the galaxy, or if you should try to maneuver through a star, or Starbase, or—heaven help you—a Klingon warship. + +10. In a pinch, or if you should miscalculate slightly, some shield control energy will be automatically diverted to warp engine control (if your shield are operational!). + +11. While you’re docked at a Starbase, a team of technicians can repair your ship (if you’re willing for them to spend the time required—and the repairmen _always_ underestimate…) + +12. If, to same maneuvering time toward the end of the game, you should cold-bloodedly destroy a Starbase, you get a nasty note from Starfleet Command. If you destroy your _last_ Starbase, you lose the game! (For those who think this is too a harsh penalty, delete line 5360-5390, and you’ll just get a “you dumdum!”-type message on all future status reports.) + +13. End game logic has been “cleaned up” in several spots, and it is possible to get a new command after successfully completing your mission (or, after resigning your old one). + +14. For those of you with certain types of CRT/keyboards setups (e.g. Westinghouse 1600), a “bell” character is inserted at appropriate spots to cause the following items to flash on and off on the screen: + - The Phrase “\*RED\*” (as in Condition: Red) + - The character representing your present quadrant in the cumulative galactic record printout. + +15. This version of Star Trek was created for a Data General Nova 800 system with 32K or core. So that it would fit, the instructions are separated from the main program via a CHAIN. For conversion to DEC BASIC-PLUS, Statement 160 (Randomize) should be moved after the return from the chained instructions, say to Statement 245. For Altair BASIC, Randomize and the chain instructions should be eliminated. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=157) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=166) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html @@ -11,4 +102,3 @@ instructions.txt #### External Links - Super Star Trek in C++ : https://www.codeproject.com/Articles/28399/The-Object-Oriented-Text-Star-Trek-Game-in-C - diff --git a/85_Synonym/README.md b/85_Synonym/README.md index b9a5b79f..66c3c4c3 100644 --- a/85_Synonym/README.md +++ b/85_Synonym/README.md @@ -1,7 +1,20 @@ ### Synonym -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=164 +A synonym of a word is another word (in the English language) which has the same, or very nearly the same, meaning. This program tests your knowledge of synonyms of a few common words. + +The computer chooses a word and asks you for a synonym. The computer then tells you whether you’re right or wrong. If you can’t think of a synonym, type “HELP” which causes a synonym to be printed. + +You may put in words of your choice in the data statements. The number following DATA in Statement 500 is the total number of data statements. In each data statement, the first number is the number of words in that statement. + +Can you think of a way to make this into a more general kind of CAI program for any subject? + +Walt Koetke of Lexington High School, Massachusetts created this program. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=164) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=179) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html @@ -14,4 +27,4 @@ http://www.vintage-basic.net/games.html all of the help. - The player can ask for HELP and then submit that answer. Is it - meant to be a clue, or just giving a correct answer to the player? \ No newline at end of file + meant to be a clue, or just giving a correct answer to the player? diff --git a/86_Target/README.md b/86_Target/README.md index ca5f9177..29e14e64 100644 --- a/86_Target/README.md +++ b/86_Target/README.md @@ -1,7 +1,16 @@ ### Target -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=165 +In this program, you are firing a weapon from a spaceship in 3-dimensional space. Your ship, the Starship Enterprise, is located at the origin (0,0,0) of a set of x,y,z coordinates. You will be told the approximate location of the target in 3-dimensional rectangular coordinates, the approximate angular deviation from the x and z axes in both radians and degrees, and the approximate distance to the target. + +Given this information, you then proceed to shoot at the target. A shot within 20 kilometers of the target destroys it. After each shot, you are given information as to the position of the explosion of your shot and a somewhat improved estimate of the location of the target. Fortunately, this is just practice and the target doesn’t shoot back. After you have attained proficiency, you ought to be able to destroy a target in 3 or 4 shots. However, attaining proficiency might take a while! + +The author is H. David Crockett of Fort Worth, Texas. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=165) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=180) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/87_3-D_Plot/README.md b/87_3-D_Plot/README.md index e7cea9b4..3361976a 100644 --- a/87_3-D_Plot/README.md +++ b/87_3-D_Plot/README.md @@ -1,7 +1,16 @@ ### 3-D Plot -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=167 +3-D PLOT will plot the family of curves of any function. The function Z is plotted as “rising” out of the x-y plane with x and y inside a circle of radius 30. The resultant plot looks almost 3-dimensional. + +You set the function you want plotted in line 5. As with any mathematical plot, some functions come out “prettier” than others. + +The author of this amazingly clever program is Mark Bramhall of DEC. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=167) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=182) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/89_Tic-Tac-Toe/README.md b/89_Tic-Tac-Toe/README.md index b4d04d06..311322fa 100644 --- a/89_Tic-Tac-Toe/README.md +++ b/89_Tic-Tac-Toe/README.md @@ -1,7 +1,25 @@ ### Tic-Tac-Toe -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=171 +The game of tic-tac-toe hardly needs any introduction. In this one, you play versus the computer. Moves are entered by number: +``` +1 2 3 + +4 5 6 + +7 8 9 +``` + +If you make any bad moves, the computer will win; if the computer makes a bad move, you can win; otherwise, the game ends in a tie. + +A second version of the game is included which prints out the board after each move. This is ideally suited to a CRT terminal, particularly if you modify it to not print out a new board after each move, but rather use the cursor to make the move. + +The first program was written by Tom Koos while a student researcher at the Oregon Museum of Science and Industry; it was extensively modified by Steve North of Creative Computing. The author of the second game is Curt Flick of Akron, Ohio. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=171) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=186) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/90_Tower/README.md b/90_Tower/README.md index 6d452f7f..cbd05830 100644 --- a/90_Tower/README.md +++ b/90_Tower/README.md @@ -1,7 +1,20 @@ ### Tower -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=173 +This is a simulation of a game of logic that originated in the middle East. It is sometimes called Pharaoh's Needles, but its most common name is the Towers of Hanoi. + +Legend has it that a secret society of monks live beneath the city of Hanoi. They possess three large towers or needles on which different size gold disks may be placed. Moving one at a time and never placing a large on a smaller disk, the monks endeavor to move the tower of disks from the left needle to the right needle. Legend says when they have finished moving this 64-disk tower, the world will end. How many moves will they have to make to accomplish this? If they can move 1 disk per minute and work 24 hours per day, how many years will it take? + +In the computer puzzle you are faced with three upright needles. On the leftmost needle are placed from two to seven graduated disks, the largest being on bottom and smallest on top. Your object is to move the entire stack of disks to the rightmost needle. However, you many only move one disk at a time and you may never place a larger disk on top of a smaller one. + +In this computer game, the disks are referred to by their size — i.e., the smallest is 3, next 5, 7, 9, 11, 13, and 15. If you play with fewer than 7 disks always use the largest, i.e. with 2 disks you would use nos. 13 and 15. The program instructions are self-explanatory. Good luck! + +Charles Lund wrote this program while at the American School in the Hague, Netherlands. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=173) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=188) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/91_Train/README.md b/91_Train/README.md index c5a249fb..50e7cf6e 100644 --- a/91_Train/README.md +++ b/91_Train/README.md @@ -1,7 +1,16 @@ ### Train -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=175 +TRAIN is a program which uses the computer to generate problems with random initial conditions to teach about the time-speed-distance relationship (distance = rate x time). You then input your answer and the computer verifies your response. + +TRAIN is merely an example of a student-generated problem. Maximum fun (and benefit) comes more from _writing_ programs like this as opposed to solving the specific problem posed. Exchange your program with others—you solve their problem and let them solve yours. + +TRAIN was originally written in FOCAL by one student for use by others in his class. It was submitted to us by Walt Koetke, Lexington High School, Lexington, Mass. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=175) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=190) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/92_Trap/README.md b/92_Trap/README.md index 7778ecb5..18d5db48 100644 --- a/92_Trap/README.md +++ b/92_Trap/README.md @@ -1,7 +1,19 @@ ### Trap -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=176 +This is another in the family of “guess the mystery number” games. In TRAP the computer selects a random number between 1 and 100 (or other limit set). Your object is to find the number. On each guess, you enter 2 numbers trying to trap the mystery number between your two trap numbers. The computer will tell you if you have trapped the number. + +To win the game, you must guess the mystery number by entering it as the same value for both of your trap numbers. You get 6 guesses (this should be changed if you change the guessing limit). + +After you have played GUESS, STARS, and TRAP, compare the guessing strategy you have found best for each game. Do you notice any similarities? What are the differences? Can you write a new guessing game with still another approach? + +TRAP was suggested by a 10-year-old when he was playing GUESS. It was originally programmed by Steve Ullman and extensively modified into its final form by Bob Albrecht of People’s Computer Co. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=176) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=191) + Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/93_23_Matches/README.md b/93_23_Matches/README.md index eb368c88..3e48212e 100644 --- a/93_23_Matches/README.md +++ b/93_23_Matches/README.md @@ -1,7 +1,18 @@ ### 23 Matches -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=177 +In the game of twenty-three matches, you start with 23 matches lying on a table. On each turn, you may take 1, 2, or 3 matches. You alternate moves with the computer and the one who has to take the last match loses. + +The easiest way to devise a winning strategy is to start at the end of the game. Since your wish to leave the last match to your opponent, you would like to have either 4, 3, or 2 on your last turn you so can take away 3, 2, or 1 and leave 1. Consequently, you would like to leave your opponent with 5 on his next to last turn so, no matter what his move, you are left with 4, 3, or 2. Work this backwards to the beginning and you’ll find the game can effectively be won on the first move. Fortunately, the computer gives you the first move, so if you play wisely, you can win. + +After you’ve mastered 23 Matches, move on to BATNUM and then to NUM. + +This version of 23 Matches was originally written by Bob Albrecht of People’s Computer Company. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=177) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=192) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/94_War/README.md b/94_War/README.md index 4345c4ac..a850f73e 100644 --- a/94_War/README.md +++ b/94_War/README.md @@ -1,7 +1,14 @@ ### War -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=178 +This program plays the card game of War. In War, the card deck is shuffled, then two cards are dealt, one to each player. Players compare cards and the higher card (numerically) wins. In case of a tie, no one wins. The game ends when you have gone through the whole deck (52 cards, 26 games) or when you decide to quit. + +The computer gives cards by suit and number, for example, S-7 is the 7 of spades. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=178) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=193) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/95_Weekday/README.md b/95_Weekday/README.md index 16f825a3..445c2c4b 100644 --- a/95_Weekday/README.md +++ b/95_Weekday/README.md @@ -1,7 +1,16 @@ ### Weekday -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=179 +This program gives facts about your date of birth (or some other day of interest). It is not prepared to give information on people born before the use of the current type of calendar, i.e. year 1582. + +You merely enter today’s date in the form—month, day, year and your date of birth in the same form. The computer then tells you the day of the week of your birth date, your age, and how much time you have spent sleeping, eating, working, and relaxing. + +This program was adapted from a GE timesharing program by Tom Kloos at the Oregon Museum of Science and Industry. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=179) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=194) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html diff --git a/96_Word/README.md b/96_Word/README.md index 404135e8..8db22c6c 100644 --- a/96_Word/README.md +++ b/96_Word/README.md @@ -1,7 +1,16 @@ ### Word -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=181 +WORD is a combination of HANGMAN and BAGELS. In this game, the player must guess a word with clues as to a letter position furnished by the computer. However, instead of guessing one letter at a time, in WORD you guess an entire word (or group of 5 letters, such as ABCDE). The computer will tell you if any letters that you have guessed are in the mystery word and if any of them are in the correct position. Armed with these clues, you go on guessing until you get the word or, if you can’t get it, input a “?” and the computer will tell you the mystery word. + +You may change the words in Data Statements, but they must be 5-letter words. + +The author of this program is Charles Reid of Lexington High School, Lexington, Massachusetts. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=181) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=194) Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html From 7f2f34709a5bc0ce28088075591408a3d0eab5c0 Mon Sep 17 00:00:00 2001 From: LukasMurdock Date: Mon, 3 Jan 2022 02:23:34 -0500 Subject: [PATCH 511/749] typo, left out y in originally --- 63_Name/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/63_Name/README.md b/63_Name/README.md index a3744cdd..302cdf07 100644 --- a/63_Name/README.md +++ b/63_Name/README.md @@ -2,7 +2,7 @@ NAME is a silly little ice-breaker to get a relationship going between a computer and a shy human. The sorting algorithm used is highly inefficient — as any reader of _Creative Computing_ will recognize, this is the worst possible sort for speed. But the program is good fun and that’s what counts here. -NAME was originall written by Geoffry Chase of the Abbey, Portsmouth, Rhode Island. +NAME was originally written by Geoffry Chase of the Abbey, Portsmouth, Rhode Island. --- From 87613662a89cc8d4480e00a39af1a361464d275a Mon Sep 17 00:00:00 2001 From: LukasMurdock Date: Mon, 3 Jan 2022 02:26:52 -0500 Subject: [PATCH 512/749] typo, misspelled Geoffrey --- 63_Name/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/63_Name/README.md b/63_Name/README.md index 302cdf07..45bf4e9a 100644 --- a/63_Name/README.md +++ b/63_Name/README.md @@ -2,7 +2,7 @@ NAME is a silly little ice-breaker to get a relationship going between a computer and a shy human. The sorting algorithm used is highly inefficient — as any reader of _Creative Computing_ will recognize, this is the worst possible sort for speed. But the program is good fun and that’s what counts here. -NAME was originally written by Geoffry Chase of the Abbey, Portsmouth, Rhode Island. +NAME was originally written by Geoffrey Chase of the Abbey, Portsmouth, Rhode Island. --- From 5e8b3b2ad2670c0d3b9575a666bde10473db384e Mon Sep 17 00:00:00 2001 From: aviyam Date: Mon, 3 Jan 2022 12:42:36 +0200 Subject: [PATCH 513/749] Fixed 2 issues: 1. Behavior of game play. New cards should be dealt every round. 2. As a result of 1, check that we have at least 3 cards for next round. --- 01_Acey_Ducey/python/acey_ducey_oo.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/01_Acey_Ducey/python/acey_ducey_oo.py b/01_Acey_Ducey/python/acey_ducey_oo.py index d8b7c752..325af4b4 100644 --- a/01_Acey_Ducey/python/acey_ducey_oo.py +++ b/01_Acey_Ducey/python/acey_ducey_oo.py @@ -95,11 +95,14 @@ class Game: self.not_done = False break - if len(self.deck.cards) <= 1: + if len(self.deck.cards) <= 3: print('You ran out of cards. Game over.') self.not_done = False break + self.card_a = self.deck.deal() + self.card_b = self.deck.deal() + if self.money == 0: self.not_done = False From 708155978c73f2a314594f421d930599b99a21f5 Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Mon, 3 Jan 2022 06:23:44 -0500 Subject: [PATCH 514/749] Add Perl port of 90_Tower (Tower of Hanoi) --- 90_Tower/perl/tower.pl | 381 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100755 90_Tower/perl/tower.pl diff --git a/90_Tower/perl/tower.pl b/90_Tower/perl/tower.pl new file mode 100755 index 00000000..f9258eea --- /dev/null +++ b/90_Tower/perl/tower.pl @@ -0,0 +1,381 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +# Manifest constant representing the maximum number of disks. We can +# change this within limits. It needs to be at least 3 or the +# explanatory text will contain negative numbers. There is no known +# upper limit, though if it is more than 10 the output lines can be more +# than 80 columns, and if it is more than 49 the disk numbers will be +# more than two digits, which will cause output lines not to align +# properly. +use constant MAX_DISKS => 7; + +print <<'EOD'; + TOWERS + Creative Computing Morristown, New Jersey + + +EOD + +while ( 1 ) { # Iterate until something makes us stop. + + print <<'EOD'; +Towers of Hanoi Puzzle. + +You must transfer the disks from the left to the right +Tower, one at a time, never putting a larger disk on a +smaller disk. + +EOD + + # Get the desired number of disks to work with. + my $size = get_input( + + # Manifest constants do not interpolate into strings. This can + # be worked around using the @{[ ... ]} construction, which + # interpolates any expression. + "How many disks do you want to move (@{[ MAX_DISKS ]} is max)? ", + + sub { + + # Accept any response which is an integer greater than zero + # and less than or equal to the maximum number of disks. + # NOTE that 'and' performs the same operation as &&, but + # binds much more loosely. + return m/ \A [0-9]+ \z /smx && + $ARG > 0 && + $ARG <= MAX_DISKS; + }, + + 3, + "Sorry, but I can't do that job for you.\n", # Warning + <<'EOD', +All right, wise guy, if you can't play the game right, I'll +just take my puzzle and go home. So long. +EOD + ); + + # Expressions can be interpolated using @{[ ... ]} + print <<"EOD"; +In this program, we shall refer to disks by numerical code. +3 will represent the smallest disk, 5 the next size, +7 the next, and so on, up to @{[ MAX_DISKS * 2 + 1 ]}. If you do the puzzle with +2 disks, their code names would be @{[ MAX_DISKS * 2 - 1 ]} and @{[ MAX_DISKS * 2 + 1 ]}. With 3 disks +the code names would be @{[ MAX_DISKS * 2 - 3 ]}, @{[ MAX_DISKS * 2 - 1 ]} and @{[ MAX_DISKS * 2 + 1 ]}, etc. The needles +are numbered from left to right, 1 to 3. We will +start with the disks on needle 1, and attempt to move them +to needle 3. + + +Good luck! + +EOD + + # Compute the legal disk numbers for this puzzle. The expression + # reads right to left thus: + # * The .. operator generates the integers between and including + # its end points, that is, from MAX_DISKS + 1 - $size to + # MAX_DISKS, inclusive. + # * map { .. } calls the block once for each of its arguments. + # The value of the argument appears in the topic variable $ARG, + # and the result of the block is returned. + # * The list generated by the map {} is assigned to array + # @legal_disks. + my @legal_disks = map { $ARG * 2 + 1 } + MAX_DISKS + 1 - $size .. MAX_DISKS; + + # Generate the board. This is an array of needles, indexed from + # zero. Each needle is represented by a reference to an array + # containing the disks on that needle, bottom to top. + my @board = ( + [ reverse @legal_disks ], + [], + [] + ); + + display( \@board ); # Display the initial board. + + my $moves = 0; # Move counter. + + while ( 1 ) { # Iterate until something makes us stop. + my $disk = get_input( + 'Which disk would you like to move? ', + sub { + # Accept any odd integer in the required range. + # NOTE that 'and' performs the same operation as &&, but + # binds much more loosely. + return m/ \A [0-9]+ \z /smx && + $ARG % 2 && + $ARG >= ( MAX_DISKS + 1 - $size ) * 2 + 1 && + $ARG <= MAX_DISKS * 2 + 1; + }, + 3, + do { # Compound statement and scope for 'local' + + # We want to interpolate @legal_disks into our warning. + # Interpolation of an array places $LIST_SEPARATOR + # between the elements of the array. The default is ' ', + # but we want ', '. We use 'local' to restrict the + # change to the current block and code called by it. + # Failure to localize the change can cause Spooky Action + # at a Distance. + local $LIST_SEPARATOR = ', '; + + "Illegal entry... You may only type @legal_disks\n"; + }, + "Stop wasting my time. Go bother someone else.\n", + ); + + # Return the number (from zero) of the needle which has the + # desired disk on top. If the desired disk is not found, we got + # undef back. In this case we redo the innermost loop. + redo unless defined( my $from = find_disk( $disk, \@board ) ); + + # Find out where the chosen disk goes. + # NOTE that unlike the BASIC implementation, we require the + # needle to be moved. + my $to = get_input( + 'Place disk on which needle? ', + sub { + # Accept integers 1 through 3, but not the current + # location of the disk + return m/ \A [0-9]+ \z /smx && + $ARG > 0 && + $ARG <= 3 && + $ARG != $from + 1; + }, + 2, + <<'EOD', +I'll assume you hit the wrong key this time. But watch it, +I only allow one mistake. +EOD + <<'EOD', +I tried to warn you, but you wouldn't listen. +Bye bye, big shot. +EOD + ) - 1; + + # Check for placing a larger disk on a smaller one. The check is + # that the destination needle has something on it (an empty + # array is false in Boolean context) and that the destination + # needle's top disk ([-1] selects the last element of an array) + # is smaller than the source needle's disk. + if ( @{ $board[$to] } && $board[$to][-1] < $board[$from][-1] ) { + warn <<'EOD'; +You can't place a larger disk on top of a smaller one, +It might crush it! +EOD + redo; + } + + # Remove the selected disk from its needle, and place it on the + # destination needle. + push @{ $board[$to] }, pop @{ $board[$from] }; + + $moves++; # Count another move. + + display( \@board ); # Display the current board. + + # If all the disks are on the last needle, we are done. + if ( @{ $board[2] } == $size ) { + + # Print a success message + print <<"EOD"; +Congratulations! + +You have performed the task in $moves moves. + +EOD + last; # Exit the innermost loop. + + # If the maximum allowed moves have been exceeded + } elsif ( $moves >= 2 ** MAX_DISKS ) { + + # Warn + warn <<"EOD"; +Sorry, but I have orders to stop if you make more than +$moves moves. +EOD + + last; # Exit the innermost loop. + } + } + + say ''; + get_input( + 'Try again? [y/N]: ', + sub { + exit if $ARG eq '' || m/ \A n /smxi; + return m/ \A y /smxi; + }, + ~0, # The 1's complement of 0 = largest possible integer + "Please respond 'y' or 'n'\n", + ); +} + +# Display the board, which is passed in as a reference. +sub display { + my ( $board ) = @_; + say ''; + + # Use a manifest constant for an empty needle. This is global + # despite its appearing to be nested in the subroutine. Perl uses + # 'x' as its string replication operator. The initial 4 blanks + # accommodate the disk number and spacing between needles. + use constant EMPTY_NEEDLE => ' ' x 4 . ' ' x MAX_DISKS . '|' . + ' ' x MAX_DISKS; + + # Iterate over the rows to be printed. + foreach my $inx ( reverse 0 .. MAX_DISKS ) { + + my $line; # Line buffer. + + # Iterate over needles. + foreach my $col ( 0 .. 2 ) { + + # If this position on the needle is occupied + if ( my $disk_num = $board->[$col][$inx] ) { + + # Compute the width of a half disk + my $half_width = ( $disk_num - 1 ) / 2; + + # Compute the graphic for the half disk. Perl uses 'x' + # as its string replication operator. + my $half_disk = '*' x $half_width; + + # Append the disk to the line. The inner sprintf() does + # most of the work; the outer simply pads the graphic to + # the required total width. + $line .= sprintf( '%*s', -( MAX_DISKS * 2 + 5 ), + sprintf( '%*d %s|%s', MAX_DISKS + 3 - $half_width, + $disk_num, $half_disk, $half_disk ) ); + + # Else this position is not occupied + } else { + + # So just append the empty needle. + $line .= EMPTY_NEEDLE; + } + } + + # Remove white space at the end of the line + $line =~ s/ \s+ \z //smx; + + # Display the line + say $line; + } + { # Display the needle numbers + my $line; + foreach my $col ( 0 .. 2 ) { + $line .= sprintf '%*d%*s', MAX_DISKS + 5, $col + 1, + MAX_DISKS, ' '; + } + $line =~ s/ \s+ \z //smx; + say $line; + } + + say ''; # Empty line + + return; +} + +# Find the named disk. The arguments are the disk number (which is +# assumed valid) and a reference to the board. If the disk is found on +# the top of a needle, the needle's index (from zero) is returned. +# Otherwise a warning is issued and undef is returned. +sub find_disk { + my ( $disk, $board ) = @_; + foreach my $inx ( 0 .. 2 ) { + @{ $board->[$inx] } # If the needle is occupied + and $disk == $board->[$inx][-1] # and we want its topmost + and return $inx; # return needle index + } + + # Since we assume the disk number is valid but we did not find it, + # it must not be the topmost disk. + warn "That disk is below another one. Make another choice.\n"; + + return undef; +} + +# Input subroutine. The arguments are: +# * The prompt. +# * Validation code. This recieves the input in the topic variable $ARG, +# and returns a true value if the validation passed, and a false value +# if it failed. +# * The maximum number of tries before dying. +# * The warning message for a validation failure, with trailing "\n". +# * The error message when the number of tries is exceeded, with +# trailing "\n". +# The return is the valid input. We exit if end-of-file is reached, +sub get_input { + my ( $prompt, $validate, $tries, $warning, $error ) = @_; + + # Instantiate the readline object. A state variable is only + # initialized once. + state $term = Term::ReadLine->new( 'tower' ); + + while ( 1 ) { # Iterate until something makes us stop. + + # The input gets read into the localized topic variable. If it + # is undefined, it signals end-of-file, so we exit. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Call the validation code. If it returns a true value, we + # return our input. + return $ARG if $validate->(); + + # Die if we are out of retries. In Perl, 0 is false and all + # other integers are true. + die $error unless --$tries; + + # Warn. + warn $warning; + } +} + +__END__ + +=head1 TITLE + +tower.pl - Play the game 'tower' from Basic Computer Games + +=head1 SYNOPSIS + + tower.pl + +=head1 DETAILS + +This Perl script is a port of C, which is the 90th entry in Basic +Computer Games. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From e9ce5210168b8d87ec6bd8766f6bb339907ec982 Mon Sep 17 00:00:00 2001 From: LukasMurdock Date: Mon, 3 Jan 2022 06:49:10 -0500 Subject: [PATCH 515/749] save 3-D tic-tac-toe --- 88_3-D_Tic-Tac-Toe/README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/88_3-D_Tic-Tac-Toe/README.md b/88_3-D_Tic-Tac-Toe/README.md index e06c4e40..df9cabf4 100644 --- a/88_3-D_Tic-Tac-Toe/README.md +++ b/88_3-D_Tic-Tac-Toe/README.md @@ -1,7 +1,17 @@ ### 3-D Tic-Tac-Toe -As published in Basic Computer Games (1978) -https://www.atariarchives.org/basicgames/showpage.php?page=168 +3-D TIC-TAC-TOE is a game of tic-tac-toe in a 4x4x4 cube. You must get 4 markers in a row or diagonal along any 3-dimensional plane in order to win. + +Each move is indicated by a 3-digit number (digits not separated by commas), with each digit between 1 and 4 inclusive. The digits indicate the level, column, and row, respectively, of the move. You can win if you play correctly; although, it is considerably more difficult than standard, two-dimensional 3x3 tic-tac-toe. + +This version of 3-D TIC-TAC-TOE is from Dartmouth College. + +--- + +As published in Basic Computer Games (1978): +- [Atari Archives](https://www.atariarchives.org/basicgames/showpage.php?page=168) +- [Annarchive](https://annarchive.com/files/Basic_Computer_Games_Microcomputer_Edition.pdf#page=183) + Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html From 711fca294d166bb6deda046695bdcebabb72b278 Mon Sep 17 00:00:00 2001 From: marijnz0r Date: Mon, 3 Jan 2022 12:51:38 +0100 Subject: [PATCH 516/749] Add csharp version of 40_Gunner --- 42_Gunner/csharp/Program.cs | 124 +++++++++++++++++++++++++++++++++ 42_Gunner/csharp/csharp.csproj | 10 +++ 2 files changed, 134 insertions(+) create mode 100644 42_Gunner/csharp/Program.cs create mode 100644 42_Gunner/csharp/csharp.csproj diff --git a/42_Gunner/csharp/Program.cs b/42_Gunner/csharp/Program.cs new file mode 100644 index 00000000..f93c57d5 --- /dev/null +++ b/42_Gunner/csharp/Program.cs @@ -0,0 +1,124 @@ +namespace Gunner +{ + class Program + { + static void Main(string[] args) + { + PrintIntro(); + + string keepPlaying = "Y"; + + while (keepPlaying == "Y") { + PlayGame(); + Console.WriteLine("TRY AGAIN (Y OR N)"); + keepPlaying = Console.ReadLine(); + } + } + + static void PlayGame() + { + int totalAttempts = 0; + int amountOfGames = 0; + + while (amountOfGames < 4) { + + int maximumRange = new Random().Next(0, 40000) + 20000; + Console.WriteLine($"MAXIMUM RANGE OF YOUR GUN IS {maximumRange} YARDS." + Environment.NewLine + Environment.NewLine + Environment.NewLine); + + int distanceToTarget = (int) (maximumRange * (0.1 + 0.8 * new Random().NextDouble())); + Console.WriteLine($"DISTANCE TO THE TARGET IS {distanceToTarget} YARDS."); + + (bool gameWon, int attempts) = HitTheTarget(maximumRange, distanceToTarget); + + if(!gameWon) { + Console.WriteLine(Environment.NewLine + "BOOM !!!! YOU HAVE JUST BEEN DESTROYED" + Environment.NewLine + + "BY THE ENEMY." + Environment.NewLine + Environment.NewLine + Environment.NewLine + ); + PrintReturnToBase(); + break; + } else { + amountOfGames += 1; + totalAttempts += attempts; + + Console.WriteLine($"TOTAL ROUNDS EXPENDED WERE:{totalAttempts}"); + + if (amountOfGames < 4) { + Console.WriteLine("THE FORWARD OBSERVER HAS SIGHTED MORE ENEMY ACTIVITY..."); + } else { + if (totalAttempts > 18) { + PrintReturnToBase(); + } else { + Console.WriteLine($"NICE SHOOTING !!"); + } + } + } + } + } + + static (bool, int) HitTheTarget(int maximumRange, int distanceToTarget) + { + int attempts = 0; + + while (attempts < 6) + { + int elevation = GetElevation(); + + int differenceBetweenTargetAndImpact = CalculateDifferenceBetweenTargetAndImpact(maximumRange, distanceToTarget, elevation); + + if (Math.Abs(differenceBetweenTargetAndImpact) < 100) + { + Console.WriteLine($"*** TARGET DESTROYED *** {attempts} ROUNDS OF AMMUNITION EXPENDED."); + return (true, attempts); + } + else if (differenceBetweenTargetAndImpact > 100) + { + Console.WriteLine($"OVER TARGET BY {Math.Abs(differenceBetweenTargetAndImpact)} YARDS."); + } + else + { + Console.WriteLine($"SHORT OF TARGET BY {Math.Abs(differenceBetweenTargetAndImpact)} YARDS."); + } + + attempts += 1; + } + return (false, attempts); + } + + static int CalculateDifferenceBetweenTargetAndImpact(int maximumRange, int distanceToTarget, int elevation) + { + double weirdNumber = 2 * elevation / 57.3; + double distanceShot = maximumRange * Math.Sin(weirdNumber); + return (int)distanceShot - distanceToTarget; + } + + static void PrintReturnToBase() + { + Console.WriteLine("BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!"); + } + + static int GetElevation() + { + Console.WriteLine("ELEVATION"); + int elevation = int.Parse(Console.ReadLine()); + if (elevation > 89) { + Console.WriteLine("MAXIMUM ELEVATION IS 89 DEGREES"); + return GetElevation(); + } + if (elevation < 1) { + Console.WriteLine("MINIMUM ELEVATION IS 1 DEGREE"); + return GetElevation(); + } + return elevation; + } + + static void PrintIntro() + { + Console.WriteLine(new String(' ', 30) + "GUNNER"); + Console.WriteLine(new String(' ', 15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" + Environment.NewLine + Environment.NewLine + Environment.NewLine); + Console.WriteLine("YOU ARE THE OFFICER-IN-CHARGE, GIVING ORDERS TO A GUN"); + Console.WriteLine("CREW, TELLING THEM THE DEGREES OF ELEVATION YOU ESTIMATE"); + Console.WriteLine("WILL PLACE A PROJECTILE ON TARGET. A HIT WITHIN 100 YARDS"); + Console.WriteLine("OF THE TARGET WILL DESTROY IT." + Environment.NewLine); + } + } +} diff --git a/42_Gunner/csharp/csharp.csproj b/42_Gunner/csharp/csharp.csproj new file mode 100644 index 00000000..74abf5c9 --- /dev/null +++ b/42_Gunner/csharp/csharp.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + From 25dcb2a32572d6d7634b618cd297616dcd753755 Mon Sep 17 00:00:00 2001 From: Luminoso-256 <63971285+Luminoso-256@users.noreply.github.com> Date: Mon, 3 Jan 2022 08:31:32 -0600 Subject: [PATCH 517/749] add C# port of 21_calendar --- 21_Calendar/csharp/21_calendar.csproj | 9 ++ 21_Calendar/csharp/21_calendar.sln | 25 +++++ 21_Calendar/csharp/Program.cs | 144 ++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 21_Calendar/csharp/21_calendar.csproj create mode 100644 21_Calendar/csharp/21_calendar.sln create mode 100644 21_Calendar/csharp/Program.cs diff --git a/21_Calendar/csharp/21_calendar.csproj b/21_Calendar/csharp/21_calendar.csproj new file mode 100644 index 00000000..895f2f3f --- /dev/null +++ b/21_Calendar/csharp/21_calendar.csproj @@ -0,0 +1,9 @@ + + + + Exe + net5.0 + _21_calendar + + + diff --git a/21_Calendar/csharp/21_calendar.sln b/21_Calendar/csharp/21_calendar.sln new file mode 100644 index 00000000..d8330a26 --- /dev/null +++ b/21_Calendar/csharp/21_calendar.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31613.86 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "21_calendar", "21_calendar.csproj", "{99AB85E1-A42B-4FEF-8BA6-0ED877F05249}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99AB85E1-A42B-4FEF-8BA6-0ED877F05249}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99AB85E1-A42B-4FEF-8BA6-0ED877F05249}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99AB85E1-A42B-4FEF-8BA6-0ED877F05249}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99AB85E1-A42B-4FEF-8BA6-0ED877F05249}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1B423C35-492F-4AF8-97FC-BEC69B44EC8D} + EndGlobalSection +EndGlobal diff --git a/21_Calendar/csharp/Program.cs b/21_Calendar/csharp/Program.cs new file mode 100644 index 00000000..4fd2b177 --- /dev/null +++ b/21_Calendar/csharp/Program.cs @@ -0,0 +1,144 @@ +using System; + +/* + 21_Calendar in C# for basic-computer-games + Converted by luminoso-256 +*/ + +namespace _21_calendar +{ + class Program + { + //basic has a TAB function. We do not by default, so we make our own! + static string Tab(int numspaces) + { + string space = ""; + //loop as many times as there are spaces specified, and add a space each time + while (numspaces > 0) + { + //add the space + space += " "; + //decrement the loop variable so we don't keep going forever! + numspaces--; + } + return space; + } + + static void Main(string[] args) + { + // print the "title" of our program + // the usage of Write*Line* means we do not have to specify a newline (\n) + Console.WriteLine(Tab(32) + "CALENDAR"); + Console.WriteLine(Tab(15) + "CREATE COMPUTING MORRISTOWN, NEW JERSEY"); + //give us some space. + Console.WriteLine(""); + Console.WriteLine(""); + Console.WriteLine(""); + + //establish some variables needed to print out a calculator + + //the length of each month in days. On a leap year, the start of this would be + // 0, 31, 29 to account for Feb. the 0 at the start is for days elapsed to work right in Jan. + int[] monthLengths = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // m in original source + + //the starting day of the month. in 1979 this was monday + // 0 = sun, -1 = mon, -2 = tue, -3 = wed, etc. + int day = -1; // called d in original source + + //how much time in the year has gone by? + int elapsed = 0; // called s in original source + + //loop through printing all the months. + for (int month = 1; month <= 12; month++) //month is called n in original source + { + //pad some space + Console.WriteLine(""); + Console.WriteLine(""); + //increment days elapsed + elapsed += monthLengths[month - 1]; + //build our header for this month of the calendar + string header = "** " + elapsed; + //add padding as needed + while (header.Length < 7) + { + header += " "; + } + for (int i = 1; i <= 18; i++) + { + header += "*"; + } + //determine what month it is, add text accordingly + switch (month) { + case 1: header += " JANUARY "; break; + case 2: header += " FEBRUARY"; break; + case 3: header += " MARCH "; break; + case 4: header += " APRIL "; break; + case 5: header += " MAY "; break; + case 6: header += " JUNE "; break; + case 7: header += " JULY "; break; + case 8: header += " AUGUST "; break; + case 9: header += "SEPTEMBER"; break; + case 10: header += " OCTOBER "; break; + case 11: header += " NOVEMBER"; break; + case 12: header += " DECEMBER"; break; + } + //more padding + for (int i = 1; i <= 18; i++) + { + header += "*"; + } + header += " "; + // how many days left till the year's over? + header += (365 - elapsed) + " **"; // on leap years 366 + Console.WriteLine(header); + //dates + Console.WriteLine(" S M T W T F S"); + Console.WriteLine(" "); + + string weekOutput = ""; + for (int i = 1; i <= 59; i++) + { + weekOutput += "*"; + } + //init some vars ahead of time + int g = 0; + int d2 = 0; + //go through the weeks and days + for (int week = 1; week <= 6; week++) + { + Console.WriteLine(weekOutput); + weekOutput = " "; + for (g = 1; g <= 7; g++) + { + //add one to the day + day++; + d2 = day - elapsed; + //check if we're done with this month + if (d2 > monthLengths[month]) + { + week = 6; + break; + } + //should we print this day? + if (d2 > 0) + { + weekOutput += d2; + } + //padding + while (weekOutput.Length < 4 + 8 * g) + { + weekOutput += " "; + } + } + if (d2 == monthLengths[month]) + { + day += g; + break; + } + } + day -= g; + Console.WriteLine(weekOutput); + } + } + } +} From 6977afdef090628d7c96e4fb23e019cb5657d0cb Mon Sep 17 00:00:00 2001 From: baka0815 Date: Mon, 3 Jan 2022 18:24:09 +0100 Subject: [PATCH 518/749] AceyDucey/pascal: Move Randomize() Randomize() should be called only once and as soon as possible. --- 01_Acey_Ducey/pascal/object-pascal/game.pas | 2 +- 01_Acey_Ducey/pascal/simple/aceyducey.pas | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/01_Acey_Ducey/pascal/object-pascal/game.pas b/01_Acey_Ducey/pascal/object-pascal/game.pas index 1a263159..1e983f7c 100644 --- a/01_Acey_Ducey/pascal/object-pascal/game.pas +++ b/01_Acey_Ducey/pascal/object-pascal/game.pas @@ -85,6 +85,7 @@ end; constructor TGame.Create; begin + Randomize; FDeck:= TDeck.Create; end; @@ -99,7 +100,6 @@ begin ClrScr; PrintGreeting; repeat - Randomize; FStash:= 100; repeat PrintBalance; diff --git a/01_Acey_Ducey/pascal/simple/aceyducey.pas b/01_Acey_Ducey/pascal/simple/aceyducey.pas index 35a9dd64..fa049eb0 100644 --- a/01_Acey_Ducey/pascal/simple/aceyducey.pas +++ b/01_Acey_Ducey/pascal/simple/aceyducey.pas @@ -118,10 +118,10 @@ begin end; begin + Randomize; ClrScr; PrintGreeting; repeat - Randomize; Stash:= 100; repeat PrintBalance; From f57c27f1ead8c1c280caac934bca45f7bef3280e Mon Sep 17 00:00:00 2001 From: Dave Shapiro Date: Mon, 3 Jan 2022 11:21:08 -0700 Subject: [PATCH 519/749] Fix typo in Bombs Away README. --- 12_Bombs_Away/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/12_Bombs_Away/README.md b/12_Bombs_Away/README.md index 0baa3558..b1b60277 100644 --- a/12_Bombs_Away/README.md +++ b/12_Bombs_Away/README.md @@ -1,6 +1,6 @@ ### Bombs Away -In this program, you fly a World War II bomber for one of the four protagonists of the war. You then pick your target or the type of plane you are flying. Depending on your flying experience and the quality of enemy defenders, you then may accomplish your mission, get shot down, or make it back through enemy fire. In any case, you get a change to fly again. +In this program, you fly a World War II bomber for one of the four protagonists of the war. You then pick your target or the type of plane you are flying. Depending on your flying experience and the quality of enemy defenders, you then may accomplish your mission, get shot down, or make it back through enemy fire. In any case, you get a chance to fly again. David Ahl modified the original program which was created by David Sherman while a student at Curtis Jr. High School, Sudbury, Massachusetts. From fd7adde9902574793873cc92d06874a5afc2fde6 Mon Sep 17 00:00:00 2001 From: Dave Shapiro Date: Mon, 3 Jan 2022 11:30:55 -0700 Subject: [PATCH 520/749] Added Bombs Away in C#. This is a Visual Studio 2022 solution and uses the latest language features like file-scoped namespaces. --- 12_Bombs_Away/csharp/BombsAway.sln | 31 +++ .../BombsAwayConsole/BombsAwayConsole.csproj | 14 ++ .../BombsAwayConsole/ConsoleUserInterface.cs | 134 +++++++++++ .../csharp/BombsAwayConsole/Program.cs | 26 +++ .../csharp/BombsAwayGame/AlliesSide.cs | 22 ++ .../csharp/BombsAwayGame/BombsAwayGame.csproj | 9 + .../csharp/BombsAwayGame/EnemyArtillery.cs | 8 + 12_Bombs_Away/csharp/BombsAwayGame/Game.cs | 58 +++++ .../csharp/BombsAwayGame/GermanySide.cs | 21 ++ .../csharp/BombsAwayGame/IUserInterface.cs | 38 ++++ .../csharp/BombsAwayGame/ItalySide.cs | 21 ++ .../csharp/BombsAwayGame/JapanSide.cs | 38 ++++ 12_Bombs_Away/csharp/BombsAwayGame/Mission.cs | 8 + .../csharp/BombsAwayGame/MissionSide.cs | 208 ++++++++++++++++++ 12_Bombs_Away/csharp/BombsAwayGame/Side.cs | 97 ++++++++ 15 files changed, 733 insertions(+) create mode 100644 12_Bombs_Away/csharp/BombsAway.sln create mode 100644 12_Bombs_Away/csharp/BombsAwayConsole/BombsAwayConsole.csproj create mode 100644 12_Bombs_Away/csharp/BombsAwayConsole/ConsoleUserInterface.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayConsole/Program.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/AlliesSide.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/BombsAwayGame.csproj create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/EnemyArtillery.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/Game.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/GermanySide.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/IUserInterface.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/ItalySide.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/JapanSide.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/Mission.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/MissionSide.cs create mode 100644 12_Bombs_Away/csharp/BombsAwayGame/Side.cs diff --git a/12_Bombs_Away/csharp/BombsAway.sln b/12_Bombs_Away/csharp/BombsAway.sln new file mode 100644 index 00000000..8ae70157 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAway.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BombsAwayConsole", "BombsAwayConsole\BombsAwayConsole.csproj", "{D80015FA-423C-4A16-AA2B-16669245AD59}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BombsAwayGame", "BombsAwayGame\BombsAwayGame.csproj", "{F57AEC18-FEE9-4F08-9F20-DFC56EFE6BFC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D80015FA-423C-4A16-AA2B-16669245AD59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D80015FA-423C-4A16-AA2B-16669245AD59}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D80015FA-423C-4A16-AA2B-16669245AD59}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D80015FA-423C-4A16-AA2B-16669245AD59}.Release|Any CPU.Build.0 = Release|Any CPU + {F57AEC18-FEE9-4F08-9F20-DFC56EFE6BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F57AEC18-FEE9-4F08-9F20-DFC56EFE6BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F57AEC18-FEE9-4F08-9F20-DFC56EFE6BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F57AEC18-FEE9-4F08-9F20-DFC56EFE6BFC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {39B2ECFB-037D-4335-BBD2-64892E953DD4} + EndGlobalSection +EndGlobal diff --git a/12_Bombs_Away/csharp/BombsAwayConsole/BombsAwayConsole.csproj b/12_Bombs_Away/csharp/BombsAwayConsole/BombsAwayConsole.csproj new file mode 100644 index 00000000..aae99def --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayConsole/BombsAwayConsole.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/12_Bombs_Away/csharp/BombsAwayConsole/ConsoleUserInterface.cs b/12_Bombs_Away/csharp/BombsAwayConsole/ConsoleUserInterface.cs new file mode 100644 index 00000000..66d6d4d3 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayConsole/ConsoleUserInterface.cs @@ -0,0 +1,134 @@ +namespace BombsAwayConsole; + +/// +/// Implements by writing to and reading from . +/// +internal class ConsoleUserInterface : BombsAwayGame.IUserInterface +{ + /// + /// Write message to console. + /// + /// Message to display. + public void Output(string message) + { + Console.WriteLine(message); + } + + /// + /// Write choices with affixed indexes, allowing the user to choose by index. + /// + /// Message to display. + /// Choices to display. + /// Choice that user picked. + public int Choose(string message, IList choices) + { + IEnumerable choicesWithIndexes = choices.Select((choice, index) => $"{choice}({index + 1})"); + string choiceText = string.Join(", ", choicesWithIndexes); + Output($"{message} -- {choiceText}"); + + ISet allowedKeys = ConsoleKeysFromList(choices); + ConsoleKey? choice; + do + { + choice = ReadChoice(allowedKeys); + if (choice is null) + { + Output("TRY AGAIN..."); + } + } + while (choice is null); + + return ListIndexFromConsoleKey(choice.Value); + } + + /// + /// Convert the given list to its equivalents. This generates keys that map + /// the first element to , the second element to , + /// and so on, up to the last element of the list. + /// + /// List whose elements will be converted to equivalents. + /// equivalents from . + private ISet ConsoleKeysFromList(IList list) + { + IEnumerable indexes = Enumerable.Range((int)ConsoleKey.D1, list.Count); + return new HashSet(indexes.Cast()); + } + + /// + /// Convert the given console key to its list index equivalent. This assumes the key was generated from + /// + /// + /// Key to convert to its list index equivalent. + /// List index equivalent of key. + private int ListIndexFromConsoleKey(ConsoleKey key) + { + return key - ConsoleKey.D1; + } + + /// + /// Read a key from the console and return it if it is in the given allowed keys. + /// + /// Allowed keys. + /// Key read from , if it is in ; null otherwise./> + private ConsoleKey? ReadChoice(ISet allowedKeys) + { + ConsoleKeyInfo keyInfo = ReadKey(); + return allowedKeys.Contains(keyInfo.Key) ? keyInfo.Key : null; + } + + /// + /// Read key from . + /// + /// Key read from . + private ConsoleKeyInfo ReadKey() + { + ConsoleKeyInfo result = Console.ReadKey(intercept: false); + // Write a blank line to the console so the displayed key is on its own line. + Console.WriteLine(); + return result; + } + + /// + /// Allow user to choose 'Y' or 'N' from . + /// + /// Message to display. + /// True if user chose 'Y', false if user chose 'N'. + public bool ChooseYesOrNo(string message) + { + Output(message); + ConsoleKey? choice; + do + { + choice = ReadChoice(new HashSet(new[] { ConsoleKey.Y, ConsoleKey.N })); + if (choice is null) + { + Output("ENTER Y OR N"); + } + } + while (choice is null); + + return choice.Value == ConsoleKey.Y; + } + + /// + /// Get integer by reading a line from . + /// + /// Integer read from . + public int InputInteger() + { + bool resultIsValid; + int result; + do + { + string? integerText = Console.ReadLine(); + resultIsValid = int.TryParse(integerText, out result); + if (!resultIsValid) + { + Output("PLEASE ENTER A NUMBER"); + } + } + while (!resultIsValid); + + return result; + } +} diff --git a/12_Bombs_Away/csharp/BombsAwayConsole/Program.cs b/12_Bombs_Away/csharp/BombsAwayConsole/Program.cs new file mode 100644 index 00000000..35728cfc --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayConsole/Program.cs @@ -0,0 +1,26 @@ +using BombsAwayConsole; +using BombsAwayGame; + +/// Create and play s using a . +PlayGameWhileUserWantsTo(new ConsoleUserInterface()); + +void PlayGameWhileUserWantsTo(ConsoleUserInterface ui) +{ + do + { + new Game(ui).Play(); + } + while (UserWantsToPlayAgain(ui)); +} + +bool UserWantsToPlayAgain(IUserInterface ui) +{ + bool result = ui.ChooseYesOrNo("ANOTHER MISSION (Y OR N)?"); + if (!result) + { + Console.WriteLine("CHICKEN !!!"); + } + + return result; +} + diff --git a/12_Bombs_Away/csharp/BombsAwayGame/AlliesSide.cs b/12_Bombs_Away/csharp/BombsAwayGame/AlliesSide.cs new file mode 100644 index 00000000..c6c7105b --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/AlliesSide.cs @@ -0,0 +1,22 @@ +namespace BombsAwayGame; + +/// +/// Allies protagonist. Can fly missions in a Liberator, B-29, B-17, or Lancaster. +/// +internal class AlliesSide : MissionSide +{ + public AlliesSide(IUserInterface ui) + : base(ui) + { + } + + protected override string ChooseMissionMessage => "AIRCRAFT"; + + protected override IList AllMissions => new Mission[] + { + new("LIBERATOR", "YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI."), + new("B-29", "YOU'RE DUMPING THE A-BOMB ON HIROSHIMA."), + new("B-17", "YOU'RE CHASING THE BISMARK IN THE NORTH SEA."), + new("LANCASTER", "YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR.") + }; +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/BombsAwayGame.csproj b/12_Bombs_Away/csharp/BombsAwayGame/BombsAwayGame.csproj new file mode 100644 index 00000000..132c02c5 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/BombsAwayGame.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/12_Bombs_Away/csharp/BombsAwayGame/EnemyArtillery.cs b/12_Bombs_Away/csharp/BombsAwayGame/EnemyArtillery.cs new file mode 100644 index 00000000..a810c8c0 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/EnemyArtillery.cs @@ -0,0 +1,8 @@ +namespace BombsAwayGame; + +/// +/// Represents enemy artillery. +/// +/// Name of artillery type. +/// Accuracy of artillery. This is the `T` variable in the original BASIC. +internal record class EnemyArtillery(string Name, int Accuracy); diff --git a/12_Bombs_Away/csharp/BombsAwayGame/Game.cs b/12_Bombs_Away/csharp/BombsAwayGame/Game.cs new file mode 100644 index 00000000..d6b5c3e9 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/Game.cs @@ -0,0 +1,58 @@ +namespace BombsAwayGame; + +/// +/// Plays the Bombs Away game using a supplied . +/// +public class Game +{ + private readonly IUserInterface _ui; + + /// + /// Create game instance using the given UI. + /// + /// UI to use for game. + public Game(IUserInterface ui) + { + _ui = ui; + } + + /// + /// Play game. Choose a side and play the side's logic. + /// + public void Play() + { + _ui.Output("YOU ARE A PILOT IN A WORLD WAR II BOMBER."); + Side side = ChooseSide(); + side.Play(); + } + + /// + /// Represents a . + /// + /// Name of side. + /// Create instance of side that this descriptor represents. + private record class SideDescriptor(string Name, Func CreateSide); + + /// + /// Choose side and return a new instance of that side. + /// + /// New instance of side that was chosen. + private Side ChooseSide() + { + SideDescriptor[] sides = AllSideDescriptors; + string[] sideNames = sides.Select(a => a.Name).ToArray(); + int index = _ui.Choose("WHAT SIDE", sideNames); + return sides[index].CreateSide(); + } + + /// + /// All side descriptors. + /// + private SideDescriptor[] AllSideDescriptors => new SideDescriptor[] + { + new("ITALY", () => new ItalySide(_ui)), + new("ALLIES", () => new AlliesSide(_ui)), + new("JAPAN", () => new JapanSide(_ui)), + new("GERMANY", () => new GermanySide(_ui)), + }; +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/GermanySide.cs b/12_Bombs_Away/csharp/BombsAwayGame/GermanySide.cs new file mode 100644 index 00000000..99843fce --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/GermanySide.cs @@ -0,0 +1,21 @@ +namespace BombsAwayGame; + +/// +/// Germany protagonist. Can fly missions to Russia, England, and France. +/// +internal class GermanySide : MissionSide +{ + public GermanySide(IUserInterface ui) + : base(ui) + { + } + + protected override string ChooseMissionMessage => "A NAZI, EH? OH WELL. ARE YOU GOING FOR"; + + protected override IList AllMissions => new Mission[] + { + new("RUSSIA", "YOU'RE NEARING STALINGRAD."), + new("ENGLAND", "NEARING LONDON. BE CAREFUL, THEY'VE GOT RADAR."), + new("FRANCE", "NEARING VERSAILLES. DUCK SOUP. THEY'RE NEARLY DEFENSELESS.") + }; +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/IUserInterface.cs b/12_Bombs_Away/csharp/BombsAwayGame/IUserInterface.cs new file mode 100644 index 00000000..50b7828c --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/IUserInterface.cs @@ -0,0 +1,38 @@ +namespace BombsAwayGame; + +/// +/// Represents an interface for supplying data to the game. +/// +/// +/// Abstracting the UI allows us to concentrate its concerns in one part of our code and to change UI behavior +/// without creating any risk of changing the game logic. It also allows us to supply an automated UI for tests. +/// +public interface IUserInterface +{ + /// + /// Display the given message. + /// + /// Message to display. + void Output(string message); + + /// + /// Choose an item from the given choices. + /// + /// Message to display. + /// Choices to choose from. + /// Index of choice in that user chose. + int Choose(string message, IList choices); + + /// + /// Allow user to choose Yes or No. + /// + /// Message to display. + /// True if user chose Yes, false if user chose No. + bool ChooseYesOrNo(string message); + + /// + /// Get integer from user. + /// + /// Integer supplied by user. + int InputInteger(); +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/ItalySide.cs b/12_Bombs_Away/csharp/BombsAwayGame/ItalySide.cs new file mode 100644 index 00000000..9f8bcd83 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/ItalySide.cs @@ -0,0 +1,21 @@ +namespace BombsAwayGame; + +/// +/// Italy protagonist. Can fly missions to Albania, Greece, and North Africa. +/// +internal class ItalySide : MissionSide +{ + public ItalySide(IUserInterface ui) + : base(ui) + { + } + + protected override string ChooseMissionMessage => "YOUR TARGET"; + + protected override IList AllMissions => new Mission[] + { + new("ALBANIA", "SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE."), + new("GREECE", "BE CAREFUL!!!"), + new("NORTH AFRICA", "YOU'RE GOING FOR THE OIL, EH?") + }; +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/JapanSide.cs b/12_Bombs_Away/csharp/BombsAwayGame/JapanSide.cs new file mode 100644 index 00000000..33abc83b --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/JapanSide.cs @@ -0,0 +1,38 @@ +namespace BombsAwayGame; + +/// +/// Japan protagonist. Flies a kamikaze mission, which has a different logic from s. +/// +internal class JapanSide : Side +{ + public JapanSide(IUserInterface ui) + : base(ui) + { + } + + /// + /// Perform a kamikaze mission. If first kamikaze mission, it will succeed 65% of the time. If it's not + /// first kamikaze mission, perform an enemy counterattack. + /// + public override void Play() + { + UI.Output("YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON."); + + bool isFirstMission = UI.ChooseYesOrNo("YOUR FIRST KAMIKAZE MISSION(Y OR N)?"); + if (!isFirstMission) + { + // LINE 207 of original BASIC: hitRatePercent is initialized to 0, + // but R, the type of artillery, is not initialized at all. Setting + // R = 1, which is to say EnemyArtillery = Guns, gives the same result. + EnemyCounterattack(Guns, hitRatePercent: 0); + } + else if (RandomFrac() > 0.65) + { + MissionSucceeded(); + } + else + { + MissionFailed(); + } + } +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/Mission.cs b/12_Bombs_Away/csharp/BombsAwayGame/Mission.cs new file mode 100644 index 00000000..c93892fd --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/Mission.cs @@ -0,0 +1,8 @@ +namespace BombsAwayGame; + +/// +/// Represents a mission that can be flown by a . +/// +/// Name of mission. +/// Description of mission. +internal record class Mission(string Name, string Description); diff --git a/12_Bombs_Away/csharp/BombsAwayGame/MissionSide.cs b/12_Bombs_Away/csharp/BombsAwayGame/MissionSide.cs new file mode 100644 index 00000000..b3a54275 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/MissionSide.cs @@ -0,0 +1,208 @@ +namespace BombsAwayGame; + +/// +/// Represents a protagonist that chooses a standard (non-kamikaze) mission. +/// +internal abstract class MissionSide : Side +{ + /// + /// Create instance using the given UI. + /// + /// UI to use. + public MissionSide(IUserInterface ui) + : base(ui) + { + } + + /// + /// Reasonable upper bound for missions flown previously. + /// + private const int MaxMissionCount = 160; + + /// + /// Choose a mission and attempt it. If attempt fails, perform an enemy counterattack. + /// + public override void Play() + { + Mission mission = ChooseMission(); + UI.Output(mission.Description); + + int missionCount = MissionCountFromUI(); + CommentOnMissionCount(missionCount); + + AttemptMission(missionCount); + } + + /// + /// Choose a mission. + /// + /// Mission chosen. + private Mission ChooseMission() + { + IList missions = AllMissions; + string[] missionNames = missions.Select(a => a.Name).ToArray(); + int index = UI.Choose(ChooseMissionMessage, missionNames); + return missions[index]; + } + + /// + /// Message to display when choosing a mission. + /// + protected abstract string ChooseMissionMessage { get; } + + /// + /// All aviailable missions to choose from. + /// + protected abstract IList AllMissions { get; } + + /// + /// Get mission count from UI. If mission count exceeds a reasonable maximum, ask UI again. + /// + /// Mission count from UI. + private int MissionCountFromUI() + { + const string HowManyMissions = "HOW MANY MISSIONS HAVE YOU FLOWN?"; + string inputMessage = HowManyMissions; + + bool resultIsValid; + int result; + do + { + UI.Output(inputMessage); + result = UI.InputInteger(); + if (result < 0) + { + UI.Output($"NUMBER OF MISSIONS CAN'T BE NEGATIVE."); + resultIsValid = false; + } + else if (result > MaxMissionCount) + { + resultIsValid = false; + UI.Output($"MISSIONS, NOT MILES...{MaxMissionCount} MISSIONS IS HIGH EVEN FOR OLD-TIMERS."); + inputMessage = "NOW THEN, " + HowManyMissions; + } + else + { + resultIsValid = true; + } + } + while (!resultIsValid); + + return result; + } + + /// + /// Display a message about the given mission count, if it is unusually high or low. + /// + /// Mission count to comment on. + private void CommentOnMissionCount(int missionCount) + { + if (missionCount >= 100) + { + UI.Output("THAT'S PUSHING THE ODDS!"); + } + else if (missionCount < 25) + { + UI.Output("FRESH OUT OF TRAINING, EH?"); + } + } + + /// + /// Attempt mission. + /// + /// Number of missions previously flown. Higher mission counts will yield a higher probability of success. + private void AttemptMission(int missionCount) + { + if (missionCount < RandomInteger(0, MaxMissionCount)) + { + MissedTarget(); + } + else + { + MissionSucceeded(); + } + } + + /// + /// Display message indicating that target was missed. Choose enemy artillery and perform a counterattack. + /// + private void MissedTarget() + { + UI.Output("MISSED TARGET BY " + (2 + RandomInteger(0, 30)) + " MILES!"); + UI.Output("NOW YOU'RE REALLY IN FOR IT !!"); + + // Choose enemy and counterattack. + EnemyArtillery enemyArtillery = ChooseEnemyArtillery(); + + if (enemyArtillery == Missiles) + { + EnemyCounterattack(enemyArtillery, hitRatePercent: 0); + } + else + { + int hitRatePercent = EnemyHitRatePercentFromUI(); + if (hitRatePercent < MinEnemyHitRatePercent) + { + UI.Output("YOU LIE, BUT YOU'LL PAY..."); + MissionFailed(); + } + else + { + EnemyCounterattack(enemyArtillery, hitRatePercent); + } + } + } + + /// + /// Choose enemy artillery from UI. + /// + /// Artillery chosen. + private EnemyArtillery ChooseEnemyArtillery() + { + EnemyArtillery[] artilleries = new EnemyArtillery[] { Guns, Missiles, Both }; + string[] artilleryNames = artilleries.Select(a => a.Name).ToArray(); + int index = UI.Choose("DOES THE ENEMY HAVE", artilleryNames); + return artilleries[index]; + } + + /// + /// Minimum allowed hit rate percent. + /// + private const int MinEnemyHitRatePercent = 10; + + /// + /// Maximum allowed hit rate percent. + /// + private const int MaxEnemyHitRatePercent = 50; + + /// + /// Get the enemy hit rate percent from UI. Value must be between zero and . + /// If value is less than , mission fails automatically because the user is + /// assumed to be untruthful. + /// + /// Enemy hit rate percent from UI. + private int EnemyHitRatePercentFromUI() + { + UI.Output($"WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS ({MinEnemyHitRatePercent} TO {MaxEnemyHitRatePercent})"); + + bool resultIsValid; + int result; + do + { + result = UI.InputInteger(); + // Let them enter a number below the stated minimum, as they will be caught and punished. + if (0 <= result && result <= MaxEnemyHitRatePercent) + { + resultIsValid = true; + } + else + { + resultIsValid = false; + UI.Output($"NUMBER MUST BE FROM {MinEnemyHitRatePercent} TO {MaxEnemyHitRatePercent}"); + } + } + while (!resultIsValid); + + return result; + } +} diff --git a/12_Bombs_Away/csharp/BombsAwayGame/Side.cs b/12_Bombs_Away/csharp/BombsAwayGame/Side.cs new file mode 100644 index 00000000..7e643971 --- /dev/null +++ b/12_Bombs_Away/csharp/BombsAwayGame/Side.cs @@ -0,0 +1,97 @@ +namespace BombsAwayGame; + +/// +/// Represents a protagonist in the game. +/// +internal abstract class Side +{ + /// + /// Create instance using the given UI. + /// + /// UI to use. + public Side(IUserInterface ui) + { + UI = ui; + } + + /// + /// Play this side. + /// + public abstract void Play(); + + /// + /// User interface supplied to ctor. + /// + protected IUserInterface UI { get; } + + /// + /// Random-number generator for this play-through. + /// + private readonly Random _random = new(); + + /// + /// Gets a random floating-point number greater than or equal to zero, and less than one. + /// + /// Random floating-point number greater than or equal to zero, and less than one. + protected double RandomFrac() => _random.NextDouble(); + + /// + /// Gets a random integer in a range. + /// + /// The inclusive lower bound of the number returned. + /// The exclusive upper bound of the number returned. + /// Random integer in a range. + protected int RandomInteger(int minValue, int maxValue) => _random.Next(minValue: minValue, maxValue: maxValue); + + /// + /// Display messages indicating the mission succeeded. + /// + protected void MissionSucceeded() + { + UI.Output("DIRECT HIT!!!! " + RandomInteger(0, 100) + " KILLED."); + UI.Output("MISSION SUCCESSFUL."); + } + + /// + /// Gets the Guns type of enemy artillery. + /// + protected EnemyArtillery Guns { get; } = new("GUNS", 0); + + /// + /// Gets the Missiles type of enemy artillery. + /// + protected EnemyArtillery Missiles { get; } = new("MISSILES", 35); + + /// + /// Gets the Both Guns and Missiles type of enemy artillery. + /// + protected EnemyArtillery Both { get; } = new("BOTH", 35); + + /// + /// Perform enemy counterattack using the given artillery and hit rate percent. + /// + /// Enemy artillery to use. + /// Hit rate percent for enemy. + protected void EnemyCounterattack(EnemyArtillery artillery, int hitRatePercent) + { + if (hitRatePercent + artillery.Accuracy > RandomInteger(0, 100)) + { + MissionFailed(); + } + else + { + UI.Output("YOU MADE IT THROUGH TREMENDOUS FLAK!!"); + } + } + + /// + /// Display messages indicating the mission failed. + /// + protected void MissionFailed() + { + UI.Output("* * * * BOOM * * * *"); + UI.Output("YOU HAVE BEEN SHOT DOWN....."); + UI.Output("DEARLY BELOVED, WE ARE GATHERED HERE TODAY TO PAY OUR"); + UI.Output("LAST TRIBUTE..."); + } +} From 26492ed257d5ee5b1352f296015b705dfcd7ad49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= Date: Mon, 3 Jan 2022 19:39:53 +0000 Subject: [PATCH 521/749] Add Perl version of 93_23Matches --- 93_23_Matches/perl/23matches.pl | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 93_23_Matches/perl/23matches.pl diff --git a/93_23_Matches/perl/23matches.pl b/93_23_Matches/perl/23matches.pl new file mode 100644 index 00000000..c575d9cb --- /dev/null +++ b/93_23_Matches/perl/23matches.pl @@ -0,0 +1,86 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +print ' ' x 31 . "23 MATCHES\n"; +print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; + +print " THIS IS A GAME CALLED '23 MATCHES'.\n\n"; + +print "WHEN IT IS YOUR TURN, YOU MAY TAKE ONE, TWO, OR THREE\n"; +print "MATCHES. THE OBJECT OF THE GAME IS NOT TO HAVE TO TAKE\n"; +print "THE LAST MATCH.\n\n"; + +print "LET'S FLIP A COIN TO SEE WHO GOES FIRST.\n"; +print "IF IT COMES UP HEADS, I WILL WIN THE TOSS.\n\n"; + +my $N = 23; +my $Q = int( 2 * rand(5) ); + +if ( $Q == 1 ) { + print "HEADS! I WIN! HA! HA!\n"; + print "PREPARE TO LOSE, MEATBALL-NOSE!!\n\n"; + + print "I TAKE 2 MATCHES\n"; + $N -= 2; + + print "THE NUMBER OF MATCHES IS NOW $N\n\n"; + + print "YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES.\n"; +} +else { + print "TAILS! YOU GO FIRST.\n\n"; +} + +print "HOW MANY DO YOU WISH TO REMOVE?\n"; + +INPUT: +{ + chomp( my $K = ); + + if ( $K > 3 or $K <= 0 ) { + print "VERY FUNNY! DUMMY!\n"; + print "DO YOU WANT TO PLAY OR GOOF AROUND?\n"; + print "NOW, HOW MANY MATCHES DO YOU WANT?\n"; + redo INPUT; + } + + $N -= $K; + + print "THERE ARE NOW $N MATCHES REMAINING.\n"; + + my $Z; + + if ( $N <= 1 ) { + print "YOU WON, FLOPPY EARS!\n"; + print "THINK YOU'RE PRETTY SMART!\n"; + print "LET'S PLAY AGAIN AND I'LL BLOW YOUR SHOES OFF!!\n"; + exit; + } + elsif ( $N > 4 ) { + $Z = 4 - $K; + } + else { + $Z = $N - 1; + } + + print "MY TURN! I REMOVE $Z MATCHES\n"; + + $N -= $Z; + + if ( $N <= 1 ) { + print "\nYOU POOR BOOB! YOU TOOK THE LAST MATCH! I GOTCHA!!\n"; + print "HA! HA! I BEAT YOU!!!\n\n"; + + print "GOOD BYE LOSER!\n"; + } + else { + print "THE NUMBER OF MATCHES IS NOW $N\n\n"; + + print "YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES.\n"; + print "HOW MANY DO YOU WISH TO REMOVE?\n"; + redo INPUT; + } +} From d77d3ee168913e7cce342c2e3bd9c778c546eb1b Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Mon, 3 Jan 2022 15:14:45 -0500 Subject: [PATCH 522/749] Port 03_Animal to Perl. Replaed array-based simulation of binary tree with hash-based simulation of binary tree. --- 03_Animal/perl/animal.pl | 223 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100755 03_Animal/perl/animal.pl diff --git a/03_Animal/perl/animal.pl b/03_Animal/perl/animal.pl new file mode 100755 index 00000000..a7c8bf9e --- /dev/null +++ b/03_Animal/perl/animal.pl @@ -0,0 +1,223 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +# The Perl ref() built-in returns 'HASH' for a hash reference. But we +# make it a manifest constant just to avoid typos. +use constant REF_HASH => ref {}; + +print <<'EOD'; + ANIMAL + Creative Computing Morristown, New Jersey + + + +Play 'Guess the Animal' +Think of an animal and the computer will try to guess it. + +EOD + +# We keep the accumulated data in a tree structure, initialized here. As +# we accumulate animals, we replace the 'yes' or 'no' keys with new hash +# references. +my $database = { + question => 'Does it swim', # Initial question + yes => 'fish', # Result of answering 'y' + no => 'bird', # Result of answering 'n' +}; + +while ( 1 ) { + + my $resp = get_input( + 'Are you thinking of an an animal? [y/n/list]: ' + ); + + if ( $resp =~ m/ \A y /smxi ) { + # If we got an answer beginning with 'y', walk the database + walk_tree( $database ); + } elsif ( $resp =~ m/ \A list \z /smxi ) { + # If we got 'list', list the currently-known animals. + say ''; + say 'Animals I already know are:'; + say " $_" for sort( list_animals( $database ) ); + } +} + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'animal' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +# Recurse through the database, returning the names of all animals in +# it, in an undefined order. +sub list_animals { + my ( $node ) = @ARG; + return $node unless REF_HASH eq ref $node; + return( map { list_animals( $node->{$_} ) } qw{ yes no } ); +} + +# Find or create the desired animal. +# Ask the question stored in the node given in its argument. If the key +# selected by the answer ('yes' or 'no') is another node, recurse. If it +# is an animal name, confirm it, or add a new animal as appropriate. +sub walk_tree { + my ( $node ) = @ARG; + + # Ask the question associated with this node. Turn the true/false + # response into 'yes' or 'no', since those are the names of the + # respective keys. + my $resp = get_yes_no ( $node->{question} ) ? 'yes' : 'no'; + + # Chose the datum for the response. + my $choice = $node->{ $resp }; + + # If the datum is a hash reference + if ( REF_HASH eq ref $choice ) { + + # Recurse into it + walk_tree( $choice ); + + # Otherwise it is an actual animal (i.e. terminal node). Check it. + } else { + + # If this is not the animal the player was thinking of + unless ( get_yes_no( "Is it a $choice" ) ) { + + # Find out what animal the player was thinking of + my $animal = lc get_input( + 'The animal you were thinking of was a ', + ); + + # Get a yes/no question that distinguishes the animal the + # player was thinking of from the animal we found in the + # tree. + say 'Please type in a question that would distinguish a'; + my $question = get_input( "$animal from a $choice: " ); + + # Find out whether the new animal is selected by 'yes' or + # 'no'. If 'no', swap the original animal with the new one + # for convenience. + ( $choice, $animal ) = ( $animal, $choice ) if get_yes_no( + "For a $animal the answer would be", + ); + + # Replace the animal we originally found by a new node + # giving the original animal, the new animal, and the + # question that distinguishes them. + $node->{ $resp } = { + question => $question, + no => $animal, + yes => $choice, + }; + } + + # Find out if the player wants to play again. If not, exit. If + # so, just return. + say ''; + exit unless get_yes_no( 'Why not try another animal' ); + return; + } +} + +__END__ + +=head1 TITLE + +animal.pl - Play the game 'animal' from Basic Computer Games + +=head1 SYNOPSIS + + animal.pl + +=head1 DETAILS + +This Perl script is a port of C, which is the 3ed entry in Basic +Computer Games. + +The original BASIC was greatly complicated by the need to emulate a +binary tree with an array. The implementation using hashes as nodes in +an actual binary tree is much simpler. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From ec189883f96a93d15355dc0c34c47fa9719859e9 Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Mon, 3 Jan 2022 15:59:14 -0500 Subject: [PATCH 523/749] Perl version of Chomp --- 26_Chomp/perl/chomp.pl | 173 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 26_Chomp/perl/chomp.pl diff --git a/26_Chomp/perl/chomp.pl b/26_Chomp/perl/chomp.pl new file mode 100644 index 00000000..34727626 --- /dev/null +++ b/26_Chomp/perl/chomp.pl @@ -0,0 +1,173 @@ +#!/usr/bin/perl + + +my @cookie; + +&main; + +sub main { + my $answer = 1; + until ($answer == 0) { + $answer=&game_play; + } +} + +sub game_play { + + # the initial game set up + &print_intro; + my ($players,$rows,$cols) = &get_user_info; + &create_gameboard($rows,$cols); + &print_gameboard($rows,$cols); + my $game_over = 0; + my $player = 0; + + # continuous loop until the poison pill is swallowed + until ($game_over == 1) { + if ($player > ($players-1)) { #checks to make sure we're just looping thru valid players + $player = 0; + } + $player++; + my ($user_row,$user_col) = &get_player_row_col($player,$rows,$cols); + if ($cookie[$user_row][$user_col] == -1) { + print "YOU LOSE, PLAYER $player\n\n"; + print "AGAIN (1=YES, 0=NO!)\n"; + my $answer=; + chomp($answer); + return($answer); + } + &modify_gameboard($rows,$cols,$user_row,$user_col); + &print_gameboard($rows,$cols); + } + +} + +sub get_player_row_col { + my ($player,$row,$col) = @_; + my @coords; + my $validity="invalid"; + # Getting coordinates from user + until ($validity eq "valid") { + print "PLAYER $player COORDINATES OF CHOMP (ROW,COLUMN)\n"; + my $input=; + chomp($input); + @coords = split/,/,$input; + + #verifying coordinates are valid + if ($coords[0] < 1 || $coords[0] > $row || $coords[1] < 1 || $coords[1] > $col || $cookie[$coords[0]][$coords[1]] == 0) { + print "NO FAIR. YOU'RE TRYING TO CHOMP ON EMPTY SPACE!\n"; + } + else { + $validity="valid"; + } + } + return($coords[0],$coords[1]); +} + +sub get_user_info { + my ($players,$rows,$cols)=0; + until ($players > 0) { + print "HOW MANY PLAYERS\n"; + $players=; + chomp($players); + } + until ($rows > 0 && $rows < 10) { + print "HOW MANY ROWS\n"; + $rows=; + chomp($rows); + if ($rows > 9) { + print "TOO MANY ROWS (9 IS MAXIMUM). NOW, "; + } + } + until ($cols > 0 && $cols < 10) { + print "HOW MANY COLUMNS\n"; + $cols=; + chomp($cols); + if ($cols > 9) { + print "TOO MANY COLUMNS (9 IS MAXIMUM). NOW, "; + } + } + return($players,$rows,$cols); +} + +sub print_intro{ + print ' ' x 33 . "CHOMP\n"; + print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n"; + print "THIS IS THE GAME OF CHOMP (SCIENTIFIC AMERICAN, JAN 1973)\n"; + print "DO YOU WANT THE RULES (1=YES, 0=NO!)"; + my $answer = ; + chomp($answer); + if ($answer == 0) { + return; + } + else { + print "CHOMP IS FOR 1 OR MORE PLAYERS (HUMANS ONLY).\n\n"; + print "HERE'S HOW A BOARD LOOKS (THIS ONE IS 5 BY 7):\n"; + &create_gameboard(5,7); + &print_gameboard(5,7); + print "THE BOARD IS A BIG COOKIE - R ROWS HIGH AND C COLUMNS\n"; + print "WIDE. YOU INPUT R AND C AT THE START. IN THE UPPER LEFT\n"; + print "CORNER OF THE COOKIE IS A POISON SQUARE (P). THE ONE WHO\n"; + print "CHOMPS THE POISON SQUARE LOSES. TO TAKE A CHOMP, TYPE THE\n"; + print "ROW AND COLUMN OF ONE OF THE SQUARES ON THE COOKIE.\n"; + print "ALL OF THE SQUARES BELOW AND TO THE RIGHT OF THAT SQUARE\n"; + print "(INCLUDING THAT SQUARE, TOO) DISAPPEAR -- CHOMP!!\n"; + print "NO FAIR CHOMPING SQUARES THAT HAVE ALREADY BEEN CHOMPED,\n"; + print "OR THAT ARE OUTSIDE THE ORIGINAL DIMENSIONS OF THE COOKIE.\n\n"; + print "HERE WE GO...\n"; + undef @cookie; + } +} + +#initial creation of the gameboard +sub create_gameboard { + my $rows = shift; + my $cols = shift; + foreach my $row (1..($rows)) { + foreach my $col (1..($cols)) { + $cookie[$row][$col]=1; + } + } + $cookie[1][1]=-1; +} + +#modification of the gameboard based on the input from the player +sub modify_gameboard { + my ($rows,$cols,$user_row,$user_col) = @_; + foreach my $row ($user_row..($rows)) { + foreach my $col ($user_col..($cols)) { + $cookie[$row][$col]=" "; + } + } +} + +#prints the gameboard based on the current state of the gameboard +sub print_gameboard { + my ($rows,$cols) = @_; + foreach my $col (1..$cols) { + if ($col == $cols) { + print "$col\n"; + } + elsif ($col == 1) { + print "\t $col "; + } + else { + print "$col "; + } + } + foreach my $row (1..($rows)) { + print "\t$row "; + foreach my $col (1..($cols)) { + if ($cookie[$row][$col] == 1) { + print "* "; + } + if ($cookie[$row][$col] == 0) { + print " "; + } + if ($cookie[$row][$col] == -1) { + print "P "; + } + } + print "\n"; + } +} From d10e80e2c0e0eefca5cd3ecfa368994d5a7f9271 Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Mon, 3 Jan 2022 17:12:34 -0500 Subject: [PATCH 524/749] Ported 73_Reverse to Perl. In a language with list assignments, array slices, and a reverse() built-in, the reversal can be done in one statement. --- 73_Reverse/perl/reverse.pl | 234 +++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100755 73_Reverse/perl/reverse.pl diff --git a/73_Reverse/perl/reverse.pl b/73_Reverse/perl/reverse.pl new file mode 100755 index 00000000..94ef40e6 --- /dev/null +++ b/73_Reverse/perl/reverse.pl @@ -0,0 +1,234 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use List::Util qw{ shuffle }; # Shuffle an array. +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +# Manifest constant for size of list. +use constant NUMBER_OF_NUMBERS => 9; + +print <<'EOD'; + REVERSE + Creative Computing Morristown, New Jersey + + + +Reverse -- a game of skill + +EOD + +# Display the rules if desired. There is no straightforward way to +# interpolate a manifest constant into a string, but @{[ ... ]} will +# interpolate any expression. +print <<"EOD" if get_yes_no( 'Do you want the rules' ); + +This is the game of 'Reverse'. To win, all you have +to do is arrange a list of numbers (1 through @{[ NUMBER_OF_NUMBERS ]}) +in numerical order from left to right. To move, you +tell me how many numbers (counting from the left) to +reverse. For example, if the current list is: + +2 3 4 5 1 6 7 8 9 + +and you reverse 4, the result will be: + +5 4 3 2 1 6 7 8 9 + +Now if you reverse 5, you win! + +1 2 3 4 5 6 7 8 9 + +No doubt you will like this game, but +if you want to quit, reverse 0 (zero). + +EOD + +while ( 1 ) { # Iterate until something interrupts us. + + # Populate the list with the integers from 1, shuffled. If we + # accidentally generate a winning list, just redo the loop. + my @list = shuffle( 1 .. NUMBER_OF_NUMBERS ); + redo if is_win( \@list ); + + print <<"EOD"; + +Here we go ... The list is: +EOD + + my $moves = 0; # Move counter + + while ( 1 ) { # Iterate until something interrupts us. + print <<"EOD"; + +@list + +EOD + + # Read the number of values to reverse. Zero is special-cased to + # take us out of this loop. + last unless my $max_index = get_input( + 'How many shall I reverse (0 to quit)? ', + sub { + return m/ \A [0-9]+ \z /smx && + $ARG <= NUMBER_OF_NUMBERS; + }, + "Oops! Too many! I can reverse at most " . + NUMBER_OF_NUMBERS, + ); + + --$max_index; # Convert number to reverse to upper index + + # Use a Perl array slice and the reverse() built-in to reverse + # the beginning of the list. + @list[ 0 .. $max_index ] = reverse @list[ 0 .. $max_index ]; + + $moves++; # Count a move + + # If we have not won, iterate again. + next unless is_win( \@list ); + + # Announce the win, and drop out of the loop. + print <<"EOD"; + +You won it in $moves moves!!! +EOD + last; + } + + # Drop out of this loop unless the player wants to play again. + say ''; + last unless get_yes_no( 'Try again' ); +} + +print <<'EOD'; + +O.K. Hope you had fun!! +EOD + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +# Determine if a given list represents a win. The argument is a +# reference to the array containing the list. We return a true value for +# a win, or a false value otherwise. +sub is_win { + my ( $list ) = @_; + my $expect = 1; # We expect the first element to be 1; + + # Iterate over the array. + foreach my $element ( @{ $list } ) { + + # If the element does not have the expected value, we return + # false. We post-increment the expected value en passant. + $element == $expect++ + or return 0; + } + + # All elements had the expected value, so we won. Return a true + # value. + return 1; +} + +__END__ + +=head1 TITLE + +reverse.pl - Play the game 'reverse' from Basic Computer Games + +=head1 SYNOPSIS + + reverse.pl + +=head1 DETAILS + +This Perl script is a port of C, which is the 73rd entry in +Basic Computer Games. + +The cool thing about this port is the fact that, in a language with +array slices, list assignments, and a C built-in, the +reversal is a single assignment statement. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From d32c56800a459936e1d8703c7bd3dbb38cfc2379 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 4 Jan 2022 10:13:48 +1100 Subject: [PATCH 525/749] initial kotlin implementation of "King" --- 53_King/king_variable_update.bas | 306 ++++++++++++++++ 53_King/kotlin/King.kt | 586 +++++++++++++++++++++++++++++++ 2 files changed, 892 insertions(+) create mode 100644 53_King/king_variable_update.bas create mode 100644 53_King/kotlin/King.kt diff --git a/53_King/king_variable_update.bas b/53_King/king_variable_update.bas new file mode 100644 index 00000000..c88edf93 --- /dev/null +++ b/53_King/king_variable_update.bas @@ -0,0 +1,306 @@ +1 PRINT TAB(34);"KING" +2 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" +3 PRINT:PRINT:PRINT +4 PRINT "DO YOU WANT INSTRUCTIONS"; +5 INPUT Z$ +6 YEARS_REQUIRED=8 +10 IF LEFT$(Z$,1)="N" THEN 47 + 11 IF Z$="AGAIN" THEN 1960 + 12 PRINT:PRINT:PRINT + 20 PRINT "CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS" + 22 PRINT "DETINU, RALLODS SMALL COMMUNIST ISLAND 30 BY 70 MILES LONG. YOUR" + 24 PRINT "JOB IS TO DECIDE UPON THE CONTRY'S BUDGET AND DISTRIBUTE" + 26 PRINT "MONEY TO YOUR COUNTRYMEN FROM THE COMMUNAL TREASURY." + 28 PRINT "THE MONEY SYSTEM IS RALLODS, AND EACH PERSON NEEDS 100" + 30 PRINT "RALLODS PER YEAR TO SURVIVE. YOUR COUNTRY'S INCOME COMES" + 32 PRINT "FROM FARM PRODUCE AND TOURISTS VISITING YOUR MAGNIFICENT" + 34 PRINT "FORESTS, HUNTING, FISHING, ETC. HALF YOUR LAND IS FARM LAND" + 36 PRINT "WHICH ALSO HAS AN EXCELLENT MINERAL CONTENT AND MAY BE SOLD" + 38 PRINT "TO FOREIGN INDUSTRY (STRIP MINING) WHO IMPORT AND SUPPORT" + 40 PRINT "THEIR OWN WORKERS. CROPS COST BETWEEN 10 AND 15 RALLODS PER" + 42 PRINT "SQUARE MILE TO PLANT." + 44 PRINT "YOUR GOAL IS TO COMPLETE YOUR";YEARS_REQUIRED;"YEAR TERM OF OFFICE." + 46 PRINT "GOOD LUCK!" + +47 PRINT + +50 RALLODS=INT(60000+(1000*RND(1))-(1000*RND(1))) +55 COUNTRYMEN=INT(500+(10*RND(1))-(10*RND(1))) +65 LANDAREA=2000 +100 LANDPRICE=INT(10*RND(1)+95) +102 PRINT +105 PRINT "YOU NOW HAVE ";RALLODS;" RALLODS IN THE TREASURY." +110 PRINT INT(COUNTRYMEN);:PRINT "COUNTRYMEN, "; +115 COST_TO_PLANT=INT(((RND(1)/2)*10+10)) +120 IF FOREIGN_WORKERS=0 THEN 140 +130 PRINT INT(FOREIGN_WORKERS);"FOREIGN WORKERS, "; +140 PRINT "AND";INT(LANDAREA);"SQ. MILES OF LAND." +150 PRINT "THIS YEAR INDUSTRY WILL BUY LAND FOR";LANDPRICE; +152 PRINT "RALLODS PER SQUARE MILE." +155 PRINT "LAND CURRENTLY COSTS";COST_TO_PLANT;"RALLODS PER SQUARE MILE TO PLANT." +162 PRINT + +200 PRINT "HOW MANY SQUARE MILES DO YOU WISH TO SELL TO INDUSTRY"; +210 INPUT SELL_TO_INDUSTRY +215 IF SELL_TO_INDUSTRY<0 THEN 200 +220 IF SELL_TO_INDUSTRY<=LANDAREA-1000 THEN 300 +230 PRINT "*** THINK AGAIN. YOU ONLY HAVE";LANDAREA-1000;"SQUARE MILES OF FARM LAND." + +240 IF EXPLANATION_GIVEN THEN 200 + 250 PRINT:PRINT "(FOREIGN INDUSTRY WILL ONLY BUY FARM LAND BECAUSE" + 260 PRINT "FOREST LAND IS UNECONOMICAL TO STRIP MINE DUE TO TREES," + 270 PRINT "THICKER TOP SOIL, ETC.)" + 280 EXPLANATION_GIVEN=TRUE +299 GOTO 200 + +300 LANDAREA=INT(LANDAREA-SELL_TO_INDUSTRY) +310 RALLODS=INT(RALLODS+(SELL_TO_INDUSTRY*LANDPRICE)) +320 PRINT "HOW MANY RALLODS WILL YOU DISTRIBUTE AMONG YOUR COUNTRYMEN"; +340 INPUT WELFARE +342 IF WELFARE<0 THEN 320 +350 IF WELFARE0 THEN 1002 +602 IF WELFARE<>0 THEN 1002 +604 IF PLANTING_AREA<>0 THEN 1002 +606 IF MONEY_SPENT_ON_POLLUTION_CONTROL<>0 THEN 1002 + +609 PRINT +612 PRINT "GOODBYE." +614 PRINT "(IF YOU WISH TO CONTINUE THIS GAME AT A LATER DATE, ANSWER" +616 PRINT "'AGAIN' WHEN ASKED IF YOU WANT INSTRUCTIONS AT THE START" +617 PRINT "OF THE GAME)." +618 STOP + +1000 GOTO 600 + +1002 PRINT +1003 PRINT + +1010 RALLODS=INT(RALLODS-MONEY_SPENT_ON_POLLUTION_CONTROL) +1020 ORIGINAL_RALLODS=RALLODS + +1100 IF INT(WELFARE/100-COUNTRYMEN)>=0 THEN 1120 +1105 IF WELFARE/100<50 THEN 1700 +1110 PRINT INT(COUNTRYMEN-(WELFARE/100));"COUNTRYMEN DIED OF STARVATION" + +1120 POLLUTION_DEATHS=INT(RND(1)*(2000-LANDAREA)) +1122 IF MONEY_SPENT_ON_POLLUTION_CONTROL<25 THEN 1130 +1125 POLLUTION_DEATHS=INT(POLLUTION_DEATHS/(MONEY_SPENT_ON_POLLUTION_CONTROL/25)) + +1130 IF POLLUTION_DEATHS<=0 THEN 1150 +1140 PRINT POLLUTION_DEATHS;"COUNTRYMEN DIED OF CARBON-MONOXIDE AND DUST INHALATION" + +1150 IF INT((WELFARE/100)-COUNTRYMEN)<0 THEN 1170 +1160 IF POLLUTION_DEATHS>0 THEN 1180 +1165 GOTO 1200 + +1170 PRINT " YOU WERE FORCED TO SPEND";INT((POLLUTION_DEATHS+(COUNTRYMEN-(WELFARE/100)))*9); +1172 PRINT "RALLODS ON FUNERAL EXPENSES" +1174 DEATHS=INT(POLLUTION_DEATHS+(COUNTRYMEN-(WELFARE/100))) +1175 RALLODS=INT(RALLODS-((POLLUTION_DEATHS+(COUNTRYMEN-(WELFARE/100)))*9)) +1176 GOTO 1185 + +1180 PRINT " YOU WERE FORCED TO SPEND ";INT(POLLUTION_DEATHS*9);"RALLODS ON "; +1181 PRINT "FUNERAL EXPENSES." +1182 DEATHS=POLLUTION_DEATHS +1183 RALLODS=INT(RALLODS-(POLLUTION_DEATHS*9)) + +1185 IF RALLODS>=0 THEN 1194 +1187 PRINT " INSUFFICIENT RESERVES TO COVER COST - LAND WAS SOLD" +1189 LANDAREA=INT(LANDAREA+(RALLODS/LANDPRICE)) +1190 RALLODS=0 + +1194 COUNTRYMEN=INT(COUNTRYMEN-DEATHS) + +1200 IF SELL_TO_INDUSTRY=0 THEN 1250 +1220 NEW_FOREIGNERS=INT(SELL_TO_INDUSTRY+(RND(1)*10)-(RND(1)*20)) +1224 IF FOREIGN_WORKERS>0 THEN 1230 +1226 NEW_FOREIGNERS=NEW_FOREIGNERS+20 + +1230 PRINT NEW_FOREIGNERS;"WORKERS CAME TO THE COUNTRY AND"; + +1250 IMMIGRATION=INT(((WELFARE/100-COUNTRYMEN)/10)+(MONEY_SPENT_ON_POLLUTION_CONTROL/25)-((2000-LANDAREA)/50)-(POLLUTION_DEATHS/2)) +1255 PRINT ABS(IMMIGRATION);"COUNTRYMEN "; +1260 IF IMMIGRATION<0 THEN 1275 +1265 PRINT "CAME TO"; +1270 GOTO 1280 +1275 PRINT "LEFT"; +1280 PRINT " THE ISLAND." +1290 COUNTRYMEN=INT(COUNTRYMEN+IMMIGRATION) + + +1292 FOREIGN_WORKERS=INT(FOREIGN_WORKERS+NEW_FOREIGNERS) + +1305 CROP_LOSS=INT(((2000-LANDAREA)*((RND(1)+1.5)/2))) +1310 IF FOREIGN_WORKERS=0 THEN 1324 +1320 PRINT "OF ";INT(PLANTING_AREA);"SQ. MILES PLANTED,"; +1324 IF PLANTING_AREA>CROP_LOSS THEN 1330 +1326 CROP_LOSS=PLANTING_AREA +1330 PRINT " YOU HARVESTED ";INT(PLANTING_AREA-CROP_LOSS);"SQ. MILES OF CROPS." +1340 IF CROP_LOSS=0 THEN 1370 +1344 IF T1>=2 THEN 1370 +1350 PRINT " (DUE TO "; +1355 IF T1=0 THEN 1365 +1360 PRINT "INCREASED "; +1365 PRINT "AIR AND WATER POLLUTION FROM FOREIGN INDUSTRY.)" +1370 AGRICULTURAL_INCOME=INT((PLANTING_AREA-CROP_LOSS)*(LANDPRICE/2)) +1380 PRINT "MAKING";INT(AGRICULTURAL_INCOME);"RALLODS." +1390 RALLODS=INT(RALLODS+AGRICULTURAL_INCOME) + +REM I think tourism calculations are actually wrong in the original code! + +1400 V1=INT(((COUNTRYMEN-IMMIGRATION)*22)+(RND(1)*500)) +1405 V2=INT((2000-LANDAREA)*15) +1410 PRINT " YOU MADE";ABS(INT(V1-V2));"RALLODS FROM TOURIST TRADE." +1420 IF V2=0 THEN 1450 +1425 IF V1-V2>=V3 THEN 1450 +1430 PRINT " DECREASE BECAUSE "; +1435 G1=10*RND(1) +1440 IF G1<=2 THEN 1460 +1442 IF G1<=4 THEN 1465 +1444 IF G1<=6 THEN 1470 +1446 IF G1<=8 THEN 1475 +1448 IF G1<=10 THEN 1480 +1450 V3=INT(RALLODS+V3) +1451 RALLODS=INT(RALLODS+V3) +1452 GOTO 1500 +1460 PRINT "FISH POPULATION HAS DWINDLED DUE TO WATER POLLUTION." +1462 GOTO 1450 +1465 PRINT "AIR POLLUTION IS KILLING GAME BIRD POPULATION." +1467 GOTO 1450 +1470 PRINT "MINERAL BATHS ARE BEING RUINED BY WATER POLLUTION." +1472 GOTO 1450 +1475 PRINT "UNPLEASANT SMOG IS DISCOURAGING SUN BATHERS." +1477 GOTO 1450 +1480 PRINT "HOTELS ARE LOOKING SHABBY DUE TO SMOG GRIT." +1482 GOTO 1450 +1500 IF DEATHS>200 THEN 1600 +1505 IF COUNTRYMEN<343 THEN 1700 +1510 IF (ORIGINAL_RALLODS/100)>5 THEN 1800 +1515 IF FOREIGN_WORKERS>COUNTRYMEN THEN 1550 +1520 IF YEARS_REQUIRED-1=X5 THEN 1900 +1545 GOTO 2000 +1550 PRINT +1552 PRINT +1560 PRINT "THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER" +1562 PRINT "OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND" +1564 PRINT "TAKEN OVER THE COUNTRY." +1570 IF RND(1)<=.5 THEN 1580 +1574 PRINT "YOU HAVE BEEN THROWN OUT OF OFFICE AND ARE NOW" +1576 PRINT "RESIDING IN PRISON." +1578 GOTO 1590 +1580 PRINT "YOU HAVE BEEN ASSASSINATED." +1590 PRINT +1592 PRINT +1596 STOP +1600 PRINT +1602 PRINT +1610 PRINT DEATHS;"COUNTRYMEN DIED IN ONE YEAR!!!!!" +1615 PRINT "DUE TO THIS EXTREME MISMANAGEMENT, YOU HAVE NOT ONLY" +1620 PRINT "BEEN IMPEACHED AND THROWN OUT OF OFFICE, BUT YOU" +1622 M6=INT(RND(1)*10) +1625 IF M6<=3 THEN 1670 +1630 IF M6<=6 THEN 1680 +1635 IF M6<=10 THEN 1690 +1670 PRINT "ALSO HAD YOUR LEFT EYE GOUGED OUT!" +1672 GOTO 1590 +1680 PRINT "HAVE ALSO GAINED A VERY BAD REPUTATION." +1682 GOTO 1590 +1690 PRINT "HAVE ALSO BEEN DECLARED NATIONAL FINK." +1692 GOTO 1590 + +1700 PRINT +1702 PRINT +1710 PRINT "OVER ONE THIRD OF THE POPULTATION HAS DIED SINCE YOU" +1715 PRINT "WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING)" +1720 PRINT "HATE YOUR GUTS." +1730 GOTO 1570 +1800 IF DEATHS-POLLUTION_DEATHS<2 THEN 1515 +1807 PRINT +1815 PRINT "MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID" +1820 PRINT "NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED" +1825 PRINT "OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE" +1830 PRINT "BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE." +1835 PRINT "THE CHOICE IS YOURS." +1840 PRINT "IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER" +1845 PRINT "BEFORE PROCEEDING." +1850 GOTO 1590 +1900 PRINT +1902 PRINT +1920 PRINT "CONGRATULATIONS!!!!!!!!!!!!!!!!!!" +1925 PRINT "YOU HAVE SUCCESFULLY COMPLETED YOUR";YEARS_REQUIRED;"YEAR TERM" +1930 PRINT "OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT" +1935 PRINT "NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD" +1940 PRINT "LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT" +1945 PRINT "PLAYS THIS GAME." +1950 GOTO 1590 + +1960 PRINT "HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED"; +1961 INPUT X5 +1962 IF X5<0 THEN 1590 +1963 IF X5<8 THEN 1969 +1965 PRINT " COME ON, YOUR TERM IN OFFICE IS ONLY";YEARS_REQUIRED;"YEARS." +1967 GOTO 1960 +1969 PRINT "HOW MUCH DID YOU HAVE IN THE TREASURY"; +1970 INPUT RALLODS +1971 IF RALLODS<0 THEN 1590 +1975 PRINT "HOW MANY COUNTRYMEN"; +1976 INPUT COUNTRYMEN +1977 IF COUNTRYMEN<0 THEN 1590 +1980 PRINT "HOW MANY WORKERS"; +1981 INPUT FOREIGN_WORKERS +1982 IF FOREIGN_WORKERS<0 THEN 1590 +1990 PRINT "HOW MANY SQUARE MILES OF LAND"; +1991 INPUT LANDAREA +1992 IF LANDAREA<0 THEN 1590 +1993 IF LANDAREA>2000 THEN 1996 +1994 IF LANDAREA>1000 THEN 100 +1996 PRINT " COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND" +1997 PRINT " AND 10,000 SQ. MILES OF FOREST LAND." +1998 GOTO 1990 + +2000 X5=X5+1 +2020 DEATHS=0 +2040 GOTO 100 +2046 END diff --git a/53_King/kotlin/King.kt b/53_King/kotlin/King.kt new file mode 100644 index 00000000..2200a9be --- /dev/null +++ b/53_King/kotlin/King.kt @@ -0,0 +1,586 @@ +import kotlin.math.abs +import kotlin.random.Random +import kotlin.system.exitProcess + +lateinit var gameState: GameState +const val INCLUDE_BUGS_FROM_ORIGINAL = false + +val rnd: Double get() = Random.nextDouble() +fun tab(i: Int) = " ".repeat(i) +class EndOfInputException : Throwable() + +fun main() { + header() + + print("DO YOU WANT INSTRUCTIONS? ") + readLine()?.apply { + gameState = if (startsWith("AGAIN")) loadOldGame() else GameState() + if (startsWith("Y")) instructions(gameState.yearsRequired) + } + ?: throw EndOfInputException() + + try { + with(gameState) { + while(currentYear < yearsRequired) { + recalculateLandCost() + displayStatus() + inputLandSale() + performLandSale() + inputWelfare() + performWelfare() + inputPlantingArea() + performPlanting() + inputPollutionControl() + if (zeroInput()) { + displayExitMessage() + exitProcess(0) + } + simulateOneYear() + currentYear ++ + } + } + win(gameState.yearsRequired) + } catch (e: GameEndingException) { + e.displayConsequences() + } +} + +private fun header() { + println("${tab(34)}KING") + println("${tab(14)}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + println() + println() + println() +} + +fun instructions(yearsRequired: Int) { + println(""" + + + CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS + DETINU, A SMALL COMMUNIST ISLAND 30 BY 70 MILES LONG. YOUR + JOB IS TO DECIDE UPON THE CONTRY'S BUDGET AND DISTRIBUTE + MONEY TO YOUR COUNTRYMEN FROM THE COMMUNAL TREASURY. + THE MONEY SYSTEM IS RALLODS, AND EACH PERSON NEEDS 100 + RALLODS PER YEAR TO SURVIVE. YOUR COUNTRY'S INCOME COMES + FROM FARM PRODUCE AND TOURISTS VISITING YOUR MAGNIFICENT + FORESTS, HUNTING, FISHING, ETC. HALF YOUR LAND IS FARM LAND + WHICH ALSO HAS AN EXCELLENT MINERAL CONTENT AND MAY BE SOLD + TO FOREIGN INDUSTRY (STRIP MINING) WHO IMPORT AND SUPPORT + THEIR OWN WORKERS. CROPS COST BETWEEN 10 AND 15 RALLODS PER + SQUARE MILE TO PLANT. + YOUR GOAL IS TO COMPLETE YOUR $yearsRequired YEAR TERM OF OFFICE. + GOOD LUCK! + """.trimIndent() + ) +} + +fun loadOldGame(): GameState = GameState().apply { + + do { + var retry = false + print("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED? ") + currentYear = numberInput() + + if (currentYear <= 0) + throw GameEndingException.DataEntryValidation() + + if (currentYear >= yearsRequired) { + println(" COME ON, YOUR TERM IN OFFICE IS ONLY $yearsRequired YEARS.") + retry = true + } + } while (retry) + + print("HOW MUCH DID YOU HAVE IN THE TREASURY? ") + rallods = numberInput() + if (rallods < 0) + throw GameEndingException.DataEntryValidation() + + print("HOW MANY WORKERS? ") + foreignWorkers = numberInput() + if (foreignWorkers < 0) + throw GameEndingException.DataEntryValidation() + + do { + var retry = false + print("HOW MANY SQUARE MILES OF LAND? ") + landArea = numberInput() + if (landArea<0) + throw GameEndingException.DataEntryValidation() + if (landArea > 2000 || landArea <= 1000) { + println(" COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND") + println(" AND 10,000 SQ. MILES OF FOREST LAND.") + retry = true + } + } while (retry) + +} + + +/** + * All exceptions which indicate the premature ending of the game, due + * to mismanagement, starvation, revolution, or mis-entry of a game state. + */ +sealed class GameEndingException : Throwable() { + abstract fun displayConsequences() + + fun finalFate() { + if (rnd < .5) { + println("YOU HAVE BEEN THROWN OUT OF OFFICE AND ARE NOW") + println("RESIDING IN PRISON.") + } else { + println("YOU HAVE BEEN ASSASSINATED.") + } + println() + println() + } + + class ExtremeMismanagement(private val death: Int) : GameEndingException() { + override fun displayConsequences() { + println() + println("$death COUNTRYMEN DIED IN ONE YEAR!!!!!") + println("DUE TO THIS EXTREME MISMANAGEMENT, YOU HAVE NOT ONLY") + println("BEEN IMPEACHED AND THROWN OUT OF OFFICE, BUT YOU") + println( + when ((rnd * 10.0).toInt()) { + in 0..3 -> "ALSO HAD YOUR LEFT EYE GOUGED OUT!" + in 4..6 -> "HAVE ALSO GAINED A VERY BAD REPUTATION." + else -> "HAVE ALSO BEEN DECLARED NATIONAL FINK." + } + ) + } + } + + class TooManyPeopleDead : GameEndingException() { + // The mistyping of "population" is in the original game. + override fun displayConsequences() { + println(""" + + + OVER ONE THIRD OF THE POPULTATION HAS DIED SINCE YOU + WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING) + HATE YOUR GUTS. + """.trimIndent()) + finalFate() + } + } + + class AntiImmigrationRevolution : GameEndingException() { + override fun displayConsequences() { + println(""" + THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER + OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND + TAKEN OVER THE COUNTRY. + """.trimIndent()) + finalFate() + } + } + + class StarvationWithFullTreasury : GameEndingException() { + override fun displayConsequences() { + println(""" + MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID + NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED + OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE + BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE. + THE CHOICE IS YOURS. + IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER + BEFORE PROCEEDING. + """.trimIndent()) + } + } + + class DataEntryValidation : GameEndingException() { + override fun displayConsequences() { + // no action + } + } + + +} + +fun win(yearsRequired: Int) { + // The misspelling of "successfully" is in the original code. + println(""" + + CONGRATULATIONS!!!!!!!!!!!!!!!!!! + YOU HAVE SUCCESFULLY COMPLETED YOUR $yearsRequired YEAR TERM + OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT + NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD + LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT + PLAYS THIS GAME. + + + """.trimIndent()) +} + +/** + * Record data, allow data input, and process the simulation for the game. + */ +class GameState(val yearsRequired: Int = 8) { + + /** + * The current year. Years start with zero, but we never + * output the current year. + */ + var currentYear = 0 + + /** + * Number of countrymen who have died of either pollution + * or starvation this year. + * It costs 9 rallods to bury a body. + * If you lose 200 people in one year, you will throw an {@see ExtremeMismanagementException} + */ + private var death = 0 + + /** + * Last year's tourist numbers. Use this to check whether the number + * of tourists has gone up or down each year. + */ + private var tourists = 0 + + private var moneySpentOnPollutionControl = 0 + private var moneySpentOnPlanting = 0 + + /** + * Current stock of rallods. + * Player starts with between 59000 and 61000 rallods, but + * mostly distributed close to 60000. 75% of the time it's + * between 59500 and 60500. + */ + var rallods = (60000.0 + (1000.0 * rnd) - (1000.0 * rnd)).toInt() + + /** + * Population. + * Initial population is about to 500. + * 75% of the time it's between 495 and 505. + */ + private var countrymen = (500 + (10 * rnd) - (10 * rnd)).toInt() + + /** + * Land sale price is evenly between 95 and 104 rallods per + * square mile. + * Price doesn't change over the course of the game. + */ + private var landPrice = (10 * rnd + 95).toInt() + + private var plantingArea = 0 + private var welfareThisYear = 0 + + /** + * Land area in square miles. Arable land is 1000 square miles less. + * Almost all calculations use landArea-1000 because only arable + * land is of any use. + */ + var landArea = 2000 + + /** + * Number of foreigners brought in by companies to whom you + * have sold land. If this gets higher than your population, there will + * be a revolution. + */ + var foreignWorkers = 0 + + /** + * Planting cost is recalculated every year. + */ + private var costToPlant: Int = 1 + + /** + * There is a brief explanation of land selling only + * on the first turn. + */ + private var explanationOfSellingGiven = false + + private var sellThisYear: Int = 0 + + /** + * Planting cost is recalculated every year + * at between 10 and 14 rallods. + */ + fun recalculateLandCost() { + costToPlant = ((rnd / 2.0) * 10.0 + 10.0).toInt() + } + + /** + * Show the current status of the world. + */ + fun displayStatus() { + println() + println("YOU NOW HAVE $rallods RALLODS IN THE TREASURY.") + print("$countrymen COUNTRYMEN, ") + if (foreignWorkers != 0) { + println("$foreignWorkers FOREIGN WORKERS, ") + } + println("AND $landArea SQ. MILES OF LAND.") + println("THIS YEAR INDUSTRY WILL BUY LAND FOR $landPrice") + println("RALLODS PER SQUARE MILE.") + println("LAND CURRENTLY COSTS $costToPlant RALLODS PER SQUARE MILE TO PLANT.") + } + + fun displayExitMessage() { + println() + println("GOODBYE.") + println("(IF YOU WISH TO CONTINUE THIS GAME AT A LATER DATE, ANSWER") + println("'AGAIN' WHEN ASKED IF YOU WANT INSTRUCTIONS AT THE START") + println("OF THE GAME).") + } + + fun performLandSale() { + landArea -= sellThisYear + rallods += sellThisYear * landPrice + } + + fun performPlanting() { + rallods -= moneySpentOnPlanting + } + + fun performWelfare() { + rallods -= welfareThisYear + } + + + /** + * Ask how much land we want to sell. Immediately get the money. + * The player has to do the calculations to work out how much + * money that makes. + */ + fun inputLandSale() { + do { + print("HOW MANY SQUARE MILES DO YOU WISH TO SELL TO INDUSTRY? ") + sellThisYear = numberInput() + if (sellThisYear > landArea - 1000) { + println("*** THINK AGAIN. YOU ONLY HAVE ${landArea - 1000} SQUARE MILES OF FARM LAND.") + if (!explanationOfSellingGiven) { + println() + println("(FOREIGN INDUSTRY WILL ONLY BUY FARM LAND BECAUSE") + println("FOREST LAND IS UNECONOMICAL TO STRIP MINE DUE TO TREES,") + println("THICKER TOP SOIL, ETC.)") + explanationOfSellingGiven = true + } + } + } while (sellThisYear <= 0 || sellThisYear > landArea - 1000) + } + + /** + * Input the value of `welfareThisYear` + */ + fun inputWelfare() { + do { + var retry = false + print("HOW MANY RALLODS WILL YOU DISTRIBUTE AMONG YOUR COUNTRYMEN? ") + welfareThisYear = numberInput() + + if (welfareThisYear > rallods) { + println(" THINK AGAIN. YOU'VE ONLY $rallods RALLODS IN THE TREASURY") + retry = true + } + + if (welfareThisYear <= 0) { + retry = true + } + } while (retry) + } + + /** + * Get the number of square miles to plant this year. + * Validate the response: + * Each countryman can only plant 2 square miles. + * You can only plant on arable land. + * You may not spend more on planting than your treasury. + */ + fun inputPlantingArea() { + if (welfareThisYear == rallods) { + plantingArea = 0 + } else { + do { + var retry = false + print("HOW MANY SQUARE MILES DO YOU WISH TO PLANT? ") + plantingArea = numberInput() + val moneySpentOnPlanting = plantingArea * costToPlant + + if (plantingArea < 0) { + retry = true + } else if (plantingArea >= 0 && plantingArea > countrymen * 2) { + println(" SORRY, BUT EACH COUNTRYMAN CAN ONLY PLANT 2 SQ. MILES.") + retry = true + } else if (plantingArea > landArea - 1000) { + println(" SORRY, BUT YOU'VE ONLY ${landArea - 1000} SQ. MILES OF FARM LAND.") + retry = true + } else if (moneySpentOnPlanting > rallods) { + println(" THINK AGAIN. YOU'VE ONLY $rallods RALLODS LEFT IN THE TREASURY.") + retry = true + } + } while (retry) + } + + } + + /** + * Enter amount for pollution control. + * Validate that this does not exceed treasury. + */ + fun inputPollutionControl() { + do { + var retry = false + print("HOW MANY RALLODS DO YOU WISH TO SPEND ON POLLUTION CONTROL? ") + moneySpentOnPollutionControl = numberInput() + + if (rallods < 0) { + retry = true + } else if (moneySpentOnPollutionControl > rallods) { + println(" THINK AGAIN. YOU ONLY HAVE $rallods RALLODS REMAINING.") + retry = true + } + + } while (retry) + } + + /** + * @return true if all data entered so far has been zero. + */ + fun zeroInput() = sellThisYear == 0 && + welfareThisYear == 0 && + plantingArea == 0 && + moneySpentOnPollutionControl == 0 + + fun simulateOneYear() { + rallods -= moneySpentOnPollutionControl + val rallodsAfterPollutionControl = rallods + + var starvationDeaths = 0 + if (welfareThisYear / 100.0 - countrymen < 0) { + + /* + Wait, WHAT? + If you spend less than 5000 rallods on welfare, no matter the current size of the + population, then you will end the game, with the game claiming that too many + people have died, without showing exactly how many have died? + + https://github.com/coding-horror/basic-computer-games/blob/main/53_King/king.bas#:~:text=1105%20IF%20I/100%3C50%20THEN%201700 + */ + if (welfareThisYear / 100.0 < 50) + throw GameEndingException.TooManyPeopleDead() + + starvationDeaths = (countrymen - (welfareThisYear / 100.0)).toInt() + println("$starvationDeaths COUNTRYMEN DIED OF STARVATION") + } + + var pollutionDeaths = (rnd * (2000 - landArea)).toInt() + if (moneySpentOnPollutionControl >= 25) { + pollutionDeaths = (pollutionDeaths / (moneySpentOnPollutionControl / 25.0)).toInt() + } + + if (pollutionDeaths > 0) { + println("$pollutionDeaths COUNTRYMEN DIED OF CARBON-MONOXIDE AND DUST INHALATION") + } + + death = pollutionDeaths + starvationDeaths + if (death > 0) { + println(" YOU WERE FORCED TO SPEND ${death * 9}") + println("RALLODS ON FUNERAL EXPENSES") + rallods -= death * 9 + } + + if (rallods < 0) { + println(" INSUFFICIENT RESERVES TO COVER COST - LAND WAS SOLD") + landArea += rallods / landPrice + rallods = 1 + } + + countrymen -= death + + val newForeigners = + if (sellThisYear > 0) { + (sellThisYear + rnd * 10.0 + rnd * 20.0).toInt() + (if (foreignWorkers <= 0) 20 else 0) + } else 0 + + val immigration = ( + (welfareThisYear / 100.0 - countrymen) / 10.0 + + moneySpentOnPollutionControl / 25.0 - + (2000 - landArea) / 50.0 - + pollutionDeaths / 2.0 + ).toInt() + println( + "$newForeigners WORKERS CAME TO THE COUNTRY AND" + + " ${abs(immigration)} COUNTRYMEN ${if (immigration < 0) "LEFT" else "CAME TO"}" + + " THE ISLAND." + ) + + countrymen += immigration + foreignWorkers += newForeigners + + var cropLoss = ((2000 - landArea) * (rnd + 1.5) / 2.0).toInt() + val cropLossWorse = false + if (foreignWorkers > 0) + print("OF $plantingArea SQ. MILES PLANTED,") + if (plantingArea <= cropLoss) + cropLoss = plantingArea + println(" YOU HARVESTED ${plantingArea - cropLoss} SQ. MILES OF CROPS.") + + if (cropLoss > 0) { + println(" (DUE TO ${if (cropLossWorse) "INCREASED " else ""}AIR AND WATER POLLUTION FROM FOREIGN INDUSTRY)") + } + + val agriculturalIncome = ((plantingArea - cropLoss) * landPrice / 2.0).toInt() + println("MAKING $agriculturalIncome RALLODS.") + rallods += agriculturalIncome + + val v1 = (((countrymen - immigration) * 22.0) + rnd * 500).toInt() + val v2 = ((2000.0 - landArea) * 15.0).toInt() + println(" YOU MADE ${abs(v1 - v2)} RALLODS FROM TOURIST TRADE.") + if (v2 != 0 && v1 - v2 < tourists) { + print(" DECREASE BECAUSE ") + println( + when ((10 * rnd).toInt()) { + in 0..2 -> "FISH POPULATION HAS DWINDLED DUE TO WATER POLLUTION." + in 3..4 -> "AIR POLLUTION IS KILLING GAME BIRD POPULATION." + in 5..6 -> "MINERAL BATHS ARE BEING RUINED BY WATER POLLUTION." + in 7..8 -> "UNPLEASANT SMOG IS DISCOURAGING SUN BATHERS." + else -> "HOTELS ARE LOOKING SHABBY DUE TO SMOG GRIT." + } + ) + } + + /* + The original code was incorrect. + If v3 starts at 0, for example, our money doubles, when we + have already been told that "YOU MADE ${abs(v1 - v2)} RALLODS + FROM TOURIST TRADE" + + See the original code + 1450 V3=INT(A+V3) + 1451 A=INT(A+V3) + + https://github.com/coding-horror/basic-computer-games/blob/main/53_King/king.bas#:~:text=1450%20V3%3DINT,INT(A%2BV3) + */ + if (INCLUDE_BUGS_FROM_ORIGINAL) { + tourists += rallods + } else { + tourists = abs(v1 - v2) + } + rallods += tourists + + if (death > 200) + throw GameEndingException.ExtremeMismanagement(death) + if (countrymen < 343) + throw GameEndingException.TooManyPeopleDead() + if (rallodsAfterPollutionControl / 100 > 5 && death - pollutionDeaths >= 2) + throw GameEndingException.StarvationWithFullTreasury() + if (foreignWorkers > countrymen) + throw GameEndingException.AntiImmigrationRevolution() + + } +} + + +private fun numberInput() = try { + readLine()?.toInt() ?: throw EndOfInputException() +} catch (r: NumberFormatException) { + 0 +} + + + + + From 2d994033c52c3ce42820d8d517863450fb9c0b5c Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 4 Jan 2022 10:14:09 +1100 Subject: [PATCH 526/749] update docs --- 53_King/kotlin/King.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/53_King/kotlin/King.kt b/53_King/kotlin/King.kt index 2200a9be..01558c99 100644 --- a/53_King/kotlin/King.kt +++ b/53_King/kotlin/King.kt @@ -359,7 +359,7 @@ class GameState(val yearsRequired: Int = 8) { explanationOfSellingGiven = true } } - } while (sellThisYear <= 0 || sellThisYear > landArea - 1000) + } while (sellThisYear < 0 || sellThisYear > landArea - 1000) } /** @@ -376,7 +376,7 @@ class GameState(val yearsRequired: Int = 8) { retry = true } - if (welfareThisYear <= 0) { + if (welfareThisYear < 0) { retry = true } } while (retry) @@ -495,6 +495,14 @@ class GameState(val yearsRequired: Int = 8) { (sellThisYear + rnd * 10.0 + rnd * 20.0).toInt() + (if (foreignWorkers <= 0) 20 else 0) } else 0 + /* + Immigration is calculated as + One for every thousand rallods more welfare than strictly required + minus one for every 10 starvation deaths + plus One for every 25 rallods spent on pollution control + plus one for every 50 square miles of arable land + minus one for every 2 pollution deaths + */ val immigration = ( (welfareThisYear / 100.0 - countrymen) / 10.0 + moneySpentOnPollutionControl / 25.0 - @@ -510,6 +518,12 @@ class GameState(val yearsRequired: Int = 8) { countrymen += immigration foreignWorkers += newForeigners + /* + Crop loss is between 75% and 125% of the land sold to industry, + due to the pollution that industry causes. + Money spent on pollution control reduces pollution deaths among + the population, but does not affect crop losses. + */ var cropLoss = ((2000 - landArea) * (rnd + 1.5) / 2.0).toInt() val cropLossWorse = false if (foreignWorkers > 0) From 4a2217f4be3b586a5cf23098b0ef0de0024d9e38 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 4 Jan 2022 10:41:42 +1100 Subject: [PATCH 527/749] Update README.md --- 53_King/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/53_King/README.md b/53_King/README.md index eb0ba8ab..206202f0 100644 --- a/53_King/README.md +++ b/53_King/README.md @@ -8,6 +8,28 @@ The money system is Rollods; each person needs 100 Rallods per year to survive. The author of this program is James A. Storer who wrote it while a student at Lexington High School. +## Bugs + +Implementers should be aware that this game contains at least one bug. + +On basic line 1450 + + 1450 V3=INT(A+V3) + 1451 A=INT(A+V3) + +...where A is the current treasury, and V3 is initially zero. +This would mean that the treasury doubles at the end of the first year, and all calculations for an increase in the treasury due to tourism are discarded. +Possibly, this made the game more playable, although impossible for the player to understand why the treasury was increasing? + +A quick fix for this bug in the original code would be + + 1450 V3=ABS(INT(V1-V2)) + 1451 A=INT(A+V3) + +...judging from the description of tourist income on basic line 1410 + + 1410 PRINT " YOU MADE";ABS(INT(V1-V2));"RALLODS FROM TOURIST TRADE." + --- As published in Basic Computer Games (1978): From 1e9c8008d162d294515ab4b454b29ee008f0c7a8 Mon Sep 17 00:00:00 2001 From: John Long Date: Mon, 3 Jan 2022 16:37:04 -0800 Subject: [PATCH 528/749] Add Kotlin for Synonym This is so much cleaner than the Java :). --- 85_Synonym/kotlin/README.md | 3 ++ 85_Synonym/kotlin/Synonym.kt | 71 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 85_Synonym/kotlin/README.md create mode 100644 85_Synonym/kotlin/Synonym.kt diff --git a/85_Synonym/kotlin/README.md b/85_Synonym/kotlin/README.md new file mode 100644 index 00000000..f43a5b70 --- /dev/null +++ b/85_Synonym/kotlin/README.md @@ -0,0 +1,3 @@ +Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) + +Conversion to [Kotlin](https://kotlinlang.org/) diff --git a/85_Synonym/kotlin/Synonym.kt b/85_Synonym/kotlin/Synonym.kt new file mode 100644 index 00000000..94066d03 --- /dev/null +++ b/85_Synonym/kotlin/Synonym.kt @@ -0,0 +1,71 @@ +/** + * Game of Synonym + * + * + * Based on the Basic game of Synonym here + * https://github.com/coding-horror/basic-computer-games/blob/main/85%20Synonym/synonym.bas + * + * + * 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. + */ + +fun main() { + println(introText) + synonyms.forEach { + // Inside with, "this" is the current synonym + with(it) { + do { + val answer = ask(" WHAT IS A SYNONYM OF $word ? ") + when { + answer == "HELP" -> + println("""**** A SYNONYM OF $word IS ${synonyms.random()}.""") + synonyms.contains(answer) -> + println(RANDOM_ANSWERS.random()) + else -> + println("TRY AGAIN.") + } + } while (!synonyms.contains(answer)) + } + } + println("SYNONYM DRILL COMPLETED.") +} + +val introText = """ +${tab(33)}SYNONYM +${tab(15)}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY +A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH +LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME + MEANING. +I CHOOSE A WORD -- YOU TYPE A SYNONYM. +IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP' +AND I WILL TELL YOU A SYNONYM. + + """ + +// prints a question and reads a string (and converts to uppercase) +private fun ask(text: String): String { + print(text) + return readln().uppercase() +} + +// Just like TAB in BASIC +private fun tab(spaces: Int): String = " ".repeat(spaces) + +val RANDOM_ANSWERS = arrayOf("RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK") + +// List of words and synonyms +private val synonyms = listOf( + SynonymList("FIRST", listOf("START", "BEGINNING", "ONSET", "INITIAL")), + SynonymList("SIMILAR", listOf("SAME", "LIKE", "RESEMBLING")), + SynonymList("MODEL", listOf("PATTERN", "PROTOTYPE", "STANDARD", "CRITERION")), + SynonymList("SMALL", listOf("INSIGNIFICANT", "LITTLE", "TINY", "MINUTE")), + SynonymList("STOP", listOf("HALT", "STAY", "ARREST", "CHECK", "STANDSTILL")), + SynonymList("HOUSE", listOf("DWELLING", "RESIDENCE", "DOMICILE", "LODGING", "HABITATION")), + SynonymList("PIT", listOf("HOLE", "HOLLOW", "WELL", "GULF", "CHASM", "ABYSS")), + SynonymList("PUSH", listOf("SHOVE", "THRUST", "PROD", "POKE", "BUTT", "PRESS")), + SynonymList("RED", listOf("ROUGE", "SCARLET", "CRIMSON", "FLAME", "RUBY")), + SynonymList("PAIN", listOf("SUFFERING", "HURT", "MISERY", "DISTRESS", "ACHE", "DISCOMFORT")) +) + +class SynonymList(val word: String, val synonyms: List) \ No newline at end of file From 8be28cd39a3ee3a642a047a8e303f70a24b1e5a4 Mon Sep 17 00:00:00 2001 From: John Long Date: Mon, 3 Jan 2022 16:45:26 -0800 Subject: [PATCH 529/749] A little cleaner implementation --- 85_Synonym/kotlin/Synonym.kt | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/85_Synonym/kotlin/Synonym.kt b/85_Synonym/kotlin/Synonym.kt index 94066d03..d2e68dc4 100644 --- a/85_Synonym/kotlin/Synonym.kt +++ b/85_Synonym/kotlin/Synonym.kt @@ -13,23 +13,25 @@ fun main() { println(introText) synonyms.forEach { - // Inside with, "this" is the current synonym - with(it) { - do { - val answer = ask(" WHAT IS A SYNONYM OF $word ? ") - when { - answer == "HELP" -> - println("""**** A SYNONYM OF $word IS ${synonyms.random()}.""") - synonyms.contains(answer) -> - println(RANDOM_ANSWERS.random()) - else -> - println("TRY AGAIN.") - } - } while (!synonyms.contains(answer)) - } + it.testUser() } println("SYNONYM DRILL COMPLETED.") } +// We could put this inside of SynonymList, but this keeps the core implementation +// right here at the top +private fun SynonymList.testUser() { + do { + val answer = ask(" WHAT IS A SYNONYM OF $word ? ") + when { + answer == "HELP" -> + println("""**** A SYNONYM OF $word IS ${synonyms.random()}.""") + synonyms.contains(answer) -> + println(RANDOM_ANSWERS.random()) + else -> + println("TRY AGAIN.") + } + } while (!synonyms.contains(answer)) +} val introText = """ ${tab(33)}SYNONYM From 1520a8f225ec55582cb4ff9070389fab56c9e1f5 Mon Sep 17 00:00:00 2001 From: John Long Date: Mon, 3 Jan 2022 16:47:47 -0800 Subject: [PATCH 530/749] Affirmation more accurate than Answer --- 85_Synonym/kotlin/Synonym.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/85_Synonym/kotlin/Synonym.kt b/85_Synonym/kotlin/Synonym.kt index d2e68dc4..dda96a82 100644 --- a/85_Synonym/kotlin/Synonym.kt +++ b/85_Synonym/kotlin/Synonym.kt @@ -26,7 +26,7 @@ private fun SynonymList.testUser() { answer == "HELP" -> println("""**** A SYNONYM OF $word IS ${synonyms.random()}.""") synonyms.contains(answer) -> - println(RANDOM_ANSWERS.random()) + println(RANDOM_AFFIRMATION.random()) else -> println("TRY AGAIN.") } @@ -54,7 +54,7 @@ private fun ask(text: String): String { // Just like TAB in BASIC private fun tab(spaces: Int): String = " ".repeat(spaces) -val RANDOM_ANSWERS = arrayOf("RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK") +val RANDOM_AFFIRMATION = arrayOf("RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK") // List of words and synonyms private val synonyms = listOf( From 916fa6f252188b1fa8a9bb605eda1d29569defb0 Mon Sep 17 00:00:00 2001 From: John Long Date: Mon, 3 Jan 2022 16:48:49 -0800 Subject: [PATCH 531/749] And now RANDOM is redundant --- 85_Synonym/kotlin/Synonym.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/85_Synonym/kotlin/Synonym.kt b/85_Synonym/kotlin/Synonym.kt index dda96a82..386a2525 100644 --- a/85_Synonym/kotlin/Synonym.kt +++ b/85_Synonym/kotlin/Synonym.kt @@ -26,7 +26,7 @@ private fun SynonymList.testUser() { answer == "HELP" -> println("""**** A SYNONYM OF $word IS ${synonyms.random()}.""") synonyms.contains(answer) -> - println(RANDOM_AFFIRMATION.random()) + println(AFFIRMATIONS.random()) else -> println("TRY AGAIN.") } @@ -54,7 +54,7 @@ private fun ask(text: String): String { // Just like TAB in BASIC private fun tab(spaces: Int): String = " ".repeat(spaces) -val RANDOM_AFFIRMATION = arrayOf("RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK") +val AFFIRMATIONS = arrayOf("RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK") // List of words and synonyms private val synonyms = listOf( From 2c1dea4de7cef0c0e8f6b0a3843b55396af0658f Mon Sep 17 00:00:00 2001 From: a2wd Date: Tue, 4 Jan 2022 01:57:36 +0100 Subject: [PATCH 532/749] Added bombardment in c# --- 11_Bombardment/csharp/Bombardment.cs | 183 +++++++++++++++++++++++ 11_Bombardment/csharp/Bombardment.csproj | 8 + 11_Bombardment/csharp/Program.cs | 13 ++ 3 files changed, 204 insertions(+) create mode 100644 11_Bombardment/csharp/Bombardment.cs create mode 100644 11_Bombardment/csharp/Bombardment.csproj create mode 100644 11_Bombardment/csharp/Program.cs diff --git a/11_Bombardment/csharp/Bombardment.cs b/11_Bombardment/csharp/Bombardment.cs new file mode 100644 index 00000000..bcbdcc26 --- /dev/null +++ b/11_Bombardment/csharp/Bombardment.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; + +namespace Bombardment +{ + // + // Game of Bombardment + // Based on the Basic game of Bombardment here + // https://github.com/coding-horror/basic-computer-games/blob/main/11%20Bombardment/bombardment.bas + // Note: The idea was to create a version of the 1970's Basic game in C#, without introducing + // new features - no additional text, error checking, etc has been added. + // + internal class Bombardment + { + private static int MAX_GRID_SIZE = 25; + private static int MAX_PLATOONS = 4; + private static Random random = new Random(); + private List computerPositions = new List(); + private List playerPositions = new List(); + private List computerGuesses = new List(); + + private void PrintStartingMessage() + { + Console.WriteLine("{0}BOMBARDMENT", new string(' ', 33)); + Console.WriteLine("{0}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", new string(' ', 15)); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + + Console.WriteLine("YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU"); + Console.WriteLine("HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED."); + Console.WriteLine("YOU CAN ONLY PLACE ONE PLATOON AT ANY ONE OUTPOST."); + Console.WriteLine("THE COMPUTER DOES THE SAME WITH ITS FOUR PLATOONS."); + Console.WriteLine(); + Console.WriteLine("THE OBJECT OF THE GAME IS TO FIRE MISSLES AT THE"); + Console.WriteLine("OUTPOSTS OF THE COMPUTER. IT WILL DO THE SAME TO YOU."); + Console.WriteLine("THE ONE WHO DESTROYS ALL FOUR OF THE ENEMY'S PLATOONS"); + Console.WriteLine("FIRST IS THE WINNER."); + Console.WriteLine(); + Console.WriteLine("GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT!"); + Console.WriteLine(); + Console.WriteLine("TEAR OFF MATRIX AND USE IT TO CHECK OFF THE NUMBERS."); + + // As an alternative to repeating the call to WriteLine(), + // we can print the new line character five times. + Console.Write(new string('\n', 5)); + + // Print a sample board (presumably the game was originally designed to be + // physically printed on paper while played). + for (var i = 1; i <= 25; i += 5) + { + // The token replacement can be padded by using the format {tokenPosition, padding} + // Negative values for the padding cause the output to be left-aligned. + Console.WriteLine("{0,-3}{1,-3}{2,-3}{3,-3}{4,-3}", i, i + 1, i + 2, i + 3, i + 4); + } + + Console.WriteLine("\n"); + } + + // Generate 5 random positions for the computer's platoons. + private void PlaceComputerPlatoons() + { + do + { + var nextPosition = random.Next(1, MAX_GRID_SIZE); + if (!computerPositions.Contains(nextPosition)) + { + computerPositions.Add(nextPosition); + } + + } while (computerPositions.Count < MAX_PLATOONS); + } + + private void StoreHumanPositions() + { + Console.WriteLine("WHAT ARE YOUR FOUR POSITIONS"); + + // The original game assumed that the input would be five comma-separated values, all on one line. + // For example: 12,22,1,4,17 + var input = Console.ReadLine(); + var playerPositionsAsStrings = input.Split(","); + foreach (var playerPosition in playerPositionsAsStrings) { + playerPositions.Add(int.Parse(playerPosition)); + } + } + + private void HumanTurn() + { + Console.WriteLine("WHERE DO YOU WISH TO FIRE YOUR MISSLE"); + var input = Console.ReadLine(); + var humanGuess = int.Parse(input); + + if(computerPositions.Contains(humanGuess)) + { + Console.WriteLine("YOU GOT ONE OF MY OUTPOSTS!"); + computerPositions.Remove(humanGuess); + + switch(computerPositions.Count) + { + case 3: + Console.WriteLine("ONE DOWN, THREE TO GO."); + break; + case 2: + Console.WriteLine("TWO DOWN, TWO TO GO."); + break; + case 1: + Console.WriteLine("THREE DOWN, ONE TO GO."); + break; + case 0: + Console.WriteLine("YOU GOT ME, I'M GOING FAST."); + Console.WriteLine("BUT I'LL GET YOU WHEN MY TRANSISTO&S RECUP%RA*E!"); + break; + } + } + else + { + Console.WriteLine("HA, HA YOU MISSED. MY TURN NOW:"); + } + } + + private int GenerateComputerGuess() + { + int computerGuess; + do + { + computerGuess = random.Next(1, 25); + } + while(computerGuesses.Contains(computerGuess)); + computerGuesses.Add(computerGuess); + + return computerGuess; + } + + private void ComputerTurn() + { + var computerGuess = GenerateComputerGuess(); + + if (playerPositions.Contains(computerGuess)) + { + Console.WriteLine("I GOT YOU. IT WON'T BE LONG NOW. POST {0} WAS HIT.", computerGuess); + playerPositions.Remove(computerGuess); + + switch(playerPositions.Count) + { + case 3: + Console.WriteLine("YOU HAVE ONLY THREE OUTPOSTS LEFT."); + break; + case 2: + Console.WriteLine("YOU HAVE ONLY TWO OUTPOSTS LEFT."); + break; + case 1: + Console.WriteLine("YOU HAVE ONLY ONE OUTPOST LEFT."); + break; + case 0: + Console.WriteLine("YOU'RE DEAD. YOUR LAST OUTPOST WAS AT {0}. HA, HA, HA.", computerGuess); + Console.WriteLine("BETTER LUCK NEXT TIME."); + break; + } + } + else + { + Console.WriteLine("I MISSED YOU, YOU DIRTY RAT. I PICKED {0}. YOUR TURN:", computerGuess); + } + } + + public void Play() + { + PrintStartingMessage(); + PlaceComputerPlatoons(); + StoreHumanPositions(); + + while (playerPositions.Count > 0 && computerPositions.Count > 0) + { + HumanTurn(); + + if (computerPositions.Count > 0) + { + ComputerTurn(); + } + } + } + } +} diff --git a/11_Bombardment/csharp/Bombardment.csproj b/11_Bombardment/csharp/Bombardment.csproj new file mode 100644 index 00000000..e5e0e164 --- /dev/null +++ b/11_Bombardment/csharp/Bombardment.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.1 + + + diff --git a/11_Bombardment/csharp/Program.cs b/11_Bombardment/csharp/Program.cs new file mode 100644 index 00000000..acc438ba --- /dev/null +++ b/11_Bombardment/csharp/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace Bombardment +{ + class Program + { + static void Main(string[] args) + { + var bombardment = new Bombardment(); + bombardment.Play(); + } + } +} From e8849566baf01424909f797d9db7db36e432b0c2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 4 Jan 2022 12:35:51 +1100 Subject: [PATCH 533/749] fix(amazing): guarantee exit on bottom row of maze This issue only tends to show up on very small mazes (e.g. 2x2, 3x3). It is possible for the algorithm to never generate an exit to the maze. While the algorithm guarantees with the `Z` variable that only one exit will be generated, it does not test for the situation where we just happen to never get the right random value to open an exit on the bottom row. The simplest resolution is just to check for this before rendering the final result (i.e. `IF Z=0`), and add an exit to a random cell on the bottom row. --- 02_Amazing/amazing.bas | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/02_Amazing/amazing.bas b/02_Amazing/amazing.bas index 63255319..3b39c93a 100644 --- a/02_Amazing/amazing.bas +++ b/02_Amazing/amazing.bas @@ -117,10 +117,15 @@ 975 V(R,S)=3:Q=0:GOTO 1000 980 V(R,S)=1:Q=0:R=1:S=1:GOTO 250 1000 GOTO 210 -1010 FOR J=1 TO V -1011 PRINT "I"; -1012 FOR I=1 TO H -1013 IF V(I,J)<2 THEN 1030 +1010 IF Z=1 THEN 1015 +1011 X=INT(RND(1)*H+1) +1012 IF V(X,V)=0 THEN 1014 +1013 V(X,V)=3: GOTO 1015 +1014 V(X,V)=1 +1015 FOR J=1 TO V +1016 PRINT "I"; +1017 FOR I=1 TO H +1018 IF V(I,J)<2 THEN 1030 1020 PRINT " "; 1021 GOTO 1040 1030 PRINT " I"; From 321205cc7769f75671028fc3190b1aa45b338b78 Mon Sep 17 00:00:00 2001 From: Alaa Sarhan Date: Tue, 4 Jan 2022 02:49:50 +0100 Subject: [PATCH 534/749] minor changes --- 13_Bounce/ruby/bounce.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/13_Bounce/ruby/bounce.rb b/13_Bounce/ruby/bounce.rb index 339c7851..e215a897 100644 --- a/13_Bounce/ruby/bounce.rb +++ b/13_Bounce/ruby/bounce.rb @@ -110,8 +110,8 @@ def plot_bouncing_ball(strobbing_time, v0, c) } if heighest_position_in_next_bounce(time_in_bounce, v0, i, c) < plotted_height then - # If we got no more ball positions at or above current height, we can skip - # the rest of the bounces and move down to the next height to plot + # If we got no more ball positions at or above current height in the next bounce, + # we can skip the rest of the bounces and move down to the next height to plot puts break end @@ -170,11 +170,11 @@ def game_loop end -## Game entry point +## Entry point begin intro - while true + loop do game_loop end rescue SystemExit, Interrupt From f98c8af9f82a3cfe36c5ca2c18f3b70af6b94149 Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Tue, 4 Jan 2022 00:21:38 -0500 Subject: [PATCH 535/749] Perl version of 35_evenwins --- 35_Even_Wins/perl/evenwins.pl | 168 ++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 35_Even_Wins/perl/evenwins.pl diff --git a/35_Even_Wins/perl/evenwins.pl b/35_Even_Wins/perl/evenwins.pl new file mode 100644 index 00000000..20065c23 --- /dev/null +++ b/35_Even_Wins/perl/evenwins.pl @@ -0,0 +1,168 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +&main; + +sub main { + &print_intro; + &game_play; +} + +sub game_play { + my $marbles = 27; + my $turn = 0; + my $player_total = 0; + my $computer_total = 0; + print "TYPE A '1' IF YOU WANT TO GO FIRST AND TYPE A '0' IF YOU WANT ME TO GO FIRST\n"; + my $choice = ; + chomp($choice); + if ($choice == 0) { + until ($marbles == 0) { + + my $computer_choice = &computer_select($marbles,$turn); + $marbles = $marbles - $computer_choice; + $computer_total = $computer_total + $computer_choice; + print "MY TOTAL IS $computer_total\n"; + + print "TOTAL= $marbles\n"; + + if ($marbles == 0) {&determine_winner($computer_total,$player_total)}; + + my $player_choice = &player_select($marbles,$turn); + $marbles = $marbles - $player_choice; + $player_total = $player_total + $player_choice; + print "YOUR TOTAL IS $player_total\n"; + $turn++; + print "TOTAL= $marbles\n"; + if ($marbles == 0) {&determine_winner($computer_total,$player_total)}; + } + } + elsif ($choice == 1) { + until ($marbles == 0) { + + my $player_choice = &player_select($marbles,$turn); + $marbles = $marbles - $player_choice; + $player_total = $player_total + $player_choice; + $turn++; + print "YOUR TOTAL IS $player_total\n"; + + print "TOTAL= $marbles\n"; + + if ($marbles == 0) {&determine_winner($computer_total,$player_total)}; + + my $computer_choice = &computer_select($marbles,$turn); + $marbles = $marbles - $computer_choice; + $computer_total = $computer_total + $computer_choice; + print "MY TOTAL IS $computer_total\n"; + + print "TOTAL= $marbles\n"; + + if ($marbles == 0) {&determine_winner($computer_total,$player_total)}; + + } + } +} + +sub determine_winner { + my $computer = shift; + my $player = shift; + print "THAT IS ALL OF THE MARBLES.\n\n"; + print "MY TOTAL IS $computer, YOUR TOTAL IS $player\n"; + if ($player % 2 == 0) { + print " YOU WON.\n"; + } + if ($computer % 2 == 0) { + print " I WON.\n"; + } + my $answer = -1; + until ($answer == 1 || $answer == 0) { + print "DO YOU WANT TO PLAY AGAIN? TYPE 1 FOR YES AND 0 FOR NO.\n"; + $answer=; + chomp($answer); + } + if ($answer == 1) { + &game_play; + } + else { + print "OK. SEE YOU LATER.\n"; + exit; + } +} + +sub player_select { + my $marbles = shift; + my $turn = shift; + my $validity="invalid"; + if ($turn == 0) { + print "WHAT IS YOUR FIRST MOVE\n"; + } + else { + print "WHAT IS YOUR NEXT MOVE\n"; + } + until ($validity eq "valid") { + my $num = ; + chomp($num); + my $validity=&validity_check($marbles,$num); + if ($validity eq "valid") { + return $num; + } + } +} + +sub computer_select { + my $marbles = shift; + my $turn = shift; + my $num = 2; + my $validity = "invalid"; + if ($turn == 0) { + print "I PICK UP $num MARBLES.\n\n"; + } + else { + until ($validity eq "valid") { + my $R=$marbles-6*int(($marbles/6)); + if ($marbles < 4.2) { + $num = $marbles; + } + if ($R > 3.4) { + if ($R < 4.7 || $R > 3.5) { + $num = 4; + } + else { + $num = 1; + } + } + $validity=&validity_check($marbles,$num); + } + print "\nI PICK UP $num MARBLES.\n\n"; + } + return $num; +} + +sub validity_check { + my $marbles = shift; + my $num = shift; + if ($num > $marbles) { + print "YOU HAVE TRIED TO TAKE MORE MARBLES THAN THERE ARE LEFT. TRY AGAIN. THERE ARE $marbles MARBLES LEFT\n"; + return "invalid"; + } + if ($num > 0 && $num <= 4) { + return "valid"; + } + if ($num < 1 || $num > 4) { + print "THE NUMBER OF MARBLES YOU TAKE MUST BE A POSITIVE INTEGER BETWEEN 1 AND 4\nWHAT IS YOUR NEXT MOVE?\n"; + return "invalid"; + } + else { + return "invalid"; + } +} + +sub print_intro { + print ' ' x 31 . "EVEN WINS\n"; + print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n"; + print "THIS IS A 2 PERSON GAME CALLED 'EVEN WINS'. TO PLAY THE GAME, THE PLAYERS NEED 27 MARBLES OR OTHER OBJECTS ON THE TABLE\n\n"; + print "THE 2 PLAYERS ALTERNATE TURNS, WITH EACH PLAYER REMOVING FROM 1 TO 4 MARBLES ON EACH MOVE. THE GAME ENDS WHEN THERE ARE NO MARBLES LEFT, AND THE WINNER IS THE ONE WITH AN EVEN NUMBER OF MARBLES\n"; + print "THE ONLY RULES ARE THAT (1) YOU MUST ALTERNATE TURNS, (2) YOU MUST TAKE BETWEEN 1 AND 4 MARBLES EACH TURN, AND (3) YOU CANNOT SKIP A TURN.\n\n"; +} From d82a637152968ff3dd6e035965b6bf65f1a228de Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 4 Jan 2022 16:47:32 +1100 Subject: [PATCH 536/749] chore(amazing): add note to README.md for #400 --- 02_Amazing/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/02_Amazing/README.md b/02_Amazing/README.md index 8f7b271b..e94949bd 100644 --- a/02_Amazing/README.md +++ b/02_Amazing/README.md @@ -12,3 +12,7 @@ As published in Basic Computer Games (1978): Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html + +--- + +**2022-01-04:** patched original source in [#400](https://github.com/coding-horror/basic-computer-games/pull/400) to fix a minor bug where a generated maze may be missing an exit, particularly at small maze sizes. From 55b3c0d4e76142312e9abf2276b51b097aa5631d Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Tue, 4 Jan 2022 01:33:11 -0500 Subject: [PATCH 537/749] Add files via upload --- 35_Even_Wins/perl/evenwins.pl | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/35_Even_Wins/perl/evenwins.pl b/35_Even_Wins/perl/evenwins.pl index 20065c23..c2fdc2d8 100644 --- a/35_Even_Wins/perl/evenwins.pl +++ b/35_Even_Wins/perl/evenwins.pl @@ -21,7 +21,7 @@ sub game_play { if ($choice == 0) { until ($marbles == 0) { - my $computer_choice = &computer_select($marbles,$turn); + my $computer_choice = &computer_select($marbles,$turn,$player_total); $marbles = $marbles - $computer_choice; $computer_total = $computer_total + $computer_choice; print "MY TOTAL IS $computer_total\n"; @@ -52,7 +52,7 @@ sub game_play { if ($marbles == 0) {&determine_winner($computer_total,$player_total)}; - my $computer_choice = &computer_select($marbles,$turn); + my $computer_choice = &computer_select($marbles,$turn,$player_total); $marbles = $marbles - $computer_choice; $computer_total = $computer_total + $computer_choice; print "MY TOTAL IS $computer_total\n"; @@ -114,6 +114,7 @@ sub player_select { sub computer_select { my $marbles = shift; my $turn = shift; + my $player_total = shift; my $num = 2; my $validity = "invalid"; if ($turn == 0) { @@ -122,14 +123,24 @@ sub computer_select { else { until ($validity eq "valid") { my $R=$marbles-6*int(($marbles/6)); - if ($marbles < 4.2) { + + if (int($player_total/2) == $player_total/2) { + if ($R < 1.5 || $R > 5.3) { + $num = 1; + } + else { + $num = $R - 1; + } + } + + elsif ($marbles < 4.2) { $num = $marbles; } - if ($R > 3.4) { + elsif ($R > 3.4) { if ($R < 4.7 || $R > 3.5) { $num = 4; } - else { + else { $num = 1; } } From 41183198a8d9e57135b079c48923ef7207d87404 Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Tue, 4 Jan 2022 01:37:57 -0500 Subject: [PATCH 538/749] added logic/intelligence into the AI modified the logic from how the computer was making its selections. Original code had a simple random number, this incorporates the original logic from the BASIC game. --- 35_Even_Wins/python/evenwins.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/35_Even_Wins/python/evenwins.py b/35_Even_Wins/python/evenwins.py index fba20024..3fb9d4af 100644 --- a/35_Even_Wins/python/evenwins.py +++ b/35_Even_Wins/python/evenwins.py @@ -142,17 +142,32 @@ def game_over(): print('') def computer_turn(): - global marbles_in_middle - global computer_marbles + global marbles_in_middle + global computer_marbles + global human_marbles - print("It's the computer's turn ...") - max_choice = min(4, marbles_in_middle) + marbles_to_take=0 - # choose at random - n = random.randint(1, max_choice) - print(f'Computer takes {marbles_str(n)} ...') - marbles_in_middle -= n - computer_marbles += n + print("It's the computer's turn ...") + r = marbles_in_middle - 6 * int((marbles_in_middle/6)) #line 500 + + if int(human_marbles/2) == human_marbles/2: #line 510 + if r < 1.5 or r > 5.3: #lines 710 and 720 + marbles_to_take = 1 + else: + marbles_to_take = r - 1 + + elif marbles_in_middle < 4.2: #line 580 + marbles_to_take = marbles_in_middle + elif r > 3.4: #line 530 + if r < 4.7 or r > 3.5: + marbles_to_take = 4 + else: + marbles_to_take = r + 1 + + print(f'Computer takes {marbles_str(marbles_to_take)} ...') + marbles_in_middle -= marbles_to_take + computer_marbles += marbles_to_take def play_game(): global marbles_in_middle From 3b4b14427c6da19f03fd557afd380e20b65bd638 Mon Sep 17 00:00:00 2001 From: Alex Kapranoff Date: Tue, 4 Jan 2022 00:38:57 -0800 Subject: [PATCH 539/749] 02_Amazing in Perl --- 02_Amazing/perl/amazing.pl | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 02_Amazing/perl/amazing.pl diff --git a/02_Amazing/perl/amazing.pl b/02_Amazing/perl/amazing.pl new file mode 100644 index 00000000..a474ba59 --- /dev/null +++ b/02_Amazing/perl/amazing.pl @@ -0,0 +1,155 @@ +#! /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); + } +} + +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) = =~ / \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; +} From 6f599f12f64a51cfd2bc039a5ad48d5f9d8ef9d9 Mon Sep 17 00:00:00 2001 From: Alex Kapranoff Date: Tue, 4 Jan 2022 00:47:34 -0800 Subject: [PATCH 540/749] Fix the bug identified in #400 --- 02_Amazing/perl/amazing.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/02_Amazing/perl/amazing.pl b/02_Amazing/perl/amazing.pl index a474ba59..c7cb5f44 100644 --- a/02_Amazing/perl/amazing.pl +++ b/02_Amazing/perl/amazing.pl @@ -60,6 +60,10 @@ while (keys %is_visited < $width * $height) { } } +unless ($path_found) { + $walls[-1]->[rand $width] |= 1; +} + print_maze(); sub input_dimensions { From 5409fa3daf6d935d74543d8009d722d72cb0f6ba Mon Sep 17 00:00:00 2001 From: Alex Kapranoff Date: Tue, 4 Jan 2022 00:51:54 -0800 Subject: [PATCH 541/749] chmod +x on the Perl script, as is done in #307 --- 02_Amazing/perl/amazing.pl | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 02_Amazing/perl/amazing.pl diff --git a/02_Amazing/perl/amazing.pl b/02_Amazing/perl/amazing.pl old mode 100644 new mode 100755 From ec43a4fc9490c220e76b434c045b3c84198eeefd Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Mon, 3 Jan 2022 00:19:19 +0100 Subject: [PATCH 542/749] D version of Acey-Ducey. --- 01_Acey_Ducey/d/.gitignore | 2 + 01_Acey_Ducey/d/README.md | 29 ++++++ 01_Acey_Ducey/d/aceyducey.d | 131 ++++++++++++++++++++++++++++ 01_Acey_Ducey/d/aceyducey_literal.d | 104 ++++++++++++++++++++++ 4 files changed, 266 insertions(+) create mode 100644 01_Acey_Ducey/d/.gitignore create mode 100644 01_Acey_Ducey/d/README.md create mode 100644 01_Acey_Ducey/d/aceyducey.d create mode 100644 01_Acey_Ducey/d/aceyducey_literal.d diff --git a/01_Acey_Ducey/d/.gitignore b/01_Acey_Ducey/d/.gitignore new file mode 100644 index 00000000..d969f6b2 --- /dev/null +++ b/01_Acey_Ducey/d/.gitignore @@ -0,0 +1,2 @@ +*.exe +*.obj diff --git a/01_Acey_Ducey/d/README.md b/01_Acey_Ducey/d/README.md new file mode 100644 index 00000000..a45fcb2c --- /dev/null +++ b/01_Acey_Ducey/d/README.md @@ -0,0 +1,29 @@ +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). + +Two versions are supplied that are functionally equivalent, but differ in source layout: + + + +## Running the code + +Assuming the reference [dmd](https://dlang.org/download.html#dmd) compiler: +```shell +dmd -run aceyducey.d +``` + +[Other compilers](https://dlang.org/download.html) also exist. + +Note that there are compiler switches related to memory-safety (`-preview=dip25` and `-preview=dip1000`) that are not +used here because they are unnecessary in this case. What these do is to make the analysis more thorough, so that with +them some code that needed to be `@system` can then be inferred to be in fact `@safe`. [Code that compiles without +these switches is just as safe as when compiled with them] +(https://forum.dlang.org/post/dftgjalswvwfjpyushgn@forum.dlang.org). diff --git a/01_Acey_Ducey/d/aceyducey.d b/01_Acey_Ducey/d/aceyducey.d new file mode 100644 index 00000000..036786c5 --- /dev/null +++ b/01_Acey_Ducey/d/aceyducey.d @@ -0,0 +1,131 @@ +@safe: // Make @safe the default for this file, enforcing memory-safety. + +void main() +{ + import std.stdio : write, writeln; + import std.string : center, toUpper, wrap; + import std.exception : ifThrown; + + enum width = 80; + writeln(center("Acey Ducey Card Game", width)); + writeln(center("(After Creative Computing Morristown, New Jersey)\n", width)); + writeln(wrap("Acey-Ducey is played in the following manner: The dealer (computer) deals two cards face up. " ~ + "You have an option to bet or not bet depending on whether or not you feel the third card will " ~ + "have a value between the first two. If you do not want to bet, input a 0.", width)); + + enum Hand {low, middle, high} + Card[Hand.max + 1] cards; // Three cards. + bool play = true; + + while (play) + { + int cash = 100; + while (cash > 0) + { + writeln("\nYou now have ", cash, " dollars."); + int bet = 0; + while (bet <= 0) + { + do // Draw new cards, until the first card has a smaller value than the last card. + { + foreach (ref card; cards) + card.drawNew; + } while (cards[Hand.low] >= cards[Hand.high]); + writeln("Here are your next two cards:\n", cards[Hand.low], "\n", cards[Hand.high]); + + int askBet() // A nested function. + { + import std.conv : to; + + write("\nWhat is your bet? "); + int answer = readString.to!int. + ifThrown!Exception(askBet); // Try again when answer does not convert to int. + if (answer <= cash) + return answer; + writeln("Sorry, my friend, but you bet too much.\nYou have only ", cash, " dollars to bet."); + return askBet; // Recurse: Ask again. + } + bet = askBet; + if (bet <= 0) // Negative bets are interpreted as 0. + writeln("CHICKEN!!"); + } // bet is now > 0. + + writeln(cards[Hand.middle]); + if (cards[Hand.low] < cards[Hand.middle] && cards[Hand.middle] < cards[Hand.high]) + { + writeln("YOU WIN!!!"); + cash += bet; + } + else + { + writeln("Sorry, you lose."); + cash -= bet; + if (cash <= 0) + { + writeln("\n\nSorry, friend, but you blew your wad."); + write("\n\nTry again (Yes or No)? "); + play = readString.toUpper == "YES"; + } + } + } + } + writeln("O.K., hope you had fun!"); +} + +struct Card +{ + int value = 2; + alias value this; // Enables Card to stand in as an int, so that cards can be compared as ints. + + invariant + { + assert(2 <= value && value <= 14); // Ensure cards always have a valid value. + } + + /// Adopt a new value. + void drawNew() + { + import std.random : uniform; + + value = uniform!("[]", int, int)(2, 14); // A random int between inclusive bounds. + } + + /// Called for implicit conversion to string. + string toString() const pure + { + import std.conv : text; + + switch (value) + { + case 11: return "Jack"; + case 12: return "Queen"; + case 13: return "King"; + case 14: return "Ace"; + default: return text(" ", value); // Basic prepends a space. + } + } +} + +/// Read a string from standard input, stripping newline and other enclosing whitespace. +string readString() nothrow +{ + import std.string : strip; + + 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 +{ + import std.stdio : readln; + + return readln; +} diff --git a/01_Acey_Ducey/d/aceyducey_literal.d b/01_Acey_Ducey/d/aceyducey_literal.d new file mode 100644 index 00000000..a51028de --- /dev/null +++ b/01_Acey_Ducey/d/aceyducey_literal.d @@ -0,0 +1,104 @@ +void main() +{ + import std; + + L10: writef("%26s", ' '); writeln("ACEY DUCEY CARD GAME"); + L20: writef("%15s", ' '); writeln("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + L21: writeln; + L22: writeln; + L30: writeln("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER "); + L40: writeln("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP"); + L50: writeln("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING"); + L60: writeln("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE"); + L70: writeln("A VALUE BETWEEN THE FIRST TWO."); + L80: writeln("IF YOU DO NOT WANT TO BET, INPUT A 0"); + L100: int N=100; + L110: int Q=100, M; + L120: writeln("YOU NOW HAVE ",Q," DOLLARS."); + L130: writeln; + L140: goto L260; + L210: Q=Q+M; + L220: goto L120; + L240: Q=Q-M; + L250: goto L120; + L260: writeln("HERE ARE YOUR NEXT TWO CARDS: "); + L270: auto A=to!int(14*uniform01)+2; + L280: if (A<2) goto L270; + L290: if (A>14) goto L270; + L300: auto B=to!int(14*uniform01)+2; + L310: if (B<2) goto L300; + L320: if (B>14) goto L300; + L330: if (A>=B) goto L270; + L350: if (A<11) goto L400; + L360: if (A==11) goto L420; + L370: if (A==12) goto L440; + L380: if (A==13) goto L460; + L390: if (A==14) goto L480; + L400: writefln("%2d", A); + L410: goto L500; + L420: writeln("JACK"); + L430: goto L500; + L440: writeln("QUEEN"); + L450: goto L500; + L460: writeln("KING"); + L470: goto L500; + L480: writeln("ACE"); + L500: if (B<11) goto L550; + L510: if (B==11) goto L570; + L520: if (B==12) goto L590; + L530: if (B==13) goto L610; + L540: if (B==14) goto L630; + L550: writefln("%2d", B); + L560: goto L650; + L570: writeln("JACK"); + L580: goto L650; + L590: writeln("QUEEN"); + L600: goto L650; + L610: writeln("KING"); + L620: goto L650; + L630: writeln("ACE"); + L640: writeln; + L650: writeln; + L660: write("WHAT IS YOUR BET? "); M = stdin.readln.strip.to!int; + L670: if (M!=0) goto L680; + L675: writeln("CHICKEN!!"); + L676: writeln; + L677: goto L260; + L680: if (M<=Q) goto L730; + L690: writeln("SORRY, MY FRIEND, BUT YOU BET TOO MUCH."); + L700: writeln("YOU HAVE ONLY ",Q," DOLLARS TO BET."); + L710: goto L650; + L730: auto C=to!int(14*uniform01)+2; + L740: if (C<2) goto L730; + L750: if (C>14) goto L730; + L760: if (C<11) goto L810; + L770: if (C==11) goto L830; + L780: if (C==12) goto L850; + L790: if (C==13) goto L870; + L800: if (C==14) goto L890; + L810: writeln(C); + L820: goto L910; + L830: writeln("JACK"); + L840: goto L910; + L850: writeln("QUEEN"); + L860: goto L910; + L870: writeln("KING"); + L880: goto L910; + L890: writeln( "ACE"); + L900: writeln; + L910: if (C>A) goto L930; + L920: goto L970; + L930: if (C>=B) goto L970; + L950: writeln("YOU WIN!!!"); + L960: goto L210; + L970: writeln("SORRY, YOU LOSE"); + L980: if (M Date: Wed, 5 Jan 2022 00:13:52 +1100 Subject: [PATCH 543/749] Remove exceptions used for standard flow-control - this is an antipattern. --- 53_King/kotlin/King.kt | 158 ++++++++++++++++++++++------------------- 1 file changed, 85 insertions(+), 73 deletions(-) diff --git a/53_King/kotlin/King.kt b/53_King/kotlin/King.kt index 01558c99..8f660357 100644 --- a/53_King/kotlin/King.kt +++ b/53_King/kotlin/King.kt @@ -19,29 +19,25 @@ fun main() { } ?: throw EndOfInputException() - try { - with(gameState) { - while(currentYear < yearsRequired) { - recalculateLandCost() - displayStatus() - inputLandSale() - performLandSale() - inputWelfare() - performWelfare() - inputPlantingArea() - performPlanting() - inputPollutionControl() - if (zeroInput()) { - displayExitMessage() - exitProcess(0) - } - simulateOneYear() - currentYear ++ + with(gameState) { + do { + recalculateLandCost() + displayStatus() + inputLandSale() + performLandSale() + inputWelfare() + performWelfare() + inputPlantingArea() + performPlanting() + inputPollutionControl() + if (zeroInput()) { + displayExitMessage() + exitProcess(0) } - } - win(gameState.yearsRequired) - } catch (e: GameEndingException) { - e.displayConsequences() + val yearResult = simulateOneYear().also { + it.displayConsequences() + } + } while (yearResult == YearOutcome.ContinueNextYear) } } @@ -54,7 +50,8 @@ private fun header() { } fun instructions(yearsRequired: Int) { - println(""" + println( + """ CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS @@ -83,7 +80,7 @@ fun loadOldGame(): GameState = GameState().apply { currentYear = numberInput() if (currentYear <= 0) - throw GameEndingException.DataEntryValidation() + throw DataEntryValidation() if (currentYear >= yearsRequired) { println(" COME ON, YOUR TERM IN OFFICE IS ONLY $yearsRequired YEARS.") @@ -94,19 +91,19 @@ fun loadOldGame(): GameState = GameState().apply { print("HOW MUCH DID YOU HAVE IN THE TREASURY? ") rallods = numberInput() if (rallods < 0) - throw GameEndingException.DataEntryValidation() + throw DataEntryValidation() print("HOW MANY WORKERS? ") foreignWorkers = numberInput() if (foreignWorkers < 0) - throw GameEndingException.DataEntryValidation() + throw DataEntryValidation() do { var retry = false print("HOW MANY SQUARE MILES OF LAND? ") landArea = numberInput() - if (landArea<0) - throw GameEndingException.DataEntryValidation() + if (landArea < 0) + throw DataEntryValidation() if (landArea > 2000 || landArea <= 1000) { println(" COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND") println(" AND 10,000 SQ. MILES OF FOREST LAND.") @@ -118,11 +115,13 @@ fun loadOldGame(): GameState = GameState().apply { /** - * All exceptions which indicate the premature ending of the game, due - * to mismanagement, starvation, revolution, or mis-entry of a game state. + * Possible outcomes for a year. */ -sealed class GameEndingException : Throwable() { - abstract fun displayConsequences() +sealed class YearOutcome { + + open fun displayConsequences() { + // Default display nothing + } fun finalFate() { if (rnd < .5) { @@ -135,7 +134,28 @@ sealed class GameEndingException : Throwable() { println() } - class ExtremeMismanagement(private val death: Int) : GameEndingException() { + object ContinueNextYear : YearOutcome() + + class Win(val yearsRequired: Int) : YearOutcome() { + override fun displayConsequences() { + // The misspelling of "successfully" is in the original code. + println( + """ + + CONGRATULATIONS!!!!!!!!!!!!!!!!!! + YOU HAVE SUCCESFULLY COMPLETED YOUR $yearsRequired YEAR TERM + OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT + NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD + LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT + PLAYS THIS GAME. + + + """.trimIndent() + ) + } + } + + class ExtremeMismanagement(private val death: Int) : YearOutcome() { override fun displayConsequences() { println() println("$death COUNTRYMEN DIED IN ONE YEAR!!!!!") @@ -151,34 +171,39 @@ sealed class GameEndingException : Throwable() { } } - class TooManyPeopleDead : GameEndingException() { + object TooManyPeopleDead : YearOutcome() { // The mistyping of "population" is in the original game. override fun displayConsequences() { - println(""" + println( + """ OVER ONE THIRD OF THE POPULTATION HAS DIED SINCE YOU WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING) HATE YOUR GUTS. - """.trimIndent()) + """.trimIndent() + ) finalFate() } } - class AntiImmigrationRevolution : GameEndingException() { + object AntiImmigrationRevolution : YearOutcome() { override fun displayConsequences() { - println(""" + println( + """ THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND TAKEN OVER THE COUNTRY. - """.trimIndent()) + """.trimIndent() + ) finalFate() } } - class StarvationWithFullTreasury : GameEndingException() { + object StarvationWithFullTreasury : YearOutcome() { override fun displayConsequences() { - println(""" + println( + """ MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE @@ -186,33 +211,14 @@ sealed class GameEndingException : Throwable() { THE CHOICE IS YOURS. IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER BEFORE PROCEEDING. - """.trimIndent()) + """.trimIndent() + ) } } - class DataEntryValidation : GameEndingException() { - override fun displayConsequences() { - // no action - } - } - - } -fun win(yearsRequired: Int) { - // The misspelling of "successfully" is in the original code. - println(""" - - CONGRATULATIONS!!!!!!!!!!!!!!!!!! - YOU HAVE SUCCESFULLY COMPLETED YOUR $yearsRequired YEAR TERM - OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT - NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD - LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT - PLAYS THIS GAME. - - - """.trimIndent()) -} +class DataEntryValidation : Throwable() /** * Record data, allow data input, and process the simulation for the game. @@ -444,7 +450,7 @@ class GameState(val yearsRequired: Int = 8) { plantingArea == 0 && moneySpentOnPollutionControl == 0 - fun simulateOneYear() { + fun simulateOneYear(): YearOutcome { rallods -= moneySpentOnPollutionControl val rallodsAfterPollutionControl = rallods @@ -460,7 +466,7 @@ class GameState(val yearsRequired: Int = 8) { https://github.com/coding-horror/basic-computer-games/blob/main/53_King/king.bas#:~:text=1105%20IF%20I/100%3C50%20THEN%201700 */ if (welfareThisYear / 100.0 < 50) - throw GameEndingException.TooManyPeopleDead() + return YearOutcome.TooManyPeopleDead starvationDeaths = (countrymen - (welfareThisYear / 100.0)).toInt() println("$starvationDeaths COUNTRYMEN DIED OF STARVATION") @@ -575,14 +581,20 @@ class GameState(val yearsRequired: Int = 8) { } rallods += tourists - if (death > 200) - throw GameEndingException.ExtremeMismanagement(death) - if (countrymen < 343) - throw GameEndingException.TooManyPeopleDead() - if (rallodsAfterPollutionControl / 100 > 5 && death - pollutionDeaths >= 2) - throw GameEndingException.StarvationWithFullTreasury() - if (foreignWorkers > countrymen) - throw GameEndingException.AntiImmigrationRevolution() + return if (death > 200) + YearOutcome.ExtremeMismanagement(death) + else if (countrymen < 343) + YearOutcome.TooManyPeopleDead + else if (rallodsAfterPollutionControl / 100 > 5 && death - pollutionDeaths >= 2) + YearOutcome.StarvationWithFullTreasury + else if (foreignWorkers > countrymen) + YearOutcome.AntiImmigrationRevolution + else { + if (currentYear++ > yearsRequired) + YearOutcome.Win(yearsRequired) + else + YearOutcome.ContinueNextYear + } } } From 581a3f1441a9a7eed06709560ca1f3be1c00f9e4 Mon Sep 17 00:00:00 2001 From: Martin VanWinkle III Date: Tue, 4 Jan 2022 08:36:37 -0500 Subject: [PATCH 544/749] cleanup --- 31_Depth_Charge/ruby/.gitignore | 57 +++++++++++++++++++++++++++++ 31_Depth_Charge/ruby/depthcharge.rb | 48 ++++-------------------- 2 files changed, 65 insertions(+), 40 deletions(-) create mode 100644 31_Depth_Charge/ruby/.gitignore diff --git a/31_Depth_Charge/ruby/.gitignore b/31_Depth_Charge/ruby/.gitignore new file mode 100644 index 00000000..d25ad7bc --- /dev/null +++ b/31_Depth_Charge/ruby/.gitignore @@ -0,0 +1,57 @@ +# Package Shell Specific Things + +## Build Process + +/build + +## Transient files + +/src/input +/src/output +/src/log +/drop + +# Programming Languages + +## Java +/src/java/**/*.class + +## Rakudo / Perl6 +/src/**/.precomp + +## PHP +/vendor/ + +## Python +*.swp +__pycache__/ +*.pyc +*.egg-info +/dist + +## Ruby +*.gem +.bundle + +# Editors + +## Dia +*.dia.autosave + +## Emacs +\#*\# +.\#* + + +## Vi / Vim +*.swp + +# Filesystem Artifacts + +## Mac + +.DS_Store + +## NFS + +.nfs* diff --git a/31_Depth_Charge/ruby/depthcharge.rb b/31_Depth_Charge/ruby/depthcharge.rb index 5ba36ba6..ba2a5d83 100755 --- a/31_Depth_Charge/ruby/depthcharge.rb +++ b/31_Depth_Charge/ruby/depthcharge.rb @@ -13,7 +13,6 @@ class DepthCharge break if ! get_input_another_game() end - # 420 PRINT "OK. HOPE YOU ENJOYED YOURSELF." : GOTO 600 printf("OK. HOPE YOU ENJOYED YOURSELF.\n") end @@ -51,7 +50,7 @@ class DepthCharge the_input = Integer(value) rescue nil - if the_input == nil || the_input < 0 + if the_input == nil || the_input < 1 printf("PLEASE ENTER A POSITIVE NUMBER\n\n") next @@ -61,25 +60,7 @@ class DepthCharge end end - def get_search_area_dimension - # 20 INPUT "DIMENSION OF SEARCH AREA";G: PRINT - @search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ") - # 30 N=INT(LOG(G)/LOG(2))+1 - - @num_tries = Integer( - Math.log(@search_area_dimension)/Math.log(2) - ) - - end - def print_instructions - # 40 PRINT "YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER" - # 50 PRINT "AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR" - # 60 PRINT "MISSION IS TO DESTROY IT. YOU HAVE";N;"SHOTS." - # 70 PRINT "SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A" - # 80 PRINT "TRIO OF NUMBERS -- THE FIRST TWO ARE THE" - # 90 PRINT "SURFACE COORDINATES; THE THIRD IS THE DEPTH." - # 100 PRINT : PRINT "GOOD LUCK !": PRINT printf( <<~INSTRUCTIONS YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR @@ -110,19 +91,21 @@ GOOD LUCK ! end def setup_game - get_search_area_dimension() + @search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ") + + @num_tries = Integer( + Math.log(@search_area_dimension)/Math.log(2) + 1 + ) setup_enemy() end def setup_enemy - # 110 A=INT(G*RND(1)) : B=INT(G*RND(1)) : C=INT(G*RND(1)) @enemy_x = rand(1..@search_area_dimension) @enemy_y = rand(1..@search_area_dimension) @enemy_z = rand(1..@search_area_dimension) - end + end def game_loop - # 120 FOR D=1 TO N : PRINT : PRINT "TRIAL #";D; : INPUT X,Y,Z for @trial in 1..@num_tries do output_game_status() @@ -130,7 +113,6 @@ GOOD LUCK ! @shot_y = get_input_positive_integer("Y: ") @shot_z = get_input_positive_integer("Z: ") - # 130 IF ABS(X-A)+ABS(Y-B)+ABS(Z-C)=0 THEN 300 if ( (@enemy_x - @shot_x).abs \ + (@enemy_y - @shot_y).abs \ @@ -140,7 +122,6 @@ GOOD LUCK ! you_win() return else - # 140 GOSUB 500 : PRINT : NEXT D missed_shot() end end @@ -156,54 +137,41 @@ GOOD LUCK ! printf("TRIAL \#%d\n", @trial) end def you_win - printf("B O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial ) + printf("\nB O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial ) end def missed_shot missed_directions = [] - # 530 IF X>A THEN PRINT "EAST"; - # 540 IF X @enemy_x missed_directions.push('TOO FAR EAST') elsif @shot_x < @enemy_x missed_directions.push('TOO FAR WEST') end - # 510 IF Y>B THEN PRINT "NORTH"; - # 520 IF Y @enemy_y missed_directions.push('TOO FAR NORTH') elsif @shot_y < @enemy_y missed_directions.push('TOO FAR SOUTH') end - # 560 IF Z>C THEN PRINT " TOO LOW." - # 570 IF Z @enemy_z missed_directions.push('TOO DEEP') elsif @shot_z < @enemy_z missed_directions.push('TOO SHALLOW') end - # 500 PRINT "SONAR REPORTS SHOT WAS "; printf("SONAR REPORTS SHOT WAS: \n") printf("%s\n", "\t" + missed_directions.join("\n\t")) - # 550 IF Y<>B OR X<>A THEN PRINT " AND"; - # 590 RETURN end def you_lose - # You took too long! printf("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!\n") printf("THE SUBMARINE WAS AT %d %d %d\n", @enemy_x, @enemy_y, @enemy_z) end def get_input_another_game - # 400 PRINT : PRINT: INPUT "ANOTHER GAME (Y OR N)";A$ return get_input_y_or_n("ANOTHER GAME (Y OR N): ") - # 410 IF A$="Y" THEN 100 end end From ec6dfd4bc3a1dca54553905a268828ac69751724 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Wed, 5 Jan 2022 01:24:08 +1100 Subject: [PATCH 545/749] Bug fix - restoring game did not enter countrymen Refactor - Added validatedInput function --- 53_King/kotlin/King.kt | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/53_King/kotlin/King.kt b/53_King/kotlin/King.kt index 8f660357..f16f24e5 100644 --- a/53_King/kotlin/King.kt +++ b/53_King/kotlin/King.kt @@ -77,10 +77,7 @@ fun loadOldGame(): GameState = GameState().apply { do { var retry = false print("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED? ") - currentYear = numberInput() - - if (currentYear <= 0) - throw DataEntryValidation() + currentYear = validatedInput { it > 0 } if (currentYear >= yearsRequired) { println(" COME ON, YOUR TERM IN OFFICE IS ONLY $yearsRequired YEARS.") @@ -89,21 +86,19 @@ fun loadOldGame(): GameState = GameState().apply { } while (retry) print("HOW MUCH DID YOU HAVE IN THE TREASURY? ") - rallods = numberInput() - if (rallods < 0) - throw DataEntryValidation() + rallods = validatedInput { it >= 0 } + + print("HOW MANY COUNTRYMEN? ") + countrymen = validatedInput { it >= 0 } print("HOW MANY WORKERS? ") - foreignWorkers = numberInput() - if (foreignWorkers < 0) - throw DataEntryValidation() + foreignWorkers = validatedInput { it >= 0 } do { var retry = false print("HOW MANY SQUARE MILES OF LAND? ") - landArea = numberInput() - if (landArea < 0) - throw DataEntryValidation() + landArea = validatedInput { it >= 0 } + if (landArea > 2000 || landArea <= 1000) { println(" COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND") println(" AND 10,000 SQ. MILES OF FOREST LAND.") @@ -218,13 +213,10 @@ sealed class YearOutcome { } -class DataEntryValidation : Throwable() - /** * Record data, allow data input, and process the simulation for the game. */ class GameState(val yearsRequired: Int = 8) { - /** * The current year. Years start with zero, but we never * output the current year. @@ -246,8 +238,8 @@ class GameState(val yearsRequired: Int = 8) { private var tourists = 0 private var moneySpentOnPollutionControl = 0 - private var moneySpentOnPlanting = 0 + private var moneySpentOnPlanting = 0 /** * Current stock of rallods. * Player starts with between 59000 and 61000 rallods, but @@ -258,10 +250,10 @@ class GameState(val yearsRequired: Int = 8) { /** * Population. - * Initial population is about to 500. + * Initial population is about 500. * 75% of the time it's between 495 and 505. */ - private var countrymen = (500 + (10 * rnd) - (10 * rnd)).toInt() + var countrymen = (500 + (10 * rnd) - (10 * rnd)).toInt() /** * Land sale price is evenly between 95 and 104 rallods per @@ -271,8 +263,8 @@ class GameState(val yearsRequired: Int = 8) { private var landPrice = (10 * rnd + 95).toInt() private var plantingArea = 0 - private var welfareThisYear = 0 + private var welfareThisYear = 0 /** * Land area in square miles. Arable land is 1000 square miles less. * Almost all calculations use landArea-1000 because only arable @@ -345,7 +337,6 @@ class GameState(val yearsRequired: Int = 8) { rallods -= welfareThisYear } - /** * Ask how much land we want to sell. Immediately get the money. * The player has to do the calculations to work out how much @@ -368,6 +359,7 @@ class GameState(val yearsRequired: Int = 8) { } while (sellThisYear < 0 || sellThisYear > landArea - 1000) } + /** * Input the value of `welfareThisYear` */ @@ -599,14 +591,12 @@ class GameState(val yearsRequired: Int = 8) { } } - private fun numberInput() = try { readLine()?.toInt() ?: throw EndOfInputException() } catch (r: NumberFormatException) { 0 } - - - - +class DataEntryValidationException : Throwable() +private fun validatedInput(predicate : (Int)->Boolean) = + numberInput().apply { if (!predicate(this)) throw DataEntryValidationException() } From bd0e7049149efb70999efe670a9926e91579cedd Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Wed, 5 Jan 2022 01:30:39 +1100 Subject: [PATCH 546/749] Update README.md --- 53_King/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/53_King/README.md b/53_King/README.md index 206202f0..4542f90c 100644 --- a/53_King/README.md +++ b/53_King/README.md @@ -8,6 +8,8 @@ The money system is Rollods; each person needs 100 Rallods per year to survive. The author of this program is James A. Storer who wrote it while a student at Lexington High School. +⚠️ This game includes references to suicide or self-harm. + ## Bugs Implementers should be aware that this game contains at least one bug. From 46baddd24c2bc487c970344e88981c048dce09d2 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Wed, 5 Jan 2022 01:33:41 +1100 Subject: [PATCH 547/749] change headings --- 53_King/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/53_King/README.md b/53_King/README.md index 206202f0..f97e7b33 100644 --- a/53_King/README.md +++ b/53_King/README.md @@ -1,4 +1,4 @@ -### King +## King This is one of the most comprehensive, difficult, and interesting games. (If you’ve never played one of these games, start with HAMMURABI.) @@ -8,7 +8,7 @@ The money system is Rollods; each person needs 100 Rallods per year to survive. The author of this program is James A. Storer who wrote it while a student at Lexington High School. -## Bugs +### Bugs Implementers should be aware that this game contains at least one bug. From c744cd928247fd0059dad04645667fe6dc74446c Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Wed, 5 Jan 2022 02:09:38 +1100 Subject: [PATCH 548/749] Remove suicide reference by default --- 53_King/kotlin/King.kt | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/53_King/kotlin/King.kt b/53_King/kotlin/King.kt index f16f24e5..71e6d505 100644 --- a/53_King/kotlin/King.kt +++ b/53_King/kotlin/King.kt @@ -3,7 +3,8 @@ import kotlin.random.Random import kotlin.system.exitProcess lateinit var gameState: GameState -const val INCLUDE_BUGS_FROM_ORIGINAL = false +const val KEEP_ORIGINAL_BUGS = false +const val KEEP_ORIGINAL_SUICIDE_REFERENCE = false val rnd: Double get() = Random.nextDouble() fun tab(i: Int) = " ".repeat(i) @@ -198,15 +199,26 @@ sealed class YearOutcome { object StarvationWithFullTreasury : YearOutcome() { override fun displayConsequences() { println( - """ - MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID - NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED - OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE - BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE. - THE CHOICE IS YOURS. - IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER - BEFORE PROCEEDING. - """.trimIndent() + if (KEEP_ORIGINAL_SUICIDE_REFERENCE) { + """ + MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID + NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED + OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE + BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE. + THE CHOICE IS YOURS. + IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER + BEFORE PROCEEDING. + """.trimIndent() + } else { + """ + MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID + NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED + OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE + BEEN FORCED TO RESIGN. + PLEASE TURN OFF YOUR COMPUTER AND SURRENDER IT TO + THE NEAREST POLICE STATION. + """.trimIndent() + } ) } } @@ -566,7 +578,7 @@ class GameState(val yearsRequired: Int = 8) { https://github.com/coding-horror/basic-computer-games/blob/main/53_King/king.bas#:~:text=1450%20V3%3DINT,INT(A%2BV3) */ - if (INCLUDE_BUGS_FROM_ORIGINAL) { + if (KEEP_ORIGINAL_BUGS) { tourists += rallods } else { tourists = abs(v1 - v2) From d16cc8d6d9f21053a37ae4a89555b5a8ed6448aa Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Wed, 5 Jan 2022 02:17:22 +1100 Subject: [PATCH 549/749] Warning for suicide references --- 76_Russian_Roulette/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/76_Russian_Roulette/README.md b/76_Russian_Roulette/README.md index cf1b64fc..5ec8148e 100644 --- a/76_Russian_Roulette/README.md +++ b/76_Russian_Roulette/README.md @@ -4,6 +4,8 @@ In this game, you are given by the computer a revolver loaded with one bullet an Tom Adametx wrote this program while a student at Curtis Jr. High School in Sudbury, Massachusetts. +⚠️ This game includes EXPLICT references to suicide, and should not be included in most distributions, especially considering the extreme simplicity of the program. + --- As published in Basic Computer Games (1978): From a05a1fedf37285e5e087138f3a529a2879d7f888 Mon Sep 17 00:00:00 2001 From: "christopher.millward" Date: Tue, 4 Jan 2022 10:40:59 -0500 Subject: [PATCH 550/749] War refactor and cleanup --- 94_War/javascript/war.js | 228 ++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 100 deletions(-) diff --git a/94_War/javascript/war.js b/94_War/javascript/war.js index eb74fb0c..bdc935bc 100644 --- a/94_War/javascript/war.js +++ b/94_War/javascript/war.js @@ -1,60 +1,95 @@ // WAR // -// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess) +// Original conversion from BASIC to Javascript by Oscar Toledo G. (nanochess) // -function print(str) -{ +function print(str) { document.getElementById("output").appendChild(document.createTextNode(str)); } -function input() -{ - var input_element; - var input_str; - - return new Promise(function (resolve) { - input_element = document.createElement("INPUT"); - - print("? "); - input_element.setAttribute("type", "text"); - input_element.setAttribute("length", "50"); - document.getElementById("output").appendChild(input_element); - input_element.focus(); - input_str = undefined; - input_element.addEventListener("keydown", function (event) { - if (event.keyCode == 13) { - input_str = input_element.value; - document.getElementById("output").removeChild(input_element); - print(input_str); - print("\n"); - resolve(input_str); - } - }); - }); -} - -function tab(space) -{ - var str = ""; - while (space-- > 0) +function tab(space) { + let str = ""; + while (space-- > 0) { str += " "; + } return str; } -var a = [, "S-2","H-2","C-2","D-2","S-3","H-3","C-3","D-3", - "S-4","H-4","C-4","D-4","S-5","H-5","C-5","D-5", - "S-6","H-6","C-6","D-6","S-7","H-7","C-7","D-7", - "S-8","H-8","C-8","D-8","S-9","H-9","C-9","D-9", - "S-10","H-10","C-10","D-10","S-J","H-J","C-J","D-J", - "S-Q","H-Q","C-Q","D-Q","S-K","H-K","C-K","D-K", - "S-A","H-A","C-A","D-A"]; +function input() { + return new Promise(function (resolve) { + const input_element = document.createElement("INPUT"); -var l = []; + print("? "); + input_element.setAttribute("type", "text"); + input_element.setAttribute("length", "50"); + document.getElementById("output").appendChild(input_element); + input_element.focus(); + input_element.addEventListener("keydown", function (event) { + if (event.keyCode == 13) { + const input_str = input_element.value; + document.getElementById("output").removeChild(input_element); + print(input_str); + print("\n"); + resolve(input_str); + } + }); + }); +} -// Main control section -async function main() -{ +async function askYesOrNo(question) { + while (1) { + print(question); + const str = await input(); + if (str == "YES") { + return true; + } + else if (str == "NO") { + return false; + } + else { + print("YES OR NO, PLEASE. "); + } + } +} + +async function askAboutInstructions() { + const playerWantsInstructions = await askYesOrNo("DO YOU WANT DIRECTIONS"); + if (playerWantsInstructions) { + print("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD\n"); + print("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO\n"); + print("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n"); + } + print("\n"); + print("\n"); +} + +function createGameDeck(cards, gameSize) { + const deck = []; + const deckSize = cards.length; + for (let j = 0; j < gameSize; j++) { + let card; + + // Compute a new card index until we find one that isn't already in the new deck + do { + card = Math.floor(deckSize * Math.random()); + } while (deck.includes(card)); + deck[j] = card + } + return deck; +} + +function computeCardValue(cardIndex) { + return Math.floor(cardIndex / 4); +} + +function printGameOver(playerScore, computerScore) { + print("\n"); + print("\n"); + print(`WE HAVE RUN OUT OF CARDS. FINAL SCORE: YOU: ${playerScore} THE COMPUTER: ${computerScore}\n`); + print("\n"); +} + +function printTitle() { print(tab(33) + "WAR\n"); print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"); print("\n"); @@ -62,72 +97,65 @@ async function main() print("\n"); print("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#\n"); print("AS S-7 FOR SPADE 7. "); - while (1) { - print("DO YOU WANT DIRECTIONS"); - str = await input(); - if (str == "YES") { - print("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD\n"); - print("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO\n"); - print("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n"); - break; - } - if (str == "NO") - break; - print("YES OR NO, PLEASE. "); - } - print("\n"); +} + +function printCards(playerCard, computerCard) { print("\n"); + print(`YOU: ${playerCard}\tCOMPUTER: ${computerCard}\n`); +} + +const cards = [ + "S-2", "H-2", "C-2", "D-2", + "S-3", "H-3", "C-3", "D-3", + "S-4", "H-4", "C-4", "D-4", + "S-5", "H-5", "C-5", "D-5", + "S-6", "H-6", "C-6", "D-6", + "S-7", "H-7", "C-7", "D-7", + "S-8", "H-8", "C-8", "D-8", + "S-9", "H-9", "C-9", "D-9", + "S-10", "H-10", "C-10", "D-10", + "S-J", "H-J", "C-J", "D-J", + "S-Q", "H-Q", "C-Q", "D-Q", + "S-K", "H-K", "C-K", "D-K", + "S-A", "H-A", "C-A", "D-A" +]; + +// Main control section +async function main() { + printTitle(); + await askAboutInstructions(); - a1 = 0; - b1 = 0; - p = 0; + let computerScore = 0; + let playerScore = 0; // Generate a random deck - for (j = 1; j <= 52; j++) { - do { - l[j] = Math.floor(52 * Math.random()) + 1; - for (k = 1; k < j; k++) { - if (l[k] == l[j]) // Already in deck? - break; - } - } while (j != 1 && k < j) ; - } - l[j] = 0; // Mark the end of the deck + const gameSize = 4; + const deck = createGameDeck(cards, gameSize); + let shouldContinuePlaying = true; - while (1) { - m1 = l[++p]; // Take a card - m2 = l[++p]; // Take a card - print("\n"); - print("YOU: " + a[m1] + "\tCOMPUTER: " + a[m2] + "\n"); - n1 = Math.floor((m1 - 0.5) / 4); - n2 = Math.floor((m2 - 0.5) / 4); - if (n1 < n2) { - a1++; - print("THE COMPUTER WINS!!! YOU HAVE " + b1 + " AND THE COMPUTER HAS " + a1 + "\n"); - } else if (n1 > n2) { - b1++; - print("YOU WIN. YOU HAVE " + b1 + " AND THE COMPUTER HAS " + a1 + "\n"); + while (deck.length > 0 && shouldContinuePlaying) { + const m1 = deck.shift(); // Take a card + const m2 = deck.shift(); // Take a card + printCards(cards[m1], cards[m2]); + + const playerCardValue = computeCardValue(m1); + const computerCardValue = computeCardValue(m2); + if (playerCardValue < computerCardValue) { + computerScore++; + print("THE COMPUTER WINS!!! YOU HAVE " + playerScore + " AND THE COMPUTER HAS " + computerScore + "\n"); + } else if (playerCardValue > computerCardValue) { + playerScore++; + print("YOU WIN. YOU HAVE " + playerScore + " AND THE COMPUTER HAS " + computerScore + "\n"); } else { print("TIE. NO SCORE CHANGE.\n"); } - if (l[p + 1] == 0) { - print("\n"); - print("\n"); - print("WE HAVE RUN OUT OF CARDS. FINAL SCORE: YOU: " + b1 + " THE COMPUTER: " + a1 + "\n"); - print("\n"); - break; + + if (deck.length === 0) { + printGameOver(playerScore, computerScore); } - while (1) { - print("DO YOU WANT TO CONTINUE"); - str = await input(); - if (str == "YES") - break; - if (str == "NO") - break; - print("YES OR NO, PLEASE. "); + else { + shouldContinuePlaying = await askYesOrNo("DO YOU WANT TO CONTINUE"); } - if (str == "NO") - break; } print("THANKS FOR PLAYING. IT WAS FUN.\n"); print("\n"); From fe6ff50d2f5d18c32dc71548b2b969de67e3ada8 Mon Sep 17 00:00:00 2001 From: "christopher.millward" Date: Tue, 4 Jan 2022 10:44:48 -0500 Subject: [PATCH 551/749] Updated documentation and used push() --- 94_War/javascript/war.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/94_War/javascript/war.js b/94_War/javascript/war.js index bdc935bc..965294a6 100644 --- a/94_War/javascript/war.js +++ b/94_War/javascript/war.js @@ -73,7 +73,7 @@ function createGameDeck(cards, gameSize) { do { card = Math.floor(deckSize * Math.random()); } while (deck.includes(card)); - deck[j] = card + deck.push(card); } return deck; } @@ -129,7 +129,7 @@ async function main() { let playerScore = 0; // Generate a random deck - const gameSize = 4; + const gameSize = cards.length; // Number of cards to shuffle into the game deck. Can be <= cards.length. const deck = createGameDeck(cards, gameSize); let shouldContinuePlaying = true; From a6957caed0aba39c52d4d2e520aa7abf9926fdea Mon Sep 17 00:00:00 2001 From: "christopher.millward" Date: Tue, 4 Jan 2022 10:46:44 -0500 Subject: [PATCH 552/749] Removed last of the single-letter variables --- 94_War/javascript/war.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/94_War/javascript/war.js b/94_War/javascript/war.js index 965294a6..ededa1ed 100644 --- a/94_War/javascript/war.js +++ b/94_War/javascript/war.js @@ -134,12 +134,12 @@ async function main() { let shouldContinuePlaying = true; while (deck.length > 0 && shouldContinuePlaying) { - const m1 = deck.shift(); // Take a card - const m2 = deck.shift(); // Take a card - printCards(cards[m1], cards[m2]); + const playerCard = deck.shift(); // Take a card + const computerCard = deck.shift(); // Take a card + printCards(cards[playerCard], cards[computerCard]); - const playerCardValue = computeCardValue(m1); - const computerCardValue = computeCardValue(m2); + const playerCardValue = computeCardValue(playerCard); + const computerCardValue = computeCardValue(computerCard); if (playerCardValue < computerCardValue) { computerScore++; print("THE COMPUTER WINS!!! YOU HAVE " + playerScore + " AND THE COMPUTER HAS " + computerScore + "\n"); From 05f597b12c1518da66b104fca8875aaf6ad00bd9 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Tue, 4 Jan 2022 14:37:22 -0300 Subject: [PATCH 553/749] Added Calendar first implementation it has some formatting problems --- 21_Calendar/python/calendar.py | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 21_Calendar/python/calendar.py diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py new file mode 100644 index 00000000..6f3cb191 --- /dev/null +++ b/21_Calendar/python/calendar.py @@ -0,0 +1,69 @@ + +def calendar(weekday, leap_year): + """ + function to print a year's calendar. + + input: + _weekday_: int - the initial day of the week (0=SUN, -1=MON, -2=TUES...) + _leap_year_: bool - indicates if the year is a leap year + """ + months_days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + days = ' S M T W T F S' + sep = "*" * 59 + years_day = 365 + d = weekday + + if leap_year: + months_days[2] = 29 + years_day = 366 + + months_names = [" JANUARY ", + " FEBRUARY", + " MARCH ", + " APRIL ", + " MAY ", + " JUNE ", + " JULY ", + " AUGUST ", + "SEPTEMBER", + " OCTOBER ", + " NOVEMBER", + " DECEMBER"] + + print(" "*32 + "CALENDAR") + print(" "*15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + + days_count = 0 # S in the original program + + # main loop + for n in range(1, 13): + days_count += months_days[n-1] + print("** {} ****************** {} ****************** {} **".format(days_count, + months_names[n-1], years_day-days_count)) + print(days) + print(sep) + print("\n") + + for w in range(1, 7): + print("\n") + for g in range(1, 8): + d += 1 + d2 = d - days_count + + if d2 > months_days[n]: + break + + if d2 > 0: + print("{}".format(d2),end=' ') + else: + print("{}".format(''),end=' ') + if d2 >= months_days[n]: + break + + if d2 > months_days[n]: + d -= g + + print("\n") + +if __name__ == "__main__": + calendar(-1, False) \ No newline at end of file From 1b81994c4a00ffc2b60e5d70813482bbd557fa47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= Date: Tue, 4 Jan 2022 17:59:28 +0000 Subject: [PATCH 554/749] Add Perl version of 25_Chief --- 25_Chief/perl/chief.pl | 69 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 25_Chief/perl/chief.pl diff --git a/25_Chief/perl/chief.pl b/25_Chief/perl/chief.pl new file mode 100644 index 00000000..d3462514 --- /dev/null +++ b/25_Chief/perl/chief.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +print ' ' x 30 . "CHIEF\n"; +print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; +print "\n\n\n"; + +print "I AM CHIEF NUMBERS FREEK, THE GREAT INDIAN MATH GOD.\n"; +print "ARE YOU READY TO TAKE THE TEST YOU CALLED ME OUT FOR?\n"; + +chomp( my $A = uc ); +print "SHUT UP, PALE FACE WITH WISE TONGUE.\n" unless ( $A eq 'YES' ); + +print " TAKE A NUMBER AND ADD 3. DIVIDE THIS NUMBER BY 5 AND\n"; +print "MULTIPLY BY 8. DIVIDE BY 5 AND ADD THE SAME. SUBTRACT 1.\n"; +print " WHAT DO YOU HAVE?\n"; + +chomp( my $B = ); +my $C = ( $B + 1 - 5 ) * 5 / 8 * 5 - 3; + +print "I BET YOUR NUMBER WAS $C. AM I RIGHT?\n"; + +chomp( my $D = uc ); +if ( $D eq 'YES' ) { + print "BYE!!!\n"; + exit; +} + +print "WHAT WAS YOUR ORIGINAL NUMBER?\n"; + +chomp( my $K = ); +my $F = $K + 3; +my $G = $F / 5; +my $H = $G * 8; +my $I = $H / 5 + 5; +my $J = $I - 1; + +print "SO YOU THINK YOU'RE SO SMART, EH?\n"; +print "NOW WATCH.\n"; +print "$K PLUS 3 EQUALS $F. THIS DIVIDED BY 5 EQUALS $G;\n"; +print "THIS TIMES 8 EQUALS $H. IF WE DIVIDE BY 5 AND ADD 5,\n"; +print "WE GET $I , WHICH, MINUS 1, EQUALS $J.\n"; +print "NOW DO YOU BELIEVE ME?\n"; + +chomp( my $Z = uc ); +if ( $Z eq 'YES' ) { + print "BYE!!!\n"; + exit; +} + +print "YOU HAVE MADE ME MAD!!!\n"; +print "THERE MUST BE A GREAT LIGHTNING BOLT!\n\n\n"; + +for my $i ( reverse 22 .. 30 ) { + print ' ' x $i . "X X\n"; +} +print ' ' x 21 . "X XXX\n"; +print ' ' x 20 . "X X\n"; +print ' ' x 19 . "XX X\n"; +for my $i ( reverse 13 .. 20 ) { + print ' ' x $i . "X X\n"; +} +print ' ' x 12 . "XX\n"; +print ' ' x 11 . "X\n"; +print ' ' x 10 . "*\n"; +print "\n#########################\n\n"; +print "I HOPE YOU BELIEVE ME NOW, FOR YOUR SAKE!!\n"; From a8f0bb10c6fe8acfcfb5c5cb59fd35370292d566 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Tue, 4 Jan 2022 15:10:08 -0300 Subject: [PATCH 555/749] formatting text updated --- 21_Calendar/python/calendar.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py index 6f3cb191..6c803771 100644 --- a/21_Calendar/python/calendar.py +++ b/21_Calendar/python/calendar.py @@ -8,7 +8,7 @@ def calendar(weekday, leap_year): _leap_year_: bool - indicates if the year is a leap year """ months_days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] - days = ' S M T W T F S' + days = 'S M T W T F S\n' sep = "*" * 59 years_day = 365 d = weekday @@ -32,17 +32,16 @@ def calendar(weekday, leap_year): print(" "*32 + "CALENDAR") print(" "*15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - + print("\n"*11) days_count = 0 # S in the original program # main loop for n in range(1, 13): days_count += months_days[n-1] - print("** {} ****************** {} ****************** {} **".format(days_count, + print("** {} ****************** {} ****************** {} **\n".format(days_count, months_names[n-1], years_day-days_count)) print(days) print(sep) - print("\n") for w in range(1, 7): print("\n") @@ -54,9 +53,13 @@ def calendar(weekday, leap_year): break if d2 > 0: - print("{}".format(d2),end=' ') + if d2 < 10: + print(" {}".format(d2), end=' ') + else: + print("{}".format(d2), end=' ') else: - print("{}".format(''),end=' ') + print("{}".format(' '), end=' ') + if d2 >= months_days[n]: break @@ -65,5 +68,6 @@ def calendar(weekday, leap_year): print("\n") + if __name__ == "__main__": - calendar(-1, False) \ No newline at end of file + calendar(-6, False) From 873ca419e1846ab5e49e350f181a408875eb51fb Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Tue, 4 Jan 2022 15:12:41 -0300 Subject: [PATCH 556/749] formatting logic updated --- 21_Calendar/python/calendar.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py index 6c803771..c90b1b62 100644 --- a/21_Calendar/python/calendar.py +++ b/21_Calendar/python/calendar.py @@ -39,7 +39,7 @@ def calendar(weekday, leap_year): for n in range(1, 13): days_count += months_days[n-1] print("** {} ****************** {} ****************** {} **\n".format(days_count, - months_names[n-1], years_day-days_count)) + months_names[n-1], years_day-days_count)) print(days) print(sep) @@ -52,13 +52,12 @@ def calendar(weekday, leap_year): if d2 > months_days[n]: break - if d2 > 0: - if d2 < 10: - print(" {}".format(d2), end=' ') - else: - print("{}".format(d2), end=' ') - else: + if d2 <= 0: print("{}".format(' '), end=' ') + elif d2 < 10: + print(" {}".format(d2), end=' ') + else: + print("{}".format(d2), end=' ') if d2 >= months_days[n]: break From 6517975e250a0fa4f3d84936498877a5dd6a0f24 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Tue, 4 Jan 2022 15:15:02 -0300 Subject: [PATCH 557/749] Updated formatting to look like the original program --- 21_Calendar/python/calendar.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py index c90b1b62..b59d09f4 100644 --- a/21_Calendar/python/calendar.py +++ b/21_Calendar/python/calendar.py @@ -58,6 +58,7 @@ def calendar(weekday, leap_year): print(" {}".format(d2), end=' ') else: print("{}".format(d2), end=' ') + print() if d2 >= months_days[n]: break @@ -67,6 +68,8 @@ def calendar(weekday, leap_year): print("\n") + print("\n") + if __name__ == "__main__": calendar(-6, False) From 9b44692b8ccaa3fca3dee78781b006ce67b660ec Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Tue, 4 Jan 2022 15:31:16 -0300 Subject: [PATCH 558/749] Added parse function for starting day of the week of the year and boolean to check if it's a leap year structured code --- 21_Calendar/python/calendar.py | 56 +++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py index b59d09f4..63c2741f 100644 --- a/21_Calendar/python/calendar.py +++ b/21_Calendar/python/calendar.py @@ -1,4 +1,46 @@ +def parse_input(): + """ + function to parse input for weekday and leap year boolean + """ + + days_mapping = { + "sunday": 0, + "monday": -1, + "tuesday": -2, + "wednesday": -3, + "thursday": -4, + "friday": -5, + "saturday": -6 + } + + day = 0 + leap_day = False + + correct_day_input = False + while not correct_day_input: + weekday = input("INSERT THE STARTING DAY OF THE WEEK OF THE YEAR:") + + for day_k in days_mapping.keys(): + if weekday.lower() in day_k: + day = days_mapping[day_k] + correct_day_input = True + break + + while True: + leap = input("IS IT A LEAP YEAR?:") + + if 'y' in leap.lower(): + leap_day = True + break + + if 'n' in leap.lower(): + leap_day = False + break + + return day, leap_day + + def calendar(weekday, leap_year): """ function to print a year's calendar. @@ -30,9 +72,6 @@ def calendar(weekday, leap_year): " NOVEMBER", " DECEMBER"] - print(" "*32 + "CALENDAR") - print(" "*15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print("\n"*11) days_count = 0 # S in the original program # main loop @@ -71,5 +110,14 @@ def calendar(weekday, leap_year): print("\n") +def main(): + print(" "*32 + "CALENDAR") + print(" "*15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print("\n"*11) + + day, leap_year = parse_input() + calendar(day, leap_year) + + if __name__ == "__main__": - calendar(-6, False) + main() From f673a3740f0bac5552e9359f8a7072e759558c69 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Tue, 4 Jan 2022 15:45:12 -0300 Subject: [PATCH 559/749] Added porting notes and original program commentary --- 21_Calendar/python/calendar.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py index 63c2741f..6f3f572b 100644 --- a/21_Calendar/python/calendar.py +++ b/21_Calendar/python/calendar.py @@ -1,3 +1,24 @@ +######################################################## +# Calendar +# +# From: BASIC Computer Games (1978) +# Edited by David Ahl# +# +# This program prints out a calendar +# for any year. You must specify the +# starting day of the week of the year in +# statement 130. (Sunday(0), Monday +# (-1), Tuesday(-2), etc.) You can determine +# this by using the program WEEKDAY. +# You must also make two changes +# for leap years in statement 360 and 620. +# The program listing describes the necessary +# changes. Running the program produces a +# nice 12-month calendar. +# The program was written by Geofrey +# Chase of the Abbey, Portsmouth, Rhode Island. +# +######################################################## def parse_input(): """ @@ -121,3 +142,15 @@ def main(): if __name__ == "__main__": main() + +######################################################## +# +######################################################## +# +# Porting notes: +# +# It has been added an input at the beginning of the +# program so the user can specify the first day of the +# week of the year and if the year is leap or not. +# +######################################################## From 89ffbe6c6d0070f91523618aecc9f5f128c69001 Mon Sep 17 00:00:00 2001 From: a2wd Date: Tue, 4 Jan 2022 19:51:10 +0100 Subject: [PATCH 560/749] Added instruction on how to run the games --- HOW_TO_RUN_THE_GAMES.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 HOW_TO_RUN_THE_GAMES.md diff --git a/HOW_TO_RUN_THE_GAMES.md b/HOW_TO_RUN_THE_GAMES.md new file mode 100644 index 00000000..e69de29b From 40935505006bea529956b5e17e8708b7f48c3e6e Mon Sep 17 00:00:00 2001 From: Alito Date: Tue, 4 Jan 2022 19:57:29 +0100 Subject: [PATCH 561/749] Updated HOW_TO_RUN_THE_GAMES.md Added a new line to improve formatting around the note on the python environments. --- HOW_TO_RUN_THE_GAMES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HOW_TO_RUN_THE_GAMES.md b/HOW_TO_RUN_THE_GAMES.md index 6de43c98..96533226 100644 --- a/HOW_TO_RUN_THE_GAMES.md +++ b/HOW_TO_RUN_THE_GAMES.md @@ -67,6 +67,7 @@ The python translations can be run from the command line by using the `py` inter * 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/). @@ -81,4 +82,4 @@ If you don't already have a ruby interpreter, you can download it from the [ruby ## vbnet -Follow the same steps as for the [csharp](#csharp) translations. This can be run with `dotnet` or `Visual Studio`. \ No newline at end of file +Follow the same steps as for the [csharp](#csharp) translations. This can be run with `dotnet` or `Visual Studio`. From 990eb9915cc2a09e2880b7c4a51138c537b6bc58 Mon Sep 17 00:00:00 2001 From: Alito Date: Tue, 4 Jan 2022 19:58:48 +0100 Subject: [PATCH 562/749] Updated HOW_TO_RUN_THE_GAMES.md Fixed a typo (missing 'c' in the ruby project link text). --- HOW_TO_RUN_THE_GAMES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HOW_TO_RUN_THE_GAMES.md b/HOW_TO_RUN_THE_GAMES.md index 96533226..44d82e98 100644 --- a/HOW_TO_RUN_THE_GAMES.md +++ b/HOW_TO_RUN_THE_GAMES.md @@ -74,7 +74,7 @@ You can manage and use different versions of python with [pip](https://pypi.org/ ## ruby -If you don't already have a ruby interpreter, you can download it from the [ruby projet site](https://www.ruby-lang.org/en/). +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. From 75cf4767f020f16c054ac680ccbc83db3be5b3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= Date: Tue, 4 Jan 2022 20:20:00 +0000 Subject: [PATCH 563/749] Update aceyducey.pl --- 01_Acey_Ducey/perl/aceyducey.pl | 123 ++++++++++++++------------------ 1 file changed, 53 insertions(+), 70 deletions(-) diff --git a/01_Acey_Ducey/perl/aceyducey.pl b/01_Acey_Ducey/perl/aceyducey.pl index e2de13df..d4dfb2c2 100755 --- a/01_Acey_Ducey/perl/aceyducey.pl +++ b/01_Acey_Ducey/perl/aceyducey.pl @@ -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 = ; - 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 = ); - 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 = ; - 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 ); - return $keepGoing; + if ( $input eq 'Y' ) { + return 1; + } + elsif ( $input eq 'N' ) { + return 0; + } + else { + redo YESNO; + } + } } From cf9c2328b3ca8b7b1ae05282f3a9ef1d7279e503 Mon Sep 17 00:00:00 2001 From: Eric S Weilnau Date: Tue, 4 Jan 2022 18:38:07 -0500 Subject: [PATCH 564/749] Format external links --- 01_Acey_Ducey/README.md | 3 ++- 24_Chemist/README.md | 3 ++- 43_Hammurabi/README.md | 6 +++--- 84_Super_Star_Trek/README.md | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/01_Acey_Ducey/README.md b/01_Acey_Ducey/README.md index 3434eb8e..77ff8621 100644 --- a/01_Acey_Ducey/README.md +++ b/01_Acey_Ducey/README.md @@ -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 diff --git a/24_Chemist/README.md b/24_Chemist/README.md index 95db3f66..b93c1431 100644 --- a/24_Chemist/README.md +++ b/24_Chemist/README.md @@ -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 diff --git a/43_Hammurabi/README.md b/43_Hammurabi/README.md index c92b7ee3..c02219b1 100644 --- a/43_Hammurabi/README.md +++ b/43_Hammurabi/README.md @@ -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 diff --git a/84_Super_Star_Trek/README.md b/84_Super_Star_Trek/README.md index 4a96f528..77fae3d8 100644 --- a/84_Super_Star_Trek/README.md +++ b/84_Super_Star_Trek/README.md @@ -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 From f7b4b999dddf1066d91844b1855e0b228213aefb Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Wed, 5 Jan 2022 01:51:34 +0100 Subject: [PATCH 565/749] D version of the word game. --- 96_Word/d/.gitignore | 2 ++ 96_Word/d/README.md | 15 ++++++++ 96_Word/d/word.d | 85 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 96_Word/d/.gitignore create mode 100644 96_Word/d/README.md create mode 100644 96_Word/d/word.d diff --git a/96_Word/d/.gitignore b/96_Word/d/.gitignore new file mode 100644 index 00000000..d969f6b2 --- /dev/null +++ b/96_Word/d/.gitignore @@ -0,0 +1,2 @@ +*.exe +*.obj diff --git a/96_Word/d/README.md b/96_Word/d/README.md new file mode 100644 index 00000000..764cb141 --- /dev/null +++ b/96_Word/d/README.md @@ -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. diff --git a/96_Word/d/word.d b/96_Word/d/word.d new file mode 100644 index 00000000..6f4d46d6 --- /dev/null +++ b/96_Word/d/word.d @@ -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; +} From 5263ee6ba9eed38009724014098f9b9fe4baadc7 Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Tue, 4 Jan 2022 22:12:28 -0600 Subject: [PATCH 566/749] Initial commit --- 44_Hangman/perl/hangman.pl | 223 +++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100755 44_Hangman/perl/hangman.pl diff --git a/44_Hangman/perl/hangman.pl b/44_Hangman/perl/hangman.pl new file mode 100755 index 00000000..e2aca815 --- /dev/null +++ b/44_Hangman/perl/hangman.pl @@ -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,@L,$board,@guessedLetters,$guesses,$hangCount); +my($guess,%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 ', + ); + $guesses = 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($guess = ); + # 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; + ++$guesses; + + # 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 = ); + 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", $guesses, ($guesses == 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 = ); + 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 +} From 6e3da5b1a1c79b24bac5619ee9f3cd74edd7c6cc Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Tue, 4 Jan 2022 22:14:49 -0600 Subject: [PATCH 567/749] Removal of unused var --- 44_Hangman/perl/hangman.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/44_Hangman/perl/hangman.pl b/44_Hangman/perl/hangman.pl index e2aca815..aadf631b 100755 --- a/44_Hangman/perl/hangman.pl +++ b/44_Hangman/perl/hangman.pl @@ -17,7 +17,7 @@ my(@WORDS) = qw( MAGISTRATE ERRONEOUSLY LOUDSPEAKER PHYTOTOXIC MATRIMONIAL PARASYMPATHOMIMETIC THIGMOTROPISM ); -my(@PIC,@L,$board,@guessedLetters,$guesses,$hangCount); +my(@PIC,$board,@guessedLetters,$guesses,$hangCount); my($guess,%GUESSED); # Subroutines defined here. From daab84dbd55d623c07059bc3f85fccc011174aad Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Tue, 4 Jan 2022 22:18:09 -0600 Subject: [PATCH 568/749] Rename some vars to be more helpful --- 44_Hangman/perl/hangman.pl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/44_Hangman/perl/hangman.pl b/44_Hangman/perl/hangman.pl index aadf631b..45a6da9b 100755 --- a/44_Hangman/perl/hangman.pl +++ b/44_Hangman/perl/hangman.pl @@ -17,8 +17,8 @@ my(@WORDS) = qw( MAGISTRATE ERRONEOUSLY LOUDSPEAKER PHYTOTOXIC MATRIMONIAL PARASYMPATHOMIMETIC THIGMOTROPISM ); -my(@PIC,$board,@guessedLetters,$guesses,$hangCount); -my($guess,%GUESSED); +my(@PIC,$board,@guessedLetters,$guessCount,$hangCount); +my(%GUESSED); # Subroutines defined here. @@ -41,7 +41,7 @@ sub init_variables { 'X ', 'X ', ); - $guesses = 0; %GUESSED = (); + $guessCount = 0; %GUESSED = (); $hangCount = 0; } @@ -83,7 +83,7 @@ PLAY: while (1) { printf("\n\n%s\n", $board); print "What is your guess for a letter ? "; - chomp($guess = ); + chomp(my $guess = ); # The %GUESSED hash allows us to quickly identify # letters that have already been guessed if ($GUESSED{lc $guess}) { @@ -94,7 +94,7 @@ PLAY: while (1) { # save the guessed letter push @guessedLetters, $guess; $GUESSED{lc $guess} = 1; - ++$guesses; + ++$guessCount; # now look for the letter in the $thisWord var # and put it into the $board var wherever it @@ -123,7 +123,7 @@ PLAY: while (1) { # Go to the next iteration of the GUESS loop next GUESS; } - printf("Right! It took you %d %s!\n", $guesses, ($guesses == 1 ? 'guess' : 'guesses')); + 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 From f2e7381878c198b467093eef1deac7c3bc3b6e88 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 20:44:47 -0800 Subject: [PATCH 569/749] first very ugly port. --- 81_Splat/java/src/Splat.java | 277 +++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 81_Splat/java/src/Splat.java diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java new file mode 100644 index 00000000..0930dcc2 --- /dev/null +++ b/81_Splat/java/src/Splat.java @@ -0,0 +1,277 @@ +import java.util.Arrays; +import java.util.Random; +import java.util.Scanner; + +public class Splat { + private final Random random = new Random(); + private final Scanner scanner = new Scanner(System.in); + + public static void main(String[] args) { + new Splat().run(); + } + + public void run() { + 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."); + + float[] Arr = new float[42]; + Arrays.fill(Arr, 0.0f); + int K = 0; + int K1 = 0; + while (true) { + + System.out.print("\n\n"); + float V = 0.0f; + float A = 0.0f; + int N = 0; + int M = 0; + int D1 = (int) (9001.0f * random.nextFloat() + 1000); + D1 = 2937; //debug fixme + + System.out.print("SELECT YOUR OWN TERMINAL VELOCITY (YES OR NO) "); + float V1; + while (true) { + String A1 = scanner.next(); + if (A1.equals("NO")) { + V1 = (int) (1000 * random.nextFloat()); + System.out.printf("OK. TERMINAL VELOCITY = %d MI/HR\n", (int) V1); + break; + } + if (!A1.equals("YES")) { + System.out.print("YES OR NO "); + continue; + } + System.out.print("WHAT TERMINAL VELOCITY (MI/HR) "); + V1 = scanner.nextInt(); + break; + } + V1 = V1 * (5280.0f / 3600.0f); + V = V1 + ((V1 * random.nextFloat()) / 20.0f) - ((V1 * random.nextFloat()) / 20.0f); + System.out.print("WANT TO SELECT ACCELERATION DUE TO GRAVITY (YES OR NO) "); + float A2; + while (true) { + String B1 = scanner.next(); + if (B1.equals("NO")) { + switch (random.nextInt(10)) { + case 0: + System.out.println("FINE. YOU'RE ON MERCURY. ACCELERATION=12.2 FT/SEC/SEC."); + A2 = 12.2f; + break; + case 1: + System.out.println("ALL RIGHT. YOU'RE ON VENUS. ACCELERATION=28.3 FT/SEC/SEC."); + A2 = 28.3f; + break; + case 2: + System.out.println("THEN YOU'RE ON EARTH. ACCELERATION=32.16 FT/SEC/SEC."); + A2 = 32.16f; + break; + case 3: + System.out.println("FINE. YOU'RE ON THE MOON. ACCELERATION=5.15 FT/SEC/SEC."); + A2 = 5.15f; + break; + case 4: + System.out.println("ALL RIGHT. YOU'RE ON MARS. ACCELERATION=12.5 FT/SEC/SEC."); + A2 = 12.5f; + break; + case 5: + System.out.println("THEN YOU'RE ON JUPITER. ACCELERATION=85.2 FT/SEC/SEC."); + A2 = 85.2f; + break; + case 6: + System.out.println("FINE. YOU'RE ON SATURN. ACCELERATION=37.6 FT/SEC/SEC."); + A2 = 37.6f; + break; + case 7: + System.out.println("ALL RIGHT. YOU'RE ON URANUS. ACCELERATION=33.8 FT/SEC/SEC."); + A2 = 33.8f; + break; + case 8: + System.out.println("THEN YOU'RE ON NEPTUNE. ACCELERATION=39.6 FT/SEC/SEC."); + A2 = 39.6f; + break; + case 9: + System.out.println("FINE. YOU'RE ON THE SUN. ACCELERATION=896 FT/SEC/SEC."); + A2 = 896.0f; + break; + default: + throw new RuntimeException("Impossible. Will fix stupid switch statement later."); + } + break; + } + if (!B1.equals("YES")) { + System.out.print("YES OR NO "); + continue; + } + System.out.print("WHAT ACCELERATION (FT/SEC/SEC) "); + A2 = scanner.nextFloat(); + break; + } + A = A2 + ((A2 * random.nextFloat()) / 20.0f) - ((A2 * random.nextFloat()) / 20.0f); + System.out.println(); + System.out.printf(" ALTITUDE = %d FT\n", D1); + System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", V1); + System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", A2); + System.out.println("SET THE TIMER FOR YOUR FREEFALL."); + System.out.print("HOW MANY SECONDS "); + float T = scanner.nextFloat(); + System.out.println("HERE WE GO.\n"); + System.out.println("TIME (SEC) DIST TO FALL (FT)"); + System.out.println("========== ================="); + boolean splat = false; + boolean terminalReached = false; + float D = 0.0f; + for (float i = 0.0f; !splat && (i < T); i += T / 8) { + if (i > (V / A)) { + terminalReached = true; + System.out.printf("TERMINAL VELOCITY REACHED AT T PLUS %f SECONDS.\n", (V / A)); + for (i = i; i < T; i += T / 8) { + D = D1 - ((V * V / (2 * A)) + (V * (i - (V / A)))); +// System.out.printf(" ......................................tv %f\n", D); + if (D <= 0) { + splat = true; + break; + } + System.out.printf("%10.2f %f\n", i, D); + } + break; + } + D = D1 - ((A / 2) * i * i); +// System.out.printf(" ......................................debug %f\n", D); + if (D <= 0) { + splat = true; + break; + } + System.out.printf("%10.2f %f\n", i, D); + } + + if (!splat) { + + System.out.println("CHUTE OPEN"); + int J = 0; + for (J = 0; J < 42; J++) { + if (Arr[J] == 0) { + Arr[J] = D; + break; + } + K = K + 1; + if (D > Arr[J]) { + continue; + } + K1 = K1 + 1; + } + + if (J > 2) { + if (K - K1 <= 0.1 * K) { + System.out.printf("WOW! THAT'S SOME JUMPING. OF THE %d SUCCESSFUL JUMPS\n", K); + System.out.printf("BEFORE YOURS, ONLY %d OPENED THEIR CHUTES LOWER THAN\n", K - K1); + System.out.println("YOU DID."); + } else if (K - K1 <= 0.25 * K) { + System.out.printf("PRETTY GOOD! %d SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n", K); + System.out.printf("%d OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n", K - K1); + System.out.println("OPENED."); + } else if (K - K1 <= 0.5 * K) { + System.out.printf("NOT BAD. THERE HAVE BEEN %d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); + System.out.printf("YOU WERE BEATEN OUT BY %d OF THEM.\n", K - K1); + } else if (K - K1 <= 0.75 * K) { + System.out.printf("CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY %d IN THE\n", K - K1); + System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.", K); + } else if (K - K1 <= -0.9 * K) { + 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", K, K1); + System.out.println("BETTER THAN THE WORST. SHAPE UP!!!\n"); + } else { + System.out.printf("HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. %f SUCCESSFUL\n", K); + System.out.printf("JUMPS BEFORE YOURS AND YOU CAME IN NUMBER %d! GET WITH IT!\n", K - K1); + } + } else { + System.out.println("AMAZING!!! NOT BAD FOR YOUR "); + switch (J) { + case 0: + System.out.print("1ST "); + break; + case 1: + System.out.print("2ND "); + break; + case 2: + System.out.print("3RD "); + break; + } + System.out.println("SUCCESSFUL JUMP!!!"); + } + + + } else { + if (terminalReached) { + System.out.printf("%.2f SPLAT\n", (V / A) + ((D1 - (V * V / (2 * A))) / V)); + } else { + System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * D1 / A)); + + } + switch (random.nextInt(10)) { + case 0: + System.out.println("REQUIESCAT IN PACE."); + break; + case 1: + System.out.println("MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE."); + break; + case 2: + System.out.println("REST IN PEACE."); + break; + case 3: + System.out.println("SON-OF-A-GUN."); + break; + case 4: + System.out.println("#$%&&%!$"); + break; + case 5: + System.out.println("A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT."); + break; + case 6: + System.out.println("HMMM. SHOULD HAVE PICKED A SHORTER TIME."); + break; + case 7: + System.out.println("MUTTER. MUTTER. MUTTER."); + break; + case 8: + System.out.println("PUSHING UP DAISIES."); + break; + default: + System.out.println("EASY COME, EASY GO."); + + } + } + boolean chosen = false; + while (!chosen) { + System.out.print("DO YOU WANT TO PLAY AGAIN "); + String Z = scanner.next(); + if (Z.equals("YES")) { + break; + } + if (Z.equals("NO")) { + System.out.print("PLEASE "); + while (true) { + Z = scanner.next(); + if (Z.equals("YES")) { + chosen = true; + break; + } + if (Z.equals("NO")) { + System.out.println("SSSSSSSSSS."); + return; + } + System.out.print("YES OR NO "); + } + continue; + } else { + System.out.print("YES OR NO "); + } + } + + } + + } +} \ No newline at end of file From b899d6d5c508bfe9a746c64b9dbaad2496ac33dd Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 21:14:36 -0800 Subject: [PATCH 570/749] factor out planet enum --- 81_Splat/java/src/Splat.java | 86 +++++++++++++++++------------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 0930dcc2..c5c94a5d 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -30,7 +30,6 @@ public class Splat { int N = 0; int M = 0; int D1 = (int) (9001.0f * random.nextFloat() + 1000); - D1 = 2937; //debug fixme System.out.print("SELECT YOUR OWN TERMINAL VELOCITY (YES OR NO) "); float V1; @@ -56,50 +55,7 @@ public class Splat { while (true) { String B1 = scanner.next(); if (B1.equals("NO")) { - switch (random.nextInt(10)) { - case 0: - System.out.println("FINE. YOU'RE ON MERCURY. ACCELERATION=12.2 FT/SEC/SEC."); - A2 = 12.2f; - break; - case 1: - System.out.println("ALL RIGHT. YOU'RE ON VENUS. ACCELERATION=28.3 FT/SEC/SEC."); - A2 = 28.3f; - break; - case 2: - System.out.println("THEN YOU'RE ON EARTH. ACCELERATION=32.16 FT/SEC/SEC."); - A2 = 32.16f; - break; - case 3: - System.out.println("FINE. YOU'RE ON THE MOON. ACCELERATION=5.15 FT/SEC/SEC."); - A2 = 5.15f; - break; - case 4: - System.out.println("ALL RIGHT. YOU'RE ON MARS. ACCELERATION=12.5 FT/SEC/SEC."); - A2 = 12.5f; - break; - case 5: - System.out.println("THEN YOU'RE ON JUPITER. ACCELERATION=85.2 FT/SEC/SEC."); - A2 = 85.2f; - break; - case 6: - System.out.println("FINE. YOU'RE ON SATURN. ACCELERATION=37.6 FT/SEC/SEC."); - A2 = 37.6f; - break; - case 7: - System.out.println("ALL RIGHT. YOU'RE ON URANUS. ACCELERATION=33.8 FT/SEC/SEC."); - A2 = 33.8f; - break; - case 8: - System.out.println("THEN YOU'RE ON NEPTUNE. ACCELERATION=39.6 FT/SEC/SEC."); - A2 = 39.6f; - break; - case 9: - System.out.println("FINE. YOU'RE ON THE SUN. ACCELERATION=896 FT/SEC/SEC."); - A2 = 896.0f; - break; - default: - throw new RuntimeException("Impossible. Will fix stupid switch statement later."); - } + A2 = chooseRandomAcceleration(); break; } if (!B1.equals("YES")) { @@ -274,4 +230,44 @@ public class Splat { } } + + private float chooseRandomAcceleration() { + Planet planet = Planet.pickRandom(); + System.out.printf("%s. ACCELERATION=%.2f FT/SEC/SEC.\n", planet.getMessage(), planet.getAcceleration()); + return planet.getAcceleration(); + } + + enum Planet { + MERCURY("FINE. YOU'RE ON MERCURY", 12.2f), + VENUS("ALL RIGHT. YOU'RE ON VENUS", 28.3f), + EARTH("THEN YOU'RE ON EARTH", 32.16f), + MOON("FINE. YOU'RE ON THE MOON", 5.15f), + MARS("ALL RIGHT. YOU'RE ON MARS", 12.5f), + JUPITER("THEN YOU'RE ON JUPITER", 85.2f), + SATURN("FINE. YOU'RE ON SATURN", 37.6f), + URANUS("ALL RIGHT. YOU'RE ON URANUS", 33.8f), + NEPTUNE("THEN YOU'RE ON NEPTUNE", 39.6f), + SUN("FINE. YOU'RE ON THE SUN", 896.0f); + + 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)]; + } + + public String getMessage() { + return message; + } + + public float getAcceleration() { + return acceleration; + } + } } \ No newline at end of file From 22213547fc81233c2645c7014e60a2537a9a50ef Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 21:22:11 -0800 Subject: [PATCH 571/749] factor out askYesNo --- 81_Splat/java/src/Splat.java | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index c5c94a5d..3f44af2f 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -27,27 +27,18 @@ public class Splat { System.out.print("\n\n"); float V = 0.0f; float A = 0.0f; - int N = 0; - int M = 0; int D1 = (int) (9001.0f * random.nextFloat() + 1000); - System.out.print("SELECT YOUR OWN TERMINAL VELOCITY (YES OR NO) "); float V1; - while (true) { - String A1 = scanner.next(); - if (A1.equals("NO")) { - V1 = (int) (1000 * random.nextFloat()); - System.out.printf("OK. TERMINAL VELOCITY = %d MI/HR\n", (int) V1); - break; - } - if (!A1.equals("YES")) { - System.out.print("YES OR NO "); - continue; - } + if(askYesNo("SELECT YOUR OWN TERMINAL VELOCITY")){ System.out.print("WHAT TERMINAL VELOCITY (MI/HR) "); V1 = scanner.nextInt(); - break; } + else { + V1 = (int) (1000 * random.nextFloat()); + System.out.printf("OK. TERMINAL VELOCITY = %d MI/HR\n", (int) V1); + } + V1 = V1 * (5280.0f / 3600.0f); V = V1 + ((V1 * random.nextFloat()) / 20.0f) - ((V1 * random.nextFloat()) / 20.0f); System.out.print("WANT TO SELECT ACCELERATION DUE TO GRAVITY (YES OR NO) "); @@ -231,6 +222,18 @@ public class Splat { } + 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. ACCELERATION=%.2f FT/SEC/SEC.\n", planet.getMessage(), planet.getAcceleration()); From 9fba41771c254890d30b14cf343d4f6babc4b645 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 21:24:01 -0800 Subject: [PATCH 572/749] plug in yesno prompt for acceleration --- 81_Splat/java/src/Splat.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 3f44af2f..ba1496ca 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -41,22 +41,16 @@ public class Splat { V1 = V1 * (5280.0f / 3600.0f); V = V1 + ((V1 * random.nextFloat()) / 20.0f) - ((V1 * random.nextFloat()) / 20.0f); - System.out.print("WANT TO SELECT ACCELERATION DUE TO GRAVITY (YES OR NO) "); + float A2; - while (true) { - String B1 = scanner.next(); - if (B1.equals("NO")) { - A2 = chooseRandomAcceleration(); - break; - } - if (!B1.equals("YES")) { - System.out.print("YES OR NO "); - continue; - } + if(askYesNo("WANT TO SELECT ACCELERATION DUE TO GRAVITY")){ System.out.print("WHAT ACCELERATION (FT/SEC/SEC) "); A2 = scanner.nextFloat(); - break; } + else { + A2 = chooseRandomAcceleration(); + } + A = A2 + ((A2 * random.nextFloat()) / 20.0f) - ((A2 * random.nextFloat()) / 20.0f); System.out.println(); System.out.printf(" ALTITUDE = %d FT\n", D1); From c3a1b621b917aaa71966c18cbe64004924d36dfd Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 21:32:56 -0800 Subject: [PATCH 573/749] factor out intro and prompt messages --- 81_Splat/java/src/Splat.java | 69 ++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index ba1496ca..e4614fa8 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -11,12 +11,7 @@ public class Splat { } public void run() { - 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."); + showIntroduction(); float[] Arr = new float[42]; Arrays.fill(Arr, 0.0f); @@ -25,37 +20,18 @@ public class Splat { while (true) { System.out.print("\n\n"); - float V = 0.0f; - float A = 0.0f; int D1 = (int) (9001.0f * random.nextFloat() + 1000); - float V1; - if(askYesNo("SELECT YOUR OWN TERMINAL VELOCITY")){ - System.out.print("WHAT TERMINAL VELOCITY (MI/HR) "); - V1 = scanner.nextInt(); - } - else { - V1 = (int) (1000 * random.nextFloat()); - System.out.printf("OK. TERMINAL VELOCITY = %d MI/HR\n", (int) V1); - } + float terminalVelocity = promptTerminalVelocity(); + float V = terminalVelocity + ((terminalVelocity * random.nextFloat()) / 20.0f) - ((terminalVelocity * random.nextFloat()) / 20.0f); - V1 = V1 * (5280.0f / 3600.0f); - V = V1 + ((V1 * random.nextFloat()) / 20.0f) - ((V1 * random.nextFloat()) / 20.0f); + float gravitationalAcceleration = promptGravitationalAcceleration(); + float A = gravitationalAcceleration + ((gravitationalAcceleration * random.nextFloat()) / 20.0f) - ((gravitationalAcceleration * random.nextFloat()) / 20.0f); - float A2; - if(askYesNo("WANT TO SELECT ACCELERATION DUE TO GRAVITY")){ - System.out.print("WHAT ACCELERATION (FT/SEC/SEC) "); - A2 = scanner.nextFloat(); - } - else { - A2 = chooseRandomAcceleration(); - } - - A = A2 + ((A2 * random.nextFloat()) / 20.0f) - ((A2 * random.nextFloat()) / 20.0f); System.out.println(); System.out.printf(" ALTITUDE = %d FT\n", D1); - System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", V1); - System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", A2); + System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", terminalVelocity); + System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", gravitationalAcceleration); System.out.println("SET THE TIMER FOR YOUR FREEFALL."); System.out.print("HOW MANY SECONDS "); float T = scanner.nextFloat(); @@ -216,6 +192,37 @@ public class Splat { } + 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 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 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) { From eba6c07fd03cd2f08ec0b711a3289397ba3b4cf9 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 22:05:24 -0800 Subject: [PATCH 574/749] factor out initial jump conditions --- 81_Splat/java/src/Splat.java | 94 ++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index e4614fa8..67e278f8 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -3,7 +3,7 @@ import java.util.Random; import java.util.Scanner; public class Splat { - private final Random random = new Random(); + private static final Random random = new Random(); private final Scanner scanner = new Scanner(System.in); public static void main(String[] args) { @@ -19,19 +19,15 @@ public class Splat { int K1 = 0; while (true) { - System.out.print("\n\n"); - int D1 = (int) (9001.0f * random.nextFloat() + 1000); - - float terminalVelocity = promptTerminalVelocity(); - float V = terminalVelocity + ((terminalVelocity * random.nextFloat()) / 20.0f) - ((terminalVelocity * random.nextFloat()) / 20.0f); - - float gravitationalAcceleration = promptGravitationalAcceleration(); - float A = gravitationalAcceleration + ((gravitationalAcceleration * random.nextFloat()) / 20.0f) - ((gravitationalAcceleration * random.nextFloat()) / 20.0f); + InitialJumpConditions jump = buildInitialConditions(); + final float V = jump.getTerminalVelocity(); + final float A = jump.getGravitationalAcceleration(); System.out.println(); - System.out.printf(" ALTITUDE = %d FT\n", D1); - System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", terminalVelocity); - System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", gravitationalAcceleration); + System.out.printf(" ALTITUDE = %d FT\n", jump.getAltitude()); + System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", jump.getOriginalTerminalVelocity()); + System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", jump.getOriginalGravitationalAcceleration()); + System.out.println("SET THE TIMER FOR YOUR FREEFALL."); System.out.print("HOW MANY SECONDS "); float T = scanner.nextFloat(); @@ -42,12 +38,11 @@ public class Splat { boolean terminalReached = false; float D = 0.0f; for (float i = 0.0f; !splat && (i < T); i += T / 8) { - if (i > (V / A)) { + if (i > jump.getTimeOfTerminalAccelerationReached()) { terminalReached = true; - System.out.printf("TERMINAL VELOCITY REACHED AT T PLUS %f SECONDS.\n", (V / A)); + System.out.printf("TERMINAL VELOCITY REACHED AT T PLUS %f SECONDS.\n", jump.getTimeOfTerminalAccelerationReached()); for (i = i; i < T; i += T / 8) { - D = D1 - ((V * V / (2 * A)) + (V * (i - (V / A)))); -// System.out.printf(" ......................................tv %f\n", D); + D = jump.getAltitude() - ((V * V / (2 * A)) + (V * (i - (V / A)))); if (D <= 0) { splat = true; break; @@ -56,8 +51,7 @@ public class Splat { } break; } - D = D1 - ((A / 2) * i * i); -// System.out.printf(" ......................................debug %f\n", D); + D = jump.getAltitude() - ((A / 2) * i * i); if (D <= 0) { splat = true; break; @@ -123,9 +117,9 @@ public class Splat { } else { if (terminalReached) { - System.out.printf("%.2f SPLAT\n", (V / A) + ((D1 - (V * V / (2 * A))) / V)); + System.out.printf("%.2f SPLAT\n", (V / A) + ((jump.getAltitude() - (V * V / (2 * A))) / V)); } else { - System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * D1 / A)); + System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * jump.getAltitude() / A)); } switch (random.nextInt(10)) { @@ -192,6 +186,13 @@ public class Splat { } + private InitialJumpConditions buildInitialConditions() { + System.out.print("\n\n"); + float terminalVelocity = promptTerminalVelocity(); + float gravitationalAcceleration = promptGravitationalAcceleration(); + return InitialJumpConditions.create(terminalVelocity, gravitationalAcceleration); + } + private void showIntroduction() { System.out.printf("%33s%s\n", " ", "SPLAT"); System.out.printf("%15s%s\n", " ", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); @@ -241,6 +242,59 @@ public class Splat { return planet.getAcceleration(); } + + static class InitialJumpConditions { + private final float originalTerminalVelocity; + private final float originalGravitationalAcceleration; + private final float terminalVelocity; + private final float gravitationalAcceleration; + private final int altitude; + + private InitialJumpConditions(float originalTerminalVelocity, float originalGravitationalAcceleration, + float terminalVelocity, float gravitationalAcceleration, int altitude) { + this.originalTerminalVelocity = originalTerminalVelocity; + this.originalGravitationalAcceleration = originalGravitationalAcceleration; + this.terminalVelocity = terminalVelocity; + this.gravitationalAcceleration = gravitationalAcceleration; + 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); + } + + public float getOriginalTerminalVelocity() { + return originalTerminalVelocity; + } + + public float getOriginalGravitationalAcceleration() { + return originalGravitationalAcceleration; + } + + public float getTerminalVelocity() { + return terminalVelocity; + } + + public float getGravitationalAcceleration() { + return gravitationalAcceleration; + } + + public int getAltitude() { + return altitude; + } + + public float getTimeOfTerminalAccelerationReached(){ + return terminalVelocity / gravitationalAcceleration; + } + } + enum Planet { MERCURY("FINE. YOU'RE ON MERCURY", 12.2f), VENUS("ALL RIGHT. YOU'RE ON VENUS", 28.3f), From 8a992b6ba44b38beb827a66d6e5f551dbbbec786 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 22:07:32 -0800 Subject: [PATCH 575/749] invert if and factor out splat message --- 81_Splat/java/src/Splat.java | 85 +++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 67e278f8..65be1d77 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -59,7 +59,15 @@ public class Splat { System.out.printf("%10.2f %f\n", i, D); } - if (!splat) { + if (splat) { + if (terminalReached) { + System.out.printf("%.2f SPLAT\n", (V / A) + ((jump.getAltitude() - (V * V / (2 * A))) / V)); + } else { + System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * jump.getAltitude() / A)); + + } + showRandomSplatMessage(); + } else { System.out.println("CHUTE OPEN"); int J = 0; @@ -115,45 +123,6 @@ public class Splat { } - } else { - if (terminalReached) { - System.out.printf("%.2f SPLAT\n", (V / A) + ((jump.getAltitude() - (V * V / (2 * A))) / V)); - } else { - System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * jump.getAltitude() / A)); - - } - switch (random.nextInt(10)) { - case 0: - System.out.println("REQUIESCAT IN PACE."); - break; - case 1: - System.out.println("MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE."); - break; - case 2: - System.out.println("REST IN PEACE."); - break; - case 3: - System.out.println("SON-OF-A-GUN."); - break; - case 4: - System.out.println("#$%&&%!$"); - break; - case 5: - System.out.println("A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT."); - break; - case 6: - System.out.println("HMMM. SHOULD HAVE PICKED A SHORTER TIME."); - break; - case 7: - System.out.println("MUTTER. MUTTER. MUTTER."); - break; - case 8: - System.out.println("PUSHING UP DAISIES."); - break; - default: - System.out.println("EASY COME, EASY GO."); - - } } boolean chosen = false; while (!chosen) { @@ -186,6 +155,41 @@ public class Splat { } + private void showRandomSplatMessage() { + switch (random.nextInt(10)) { + case 0: + System.out.println("REQUIESCAT IN PACE."); + break; + case 1: + System.out.println("MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE."); + break; + case 2: + System.out.println("REST IN PEACE."); + break; + case 3: + System.out.println("SON-OF-A-GUN."); + break; + case 4: + System.out.println("#$%&&%!$"); + break; + case 5: + System.out.println("A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT."); + break; + case 6: + System.out.println("HMMM. SHOULD HAVE PICKED A SHORTER TIME."); + break; + case 7: + System.out.println("MUTTER. MUTTER. MUTTER."); + break; + case 8: + System.out.println("PUSHING UP DAISIES."); + break; + default: + System.out.println("EASY COME, EASY GO."); + + } + } + private InitialJumpConditions buildInitialConditions() { System.out.print("\n\n"); float terminalVelocity = promptTerminalVelocity(); @@ -243,6 +247,7 @@ public class Splat { } + // Immutable static class InitialJumpConditions { private final float originalTerminalVelocity; private final float originalGravitationalAcceleration; From dd0dbf648037ba072c4df2bba66b9ed2d62bccc7 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 22:10:44 -0800 Subject: [PATCH 576/749] simplify splat message --- 81_Splat/java/src/Splat.java | 48 +++++++++++------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 65be1d77..3e2f2f83 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -1,4 +1,5 @@ import java.util.Arrays; +import java.util.List; import java.util.Random; import java.util.Scanner; @@ -121,8 +122,6 @@ public class Splat { } System.out.println("SUCCESSFUL JUMP!!!"); } - - } boolean chosen = false; while (!chosen) { @@ -156,38 +155,19 @@ public class Splat { } private void showRandomSplatMessage() { - switch (random.nextInt(10)) { - case 0: - System.out.println("REQUIESCAT IN PACE."); - break; - case 1: - System.out.println("MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE."); - break; - case 2: - System.out.println("REST IN PEACE."); - break; - case 3: - System.out.println("SON-OF-A-GUN."); - break; - case 4: - System.out.println("#$%&&%!$"); - break; - case 5: - System.out.println("A KICK IN THE PANTS IS A BOOST IF YOU'RE HEADED RIGHT."); - break; - case 6: - System.out.println("HMMM. SHOULD HAVE PICKED A SHORTER TIME."); - break; - case 7: - System.out.println("MUTTER. MUTTER. MUTTER."); - break; - case 8: - System.out.println("PUSHING UP DAISIES."); - break; - default: - System.out.println("EASY COME, EASY GO."); - - } + List 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 InitialJumpConditions buildInitialConditions() { From 42f57024fe971b10c0399eb81decc776e04ce04d Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 22:31:51 -0800 Subject: [PATCH 577/749] factor out silly play again prompt --- 81_Splat/java/src/Splat.java | 72 +++++++++++++++--------------------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 3e2f2f83..73d91021 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -21,13 +21,11 @@ public class Splat { while (true) { InitialJumpConditions jump = buildInitialConditions(); - final float V = jump.getTerminalVelocity(); - final float A = jump.getGravitationalAcceleration(); System.out.println(); System.out.printf(" ALTITUDE = %d FT\n", jump.getAltitude()); System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", jump.getOriginalTerminalVelocity()); - System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", jump.getOriginalGravitationalAcceleration()); + System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", jump.getOriginalAcceleration()); System.out.println("SET THE TIMER FOR YOUR FREEFALL."); System.out.print("HOW MANY SECONDS "); @@ -35,6 +33,8 @@ public class Splat { System.out.println("HERE WE GO.\n"); System.out.println("TIME (SEC) DIST TO FALL (FT)"); System.out.println("========== ================="); + final float V = jump.getTerminalVelocity(); + final float A = jump.getAcceleration(); boolean splat = false; boolean terminalReached = false; float D = 0.0f; @@ -123,37 +123,24 @@ public class Splat { System.out.println("SUCCESSFUL JUMP!!!"); } } - boolean chosen = false; - while (!chosen) { - System.out.print("DO YOU WANT TO PLAY AGAIN "); - String Z = scanner.next(); - if (Z.equals("YES")) { - break; - } - if (Z.equals("NO")) { - System.out.print("PLEASE "); - while (true) { - Z = scanner.next(); - if (Z.equals("YES")) { - chosen = true; - break; - } - if (Z.equals("NO")) { - System.out.println("SSSSSSSSSS."); - return; - } - System.out.print("YES OR NO "); - } - continue; - } else { - System.out.print("YES OR NO "); - } + if(!playAgain()){ + return; } - } } + private boolean playAgain() { + if (askYesNo("DO YOU WANT TO PLAY AGAIN ")) { + return true; + } + if (askYesNo("PLEASE")) { + return true; + } + System.out.println("SSSSSSSSSS."); + return false; + } + private void showRandomSplatMessage() { List messages = Arrays.asList( "REQUIESCAT IN PACE.", @@ -173,8 +160,8 @@ public class Splat { private InitialJumpConditions buildInitialConditions() { System.out.print("\n\n"); float terminalVelocity = promptTerminalVelocity(); - float gravitationalAcceleration = promptGravitationalAcceleration(); - return InitialJumpConditions.create(terminalVelocity, gravitationalAcceleration); + float acceleration = promptGravitationalAcceleration(); + return InitialJumpConditions.create(terminalVelocity, acceleration); } private void showIntroduction() { @@ -226,21 +213,20 @@ public class Splat { return planet.getAcceleration(); } - // Immutable static class InitialJumpConditions { private final float originalTerminalVelocity; - private final float originalGravitationalAcceleration; + private final float originalAcceleration; private final float terminalVelocity; - private final float gravitationalAcceleration; + private final float acceleration; private final int altitude; - private InitialJumpConditions(float originalTerminalVelocity, float originalGravitationalAcceleration, - float terminalVelocity, float gravitationalAcceleration, int altitude) { + private InitialJumpConditions(float originalTerminalVelocity, float originalAcceleration, + float terminalVelocity, float acceleration, int altitude) { this.originalTerminalVelocity = originalTerminalVelocity; - this.originalGravitationalAcceleration = originalGravitationalAcceleration; + this.originalAcceleration = originalAcceleration; this.terminalVelocity = terminalVelocity; - this.gravitationalAcceleration = gravitationalAcceleration; + this.acceleration = acceleration; this.altitude = altitude; } @@ -259,16 +245,16 @@ public class Splat { return originalTerminalVelocity; } - public float getOriginalGravitationalAcceleration() { - return originalGravitationalAcceleration; + public float getOriginalAcceleration() { + return originalAcceleration; } public float getTerminalVelocity() { return terminalVelocity; } - public float getGravitationalAcceleration() { - return gravitationalAcceleration; + public float getAcceleration() { + return acceleration; } public int getAltitude() { @@ -276,7 +262,7 @@ public class Splat { } public float getTimeOfTerminalAccelerationReached(){ - return terminalVelocity / gravitationalAcceleration; + return terminalVelocity / acceleration; } } From 347558b966a041a6bf221cfeb8d655aeedd28441 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 22:53:32 -0800 Subject: [PATCH 578/749] factor out JumpResult and executeJump() --- 81_Splat/java/src/Splat.java | 111 +++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 39 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 73d91021..ad15d84e 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -20,65 +20,41 @@ public class Splat { int K1 = 0; while (true) { - InitialJumpConditions jump = buildInitialConditions(); + InitialJumpConditions initial = buildInitialConditions(); System.out.println(); - System.out.printf(" ALTITUDE = %d FT\n", jump.getAltitude()); - System.out.printf(" TERM. VELOCITY = %.2f FT/SEC +/-5%%\n", jump.getOriginalTerminalVelocity()); - System.out.printf(" ACCELERATION = %.2f FT/SEC/SEC +/-5%%\n", jump.getOriginalAcceleration()); + 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 T = scanner.nextFloat(); + float freefallTime = scanner.nextFloat(); System.out.println("HERE WE GO.\n"); System.out.println("TIME (SEC) DIST TO FALL (FT)"); System.out.println("========== ================="); - final float V = jump.getTerminalVelocity(); - final float A = jump.getAcceleration(); - boolean splat = false; - boolean terminalReached = false; - float D = 0.0f; - for (float i = 0.0f; !splat && (i < T); i += T / 8) { - if (i > jump.getTimeOfTerminalAccelerationReached()) { - terminalReached = true; - System.out.printf("TERMINAL VELOCITY REACHED AT T PLUS %f SECONDS.\n", jump.getTimeOfTerminalAccelerationReached()); - for (i = i; i < T; i += T / 8) { - D = jump.getAltitude() - ((V * V / (2 * A)) + (V * (i - (V / A)))); - if (D <= 0) { - splat = true; - break; - } - System.out.printf("%10.2f %f\n", i, D); - } - break; - } - D = jump.getAltitude() - ((A / 2) * i * i); - if (D <= 0) { - splat = true; - break; - } - System.out.printf("%10.2f %f\n", i, D); - } + final float V = initial.getTerminalVelocity(); + final float A = initial.getAcceleration(); + JumpResult jump = executeJump(initial, freefallTime); - if (splat) { - if (terminalReached) { - System.out.printf("%.2f SPLAT\n", (V / A) + ((jump.getAltitude() - (V * V / (2 * A))) / V)); + if (jump.isSplat()) { + if (jump.hasReachedTerminalVelocity()) { + System.out.printf("%.2f SPLAT\n", (V / A) + ((initial.getAltitude() - (V * V / (2 * A))) / V)); } else { - System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * jump.getAltitude() / A)); + System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * initial.getAltitude() / A)); } showRandomSplatMessage(); } else { - System.out.println("CHUTE OPEN"); int J = 0; for (J = 0; J < 42; J++) { if (Arr[J] == 0) { - Arr[J] = D; + Arr[J] = jump.getDistance(); break; } K = K + 1; - if (D > Arr[J]) { + if (jump.getDistance() > Arr[J]) { continue; } K1 = K1 + 1; @@ -98,7 +74,7 @@ public class Splat { System.out.printf("YOU WERE BEATEN OUT BY %d OF THEM.\n", K - K1); } else if (K - K1 <= 0.75 * K) { System.out.printf("CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY %d IN THE\n", K - K1); - System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.", K); + System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); } else if (K - K1 <= -0.9 * K) { 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", K, K1); @@ -130,6 +106,33 @@ public class Splat { } + private JumpResult executeJump(InitialJumpConditions initial, float T) { + final float V = initial.getTerminalVelocity(); + final float A = initial.getAcceleration(); + + JumpResult jump = new JumpResult(initial.getAltitude()); + for (float i = 0.0f; !jump.isSplat() && (i < T); i += T / 8) { + if (i > initial.getTimeOfTerminalAccelerationReached()) { + jump.setReachedTerminalVelocity(); + System.out.printf("TERMINAL VELOCITY REACHED AT T PLUS %f SECONDS.\n", initial.getTimeOfTerminalAccelerationReached()); + for (i = i; i < T; i += T / 8) { + jump.setDistance(initial.getAltitude() - ((V * V / (2 * A)) + (V * (i - (V / A))))); + if (jump.isSplat()) { + break; + } + System.out.printf("%10.2f %f\n", i, jump.getDistance()); + } + break; + } + jump.setDistance( initial.getAltitude() - ((A / 2) * i * i)); + if (jump.isSplat()) { + break; + } + System.out.printf("%10.2f %f\n", i, jump.getDistance()); + } + return jump; + } + private boolean playAgain() { if (askYesNo("DO YOU WANT TO PLAY AGAIN ")) { return true; @@ -213,6 +216,36 @@ public class Splat { return planet.getAcceleration(); } + // Mutable + static class JumpResult { + private boolean reachedTerminalVelocity = false; + private float distance; // from the ground + + public JumpResult(float distance) { + this.distance = distance; + } + + public boolean isSplat() { + return distance <= 0; + } + + public boolean hasReachedTerminalVelocity() { + return reachedTerminalVelocity; + } + + public float getDistance() { + return distance; + } + + public void setDistance(float distance){ + this.distance = distance; + } + + public void setReachedTerminalVelocity(){ + reachedTerminalVelocity = true; + } + } + // Immutable static class InitialJumpConditions { private final float originalTerminalVelocity; From 98b4e94719d08fbcc05cf6fba07eca8df7aaa66f Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 23:14:58 -0800 Subject: [PATCH 579/749] factor out result message display and clean up ordinal switch --- 81_Splat/java/src/Splat.java | 159 +++++++++++++++++------------------ 1 file changed, 76 insertions(+), 83 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index ad15d84e..a0193507 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -6,6 +6,9 @@ import java.util.Scanner; public class Splat { private static final Random random = new Random(); private final Scanner scanner = new Scanner(System.in); + private final float[] Arr = new float[42]; + private int K = 0; + private int K1 = 0; public static void main(String[] args) { new Splat().run(); @@ -14,10 +17,7 @@ public class Splat { public void run() { showIntroduction(); - float[] Arr = new float[42]; Arrays.fill(Arr, 0.0f); - int K = 0; - int K1 = 0; while (true) { InitialJumpConditions initial = buildInitialConditions(); @@ -33,106 +33,100 @@ public class Splat { System.out.println("HERE WE GO.\n"); System.out.println("TIME (SEC) DIST TO FALL (FT)"); System.out.println("========== ================="); - final float V = initial.getTerminalVelocity(); - final float A = initial.getAcceleration(); + JumpResult jump = executeJump(initial, freefallTime); + showJumpResults(initial, jump); - if (jump.isSplat()) { - if (jump.hasReachedTerminalVelocity()) { - System.out.printf("%.2f SPLAT\n", (V / A) + ((initial.getAltitude() - (V * V / (2 * A))) / V)); - } else { - System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * initial.getAltitude() / A)); - - } - showRandomSplatMessage(); - } else { - System.out.println("CHUTE OPEN"); - int J = 0; - for (J = 0; J < 42; J++) { - if (Arr[J] == 0) { - Arr[J] = jump.getDistance(); - break; - } - K = K + 1; - if (jump.getDistance() > Arr[J]) { - continue; - } - K1 = K1 + 1; - } - - if (J > 2) { - if (K - K1 <= 0.1 * K) { - System.out.printf("WOW! THAT'S SOME JUMPING. OF THE %d SUCCESSFUL JUMPS\n", K); - System.out.printf("BEFORE YOURS, ONLY %d OPENED THEIR CHUTES LOWER THAN\n", K - K1); - System.out.println("YOU DID."); - } else if (K - K1 <= 0.25 * K) { - System.out.printf("PRETTY GOOD! %d SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n", K); - System.out.printf("%d OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n", K - K1); - System.out.println("OPENED."); - } else if (K - K1 <= 0.5 * K) { - System.out.printf("NOT BAD. THERE HAVE BEEN %d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); - System.out.printf("YOU WERE BEATEN OUT BY %d OF THEM.\n", K - K1); - } else if (K - K1 <= 0.75 * K) { - System.out.printf("CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY %d IN THE\n", K - K1); - System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); - } else if (K - K1 <= -0.9 * K) { - 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", K, K1); - System.out.println("BETTER THAN THE WORST. SHAPE UP!!!\n"); - } else { - System.out.printf("HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. %f SUCCESSFUL\n", K); - System.out.printf("JUMPS BEFORE YOURS AND YOU CAME IN NUMBER %d! GET WITH IT!\n", K - K1); - } - } else { - System.out.println("AMAZING!!! NOT BAD FOR YOUR "); - switch (J) { - case 0: - System.out.print("1ST "); - break; - case 1: - System.out.print("2ND "); - break; - case 2: - System.out.print("3RD "); - break; - } - System.out.println("SUCCESSFUL JUMP!!!"); - } - } if(!playAgain()){ + System.out.println("SSSSSSSSSS."); return; } } - } - private JumpResult executeJump(InitialJumpConditions initial, float T) { + private void showJumpResults(InitialJumpConditions initial, JumpResult jump) { final float V = initial.getTerminalVelocity(); final float A = initial.getAcceleration(); + if (jump.isSplat()) { + if (jump.hasReachedTerminalVelocity()) { + System.out.printf("%.2f SPLAT\n", (V / A) + ((initial.getAltitude() - (V * V / (2 * A))) / V)); + } else { + System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * initial.getAltitude() / A)); + } + showRandomSplatMessage(); + } else { + System.out.println("CHUTE OPEN"); + int J = 0; + for (J = 0; J < 42; J++) { + if (Arr[J] == 0) { + Arr[J] = jump.getDistance(); + break; + } + K = K + 1; + if (jump.getDistance() > Arr[J]) { + continue; + } + K1 = K1 + 1; + } + + if (J > 2) { + if (K - K1 <= 0.1 * K) { + System.out.printf("WOW! THAT'S SOME JUMPING. OF THE %d SUCCESSFUL JUMPS\n", K); + System.out.printf("BEFORE YOURS, ONLY %d OPENED THEIR CHUTES LOWER THAN\n", K - K1); + System.out.println("YOU DID."); + } else if (K - K1 <= 0.25 * K) { + System.out.printf("PRETTY GOOD! %d SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n", K); + System.out.printf("%d OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n", K - K1); + System.out.println("OPENED."); + } else if (K - K1 <= 0.5 * K) { + System.out.printf("NOT BAD. THERE HAVE BEEN %d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); + System.out.printf("YOU WERE BEATEN OUT BY %d OF THEM.\n", K - K1); + } else if (K - K1 <= 0.75 * K) { + System.out.printf("CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY %d IN THE\n", K - K1); + System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); + } else if (K - K1 <= -0.9 * K) { + 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", K, K1); + System.out.println("BETTER THAN THE WORST. SHAPE UP!!!\n"); + } else { + System.out.printf("HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. %f SUCCESSFUL\n", K); + System.out.printf("JUMPS BEFORE YOURS AND YOU CAME IN NUMBER %d! GET WITH IT!\n", K - K1); + } + } else { + String[] nums = new String[]{ "1ST", "2ND", "3RD"}; + System.out.printf("AMAZING!!! NOT BAD FOR YOUR %s SUCCESSFUL JUMP!!!\n", nums[J]); + } + } + } + + private JumpResult executeJump(InitialJumpConditions initial, float chuteOpenTime) { JumpResult jump = new JumpResult(initial.getAltitude()); - for (float i = 0.0f; !jump.isSplat() && (i < T); i += T / 8) { - if (i > initial.getTimeOfTerminalAccelerationReached()) { + for (float time = 0.0f; !jump.isSplat() && (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()); - for (i = i; i < T; i += T / 8) { - jump.setDistance(initial.getAltitude() - ((V * V / (2 * A)) + (V * (i - (V / A))))); - if (jump.isSplat()) { - break; - } - System.out.printf("%10.2f %f\n", i, jump.getDistance()); - } - break; } - jump.setDistance( initial.getAltitude() - ((A / 2) * i * i)); + float newDistance = computeDistance(initial, time, jump.hasReachedTerminalVelocity()); + jump.setDistance(newDistance); + if (jump.isSplat()) { - break; + return jump; } - System.out.printf("%10.2f %f\n", i, jump.getDistance()); + 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 boolean playAgain() { if (askYesNo("DO YOU WANT TO PLAY AGAIN ")) { return true; @@ -140,7 +134,6 @@ public class Splat { if (askYesNo("PLEASE")) { return true; } - System.out.println("SSSSSSSSSS."); return false; } From 8e98439f35e93e95379ef652fd283a10d919baeb Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 23:49:31 -0800 Subject: [PATCH 580/749] simplify handling of past successes --- 81_Splat/java/src/Splat.java | 146 +++++++++++++++++------------------ 1 file changed, 72 insertions(+), 74 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index a0193507..2586ecab 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -1,14 +1,9 @@ -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.Scanner; +import java.util.*; public class Splat { private static final Random random = new Random(); private final Scanner scanner = new Scanner(System.in); - private final float[] Arr = new float[42]; - private int K = 0; - private int K1 = 0; + private final List pastSuccessfulJumpDistances = new ArrayList<>(); public static void main(String[] args) { new Splat().run(); @@ -17,7 +12,6 @@ public class Splat { public void run() { showIntroduction(); - Arrays.fill(Arr, 0.0f); while (true) { InitialJumpConditions initial = buildInitialConditions(); @@ -45,59 +39,66 @@ public class Splat { } private void showJumpResults(InitialJumpConditions initial, JumpResult jump) { + if (jump.isSplat()) { + showSplatMessage(initial, jump); + showCleverSplatMessage(); + return; + } + System.out.println("CHUTE OPEN"); + int worseJumpCount = countWorseHistoricalJumps(jump); + pastSuccessfulJumpDistances.add(jump.getDistance()); + int successfulJumpCt = pastSuccessfulJumpDistances.size(); + + if (pastSuccessfulJumpDistances.size() <= 2) { + List 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); + } + + private double computeTimeOfSplat(InitialJumpConditions initial, JumpResult jump) { final float V = initial.getTerminalVelocity(); final float A = initial.getAcceleration(); - - if (jump.isSplat()) { - if (jump.hasReachedTerminalVelocity()) { - System.out.printf("%.2f SPLAT\n", (V / A) + ((initial.getAltitude() - (V * V / (2 * A))) / V)); - } else { - System.out.printf("%.2f SPLAT\n", Math.sqrt(2 * initial.getAltitude() / A)); - } - showRandomSplatMessage(); - } else { - System.out.println("CHUTE OPEN"); - int J = 0; - for (J = 0; J < 42; J++) { - if (Arr[J] == 0) { - Arr[J] = jump.getDistance(); - break; - } - K = K + 1; - if (jump.getDistance() > Arr[J]) { - continue; - } - K1 = K1 + 1; - } - - if (J > 2) { - if (K - K1 <= 0.1 * K) { - System.out.printf("WOW! THAT'S SOME JUMPING. OF THE %d SUCCESSFUL JUMPS\n", K); - System.out.printf("BEFORE YOURS, ONLY %d OPENED THEIR CHUTES LOWER THAN\n", K - K1); - System.out.println("YOU DID."); - } else if (K - K1 <= 0.25 * K) { - System.out.printf("PRETTY GOOD! %d SUCCESSFUL JUMPS PRECEDED YOURS AND ONLY\n", K); - System.out.printf("%d OF THEM GOT LOWER THAN YOU DID BEFORE THEIR CHUTES\n", K - K1); - System.out.println("OPENED."); - } else if (K - K1 <= 0.5 * K) { - System.out.printf("NOT BAD. THERE HAVE BEEN %d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); - System.out.printf("YOU WERE BEATEN OUT BY %d OF THEM.\n", K - K1); - } else if (K - K1 <= 0.75 * K) { - System.out.printf("CONSERVATIVE, AREN'T YOU? YOU RANKED ONLY %d IN THE\n", K - K1); - System.out.printf("%d SUCCESSFUL JUMPS BEFORE YOURS.\n", K); - } else if (K - K1 <= -0.9 * K) { - 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", K, K1); - System.out.println("BETTER THAN THE WORST. SHAPE UP!!!\n"); - } else { - System.out.printf("HEY! YOU PULLED THE RIP CORD MUCH TOO SOON. %f SUCCESSFUL\n", K); - System.out.printf("JUMPS BEFORE YOURS AND YOU CAME IN NUMBER %d! GET WITH IT!\n", K - K1); - } - } else { - String[] nums = new String[]{ "1ST", "2ND", "3RD"}; - System.out.printf("AMAZING!!! NOT BAD FOR YOUR %s SUCCESSFUL JUMP!!!\n", nums[J]); - } + if (jump.hasReachedTerminalVelocity()) { + return (V / A) + ((initial.getAltitude() - (V * V / (2 * A))) / V); } + return Math.sqrt(2 * initial.getAltitude() / A); + } + + // Returns the number of jumps that this jump was better than + private int countWorseHistoricalJumps(JumpResult jump) { + return (int) pastSuccessfulJumpDistances.stream() + .filter(distance -> jump.getDistance() < distance) + .count(); } private JumpResult executeJump(InitialJumpConditions initial, float chuteOpenTime) { @@ -131,13 +132,10 @@ public class Splat { if (askYesNo("DO YOU WANT TO PLAY AGAIN ")) { return true; } - if (askYesNo("PLEASE")) { - return true; - } - return false; + return askYesNo("PLEASE"); } - private void showRandomSplatMessage() { + private void showCleverSplatMessage() { List messages = Arrays.asList( "REQUIESCAT IN PACE.", "MAY THE ANGEL OF HEAVEN LEAD YOU INTO PARADISE.", @@ -205,7 +203,7 @@ public class Splat { private float chooseRandomAcceleration() { Planet planet = Planet.pickRandom(); - System.out.printf("%s. ACCELERATION=%.2f FT/SEC/SEC.\n", planet.getMessage(), planet.getAcceleration()); + System.out.printf("%s %s. ACCELERATION=%.2f FT/SEC/SEC.\n", planet.getMessage(), planet.name(), planet.getAcceleration()); return planet.getAcceleration(); } @@ -293,16 +291,16 @@ public class Splat { } enum Planet { - MERCURY("FINE. YOU'RE ON MERCURY", 12.2f), - VENUS("ALL RIGHT. YOU'RE ON VENUS", 28.3f), - EARTH("THEN YOU'RE ON EARTH", 32.16f), - MOON("FINE. YOU'RE ON THE MOON", 5.15f), - MARS("ALL RIGHT. YOU'RE ON MARS", 12.5f), - JUPITER("THEN YOU'RE ON JUPITER", 85.2f), - SATURN("FINE. YOU'RE ON SATURN", 37.6f), - URANUS("ALL RIGHT. YOU'RE ON URANUS", 33.8f), - NEPTUNE("THEN YOU'RE ON NEPTUNE", 39.6f), - SUN("FINE. YOU'RE ON THE SUN", 896.0f); + 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); static final Random random = new Random(); private final String message; From 522975485110ed58784438945e21e575e14bc5ef Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 4 Jan 2022 23:59:26 -0800 Subject: [PATCH 581/749] fix problem with holding count after add and fix up some visiblity for simplicity --- 81_Splat/java/src/Splat.java | 92 ++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 2586ecab..6b89dde2 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -46,8 +46,8 @@ public class Splat { } System.out.println("CHUTE OPEN"); int worseJumpCount = countWorseHistoricalJumps(jump); - pastSuccessfulJumpDistances.add(jump.getDistance()); int successfulJumpCt = pastSuccessfulJumpDistances.size(); + pastSuccessfulJumpDistances.add(jump.getDistance()); if (pastSuccessfulJumpDistances.size() <= 2) { List ordinals = Arrays.asList("1ST", "2ND", "3RD"); @@ -207,6 +207,40 @@ public class Splat { 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; @@ -216,23 +250,23 @@ public class Splat { this.distance = distance; } - public boolean isSplat() { + boolean isSplat() { return distance <= 0; } - public boolean hasReachedTerminalVelocity() { + boolean hasReachedTerminalVelocity() { return reachedTerminalVelocity; } - public float getDistance() { + float getDistance() { return distance; } - public void setDistance(float distance){ + void setDistance(float distance){ this.distance = distance; } - public void setReachedTerminalVelocity(){ + void setReachedTerminalVelocity(){ reachedTerminalVelocity = true; } } @@ -265,62 +299,28 @@ public class Splat { return value + ((value * random.nextFloat()) / 20.0f) - ((value * random.nextFloat()) / 20.0f); } - public float getOriginalTerminalVelocity() { + float getOriginalTerminalVelocity() { return originalTerminalVelocity; } - public float getOriginalAcceleration() { + float getOriginalAcceleration() { return originalAcceleration; } - public float getTerminalVelocity() { + float getTerminalVelocity() { return terminalVelocity; } - public float getAcceleration() { + float getAcceleration() { return acceleration; } - public int getAltitude() { + int getAltitude() { return altitude; } - public float getTimeOfTerminalAccelerationReached(){ + float getTimeOfTerminalAccelerationReached(){ return terminalVelocity / acceleration; } } - - 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); - - 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)]; - } - - public String getMessage() { - return message; - } - - public float getAcceleration() { - return acceleration; - } - } } \ No newline at end of file From 9cc332f568189fa7bc028e662de6a5e08e3a88a7 Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 5 Jan 2022 00:00:03 -0800 Subject: [PATCH 582/749] grammar nit --- 81_Splat/java/src/Splat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 6b89dde2..4c0e2fdf 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -94,7 +94,7 @@ public class Splat { return Math.sqrt(2 * initial.getAltitude() / A); } - // Returns the number of jumps that this jump was better than + // Returns the number of jumps for which this jump was better private int countWorseHistoricalJumps(JumpResult jump) { return (int) pastSuccessfulJumpDistances.stream() .filter(distance -> jump.getDistance() < distance) From 11dba9dd92cef1a0d26c2300129be460072a6fd7 Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 5 Jan 2022 00:04:24 -0800 Subject: [PATCH 583/749] debrand --- 81_Splat/java/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/81_Splat/java/README.md b/81_Splat/java/README.md index 51edd8d4..b8998fa6 100644 --- a/81_Splat/java/README.md +++ b/81_Splat/java/README.md @@ -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/) From 18b37bda81c1504cc6c062de84787a6403953630 Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 5 Jan 2022 00:12:43 -0800 Subject: [PATCH 584/749] add top comment copied from readme (includes attribution) and reorganize methods for readability. --- 81_Splat/java/src/Splat.java | 196 +++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 87 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 4c0e2fdf..3c4cd817 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -1,5 +1,22 @@ 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. + *

+ * The computer then tells you the height you’re 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. + *

+ * John Yegge created this program while at the Oak Ridge Associated Universities. + *

+ * Ported from BASIC by jason plumb (@breedx2) + *

+ */ public class Splat { private static final Random random = new Random(); private final Scanner scanner = new Scanner(System.in); @@ -31,13 +48,74 @@ public class Splat { JumpResult jump = executeJump(initial, freefallTime); showJumpResults(initial, jump); - if(!playAgain()){ + 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; !jump.isSplat() && (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); @@ -85,6 +163,9 @@ public class Splat { 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(); @@ -94,38 +175,26 @@ public class Splat { return Math.sqrt(2 * initial.getAltitude() / A); } - // Returns the number of jumps for which this jump was better private int countWorseHistoricalJumps(JumpResult jump) { return (int) pastSuccessfulJumpDistances.stream() .filter(distance -> jump.getDistance() < distance) .count(); } - private JumpResult executeJump(InitialJumpConditions initial, float chuteOpenTime) { - JumpResult jump = new JumpResult(initial.getAltitude()); - for (float time = 0.0f; !jump.isSplat() && (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 showCleverSplatMessage() { + List 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() { @@ -135,68 +204,21 @@ public class Splat { return askYesNo("PLEASE"); } - private void showCleverSplatMessage() { - List 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 InitialJumpConditions buildInitialConditions() { - System.out.print("\n\n"); - float terminalVelocity = promptTerminalVelocity(); - float acceleration = promptGravitationalAcceleration(); - return InitialJumpConditions.create(terminalVelocity, acceleration); - } - - 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 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 float mphToFeetPerSec(float speed){ + private float mphToFeetPerSec(float speed) { return speed * (5280.0f / 3600.0f); } - private boolean askYesNo(String prompt){ + 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 "); + switch (answer) { + case "YES": + return true; + case "NO": + return false; + default: + System.out.print("YES OR NO "); } } } @@ -228,7 +250,7 @@ public class Splat { this.acceleration = acceleration; } - static Planet pickRandom(){ + static Planet pickRandom() { return values()[random.nextInt(Planet.values().length)]; } @@ -262,11 +284,11 @@ public class Splat { return distance; } - void setDistance(float distance){ + void setDistance(float distance) { this.distance = distance; } - void setReachedTerminalVelocity(){ + void setReachedTerminalVelocity() { reachedTerminalVelocity = true; } } @@ -319,7 +341,7 @@ public class Splat { return altitude; } - float getTimeOfTerminalAccelerationReached(){ + float getTimeOfTerminalAccelerationReached() { return terminalVelocity / acceleration; } } From 3c185d1c8c2c3c7eed2995b04aed9861699294dc Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 5 Jan 2022 00:15:05 -0800 Subject: [PATCH 585/749] remove unnecessary leftover check --- 81_Splat/java/src/Splat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index 3c4cd817..b76c82ff 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -91,7 +91,7 @@ public class Splat { private JumpResult executeJump(InitialJumpConditions initial, float chuteOpenTime) { JumpResult jump = new JumpResult(initial.getAltitude()); - for (float time = 0.0f; !jump.isSplat() && (time < chuteOpenTime); time += chuteOpenTime / 8) { + 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()); From 3bdb7be6d171f0f7dd461af0a72e1e8f0f3c27ab Mon Sep 17 00:00:00 2001 From: Minas Date: Wed, 5 Jan 2022 14:08:37 +0000 Subject: [PATCH 586/749] Fixed the A to be : to make more sense in the first game in java --- 01_Acey_Ducey/java/src/AceyDucey.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01_Acey_Ducey/java/src/AceyDucey.java b/01_Acey_Ducey/java/src/AceyDucey.java index 43fc9950..d53c0d05 100644 --- a/01_Acey_Ducey/java/src/AceyDucey.java +++ b/01_Acey_Ducey/java/src/AceyDucey.java @@ -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"); } } \ No newline at end of file From e1871a1df90591863aa46e5dd66e598ea485e019 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Thu, 6 Jan 2022 01:59:09 +1100 Subject: [PATCH 587/749] initial jvm gradle build scripts. --- .../build/kotlin/build53Kingkotlinjar-classes.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt diff --git a/buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt b/buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt new file mode 100644 index 00000000..1bd92f25 --- /dev/null +++ b/buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt @@ -0,0 +1 @@ +/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/DataEntryValidationException.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/EndOfInputException.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/GameState.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$1.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$2.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$3.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$4.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$5.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$AntiImmigrationRevolution.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$ContinueNextYear.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$ExtremeMismanagement.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$StarvationWithFullTreasury.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$TooManyPeopleDead.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$Win.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome.class \ No newline at end of file From d9cac10ed59c3161943b5d7eb9b5d0fad0c5a7e0 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Thu, 6 Jan 2022 02:01:18 +1100 Subject: [PATCH 588/749] change King package --- 53_King/kotlin/King.kt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/53_King/kotlin/King.kt b/53_King/kotlin/King.kt index 71e6d505..169cd6a0 100644 --- a/53_King/kotlin/King.kt +++ b/53_King/kotlin/King.kt @@ -1,3 +1,5 @@ +package king53 + import kotlin.math.abs import kotlin.random.Random import kotlin.system.exitProcess @@ -22,6 +24,7 @@ fun main() { with(gameState) { do { + recalculateLandCost() displayStatus() inputLandSale() @@ -84,6 +87,7 @@ fun loadOldGame(): GameState = GameState().apply { println(" COME ON, YOUR TERM IN OFFICE IS ONLY $yearsRequired YEARS.") retry = true } + } while (retry) print("HOW MUCH DID YOU HAVE IN THE TREASURY? ") @@ -115,6 +119,10 @@ fun loadOldGame(): GameState = GameState().apply { */ sealed class YearOutcome { + /** + * Display output for the end of the year, for each different possible + * year outcome. + */ open fun displayConsequences() { // Default display nothing } @@ -132,7 +140,7 @@ sealed class YearOutcome { object ContinueNextYear : YearOutcome() - class Win(val yearsRequired: Int) : YearOutcome() { + class Win(private val yearsRequired: Int) : YearOutcome() { override fun displayConsequences() { // The misspelling of "successfully" is in the original code. println( @@ -229,12 +237,18 @@ sealed class YearOutcome { * Record data, allow data input, and process the simulation for the game. */ class GameState(val yearsRequired: Int = 8) { + /** * The current year. Years start with zero, but we never * output the current year. */ var currentYear = 0 + /** + * Keep track of each year's crop loss, so we can report increases. + */ + private var lastYearsCropLoss: Int = 0 + /** * Number of countrymen who have died of either pollution * or starvation this year. @@ -535,11 +549,12 @@ class GameState(val yearsRequired: Int = 8) { the population, but does not affect crop losses. */ var cropLoss = ((2000 - landArea) * (rnd + 1.5) / 2.0).toInt() - val cropLossWorse = false if (foreignWorkers > 0) print("OF $plantingArea SQ. MILES PLANTED,") if (plantingArea <= cropLoss) cropLoss = plantingArea + val cropLossWorse = cropLoss > lastYearsCropLoss + lastYearsCropLoss = cropLoss println(" YOU HARVESTED ${plantingArea - cropLoss} SQ. MILES OF CROPS.") if (cropLoss > 0) { From f4a71b965b5f0e661d00aade832aa86963a8cd5a Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Thu, 6 Jan 2022 02:02:29 +1100 Subject: [PATCH 589/749] remove build artifacts accidentally added --- .../build/kotlin/build53Kingkotlinjar-classes.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt diff --git a/buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt b/buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt deleted file mode 100644 index 1bd92f25..00000000 --- a/buildJvm/build_53_King_kotlin/build/kotlin/build53Kingkotlinjar-classes.txt +++ /dev/null @@ -1 +0,0 @@ -/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/DataEntryValidationException.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/EndOfInputException.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/GameState.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$1.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$2.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$3.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$4.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt$loadOldGame$1$5.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/KingKt.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$AntiImmigrationRevolution.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$ContinueNextYear.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$ExtremeMismanagement.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$StarvationWithFullTreasury.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$TooManyPeopleDead.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome$Win.class:/home/paul/Projects/basic-computer-games/buildJvm/build_53_King_kotlin/build/classes/kotlin/main/king53/YearOutcome.class \ No newline at end of file From a98662a4f0521d3fd7537b79849f26140d171e9f Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 11:35:09 -0500 Subject: [PATCH 590/749] Create HighIQ.java --- 48_High_IQ/java/HighIQ.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 48_High_IQ/java/HighIQ.java diff --git a/48_High_IQ/java/HighIQ.java b/48_High_IQ/java/HighIQ.java new file mode 100644 index 00000000..58f3203a --- /dev/null +++ b/48_High_IQ/java/HighIQ.java @@ -0,0 +1,4 @@ +public class HighIQ { + + +} From c9d26373b597ea8e2983f02dbca7d6426dc3ce10 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 11:36:38 -0500 Subject: [PATCH 591/749] Move java to src folder --- 48_High_IQ/java/{ => src}/HighIQ.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 48_High_IQ/java/{ => src}/HighIQ.java (100%) diff --git a/48_High_IQ/java/HighIQ.java b/48_High_IQ/java/src/HighIQ.java similarity index 100% rename from 48_High_IQ/java/HighIQ.java rename to 48_High_IQ/java/src/HighIQ.java From 9b47c69be55bb6b24ff8bdf4a71c735a7d14aae0 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 11:37:24 -0500 Subject: [PATCH 592/749] Create HighIQGame.java --- 48_High_IQ/java/src/HighIQGame.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 48_High_IQ/java/src/HighIQGame.java diff --git a/48_High_IQ/java/src/HighIQGame.java b/48_High_IQ/java/src/HighIQGame.java new file mode 100644 index 00000000..c7d4df9b --- /dev/null +++ b/48_High_IQ/java/src/HighIQGame.java @@ -0,0 +1,5 @@ +public class HighIQGame { + public static void main(String[] args) { + + } +} From 917915048e22d329c521ff8a214c132beae651a2 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 11:41:21 -0500 Subject: [PATCH 593/749] Create Board.java --- 48_High_IQ/java/src/Board.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 48_High_IQ/java/src/Board.java diff --git a/48_High_IQ/java/src/Board.java b/48_High_IQ/java/src/Board.java new file mode 100644 index 00000000..18b17cf5 --- /dev/null +++ b/48_High_IQ/java/src/Board.java @@ -0,0 +1,10 @@ +public class Board { + + public Board() { + + } + + public String toString() { + return ""; + } +} From 4ea34f845644d89cdc009c7c33a6937201b3fb1e Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 11:49:07 -0500 Subject: [PATCH 594/749] Add method signatures to HighIQ.java --- 48_High_IQ/java/src/HighIQ.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 58f3203a..2516bb1b 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -1,4 +1,10 @@ public class HighIQ { + public HighIQ() { + + } + public void play() { + + } } From fb8a87bade402b7ddd225f8554bfe5a3af4d2682 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 11:59:12 -0500 Subject: [PATCH 595/749] Added the board matrix --- 48_High_IQ/java/src/Board.java | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/48_High_IQ/java/src/Board.java b/48_High_IQ/java/src/Board.java index 18b17cf5..6a320bd1 100644 --- a/48_High_IQ/java/src/Board.java +++ b/48_High_IQ/java/src/Board.java @@ -1,10 +1,28 @@ public class Board { - public Board() { - - } + private int[][] board; - public String toString() { - return ""; - } + public Board() { + board = new int[7][7]; + + //Set all of the corners to -1, and place pegs in proper spaces + for(int i = 0; i < 7; i++) { + for(int j = 0; j < 7; j++) { + if((i < 3 || i > 5) && (j < 3 || j > 5)) { + //If both i and j are either less than 3 or greater than 5, then the index is a corner + board[i][j] = -1; + } else if(i == 4 && j == 4) { + //Do not place a peg in the center + board[i][j] = 0; + } else { + //Place a peg everywhere else + board[i][j] = 1; + } + } + } + } + + public String toString() { + return ""; + } } From 64f854171814659ed7968b8fb24445737ad5dbfd Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Wed, 5 Jan 2022 15:02:47 +0100 Subject: [PATCH 596/749] D version of 3D-plot. With bonus. --- 87_3-D_Plot/d/.gitignore | 2 + 87_3-D_Plot/d/README.md | 182 ++++++++++++++++++++++++++++ 87_3-D_Plot/d/threedeeplot.d | 35 ++++++ 87_3-D_Plot/d/threedeeplot_random.d | 50 ++++++++ 4 files changed, 269 insertions(+) create mode 100644 87_3-D_Plot/d/.gitignore create mode 100644 87_3-D_Plot/d/README.md create mode 100644 87_3-D_Plot/d/threedeeplot.d create mode 100644 87_3-D_Plot/d/threedeeplot_random.d diff --git a/87_3-D_Plot/d/.gitignore b/87_3-D_Plot/d/.gitignore new file mode 100644 index 00000000..d969f6b2 --- /dev/null +++ b/87_3-D_Plot/d/.gitignore @@ -0,0 +1,2 @@ +*.exe +*.obj diff --git a/87_3-D_Plot/d/README.md b/87_3-D_Plot/d/README.md new file mode 100644 index 00000000..8a01faf3 --- /dev/null +++ b/87_3-D_Plot/d/README.md @@ -0,0 +1,182 @@ +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). + +## Running the code + +Assuming the reference [dmd](https://dlang.org/download.html#dmd) compiler: +```shell +dmd -dip1000 -run threedeeplot.d +``` + +[Other compilers](https://dlang.org/download.html) also exist. + +## On rounding floating point values to integer values + +The D equivalent of Basic `INT` is [`floor`](https://dlang.org/phobos/std_math_rounding.html#.floor), +which rounds towards negative infinity. If you change occurrences of `floor` to +[`lrint`](https://dlang.org/phobos/std_math_rounding.html#.lrint), you'll see that the plots show a bit more detail, +as is done in the bonus below. + +## Bonus: Self-writing programs + +With a small modification to the source, the program can be extended to **plot a random function**, and **print its formula**. + +```shell +rdmd -dip1000 threedeeplot_random.d +``` +(`rdmd` caches the executable, which results in speedy execution when the source does not change.) + +### Example output +``` + 3D Plot + (After Creative Computing Morristown, New Jersey) + + + f(z) = 30 * sin(z / 10.0) + + * + * * * * + * * * * * + * * * * * + * * * * * * + * * * * * * + * * * * * ** + * * * * * * * + * * * * * * ** + * * * * * * * * + * * * * * * * * + * * * * * * * ** + * * * * * * * * * + * * * * ** * * * * + * * * * ** * * * + * * * * * * * * + * * * * * * * * + * * * ** * * ** + * * * ** * ** + * * * * * ** + * * * * * ** + * * * * * ** + * * * ** * ** + * * * ** * * ** + * * * * * * * * + * * * * * * * * + * * * * ** * * * + * * * * ** * * * * + * * * * * * * * * + * * * * * * * ** + * * * * * * * * + * * * * * * * * + * * * * * * ** + * * * * * * * + * * * * * ** + * * * * * * + * * * * * * + * * * * * + * * * * * + * * * * + * +``` + +### Breakdown of differences + +Have a look at the relevant differences between `threedeeplot.d` and `threedeeplot_random.d`. +This is the original function with the single expression that is evaluated for the plot: +```d + static float fna(float z) + { + return 30.0 * exp(-z * z / 100.0); + } +``` +Here `static` means that the nested function does not need acces to its enclosing scope. + +Now, by inserting the following: +```d + enum functions = ["30.0 * exp(-z * z / 100.0)", + "sqrt(900.01 - z * z) * .9 - 2", + "30 * (cos(z / 16.0) + .5)", + "30 - 30 * sin(z / 18.0)", + "30 * exp(-cos(z / 16.0)) - 30", + "30 * sin(z / 10.0)"]; + + size_t index = uniform(0, functions.length); + writeln(center("f(z) = " ~ functions[index], width), "\n"); +``` +and changing the implementation of `fna` to +```d + float fna(float z) + { + final switch (index) + { + static foreach (i, f; functions) + case i: + mixin("return " ~ f ~ ";"); + } + } +``` +we unlock some very special abilities of D. Let's break it down: + +```d + enum functions = ["30.0 * exp(-z * z / 100.0)", /*...*/]; +``` +This defines an array of strings, each containing a mathematical expression. Due to the `enum` keyword, this is an +array that really only exists at compile-time. + +```d + size_t index = uniform(0, functions.length); +``` +This defines a random index into the array. `functions.length` is evaluated at compile-time, due to D's compile-time +function evaluation (CTFE). + +```d + writeln(center("f(z) = " ~ functions[index], width), "\n"); +``` +Unmistakenly, this prints the formula centered on a line. What happens behind the scenes is that `functions` (which +only existed at compile-time before now) is pasted in, so that an instance of that array actually exists at run-time +at this spot, and is instantly indexed. + +```d + float fna(float z) + { + final switch (index) + { + // ... + } + } +``` +`static` has been dropped from the nested function because we want to evaluate `index` inside it. The function contains +an ordinary `switch`, with `final` providing some extra robustness. It disallows a `default` case and produces an error +when the switch doesn't handle all cases. The `switch` body is where the magic happens and consists of these three +lines: +```d + static foreach (i, f; functions) + case i: + mixin("return " ~ f ~ ";"); +``` +The `static foreach` iterates over `functions` at compile-time, producing one `case` for every element in `functions`. +`mixin` takes a string, which is constructed at compile-time, and pastes it right into the source. + +In effect, the implementation of `float fna(float z)` unrolls itself into +```d + float fna(float z) + { + final switch (index) + { + case 0: + return 30.0 * exp(-z * z / 100.0); + case 1: + return sqrt(900.01 - z * z) * .9 - 2; + case 2: + return 30 * (cos(z / 16.0) + .5); + case 3: + return 30 - 30 * sin(z / 18.0); + case 4: + return 30 * exp(-cos(z / 16.0)) - 30; + case 5: + return 30 * sin(z / 10.0)"; + } + } +``` + +So if you feel like adding another function, all you need to do is append it to the `functions` array, and the rest of +the program *rewrites itself...* diff --git a/87_3-D_Plot/d/threedeeplot.d b/87_3-D_Plot/d/threedeeplot.d new file mode 100644 index 00000000..a3660321 --- /dev/null +++ b/87_3-D_Plot/d/threedeeplot.d @@ -0,0 +1,35 @@ +@safe: // Make @safe the default for this file, enforcing memory-safety. +import std.stdio, std.string, std.math, std.range, std.conv, std.algorithm; + +void main() +{ + enum width = 80; + writeln(center("3D Plot", width)); + writeln(center("(After Creative Computing Morristown, New Jersey)\n\n\n", width)); + + static float fna(float z) + { + return 30.0 * exp(-z * z / 100.0); + } + + char[] row; + + for (float x = -30.0; x <= 30.0; x += 1.5) + { + size_t max_z = 0L; + auto y1 = 5 * floor((sqrt(900 - x * x)) / 5.0); + for (float y = y1; y >= -y1; y -= 5) + { + auto z = to!size_t(max(0, floor(25 + fna(sqrt(x * x + y * y)) - .7 * y))); + if (z > max_z) // Visible + { + max_z = z; + if (z + 1 > row.length) // row needs to grow + row ~= ' '.repeat(z + 1 - row.length).array; + row[z] = '*'; + } + } + writeln(row); + row = null; + } +} diff --git a/87_3-D_Plot/d/threedeeplot_random.d b/87_3-D_Plot/d/threedeeplot_random.d new file mode 100644 index 00000000..3db1a2cd --- /dev/null +++ b/87_3-D_Plot/d/threedeeplot_random.d @@ -0,0 +1,50 @@ +@safe: // Make @safe the default for this file, enforcing memory-safety. +import std.stdio, std.string, std.math, std.range, std.conv, std.random, std.algorithm; + +void main() +{ + enum width = 80; + writeln(center("3D Plot", width)); + writeln(center("(After Creative Computing Morristown, New Jersey)\n\n", width)); + + enum functions = ["30.0 * exp(-z * z / 100.0)", + "sqrt(900.01 - z * z) * .9 - 2", + "30 * (cos(z / 16.0) + .5)", + "30 - 30 * sin(z / 18.0)", + "30 * exp(-cos(z / 16.0)) - 30", + "30 * sin(z / 10.0)"]; + + size_t index = uniform(0, functions.length); + writeln(center("f(z) = " ~ functions[index], width), "\n"); + + float fna(float z) + { + final switch (index) + { + static foreach (i, f; functions) + case i: + mixin("return " ~ f ~ ";"); + } + } + + char[] row; + + for (float x = -30.0; x <= 30.0; x += 1.5) + { + size_t max_z = 0L; + auto y1 = 5 * lrint((sqrt(900 - x * x)) / 5.0); + for (float y = y1; y >= -y1; y -= 5) + { + auto z = to!size_t(max(0, lrint(25 + fna(sqrt(x * x + y * y)) - .7 * y))); + if (z > max_z) // Visible + { + max_z = z; + if (z + 1 > row.length) // row needs to grow + row ~= ' '.repeat(z + 1 - row.length).array; + row[z] = '*'; + } + } + writeln(row); + row = null; + } +} From b250689f378aff08202fa72e735f233c2f45f109 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 12:20:07 -0500 Subject: [PATCH 597/749] Use Map instead of 2d array --- 48_High_IQ/java/src/Board.java | 36 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/48_High_IQ/java/src/Board.java b/48_High_IQ/java/src/Board.java index 6a320bd1..8d183675 100644 --- a/48_High_IQ/java/src/Board.java +++ b/48_High_IQ/java/src/Board.java @@ -1,25 +1,27 @@ +import java.util.Map; +import java.util.HashMap; + public class Board { - private int[][] board; + private final Map board; public Board() { - board = new int[7][7]; - - //Set all of the corners to -1, and place pegs in proper spaces - for(int i = 0; i < 7; i++) { - for(int j = 0; j < 7; j++) { - if((i < 3 || i > 5) && (j < 3 || j > 5)) { - //If both i and j are either less than 3 or greater than 5, then the index is a corner - board[i][j] = -1; - } else if(i == 4 && j == 4) { - //Do not place a peg in the center - board[i][j] = 0; - } else { - //Place a peg everywhere else - board[i][j] = 1; - } - } + board = new HashMap<>(); + + int[] locations = new int[] {13,14,15, + 22,23,24, + 29,30,31,32,33,34,35, + 38,39,40,42,43,44, + 47,48,49,50,51,52,53, + 58,59,60, + 67,68,69}; + + for(int i : locations) { + //put board(i) in } + + //set the center position as 0 + } public String toString() { From 4a44f5097a1b97dde887f2b1348a84b5db41869a Mon Sep 17 00:00:00 2001 From: Yash Chauhan <68198489+ITrustNumbers@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:19:34 +0530 Subject: [PATCH 598/749] Ported the Traditional NIM Game into python 3 I just completed the NIM(Traditional Version) game in python. Hope it works as expected --- 65_Nim/python/Traditional_NIM.py | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 65_Nim/python/Traditional_NIM.py diff --git a/65_Nim/python/Traditional_NIM.py b/65_Nim/python/Traditional_NIM.py new file mode 100644 index 00000000..5c01ee2e --- /dev/null +++ b/65_Nim/python/Traditional_NIM.py @@ -0,0 +1,126 @@ +import random + +#Class of the Game +class NIM: + + def __init__(self): + + self.Piles = { + 1 : 7, + 2 : 5, + 3 : 3, + 4 : 1 + } + + def Remove_pegs(self, command): + + try: + + pile, num = command.split(',') + num = int(num) + pile = int(pile) + + except Exception as e: + + if 'not enough values' in str(e): + print('\nNot a valid command. Your command should be in the form of "1,3", Try Again\n') + + else: + print('\nError, Try again\n') + return None + + if self._command_integrity(num, pile) == True: + self.Piles[pile] -= num + else: + print('\nInvalid value of either Peg or Pile\n') + + def get_AI_move(self): + + possible_pile = [] + for k,v in self.Piles.items(): + if v != 0: + possible_pile.append(k) + + pile = random.choice(possible_pile) + + num = random.randint(1,self.Piles[pile]) + + return pile, num + + def _command_integrity(self, num, pile): + + if pile <= 4 and pile >= 1: + if num <= self.Piles[pile]: + return True + + return False + + def print_pegs(self): + + for pile, peg in self.Piles.items(): + print('Pile {} : {}'.format(pile, 'O '*peg)) + + def Help(self): + + print('-'*10) + print('\nThe Game is player with a number of Piles of Objects("O" == one peg)') + print('\nThe Piles are arranged as given below(Tradional NIM)\n') + self.print_pegs() + print('\nAny Number of of Objects are removed one pile by "YOU" and the machine alternatively') + print('\nOn your turn, you may take all the objects that remain in any pile') + print('but you must take ATLEAST one object') + print('\nAnd you may take objects from only one pile on a single turn.') + print('\nThe winner is defined as the one that picks the last remaning object') + print('-'*10) + + def Checkforwin(self): + + sum = 0 + for k,v in self.Piles.items(): + sum += v + + if sum == 0: + return True + + else: + return False + +#main program +if __name__ == "__main__": + + #Game initialization + game = NIM() + + print('Hello, This is a game of NIM') + help = input('Do You Need Instruction (YES or NO): ') + + if help == 'yes' or help == 'YES' or help == 'Yes': + + #Printing Game Instruction + game.Help() + + #Start game loop + input('\nPress Enter to start the Game:\n') + End = False + while True: + + game.print_pegs() + + #Players Move + command = input('\nYOUR MOVE - Number of PILE, Number of Object? ') + game.Remove_pegs(command) + End = game.Checkforwin() + if End == True: + print('Player Wins the Game, Congratulations!!') + input('Press any key to exit') + break + + #Computers Move + command = game.get_AI_move() + print('\nA.I MOVE - A.I Removed {} pegs from Pile {}'.format(command[1],command[0])) + game.Remove_pegs(str(command[0]) +',' + str(command[1])) + End = game.Checkforwin() + if End == True: + print('\nComputer Wins the Game, Better Luck Next Time\n') + input('Press any key to exit') + break From df70eca658dc62f31ac5897ae5ab206a16582875 Mon Sep 17 00:00:00 2001 From: Yash Chauhan <68198489+ITrustNumbers@users.noreply.github.com> Date: Thu, 6 Jan 2022 00:36:48 +0530 Subject: [PATCH 599/749] Minor Changes to the Traditional NIM --- 65_Nim/python/Traditional_NIM.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/65_Nim/python/Traditional_NIM.py b/65_Nim/python/Traditional_NIM.py index 5c01ee2e..3507ecc2 100644 --- a/65_Nim/python/Traditional_NIM.py +++ b/65_Nim/python/Traditional_NIM.py @@ -111,8 +111,8 @@ if __name__ == "__main__": game.Remove_pegs(command) End = game.Checkforwin() if End == True: - print('Player Wins the Game, Congratulations!!') - input('Press any key to exit') + print('\nPlayer Wins the Game, Congratulations!!') + input('\nPress any key to exit') break #Computers Move From f34bf73563db35671a930fad7d8d6a08f54e3703 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Wed, 5 Jan 2022 16:07:54 -0300 Subject: [PATCH 600/749] Aded synonym ruby port --- 85_Synonym/ruby/synonim.rb | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 85_Synonym/ruby/synonim.rb diff --git a/85_Synonym/ruby/synonim.rb b/85_Synonym/ruby/synonim.rb new file mode 100644 index 00000000..f4dcb558 --- /dev/null +++ b/85_Synonym/ruby/synonim.rb @@ -0,0 +1,59 @@ + + +puts <<~INSTRUCTIONS + SYNONYM + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + +A SYNONYM OF A WORD MEANS ANOTHER WORD IN THE ENGLISH +LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME MEANING. +I CHOOSE A WORD -- YOU TYPE A SYNONYM. +IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP' +AND I WILL TELL YOU A SYNONYM. + + +INSTRUCTIONS + +right_words = ["RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"] + +synonym_words = [ + ["FIRST", "START", "BEGINNING", "ONSET", "INITIAL"], + ["SIMILAR", "ALIKE", "SAME", "LIKE", "RESEMBLING"], + ["MODEL", "PATTERN", "PROTOTYPE", "STANDARD", "CRITERION"], + ["SMALL", "INSIGNIFICANT", "LITTLE", "TINY", "MINUTE"], + ["STOP", "HALT", "STAY", "ARREST", "CHECK", "STANDSTILL"], + ["HOUSE", "DWELLING", "RESIDENCE", "DOMICILE", "LODGING", "HABITATION"], + ["PIT", "HOLE", "HOLLOW", "WELL", "GULF", "CHASM", "ABYSS"], + ["PUSH", "SHOVE", "THRUST", "PROD", "POKE", "BUTT", "PRESS"], + ["RED", "ROUGE", "SCARLET", "CRIMSON", "FLAME", "RUBY"], + ["PAIN", "SUFFERING", "HURT", "MISERY", "DISTRESS", "ACHE", "DISCOMFORT"], +] + +synonym_words.shuffle.each {|words_ar| + +} + + +synonym_words.each {|words_ar| + answer = false + keyword = words_ar.shift + + while not answer and words_ar.length != 0 + puts " WHAT IS A SYNONYM OF #{keyword}? " + inp = gets.chomp.upcase + + if inp == "HELP" + clue = words_ar.sample + puts "**** A SYNONYM OF #{keyword} IS #{clue}." + words_ar.delete(clue) + elsif words_ar.include? inp + puts right_words.sample + answer = true + else + puts "TRY AGAIN." + end + + end + +} + +puts "SYNONYM DRILL COMPLETED" \ No newline at end of file From fd489bf3da56b950c1ca12f68af9eb5f94c357f2 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Wed, 5 Jan 2022 14:30:02 -0500 Subject: [PATCH 601/749] Using single class --- 48_High_IQ/java/src/Board.java | 30 ------------ 48_High_IQ/java/src/HighIQ.java | 82 +++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 38 deletions(-) delete mode 100644 48_High_IQ/java/src/Board.java diff --git a/48_High_IQ/java/src/Board.java b/48_High_IQ/java/src/Board.java deleted file mode 100644 index 8d183675..00000000 --- a/48_High_IQ/java/src/Board.java +++ /dev/null @@ -1,30 +0,0 @@ -import java.util.Map; -import java.util.HashMap; - -public class Board { - - private final Map board; - - public Board() { - board = new HashMap<>(); - - int[] locations = new int[] {13,14,15, - 22,23,24, - 29,30,31,32,33,34,35, - 38,39,40,42,43,44, - 47,48,49,50,51,52,53, - 58,59,60, - 67,68,69}; - - for(int i : locations) { - //put board(i) in - } - - //set the center position as 0 - - } - - public String toString() { - return ""; - } -} diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 2516bb1b..cf0c05ab 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -1,10 +1,76 @@ +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + public class HighIQ { - - public HighIQ() { - - } - - public void play() { - - } + + private Map board; + private PrintStream out; + private Scanner scanner; + + public HighIQ() { + out = System.out; + scanner = new Scanner(System.in); + board = new HashMap<>(); + + //Set of all locations to put initial pegs on + int[] locations = new int[]{ + 13, 14, 15, 22, 23, 24, 29, 30, 31, 32, 33, 34, 35, 38, 39, 40, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 58, 59, 60, 67, 68, 69 + }; + + for (int i : locations) { + board.put(i, true); + } + + board.put(41, false); + } + + public boolean move() { + System.out.println("MOVE WHICH PIECE"); + int from = scanner.nextInt(); + + //using the getOrDefault, which will make the statement false if it is an invalid position + if(!board.getOrDefault(from,false)) { + return false; + } + + System.out.println("TO WHERE"); + int to = scanner.nextInt(); + + if(board.getOrDefault(to,true)) { + return false; + } + + //Do nothing if they are the same + if(from == to) { + return true; + } + + //using the difference to check if the relative locations are valid + int difference = Math.abs(to - from); + if(difference != 2 && difference != 18) { + return false; + } + + //check if there is a peg between from and to + if(!board.getOrDefault((to + from) / 2,false)) { + return false; + } + + return true; + } + + public void play() { + while(true) { + while(!move()) { + System.out.println("ILLEGAL MOVE, TRY AGAIN..."); + + } + } + } + + public void printBoard() { + + } } From 6a43be82295eb141b729e282b3b07fd469155e40 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Wed, 5 Jan 2022 16:42:43 -0300 Subject: [PATCH 602/749] Added history and porting comments --- 85_Synonym/ruby/synonim.rb | 39 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/85_Synonym/ruby/synonim.rb b/85_Synonym/ruby/synonim.rb index f4dcb558..6334104a 100644 --- a/85_Synonym/ruby/synonim.rb +++ b/85_Synonym/ruby/synonim.rb @@ -1,4 +1,25 @@ - +######################################################## +# +# Synonym +# +# From Basic Computer Games (1978) +# +#A synonym of a word is another word (in the English language) which has the same, +#or very nearly the same, meaning. This program tests your knowledge of synonyms +#of a few common words. +# +#The computer chooses a word and asks you for a synonym. The computer then tells +#you whether you’re right or wrong. If you can’t think of a synonym, type “HELP” +#which causes a synonym to be printed. +#You may put in words of your choice in the data statements. +#The number following DATA in Statement 500 is the total number of data statements. +#In each data statement, the first number is the number of words in that statement. +# +#Can you think of a way to make this into a more general kind of CAI program for any subject? +#Walt Koetke of Lexington High School, Massachusetts created this program. +# +# +######################################################## puts <<~INSTRUCTIONS SYNONYM @@ -56,4 +77,18 @@ synonym_words.each {|words_ar| } -puts "SYNONYM DRILL COMPLETED" \ No newline at end of file +puts "SYNONYM DRILL COMPLETED" + + +###################################################################### +# +# Porting notes +# +# There is a bug in the original program where if you keep asking for +# synoyms of a given word it ends up running out of synonyms +# in the array and the program crashes. +# The bug has been fixed in this version and now when +# it runs out of words it continues with the next +# array. +# +###################################################################### From f85645fceec41fd2f7786a2b9ecffa3c8c856711 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Wed, 5 Jan 2022 16:45:12 -0300 Subject: [PATCH 603/749] Formatting comments --- 85_Synonym/ruby/synonim.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/85_Synonym/ruby/synonim.rb b/85_Synonym/ruby/synonim.rb index 6334104a..92d2e8c7 100644 --- a/85_Synonym/ruby/synonim.rb +++ b/85_Synonym/ruby/synonim.rb @@ -4,19 +4,19 @@ # # From Basic Computer Games (1978) # -#A synonym of a word is another word (in the English language) which has the same, -#or very nearly the same, meaning. This program tests your knowledge of synonyms -#of a few common words. +# A synonym of a word is another word (in the English language) which has the same, +# or very nearly the same, meaning. This program tests your knowledge of synonyms +# of a few common words. # -#The computer chooses a word and asks you for a synonym. The computer then tells -#you whether you’re right or wrong. If you can’t think of a synonym, type “HELP” -#which causes a synonym to be printed. -#You may put in words of your choice in the data statements. -#The number following DATA in Statement 500 is the total number of data statements. -#In each data statement, the first number is the number of words in that statement. +# The computer chooses a word and asks you for a synonym. The computer then tells +# you whether you’re right or wrong. If you can’t think of a synonym, type “HELP” +# which causes a synonym to be printed. +# You may put in words of your choice in the data statements. +# The number following DATA in Statement 500 is the total number of data statements. +# In each data statement, the first number is the number of words in that statement. # -#Can you think of a way to make this into a more general kind of CAI program for any subject? -#Walt Koetke of Lexington High School, Massachusetts created this program. +# Can you think of a way to make this into a more general kind of CAI program for any subject? +# Walt Koetke of Lexington High School, Massachusetts created this program. # # ######################################################## From f74537329b88473a1061061f2d877857bf454cff Mon Sep 17 00:00:00 2001 From: Yash Chauhan <68198489+ITrustNumbers@users.noreply.github.com> Date: Thu, 6 Jan 2022 03:03:02 +0530 Subject: [PATCH 604/749] Ported Chief game to Python --- 25_Chief/python/Chief.py | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 25_Chief/python/Chief.py diff --git a/25_Chief/python/Chief.py b/25_Chief/python/Chief.py new file mode 100644 index 00000000..67b4eab8 --- /dev/null +++ b/25_Chief/python/Chief.py @@ -0,0 +1,77 @@ +def print_lightning_bolt(): + + print('*'*36) + n = 24 + while n > 16: + print(' '*n + 'x x') + n -=1 + print(' '*16 + 'x xxx') + print(' '*15 + 'x x') + print(' '*14+ 'xxx x') + n -=1 + while n > 8: + print(' '*n + 'x x') + n -=1 + print(' '*8 + 'xx') + print(' '*7 +'x') + print('*'*36) + + +def print_solution(n): + + print('\n{} plus 3 gives {}. This Divided by 5 equals {}'.format(n, n+3, (n+3)/5)) + print('This times 8 gives {}. If we divide 5 and add 5.'.format(( (n+3)/5 )*8 )) + print('We get {}, which, minus 1 equals {}'.format(( ((n+3)/5)*8)/5+5, ((((n+3)/5)*8)/5+5)-1 )) + +def Game(): + print('\nTake a Number and ADD 3. Now, Divide this number by 5 and') + print('multiply by 8. Now, Divide by 5 and add the same. Subtract 1') + + resp = float(input('\nWhat do you have? ')) + comp_guess = (((resp - 4)*5)/8)*5 -3 + resp2 = input('\nI bet your number was {} was i right(Yes or No)? '.format(comp_guess)) + + if resp2 == 'Yes' or resp2 == 'YES' or resp2 == 'yes': + print('\nHuh, I Knew I was unbeatable') + print('And here is how i did it') + print_solution(comp_guess) + input('') + + else: + resp3 = float(input('\nHUH!! what was you original number? ')) + + if resp3 == comp_guess: + print('\nThat was my guess, AHA i was right') + print("Shamed to accept defeat i guess, don't worry you can master mathematics too") + print('Here is how i did it') + print_solution(comp_guess) + input('') + + else: + print('\nSo you think you\'re so smart, EH?') + print('Now, Watch') + print_solution(resp3) + + resp4 = input('\nNow do you believe me? ') + + if resp4 == 'Yes' or resp4 == 'YES' or resp4 == 'yes': + print('\nOk, Lets play again sometime bye!!!!') + input('') + + else: + print('\nYOU HAVE MADE ME VERY MAD!!!!!') + print("BY THE WRATH OF THE MATHEMATICS AND THE RAGE OF THE GODS") + print("THERE SHALL BE LIGHTNING!!!!!!!") + print_lightning_bolt() + print('\nI Hope you believe me now, for your own sake') + input('') + +if __name__ == '__main__': + + print('I am CHIEF NUMBERS FREEK, The GREAT INDIAN MATH GOD.') + play = input('\nAre you ready to take the test you called me out for(Yes or No)? ') + if play == 'Yes' or play == 'YES' or play == 'yes': + Game() + else: + print('Ok, Nevermind. Let me go back to my great slumber, Bye') + input('') From 56ccff2d55d16b71f16956f893ec17bfee4cae6e Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 5 Jan 2022 19:48:19 -0800 Subject: [PATCH 605/749] improve input handling of numeric values --- 81_Splat/java/src/Splat.java | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/81_Splat/java/src/Splat.java b/81_Splat/java/src/Splat.java index b76c82ff..e042c326 100644 --- a/81_Splat/java/src/Splat.java +++ b/81_Splat/java/src/Splat.java @@ -39,8 +39,7 @@ public class Splat { 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(); + float freefallTime = promptFloat("HOW MANY SECONDS "); System.out.println("HERE WE GO.\n"); System.out.println("TIME (SEC) DIST TO FALL (FT)"); System.out.println("========== ================="); @@ -73,18 +72,28 @@ public class Splat { private float promptTerminalVelocity() { if (askYesNo("SELECT YOUR OWN TERMINAL VELOCITY")) { - System.out.print("WHAT TERMINAL VELOCITY (MI/HR) "); - return mphToFeetPerSec(scanner.nextFloat()); + float terminalVelocity = promptFloat("WHAT TERMINAL VELOCITY (MI/HR) "); + return mphToFeetPerSec(terminalVelocity); } float terminalVelocity = (int) (1000 * random.nextFloat()); System.out.printf("OK. TERMINAL VELOCITY = %.2f MI/HR\n", terminalVelocity); return mphToFeetPerSec(terminalVelocity); } + private float promptFloat(String prompt){ + while(true){ + System.out.print(prompt); + try { + return scanner.nextFloat(); + } catch (Exception e) { + scanner.next(); // clear current input + } + } + } + private float promptGravitationalAcceleration() { if (askYesNo("WANT TO SELECT ACCELERATION DUE TO GRAVITY")) { - System.out.print("WHAT ACCELERATION (FT/SEC/SEC) "); - return scanner.nextFloat(); + return promptFloat("WHAT ACCELERATION (FT/SEC/SEC) "); } return chooseRandomAcceleration(); } From e6586027238a750768fd6cc75b226eec87086bd2 Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 5 Jan 2022 20:17:52 -0600 Subject: [PATCH 606/749] initial implementation of FlipFlop in Ruby --- 36_Flip_Flop/ruby/flipflop.rb | 162 ++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 36_Flip_Flop/ruby/flipflop.rb diff --git a/36_Flip_Flop/ruby/flipflop.rb b/36_Flip_Flop/ruby/flipflop.rb new file mode 100644 index 00000000..3a65a4c2 --- /dev/null +++ b/36_Flip_Flop/ruby/flipflop.rb @@ -0,0 +1,162 @@ +#A class representing the internal state of a single game of flip flop +# state represents the list of X's (A in the original code) +# guesses represents the number of guesses the user has made (C in the original code) +# seed represents the random seed for an instance of the game (Q in the original code) +Game = Struct.new(:state, :guesses, :seed) do + + #The original BASIC program used 1 indexed arrays while Ruby has 0-indexed arrays. + #We can't use 0 indexed arrays for the flip functions or we'll get divide by zero errors. + #These convenience functions allow us to modify and access internal game state in a 1-indexed fashion + def flip_letter(letter_number) + index = letter_number -1 + if self.state[index] == 'X' + self.state[index] = 'O' + else + self.state[index] = 'X' + end + end + + def letter_at(letter_number) + self.state[letter_number - 1] + end +end + +def print_welcome + puts 'FLIPFLOP'.center(72) + puts 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'.center(72) + puts <<~EOS + + THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS: + + X X X X X X X X X X + + TO THIS: + + O O O O O O O O O O + + BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE + LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON + OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0 + (ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE + 11 (ELEVEN). + EOS +end + +def print_starting_message + puts <<~EOS + + HERE IS THE STARTING LINE OF X'S. + + 1 2 3 4 5 6 7 8 9 10 + X X X X X X X X X X + + EOS +end + +#Create a new game with [X,X,X,X,X,X,X,X,X,X] as the state +#0 as the number of guesses and a random seed between 0 and 1 +def generate_new_game + Game.new(Array.new(10, 'X'), 0, rand()) +end + +#Given a game, an index, and a shuffle function, flip one or more letters +def shuffle_board(game, index, shuffle_function) + n = method(shuffle_function).call(game, index) + + if game.letter_at(n) == "O" + game.flip_letter(n) + if index == n + n = shuffle_board(game, index, shuffle_function) + end + else + game.flip_letter(n) + end + return n +end + +#Shuffle logic copied from original BASIC code +def shuffle_function1(game, index) + r = Math.tan(game.seed + index / game.seed - index) - Math.sin(game.seed / index) + 336 * Math.sin(8 * index) + n = r - r.floor + (10 * n).floor +end + +def shuffle_function2(game, index) + r = 0.592 * (1/ Math.tan(game.seed / index + game.seed)) / Math.sin(index * 2 + game.seed) - Math.cos(index) + n = r - r.floor + (10 * n) +end + +def play_game + print_starting_message + game = generate_new_game + working_index = nil + + loop do + puts "INPUT THE NUMBER" + input = gets.chomp.downcase + + #See if the user input a valid integer, fail otherwise + if numeric_input = Integer(input, exception: false) + + #If 11 is entered, we're done with this version of the game + if numeric_input == 11 + return :restart + end + + if numeric_input > 11 + puts 'ILLEGAL ENTRY--TRY AGAIN.' + next #illegal entries don't count towards your guesses + end + + if working_index == numeric_input + game.flip_letter(numeric_input) + working_index = shuffle_board(game, numeric_input, :shuffle_function2) + #If 0 is entered, we want to reset the state, but not the random seed or number of guesses and keep playing + elsif numeric_input == 0 + game.state = Array.new(10, 'X') + elsif game.letter_at(numeric_input) == "O" + game.flip_letter(numeric_input) + if numeric_input == working_index + working_index = shuffle_board(game, numeric_input, :shuffle_function1) + end + else + game.flip_letter(numeric_input) + working_index = shuffle_board(game, numeric_input, :shuffle_function1) + end + else + puts 'ILLEGAL ENTRY--TRY AGAIN.' + next #illegal entries don't count towards your guesses + end + + game.guesses += 1 + puts '1 2 3 4 5 6 7 8 9 10' + puts game.state.join(' ') + + if game.state.all? { |x| x == 'O' } + if game.guesses > 12 + puts "TRY HARDER NEXT TIME. IT TOOK YOU #{game.guesses} GUESSES." + else + puts "VERY GOOD. YOU GUESSED IT IN ONLY #{game.guesses} GUESSES." + end + #game is complete + return + end + end +end + + + +#Execution starts +print_welcome +loop do + result = play_game + if result == :restart + next + end + + puts 'DO YOU WANT TO TRY ANOTHER PUZZLE' + if gets.chomp.downcase[0] == 'n' + break + end +end From aed1f65c761348a046a39bfe8e3e097b8661972a Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Thu, 6 Jan 2022 01:24:44 -0500 Subject: [PATCH 607/749] 11_Bombardment in Perl A version of bombardment written in perl --- 11_Bombardment/perl/bombardment.pl | 129 +++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 11_Bombardment/perl/bombardment.pl diff --git a/11_Bombardment/perl/bombardment.pl b/11_Bombardment/perl/bombardment.pl new file mode 100644 index 00000000..593bd9fa --- /dev/null +++ b/11_Bombardment/perl/bombardment.pl @@ -0,0 +1,129 @@ +#!/usr/bin/perl + +use strict; +use warnings; + + +#GLOBAL +my %player_bases; +my %computer_bases; +my %player_choices; +my %computer_choices; + +&main; + +sub main { + &print_intro; + &display_field; + &populate_computer_bases; + &populate_player_bases; + &game_play; +} + +sub game_play { + until (keys %computer_bases == 0 || keys %player_bases == 0) { + &player_turn; + if (keys %computer_bases == 0) { + exit; + } + &computer_turn; + } + exit; +} + +sub computer_turn { + # There is logic in here to ensure that the computer doesn't try to pick a target it has already picked + my $valid_choice = 0; + until ($valid_choice == 1) { + my $target = int(rand(25)+1); + if (exists $computer_choices{$target}) { + $valid_choice = 0; + } + else { + $valid_choice = 1; + $computer_choices{$target}=1; + if (exists $player_bases{$target}) { + delete($player_bases{$target}); + my $size = keys %player_bases; + if ($size > 0) { + print "I GOT YOU. IT WON'T BE LONG NOW. POST $target WAS HIT.\n"; + if ($size == 3) { print "YOU HAVE ONLY THREE OUTPOSTS LEFT.\n"}; + if ($size == 2) { print "YOU HAVE ONLY TWO OUTPOSTS LEFT.\n"}; + if ($size == 1) { print "YOU HAVE ONLY ONE OUTPOSTS LEFT.\n"}; + } + else { + print "YOU'RE DEAD. YOUR LAST OUTPOST WAS AT $target. HA, HA, HA.\nBETTER LUCK NEXT TIME\n"; + } + + } + else { + print "I MISSED YOU, YOU DIRTY RAT. I PICKED $target. YOUR TURN:\n"; + } + } + } +} + +sub player_turn { + print "WHERE DO YOU WISH TO FIRE YOUR MISSILE\n"; + chomp(my $target=); + if (exists $computer_bases{$target}) { + print "YOU GOT ONE OF MY OUTPOSTS!\n"; + delete($computer_bases{$target}); + my $size = keys %computer_bases; + if ($size == 3) { print "ONE DOWN, THREE TO GO.\n"}; + if ($size == 2) { print "TWO DOWN, TWO TO GO.\n"}; + if ($size == 1) { print "THREE DOWN, ONE TO GO.\n"}; + if ($size == 0) { print "YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN\nMY TRANSISTO&S RECUP%RA*E!\n"}; + } + else { + print "HA, HA YOU MISSED. MY TURN NOW:\n"; + } +} + +sub populate_player_bases { + print "WHAT ARE YOUR FOUR POSITIONS\n"; + my $positions=; + chomp($positions); + my @positions = split/ /,$positions; + foreach my $base (@positions) { + $player_bases{$base}=0; + } +} + +sub display_field { + for my $num (1..25) { + if (length($num) < 2) { + $num = " $num"; + } + print "$num "; + if ($num % 5 == 0) { + print "\n"; + } + } +} + +sub populate_computer_bases { + my $size = 0; + until ($size == 4) { + my $base = int(rand(25)+1); + $computer_bases{$base}=0; + $size = keys %computer_bases; + } +} + +sub print_intro { + print "" * 33 + "BOMBARDMENT\n"; + print "" * 15 + " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; + print "\n\n"; + print "YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU\n"; + print "HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED.\n"; + print "YOU CAN ONLY PLACE ONE PLATOON AT ANY ONE OUTPOST.\n"; + print "THE COMPUTER DOES THE SAME WITH ITS FOUR PLATOONS.\n\n"; + print "THE OBJECT OF THE GAME IS TO FIRE MISSLES AT THE\n"; + print "OUTPOSTS OF THE COMPUTER. IT WILL DO THE SAME TO YOU.\n"; + print "THE ONE WHO DESTROYS ALL FOUR OF THE ENEMY'S PLATOONS\n"; + print "FIRST IS THE WINNER.\n"; + print "GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT!\n"; + print "TEAR OFF MATRIX AND USE IT TO CHECK OFF THE NUMBERS.\n"; + print "\n\n\n\n"; +} From 71c754190550fbebb0ac8ae92d4bef3cd8b7c94b Mon Sep 17 00:00:00 2001 From: John Long Date: Wed, 5 Jan 2022 23:22:46 -0800 Subject: [PATCH 608/749] Switch to readln readln throws an exception when a file hits EOF, wheras readLine returns null. That puts us in an infinite loop if we hit EOF. --- 03_Animal/kotlin/Animal.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/03_Animal/kotlin/Animal.kt b/03_Animal/kotlin/Animal.kt index bac9af08..90fc9f20 100644 --- a/03_Animal/kotlin/Animal.kt +++ b/03_Animal/kotlin/Animal.kt @@ -37,14 +37,14 @@ fun main() { // an answer or a blank string fun ask(question: String): String { print("$question? ") - return readLine()?.uppercase() ?: "" + return readln().uppercase() ?: "" } // Special case for a "yes or no" question, returns true of yes fun askYesOrNo(question: String): Boolean { return generateSequence { print("$question? ") - readLine() + readln() }.firstNotNullOf { yesOrNo(it) } } From f8cc93aaeab6f7a73ebc15e1a91957b75e794e5a Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 08:50:17 -0500 Subject: [PATCH 609/749] added getChar method --- 48_High_IQ/java/src/HighIQ.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index cf0c05ab..75426197 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -71,6 +71,17 @@ public class HighIQ { } public void printBoard() { - + + } + + private char getChar(int position) { + Boolean value = board.get(position); + if(value == null) { + return ' '; + } else if(value) { + return '!'; + } else { + return 'O'; + } } } From 918b42149e0f4abe2512eaf69343fb1cbe7baef5 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 08:52:12 -0500 Subject: [PATCH 610/749] Implemented Possible printBoard Doing this through web browser, so unsure if this will work or compile.. Will check later --- 48_High_IQ/java/src/HighIQ.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 75426197..93340556 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -71,7 +71,12 @@ public class HighIQ { } public void printBoard() { - + for(int i = 0; i < 7; i++) { + for(int j = 11; j < 18; j++) { + out.print(getChar(j + 9 * i)); + } + out.println(); + } } private char getChar(int position) { From 056c8cd4d971174bd68aed81708a2de1b39e59a2 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 09:06:15 -0500 Subject: [PATCH 611/749] Update HighIQ.java --- 48_High_IQ/java/src/HighIQ.java | 36 ++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 93340556..77e0e5ae 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -62,12 +62,38 @@ public class HighIQ { } public void play() { - while(true) { - while(!move()) { - System.out.println("ILLEGAL MOVE, TRY AGAIN..."); - + do { + do { + while(!move()) { + System.out.println("ILLEGAL MOVE, TRY AGAIN..."); + } + } while(!isGameFinished()); + + int pegCount = 0; + for(Integer key : board.getKeySet()) { + if(board.getOrDefault(key,false)) { + pegCount++; + } } - } + + out.println("YOU HAD " + pegCount + " PEGS REMAINING"); + + if(pegCount == 1) { + out.println("BRAVO! YOU MADE A PERFECT SCORE!"); + out.println("SAVE THIS PAPER AS A RECORD OF YOUR ACCOMPLISHMENT!"); + } + + } while(playAgain()); + } + + private boolean playAgain() { + out.println("PLAY AGAIN (YES OR NO)"); + return scanner.nextLine().toLowerCase().equals("yes"); + } + + + public boolean isGameFinished() { + return false; } public void printBoard() { From aaa8d6186061983dc6af1f8b7b9ec09c0b926353 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 09:34:20 -0500 Subject: [PATCH 612/749] Implemented GameFinished does it work? Unsure... --- 48_High_IQ/java/src/HighIQ.java | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 77e0e5ae..99d046fe 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -93,7 +93,26 @@ public class HighIQ { public boolean isGameFinished() { - return false; + for(Integer key : board.getKeySet()) { + if(board.get(key)) { + //Spacing is either 1 or 9 + for(int space = 1; space <= 9; space += 8) { + //Next val is the next spot, prev and next after are the two spots where the peg would go if a move was possible + Boolean nextVal = board.get(key + space); + Boolean prevAfter = board.get(key - space); + Boolean nextAfter = board.get(key + space * 2); + + if(nextVal != null && nextVal) { + if((prevAfter != null && !prevAfter) || (nextAfter != null && !nextAfter)) { + return false; + } + } + + } + } + + } + return true; } public void printBoard() { From 31dec710639d360536207692634a24b3e2bf108e Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 09:45:04 -0500 Subject: [PATCH 613/749] Simplified isGameFinished Unsure if I should simplify further --- 48_High_IQ/java/src/HighIQ.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 99d046fe..83cff254 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -96,18 +96,13 @@ public class HighIQ { for(Integer key : board.getKeySet()) { if(board.get(key)) { //Spacing is either 1 or 9 - for(int space = 1; space <= 9; space += 8) { - //Next val is the next spot, prev and next after are the two spots where the peg would go if a move was possible - Boolean nextVal = board.get(key + space); - Boolean prevAfter = board.get(key - space); - Boolean nextAfter = board.get(key + space * 2); - - if(nextVal != null && nextVal) { - if((prevAfter != null && !prevAfter) || (nextAfter != null && !nextAfter)) { - return false; - } + //Looking to the right and down from every point, checking for both directions of movement + for(int space : new int[] {1,9}) { + Boolean nextToPeg = board.getOrDefault(key + space,false); + Boolean hasMovableSpace = !board.getOrDefault(key - space,true) || !board.getOrDefault(key + space * 2, true); + if(nextToPeg && hasMovableSpace) { + return false; } - } } From e19a4aef19457cdb6256899c062b88e2580679fd Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 09:46:58 -0500 Subject: [PATCH 614/749] Added leaving comment --- 48_High_IQ/java/src/HighIQ.java | 1 + 1 file changed, 1 insertion(+) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 83cff254..b1a40831 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -84,6 +84,7 @@ public class HighIQ { } } while(playAgain()); + out.println("SO LONG FOR NOW."); } private boolean playAgain() { From 821ae4befe7bb7845e7fcea6f1f28a0308bd778a Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 10:02:44 -0500 Subject: [PATCH 615/749] Moving re-playability to other script --- 48_High_IQ/java/src/HighIQ.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index b1a40831..37fd6aa2 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -9,9 +9,9 @@ public class HighIQ { private PrintStream out; private Scanner scanner; - public HighIQ() { + public HighIQ(Scanner sccanner) { out = System.out; - scanner = new Scanner(System.in); + this.scanner = scanner; board = new HashMap<>(); //Set of all locations to put initial pegs on @@ -25,6 +25,7 @@ public class HighIQ { board.put(41, false); } + public boolean move() { System.out.println("MOVE WHICH PIECE"); @@ -63,7 +64,6 @@ public class HighIQ { public void play() { do { - do { while(!move()) { System.out.println("ILLEGAL MOVE, TRY AGAIN..."); } @@ -83,14 +83,12 @@ public class HighIQ { out.println("SAVE THIS PAPER AS A RECORD OF YOUR ACCOMPLISHMENT!"); } - } while(playAgain()); - out.println("SO LONG FOR NOW."); } - private boolean playAgain() { - out.println("PLAY AGAIN (YES OR NO)"); - return scanner.nextLine().toLowerCase().equals("yes"); - } +// private boolean playAgain() { +// out.println("PLAY AGAIN (YES OR NO)"); +// return scanner.nextLine().toLowerCase().equals("yes"); +// } public boolean isGameFinished() { From f5997021970a2ac6b278a5321430cf74553d0caf Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Thu, 6 Jan 2022 13:03:31 -0300 Subject: [PATCH 616/749] Added script to write a markdown TODO list of implementations for games --- 00_Utilities/markdown_todo.py | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 00_Utilities/markdown_todo.py diff --git a/00_Utilities/markdown_todo.py b/00_Utilities/markdown_todo.py new file mode 100644 index 00000000..accf1ac2 --- /dev/null +++ b/00_Utilities/markdown_todo.py @@ -0,0 +1,43 @@ +import os + + +lang_pos = { + "csharp": 1, "java": 2, "javascript": 3, + "pascal": 4, "perl": 5, "python": 6, "ruby": 7, "vbnet": 8 +} + +write_string = "# TODO list \n game | csharp | java | javascript | pascal | perl | python | ruby | vbnet \n --- | --- | --- | --- | --- | --- | --- | --- | --- \n" +# Set the directory you want to start from +rootDir = '..' + +checklist = ["game", "csharp", "java", "javascript", + "pascal", "perl", "python", "ruby", "vbnet"] + +prev_game = "" + +for dirName, subdirList, fileList in os.walk(rootDir): + split_dir = dirName.split("/") + + if len(split_dir) == 2 and not split_dir[1] in ['.git', '00_Utilities']: + if prev_game == "": + prev_game = split_dir[1] + checklist[0] = split_dir[1] + + if prev_game != split_dir[1]: + # it's a new dir + write_string += " | ".join(checklist) + "\n" + checklist = [split_dir[1], "csharp", "java", "javascript", + "pascal", "perl", "python", "ruby", "vbnet"] + prev_game = split_dir[1] + + elif len(split_dir) == 3 and split_dir[1] != '.git': + if split_dir[2] in lang_pos.keys(): + if len(fileList) > 1 or len(subdirList) > 0: + # there is more files than the readme + checklist[lang_pos[split_dir[2]]] = "✅" + else: + checklist[lang_pos[split_dir[2]]] = "⬜️" + + +with open("README.md", "w") as f: + f.write(write_string) From 08b299b3bb23a22f03dec849d460660a004ce946 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Thu, 6 Jan 2022 13:13:04 -0300 Subject: [PATCH 617/749] Sorted table --- 00_Utilities/markdown_todo.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/00_Utilities/markdown_todo.py b/00_Utilities/markdown_todo.py index accf1ac2..74e358c0 100644 --- a/00_Utilities/markdown_todo.py +++ b/00_Utilities/markdown_todo.py @@ -10,6 +10,8 @@ write_string = "# TODO list \n game | csharp | java | javascript | pascal | perl # Set the directory you want to start from rootDir = '..' +strings_done = [] + checklist = ["game", "csharp", "java", "javascript", "pascal", "perl", "python", "ruby", "vbnet"] @@ -25,7 +27,7 @@ for dirName, subdirList, fileList in os.walk(rootDir): if prev_game != split_dir[1]: # it's a new dir - write_string += " | ".join(checklist) + "\n" + strings_done.append(checklist) checklist = [split_dir[1], "csharp", "java", "javascript", "pascal", "perl", "python", "ruby", "vbnet"] prev_game = split_dir[1] @@ -39,5 +41,10 @@ for dirName, subdirList, fileList in os.walk(rootDir): checklist[lang_pos[split_dir[2]]] = "⬜️" +sorted_strings = list(map(lambda l: " | ".join(l) + "\n", + sorted(strings_done, key=lambda x: x[0]))) +write_string += ''.join(sorted_strings) + + with open("README.md", "w") as f: f.write(write_string) From 048b9c31a283b6b40bafd3480cd7cc5667f1eab6 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 11:38:17 -0500 Subject: [PATCH 618/749] Added re-playability --- 48_High_IQ/java/src/HighIQGame.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/48_High_IQ/java/src/HighIQGame.java b/48_High_IQ/java/src/HighIQGame.java index c7d4df9b..efbd09ec 100644 --- a/48_High_IQ/java/src/HighIQGame.java +++ b/48_High_IQ/java/src/HighIQGame.java @@ -1,5 +1,11 @@ +import java.util.Scanner; + public class HighIQGame { public static void main(String[] args) { - + Scanner scanner = new Scanner(System.in); + do { + new HighIQ(scanner).play(); + System.out.println("PLAY AGAIN (YES OR NO)"); + } while(scanner.nextLine().toLowerCase().equals("yes")); } } From 18016b59ed7f647cef92213243cb20ba8b689983 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 13:15:48 -0500 Subject: [PATCH 619/749] Typo Fixes --- 48_High_IQ/java/src/HighIQ.java | 6 +++--- 48_High_IQ/java/src/HighIQGame.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 37fd6aa2..37528748 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -9,7 +9,7 @@ public class HighIQ { private PrintStream out; private Scanner scanner; - public HighIQ(Scanner sccanner) { + public HighIQ(Scanner scanner) { out = System.out; this.scanner = scanner; board = new HashMap<>(); @@ -70,7 +70,7 @@ public class HighIQ { } while(!isGameFinished()); int pegCount = 0; - for(Integer key : board.getKeySet()) { + for(Integer key : board.keySet()) { if(board.getOrDefault(key,false)) { pegCount++; } @@ -92,7 +92,7 @@ public class HighIQ { public boolean isGameFinished() { - for(Integer key : board.getKeySet()) { + for(Integer key : board.keySet()) { if(board.get(key)) { //Spacing is either 1 or 9 //Looking to the right and down from every point, checking for both directions of movement diff --git a/48_High_IQ/java/src/HighIQGame.java b/48_High_IQ/java/src/HighIQGame.java index efbd09ec..4df22853 100644 --- a/48_High_IQ/java/src/HighIQGame.java +++ b/48_High_IQ/java/src/HighIQGame.java @@ -6,6 +6,6 @@ public class HighIQGame { do { new HighIQ(scanner).play(); System.out.println("PLAY AGAIN (YES OR NO)"); - } while(scanner.nextLine().toLowerCase().equals("yes")); + } while(scanner.nextLine().equalsIgnoreCase("yes")); } } From 45345d593d136668e36d63668eed61e124435f63 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 13:16:55 -0500 Subject: [PATCH 620/749] Reformatted Code --- 48_High_IQ/java/src/HighIQ.java | 84 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 37528748..5c3f31aa 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -5,7 +5,7 @@ import java.util.Scanner; public class HighIQ { - private Map board; + private Map board; private PrintStream out; private Scanner scanner; @@ -25,104 +25,100 @@ public class HighIQ { board.put(41, false); } - + + public void play() { + do { + while (!move()) { + System.out.println("ILLEGAL MOVE, TRY AGAIN..."); + } + } while (!isGameFinished()); + + int pegCount = 0; + for (Integer key : board.keySet()) { + if (board.getOrDefault(key, false)) { + pegCount++; + } + } + + out.println("YOU HAD " + pegCount + " PEGS REMAINING"); + + if (pegCount == 1) { + out.println("BRAVO! YOU MADE A PERFECT SCORE!"); + out.println("SAVE THIS PAPER AS A RECORD OF YOUR ACCOMPLISHMENT!"); + } + } public boolean move() { System.out.println("MOVE WHICH PIECE"); int from = scanner.nextInt(); //using the getOrDefault, which will make the statement false if it is an invalid position - if(!board.getOrDefault(from,false)) { + if (!board.getOrDefault(from, false)) { return false; } System.out.println("TO WHERE"); int to = scanner.nextInt(); - if(board.getOrDefault(to,true)) { + if (board.getOrDefault(to, true)) { return false; } //Do nothing if they are the same - if(from == to) { + if (from == to) { return true; } //using the difference to check if the relative locations are valid int difference = Math.abs(to - from); - if(difference != 2 && difference != 18) { + if (difference != 2 && difference != 18) { return false; } //check if there is a peg between from and to - if(!board.getOrDefault((to + from) / 2,false)) { + if (!board.getOrDefault((to + from) / 2, false)) { return false; } return true; } - public void play() { - do { - while(!move()) { - System.out.println("ILLEGAL MOVE, TRY AGAIN..."); - } - } while(!isGameFinished()); - - int pegCount = 0; - for(Integer key : board.keySet()) { - if(board.getOrDefault(key,false)) { - pegCount++; - } - } - - out.println("YOU HAD " + pegCount + " PEGS REMAINING"); - - if(pegCount == 1) { - out.println("BRAVO! YOU MADE A PERFECT SCORE!"); - out.println("SAVE THIS PAPER AS A RECORD OF YOUR ACCOMPLISHMENT!"); - } - - } - // private boolean playAgain() { // out.println("PLAY AGAIN (YES OR NO)"); // return scanner.nextLine().toLowerCase().equals("yes"); // } - - + public boolean isGameFinished() { - for(Integer key : board.keySet()) { - if(board.get(key)) { + for (Integer key : board.keySet()) { + if (board.get(key)) { //Spacing is either 1 or 9 //Looking to the right and down from every point, checking for both directions of movement - for(int space : new int[] {1,9}) { - Boolean nextToPeg = board.getOrDefault(key + space,false); - Boolean hasMovableSpace = !board.getOrDefault(key - space,true) || !board.getOrDefault(key + space * 2, true); - if(nextToPeg && hasMovableSpace) { + for (int space : new int[]{1, 9}) { + Boolean nextToPeg = board.getOrDefault(key + space, false); + Boolean hasMovableSpace = !board.getOrDefault(key - space, true) || !board.getOrDefault(key + space * 2, true); + if (nextToPeg && hasMovableSpace) { return false; } } } - } return true; } public void printBoard() { - for(int i = 0; i < 7; i++) { - for(int j = 11; j < 18; j++) { + for (int i = 0; i < 7; i++) { + for (int j = 11; j < 18; j++) { out.print(getChar(j + 9 * i)); } out.println(); } } - + private char getChar(int position) { Boolean value = board.get(position); - if(value == null) { + if (value == null) { return ' '; - } else if(value) { + } else if (value) { return '!'; } else { return 'O'; From 3d4f5c685adbb4865e707490474cf039efacd9c7 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 13:22:56 -0500 Subject: [PATCH 621/749] Added Instructions --- 48_High_IQ/java/src/HighIQ.java | 3 +++ 48_High_IQ/java/src/HighIQGame.java | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index 5c3f31aa..a0278771 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -27,7 +27,10 @@ public class HighIQ { } public void play() { + + do { + printBoard(); while (!move()) { System.out.println("ILLEGAL MOVE, TRY AGAIN..."); } diff --git a/48_High_IQ/java/src/HighIQGame.java b/48_High_IQ/java/src/HighIQGame.java index 4df22853..e74e5783 100644 --- a/48_High_IQ/java/src/HighIQGame.java +++ b/48_High_IQ/java/src/HighIQGame.java @@ -2,10 +2,34 @@ import java.util.Scanner; public class HighIQGame { public static void main(String[] args) { + + printInstructions(); + Scanner scanner = new Scanner(System.in); do { new HighIQ(scanner).play(); System.out.println("PLAY AGAIN (YES OR NO)"); } while(scanner.nextLine().equalsIgnoreCase("yes")); } + + public static void printInstructions() { + System.out.println("HERE IS THE BOARD:"); + System.out.println(" ! ! !"); + System.out.println(" 13 14 15\n"); + System.out.println(" ! ! !"); + System.out.println(" 22 23 24\n"); + System.out.println("! ! ! ! ! ! !"); + System.out.println("29 30 31 32 33 34 35\n"); + System.out.println("! ! ! ! ! ! !"); + System.out.println("38 39 40 41 42 43 44\n"); + System.out.println("! ! ! ! ! ! !"); + System.out.println("47 48 49 50 51 52 53\n"); + System.out.println(" ! ! !"); + System.out.println(" 58 59 60\n"); + System.out.println(" ! ! !"); + System.out.println(" 67 68 69"); + System.out.println("TO SAVE TYPING TIME, A COMPRESSED VERSION OF THE GAME BOARD"); + System.out.println("WILL BE USED DURING PLAY. REFER TO THE ABOVE ONE FOR PEG"); + System.out.println("NUMBERS. OK, LET'S BEGIN."); + } } From 110b77fccd5d8cbc956abae1c1538964ab9a8e27 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 13:35:37 -0500 Subject: [PATCH 622/749] Cleanup --- 48_High_IQ/java/src/HighIQ.java | 49 ++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/48_High_IQ/java/src/HighIQ.java b/48_High_IQ/java/src/HighIQ.java index a0278771..d77a2ec2 100644 --- a/48_High_IQ/java/src/HighIQ.java +++ b/48_High_IQ/java/src/HighIQ.java @@ -3,11 +3,25 @@ import java.util.HashMap; import java.util.Map; import java.util.Scanner; +/** + * Game of HighIQ + *

+ * Based on the Basic Game of HighIQ Here: + * https://github.com/coding-horror/basic-computer-games/blob/main/48_High_IQ/highiq.bas + * + * No additional functionality has been added + */ public class HighIQ { - private Map board; - private PrintStream out; - private Scanner scanner; + //Game board, as a map of position numbers to their values + private final Map board; + + //Output stream + private final PrintStream out; + + //Input scanner to use + private final Scanner scanner; + public HighIQ(Scanner scanner) { out = System.out; @@ -26,13 +40,14 @@ public class HighIQ { board.put(41, false); } + /** + * Plays the actual game, from start to finish. + */ public void play() { - - do { printBoard(); while (!move()) { - System.out.println("ILLEGAL MOVE, TRY AGAIN..."); + out.println("ILLEGAL MOVE, TRY AGAIN..."); } } while (!isGameFinished()); @@ -51,8 +66,12 @@ public class HighIQ { } } + /** + * Makes an individual move + * @return True if the move was valid, false if the user made an error and the move is invalid + */ public boolean move() { - System.out.println("MOVE WHICH PIECE"); + out.println("MOVE WHICH PIECE"); int from = scanner.nextInt(); //using the getOrDefault, which will make the statement false if it is an invalid position @@ -60,7 +79,7 @@ public class HighIQ { return false; } - System.out.println("TO WHERE"); + out.println("TO WHERE"); int to = scanner.nextInt(); if (board.getOrDefault(to, true)) { @@ -83,14 +102,18 @@ public class HighIQ { return false; } + //Actually move + board.put(from,false); + board.put(to,true); + board.put((from + to) / 2, false); + return true; } -// private boolean playAgain() { -// out.println("PLAY AGAIN (YES OR NO)"); -// return scanner.nextLine().toLowerCase().equals("yes"); -// } - + /** + * Checks if the game is finished + * @return True if there are no more moves, False otherwise + */ public boolean isGameFinished() { for (Integer key : board.keySet()) { if (board.get(key)) { From 60b84070c99624f8fa5d7db18c9d26d854b90686 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 13:40:28 -0500 Subject: [PATCH 623/749] Added Header --- 48_High_IQ/java/src/HighIQGame.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/48_High_IQ/java/src/HighIQGame.java b/48_High_IQ/java/src/HighIQGame.java index e74e5783..43400fb3 100644 --- a/48_High_IQ/java/src/HighIQGame.java +++ b/48_High_IQ/java/src/HighIQGame.java @@ -13,6 +13,8 @@ public class HighIQGame { } public static void printInstructions() { + System.out.println("\t\t\t H-I-Q"); + System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); System.out.println("HERE IS THE BOARD:"); System.out.println(" ! ! !"); System.out.println(" 13 14 15\n"); From 6ae9fbcd3676ad929d44c89b07d90dd415d83a4b Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 14:22:28 -0500 Subject: [PATCH 624/749] Initial Commit Added Instructions, Random mine placement, and the general layout --- 30_Cube/java/src/Cube.java | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 30_Cube/java/src/Cube.java diff --git a/30_Cube/java/src/Cube.java b/30_Cube/java/src/Cube.java new file mode 100644 index 00000000..2e19a691 --- /dev/null +++ b/30_Cube/java/src/Cube.java @@ -0,0 +1,80 @@ +import java.io.PrintStream; +import java.util.Random; + +public class Cube { + + private Location playerLocation; + private Location[] mines; + private PrintStream out; + + + public static void main(String[] args) { + new Cube().play(); + } + + public Cube() { + out = System.out; + } + + private void placeMines() { + mines = new Location[5]; + Random random = new Random(); + for(int i = 0; i < mines.length; i++) { + int x = random.nextInt(1,4); + int y = random.nextInt(1,4); + int z = random.nextInt(1,4); + mines[i] = new Location(x,y,z); + } + } + + public void play() { + + } + + public void printInstructions() { + out.println("THIS IS A GAME IN WHICH YOU WILL BE PLAYING AGAINST THE"); + out.println("RANDOM DECISION OF THE COMPUTER. THE FIELD OF PLAY IS A"); + out.println("CUBE OF SIDE 3. ANY OF THE 27 LOCATIONS CAN BE DESIGNATED"); + out.println("CUBE OF SIDE 3. ANY OF THE 27 LOCATIONS CAN BE DESIGNATED"); + out.println("BY INPUTTING THREE NUMBERS SUCH AS 2,3,1. AT THE START"); + out.println("YOU ARE AUTOMATICALLY AT LOCATION 1,1,1. THE OBJECT OF"); + out.println("THE GAME IS TO GET TO LOCATION 3,3,3. ONE MINOR DETAIL:"); + out.println("THE COMPUTER WILL PICK, AT RANDOM, 5 LOCATIONS AT WHICH"); + out.println("IT WILL PLANT LAND MINES. IF YOU HIT ONE OF THESE LOCATIONS"); + out.println("YOU LOSE. ONE OTHER DETAIL: YOU MAY MOVE ONLY ONE SPACE"); + out.println("IN ONE DIRECTION EACH MOVE. FOR EXAMPLE: FROM 1,1,2 YOU"); + out.println("MAY MOVE TO 2,1,2 OR 1,1,3. YOU MAY NOT CHANGE"); + out.println("TWO OF THE NUMBERS ON THE SAME MOVE. IF YOU MAKE AN ILLEGAL"); + out.println("MOVE, YOU LOSE AND THE COMPUTER TAKES THE MONEY YOU MAY"); + } + + public class Location { + int x,y,z; + + public Location(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Location location = (Location) o; + + if (x != location.x) return false; + if (y != location.y) return false; + return z == location.z; + } + + @Override + public int hashCode() { + int result = x; + result = 31 * result + y; + result = 31 * result + z; + return result; + } + } +} From 4d88281a17750b7dd00735c41b52d2f361114e8e Mon Sep 17 00:00:00 2001 From: Flavio Poletti Date: Thu, 6 Jan 2022 20:09:19 +0100 Subject: [PATCH 625/749] Add Perl for 04_Awari --- 04_Awari/perl/awari.pl | 267 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 04_Awari/perl/awari.pl diff --git a/04_Awari/perl/awari.pl b/04_Awari/perl/awari.pl new file mode 100644 index 00000000..3d70452c --- /dev/null +++ b/04_Awari/perl/awari.pl @@ -0,0 +1,267 @@ +#!/usr/bin/env perl +use v5.24; +use warnings; +use experimental 'signatures'; +no warnings 'experimental::signatures'; +use List::Util 'none'; + +# our board will be represented with an array of 14 slots, from 0 to 13. +# Positions 6 and 13 represent the "home pit" for the human and the +# computer, respectively. +use constant PLAYER_HOME => 6; +use constant COMPUTER_HOME => 13; + +use constant FIRST => 0; +use constant AGAIN => 1; + +exit main(@ARGV); + +sub main { + $|++; # disable buffering on standard output, every print will be + # done immediately + + welcome(); # startup message + + # this array will keep track of computer-side failures, defined as + # "the computer did not win". Whenever the computer loses or draws, the + # specific sequence of moves will be saved and then used to drive + # the search for a (hopefully) optimal move. + my $failures = []; + while ('enjoying') { + + # a new game starts, let's reset the board to the initial condition + my $board = [ (3) x 6, 0, (3) x 6, 0 ]; + + # this string will keep track of all moves performed + my $moves = '/'; + + # the human player starts + my $turn = 'player'; + + say "\n"; + print_board($board); + + while (not is_game_over($board)) { + + my $move; # this will collect the move in this turn + + if ($turn eq 'player') { # "first" move for player + + # player_move(...) does the move selected by the player, + # returning both the selected move as well as the pit id + # where the last seed landed + ($move, my $landing) = player_move($board); + + # if we landed on the Player's Home Pit we get another move + $turn = $landing == PLAYER_HOME ? 'player-again' : 'computer'; + } + elsif ($turn eq 'player-again') { # "second" move for player + + # here we call player_move making it clear that it's the + # second move, to get the right prompt eventually. We only + # care for the $move as the result, so we ignore the other. + ($move) = player_move($board, AGAIN); + $turn = 'computer'; + } + else { + + # the computer_move(...) function analyzes the $board as well + # as adapting the strategy based on past "failures" (i.e. + # matches where the computer did not win). For this it's + # important to pass the log of these failures, as well as the + # full record of moves in this specific match. + ($move, my $landing) = computer_move($board, $failures, $moves); + print "\nMY MOVE IS ", $move - 6; + + # do the second move in the turn if conditions apply + if ($landing == COMPUTER_HOME && ! is_game_over($board)) { + + # save the first move before doing the second one! + $moves .= "$move/"; + + my ($move) = computer_move($board, $failures, $moves); + print ',', $move - 6; + } + $turn = 'player'; + } + + # append the last selected move by either party, to track this + # specific match (useful for computer's AI and ML) + $moves .= "$move/"; + print_board($board); + } + + # assess_victory() returns the difference between player's and + # computer's seeds, so a negative value is a win for the computer. + my $computer_won = assess_victory($board) < 0; + + # if this last match was a "failure" (read: not a win for the + # computer), then record it for future memory. + push $failures->@*, $moves unless $computer_won; + } + + return 0; +} + +# calculate the difference between the two home pits. Negative values mean +# that the computer won, 0 is a draw, positive values is a player's win. +# The difference is also returned back, in case of need. +sub assess_victory ($board) { + say "\nGAME OVER"; + my $difference = $board->[PLAYER_HOME] - $board->[COMPUTER_HOME]; + if ($difference < 0) { + say 'I WIN BY ', -$difference, ' POINTS'; + } + else { + say $difference ? "YOU WIN BY $difference POINTS" : 'DRAWN GAME'; + } + return $difference; +} + +# move the seeds from $pit and take into account possible bonuses +sub move_seeds ($board, $pit) { + + # get the seeds from the selected pit $pit + my $seeds = $board->[$pit]; + $board->[$pit] = 0; + + # $landing will be our "moving cursor" to place seeds around + my $landing = $pit; + while ($seeds > 0) { + $landing = ($landing + 1) % 14; # 12 --> 13 -[wrap]-> 0 --> 1 + --$seeds; + ++$board->[$landing]; + } + + # check for "stealing seeds" condition. This cannot happen in home pits + if ($landing != PLAYER_HOME && $landing != COMPUTER_HOME + && $board->[$landing] == 1 && $board->[12 - $landing] > 0) { + my $home = $pit < 7 ? PLAYER_HOME : COMPUTER_HOME; + $board->[$home] += 1 + $board->[12 - $landing]; + $board->@[$landing, 12 - $landing] = (0, 0); + } + + return ($pit, $landing); +} + +sub get_player_move ($board, $prompt) { + print "\n$prompt? "; + while (defined(my $move = )) { + chomp($move); # remove newline + return $move - 1 if $move =~ m{\A[1-6]\z}mxs && $board->[$move - 1]; + print 'ILLEGAL MOVE\nAGAIN? '; + } + die "goodbye\n"; +} + +sub player_move ($board, $stage = FIRST) { + my $prompt = $stage == FIRST ? 'YOUR MOVE' : 'AGAIN'; + my $selected_move = get_player_move($board, $prompt); + return move_seeds($board, $selected_move); +} + +sub computer_move ($board, $failures, $moves) { + + # we will go through all possible moves for the computer and all + # possible responses by the player, collecting the "best" move in terms + # of reasonable outcome (assuming that each side wants to maximize their + # outcome. $best_move will eventually contain the best move for the + # computer, and $best_difference the best difference in scoring (as + # seen from the computer). + my ($best_move, $best_difference); + for my $c_move (7 .. 12) { + next unless $board->[$c_move]; # only consider pits with seeds inside + + # we work on a copy of the board to do all our trial-and-errors + my $copy = [ $board->@* ]; + move_seeds($copy, $c_move); + + # it's time to "think like a player" and see what's the "best" move + # for the player in this situation. This heuristic is "not perfect" + # but it seems OK anyway. + my $best_player_score = 0; + for my $p_move (0 .. 5) { + next unless $copy->[$p_move]; # only pits with seeds inside + my $landing = $copy->[$p_move] + $p_move; + + # the player's score for this move, calculated as additional seeds + # placed in the player's pit. The original algorithm sets this to + # 1 only if the $landing position is greater than 13, which can + # be obtained by setting the ORIGINAL environment variable to a + # "true" value (in Perl terms). Otherwise it is calculated + # according to the real rules for the game. + my $p_score = $ENV{ORIGINAL} ? $landing > 13 : int(($landing - 5) / 14); + + # whatever, the landing position must be within the bounds + $landing %= 14; + + # if the conditions apply, the player's move might win additional + # seeds, which we have to to take into account. + $p_score += $copy->[12 - $landing] + if $copy->[$landing] == 0 + && $landing != PLAYER_HOME && $landing != COMPUTER_HOME; + + # let's compare this move's score against the best collected + # so far (as a response to a specific computer's move). + $best_player_score = $p_score if $p_score > $best_player_score; + } + + # the overall score for the player is the additional seeds we just + # calculated into $best_player_score plus the seeds that were already + # in the player's pit + $best_player_score += $copy->[PLAYER_HOME]; + + # the best difference we can aim for with this computer's move must + # assume that the player will try its best + my $difference = $copy->[COMPUTER_HOME] - $best_player_score; + + # now it's time to check this computer's move against the history + # of failed matches. $candidate_moves will be the "candidate" list + # of moves if we accept this one. + my $candidate_moves = $moves . $c_move . '/'; + for my $failure ($failures->@*) { + + # index(.) returns 0 if and only if $candidate_moves appears at + # the very beginning of $failure, i.e. it matches a previous + # behaviour. + next if index($failure, $candidate_moves) != 0; + + # same sequence of moves as before... assign a penalty + $difference -= 2; + } + + # update $best_move and $best_difference if they need to + ($best_move, $best_difference) = ($c_move, $difference) + if (! defined $best_move) || ($best_difference < $difference); + } + + # apply the selected move and return + return move_seeds($board, $best_move); +} + +sub welcome { + say ' ' x 34, 'AWARI'; + say ' ' x 15, 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'; +} + +sub print_board ($board) { + my $template = ' + %2d %2d %2d %2d %2d %2d + %2d %d + %2d %2d %2d %2d %2d %2d +'; + printf $template, $board->@[12, 11, 10, 9, 8 , 7, 13, 6, 0 .. 5]; + return; +} + +sub is_game_over ($board) { + + # game over if the player's side is empty + return 1 if none { $_ } $board->@[0 .. 5]; + + # game over if the computers' side is empty + return 1 if none { $_ } $board->@[7 .. 12]; + + # not game over + return 0; +} From 33dbe7e92d14980b17ddfb3afa56868c95013287 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 15:35:24 -0500 Subject: [PATCH 626/749] Started work on the play cycle --- 30_Cube/java/src/Cube.java | 90 +++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/30_Cube/java/src/Cube.java b/30_Cube/java/src/Cube.java index 2e19a691..7fbe39ee 100644 --- a/30_Cube/java/src/Cube.java +++ b/30_Cube/java/src/Cube.java @@ -1,11 +1,17 @@ import java.io.PrintStream; +import java.util.HashSet; import java.util.Random; +import java.util.Scanner; +import java.util.Set; public class Cube { private Location playerLocation; - private Location[] mines; + private Set mines; private PrintStream out; + private Scanner scanner; + + private int money; public static void main(String[] args) { @@ -14,28 +20,84 @@ public class Cube { public Cube() { out = System.out; + scanner = new Scanner(System.in); + money = 500; + mines = new HashSet<>(); } private void placeMines() { - mines = new Location[5]; + mines.clear(); Random random = new Random(); - for(int i = 0; i < mines.length; i++) { + for(int i = 0; i < 5; i++) { int x = random.nextInt(1,4); int y = random.nextInt(1,4); int z = random.nextInt(1,4); - mines[i] = new Location(x,y,z); + mines.add(new Location(x,y,z)); } } public void play() { + out.println("DO YOU WANT TO SEE INSTRUCTIONS? (YES--1,NO--0)"); + if(readParsedBoolean()) { + printInstructions(); + } + do { + placeMines(); + out.println("WANT TO MAKE A WAGER?"); + int wager = 0 ; + if(readParsedBoolean()) { + out.println("HOW MUCH?"); + do { + wager = scanner.nextInt(); + if(wager > money) { + out.println("TRIED TO FOOL ME; BET AGAIN"); + } + } while(wager > money); + } + + + while(playerLocation.x + playerLocation.y + playerLocation.z != 9) { + out.println("\nNEXT MOVE"); + String input = scanner.nextLine(); + + String[] stringValues = input.split(","); + + int x = Integer.parseInt(stringValues[0]); + int y = Integer.parseInt(stringValues[1]); + int z = Integer.parseInt(stringValues[2]); + + Location location = new Location(x,y,z); + + if(x < 1 || x > 3 || y < 1 || y > 3 || z < 1 || z > 3 || isMoveValid(playerLocation,location)) { + out.println("ILLEGAL MOVE, YOU LOSE."); + return; + } + + playerLocation = location; + + if(mines.contains(location)) { + out.println("******BANG******"); + out.println("YOU LOSE!\n\n"); + money -= wager; + } + } + } while(money > 0 && !doAnotherRound()); + } + + private boolean doAnotherRound() { + if(money > 0) { + out.println("DO YOU WANT TO TRY AGAIN?"); + return readParsedBoolean(); + } else { + return false; + } } public void printInstructions() { out.println("THIS IS A GAME IN WHICH YOU WILL BE PLAYING AGAINST THE"); out.println("RANDOM DECISION OF THE COMPUTER. THE FIELD OF PLAY IS A"); out.println("CUBE OF SIDE 3. ANY OF THE 27 LOCATIONS CAN BE DESIGNATED"); - out.println("CUBE OF SIDE 3. ANY OF THE 27 LOCATIONS CAN BE DESIGNATED"); out.println("BY INPUTTING THREE NUMBERS SUCH AS 2,3,1. AT THE START"); out.println("YOU ARE AUTOMATICALLY AT LOCATION 1,1,1. THE OBJECT OF"); out.println("THE GAME IS TO GET TO LOCATION 3,3,3. ONE MINOR DETAIL:"); @@ -46,6 +108,24 @@ public class Cube { out.println("MAY MOVE TO 2,1,2 OR 1,1,3. YOU MAY NOT CHANGE"); out.println("TWO OF THE NUMBERS ON THE SAME MOVE. IF YOU MAKE AN ILLEGAL"); out.println("MOVE, YOU LOSE AND THE COMPUTER TAKES THE MONEY YOU MAY"); + out.println("\n"); + out.println("ALL YES OR NO QUESTIONS WILL BE ANSWERED BY A 1 FOR YES"); + out.println("OR A 0 (ZERO) FOR NO."); + out.println(); + out.println("WHEN STATING THE AMOUNT OF A WAGER, PRINT ONLY THE NUMBER"); + out.println("OF DOLLARS (EXAMPLE: 250) YOU ARE AUTOMATICALLY STARTED WITH"); + out.println("500 DOLLARS IN YOUR ACCOUNT."); + out.println(); + out.println("GOOD LUCK!"); + } + + private boolean readParsedBoolean() { + String in = scanner.nextLine(); + return in.toLowerCase().charAt(0) == 'y' || Boolean.parseBoolean(in); + } + + private boolean isMoveValid(Location from, Location to) { + return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) + Math.abs(from.z - to.z) <= 1; } public class Location { From 28b94b55679a7b1472367b23684707e00f9b6fa6 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 16:04:03 -0500 Subject: [PATCH 627/749] Game now works --- 30_Cube/java/src/Cube.java | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/30_Cube/java/src/Cube.java b/30_Cube/java/src/Cube.java index 7fbe39ee..1b68a285 100644 --- a/30_Cube/java/src/Cube.java +++ b/30_Cube/java/src/Cube.java @@ -49,27 +49,32 @@ public class Cube { if(readParsedBoolean()) { out.println("HOW MUCH?"); do { - wager = scanner.nextInt(); + wager = Integer.parseInt(scanner.nextLine()); if(wager > money) { out.println("TRIED TO FOOL ME; BET AGAIN"); } } while(wager > money); } - + playerLocation = new Location(1,1,1); while(playerLocation.x + playerLocation.y + playerLocation.z != 9) { out.println("\nNEXT MOVE"); String input = scanner.nextLine(); String[] stringValues = input.split(","); + if(stringValues.length < 3) { + out.println("ILLEGAL MOVE, YOU LOSE."); + return; + } + int x = Integer.parseInt(stringValues[0]); int y = Integer.parseInt(stringValues[1]); int z = Integer.parseInt(stringValues[2]); Location location = new Location(x,y,z); - if(x < 1 || x > 3 || y < 1 || y > 3 || z < 1 || z > 3 || isMoveValid(playerLocation,location)) { + if(x < 1 || x > 3 || y < 1 || y > 3 || z < 1 || z > 3 || !isMoveValid(playerLocation,location)) { out.println("ILLEGAL MOVE, YOU LOSE."); return; } @@ -80,9 +85,18 @@ public class Cube { out.println("******BANG******"); out.println("YOU LOSE!\n\n"); money -= wager; + break; } } - } while(money > 0 && !doAnotherRound()); + + if(wager > 0) { + out.printf("YOU NOW HAVE %d DOLLARS\n",money); + } + + } while(money > 0 && doAnotherRound()); + + out.println("TOUGH LUCK!"); + out.println("\nGOODBYE."); } private boolean doAnotherRound() { @@ -121,7 +135,11 @@ public class Cube { private boolean readParsedBoolean() { String in = scanner.nextLine(); - return in.toLowerCase().charAt(0) == 'y' || Boolean.parseBoolean(in); + try { + return in.toLowerCase().charAt(0) == 'y' || Boolean.parseBoolean(in) || Integer.parseInt(in) == 1; + } catch(NumberFormatException exception) { + return false; + } } private boolean isMoveValid(Location from, Location to) { From fe6cb06d6f660916fe08a8d02d58f760685ac438 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 16:11:12 -0500 Subject: [PATCH 628/749] Added Comments --- 30_Cube/java/src/Cube.java | 46 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/30_Cube/java/src/Cube.java b/30_Cube/java/src/Cube.java index 1b68a285..1237a49d 100644 --- a/30_Cube/java/src/Cube.java +++ b/30_Cube/java/src/Cube.java @@ -4,16 +4,33 @@ import java.util.Random; import java.util.Scanner; import java.util.Set; +/** + * Game of Cube + *

+ /// Mimics the "goto" version of the original program + /// + /// + static void Main(string[] args) + { + Random random = new Random(); + StartNewGame: + Console.WriteLine("23 MATCHES".PadLeft(31)); + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".PadLeft(15)); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("THIS IS A GAME CALLED '23 MATCHES'."); + Console.WriteLine(); + Console.WriteLine("WHEN IT IS YOUR TURN, YOU MAY TAKE ONE, TWO, OR THREE"); + Console.WriteLine("MATCHES. THE OBJECT OF THE GAME IS NOT TO HAVE TO TAKE"); + Console.WriteLine("THE LAST MATCH."); + Console.WriteLine(); + Console.WriteLine("Input exit to close the program."); + Console.WriteLine("Input cls Screen Clear."); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("LET'S FLIP A COIN TO SEE WHO GOES FIRST."); + Console.WriteLine("IF IT COMES UP HEADS, I WILL WIN THE TOSS."); + Console.WriteLine(); + StartTheGame: + string command; + int N = 23; + int K = 0; + int Q = random.Next(2); + if (Q == 1) + goto ComputerFirst; + else + goto PlayerFirst; + + ComputerFirst: + Console.WriteLine("HEADS! I WIN! HA! HA!"); + Console.WriteLine("PREPARE TO LOSE, MEATBALL-NOSE!!"); + Console.WriteLine(); + int ain = random.Next(1, 3); + Console.WriteLine($"I TAKE {ain} MATCHES"); + N = N - ain; + goto PlayersProceed; + + PlayerFirst: + Console.WriteLine("TAILS! YOU GO FIRST. "); + Console.WriteLine(); + goto PlayersSpeak; + + PlayersProceed: + Console.WriteLine($"THE NUMBER OF MATCHES IS NOW {N}"); + Console.WriteLine(); + Console.WriteLine("YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES."); + Console.WriteLine("HOW MANY DO YOU WISH TO REMOVE "); + goto PlayersSpeak; + + PlayersSpeak: + command = Console.ReadLine().ToLower(); + if (command.Equals("exit")) + { + System.Diagnostics.Process tt = System.Diagnostics.Process.GetProcessById(System.Diagnostics.Process.GetCurrentProcess().Id); + tt.Kill(); + } + if (command.Equals("cls")) + { + Console.Clear(); + goto PlayersProceed; + } + try + { + K = Convert.ToInt32(command); + } + catch (System.Exception) + { + goto PlayerInputError; + } + if (K > 3 || K <= 0) + goto PlayerInputError; + N = N - K; + Console.WriteLine($"THERE ARE NOW {N} MATCHES REMAINING."); + if (N == 4 || N == 3 || N == 2) + goto TheComputerSpeaks; + else if (N <= 1) + goto ThePlayerWins; + else + goto TheComputerSpeaks; + + TheComputerSpeaks: + int Z = 4 - K; + Console.WriteLine($"MY TURN ! I REMOVE {Z} MATCHES"); + N = N - Z; + if (N <= 1) + goto TheComputerWins; + else + goto PlayersProceed; + + PlayerInputError: + Console.WriteLine("VERY FUNNY! DUMMY!"); + Console.WriteLine("DO YOU WANT TO PLAY OR GOOF AROUND?"); + Console.WriteLine("NOW, HOW MANY MATCHES DO YOU WANT "); + goto PlayersSpeak; + ThePlayerWins: + Console.WriteLine("YOU WON, FLOPPY EARS !"); + Console.WriteLine("THINK YOU'RE PRETTY SMART !"); + Console.WriteLine("LETS PLAY AGAIN AND I'LL BLOW YOUR SHOES OFF !!"); + Console.WriteLine(); + Console.WriteLine(); + goto StartTheGame; + TheComputerWins: + Console.WriteLine(); + Console.WriteLine("YOU POOR BOOB! YOU TOOK THE LAST MATCH! I GOTCHA!!"); + Console.WriteLine("HA ! HA ! I BEAT YOU !!!"); + Console.WriteLine(); + Console.WriteLine("GOOD BYE LOSER!"); + Console.WriteLine(); + Console.WriteLine(); + goto StartNewGame; + + } + } +} diff --git a/93_23_Matches/csharp/ObjectOrientedVersion.Program.cs b/93_23_Matches/csharp/ObjectOrientedVersion.Program.cs new file mode 100644 index 00000000..7b88d7b7 --- /dev/null +++ b/93_23_Matches/csharp/ObjectOrientedVersion.Program.cs @@ -0,0 +1,161 @@ +using System; +using System.Threading; + +namespace _23matches +{ + class ObjectOrientedVersion_Program + { + /// + /// Object-oriented version + /// + /// + static void Main_Two(string[] args) + { + Game game = new Game(); + game.GameRun(); + } + } + public class Game + { + string command; + int N; + int K; + Random random = new Random(); + public void GameRun() + { + StartNewGame(); + StartTheGame(); + } + void StartNewGame() + { + Console.WriteLine("23 MATCHES".PadLeft(31)); + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".PadLeft(15)); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("THIS IS A GAME CALLED '23 MATCHES'."); + Console.WriteLine(); + Console.WriteLine("WHEN IT IS YOUR TURN, YOU MAY TAKE ONE, TWO, OR THREE"); + Console.WriteLine("MATCHES. THE OBJECT OF THE GAME IS NOT TO HAVE TO TAKE"); + Console.WriteLine("THE LAST MATCH."); + Console.WriteLine(); + Console.WriteLine("Input exit to close the program."); + Console.WriteLine("Input cls Screen Clear."); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("LET'S FLIP A COIN TO SEE WHO GOES FIRST."); + Console.WriteLine("IF IT COMES UP HEADS, I WILL WIN THE TOSS."); + Console.WriteLine(); + } + void StartTheGame() + { + N = 23; + K = 0; + int Q = random.Next(2); + if (Q == 1) + ComputerFirst(); + else + { + PlayerFirst(); + } + } + void ComputerFirst() + {//210 + Console.WriteLine("HEADS! I WIN! HA! HA!"); + Console.WriteLine("PREPARE TO LOSE, MEATBALL-NOSE!!"); + Console.WriteLine(); + int ain = random.Next(1, 3); + Console.WriteLine($"I TAKE {ain} MATCHES"); + N = N - ain; + PlayersProceed(); + } + void PlayerFirst() + { + Console.WriteLine("TAILS! YOU GO FIRST. "); + Console.WriteLine(); + PlayersSpeak(); + } + void PlayersProceed() + { + Console.WriteLine($"THE NUMBER OF MATCHES IS NOW {N}"); + Console.WriteLine(); + PlayersSpeak(); + } + void RemindsPlayersToEnter() + { + Console.WriteLine("YOUR TURN -- YOU MAY TAKE 1, 2 OR 3 MATCHES."); + Console.WriteLine("HOW MANY DO YOU WISH TO REMOVE "); + } + void PlayersSpeak() + { + RemindsPlayersToEnter(); + command = Console.ReadLine().ToLower(); + if (command.Equals("exit")) + { + System.Diagnostics.Process tt = System.Diagnostics.Process.GetProcessById(System.Diagnostics.Process.GetCurrentProcess().Id); + tt.Kill(); + } + if (command.Equals("cls")) + { + Console.Clear(); + PlayersSpeak(); + } + try + { + K = Convert.ToInt32(command); + } + catch (System.Exception) + { + PlayerInputError(); + } + if (K > 3 || K <= 0) + PlayerInputError(); + N = N - K; + Console.WriteLine($"THERE ARE NOW {N} MATCHES REMAINING."); + if (N == 4 || N == 3 || N == 2) + TheComputerSpeaks(N); + else if (N <= 1) + ThePlayerWins(); + else + TheComputerSpeaks(4 - K); + + } + void PlayerInputError() + { + Console.WriteLine("VERY FUNNY! DUMMY!"); + Console.WriteLine("DO YOU WANT TO PLAY OR GOOF AROUND?"); + Console.WriteLine("NOW, HOW MANY MATCHES DO YOU WANT "); + PlayersSpeak(); + } + void TheComputerSpeaks(int ain) + { + int Z = ain; + Console.WriteLine($"MY TURN ! I REMOVE {Z} MATCHES");//390 + N = N - Z; + if (N <= 1) + TheComputerWins(); + else + PlayersProceed(); + } + void ThePlayerWins() + { + Console.WriteLine("YOU WON, FLOPPY EARS !"); + Console.WriteLine("THINK YOU'RE PRETTY SMART !"); + Console.WriteLine("LETS PLAY AGAIN AND I'LL BLOW YOUR SHOES OFF !!"); + Console.WriteLine(); + Console.WriteLine(); + StartTheGame(); + } + void TheComputerWins() + { + Console.WriteLine(); + Console.WriteLine("YOU POOR BOOB! YOU TOOK THE LAST MATCH! I GOTCHA!!"); + Console.WriteLine("HA ! HA ! I BEAT YOU !!!"); + Console.WriteLine(); + Console.WriteLine("GOOD BYE LOSER!"); + Console.WriteLine(); + Console.WriteLine(); + GameRun(); + } + } +} diff --git a/93_23_Matches/csharp/README.md b/93_23_Matches/csharp/README.md index 4daabb5c..0f4d812a 100644 --- a/93_23_Matches/csharp/README.md +++ b/93_23_Matches/csharp/README.md @@ -1,3 +1,5 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/) + +The program is available in two versions, a "goto" version that mimics the original program and an "object-oriented" version. \ No newline at end of file From cc3b941bcb38b8c705d1ec5d949d3951008525fa Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Sun, 9 Jan 2022 11:21:48 -0500 Subject: [PATCH 688/749] Port 68_Orbit to Perl. Nothing fancy; just a straight port to idiomatic Perl. --- 68_Orbit/perl/README.md | 8 ++ 68_Orbit/perl/orbit.pl | 239 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100755 68_Orbit/perl/orbit.pl diff --git a/68_Orbit/perl/README.md b/68_Orbit/perl/README.md index e69c8b81..e3bc2e31 100644 --- a/68_Orbit/perl/README.md +++ b/68_Orbit/perl/README.md @@ -1,3 +1,11 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Perl](https://www.perl.org/) + +This Perl script is a port of orbit, which is the 68th entry in Basic +Computer Games. + +In this game you are a planetary defense gunner trying to shoot down a +cloaked Romulan ship before it can escape. + +This is pretty much a straight port of the BASIC into idiomatic Perl. diff --git a/68_Orbit/perl/orbit.pl b/68_Orbit/perl/orbit.pl new file mode 100755 index 00000000..f8e9fccf --- /dev/null +++ b/68_Orbit/perl/orbit.pl @@ -0,0 +1,239 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +use constant PI => atan2( 0, -1 ); +use constant DEG_TO_RAD => atan2( 0, -1 ) / 180; + +print <<'EOD'; + ORBIT + Creative Computing Morristown, New Jersey + + + +Somewhere above your planet is a Romulan ship. + +The ship is in a constant polar orbit. Its +distance from the center of your planet is from +10,000 to 30,000 miles and at its present velocity can +circle your planet once every 12 to 36 hours. + +Unfortunately, they are using a cloaking device so +you are unable to see them, but with a special +instrument you can tell how near their ship your +photon bomb exploded. You have seven hours until they +have built up sufficient power in order to escape +your planet's gravity. + +Your planet has enough power to fire one bomb an hour. + +At the beginning of each hour you will be asked to give an +angle (between 0 and 360) and a distance in units of +100 miles (between 100 and 300), after which your bomb's +distance from the enemy ship will be given. + +An explosion within 5,000 miles of the Romulan ship +will destroy it. + +Below is a diagram to help you visualize your plight. + + + 90 + 0000000000000 + 0000000000000000000 + 000000 000000 + 00000 00000 + 00000 XXXXXXXXXXX 00000 + 00000 XXXXXXXXXXXXX 00000 + 0000 XXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXXXXXX 0000 +180<== 00000 XXXXXXXXXXXXXXXXXXX 00000 ==>0 + 0000 XXXXXXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXXXX 0000 + 0000 XXXXXXXXXXXXXXX 0000 + 00000 XXXXXXXXXXXXX 00000 + 00000 XXXXXXXXXXX 00000 + 00000 00000 + 000000 000000 + 0000000000000000000 + 0000000000000 + 270 + +X - Your planet +O - The orbit of the Romulan ship + +On the above diagram, the Romulan ship is circling +counterclockwise around your planet. Don't forget that +without sufficient power the Romulan ship's altitude +and orbital rate will remain constant. + +Good luck. The Federation is counting on you. +EOD + +while ( 1 ) { # Iterate indefinitely + + my $romulan_angle = int( 360 * rand() ); + my $romulan_distance = int( 200 * rand() + 200 ); + my $romulan_velocity = int( 20 * rand() + 10 ); + + my $hour = 0; + while ( 1 ) { # Iterate indefinitely + $hour++; + + print <<"EOD"; + + +This is hour $hour, at what angle do you wish to send +EOD + my $bomb_angle = get_input( + 'do you wish to send your photon bomb? ', + sub { m/ \A [0-9]+ \z /smx }, + "Please enter an integer angle in degrees\n", + ); + say ''; + my $bomb_distance = get_input( + 'How far out do you wish to detonate it? ', + sub { m/ \A [0-9]+ \z /smx }, + "Please enter an integer distance in hundreds of miles\n", + ); + + $romulan_angle = ( $romulan_angle + $romulan_velocity ) % 360; + my $miss_angle = abs( $romulan_angle - $bomb_angle ); + $miss_angle = 360 - $miss_angle if $miss_angle >= 180; + my $miss_distance = int sqrt( + $romulan_distance * $romulan_distance + + $bomb_distance * $bomb_distance - + 2 * $romulan_distance * $bomb_distance * + cos( $miss_angle * DEG_TO_RAD ) ); + print <<"EOD"; + +Your photon bomb exploded $miss_distance*10^2 miles from the +Romulan ship. +EOD + if ( $miss_distance <= 50 ) { + say "\nYou have successfully completed your mission."; + last; + } elsif ( $hour > 6 ) { + say "\nYou have allowed the Romulans to escape."; + last; + } + } + + say "\nAnother Romulan ship has gone into orbit."; + last unless get_yes_no( 'Do you wish to try to destroy it' ); +} + +print <<'EOD'; + +Good bye. +EOD + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +__END__ + +=head1 TITLE + +orbit - Play the game 'Orbit' from Basic Computer Games + +=head1 SYNOPSIS + + orbit.pl + +=head1 DETAILS + +This Perl script is a port of orbit, which is the 68th entry in Basic +Computer Games. + +In this game you are a planetary defense gunner trying to shoot down a +cloaked Romulan ship before it can escape. + +This is pretty much a straight port of the BASIC into idiomatic Perl. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From dedca6ac0d3662863fa3721fb0ad4f08b00355b5 Mon Sep 17 00:00:00 2001 From: Flow Date: Sun, 9 Jan 2022 18:51:34 +0100 Subject: [PATCH 689/749] Add pizza implementation in c# --- 69_Pizza/csharp/Pizza/CustomerMap.cs | 131 ++++++++ 69_Pizza/csharp/Pizza/Pizza.csproj | 10 + 69_Pizza/csharp/Pizza/Pizza.sln | 25 ++ 69_Pizza/csharp/Pizza/PizzaGame.cs | 296 ++++++++++++++++++ 69_Pizza/csharp/Pizza/Program.cs | 11 + .../csharp/Pizza/StringBuilderExtensions.cs | 21 ++ 6 files changed, 494 insertions(+) create mode 100644 69_Pizza/csharp/Pizza/CustomerMap.cs create mode 100644 69_Pizza/csharp/Pizza/Pizza.csproj create mode 100644 69_Pizza/csharp/Pizza/Pizza.sln create mode 100644 69_Pizza/csharp/Pizza/PizzaGame.cs create mode 100644 69_Pizza/csharp/Pizza/Program.cs create mode 100644 69_Pizza/csharp/Pizza/StringBuilderExtensions.cs diff --git a/69_Pizza/csharp/Pizza/CustomerMap.cs b/69_Pizza/csharp/Pizza/CustomerMap.cs new file mode 100644 index 00000000..ee991de3 --- /dev/null +++ b/69_Pizza/csharp/Pizza/CustomerMap.cs @@ -0,0 +1,131 @@ +using System.Text; + +namespace Pizza +{ + internal class CustomerMap + { + private readonly int _mapSize; + private readonly string[,] _customerMap; + + public CustomerMap(int mapSize) + { + _mapSize = mapSize; + _customerMap = GenerateCustomerMap(); + } + + /// + /// Gets customer on position X, Y. + /// + /// Represents X position. + /// Represents Y position. + /// If positions is valid then returns customer name otherwise returns empty string. + public string GetCustomerOnPosition(int x, int y) + { + if(IsPositionOutOfRange(x, y)) + { + return string.Empty; + } + + return _customerMap[y, x]; + } + + /// + /// Overridden ToString for getting text representation of customers map. + /// + /// Text representation of customers map. + public override string ToString() + { + int verticalSpace = 4; + int horizontalSpace = 5; + + var mapToDisplay = new StringBuilder(); + + AppendXLine(mapToDisplay, horizontalSpace); + + for (int i = _customerMap.GetLength(0) - 1; i >= 0; i--) + { + mapToDisplay.AppendLine("-", verticalSpace); + mapToDisplay.Append($"{i + 1}"); + mapToDisplay.Append(' ', horizontalSpace); + + for (var j = 0; j < _customerMap.GetLength(1); j++) + { + mapToDisplay.Append($"{_customerMap[i, j]}"); + mapToDisplay.Append(' ', horizontalSpace); + } + + mapToDisplay.Append($"{i + 1}"); + mapToDisplay.Append(' ', horizontalSpace); + mapToDisplay.Append(Environment.NewLine); + } + + mapToDisplay.AppendLine("-", verticalSpace); + + AppendXLine(mapToDisplay, horizontalSpace); + + return mapToDisplay.ToString(); + } + + /// + /// Checks if position is out of range or not. + /// + /// Represents X position. + /// Represents Y position. + /// True if position is out of range otherwise false. + private bool IsPositionOutOfRange(int x, int y) + { + return + x < 0 || x > _mapSize - 1 || + y < 0 || y > _mapSize - 1; + } + + /// + /// Generates array which represents customers map. + /// + /// Returns customers map. + private string[,] GenerateCustomerMap() + { + string[,] customerMap = new string[_mapSize, _mapSize]; + string[] customerNames = GetCustomerNames(_mapSize * _mapSize); + int currentCustomerNameIndex = 0; + + for (int i = 0; i < customerMap.GetLength(0); i++) + { + for (int j = 0; j < customerMap.GetLength(1); j++) + { + customerMap[i, j] = customerNames[currentCustomerNameIndex++].ToString(); + } + } + + return customerMap; + } + + /// + /// Generates customer names. Names are represented by alphanumerics from 'A'. Name of last customer depends on passed parameter. + /// + /// How many customers need to be generated. + /// List of customer names. + private static string[] GetCustomerNames(int numberOfCustomers) + { + // returns ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"]; + return Enumerable.Range(65, numberOfCustomers).Select(c => ((Char)c).ToString()).ToArray(); + } + + /// + /// Appends line with X coordinates. + /// + /// Current map where a new line will be appended. + /// Number of horizontal delimiters which will be added between each coordination. + private void AppendXLine(StringBuilder mapToDisplay, int horizontalSpace) + { + mapToDisplay.Append(' '); + mapToDisplay.Append('-', horizontalSpace); + for (var i = 0; i < _customerMap.GetLength(0); i++) + { + mapToDisplay.Append($"{i + 1}"); + mapToDisplay.Append('-', horizontalSpace); + } + mapToDisplay.Append(Environment.NewLine); + } + } +} \ No newline at end of file diff --git a/69_Pizza/csharp/Pizza/Pizza.csproj b/69_Pizza/csharp/Pizza/Pizza.csproj new file mode 100644 index 00000000..74abf5c9 --- /dev/null +++ b/69_Pizza/csharp/Pizza/Pizza.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/69_Pizza/csharp/Pizza/Pizza.sln b/69_Pizza/csharp/Pizza/Pizza.sln new file mode 100644 index 00000000..91785a8c --- /dev/null +++ b/69_Pizza/csharp/Pizza/Pizza.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pizza", "Pizza.csproj", "{6AABE938-39C4-4661-AEA5-23CECA1DFEE1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F7E9FAD-38C5-47A2-B5CA-2B6E5947B982} + EndGlobalSection +EndGlobal diff --git a/69_Pizza/csharp/Pizza/PizzaGame.cs b/69_Pizza/csharp/Pizza/PizzaGame.cs new file mode 100644 index 00000000..22c78e05 --- /dev/null +++ b/69_Pizza/csharp/Pizza/PizzaGame.cs @@ -0,0 +1,296 @@ +namespace Pizza +{ + internal class PizzaGame + { + private const int CustomerMapSize = 4; + private readonly CustomerMap _customerMap = new CustomerMap(CustomerMapSize); + + /// + /// Starts game. Main coordinator for pizza game. + /// It is responsible for showing information, getting data from user and starting to delivery pizza. + /// + public void Play() + { + ShowHeader(); + + string playerName = GetPlayerName(); + + ShowIntroduction(playerName); + ShowMap(); + + if (AskForMoreDirections()) + { + ShowMoreDirections(playerName); + + var playerUnderstands = AskIfPlayerUnderstand(); + if (!playerUnderstands) + { + return; + } + } + + StartDelivery(playerName); + EndDelivery(playerName); + } + + /// + /// Starts with pizza delivering to customers. + /// Every 5 deliveries it is asking user whether want to continue in delivering. + /// + /// Player name which was filled by user. + private void StartDelivery(string playerName) + { + var numberOfDeliveredPizzas = 0; + while (true) + { + numberOfDeliveredPizzas++; + string deliverPizzaToCustomer = GetRandomCustomer(); + + WriteEmptyLine(); + Console.WriteLine($"HELLO {playerName}'S PIZZA. THIS IS {deliverPizzaToCustomer}."); + Console.WriteLine("\tPLEASE SEND A PIZZA."); + + DeliverPizzaByPlayer(playerName, deliverPizzaToCustomer); + + if (numberOfDeliveredPizzas % 5 == 0) + { + bool playerWantToDeliveryMorePizzas = AskQuestionWithYesNoResponse("DO YOU WANT TO DELIVER MORE PIZZAS?"); + if (!playerWantToDeliveryMorePizzas) + { + WriteEmptyLine(); + break; + } + } + } + } + + /// + /// Gets random customer for which pizza should be delivered. + /// + /// Customer name. + private string GetRandomCustomer() + { + int randomPositionOnX = Random.Shared.Next(0, CustomerMapSize); + int randomPositionOnY = Random.Shared.Next(0, CustomerMapSize); + + return _customerMap.GetCustomerOnPosition(randomPositionOnX, randomPositionOnY); + } + + /// + /// Delivers pizza to customer by player. It verifies whether player was delivering pizza to correct customer. + /// + /// Player name which was filled by user. + /// Customer name which order pizza. + private void DeliverPizzaByPlayer(string playerName, string deliverPizzaToCustomer) + { + while (true) + { + string userInput = GetPlayerInput($"\tDRIVER TO {playerName}: WHERE DOES {deliverPizzaToCustomer} LIVE?"); + var deliveredToCustomer = GetCustomerFromPlayerInput(userInput); + if (string.IsNullOrEmpty(deliveredToCustomer)) + { + deliveredToCustomer = "UNKNOWN CUSTOMER"; + } + + if (deliveredToCustomer.Equals(deliverPizzaToCustomer)) + { + Console.WriteLine($"HELLO {playerName}. THIS IS {deliverPizzaToCustomer}, THANKS FOR THE PIZZA."); + break; + } + + Console.WriteLine($"THIS IS {deliveredToCustomer}. I DID NOT ORDER A PIZZA."); + Console.WriteLine($"I LIVE AT {userInput}"); + } + } + + /// + /// Gets customer name by user input with customer coordinations. + /// + /// Input from users - it should represent customer coordination separated by ','. + /// If coordinations are correct and customer exists then returns true otherwise false. + private string GetCustomerFromPlayerInput(string userInput) + { + var pizzaIsDeliveredToPosition = userInput? + .Split(',') + .Select(i => int.TryParse(i, out var customerPosition) ? (customerPosition - 1) : -1) + .Where(i => i != -1) + .ToArray() ?? Array.Empty(); + if (pizzaIsDeliveredToPosition.Length != 2) + { + return string.Empty; + } + + return _customerMap.GetCustomerOnPosition(pizzaIsDeliveredToPosition[0], pizzaIsDeliveredToPosition[1]); + } + + /// + /// Shows game header in console. + /// + private void ShowHeader() + { + Console.WriteLine("PIZZA".PadLeft(22)); + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + WriteEmptyLine(3); + Console.WriteLine("PIZZA DELIVERY GAME"); + WriteEmptyLine(); + } + + /// + /// Asks user for name which will be used in game. + /// + /// Player name. + private string GetPlayerName() + { + return GetPlayerInput("WHAT IS YOUR FIRST NAME:"); + } + + /// + /// Shows game introduction in console + /// + /// Player name which was filled by user. + private void ShowIntroduction(string playerName) + { + Console.WriteLine($"HI, {playerName}. IN THIS GAME YOU ARE TO TAKE ORDERS"); + Console.WriteLine("FOR PIZZAS. THEN YOU ARE TO TELL A DELIVERY BOY"); + Console.WriteLine("WHERE TO DELIVER THE ORDERED PIZZAS."); + WriteEmptyLine(2); + } + + /// + /// Shows customers map in console. In this method is used overridden method 'ToString' for getting text representation of customers map. + /// + private void ShowMap() + { + Console.WriteLine("MAP OF THE CITY OF HYATTSVILLE"); + WriteEmptyLine(); + + Console.WriteLine(_customerMap.ToString()); + + Console.WriteLine("THE OUTPUT IS A MAP OF THE HOMES WHERE"); + Console.WriteLine("YOU ARE TO SEND PIZZAS."); + WriteEmptyLine(); + Console.WriteLine("YOUR JOB IS TO GIVE A TRUCK DRIVER"); + Console.WriteLine("THE LOCATION OR COORDINATES OF THE"); + Console.WriteLine("HOME ORDERING THE PIZZA."); + WriteEmptyLine(); + } + + /// + /// Asks user if needs more directions. + /// + /// True if user need more directions otherwise false. + private bool AskForMoreDirections() + { + var playerNeedsMoreDirections = AskQuestionWithYesNoResponse("DO YOU NEED MORE DIRECTIONS?"); + WriteEmptyLine(); + + return playerNeedsMoreDirections; + } + + /// + /// Shows more directions. + /// + /// Player name which was filled by user. + private void ShowMoreDirections(string playerName) + { + Console.WriteLine("SOMEBODY WILL ASK FOR A PIZZA TO BE"); + Console.WriteLine("DELIVERED. THEN A DELIVERY BOY WILL"); + Console.WriteLine("ASK YOU FOR THE LOCATION."); + Console.WriteLine("\tEXAMPLE:"); + Console.WriteLine("THIS IS J. PLEASE SEND A PIZZA."); + Console.WriteLine($"DRIVER TO {playerName}. WHERE DOES J LIVE?"); + Console.WriteLine("YOUR ANSWER WOULD BE 2,3"); + } + + /// + /// Asks user if understands to instructions. + /// + /// True if user understand otherwise false. + private bool AskIfPlayerUnderstand() + { + var playerUnderstands = AskQuestionWithYesNoResponse("UNDERSTAND?"); + if (!playerUnderstands) + { + Console.WriteLine("THIS JOB IS DEFINITELY TOO DIFFICULT FOR YOU. THANKS ANYWAY"); + return false; + } + + WriteEmptyLine(); + Console.WriteLine("GOOD. YOU ARE NOW READY TO START TAKING ORDERS."); + WriteEmptyLine(); + Console.WriteLine("GOOD LUCK!!"); + WriteEmptyLine(); + + return true; + } + + /// + /// Shows message about ending delivery in console. + /// + /// Player name which was filled by user. + private void EndDelivery(string playerName) + { + Console.WriteLine($"O.K. {playerName}, SEE YOU LATER!"); + WriteEmptyLine(); + } + + /// + /// Gets input from user. + /// + /// Question which is displayed in console. + /// User input. + private string GetPlayerInput(string question) + { + Console.Write($"{question} "); + + while (true) + { + var userInput = Console.ReadLine(); + if (!string.IsNullOrWhiteSpace(userInput)) + { + return userInput; + } + } + } + + /// + /// Asks user with required resposne 'YES', 'Y, 'NO', 'N'. + /// + /// Question which is displayed in console. + /// True if user write 'YES', 'Y'. False if user write 'NO', 'N'. + private static bool AskQuestionWithYesNoResponse(string question) + { + var possitiveResponse = new string[] { "Y", "YES" }; + var negativeResponse = new string[] { "N", "NO" }; + var validUserInputs = possitiveResponse.Concat(negativeResponse); + + Console.Write($"{question} "); + + string? userInput; + while (true) + { + userInput = Console.ReadLine(); + if (!string.IsNullOrWhiteSpace(userInput) && validUserInputs.Contains(userInput.ToUpper())) + { + break; + } + + Console.Write($"'YES' OR 'NO' PLEASE, NOW THEN, {question} "); + } + + return possitiveResponse.Contains(userInput.ToUpper()); + } + + /// + /// Writes empty line in console. + /// + /// Number of empty lines which will be written in console. Parameter is optional and default value is 1. + private void WriteEmptyLine(int numberOfEmptyLines = 1) + { + for (int i = 0; i < numberOfEmptyLines; i++) + { + Console.WriteLine(); + } + } + } +} \ No newline at end of file diff --git a/69_Pizza/csharp/Pizza/Program.cs b/69_Pizza/csharp/Pizza/Program.cs new file mode 100644 index 00000000..6c21fad0 --- /dev/null +++ b/69_Pizza/csharp/Pizza/Program.cs @@ -0,0 +1,11 @@ +namespace Pizza +{ + internal class Program + { + static void Main(string[] args) + { + var pizzaGame = new PizzaGame(); + pizzaGame.Play(); + } + } +} \ No newline at end of file diff --git a/69_Pizza/csharp/Pizza/StringBuilderExtensions.cs b/69_Pizza/csharp/Pizza/StringBuilderExtensions.cs new file mode 100644 index 00000000..f7cb828d --- /dev/null +++ b/69_Pizza/csharp/Pizza/StringBuilderExtensions.cs @@ -0,0 +1,21 @@ +using System.Text; + +namespace Pizza +{ + internal static class StringBuilderExtensions + { + /// + /// Extensions for adding new lines of specific value. + /// + /// Extended class. + /// Value which will be repeated. + /// Number of lines that will be appended. + public static void AppendLine(this StringBuilder stringBuilder, string value, int numberOfLines) + { + for (int i = 0; i < numberOfLines; i++) + { + stringBuilder.AppendLine(value); + } + } + } +} \ No newline at end of file From fbbf0bf622bde3293b10f6cafd4743812142d931 Mon Sep 17 00:00:00 2001 From: jcoehoorn Date: Sun, 9 Jan 2022 12:37:32 -0600 Subject: [PATCH 690/749] Create program.vb --- 02_Amazing/vbnet/program.vb | 295 ++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 02_Amazing/vbnet/program.vb diff --git a/02_Amazing/vbnet/program.vb b/02_Amazing/vbnet/program.vb new file mode 100644 index 00000000..d39eb450 --- /dev/null +++ b/02_Amazing/vbnet/program.vb @@ -0,0 +1,295 @@ +Imports System + +Module Program + + Enum Directions + SolveAndReset = 0 + Left = 1 + Up = 2 + Right = 3 + Down = 4 + End Enum + + 'Program State + Dim Width As Integer = 0, Height As Integer = 0, Q As Integer = 0, CellsVisited As Integer = 2, curCol As Integer, curRow As Integer = 1 + Dim SolutionCompleted As Boolean = False + Dim CellVisitHistory(,) As Integer + Dim CellState(,) As Integer + + Dim rnd As New Random() + + Public ReadOnly Property BlockedLeft As Boolean + Get + Return curCol - 1 = 0 OrElse CellVisitHistory(curCol - 1, curRow) <> 0 + End Get + End Property + Public ReadOnly Property BlockedAbove As Boolean + Get + Return curRow - 1 = 0 OrElse CellVisitHistory(curCol, curRow - 1) <> 0 + End Get + End Property + Public ReadOnly Property BlockedRight As Boolean + Get + Return curCol = Width OrElse CellVisitHistory(curCol + 1, curRow) <> 0 + End Get + End Property + 'Note: "BlockedBelow" does NOT include checking if we have a solution! + Public ReadOnly Property BlockedBelow As Boolean + Get + Return curRow = Height OrElse CellVisitHistory(curCol, curRow + 1) <> 0 + End Get + End Property + Public ReadOnly Property OnBottomRow As Boolean + Get + Return curRow.Equals(Height) + End Get + End Property + + Sub Main(args As String()) + Const header As String = +" AMAZING PROGRAM + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + +" + Console.WriteLine(header) + + While Width <= 1 OrElse Height <= 1 + Console.Write("WHAT ARE YOUR WIDTH AND LENGTH? ") + + 'We no longer have the old convenient INPUT command, so need to parse out the inputs + Dim parts = Console.ReadLine().Split(","c).Select(Function(s) Convert.ToInt32(s.Trim())).ToList() + Width = parts(0) + Height = parts(1) + + If Width <= 1 OrElse Height <= 1 Then Console.WriteLine($"MEANINGLESS DIMENSIONS. TRY AGAIN.{vbCrLf}") + End While + + ReDim CellVisitHistory(Width, Height), CellState(Width, Height) + + Console.WriteLine(" + +") + + curCol = rnd.Next(1, Width + 1) 'Starting X position + CellVisitHistory(curCol, 1) = 1 + Dim startXPos As Integer = curCol 'we need to know this at the end to print opening line + + Dim keepGoing As Boolean = True + While keepGoing + If BlockedLeft Then + keepGoing = ChoosePath_BlockedToTheLeft() + ElseIf BlockedAbove Then + keepGoing = ChoosePath_BlockedAbove() + ElseIf BlockedRight Then + keepGoing = ChoosePath_BlockedToTheRight() + Else + keepGoing = SelectRandomDirection(Directions.Left, Directions.Up, Directions.Right) 'Go anywhere but down + End If + End While + + PrintFinalResults(startXPos) + End Sub + + Public Sub ResetCurrentPosition() + Do + If curCol <> Width Then 'not at the right edge + curCol += 1 + ElseIf curRow <> Height Then 'not at the bottom + curCol = 1 + curRow += 1 + Else + curCol = 1 + curRow = 1 + End If + Loop While CellVisitHistory(curCol, curRow) = 0 + End Sub + + Dim methods() As Func(Of Boolean) = {AddressOf MarkSolvedAndResetPosition, AddressOf GoLeft, AddressOf GoUp, AddressOf GoRight, AddressOf GoDown} + Public Function SelectRandomDirection(ParamArray possibles() As Directions) As Boolean + Dim x As Integer = rnd.Next(0, possibles.Length) + Return methods(possibles(x))() + End Function + + Public Function ChoosePath_BlockedToTheLeft() As Boolean + If BlockedAbove Then + If BlockedRight Then + If curRow <> Height Then + If CellVisitHistory(curCol, curRow + 1) <> 0 Then ' Can't go down, but not at the edge...blocked. Reset and try again + ResetCurrentPosition() + Return True + Else + Return GoDown() + End If + ElseIf SolutionCompleted Then 'Can't go Down (there's already another solution) + ResetCurrentPosition() + Return True + Else 'Can't go LEFT, UP, RIGHT, or DOWN, but we're on the bottom and there's no solution yet + Return MarkSolvedAndResetPosition() + End If + ElseIf BlockedBelow Then + Return GoRight() + ElseIf Not OnBottomRow Then + Return SelectRandomDirection(Directions.Right, Directions.Down) + ElseIf SolutionCompleted Then 'Can only go right, and we're at the bottom + Return GoRight() + Else 'Can only go right, we're at the bottom, and there's not a solution yet + Return SelectRandomDirection(Directions.Right, Directions.SolveAndReset) + End If + '== Definitely can go Up == + ElseIf BlockedRight Then + If BlockedBelow Then + Return GoUp() + ElseIf Not OnBottomRow Then + Return SelectRandomDirection(Directions.Up, Directions.Down) + ElseIf SolutionCompleted Then 'We're on the bottom row, can only go up + Return GoUp() + Else 'We're on the bottom row, can only go up, but there's no solution + Return SelectRandomDirection(Directions.Up, Directions.SolveAndReset) + End If + '== Definitely can go Up and Right == + ElseIf BlockedBelow Then + Return SelectRandomDirection(Directions.Up, Directions.Right) + ElseIf Not OnBottomRow Then + Return SelectRandomDirection(Directions.Up, Directions.Right, Directions.Down) + ElseIf SolutionCompleted Then 'at the bottom, but already have a solution + Return SelectRandomDirection(Directions.Up, Directions.Right) + Else + Return SelectRandomDirection(Directions.Up, Directions.Right, Directions.SolveAndReset) + End If + End Function + + Public Function ChoosePath_BlockedAbove() As Boolean + 'No need to check the left side, only called from the "keepGoing" loop where LEFT is already cleared + If BlockedRight Then + If BlockedBelow Then + Return GoLeft() + ElseIf Not OnBottomRow Then + Return SelectRandomDirection(Directions.Left, Directions.Down) + ElseIf SolutionCompleted Then 'Can't go down because there's already a solution + Return GoLeft() + Else 'At the bottom, no solution yet... + Return SelectRandomDirection(Directions.Left, Directions.SolveAndReset) + End If + ElseIf BlockedBelow Then + Return SelectRandomDirection(Directions.Left, Directions.Right) + ElseIf Not OnBottomRow Then + Return SelectRandomDirection(Directions.Left, Directions.Right, Directions.Down) + ElseIf SolutionCompleted Then + Return SelectRandomDirection(Directions.Left, Directions.Right) + Else + Return SelectRandomDirection(Directions.Left, Directions.Right, Directions.SolveAndReset) + End If + End Function + + Public Function ChoosePath_BlockedToTheRight() As Boolean + 'No need to check Left or Up, only called from the "keepGoing" loop where LEFT and UP are already cleared + If BlockedRight Then 'Can't go Right -- why? we knew this when calling the function + If BlockedBelow Then + Return SelectRandomDirection(Directions.Left, Directions.Up) + ElseIf Not OnBottomRow Then + Return SelectRandomDirection(Directions.Left, Directions.Up, Directions.Down) + ElseIf SolutionCompleted Then + Return SelectRandomDirection(Directions.Left, Directions.Up) + Else + Return SelectRandomDirection(Directions.Left, Directions.Up, Directions.SolveAndReset) + End If + Else 'Should never get here + Return SelectRandomDirection(Directions.Left, Directions.Up, Directions.Right) 'Go Left, Up, or Right (but path is blocked?) + End If + End Function + + Public Sub PrintFinalResults(startPos As Integer) + For i As Integer = 0 To Width - 1 + If i = startPos Then Console.Write(". ") Else Console.Write(".--") + Next + Console.WriteLine(".") + + If Not SolutionCompleted Then 'Pick a random exit + Dim X As Integer = rnd.Next(1, Width + 1) + If CellState(X, Height) = 0 Then + CellState(X, Height) = 1 + Else + CellState(X, Height) = 3 + End If + End If + + For j As Integer = 1 To Height + Console.Write("I") + For i As Integer = 1 To Width + If CellState(i, j) < 2 Then + Console.Write(" I") + Else + Console.Write(" ") + End If + Next + Console.WriteLine() + + For i As Integer = 1 To Width + If CellState(i, j) = 0 OrElse CellState(i, j) = 2 Then + Console.Write(":--") + Else + Console.Write(": ") + End If + Next + Console.WriteLine(".") + Next + End Sub + + Public Function GoLeft() As Boolean + curCol -= 1 + CellVisitHistory(curCol, curRow) = CellsVisited + CellsVisited += 1 + CellState(curCol, curRow) = 2 + If CellsVisited > Width * Height Then Return False + Q = 0 + Return True + End Function + + Public Function GoUp() As Boolean + curRow -= 1 + CellVisitHistory(curCol, curRow) = CellsVisited + CellsVisited += 1 + CellState(curCol, curRow) = 1 + If CellsVisited > Width * Height Then Return False + Q = 0 + Return True + End Function + + Public Function GoRight() As Boolean + CellVisitHistory(curCol + 1, curRow) = CellsVisited + CellsVisited += 1 + If CellState(curCol, curRow) = 0 Then CellState(curCol, curRow) = 2 Else CellState(curCol, curRow) = 3 + curCol += 1 + If CellsVisited > Width * Height Then Return False + Return ChoosePath_BlockedToTheLeft() + End Function + + Public Function GoDown() As Boolean + If Q = 1 Then Return MarkSolvedAndResetPosition() + + CellVisitHistory(curCol, curRow + 1) = CellsVisited + CellsVisited += 1 + If CellState(curCol, curRow) = 0 Then CellState(curCol, curRow) = 1 Else CellState(curCol, curRow) = 3 + curRow += 1 + If CellsVisited > Width * Height Then Return False + Return True + End Function + + Public Function MarkSolvedAndResetPosition() As Boolean + ' AlWAYS returns true + SolutionCompleted = True + Q = 1 + If CellState(curCol, curRow) = 0 Then + CellState(curCol, curRow) = 1 + curCol = 1 + curRow = 1 + If CellVisitHistory(curCol, curRow) = 0 Then ResetCurrentPosition() + Else + CellState(curCol, curRow) = 3 + ResetCurrentPosition() + End If + Return True + End Function +End Module From e0b041dfd7fc75f1eb1e53f566b9f27581d52b6b Mon Sep 17 00:00:00 2001 From: Jackson Brouwer Date: Sun, 9 Jan 2022 15:05:24 -0600 Subject: [PATCH 691/749] Python version --- 07_Basketball/python/basketball.py | 343 +++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 07_Basketball/python/basketball.py diff --git a/07_Basketball/python/basketball.py b/07_Basketball/python/basketball.py new file mode 100644 index 00000000..5ba88188 --- /dev/null +++ b/07_Basketball/python/basketball.py @@ -0,0 +1,343 @@ +import random + +# The basketball class is a computer game that allows you to play as +# Dartmouth College's captain and playmaker +# The game uses set probabilites to simulate outcomes of each posession +# You are able to choose your shot types as well as defensive formations + + +class Basketball(): + def __init__(self): + self.time = 0 + self.score = [0, 0] # first value is opponents score, second is home + self.defense = None + self.defense_choices = [6, 6.5, 7, 7.5] + self.shot = None + self.shot_choices = [1, 2, 3, 4] + self.z1 = None + + # Explains the keyboard inputs + print("\t\t\t Basketball") + print("\t Creative Computing Morristown, New Jersey\n\n\n") + print("This is Dartmouth College basketball. ") + print("Υou will be Dartmouth captain and playmaker.") + print("Call shots as follows:") + print("1. Long (30ft.) Jump Shot; 2. Short (15 ft.) Jump Shot; " + + "3. Lay up; 4. Set Shot") + print("Both teams will use the same defense. Call Defense as follows:") + print("6. Press; 6.5 Man-to-Man; 7. Zone; 7.5 None.") + print("To change defense, just type 0 as your next shot.") + print("Your starting defense will be? ", end='') + + # takes input for a defense + try: + self.defense = float(input()) + + except ValueError: + self.defense = None + + # if the input wasn't a valid defense, takes input again + while self.defense not in self.defense_choices: + print("Your new defensive allignment is? ", end='') + try: + self.defense = float(input()) + + except ValueError: + continue + + # takes input for opponent's name + print("\nChoose your opponent? ", end='') + + self.opponent = input() + self.start_of_period() + + # adds points to the score + # team can take 0 or 1, for opponent or Dartmouth, respectively + def add_points(self, team, points): + self.score[team] += points + self.print_score() + + def ball_passed_back(self): + print("Ball passed back to you. ", end='') + self.dartmouth_ball() + + # change defense, called when the user enters 0 for their shot + def change_defense(self): + self.defense = None + + while self.defense not in self.defense_choices: + print("Your new defensive allignment is? ") + try: + self.defense = float(input()) + + except ValueError: + continue + self.dartmouth_ball() + + # simulates two foul shots for a player and adds the points + def foul_shots(self, team): + print("Shooter fouled. Two shots.") + if random.random() > .49: + if random.random() > .75: + print("Both shots missed.") + else: + print("Shooter makes one shot and misses one.") + self.score[team] += 1 + else: + print("Shooter makes both shots.") + self.score[team] += 2 + + self.print_score() + + # called when t = 50, starts a new period + def halftime(self): + print("\n ***** End of first half *****\n") + self.print_score() + self.start_of_period() + + # prints the current score + def print_score(self): + print("Score: " + str(self.score[1]) + + " to " + str(self.score[0]) + "\n") + + # simulates a center jump for posession at the beginning of a period + def start_of_period(self): + print("Center jump") + if random.random() > .6: + print("Dartmouth controls the tap.\n") + self.dartmouth_ball() + else: + print(self.opponent + " controls the tap.\n") + self.opponent_ball() + + # called when t = 92 + def two_minute_warning(self): + print(" *** Two minutes left in the game ***") + + # called when the user enters 1 or 2 for their shot + def dartmouth_jump_shot(self): + self.time += 1 + if self.time == 50: + self.halftime() + elif self.time == 92: + self.two_minute_warning() + print("Jump Shot.") + # simulates chances of different possible outcomes + if random.random() > .341 * self.defense / 8: + if random.random() > .682 * self.defense / 8: + if random.random() > .782 * self.defense / 8: + if random.random() > .843 * self.defense / 8: + print("Charging foul. Dartmouth loses ball.\n") + self.opponent_ball() + else: + # player is fouled + self.foul_shots(1) + self.opponent_ball() + else: + if random.random() > .5: + print("Shot is blocked. Ball controlled by " + + self.opponent + ".\n") + self.opponent_ball() + else: + print("Shot is blocked. Ball controlled by Dartmouth.") + self.dartmouth_ball() + else: + print("Shot is off target.") + if self.defense / 6 * random.random() > .45: + print("Rebound to " + self.opponent + "\n") + self.opponent_ball() + else: + print("Dartmouth controls the rebound.") + if random.random() > .4: + if self.defense == 6 and random.random() > .6: + print("Pass stolen by " + self.opponent + + ", easy lay up") + self.add_points(0, 2) + self.dartmouth_ball() + else: + # ball is passed back to you + self.ball_passed_back() + else: + print("") + self.dartmouth_non_jump_shot() + else: + print("Shot is good.") + self.add_points(1, 2) + self.opponent_ball() + + # called when the user enters 0, 3, or 4 + # lay up, set shot, or defense change + def dartmouth_non_jump_shot(self): + self.time += 1 + if self.time == 50: + self.halftime() + elif self.time == 92: + self.two_minute_warning() + + if self.shot == 4: + print("Set shot.") + elif self.shot == 3: + print("Lay up.") + elif self.shot == 0: + self.change_defense() + + # simulates different outcomes after a lay up or set shot + if 7/self.defense*random.random() > .4: + if 7/self.defense*random.random() > .7: + if 7/self.defense*random.random() > .875: + if 7/self.defense*random.random() > .925: + print("Charging foul. Dartmouth loses the ball.\n") + self.opponent_ball() + else: + print("Shot blocked. " + self.opponent + "'s ball.\n") + self.opponent_ball() + else: + self.foul_shots(1) + self.opponent_ball() + else: + print("Shot is off the rim.") + if random.random() > 2/3: + print("Dartmouth controls the rebound.") + if random.random() > .4: + print("Ball passed back to you.\n") + self.dartmouth_ball() + else: + self.dartmouth_non_jump_shot() + else: + print(self.opponent + " controls the rebound.\n") + self.opponent_ball() + else: + print("Shot is good. Two points.") + self.add_points(1, 2) + self.opponent_ball() + + # plays out a Dartmouth posession, starting with your choice of shot + def dartmouth_ball(self): + print("Your shot? ", end='') + self.shot = None + try: + self.shot = int(input()) + except ValueError: + self.shot = None + + while self.shot not in self.shot_choices: + print("Incorrect answer. Retype it. Your shot? ", end='') + try: + self.shot = int(input()) + except: + continue + + if self.time < 100 or random.random() < .5: + if self.shot == 1 or self.shot == 2: + self.dartmouth_jump_shot() + else: + self.dartmouth_non_jump_shot() + else: + if self.score[0] != self.score[1]: + print("\n ***** End Of Game *****") + print("Final Score: Dartmouth: " + str(self.score[1]) + " " + + self.opponent + ": " + str(self.score[0])) + else: + print("\n ***** End Of Second Half *****") + print("Score at end of regulation time:") + print(" Dartmouth: " + str(self.score[1]) + " " + + self.opponent + ": " + str(self.score[0])) + print("Begin two minute overtime period") + self.time = 93 + self.start_of_period() + + # simulates the opponents jumpshot + def opponent_jumpshot(self): + print("Jump Shot.") + if 8/self.defense*random.random() > .35: + if 8/self.defense*random.random() > .75: + if 8/self.defense*random.random() > .9: + print("Offensive foul. Dartmouth's ball.\n") + self.dartmouth_ball() + else: + self.foul_shots(0) + self.dartmouth_ball() + else: + print("Shot is off the rim.") + if self.defense/6*random.random() > .5: + print(self.opponent + " controls the rebound.") + if self.defense == 6: + if random.random() > .75: + print("Ball stolen. Easy lay up for Dartmouth.") + self.add_points(1, 2) + self.opponent_ball() + else: + if random.random() > .5: + print("") + self.opponent_non_jumpshot() + else: + print("Pass back to " + self.opponent + + " guard.\n") + self.opponent_ball() + else: + if random.random() > .5: + self.opponent_non_jumpshot() + else: + print("Pass back to " + self.opponent + + " guard.\n") + self.opponent_ball() + else: + print("Dartmouth controls the rebound.\n") + self.dartmouth_ball() + else: + print("Shot is good.") + self.add_points(0, 2) + self.dartmouth_ball() + + # simulates opponents lay up or set shot + def opponent_non_jumpshot(self): + if self.z1 > 3: + print("Set shot.") + else: + print("Lay up") + if 7/self.defense*random.random() > .413: + print("Shot is missed.") + if self.defense/6*random.random() > .5: + print(self.opponent + " controls the rebound.") + if self.defense == 6: + if random.random() > .75: + print("Ball stolen. Easy lay up for Dartmouth.") + self.add_points(1, 2) + self.opponent_ball() + else: + if random.random() > .5: + print("") + self.opponent_non_jumpshot() + else: + print("Pass back to " + self.opponent + + " guard.\n") + self.opponent_ball() + else: + if random.random() > .5: + print("") + self.opponent_non_jumpshot() + else: + print("Pass back to " + self.opponent + " guard\n") + self.opponent_ball() + else: + print("Dartmouth controls the rebound.\n") + self.dartmouth_ball() + else: + print("Shot is good.") + self.add_points(0, 2) + self.dartmouth_ball() + + # simulates an opponents possesion + # #randomly picks jump shot or lay up / set shot. + def opponent_ball(self): + self.time += 1 + if self.time == 50: + self.halftime() + self.z1 = 10/4*random.random()+1 + if self.z1 > 2: + self.opponent_non_jumpshot() + else: + self.opponent_jumpshot() + + +new_game = Basketball() From e22e1bed266fd9e6224a9bdd751645cf2d502926 Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Sun, 9 Jan 2022 23:38:17 +0100 Subject: [PATCH 692/749] Add D version of High_IQ (48). --- 48_High_IQ/d/.gitignore | 2 + 48_High_IQ/d/README.md | 214 ++++++++++++++++++++++++++++++++++++ 48_High_IQ/d/highiq.d | 238 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 454 insertions(+) create mode 100644 48_High_IQ/d/.gitignore create mode 100644 48_High_IQ/d/README.md create mode 100644 48_High_IQ/d/highiq.d diff --git a/48_High_IQ/d/.gitignore b/48_High_IQ/d/.gitignore new file mode 100644 index 00000000..d969f6b2 --- /dev/null +++ b/48_High_IQ/d/.gitignore @@ -0,0 +1,2 @@ +*.exe +*.obj diff --git a/48_High_IQ/d/README.md b/48_High_IQ/d/README.md new file mode 100644 index 00000000..0eea7b00 --- /dev/null +++ b/48_High_IQ/d/README.md @@ -0,0 +1,214 @@ +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). + +## Running the code + +Assuming the reference [dmd](https://dlang.org/download.html#dmd) compiler: +```shell +dmd -dip1000 -run highiq.d +``` + +[Other compilers](https://dlang.org/download.html) also exist. + + +## Discussion + +The original BASIC game code made use of calculus and clever choises of field IDs to determine the validity of moves. +This is the original layout of IDs over the board: + +``` + 13 14 15 + + 22 23 24 + +29 30 31 32 33 34 35 + +38 39 40 41 42 43 44 + +47 48 49 50 51 52 53 + + 58 59 60 + + 67 68 69 +``` + +This seems not very logical, because, wouldn't it make much more sense to let columns increase with 1 and rows increase +with 10, so you'd get a consistent coordinate system? It seems that the original author's first step in validating +moves was to check that moves jumped from one field over another one onto the next. He did this by making sure that +adjacent IDs alter between even and odd horizontally *and* vertically. So a valid move was always from an even ID to an +even ID *or* from an odd ID to an odd ID. So one of the checks that the BASIC code made was that the sum of both IDs +was even. This is of course not a sufficient test, because moves that jump over three fields are illegal. Therefore the +IDs seem to have been carefully laid oud so that the IDs increase with 1 horizontally, and 9 vertically, everywhere. So +the only valid difference between IDs for a horizontal move was always 2, and the only valid difference for a vertical +move was always 18. + +Fact of the matter is, however, that checking for difference is sufficient and the even sum rule is superfluous, so +there is no need for the peculiar distribution of field IDs. Therefore I have chosen the following more logical +distribution: + +``` + 13 14 15 + + 23 24 25 + +31 32 33 34 35 36 37 + +41 42 43 44 45 46 47 + +51 52 53 54 55 56 57 + + 63 64 65 + + 73 74 75 +``` + +As a consequence, the implementation of the game code has become much simpler; Not alone due to one less check, but due +to the fact that conversions between IDs and board coordinates have become unnecessary and thus we can work with a single +representation of the board state. + +This version makes a prettier print of the board than the BASIC original, with coordinates for every move, and explains +illegal moves. + + +## Demo + +``` + H-I-Q +(After Creative Computing Morristown, New Jersey) + + +Fields are identified by 2-digit numbers, each +between 1 and 7. Example: the middle field is 44, +the bottom middle is 74. + + _1 _2 _3 _4 _5 _6 _7 + ┌───┬───┬───┐ + 1_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 2_ │ ■ │ ■ │ ■ │ + ┌───┬───┼───┼───┼───┼───┬───┐ + 3_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 4_ │ ■ │ ■ │ ■ │ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 5_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + └───┴───┼───┼───┼───┼───┴───┘ + 6_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 7_ │ ■ │ ■ │ ■ │ + └───┴───┴───┘ + +Move which peg? 23 +The peg at 23 has nowhere to go. Try again. + +Move which peg? 24 +To where? 34 +Field 34 is occupied. Try again. +To where? 54 +Field 54 is occupied. Try again. +To where? 44 + + _1 _2 _3 _4 _5 _6 _7 + ┌───┬───┬───┐ + 1_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 2_ │ ■ │ │ ■ │ + ┌───┬───┼───┼───┼───┼───┬───┐ + 3_ │ ■ │ ■ │ ■ │ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 4_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 5_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + └───┴───┼───┼───┼───┼───┴───┘ + 6_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 7_ │ ■ │ ■ │ ■ │ + └───┴───┴───┘ + +Move which peg? 14 +The peg at 14 has nowhere to go. Try again. + +Move which peg? 24 +There is no peg at 24. Try again. + +Move which peg? 44 +The peg at 44 has nowhere to go. Try again. + +Move which peg? 32 +To where? 22 +Field 22 is ouside the board. Try again. +To where? 33 +Field 33 is occupied. Try again. +To where? 34 + + _1 _2 _3 _4 _5 _6 _7 + ┌───┬───┬───┐ + 1_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 2_ │ ■ │ │ ■ │ + ┌───┬───┼───┼───┼───┼───┬───┐ + 3_ │ ■ │ │ │ ■ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 4_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 5_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + └───┴───┼───┼───┼───┼───┴───┘ + 6_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 7_ │ ■ │ ■ │ ■ │ + └───┴───┴───┘ + +Move which peg? 44 +To where? 33 +You cannot move diagonally. Try again. +To where? 24 + + _1 _2 _3 _4 _5 _6 _7 + ┌───┬───┬───┐ + 1_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 2_ │ ■ │ ■ │ ■ │ + ┌───┬───┼───┼───┼───┼───┬───┐ + 3_ │ ■ │ │ │ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 4_ │ ■ │ ■ │ ■ │ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 5_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + └───┴───┼───┼───┼───┼───┴───┘ + 6_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 7_ │ ■ │ ■ │ ■ │ + └───┴───┴───┘ + +Move which peg? 36 +To where? 33 +You can't jump that far. Try again. +To where? 35 +Field 35 is occupied. Try again. +To where? 34 + + _1 _2 _3 _4 _5 _6 _7 + ┌───┬───┬───┐ + 1_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 2_ │ ■ │ ■ │ ■ │ + ┌───┬───┼───┼───┼───┼───┬───┐ + 3_ │ ■ │ │ │ ■ │ │ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 4_ │ ■ │ ■ │ ■ │ │ ■ │ ■ │ ■ │ + ├───┼───┼───┼───┼───┼───┼───┤ + 5_ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ ■ │ + └───┴───┼───┼───┼───┼───┴───┘ + 6_ │ ■ │ ■ │ ■ │ + ├───┼───┼───┤ + 7_ │ ■ │ ■ │ ■ │ + └───┴───┴───┘ + +Move which peg? 46 +To where? 36 +You need to jump over another peg. Try again. +To where? down +Field 00 is ouside the board. Try again. +To where? +``` diff --git a/48_High_IQ/d/highiq.d b/48_High_IQ/d/highiq.d new file mode 100644 index 00000000..78445545 --- /dev/null +++ b/48_High_IQ/d/highiq.d @@ -0,0 +1,238 @@ +@safe: // Make @safe the default for this file, enforcing memory-safety. +import std; + +void main() +{ + enum width = 50; + writeln(center("H-I-Q", width)); + writeln(center("(After Creative Computing Morristown, New Jersey)\n\n", width)); + writeln(wrap("Fields are identified by 2-digit numbers, each between 1 and 7. " ~ + "Example: the middle field is 44, the bottom middle is 74.", width)); + + Board board; + + while (true) + { + while (!board.isGameOver) + { + writeln(board); // Calls board.toString(). + board.makeMove; + } + writeln(board, "\nThe game is over.\nYou had ", board.numPegs, " pieces remaining."); + if (board.numPegs == 1) + writeln("Bravo! You made a perfect score!\n", + "Make a screen dump as a record of your accomplishment!\n"); + write("Play again? (Yes or No) "); + if (readString.toLower != "yes") + break; + writeln; writeln; + board = Board.init; + } + writeln("\nSo long for now.\n"); +} + +/// Representation of the game board with pegs. +struct Board +{ + enum {outside, taken, empty}; + int[8][8] state = [ + 1: [ 3: taken, 4: taken, 5: taken], + 2: [ 3: taken, 4: taken, 5: taken], + 3: [1: taken, 2: taken, 3: taken, 4: taken, 5: taken, 6: taken, 7: taken], + 4: [1: taken, 2: taken, 3: taken, 4: empty, 5: taken, 6: taken, 7: taken], + 5: [1: taken, 2: taken, 3: taken, 4: taken, 5: taken, 6: taken, 7: taken], + 6: [ 3: taken, 4: taken, 5: taken], + 7: [ 3: taken, 4: taken, 5: taken] + ]; // Row 0 and column 0 are unused. Default is 0 (outside). + + /// Returns a string representing the board and its current state. + string toString() const + { + dchar[][] lines = [(" _1 _2 _3 _4 _5 _6 _7 ").to!(dchar[]), + (" ┌───┬───┬───┐ ").to!(dchar[]), + (" 1_ │ │ │ │ ").to!(dchar[]), + (" ├───┼───┼───┤ ").to!(dchar[]), + (" 2_ │ │ │ │ ").to!(dchar[]), + (" ┌───┬───┼───┼───┼───┼───┬───┐").to!(dchar[]), + (" 3_ │ │ │ │ │ │ │ │").to!(dchar[]), + (" ├───┼───┼───┼───┼───┼───┼───┤").to!(dchar[]), + (" 4_ │ │ │ │ │ │ │ │").to!(dchar[]), + (" ├───┼───┼───┼───┼───┼───┼───┤").to!(dchar[]), + (" 5_ │ │ │ │ │ │ │ │").to!(dchar[]), + (" └───┴───┼───┼───┼───┼───┴───┘").to!(dchar[]), + (" 6_ │ │ │ │ ").to!(dchar[]), + (" ├───┼───┼───┤ ").to!(dchar[]), + (" 7_ │ │ │ │ ").to!(dchar[]), + (" └───┴───┴───┘ ").to!(dchar[])]; + foreach (y, row; state) + foreach (x, field; row) + if (field == taken) + lines[y * 2][x * 4 + 2] = '■'; + return lines.join("\n").to!string; + } + + /// Tests for possible moves. + bool isGameOver() const + { + foreach (r, row; state) + foreach (c, field; row) + if (field == taken && canMoveFrom(r, c)) + return false; + return true; + } + + bool canMoveFrom(int row, int col) const + { + if (row >= 3 && state[row - 2][col] == empty) // Up + return state[row - 1][col] == taken; + if (row <= 5 && state[row + 2][col] == empty) // Down + return state[row + 1][col] == taken; + if (col >= 3 && state[row][col - 2] == empty) // Left + return state[row][col - 1] == taken; + if (col <= 5 && state[row][col + 2] == empty) // Right + return state[row][col + 1] == taken; + return false; + } + + /// Asks for input, validates the move and updates the board. + void makeMove() + { + bool isOutside(int row, int col) + { + if (row < 1 || row > 7 || + col < 1 || col > 7 || + state[row][col] == outside) + { + writeln("Field ", row, col, " is ouside the board. Try again."); + return true; + } + return false; + } + + while (true) + { + auto from = (){ + while (true) + { + write("\nMove which peg? "); + int field = readInt; + int row = field / 10, col = field % 10; + if (isOutside(row, col)) + continue; + if (state[row][col] != taken) + { + writeln("There is no peg at ", field, ". Try again."); + continue; + } + if (!canMoveFrom(row, col)) + { + writeln("The peg at ", field, " has nowhere to go. Try again."); + continue; + } + return tuple!("row", "col")(row, col); + } + }(); + auto to = (){ + while (true) + { + write("To where? "); + int field = readInt; + int row = field / 10, col = field % 10; + if (isOutside(row, col)) + continue; + if (state[row][col] == taken) + { + writeln("Field ", field, " is occupied. Try again."); + continue; + } + if (row != from.row && col != from.col) + { + writeln("You cannot move diagonally. Try again."); + continue; + } + if (row == from.row && col == from.col) + { + writeln("You aren't going anywhere. Try again."); + continue; + } + if (abs(row - from.row) + abs(col - from.col) > 2) + { + writeln("You can't jump that far. Try again."); + continue; + } + if (abs(row - from.row) + abs(col - from.col) < 2 || + state[(row + from.row) / 2][(col + from.col) / 2] != taken) + { + writeln("You need to jump over another peg. Try again."); + continue; + } + return tuple!("row", "col")(row, col); + } + }(); + // The move is legal. Update the board state. + state[from.row][from.col] = empty; + state[ to.row][ to.col] = taken; + state[(from.row + to.row) / 2][(from.col + to.col) / 2] = empty; + writeln; + break; + } + } + + /// Returns the number of remaining pegs on the board. + int numPegs() const + { + int num = 0; + foreach (row; state) + foreach (field; row) + if (field == taken) + num++; + return num; + } +} + +/// Reads an integer from standard input. +int readInt() nothrow +{ + try + return readString.to!int; + catch (Exception) // Not an integer. + return 0; +} + +/// Reads a string from standard input. +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; +} + +version (Windows) +{ + // Make the Windows console do a better job at printing UTF-8 strings, + // and restore the default upon termination. + + import core.sys.windows.windows; + + shared static this() @trusted + { + SetConsoleOutputCP(CP_UTF8); + } + + shared static ~this() @trusted + { + SetConsoleOutputCP(GetACP); + } +} From 5d00a092af55935b604d4c7f00af71314420094c Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 11 Jan 2022 00:00:22 +1100 Subject: [PATCH 693/749] Building kotlin files. IntelliJ import instructions. --- HOW_TO_RUN_THE_GAMES.md | 28 ++++++++++++++++++++-------- buildJvm/README.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/HOW_TO_RUN_THE_GAMES.md b/HOW_TO_RUN_THE_GAMES.md index 6df23205..f067f872 100644 --- a/HOW_TO_RUN_THE_GAMES.md +++ b/HOW_TO_RUN_THE_GAMES.md @@ -23,16 +23,23 @@ Alternatively, for non-dotnet compatible translations, you will need [Visual Stu ## java +{% tip %} + +You can build all the java and kotlin games at once +using the instructions in the [buildJvm directory](buildJvm/README.md) + +{% endtip %} + 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` + * eg. `javac AceyDuceyGame.java` 1. Run the compiled program with `java`: - * eg. `java AceyDuceyGame` - + * eg. `java AceyDuceyGame` + or if you are **using JDK11 or later** you can now execute a self contained java file that has a main method directly with `java .java`. ## javascript @@ -41,6 +48,11 @@ The javascript examples can be run from within your web browser: 1. Simply open the corresponding `.html` file from your web browser. +## kotlin + +Use the directions in [buildJvm](buildJvm/README.md) to build for kotlin. You can also use those directions to +build java games. + ## 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/). @@ -48,7 +60,7 @@ The pascal examples can be run using [Free Pascal](https://www.freepascal.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` + * eg. `fpc amazing.pas` 1. The output is an executable file that can be run directly. ## perl @@ -57,7 +69,7 @@ The perl translations can be run using a perl interpreter (a copy can be downloa 1. From the command-line, navigate to the corresponding directory. 1. Invoke with the `perl` command. - * eg. `perl aceyducey.pl` + * eg. `perl aceyducey.pl` ## python @@ -65,8 +77,8 @@ The python translations can be run from the command line by using the `py` inter 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` + * eg. `py acey_ducey_oo.py` + * eg. `python aceyducey.py` **Note** @@ -80,7 +92,7 @@ If you don't already have a ruby interpreter, you can download it from the [ruby 1. From the command-line, navigate to the corresponding directory. 1. Invoke with the `ruby` tool. - * eg. `ruby aceyducey.rb` + * eg. `ruby aceyducey.rb` ## vbnet diff --git a/buildJvm/README.md b/buildJvm/README.md index f0046ab3..c70bf573 100644 --- a/buildJvm/README.md +++ b/buildJvm/README.md @@ -20,6 +20,34 @@ Then, run a game You will need to install openjdk 17, because some games use advanced Java features. We should be using version 17 anyway, because anything less than 17 is deprecated. +--- +## Using an IDE to work on JVM games + +You can open the entire Basic Computer Games project in an IDE, with any IDE capable +of importing from a gradle project. + +### IntelliJ / Android Studio + +1. (Optional) If you want to make changes, or contribute a new kotlin or java version +of one of the games, use [github "fork"](https://docs.github.com/en/get-started/quickstart/fork-a-repo) +to create your own editable fork of the project. +2. Check out the code using `File` -> `New` -> `Project from Version Control` + 1. Enter the URL of the project. For the main project this will be `https://github.com/coding-horror/basic-computer-games.git`, for your +own fork this will be `https://github.com/YOURNAMEHERE/basic-computer-games.git` + 2. Choose a directory for the clone to live in +3. Click `Clone` + +The project will open, and eventually you will get a little alert box in the bottom right corner saying "Gradle build script found". + +Click the "Load" link in the alert box, to load the gradle project. + +You should see all the games appear on the left side of the screen. If you have loaded +your own fork, you can modify, commit and push your changes to github. + +If you are using the main `coding-horror` branch, you can still make and run your own changes. If +your git skills are up to the task, you might even fork the project and change your +local clone to point to your new forked project. + --- ## Adding a new game @@ -37,6 +65,7 @@ The `build.gradle` file will normally be identical to this: plugins { id 'application' + // id 'org.jetbrains.kotlin.jvm' // UNCOMMENT for kotlin projects } sourceSets { From 25c79621a0c42a3f755a962bb9a5913ef5ae5cf8 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 11 Jan 2022 00:09:09 +1100 Subject: [PATCH 694/749] Update HOW_TO_RUN_THE_GAMES.md remove bad formatting --- HOW_TO_RUN_THE_GAMES.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/HOW_TO_RUN_THE_GAMES.md b/HOW_TO_RUN_THE_GAMES.md index f067f872..fae0656f 100644 --- a/HOW_TO_RUN_THE_GAMES.md +++ b/HOW_TO_RUN_THE_GAMES.md @@ -23,13 +23,9 @@ Alternatively, for non-dotnet compatible translations, you will need [Visual Stu ## java -{% tip %} - -You can build all the java and kotlin games at once +**TIP:** You can build all the java and kotlin games at once using the instructions in the [buildJvm directory](buildJvm/README.md) -{% endtip %} - 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/)). From 8b2c72bc21fc93fcabdb108721fbadad8ec0e1d3 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 11 Jan 2022 00:12:21 +1100 Subject: [PATCH 695/749] update README.md --- buildJvm/README.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/buildJvm/README.md b/buildJvm/README.md index c70bf573..a5169abd 100644 --- a/buildJvm/README.md +++ b/buildJvm/README.md @@ -1,25 +1,28 @@ # JVM gradle scripts ## Quickstart +You will need to install openjdk 17, because some games use advanced Java features. +We should be using version 17 anyway, because anything less than 17 is deprecated. Build all the games: - - cd buildJvm - ./gradlew -q assemble installDist distributeBin distributeLib +```shell + cd buildJvm + ./gradlew -q assemble installDist distributeBin distributeLib +``` Then, run a game ### Mac or linux: - - build/distrib/bin/build_53_King_kotlin - +```shell +build/distrib/bin/build_53_King_kotlin +``` ### Windows [not tested yet] - build\distrib\bin\build_53_King_kotlin.bat +```shell +build\distrib\bin\build_53_King_kotlin.bat +``` -You will need to install openjdk 17, because some games use advanced Java features. -We should be using version 17 anyway, because anything less than 17 is deprecated. --- ## Using an IDE to work on JVM games @@ -62,7 +65,7 @@ there is some special requirement. directory for the java or kotlin file, and the class that contains the `main` method. The `build.gradle` file will normally be identical to this: - +```groovy plugins { id 'application' // id 'org.jetbrains.kotlin.jvm' // UNCOMMENT for kotlin projects @@ -83,6 +86,7 @@ The `build.gradle` file will normally be identical to this: application { mainClass = gameMain } +``` And the `gradle.properties` file should look like this: From eaf24739e3e8f0b8f4ff5b7e9d7c306a99620622 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 10:05:28 -0500 Subject: [PATCH 696/749] Initial Commit, added instructions --- 75_Roulette/java/src/Roulette.java | 69 ++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 75_Roulette/java/src/Roulette.java diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java new file mode 100644 index 00000000..a07d2afd --- /dev/null +++ b/75_Roulette/java/src/Roulette.java @@ -0,0 +1,69 @@ +import java.io.PrintStream; + +public class Roulette { + + private PrintStream out; + + public static void main(String[] args) { + new Roulette(System.out).play(); + } + + public Roulette(PrintStream out) { + this.out = out; + } + + public void play() { + printInstructions(); + } + + + public void printInstructions() { + System.out.println(); + System.out.println( "THIS IS THE BETTING LAYOUT"); + System.out.println( " (*=RED)"); + System.out.println(); + System.out.println( " 1* 2 3*"); + System.out.println( " 4 5* 6 "); + System.out.println( " 7* 8 9*"); + System.out.println( "10 11 12*"); + System.out.println( "---------------"); + System.out.println( "13 14* 15 "); + System.out.println( "16* 17 18*"); + System.out.println( "19* 20 21*"); + System.out.println( "22 23* 24 "); + System.out.println( "---------------"); + System.out.println( "25* 26 27*"); + System.out.println( "28 29 30*"); + System.out.println( "31 32* 33 "); + System.out.println( "34* 35 36*"); + System.out.println( "---------------"); + System.out.println( " 00 0 "); + System.out.println(); + System.out.println( "TYPES OF BETS"); + System.out.println(); + System.out.println( "THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET"); + System.out.println( "ON THAT NUMBER."); + System.out.println( "THESE PAY OFF 35:1"); + System.out.println(); + System.out.println( "THE 2:1 BETS ARE:"); + System.out.println( " 37) 1-12 40) FIRST COLUMN"); + System.out.println( " 38) 13-24 41) SECOND COLUMN"); + System.out.println( " 39) 25-36 42) THIRD COLUMN"); + System.out.println(); + System.out.println( "THE EVEN MONEY BETS ARE:"); + System.out.println( " 43) 1-18 46) ODD"); + System.out.println( " 44) 19-36 47) RED"); + System.out.println( " 45) EVEN 48) BLACK"); + System.out.println(); + System.out.println( " 49)0 AND 50)00 PAY OFF 35:1"); + System.out.println( " NOTE: 0 AND 00 DO NOT COUNT UNDER ANY"); + System.out.println( " BETS EXCEPT THEIR OWN."); + System.out.println(); + System.out.println( "WHEN I ASK FOR EACH BET, TYPE THE NUMBER"); + System.out.println( "AND THE AMOUNT, SEPARATED BY A COMMA."); + System.out.println( "FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500"); + System.out.println( "WHEN I ASK FOR A BET."); + System.out.println(); + System.out.println( "THE MINIMUM BET IS $5, THE MAXIMUM IS $500."); + } +} From b97f4f5e3e404970124e78bb55674cee8e38d4a1 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 10:44:49 -0500 Subject: [PATCH 697/749] Added querying of bets and randomized roll --- 75_Roulette/java/src/Roulette.java | 198 +++++++++++++++++++++-------- 1 file changed, 147 insertions(+), 51 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index a07d2afd..3522364d 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -1,69 +1,165 @@ +import java.io.InputStream; import java.io.PrintStream; +import java.util.*; public class Roulette { private PrintStream out; + private Scanner scanner; - public static void main(String[] args) { - new Roulette(System.out).play(); + private int houseBalance, playerBalance; + + private Random random; + + private static Set RED_NUMBERS; + + static { + RED_NUMBERS = Set.of(1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36); } - public Roulette(PrintStream out) { + public static void main(String[] args) { + new Roulette(System.out, System.in).play(); + } + + public Roulette(PrintStream out, InputStream in) { this.out = out; + this.scanner = new Scanner(in); + houseBalance = 100000; + playerBalance = 1000; + random = new Random(); } public void play() { - printInstructions(); + out.println(" ROULETTE"); + out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + out.println("WELCOME TO THE ROULETTE TABLE\n"); + out.println("DO YOU WANT INSTRUCTIONS"); + if(scanner.nextLine().toLowerCase().charAt(0) != 'n') { + printInstructions(); + } + + while(houseBalance > 0 && playerBalance > 0) { + + Bet[] bets = queryBets(); + + out.println("SPINNING...\n\n\n"); + int result = random.nextInt(1,39); + + /* + Equivalent to following line + if(RED_NUMBERS.contains(result)) { + out.println(result + " RED"); + } else { + out.println(result + " BLACK"); + } + */ + out.println(result + (RED_NUMBERS.contains(result) ? " RED\n" : " BLACK\n")); + + + } } + private Bet[] queryBets() { + int numBets = -1; + while(numBets < 1) { + out.println("HOW MANY BETS"); + try { + numBets = Integer.parseInt(scanner.nextLine()); + } catch(NumberFormatException exception) { + out.println("THAT IS NOT A NUMBER"); + } + } + + Bet[] bets = new Bet[numBets]; + + for(int i = 0; i < numBets; i++) { + try { + out.println("BET NUMBER " + (i + 1) + ":"); + String[] values = scanner.nextLine().split(","); + int betNumber = Integer.parseInt(values[0]); + int betValue = Integer.parseInt(values[1]); + + for(int j = 0; j < i; j++) { + if(bets[j].number == betNumber) { + out.println("YOU MADE THAT BET ONCE ALREADY,DUM-DUM"); + throw new Exception(); + } + } + + if(betNumber < 1 || betNumber > 50 || betValue < 5 || betValue > 500) { + out.println("INVALID VALUE, TRY AGAIN"); + i--; + continue; + } + + bets[i] = new Bet(betNumber,betValue); + + } catch(Exception exception) { + if(exception instanceof NumberFormatException) { + out.println("SYNTAX ERROR, TRY AGAIN"); + } + i--; + } + } + return bets; + } public void printInstructions() { - System.out.println(); - System.out.println( "THIS IS THE BETTING LAYOUT"); - System.out.println( " (*=RED)"); - System.out.println(); - System.out.println( " 1* 2 3*"); - System.out.println( " 4 5* 6 "); - System.out.println( " 7* 8 9*"); - System.out.println( "10 11 12*"); - System.out.println( "---------------"); - System.out.println( "13 14* 15 "); - System.out.println( "16* 17 18*"); - System.out.println( "19* 20 21*"); - System.out.println( "22 23* 24 "); - System.out.println( "---------------"); - System.out.println( "25* 26 27*"); - System.out.println( "28 29 30*"); - System.out.println( "31 32* 33 "); - System.out.println( "34* 35 36*"); - System.out.println( "---------------"); - System.out.println( " 00 0 "); - System.out.println(); - System.out.println( "TYPES OF BETS"); - System.out.println(); - System.out.println( "THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET"); - System.out.println( "ON THAT NUMBER."); - System.out.println( "THESE PAY OFF 35:1"); - System.out.println(); - System.out.println( "THE 2:1 BETS ARE:"); - System.out.println( " 37) 1-12 40) FIRST COLUMN"); - System.out.println( " 38) 13-24 41) SECOND COLUMN"); - System.out.println( " 39) 25-36 42) THIRD COLUMN"); - System.out.println(); - System.out.println( "THE EVEN MONEY BETS ARE:"); - System.out.println( " 43) 1-18 46) ODD"); - System.out.println( " 44) 19-36 47) RED"); - System.out.println( " 45) EVEN 48) BLACK"); - System.out.println(); - System.out.println( " 49)0 AND 50)00 PAY OFF 35:1"); - System.out.println( " NOTE: 0 AND 00 DO NOT COUNT UNDER ANY"); - System.out.println( " BETS EXCEPT THEIR OWN."); - System.out.println(); - System.out.println( "WHEN I ASK FOR EACH BET, TYPE THE NUMBER"); - System.out.println( "AND THE AMOUNT, SEPARATED BY A COMMA."); - System.out.println( "FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500"); - System.out.println( "WHEN I ASK FOR A BET."); - System.out.println(); - System.out.println( "THE MINIMUM BET IS $5, THE MAXIMUM IS $500."); + out.println(); + out.println( "THIS IS THE BETTING LAYOUT"); + out.println( " (*=RED)"); + out.println(); + out.println( " 1* 2 3*"); + out.println( " 4 5* 6 "); + out.println( " 7* 8 9*"); + out.println( "10 11 12*"); + out.println( "---------------"); + out.println( "13 14* 15 "); + out.println( "16* 17 18*"); + out.println( "19* 20 21*"); + out.println( "22 23* 24 "); + out.println( "---------------"); + out.println( "25* 26 27*"); + out.println( "28 29 30*"); + out.println( "31 32* 33 "); + out.println( "34* 35 36*"); + out.println( "---------------"); + out.println( " 00 0 "); + out.println(); + out.println( "TYPES OF BETS"); + out.println(); + out.println( "THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET"); + out.println( "ON THAT NUMBER."); + out.println( "THESE PAY OFF 35:1"); + out.println(); + out.println( "THE 2:1 BETS ARE:"); + out.println( " 37) 1-12 40) FIRST COLUMN"); + out.println( " 38) 13-24 41) SECOND COLUMN"); + out.println( " 39) 25-36 42) THIRD COLUMN"); + out.println(); + out.println( "THE EVEN MONEY BETS ARE:"); + out.println( " 43) 1-18 46) ODD"); + out.println( " 44) 19-36 47) RED"); + out.println( " 45) EVEN 48) BLACK"); + out.println(); + out.println( " 49)0 AND 50)00 PAY OFF 35:1"); + out.println( " NOTE: 0 AND 00 DO NOT COUNT UNDER ANY"); + out.println( " BETS EXCEPT THEIR OWN."); + out.println(); + out.println( "WHEN I ASK FOR EACH BET, TYPE THE NUMBER"); + out.println( "AND THE AMOUNT, SEPARATED BY A COMMA."); + out.println( "FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500"); + out.println( "WHEN I ASK FOR A BET."); + out.println(); + out.println( "THE MINIMUM BET IS $5, THE MAXIMUM IS $500."); + } + + public class Bet { + final int number, value; + + public Bet(int number, int value) { + this.number = number; + this.value = value; + } } } From c32798aa755eddc94a878faf09e8c72f9732dd45 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 11:14:10 -0500 Subject: [PATCH 698/749] Added bet checking conditions --- 75_Roulette/java/src/Roulette.java | 45 ++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 3522364d..533afe4e 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -53,7 +53,11 @@ public class Roulette { out.println(result + " BLACK"); } */ - out.println(result + (RED_NUMBERS.contains(result) ? " RED\n" : " BLACK\n")); + switch(result) { + case 37 -> out.print("00"); + case 38 -> out.print("0"); + default -> out.println(result + (RED_NUMBERS.contains(result) ? " RED\n" : " BLACK\n")); + } } @@ -80,7 +84,7 @@ public class Roulette { int betValue = Integer.parseInt(values[1]); for(int j = 0; j < i; j++) { - if(bets[j].number == betNumber) { + if(bets[j].num == betNumber) { out.println("YOU MADE THAT BET ONCE ALREADY,DUM-DUM"); throw new Exception(); } @@ -104,6 +108,35 @@ public class Roulette { return bets; } + private void betResults(Bet[] bets, int num) { + for(int i = 0; i < bets.length; i++) { + Bet bet = bets[i]; + /* + Using a switch statement of ternary operators that check if a certain condition is met based on the bet value + Returns the coefficient that the bet amount should be multiplied by to get the resulting value + */ + int coefficient = switch(bet.num) { + case 37 -> (num <= 12) ? 2 : -1; + case 38 -> (num > 12 && num <= 24) ? 2 : -1; + case 39 -> (num > 24 && num < 37) ? 2 : -1; + case 40 -> (num < 37 && num % 3 == 1) ? 2 : -1; + case 41 -> (num < 37 && num % 3 == 2) ? 2 : -1; + case 42 -> (num < 37 && num % 3 == 0) ? 2 : -1; + case 43 -> (num <= 18) ? 1 : -1; + case 44 -> (num > 18 && num <= 36) ? 1 : -1; + case 45 -> (num % 2 == 0) ? 1 : -1; + case 46 -> (num % 2 == 1) ? 1 : -1; + case 47 -> RED_NUMBERS.contains(num) ? 1 : -1; + case 48 -> !RED_NUMBERS.contains(num) ? 1 : -1; + case 49 -> (num == 37) ? 35 : -1; + case 50 -> (num == 38) ? 35 : -1; + default -> (bet.num < 49 && bet.num == num) ? 35 : -1; + }; + + int betResult = bet.amount * coefficient; + } + } + public void printInstructions() { out.println(); out.println( "THIS IS THE BETTING LAYOUT"); @@ -155,11 +188,11 @@ public class Roulette { } public class Bet { - final int number, value; + final int num, amount; - public Bet(int number, int value) { - this.number = number; - this.value = value; + public Bet(int num, int amount) { + this.num = num; + this.amount = amount; } } } From a40c2fc5345b69bd4658e69d5657fc76e4836c42 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 11:29:50 -0500 Subject: [PATCH 699/749] Added replay and ending I think... --- 75_Roulette/java/src/Roulette.java | 42 +++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 533afe4e..49d14275 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -1,5 +1,6 @@ import java.io.InputStream; import java.io.PrintStream; +import java.lang.management.PlatformLoggingMXBean; import java.util.*; public class Roulette { @@ -38,7 +39,7 @@ public class Roulette { printInstructions(); } - while(houseBalance > 0 && playerBalance > 0) { + do { Bet[] bets = queryBets(); @@ -53,13 +54,33 @@ public class Roulette { out.println(result + " BLACK"); } */ - switch(result) { - case 37 -> out.print("00"); - case 38 -> out.print("0"); - default -> out.println(result + (RED_NUMBERS.contains(result) ? " RED\n" : " BLACK\n")); - } + switch(result) { + case 37 -> out.print("00"); + case 38 -> out.print("0"); + default -> out.println(result + (RED_NUMBERS.contains(result) ? " RED\n" : " BLACK\n")); + } + betResults(bets,result); + out.println(); + out.println("TOTALS:"); + out.println("\tME: " + houseBalance); + out.println("\tYOU " + playerBalance); + + } while(playAgain()); + if(playerBalance <= 0) { + out.println("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!"); + } else if(houseBalance <= 0) { + out.println("YOU BROKE THE HOUSE!"); + } + } + + private boolean playAgain() { + if(playerBalance > 0 && houseBalance > 0) { + out.println("PLAY AGAIN?"); + return scanner.nextLine().toLowerCase().charAt(0) == 'y'; + } else { + return false; } } @@ -134,6 +155,15 @@ public class Roulette { }; int betResult = bet.amount * coefficient; + + if(betResult < 0) { + out.println("YOU LOSE " + -betResult + " DOLLARS ON BET " + (i + 1)); + } else { + out.println("YOU WIN " + betResult + " DOLLARS ON BET " + (i + 1)); + } + + playerBalance += betResult; + houseBalance -= betResult; } } From 0d7f407197e19fd76068691270945863d830e397 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 11:31:04 -0500 Subject: [PATCH 700/749] Create roulette.py --- 75_Roulette/python/roulette.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 75_Roulette/python/roulette.py diff --git a/75_Roulette/python/roulette.py b/75_Roulette/python/roulette.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/75_Roulette/python/roulette.py @@ -0,0 +1 @@ + From 2dc63bb95a75326a78472a8698638c6e829ce258 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 11:41:02 -0500 Subject: [PATCH 701/749] Still unsure about $$ Is the check for the difference? Is it only when the house cannot pay what it owes? --- 75_Roulette/java/src/Roulette.java | 47 ++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 49d14275..c6e46152 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -1,6 +1,7 @@ import java.io.InputStream; import java.io.PrintStream; import java.lang.management.PlatformLoggingMXBean; +import java.time.LocalDateTime; import java.util.*; public class Roulette { @@ -69,14 +70,54 @@ public class Roulette { } while(playAgain()); if(playerBalance <= 0) { - out.println("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!"); + out.println("THANKS FOR YOUR MONEY\nI'LL USE IT TO BUY A SOLID GOLD ROULETTE WHEEL"); } else if(houseBalance <= 0) { - out.println("YOU BROKE THE HOUSE!"); + out.println("TO WHOM SHALL I MAKE THE CHECK"); + String name = scanner.nextLine(); + out.println(); + for(int i = 0; i < 72; i++) { + out.print("-"); + } + out.println(); + for(int i = 0; i < 50; i++) { + out.print(" "); + } + out.println("CHECK NO. " + random.nextInt(0,1000)); + out.println(); + for(int i = 0; i < 40; i++) { + out.print(" "); + } + out.println(LocalDateTime.now()); + out.println("\n"); + out.println("PAY TO THE ORDER OF----- " + name + "------$" + (playerBalance - 1000)); + out.println("\n"); + for(int i = 0; i < 10; i++) { + out.print(" "); + } + out.println("THE MEMORY BANK OF NEW YORK"); + for(int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("THE COMPUTER"); + for(int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("----------X-----"); + for(int i = 0; i < 72; i++) { + out.print("-"); + } + out.println("\n"); + out.println("COME BACK SOON"); } } private boolean playAgain() { - if(playerBalance > 0 && houseBalance > 0) { + if(playerBalance > 0) { + if(houseBalance <= 0) { + out.println("YOU BROKE THE HOUSE!"); + //using default values + playerBalance = 101000; + } out.println("PLAY AGAIN?"); return scanner.nextLine().toLowerCase().charAt(0) == 'y'; } else { From 82a126bce36b1c3aea47fbaa017953968cd968c7 Mon Sep 17 00:00:00 2001 From: Mark Wieder Date: Mon, 10 Jan 2022 10:18:24 -0800 Subject: [PATCH 702/749] initial attempt --- 65_Nim/ruby/nim.rb | 282 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 65_Nim/ruby/nim.rb diff --git a/65_Nim/ruby/nim.rb b/65_Nim/ruby/nim.rb new file mode 100644 index 00000000..a326695f --- /dev/null +++ b/65_Nim/ruby/nim.rb @@ -0,0 +1,282 @@ +puts "NIM".center(80) +puts"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".center(80) +puts "\n\n\n" + +#210 DIM A(100),B(100,10),D(2) +$pileArray = Array.new[100] +$bArray = Array.new +$dArray = Array.new[2] +$winOption = 0 # take-last option +$numberOfPiles = 1 +$c = 0 +$e = 0 +$f = 0 +$g = 0 +$h = 0 + +def displayTheRules +puts "THE GAME IS PLAYED WITH A NUMBER OF PILES OF OBJECTS." +puts "ANY NUMBER OF OBJECTS ARE REMOVED FROM ONE PILE BY YOU AND" +puts "THE MACHINE ALTERNATELY. ON YOUR TURN, YOU MAY TAKE" +puts "ALL THE OBJECTS THAT REMAIN IN ANY PILE, BUT YOU MUST" +puts "TAKE AT LEAST ONE OBJECT, AND YOU MAY TAKE OBJECTS FROM" +puts "ONLY ONE PILE ON A SINGLE TURN. YOU MUST SPECIFY WHETHER" +puts "WINNING IS DEFINED AS TAKING OR NOT TAKING THE LAST OBJECT," +puts "THE NUMBER OF PILES IN THE GAME, AND HOW MANY OBJECTS ARE" +puts "ORIGINALLY IN EACH PILE. EACH PILE MAY CONTAIN A" +puts "DIFFERENT NUMBER OF OBJECTS." +puts "THE MACHINE WILL SHOW ITS MOVE BY LISTING EACH PILE AND THE" +puts "NUMBER OF OBJECTS REMAINING IN THE PILES AFTER EACH OF ITS" +puts "MOVES." +end + +def sub1570 + $z=0 + for i in 1..$numberOfPiles do + if $pileArray[i] != 0 then + return + end + $z=1 + return + end +end + +def playAnother + put "do you want to play another game"; + return gets.strip.ucase == "YES" +end +puts "THIS IS THE GAME OF NIM." +print "DO YOU WANT INSTRUCTIONS?" +240 +wantInstructions = gets.strip.upcase +if wantInstructions == "YES" then + displayTheRules +end +#250 IF Z$="NO" THEN 440 +#260 IF Z$="no" THEN 440 +#270 IF Z$="YES" THEN displayTheRules +#280 IF Z$="yes" THEN displayTheRules +#290 PRINT "PLEASE ANSWER YES OR NO" +#300 GOTO 240 + +def sub490 # get number of piles + print "ENTER NUMBER OF PILES:" + while $numberOfPiles < 0 && $numberOfPiles <= 100 do + $numberOfPiles = gets.strip.to_i + end +end + +def getPileSizes + puts "ENTER PILE SIZES:" + for i in 1..$numberOfPiles do + print i + while true do + $pileArray[i] = gets.strip.to_i + if $pileArray[i] < 2000 && $pileArray[i] > 0 then + break + end + end + end +end + +def sub440 # get win option + puts "" + $winOption = 0 + while $winOption != 1 && q != 2 do + puts "ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST" + $winOption = gets.strip.to_i + end +end + +puts "DO YOU WANT TO MOVE FIRST?"; +#630 INPUT Q9$ +moveFirst = "" +while moveFirst != "YES" && moveFirst != "NO" do + moveFirst = gets.strip.upcase + case moveFirst + when "YES" + yourMove + when "NO" + machineMove + end +end + +#640 IF Q9$="YES" THEN 1450 +#650 IF Q9$="yes" THEN 1450 +#660 IF Q9$="NO" THEN 700 +#670 IF Q9$="no" THEN 700 +#680 PRINT "PLEASE ANSWER YES OR NO." +#690 GOTO 630 + +def machineMove + if $winOption == 1 then + sub940 # take last + end + $c=0 + for i in 1..$numberOfPiles do + if $pileArray[i] != 0 then 770 + $c=$c+1 + if $c == 3 then + sub840 + end + $dArray[$c-1]=i + end + end + + if $c == 2 then + sub920 + end + if $pileArray[$dArray[0]] > 1 then + machineWins + end + machineLoses +end + +def machineLoses + puts "MACHINE LOSES" +# 810 GOTO playAnother + if playAnother then + sub440 # loop for another + end +end + +def machineWins + puts "MACHINE WINS" +# 830 GOTO playAnother + if playAnother then + sub440 # loop for another + end +end + +def sub840 + $c=0 + for i in 1..$numberOfPiles do + if $pileArray[i] > 1 then + sub940 + end + if $pileArray[i] == 0 then 890 + $c=$c+1 + end + if $c/2 != ($c/2).to_i then + machineLoses + end + sub940 # goto + end +end + +def sub920 + if $pileArray[$dArray[0]] == 1 then + machineWins + end + if $pileArray[$dArray[1]] == 1 then + machineWins + end +end + +def sub940 + for i in 1..$numberOfPiles do + e=$pileArray[i] + for j in 0..10 do + $f = $e/2 + $bArray[i][j] = 2*($f-($f.to_i)) + $e = $f.to_i + end + end +end + +#for j in 10..0 STEP -1 do +10..0.step(-1).each do|index| + $c=0 + $h=0 + for i in 1..$numberOfPiles do + if $bArray[i][index] != 0 then + $c=$c+1 + if $pileArray[i] > $h then + $h = $pileArray[i] + $g = i + end + end + end +end + +if $c/2 != ($c/2).to_i then 1190 +end +$e = rand($numberOfPiles).to_i +#if $pileArray[$e] == 0 then 1140 + +$f = rand($pileArray[$e]).to_i +$pileArray[$e] = $pileArray[$e]-$f +sub1380 +$pileArray[$g]=0 +for j in 0..10 do +$bArray[$g][index]=0 +$c=0 +for i in 1..$numberOfPiles do + if $bArray[i][index] != 0 then + $c=$c+1 + end + end +$pileArray[$g]=$pileArray[$g]+2*($c/2-($c/2)).to_i*2^j +end +if $winOption == 1 then + sub1380 +end +$c=0 +for i in 1..$numberOfPiles do +if $pileArray[i]>1 then + sub1380 +end +if $pileArray[i] != 0 then + $c=$c+1 +end +if $c/2 == ($c/2).to_i then + sub1380 +end +$pileArray[$g] == 1 -$pileArray[$g] + +def sub1380 + puts "PILE SIZE" + for i in 1..$numberOfPiles do + put i + put $pileArray[i] + end + if $winOption == 2 then # avoid take-last option + yourMove + end + sub1570 + if $z == 1 then + machineWins + end +end + +def yourMove + put "YOUR MOVE - PILE, NUMBER TO BE REMOVED" +# 1460 INPUT x,y +x = gets.strip.to_i +y = gets.strip.to_i + if x > $numberOfPiles then yourMove + if x < 1 then yourMove + if x != INT(x) then yourMove + if y > $pileArray[x] then yourMove + if y < 1 then + yourMove + end + if y != INT(y) then + yourMove + end + + $pileArray[x] = $pileArray[x]-y + sub1570 # gosub + if $z == 1 then + machineLoses + end +# 1560 GOTO 700 +end + +end +end +end +end +end + + From 420597dbcf4ee0b1f7859b719ca2a46c53497326 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 10 Jan 2022 19:21:15 +0000 Subject: [PATCH 703/749] First cut java battleships --- 09_Battle/java/Battle.java | 372 +++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 09_Battle/java/Battle.java diff --git a/09_Battle/java/Battle.java b/09_Battle/java/Battle.java new file mode 100644 index 00000000..aa53896c --- /dev/null +++ b/09_Battle/java/Battle.java @@ -0,0 +1,372 @@ +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Random; +import java.util.function.Predicate; +import java.text.NumberFormat; + +public class Battle { + private int seaSize; + private int[] sizes; + private int[] counts; + + private ArrayList ships; + private Sea sea; + + private int[] losses; + private int hits; + private int misses; + + private static String NAMES_BY_SIZE[] = { + "error", + "size1", + "destroyer", + "cruiser", + "aircraft carrier", + "size5" }; + + public static void main(String args[]) { + Battle game = new Battle(6, + new int[] { 2, 3, 4 }, + new int[] { 2, 2, 2 }); + game.play(); + } + + public Battle(int scale, int[] shipSizes, int[] shipCounts) { + seaSize = scale; + sizes = shipSizes; + counts = shipCounts; + + /* validate parameters */ + if (seaSize < 4) throw new RuntimeException("Sea Size " + seaSize + " invalid, must be at least 4"); + + for (int sz : sizes) { + if ((sz < 1) || (sz > seaSize)) + throw new RuntimeException("Ship has invalid size " + sz); + } + + if (counts.length != sizes.length) { + throw new RuntimeException("Ship counts must match"); + } + + sea = new Sea(seaSize); + ships = new ArrayList(); + losses = new int[counts.length]; + + int shipNumber = 1; + for (int type = 0; type < counts.length; ++type) { + for (int i = 0; i < counts[i]; ++i) { + ships.add(new Ship(shipNumber++, "Ship", sizes[type])); + } + } + + ArrayList largestFirst = new ArrayList<>(ships); + Collections.sort(largestFirst, Comparator.comparingInt((Ship ship) -> ship.size()).reversed()); + + for (Ship ship : largestFirst) { + ship.placeRandom(sea); + } + } + + public void play() { + System.out.println("The following code of the bad guys' fleet disposition\nhas been captured but not decoded:\n"); + System.out.println(sea.encodedDump()); + System.out.println("De-code it and use it if you can\nbut keep the de-coding method a secret.\n"); + + int lost = 0; + System.out.println("Start game"); + try { + BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); + NumberFormat parser = NumberFormat.getIntegerInstance(); + + while (lost < ships.size()) { + System.out.print("\nTarget x,y\n> "); + String inputLine = input.readLine(); + if (inputLine == null) { + System.out.println("Game quit\n"); + return; + } + String[] coords = inputLine.split(","); + if (coords.length != 2) { + System.out.println("Need two coordinates separated by ','"); + continue; + } + int[] xy = new int[2]; + boolean error = false; + try { + for (int c = 0 ; c < 2; ++c ) { + int val = Integer.parseInt(coords[c].strip()); + if ((val < 1) || (val > seaSize)) { + System.out.println("Coordinates must be from 1 to " + seaSize); + error = true; + } else { + xy[c] = val; + } + } + } + catch (NumberFormatException ne) { + System.out.println("Coordinates must be numbers"); + error = true; + } + if (error) continue; + + int row = seaSize - xy[1]; + int col = xy[0] - 1; + + if (sea.isEmpty(col, row)) { + ++misses; + System.out.println("Splash! Try again."); + } else { + Ship ship = ships.get(sea.get(col, row) - 1); + if (ship.isSunk()) { + ++misses; + System.out.println("There used to be a ship at that point, but you sunk it."); + System.out.println("Splash! Try again."); + } else if (ship.wasHit(col, row)) { + ++misses; + System.out.println("You already put a hole in ship number " + ship.id()); + System.out.println("Splash! Try again."); + } else { + ship.hit(col, row); + ++hits; + System.out.println("A direct hit on ship number " + ship.id()); + if (ship.isSunk()) { + ++lost; + System.out.println("And you sunk it. Hurrah for the good guys."); + System.out.print("So far, the bad guys have lost "); + ArrayList typeDescription = new ArrayList<>(); + for (int i = 0 ; i < sizes.length; ++i) { + if (sizes[i] == ship.size()) { + ++losses[i]; + } + StringBuilder sb = new StringBuilder(); + sb.append(losses[i]); + sb.append(" "); + sb.append(NAMES_BY_SIZE[sizes[i]]); + if (losses[i] != 1) + sb.append("s"); + typeDescription.add(sb.toString()); + } + System.out.println(String.join(", ", typeDescription)); + double ratioNum = ((double)misses)/hits; + String ratio = NumberFormat.getInstance().format(ratioNum); + System.out.println("Your current splash/hit ratio is " + ratio); + + if (lost == ships.size()) { + System.out.println("You have totally wiped out the bad guys' fleet"); + System.out.println("With a final splash/hit ratio of " + ratio); + + if (misses == 0) { + System.out.println("Congratulations - A direct hit every time."); + } + + System.out.println("\n****************************\n"); + } + } + } + } + } + } + catch (IOException e) { + } + } + + private static class Ship { + public static final int ORIENT_E=0; + public static final int ORIENT_SE=1; + public static final int ORIENT_S=2; + public static final int ORIENT_SW=3; + + private int id; + private int size; + private String type; + private boolean placed; + private boolean sunk; + private ArrayList hits; + + private int startX; + private int startY; + private int orientX; + private int orientY; + + public Ship(int i, String name, int sz) { + id = i; type = name; size = sz; + sunk = false; placed = false; + hits = new ArrayList<>(Collections.nCopies(size, false)); + } + + public int id() { return id; } + public int size() { return size; } + + public void hit(int x, int y) { + int offset; + if (orientX != 0) { + offset = (x - startX) / orientX; + } else { + offset = (y - startY) / orientY; + } + hits.set(offset, true); + + sunk = hits.stream().allMatch(Predicate.isEqual(true)); + } + + public boolean isSunk() { return sunk; } + + public boolean wasHit(int x, int y) { + int offset; + if (orientX != 0) { + offset = (x - startX) / orientX; + } else { + offset = (y - startY) / orientY; + } + return hits.get(offset); + }; + + public void placeRandom(Sea s) { + Random random = new Random(); + for (int tries = 0 ; tries < 1000 ; ++tries) { + int x = random.nextInt(s.size()); + int y = random.nextInt(s.size()); + int orient = random.nextInt(4); + + if (place(s, x, y, orient)) return; + } + + throw new RuntimeException("Could not place any more ships"); + } + + private boolean extendShip(Sea s, int fromX, int fromY, int toX, int toY) { + if (!s.isEmpty(toX, toY)) return false; // no space + if ((fromX == toX)||(fromY == toY)) return true; // horizontal or vertical + + // we can extend the ship without colliding, but we are going diagonally + // and it should not be possible for two ships to cross each other on + // opposite diagonals. + + // check the two tiles that would cross us here - if either is empty, we are OK + // if they both contain different ships, we are OK + // but if they both contain the same ship, we are crossing! + int corner1 = s.get(fromX, toY); + int corner2 = s.get(toX, fromY); + if ((corner1 == 0) || (corner1 != corner2)) return true; + return false; + } + + public boolean place(Sea s, int x, int y, int orient) { + if (placed) { + throw new RuntimeException("Program error - placed ship " + id + " twice"); + } + switch(orient) { + case ORIENT_E: + orientX = 1; orientY = 0; + break; + case ORIENT_SE: + orientX = 1; orientY = 1; + break; + case ORIENT_S: + orientX = 0; orientY = 1; + break; + case ORIENT_SW: + orientX = -1; orientY = 1; + break; + default: + throw new RuntimeException("Invalid orientation " + orient); + } + + if (!s.isEmpty(x, y)) return false; + startX = x; startY = y; + int tilesPlaced = 1; + int nextX = startX; + int nextY = startY; + while (tilesPlaced < size) { + if (extendShip(s, nextX, nextY, nextX + orientX, nextY + orientY)) { + tilesPlaced += 1; + nextX = nextX + orientX; + nextY = nextY + orientY; + } else { + int backX = startX - orientX; + int backY = startY - orientY; + + if (extendShip(s, startX, startY, backX, backY)) { + tilesPlaced +=1; + startX = backX; + startY = backY; + } else { + return false; + } + } + } + + for (int i = 0; i < size; ++i) { + int sx = startX + i * orientX; + int sy = startY + i * orientY; + s.set(sx, sy, id); + } + placed = true; + return true; + } + + } + + private static class Sea { + private int tiles[]; + private boolean hits[]; + + private int size; + public Sea(int make_size) { + size = make_size; + tiles = new int[size*size]; + } + + public int size() { return size; } + + public String encodedDump() { + StringBuilder out = new StringBuilder(); + for (int x = 0; x < size; ++x) { + for (int y = 0; y < size; ++y) + out.append(Integer.toString(get(x, y))); + out.append('\n'); + } + return out.toString(); + } + + /* return true if x,y is in the sea and empty + * return false if x,y is occupied or is out of range + */ + public boolean isEmpty(int x, int y) { + if ((x<0)||(x>=size)||(y<0)||(y>=size)) return false; + return (get(x,y) == 0); + } + + /* return the ship number, or zero if no ship */ + public int get(int x, int y) { + return tiles[index(x,y)]; + } + + public void set(int x, int y, int value) { + tiles[index(x, y)] = value; + } + + public int shipHit(int x, int y) { + if (hits[index(x,y)]) return get(x, y); + else return 0; + } + + public void recordHit(int x, int y) { + hits[index(x, y)] = true; + } + + private int index(int x, int y) { + if ((x < 0) || (x >= size)) + throw new ArrayIndexOutOfBoundsException("Program error: x cannot be " + x); + if ((y < 0) || (y >= size)) + throw new ArrayIndexOutOfBoundsException("Program error: y cannot be " + y); + + return y*size + x; + } + } +} From c074beaf42e0c0aeb91413c152a827ac48942417 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 10 Jan 2022 19:38:23 +0000 Subject: [PATCH 704/749] pull out input parsing --- 09_Battle/java/Battle.java | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/09_Battle/java/Battle.java b/09_Battle/java/Battle.java index aa53896c..b548292c 100644 --- a/09_Battle/java/Battle.java +++ b/09_Battle/java/Battle.java @@ -1,5 +1,3 @@ -import java.io.BufferedReader; -import java.io.InputStreamReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -79,43 +77,15 @@ public class Battle { int lost = 0; System.out.println("Start game"); + Input input = new Input(seaSize); try { - BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); - NumberFormat parser = NumberFormat.getIntegerInstance(); - while (lost < ships.size()) { - System.out.print("\nTarget x,y\n> "); - String inputLine = input.readLine(); - if (inputLine == null) { - System.out.println("Game quit\n"); + if (! input.readCoordinates()) { return; } - String[] coords = inputLine.split(","); - if (coords.length != 2) { - System.out.println("Need two coordinates separated by ','"); - continue; - } - int[] xy = new int[2]; - boolean error = false; - try { - for (int c = 0 ; c < 2; ++c ) { - int val = Integer.parseInt(coords[c].strip()); - if ((val < 1) || (val > seaSize)) { - System.out.println("Coordinates must be from 1 to " + seaSize); - error = true; - } else { - xy[c] = val; - } - } - } - catch (NumberFormatException ne) { - System.out.println("Coordinates must be numbers"); - error = true; - } - if (error) continue; - int row = seaSize - xy[1]; - int col = xy[0] - 1; + int row = seaSize - input.y(); + int col = input.x() - 1; if (sea.isEmpty(col, row)) { ++misses; From 8e88e25d6c3fbc9fd783aa39d834fb10105fc0ec Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 10 Jan 2022 19:46:37 +0000 Subject: [PATCH 705/749] Classes in own files --- 09_Battle/java/.gitignore | 1 + 09_Battle/java/Battle.java | 195 ------------------------------------- 09_Battle/java/Input.java | 58 +++++++++++ 09_Battle/java/Sea.java | 57 +++++++++++ 09_Battle/java/Ship.java | 142 +++++++++++++++++++++++++++ 5 files changed, 258 insertions(+), 195 deletions(-) create mode 100644 09_Battle/java/.gitignore create mode 100644 09_Battle/java/Input.java create mode 100644 09_Battle/java/Sea.java create mode 100644 09_Battle/java/Ship.java diff --git a/09_Battle/java/.gitignore b/09_Battle/java/.gitignore new file mode 100644 index 00000000..b25c15b8 --- /dev/null +++ b/09_Battle/java/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/09_Battle/java/Battle.java b/09_Battle/java/Battle.java index b548292c..627906d0 100644 --- a/09_Battle/java/Battle.java +++ b/09_Battle/java/Battle.java @@ -144,199 +144,4 @@ public class Battle { catch (IOException e) { } } - - private static class Ship { - public static final int ORIENT_E=0; - public static final int ORIENT_SE=1; - public static final int ORIENT_S=2; - public static final int ORIENT_SW=3; - - private int id; - private int size; - private String type; - private boolean placed; - private boolean sunk; - private ArrayList hits; - - private int startX; - private int startY; - private int orientX; - private int orientY; - - public Ship(int i, String name, int sz) { - id = i; type = name; size = sz; - sunk = false; placed = false; - hits = new ArrayList<>(Collections.nCopies(size, false)); - } - - public int id() { return id; } - public int size() { return size; } - - public void hit(int x, int y) { - int offset; - if (orientX != 0) { - offset = (x - startX) / orientX; - } else { - offset = (y - startY) / orientY; - } - hits.set(offset, true); - - sunk = hits.stream().allMatch(Predicate.isEqual(true)); - } - - public boolean isSunk() { return sunk; } - - public boolean wasHit(int x, int y) { - int offset; - if (orientX != 0) { - offset = (x - startX) / orientX; - } else { - offset = (y - startY) / orientY; - } - return hits.get(offset); - }; - - public void placeRandom(Sea s) { - Random random = new Random(); - for (int tries = 0 ; tries < 1000 ; ++tries) { - int x = random.nextInt(s.size()); - int y = random.nextInt(s.size()); - int orient = random.nextInt(4); - - if (place(s, x, y, orient)) return; - } - - throw new RuntimeException("Could not place any more ships"); - } - - private boolean extendShip(Sea s, int fromX, int fromY, int toX, int toY) { - if (!s.isEmpty(toX, toY)) return false; // no space - if ((fromX == toX)||(fromY == toY)) return true; // horizontal or vertical - - // we can extend the ship without colliding, but we are going diagonally - // and it should not be possible for two ships to cross each other on - // opposite diagonals. - - // check the two tiles that would cross us here - if either is empty, we are OK - // if they both contain different ships, we are OK - // but if they both contain the same ship, we are crossing! - int corner1 = s.get(fromX, toY); - int corner2 = s.get(toX, fromY); - if ((corner1 == 0) || (corner1 != corner2)) return true; - return false; - } - - public boolean place(Sea s, int x, int y, int orient) { - if (placed) { - throw new RuntimeException("Program error - placed ship " + id + " twice"); - } - switch(orient) { - case ORIENT_E: - orientX = 1; orientY = 0; - break; - case ORIENT_SE: - orientX = 1; orientY = 1; - break; - case ORIENT_S: - orientX = 0; orientY = 1; - break; - case ORIENT_SW: - orientX = -1; orientY = 1; - break; - default: - throw new RuntimeException("Invalid orientation " + orient); - } - - if (!s.isEmpty(x, y)) return false; - startX = x; startY = y; - int tilesPlaced = 1; - int nextX = startX; - int nextY = startY; - while (tilesPlaced < size) { - if (extendShip(s, nextX, nextY, nextX + orientX, nextY + orientY)) { - tilesPlaced += 1; - nextX = nextX + orientX; - nextY = nextY + orientY; - } else { - int backX = startX - orientX; - int backY = startY - orientY; - - if (extendShip(s, startX, startY, backX, backY)) { - tilesPlaced +=1; - startX = backX; - startY = backY; - } else { - return false; - } - } - } - - for (int i = 0; i < size; ++i) { - int sx = startX + i * orientX; - int sy = startY + i * orientY; - s.set(sx, sy, id); - } - placed = true; - return true; - } - - } - - private static class Sea { - private int tiles[]; - private boolean hits[]; - - private int size; - public Sea(int make_size) { - size = make_size; - tiles = new int[size*size]; - } - - public int size() { return size; } - - public String encodedDump() { - StringBuilder out = new StringBuilder(); - for (int x = 0; x < size; ++x) { - for (int y = 0; y < size; ++y) - out.append(Integer.toString(get(x, y))); - out.append('\n'); - } - return out.toString(); - } - - /* return true if x,y is in the sea and empty - * return false if x,y is occupied or is out of range - */ - public boolean isEmpty(int x, int y) { - if ((x<0)||(x>=size)||(y<0)||(y>=size)) return false; - return (get(x,y) == 0); - } - - /* return the ship number, or zero if no ship */ - public int get(int x, int y) { - return tiles[index(x,y)]; - } - - public void set(int x, int y, int value) { - tiles[index(x, y)] = value; - } - - public int shipHit(int x, int y) { - if (hits[index(x,y)]) return get(x, y); - else return 0; - } - - public void recordHit(int x, int y) { - hits[index(x, y)] = true; - } - - private int index(int x, int y) { - if ((x < 0) || (x >= size)) - throw new ArrayIndexOutOfBoundsException("Program error: x cannot be " + x); - if ((y < 0) || (y >= size)) - throw new ArrayIndexOutOfBoundsException("Program error: y cannot be " + y); - - return y*size + x; - } - } } diff --git a/09_Battle/java/Input.java b/09_Battle/java/Input.java new file mode 100644 index 00000000..8a782dba --- /dev/null +++ b/09_Battle/java/Input.java @@ -0,0 +1,58 @@ +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; +import java.text.NumberFormat; + +public class Input { + private BufferedReader reader; + private NumberFormat parser; + private int scale; + private boolean isQuit; + private int[] coords; + + public Input(int seaSize) { + scale = seaSize; + reader = new BufferedReader(new InputStreamReader(System.in)); + parser = NumberFormat.getIntegerInstance(); + } + + public boolean readCoordinates() throws IOException { + while (true) { + System.out.print("\nTarget x,y\n> "); + String inputLine = reader.readLine(); + if (inputLine == null) { + System.out.println("Game quit\n"); + isQuit = true; + return false; + } + + String[] fields = inputLine.split(","); + if (fields.length != 2) { + System.out.println("Need two coordinates separated by ','"); + continue; + } + + coords = new int[2]; + boolean error = false; + try { + for (int c = 0 ; c < 2; ++c ) { + int val = Integer.parseInt(fields[c].strip()); + if ((val < 1) || (val > scale)) { + System.out.println("Coordinates must be from 1 to " + scale); + error = true; + } else { + coords[c] = val; + } + } + } + catch (NumberFormatException ne) { + System.out.println("Coordinates must be numbers"); + error = true; + } + if (!error) return true; + } + } + + public int x() { return coords[0]; } + public int y() { return coords[1]; } +} diff --git a/09_Battle/java/Sea.java b/09_Battle/java/Sea.java new file mode 100644 index 00000000..d9987f34 --- /dev/null +++ b/09_Battle/java/Sea.java @@ -0,0 +1,57 @@ +class Sea { + private int tiles[]; + private boolean hits[]; + + private int size; + public Sea(int make_size) { + size = make_size; + tiles = new int[size*size]; + } + + public int size() { return size; } + + public String encodedDump() { + StringBuilder out = new StringBuilder(); + for (int x = 0; x < size; ++x) { + for (int y = 0; y < size; ++y) + out.append(Integer.toString(get(x, y))); + out.append('\n'); + } + return out.toString(); + } + + /* return true if x,y is in the sea and empty + * return false if x,y is occupied or is out of range + */ + public boolean isEmpty(int x, int y) { + if ((x<0)||(x>=size)||(y<0)||(y>=size)) return false; + return (get(x,y) == 0); + } + + /* return the ship number, or zero if no ship */ + public int get(int x, int y) { + return tiles[index(x,y)]; + } + + public void set(int x, int y, int value) { + tiles[index(x, y)] = value; + } + + public int shipHit(int x, int y) { + if (hits[index(x,y)]) return get(x, y); + else return 0; + } + + public void recordHit(int x, int y) { + hits[index(x, y)] = true; + } + + private int index(int x, int y) { + if ((x < 0) || (x >= size)) + throw new ArrayIndexOutOfBoundsException("Program error: x cannot be " + x); + if ((y < 0) || (y >= size)) + throw new ArrayIndexOutOfBoundsException("Program error: y cannot be " + y); + + return y*size + x; + } +} diff --git a/09_Battle/java/Ship.java b/09_Battle/java/Ship.java new file mode 100644 index 00000000..e3fb4f44 --- /dev/null +++ b/09_Battle/java/Ship.java @@ -0,0 +1,142 @@ +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Random; +import java.util.function.Predicate; + +class Ship { + public static final int ORIENT_E=0; + public static final int ORIENT_SE=1; + public static final int ORIENT_S=2; + public static final int ORIENT_SW=3; + + private int id; + private int size; + private String type; + private boolean placed; + private boolean sunk; + private ArrayList hits; + + private int startX; + private int startY; + private int orientX; + private int orientY; + + public Ship(int i, String name, int sz) { + id = i; type = name; size = sz; + sunk = false; placed = false; + hits = new ArrayList<>(Collections.nCopies(size, false)); + } + + public int id() { return id; } + public int size() { return size; } + + public void hit(int x, int y) { + int offset; + if (orientX != 0) { + offset = (x - startX) / orientX; + } else { + offset = (y - startY) / orientY; + } + hits.set(offset, true); + + sunk = hits.stream().allMatch(Predicate.isEqual(true)); + } + + public boolean isSunk() { return sunk; } + + public boolean wasHit(int x, int y) { + int offset; + if (orientX != 0) { + offset = (x - startX) / orientX; + } else { + offset = (y - startY) / orientY; + } + return hits.get(offset); + }; + + public void placeRandom(Sea s) { + Random random = new Random(); + for (int tries = 0 ; tries < 1000 ; ++tries) { + int x = random.nextInt(s.size()); + int y = random.nextInt(s.size()); + int orient = random.nextInt(4); + + if (place(s, x, y, orient)) return; + } + + throw new RuntimeException("Could not place any more ships"); + } + + private boolean extendShip(Sea s, int fromX, int fromY, int toX, int toY) { + if (!s.isEmpty(toX, toY)) return false; // no space + if ((fromX == toX)||(fromY == toY)) return true; // horizontal or vertical + + // we can extend the ship without colliding, but we are going diagonally + // and it should not be possible for two ships to cross each other on + // opposite diagonals. + + // check the two tiles that would cross us here - if either is empty, we are OK + // if they both contain different ships, we are OK + // but if they both contain the same ship, we are crossing! + int corner1 = s.get(fromX, toY); + int corner2 = s.get(toX, fromY); + if ((corner1 == 0) || (corner1 != corner2)) return true; + return false; + } + + public boolean place(Sea s, int x, int y, int orient) { + if (placed) { + throw new RuntimeException("Program error - placed ship " + id + " twice"); + } + switch(orient) { + case ORIENT_E: + orientX = 1; orientY = 0; + break; + case ORIENT_SE: + orientX = 1; orientY = 1; + break; + case ORIENT_S: + orientX = 0; orientY = 1; + break; + case ORIENT_SW: + orientX = -1; orientY = 1; + break; + default: + throw new RuntimeException("Invalid orientation " + orient); + } + + if (!s.isEmpty(x, y)) return false; + startX = x; startY = y; + int tilesPlaced = 1; + int nextX = startX; + int nextY = startY; + while (tilesPlaced < size) { + if (extendShip(s, nextX, nextY, nextX + orientX, nextY + orientY)) { + tilesPlaced += 1; + nextX = nextX + orientX; + nextY = nextY + orientY; + } else { + int backX = startX - orientX; + int backY = startY - orientY; + + if (extendShip(s, startX, startY, backX, backY)) { + tilesPlaced +=1; + startX = backX; + startY = backY; + } else { + return false; + } + } + } + + for (int i = 0; i < size; ++i) { + int sx = startX + i * orientX; + int sy = startY + i * orientY; + s.set(sx, sy, id); + } + placed = true; + return true; + } +} + From 49be31b8e2f1086ed72565715ed3b3ee407b366f Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 10 Jan 2022 20:15:15 +0000 Subject: [PATCH 706/749] Add some comments --- 09_Battle/java/Battle.java | 49 +++++++---- 09_Battle/java/Ship.java | 166 ++++++++++++++++++++++--------------- 2 files changed, 132 insertions(+), 83 deletions(-) diff --git a/09_Battle/java/Battle.java b/09_Battle/java/Battle.java index 627906d0..c0b27906 100644 --- a/09_Battle/java/Battle.java +++ b/09_Battle/java/Battle.java @@ -7,18 +7,26 @@ import java.util.Random; import java.util.function.Predicate; import java.text.NumberFormat; + +/* This class holds the game state and the game logic */ public class Battle { + + /* parameters of the game */ private int seaSize; private int[] sizes; private int[] counts; - + + /* The game setup - the ships and the sea */ private ArrayList ships; private Sea sea; - private int[] losses; - private int hits; - private int misses; + /* game state counts */ + private int[] losses; // how many of each type of ship have been sunk + private int hits; // how many hits the player has made + private int misses; // how many misses the player has made + // Names of ships of each size. The game as written has ships of size 3, 4 and 5 but + // can easily be modified. It makes no sense to have a ship of size zero though. private static String NAMES_BY_SIZE[] = { "error", "size1", @@ -27,10 +35,11 @@ public class Battle { "aircraft carrier", "size5" }; + // Entrypoint public static void main(String args[]) { - Battle game = new Battle(6, - new int[] { 2, 3, 4 }, - new int[] { 2, 2, 2 }); + Battle game = new Battle(6, // Sea is 6 x 6 tiles + new int[] { 2, 3, 4 }, // Ships are of sizes 2, 3, and 4 + new int[] { 2, 2, 2 }); // there are two ships of each size game.play(); } @@ -39,7 +48,7 @@ public class Battle { sizes = shipSizes; counts = shipCounts; - /* validate parameters */ + // validate parameters if (seaSize < 4) throw new RuntimeException("Sea Size " + seaSize + " invalid, must be at least 4"); for (int sz : sizes) { @@ -51,20 +60,25 @@ public class Battle { throw new RuntimeException("Ship counts must match"); } - sea = new Sea(seaSize); - ships = new ArrayList(); - losses = new int[counts.length]; + // Initialize game state + sea = new Sea(seaSize); // holds what ship if any occupies each tile + ships = new ArrayList(); // positions and states of all the ships + losses = new int[counts.length]; // how many ships of each type have been sunk + // Build up the list of all the ships int shipNumber = 1; for (int type = 0; type < counts.length; ++type) { for (int i = 0; i < counts[i]; ++i) { - ships.add(new Ship(shipNumber++, "Ship", sizes[type])); + ships.add(new Ship(shipNumber++, sizes[type])); } } + // When we put the ships in the sea, we put the biggest ones in first, or they might + // not fit ArrayList largestFirst = new ArrayList<>(ships); Collections.sort(largestFirst, Comparator.comparingInt((Ship ship) -> ship.size()).reversed()); + // place each ship into the sea for (Ship ship : largestFirst) { ship.placeRandom(sea); } @@ -79,11 +93,13 @@ public class Battle { System.out.println("Start game"); Input input = new Input(seaSize); try { - while (lost < ships.size()) { - if (! input.readCoordinates()) { + while (lost < ships.size()) { // the game continues while some ships remain unsunk + if (! input.readCoordinates()) { // ... unless there is no more input from the user return; } + // The computer thinks of the sea as a grid of rows, from top to bottom. + // However, the user will use X and Y coordinates, with Y going bottom to top int row = seaSize - input.y(); int col = input.x() - 1; @@ -104,6 +120,9 @@ public class Battle { ship.hit(col, row); ++hits; System.out.println("A direct hit on ship number " + ship.id()); + + // If a ship was hit, we need to know whether it was sunk. + // If so, tell the player and update our counts if (ship.isSunk()) { ++lost; System.out.println("And you sunk it. Hurrah for the good guys."); @@ -142,6 +161,8 @@ public class Battle { } } catch (IOException e) { + // This should not happen running from console, but java requires us to check for it + System.err.println("System error.\n" + e); } } } diff --git a/09_Battle/java/Ship.java b/09_Battle/java/Ship.java index e3fb4f44..23605e5c 100644 --- a/09_Battle/java/Ship.java +++ b/09_Battle/java/Ship.java @@ -4,34 +4,41 @@ import java.util.Comparator; import java.util.Random; import java.util.function.Predicate; +/** A single ship, with its position and where it has been hit */ class Ship { - public static final int ORIENT_E=0; - public static final int ORIENT_SE=1; - public static final int ORIENT_S=2; - public static final int ORIENT_SW=3; + // These are the four directions that ships can be in + public static final int ORIENT_E=0; // goes East from starting position + public static final int ORIENT_SE=1; // goes SouthEast from starting position + public static final int ORIENT_S=2; // goes South from starting position + public static final int ORIENT_SW=3; // goes SouthWest from starting position - private int id; - private int size; - private String type; - private boolean placed; - private boolean sunk; - private ArrayList hits; + private int id; // ship number + private int size; // how many tiles it occupies + private boolean placed; // whether this ship is in the sea yet + private boolean sunk; // whether this ship has been sunk + private ArrayList hits; // which tiles of the ship have been hit - private int startX; + private int startX; // starting position coordinates private int startY; - private int orientX; + private int orientX; // x and y deltas from each tile occupied to the next private int orientY; - public Ship(int i, String name, int sz) { - id = i; type = name; size = sz; + public Ship(int i, int sz) { + id = i; size = sz; sunk = false; placed = false; hits = new ArrayList<>(Collections.nCopies(size, false)); } + /** @returns the ship number */ public int id() { return id; } + /** @returns the ship size */ public int size() { return size; } + /* record the ship as having been hit at the given coordinates */ public void hit(int x, int y) { + // need to work out how many tiles from the ship's starting position the hit is at + // that can be worked out from the difference between the starting X coord and this one + // unless the ship runs N-S, in which case use the Y coord instead int offset; if (orientX != 0) { offset = (x - startX) / orientX; @@ -40,11 +47,13 @@ class Ship { } hits.set(offset, true); + // if every tile of the ship has been hit, the ship is sunk sunk = hits.stream().allMatch(Predicate.isEqual(true)); } public boolean isSunk() { return sunk; } + // whether the ship has already been hit at the given coordinates public boolean wasHit(int x, int y) { int offset; if (orientX != 0) { @@ -55,6 +64,9 @@ class Ship { return hits.get(offset); }; + // Place the ship in the sea. + // choose a random starting position, and a random direction + // if that doesn't fit, keep picking different positions and directions public void placeRandom(Sea s) { Random random = new Random(); for (int tries = 0 ; tries < 1000 ; ++tries) { @@ -68,6 +80,77 @@ class Ship { throw new RuntimeException("Could not place any more ships"); } + // Attempt to fit the ship into the sea, starting from a given position and + // in a given direction + // This is by far the most complicated part of the program. + // It will start at the position provided, and attempt to occupy tiles in the + // requested direction. If it does not fit, either because of the edge of the + // sea, or because of ships already in place, it will try to extend the ship + // in the opposite direction instead. If that is not possible, it fails. + public boolean place(Sea s, int x, int y, int orient) { + if (placed) { + throw new RuntimeException("Program error - placed ship " + id + " twice"); + } + switch(orient) { + case ORIENT_E: // east is increasing X coordinate + orientX = 1; orientY = 0; + break; + case ORIENT_SE: // southeast is increasing X and Y + orientX = 1; orientY = 1; + break; + case ORIENT_S: // south is increasing Y + orientX = 0; orientY = 1; + break; + case ORIENT_SW: // southwest is increasing Y but decreasing X + orientX = -1; orientY = 1; + break; + default: + throw new RuntimeException("Invalid orientation " + orient); + } + + if (!s.isEmpty(x, y)) return false; // starting position is occupied - placing fails + + startX = x; startY = y; + int tilesPlaced = 1; + int nextX = startX; + int nextY = startY; + while (tilesPlaced < size) { + if (extendShip(s, nextX, nextY, nextX + orientX, nextY + orientY)) { + // It is clear to extend the ship forwards + tilesPlaced += 1; + nextX = nextX + orientX; + nextY = nextY + orientY; + } else { + int backX = startX - orientX; + int backY = startY - orientY; + + if (extendShip(s, startX, startY, backX, backY)) { + // We can move the ship backwards, so it can be one tile longer + tilesPlaced +=1; + startX = backX; + startY = backY; + } else { + // Could not make it longer or move it backwards + return false; + } + } + } + + // Mark in the sea which tiles this ship occupies + for (int i = 0; i < size; ++i) { + int sx = startX + i * orientX; + int sy = startY + i * orientY; + s.set(sx, sy, id); + } + + placed = true; + return true; + } + + // Check whether a ship which already occupies the "from" coordinates, + // can also occupy the "to" coordinates. + // They must be within the sea area, empty, and not cause the ship to cross + // over another ship private boolean extendShip(Sea s, int fromX, int fromY, int toX, int toY) { if (!s.isEmpty(toX, toY)) return false; // no space if ((fromX == toX)||(fromY == toY)) return true; // horizontal or vertical @@ -84,59 +167,4 @@ class Ship { if ((corner1 == 0) || (corner1 != corner2)) return true; return false; } - - public boolean place(Sea s, int x, int y, int orient) { - if (placed) { - throw new RuntimeException("Program error - placed ship " + id + " twice"); - } - switch(orient) { - case ORIENT_E: - orientX = 1; orientY = 0; - break; - case ORIENT_SE: - orientX = 1; orientY = 1; - break; - case ORIENT_S: - orientX = 0; orientY = 1; - break; - case ORIENT_SW: - orientX = -1; orientY = 1; - break; - default: - throw new RuntimeException("Invalid orientation " + orient); - } - - if (!s.isEmpty(x, y)) return false; - startX = x; startY = y; - int tilesPlaced = 1; - int nextX = startX; - int nextY = startY; - while (tilesPlaced < size) { - if (extendShip(s, nextX, nextY, nextX + orientX, nextY + orientY)) { - tilesPlaced += 1; - nextX = nextX + orientX; - nextY = nextY + orientY; - } else { - int backX = startX - orientX; - int backY = startY - orientY; - - if (extendShip(s, startX, startY, backX, backY)) { - tilesPlaced +=1; - startX = backX; - startY = backY; - } else { - return false; - } - } - } - - for (int i = 0; i < size; ++i) { - int sx = startX + i * orientX; - int sy = startY + i * orientY; - s.set(sx, sy, id); - } - placed = true; - return true; - } } - From f7f10d52f35e89dc5db764ea571c4e3f57d830c0 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Mon, 10 Jan 2022 15:18:46 -0500 Subject: [PATCH 707/749] Formatted "Totals" output Slowly going through and making output true to the original BASIC code --- 75_Roulette/java/src/Roulette.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index c6e46152..84986db1 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -63,10 +63,9 @@ public class Roulette { betResults(bets,result); out.println(); - - out.println("TOTALS:"); - out.println("\tME: " + houseBalance); - out.println("\tYOU " + playerBalance); + + out.println("TOTALS:\tME\tYOU"); + out.println("\t\t" + houseBalance + "\t" + playerBalance); } while(playAgain()); if(playerBalance <= 0) { From 0614831f460cf286e698b177296e5862fdad39b9 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 10 Jan 2022 20:22:14 +0000 Subject: [PATCH 708/749] Add comments to the sea class --- 09_Battle/java/Sea.java | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/09_Battle/java/Sea.java b/09_Battle/java/Sea.java index d9987f34..f0c31fac 100644 --- a/09_Battle/java/Sea.java +++ b/09_Battle/java/Sea.java @@ -1,8 +1,13 @@ +// Track the content of the sea class Sea { + // the sea is a square grid of tiles. It is a one-dimensional array, and this + // class maps x and y coordinates to an array index + // Each tile is either empty (value of tiles at index is 0) + // or contains a ship (value of tiles at index is the ship number) private int tiles[]; - private boolean hits[]; private int size; + public Sea(int make_size) { size = make_size; tiles = new int[size*size]; @@ -10,6 +15,8 @@ class Sea { public int size() { return size; } + // This writes out a representation of the sea, but in a funny order + // The idea is to give the player the job of working it out public String encodedDump() { StringBuilder out = new StringBuilder(); for (int x = 0; x < size; ++x) { @@ -22,13 +29,17 @@ class Sea { /* return true if x,y is in the sea and empty * return false if x,y is occupied or is out of range + * Doing this in one method makes placing ships much easier */ public boolean isEmpty(int x, int y) { if ((x<0)||(x>=size)||(y<0)||(y>=size)) return false; return (get(x,y) == 0); } - /* return the ship number, or zero if no ship */ + /* return the ship number, or zero if no ship. + * Unlike isEmpty(x,y), these other methods require that the + * coordinates passed be valid + */ public int get(int x, int y) { return tiles[index(x,y)]; } @@ -37,15 +48,7 @@ class Sea { tiles[index(x, y)] = value; } - public int shipHit(int x, int y) { - if (hits[index(x,y)]) return get(x, y); - else return 0; - } - - public void recordHit(int x, int y) { - hits[index(x, y)] = true; - } - + // map the coordinates to the array index private int index(int x, int y) { if ((x < 0) || (x >= size)) throw new ArrayIndexOutOfBoundsException("Program error: x cannot be " + x); From ea5c2cf72d3164654894431acb741ec971ea8a3b Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 10 Jan 2022 20:26:50 +0000 Subject: [PATCH 709/749] Comment the input class --- 09_Battle/java/Input.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/09_Battle/java/Input.java b/09_Battle/java/Input.java index 8a782dba..ee87465f 100644 --- a/09_Battle/java/Input.java +++ b/09_Battle/java/Input.java @@ -3,12 +3,15 @@ import java.io.InputStreamReader; import java.io.IOException; import java.text.NumberFormat; +// This class handles reading input from the player +// Each input is an x and y coordinate +// e.g. 5,3 public class Input { private BufferedReader reader; private NumberFormat parser; - private int scale; - private boolean isQuit; - private int[] coords; + private int scale; // size of the sea, needed to validate input + private boolean isQuit; // whether the input has ended + private int[] coords; // the last coordinates read public Input(int seaSize) { scale = seaSize; @@ -18,22 +21,27 @@ public class Input { public boolean readCoordinates() throws IOException { while (true) { + // Write a prompt System.out.print("\nTarget x,y\n> "); String inputLine = reader.readLine(); if (inputLine == null) { - System.out.println("Game quit\n"); + // If the input stream is ended, there is no way to continue the game + System.out.println("\nGame quit\n"); isQuit = true; return false; } + // split the input into two fields String[] fields = inputLine.split(","); if (fields.length != 2) { + // has to be exactly two System.out.println("Need two coordinates separated by ','"); continue; } coords = new int[2]; boolean error = false; + // each field should contain an integer from 1 to the size of the sea try { for (int c = 0 ; c < 2; ++c ) { int val = Integer.parseInt(fields[c].strip()); @@ -46,6 +54,7 @@ public class Input { } } catch (NumberFormatException ne) { + // this happens if the field is not a valid number System.out.println("Coordinates must be numbers"); error = true; } From 00a8bf8983b0cc36a8b364908ce559d3f387e249 Mon Sep 17 00:00:00 2001 From: Josh Gribbon Date: Mon, 10 Jan 2022 15:42:08 -0500 Subject: [PATCH 710/749] Move file --- .../find-missing-implementations.js | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) rename find-missing-implementations.js => 00_Utilities/find-missing-implementations.js (79%) diff --git a/find-missing-implementations.js b/00_Utilities/find-missing-implementations.js similarity index 79% rename from find-missing-implementations.js rename to 00_Utilities/find-missing-implementations.js index 04cf3f84..1f998444 100644 --- a/find-missing-implementations.js +++ b/00_Utilities/find-missing-implementations.js @@ -15,7 +15,7 @@ const ROOT_PATH = "."; const languages = [ { name: "csharp", extension: "cs" }, { name: "java", extension: "java" }, - { name: "javascript", extension: "js" }, + { name: "javascript", extension: "html" }, { name: "pascal", extension: "pas" }, { name: "perl", extension: "pl" }, { name: "python", extension: "py" }, @@ -45,6 +45,7 @@ const getPuzzleFolders = () => { (async () => { let missingGames = {}; let missingLanguageCounts = {}; + languages.forEach((l) => (missingLanguageCounts[l.name] = 0)); const puzzles = getPuzzleFolders(); for (const puzzle of puzzles) { for (const { name: language, extension } of languages) { @@ -53,12 +54,8 @@ const getPuzzleFolders = () => { extension ); if (files.length === 0) { - if (!missingGames[puzzle]) { - missingGames[puzzle] = []; - } - if (!missingLanguageCounts[language]) { - missingLanguageCounts[language] = 0; - } + if (!missingGames[puzzle]) missingGames[puzzle] = []; + missingGames[puzzle].push(language); missingLanguageCounts[language]++; } @@ -70,15 +67,14 @@ const getPuzzleFolders = () => { } else { console.log(`Missing ${missingCount} implementations:`); - console.log(`\nMissing languages by game:`); - for (const [puzzle, languages] of Object.entries(missingGames)) { - console.log(`${puzzle}: ${languages.join(", ")}`); - } + Object.entries(missingGames).forEach( + ([p, ls]) => (missingGames[p] = ls.join(", ")) + ); + console.log(`\nMissing languages by game:`); + console.table(missingGames); console.log(`\nBy language:`); - for (const [language, count] of Object.entries(missingLanguageCounts)) { - console.log(`${language}: ${count} missing`); - } + console.table(missingLanguageCounts); } })(); From 2d2df367491a06003a9f5147cc1a80fc2e9ea1e5 Mon Sep 17 00:00:00 2001 From: Josh Gribbon Date: Mon, 10 Jan 2022 15:44:23 -0500 Subject: [PATCH 711/749] Fix relative path --- 00_Utilities/find-missing-implementations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/00_Utilities/find-missing-implementations.js b/00_Utilities/find-missing-implementations.js index 1f998444..bd92bd79 100644 --- a/00_Utilities/find-missing-implementations.js +++ b/00_Utilities/find-missing-implementations.js @@ -10,7 +10,7 @@ const fs = require("fs"); const glob = require("glob"); // relative path to the repository root -const ROOT_PATH = "."; +const ROOT_PATH = "../."; const languages = [ { name: "csharp", extension: "cs" }, From 01fb3bd5009102e5bff45395981d047eccbb8756 Mon Sep 17 00:00:00 2001 From: Josh Gribbon Date: Mon, 10 Jan 2022 15:46:51 -0500 Subject: [PATCH 712/749] Skip utilities folder --- 00_Utilities/find-missing-implementations.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/00_Utilities/find-missing-implementations.js b/00_Utilities/find-missing-implementations.js index bd92bd79..61d849fe 100644 --- a/00_Utilities/find-missing-implementations.js +++ b/00_Utilities/find-missing-implementations.js @@ -38,7 +38,10 @@ const getPuzzleFolders = () => { return fs .readdirSync(ROOT_PATH, { withFileTypes: true }) .filter((dirEntry) => dirEntry.isDirectory()) - .filter((dirEntry) => ![".git", "node_modules"].includes(dirEntry.name)) + .filter( + (dirEntry) => + ![".git", "node_modules", "00_Utilities"].includes(dirEntry.name) + ) .map((dirEntry) => dirEntry.name); }; From 5c9443c5222519ab976864b570171f4ba58208c6 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Tue, 11 Jan 2022 11:43:27 +1100 Subject: [PATCH 713/749] Copying Mistale forgot to add 'clean' to the targets for the initial build --- buildJvm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildJvm/README.md b/buildJvm/README.md index a5169abd..e2b9da0b 100644 --- a/buildJvm/README.md +++ b/buildJvm/README.md @@ -7,7 +7,7 @@ We should be using version 17 anyway, because anything less than 17 is deprecate Build all the games: ```shell cd buildJvm - ./gradlew -q assemble installDist distributeBin distributeLib + ./gradlew -q clean assemble installDist distributeBin distributeLib ``` Then, run a game From 7f14b42c73a481e8a3be14649a9c653f26b4949e Mon Sep 17 00:00:00 2001 From: Rob Miller Date: Tue, 11 Jan 2022 17:47:53 +0000 Subject: [PATCH 714/749] Depth Charge: use more idiomatic Ruby Refactor the Depth Charge game (#31) to use more Ruby idioms, without changing its structure, method names, etc. --- 31_Depth_Charge/ruby/depthcharge.rb | 139 ++++++++++++++-------------- 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/31_Depth_Charge/ruby/depthcharge.rb b/31_Depth_Charge/ruby/depthcharge.rb index ba2a5d83..67ab7cc8 100755 --- a/31_Depth_Charge/ruby/depthcharge.rb +++ b/31_Depth_Charge/ruby/depthcharge.rb @@ -1,59 +1,60 @@ #!/usr/bin/ruby class DepthCharge - def run_game - output_title() - while true - printf("----------\n") - print_instructions() - setup_game() - printf("\n") - game_loop() - break if ! get_input_another_game() + output_title + + loop do + puts "----------" + print_instructions + setup_game + puts + game_loop + break unless get_input_another_game end - printf("OK. HOPE YOU ENJOYED YOURSELF.\n") + puts "OK. HOPE YOU ENJOYED YOURSELF." end def output_title - printf("--- DEPTH CHARGE ---\n") - printf("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n") - printf("\n") + puts "--- DEPTH CHARGE ---" + puts "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" + puts end def get_input_y_or_n(message) - while true - print(message) + loop do + print message value = gets.chomp - if (value == 'Y' || value == 'y') + if value.downcase == "y" return true - elsif value == 'N' || value == 'n' + elsif value.downcase == "n" return false end - printf("PLEASE ENTER Y/y OR N/n...\n\n") + puts "PLEASE ENTER Y/y OR N/n..." + puts end end def get_input_positive_integer(message) - - while true - print(message) + loop do + print message value = gets.chomp - if (value == 'd') - debug_game() + + if value == "d" + debug_game next end - the_input = Integer(value) rescue nil + the_input = Integer(value) rescue 0 - if the_input == nil || the_input < 1 - printf("PLEASE ENTER A POSITIVE NUMBER\n\n") + if the_input < 1 + puts "PLEASE ENTER A POSITIVE NUMBER" + puts next - end return the_input @@ -61,42 +62,39 @@ class DepthCharge end def print_instructions - printf( <<~INSTRUCTIONS -YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER -AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR -MISSION IS TO DESTROY IT. + puts <<~INSTRUCTIONS + YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER + AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR + MISSION IS TO DESTROY IT. -SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A -TRIO OF NUMBERS -- THE FIRST TWO ARE THE -SURFACE COORDINATES (X, Y): - WEST < X < EAST - SOUTH < Y < NORTH + SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A + TRIO OF NUMBERS -- THE FIRST TWO ARE THE + SURFACE COORDINATES (X, Y): + WEST < X < EAST + SOUTH < Y < NORTH -THE THIRD IS THE DEPTH (Z): - SHALLOW < Z < DEEP + THE THIRD IS THE DEPTH (Z): + SHALLOW < Z < DEEP -GOOD LUCK ! + GOOD LUCK ! INSTRUCTIONS - ) end def debug_game - printf("@enemy_x: %d\n", @enemy_x) - printf("@enemy_y: %d\n", @enemy_y) - printf("@enemy_z: %d\n", @enemy_z) - printf("@num_tries: %d\n", @num_tries) - printf("@trial: %d\n", @trial) - printf("\n") + puts "@enemy_x: %d" % @enemy_x + puts "@enemy_y: %d" % @enemy_y + puts "@enemy_z: %d" % @enemy_z + puts "@num_tries: %d" % @num_tries + puts "@trial: %d" % @trial + puts end def setup_game @search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ") - @num_tries = Integer( - Math.log(@search_area_dimension)/Math.log(2) + 1 - ) - setup_enemy() + @num_tries = Integer(Math.log(@search_area_dimension) / Math.log(2) + 1) + setup_enemy end def setup_enemy @@ -113,32 +111,34 @@ GOOD LUCK ! @shot_y = get_input_positive_integer("Y: ") @shot_z = get_input_positive_integer("Z: ") - if ( - (@enemy_x - @shot_x).abs \ - + (@enemy_y - @shot_y).abs \ - + (@enemy_z - @shot_z).abs \ - == 0 - ) - you_win() + + distance = (@enemy_x - @shot_x).abs + + (@enemy_y - @shot_y).abs + + (@enemy_z - @shot_z).abs + + if distance == 0 + you_win return else - missed_shot() + missed_shot end end - printf("\n") - - you_lose() + puts + you_lose end def output_game_status - printf("YOU HAVE %d SHOTS REMAINING.\n", @num_tries - @trial + 1) - printf("TRIAL \#%d\n", @trial) + puts "YOU HAVE %d SHOTS REMAINING." % @num_tries - @trial + 1 + puts "TRIAL \#%d" % @trial end + def you_win - printf("\nB O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial ) + puts "\nB O O M ! ! YOU FOUND IT IN %d TRIES!" % @trial + puts end + def missed_shot missed_directions = [] @@ -160,14 +160,13 @@ GOOD LUCK ! missed_directions.push('TOO SHALLOW') end - printf("SONAR REPORTS SHOT WAS: \n") - printf("%s\n", "\t" + missed_directions.join("\n\t")) + puts "SONAR REPORTS SHOT WAS: " + puts "\t#{missed_directions.join("\n\t")}" end def you_lose - printf("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!\n") - printf("THE SUBMARINE WAS AT %d %d %d\n", @enemy_x, @enemy_y, @enemy_z) - + puts "YOU HAVE BEEN TORPEDOED! ABANDON SHIP!" + puts "THE SUBMARINE WAS AT %d %d %d" % [@enemy_x, @enemy_y, @enemy_z] end def get_input_another_game @@ -176,4 +175,4 @@ GOOD LUCK ! end game = DepthCharge.new -game.run_game() +game.run_game From 2885acd95195bcb167e0866d107cfd471de3d6e3 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 14:10:42 -0500 Subject: [PATCH 715/749] Match Formatting to Original Program --- 75_Roulette/java/src/Roulette.java | 174 +++++++++++++++-------------- 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 84986db1..3bb042a5 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -1,7 +1,7 @@ import java.io.InputStream; import java.io.PrintStream; -import java.lang.management.PlatformLoggingMXBean; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; public class Roulette { @@ -35,135 +35,143 @@ public class Roulette { out.println(" ROULETTE"); out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); out.println("WELCOME TO THE ROULETTE TABLE\n"); - out.println("DO YOU WANT INSTRUCTIONS"); + out.print("DO YOU WANT INSTRUCTIONS? "); if(scanner.nextLine().toLowerCase().charAt(0) != 'n') { printInstructions(); } + do { Bet[] bets = queryBets(); - out.println("SPINNING...\n\n\n"); + out.print("SPINNING...\n\n"); int result = random.nextInt(1,39); /* Equivalent to following line - if(RED_NUMBERS.contains(result)) { + if(result == 37) { + out.println("00"); + } else if(result == 38) { + out.println("0"); + } else if(RED_NUMBERS.contains(result)) { out.println(result + " RED"); } else { out.println(result + " BLACK"); } */ - switch(result) { - case 37 -> out.print("00"); - case 38 -> out.print("0"); - default -> out.println(result + (RED_NUMBERS.contains(result) ? " RED\n" : " BLACK\n")); - } + out.println(switch(result) { + case 37 -> "00"; + case 38 -> "0"; + default -> result + (RED_NUMBERS.contains(result) ? " RED" : " BLACK"); + }); betResults(bets,result); out.println(); - out.println("TOTALS:\tME\tYOU"); - out.println("\t\t" + houseBalance + "\t" + playerBalance); + out.println("TOTALS:\tME\t\tYOU"); + out.format("\t\t%5d\t%d\n",houseBalance,playerBalance); } while(playAgain()); if(playerBalance <= 0) { out.println("THANKS FOR YOUR MONEY\nI'LL USE IT TO BUY A SOLID GOLD ROULETTE WHEEL"); - } else if(houseBalance <= 0) { - out.println("TO WHOM SHALL I MAKE THE CHECK"); - String name = scanner.nextLine(); - out.println(); - for(int i = 0; i < 72; i++) { - out.print("-"); - } - out.println(); - for(int i = 0; i < 50; i++) { - out.print(" "); - } - out.println("CHECK NO. " + random.nextInt(0,1000)); - out.println(); - for(int i = 0; i < 40; i++) { - out.print(" "); - } - out.println(LocalDateTime.now()); - out.println("\n"); - out.println("PAY TO THE ORDER OF----- " + name + "------$" + (playerBalance - 1000)); - out.println("\n"); - for(int i = 0; i < 10; i++) { - out.print(" "); - } - out.println("THE MEMORY BANK OF NEW YORK"); - for(int i = 0; i < 40; i++) { - out.print(" "); - } - out.println("THE COMPUTER"); - for(int i = 0; i < 40; i++) { - out.print(" "); - } - out.println("----------X-----"); - for(int i = 0; i < 72; i++) { - out.print("-"); - } - out.println("\n"); - out.println("COME BACK SOON"); + } else { + printCheck(); } + out.println("COME BACK SOON!"); + } + + private void printCheck() { + out.print("TO WHOM SHALL I MAKE THE CHECK? "); + String name = scanner.nextLine(); + + out.println(); + for(int i = 0; i < 72; i++) { + out.print("-"); + } + out.println(); + + for(int i = 0; i < 50; i++) { + out.print(" "); + } + out.println("CHECK NO. " + random.nextInt(0,100)); + + for(int i = 0; i< 40; i++) { + out.print(" "); + } + out.println(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE)); + out.println(); + + out.println("PAY TO THE ORDER OF -----" + name + "----- $" + (playerBalance)); + out.println(); + + for(int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("THE MEMORY BANK OF NEW YORK"); + + for(int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("THE COMPUTER"); + + for(int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("----------X-----"); + + for(int i = 0; i < 72; i++) { + out.print("-"); + } + out.println(); } private boolean playAgain() { - if(playerBalance > 0) { - if(houseBalance <= 0) { - out.println("YOU BROKE THE HOUSE!"); - //using default values - playerBalance = 101000; - } + + if(playerBalance <= 0) { + out.println("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!"); + return false; + } else if(houseBalance <= 0) { + out.println("YOU BROKE THE HOUSE!"); + playerBalance = 10100; + houseBalance = 0; + return false; + } else { out.println("PLAY AGAIN?"); return scanner.nextLine().toLowerCase().charAt(0) == 'y'; - } else { - return false; } } private Bet[] queryBets() { int numBets = -1; while(numBets < 1) { - out.println("HOW MANY BETS"); + out.print("HOW MANY BETS? "); try { numBets = Integer.parseInt(scanner.nextLine()); - } catch(NumberFormatException exception) { - out.println("THAT IS NOT A NUMBER"); - } + } catch(NumberFormatException ignored) {} } Bet[] bets = new Bet[numBets]; for(int i = 0; i < numBets; i++) { - try { - out.println("BET NUMBER " + (i + 1) + ":"); - String[] values = scanner.nextLine().split(","); - int betNumber = Integer.parseInt(values[0]); - int betValue = Integer.parseInt(values[1]); + while(bets[i] == null) { + try { + out.print("NUMBER" + (i + 1) + "? "); + String[] values = scanner.nextLine().split(","); + int betNumber = Integer.parseInt(values[0]); + int betValue = Integer.parseInt(values[1]); - for(int j = 0; j < i; j++) { - if(bets[j].num == betNumber) { - out.println("YOU MADE THAT BET ONCE ALREADY,DUM-DUM"); - throw new Exception(); + for(int j = 0; j < i; j++) { + if(bets[j].num == betNumber) { + out.println("YOU MADE THAT BET ONCE ALREADY,DUM-DUM"); + betNumber = -1; //Since -1 is out of the range, this will throw it out at the end + } } - } - if(betNumber < 1 || betNumber > 50 || betValue < 5 || betValue > 500) { - out.println("INVALID VALUE, TRY AGAIN"); - i--; - continue; - } - - bets[i] = new Bet(betNumber,betValue); - - } catch(Exception exception) { - if(exception instanceof NumberFormatException) { - out.println("SYNTAX ERROR, TRY AGAIN"); - } - i--; + if(betNumber > 0 && betNumber <= 50 && betValue >= 5 && betValue <= 500) { + bets[i] = new Bet(betValue,betNumber); + } + } catch(Exception ignored) {} } } return bets; From f43e31fb83cdb7ca47e59ca3514da82bbf0ca25d Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 14:15:37 -0500 Subject: [PATCH 716/749] Re-Formatted Code --- 75_Roulette/java/src/Roulette.java | 263 +++++++++++++++-------------- 1 file changed, 132 insertions(+), 131 deletions(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 3bb042a5..5fed5c65 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -2,26 +2,22 @@ import java.io.InputStream; import java.io.PrintStream; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.util.Random; +import java.util.Scanner; +import java.util.Set; public class Roulette { - private PrintStream out; - private Scanner scanner; - - private int houseBalance, playerBalance; - - private Random random; - private static Set RED_NUMBERS; static { RED_NUMBERS = Set.of(1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36); } - public static void main(String[] args) { - new Roulette(System.out, System.in).play(); - } + private PrintStream out; + private Scanner scanner; + private int houseBalance, playerBalance; + private Random random; public Roulette(PrintStream out, InputStream in) { this.out = out; @@ -31,22 +27,25 @@ public class Roulette { random = new Random(); } + public static void main(String[] args) { + new Roulette(System.out, System.in).play(); + } + public void play() { out.println(" ROULETTE"); out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); out.println("WELCOME TO THE ROULETTE TABLE\n"); out.print("DO YOU WANT INSTRUCTIONS? "); - if(scanner.nextLine().toLowerCase().charAt(0) != 'n') { + if (scanner.nextLine().toLowerCase().charAt(0) != 'n') { printInstructions(); } - do { Bet[] bets = queryBets(); out.print("SPINNING...\n\n"); - int result = random.nextInt(1,39); + int result = random.nextInt(1, 39); /* Equivalent to following line @@ -60,20 +59,19 @@ public class Roulette { out.println(result + " BLACK"); } */ - out.println(switch(result) { + out.println(switch (result) { case 37 -> "00"; case 38 -> "0"; - default -> result + (RED_NUMBERS.contains(result) ? " RED" : " BLACK"); + default -> result + (RED_NUMBERS.contains(result) ? " RED" : " BLACK"); }); - betResults(bets,result); + betResults(bets, result); out.println(); - - out.println("TOTALS:\tME\t\tYOU"); - out.format("\t\t%5d\t%d\n",houseBalance,playerBalance); - } while(playAgain()); - if(playerBalance <= 0) { + out.println("TOTALS:\tME\t\tYOU"); + out.format("\t\t%5d\t%d\n", houseBalance, playerBalance); + } while (playAgain()); + if (playerBalance <= 0) { out.println("THANKS FOR YOUR MONEY\nI'LL USE IT TO BUY A SOLID GOLD ROULETTE WHEEL"); } else { printCheck(); @@ -81,110 +79,101 @@ public class Roulette { out.println("COME BACK SOON!"); } - private void printCheck() { - out.print("TO WHOM SHALL I MAKE THE CHECK? "); - String name = scanner.nextLine(); - + public void printInstructions() { out.println(); - for(int i = 0; i < 72; i++) { - out.print("-"); - } + out.println("THIS IS THE BETTING LAYOUT"); + out.println(" (*=RED)"); out.println(); - - for(int i = 0; i < 50; i++) { - out.print(" "); - } - out.println("CHECK NO. " + random.nextInt(0,100)); - - for(int i = 0; i< 40; i++) { - out.print(" "); - } - out.println(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE)); + out.println(" 1* 2 3*"); + out.println(" 4 5* 6 "); + out.println(" 7* 8 9*"); + out.println("10 11 12*"); + out.println("---------------"); + out.println("13 14* 15 "); + out.println("16* 17 18*"); + out.println("19* 20 21*"); + out.println("22 23* 24 "); + out.println("---------------"); + out.println("25* 26 27*"); + out.println("28 29 30*"); + out.println("31 32* 33 "); + out.println("34* 35 36*"); + out.println("---------------"); + out.println(" 00 0 "); out.println(); - - out.println("PAY TO THE ORDER OF -----" + name + "----- $" + (playerBalance)); + out.println("TYPES OF BETS"); out.println(); - - for(int i = 0; i < 40; i++) { - out.print(" "); - } - out.println("THE MEMORY BANK OF NEW YORK"); - - for(int i = 0; i < 40; i++) { - out.print(" "); - } - out.println("THE COMPUTER"); - - for(int i = 0; i < 40; i++) { - out.print(" "); - } - out.println("----------X-----"); - - for(int i = 0; i < 72; i++) { - out.print("-"); - } + out.println("THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET"); + out.println("ON THAT NUMBER."); + out.println("THESE PAY OFF 35:1"); out.println(); - } - - private boolean playAgain() { - - if(playerBalance <= 0) { - out.println("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!"); - return false; - } else if(houseBalance <= 0) { - out.println("YOU BROKE THE HOUSE!"); - playerBalance = 10100; - houseBalance = 0; - return false; - } else { - out.println("PLAY AGAIN?"); - return scanner.nextLine().toLowerCase().charAt(0) == 'y'; - } + out.println("THE 2:1 BETS ARE:"); + out.println(" 37) 1-12 40) FIRST COLUMN"); + out.println(" 38) 13-24 41) SECOND COLUMN"); + out.println(" 39) 25-36 42) THIRD COLUMN"); + out.println(); + out.println("THE EVEN MONEY BETS ARE:"); + out.println(" 43) 1-18 46) ODD"); + out.println(" 44) 19-36 47) RED"); + out.println(" 45) EVEN 48) BLACK"); + out.println(); + out.println(" 49)0 AND 50)00 PAY OFF 35:1"); + out.println(" NOTE: 0 AND 00 DO NOT COUNT UNDER ANY"); + out.println(" BETS EXCEPT THEIR OWN."); + out.println(); + out.println("WHEN I ASK FOR EACH BET, TYPE THE NUMBER"); + out.println("AND THE AMOUNT, SEPARATED BY A COMMA."); + out.println("FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500"); + out.println("WHEN I ASK FOR A BET."); + out.println(); + out.println("THE MINIMUM BET IS $5, THE MAXIMUM IS $500."); } private Bet[] queryBets() { int numBets = -1; - while(numBets < 1) { + while (numBets < 1) { out.print("HOW MANY BETS? "); try { numBets = Integer.parseInt(scanner.nextLine()); - } catch(NumberFormatException ignored) {} + } catch (NumberFormatException ignored) { + } } Bet[] bets = new Bet[numBets]; - for(int i = 0; i < numBets; i++) { - while(bets[i] == null) { + for (int i = 0; i < numBets; i++) { + while (bets[i] == null) { try { out.print("NUMBER" + (i + 1) + "? "); String[] values = scanner.nextLine().split(","); int betNumber = Integer.parseInt(values[0]); int betValue = Integer.parseInt(values[1]); - for(int j = 0; j < i; j++) { - if(bets[j].num == betNumber) { + for (int j = 0; j < i; j++) { + if (bets[j].num == betNumber) { out.println("YOU MADE THAT BET ONCE ALREADY,DUM-DUM"); betNumber = -1; //Since -1 is out of the range, this will throw it out at the end } } - if(betNumber > 0 && betNumber <= 50 && betValue >= 5 && betValue <= 500) { - bets[i] = new Bet(betValue,betNumber); + if (betNumber > 0 && betNumber <= 50 && betValue >= 5 && betValue <= 500) { + bets[i] = new Bet(betValue, betNumber); } - } catch(Exception ignored) {} + } catch (Exception ignored) { + } } } return bets; } private void betResults(Bet[] bets, int num) { - for(int i = 0; i < bets.length; i++) { + for (int i = 0; i < bets.length; i++) { Bet bet = bets[i]; /* Using a switch statement of ternary operators that check if a certain condition is met based on the bet value Returns the coefficient that the bet amount should be multiplied by to get the resulting value */ - int coefficient = switch(bet.num) { + int coefficient = switch (bet.num) { case 37 -> (num <= 12) ? 2 : -1; case 38 -> (num > 12 && num <= 24) ? 2 : -1; case 39 -> (num > 24 && num < 37) ? 2 : -1; @@ -204,7 +193,7 @@ public class Roulette { int betResult = bet.amount * coefficient; - if(betResult < 0) { + if (betResult < 0) { out.println("YOU LOSE " + -betResult + " DOLLARS ON BET " + (i + 1)); } else { out.println("YOU WIN " + betResult + " DOLLARS ON BET " + (i + 1)); @@ -215,57 +204,69 @@ public class Roulette { } } - public void printInstructions() { + private boolean playAgain() { + + if (playerBalance <= 0) { + out.println("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!"); + return false; + } else if (houseBalance <= 0) { + out.println("YOU BROKE THE HOUSE!"); + playerBalance = 10100; + houseBalance = 0; + return false; + } else { + out.println("PLAY AGAIN?"); + return scanner.nextLine().toLowerCase().charAt(0) == 'y'; + } + } + + private void printCheck() { + out.print("TO WHOM SHALL I MAKE THE CHECK? "); + String name = scanner.nextLine(); + out.println(); - out.println( "THIS IS THE BETTING LAYOUT"); - out.println( " (*=RED)"); + for (int i = 0; i < 72; i++) { + out.print("-"); + } out.println(); - out.println( " 1* 2 3*"); - out.println( " 4 5* 6 "); - out.println( " 7* 8 9*"); - out.println( "10 11 12*"); - out.println( "---------------"); - out.println( "13 14* 15 "); - out.println( "16* 17 18*"); - out.println( "19* 20 21*"); - out.println( "22 23* 24 "); - out.println( "---------------"); - out.println( "25* 26 27*"); - out.println( "28 29 30*"); - out.println( "31 32* 33 "); - out.println( "34* 35 36*"); - out.println( "---------------"); - out.println( " 00 0 "); + + for (int i = 0; i < 50; i++) { + out.print(" "); + } + out.println("CHECK NO. " + random.nextInt(0, 100)); + + for (int i = 0; i < 40; i++) { + out.print(" "); + } + out.println(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE)); out.println(); - out.println( "TYPES OF BETS"); + + out.println("PAY TO THE ORDER OF -----" + name + "----- $" + (playerBalance)); out.println(); - out.println( "THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET"); - out.println( "ON THAT NUMBER."); - out.println( "THESE PAY OFF 35:1"); + + for (int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("THE MEMORY BANK OF NEW YORK"); + + for (int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("THE COMPUTER"); + + for (int i = 0; i < 40; i++) { + out.print(" "); + } + out.println("----------X-----"); + + for (int i = 0; i < 72; i++) { + out.print("-"); + } out.println(); - out.println( "THE 2:1 BETS ARE:"); - out.println( " 37) 1-12 40) FIRST COLUMN"); - out.println( " 38) 13-24 41) SECOND COLUMN"); - out.println( " 39) 25-36 42) THIRD COLUMN"); - out.println(); - out.println( "THE EVEN MONEY BETS ARE:"); - out.println( " 43) 1-18 46) ODD"); - out.println( " 44) 19-36 47) RED"); - out.println( " 45) EVEN 48) BLACK"); - out.println(); - out.println( " 49)0 AND 50)00 PAY OFF 35:1"); - out.println( " NOTE: 0 AND 00 DO NOT COUNT UNDER ANY"); - out.println( " BETS EXCEPT THEIR OWN."); - out.println(); - out.println( "WHEN I ASK FOR EACH BET, TYPE THE NUMBER"); - out.println( "AND THE AMOUNT, SEPARATED BY A COMMA."); - out.println( "FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500"); - out.println( "WHEN I ASK FOR A BET."); - out.println(); - out.println( "THE MINIMUM BET IS $5, THE MAXIMUM IS $500."); } public class Bet { + final int num, amount; public Bet(int num, int amount) { From 74a3cb72aca72719cd9fc1c16fb9cf784ad8bb64 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 15:09:03 -0500 Subject: [PATCH 717/749] Started Roulette in Python --- 75_Roulette/python/roulette.py | 130 +++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/75_Roulette/python/roulette.py b/75_Roulette/python/roulette.py index 8b137891..db1f5639 100644 --- a/75_Roulette/python/roulette.py +++ b/75_Roulette/python/roulette.py @@ -1 +1,131 @@ + +global RED_NUMBERS +RED_NUMBERS = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36] + +def print_instructions(): + print(""" +THIS IS THE BETTING LAYOUT + (*=RED) + + 1* 2 3* + 4 5* 6 + 7* 8 9* +10 11 12* +--------------- +13 14* 15 +16* 17 18* +19* 20 21* +22 23* 24 +--------------- +25* 26 27* +28 29 30* +31 32* 33 +34* 35 36* +--------------- + 00 0 + +TYPES OF BETS + +THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET +ON THAT NUMBER. +THESE PAY OFF 35:1 + +THE 2:1 BETS ARE: +37) 1-12 40) FIRST COLUMN +38) 13-24 41) SECOND COLUMN +39) 25-36 42) THIRD COLUMN + +THE EVEN MONEY BETS ARE: +43) 1-18 46) ODD +44) 19-36 47) RED +45) EVEN 48) BLACK + + 49)0 AND 50)00 PAY OFF 35:1 +NOTE: 0 AND 00 DO NOT COUNT UNDER ANY + BETS EXCEPT THEIR OWN. + +WHEN I ASK FOR EACH BET, TYPE THE NUMBER +AND THE AMOUNT, SEPARATED BY A COMMA. +FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500 +WHEN I ASK FOR A BET. + +THE MINIMUM BET IS $5, THE MAXIMUM IS $500. + + """) + +def query_bets(): + betCount = -1 + while betCount <= 0: + try: + betCount = int(input("HOW MANY BETS? ")) + except: + ... + + bet_IDs = [-1] * betCount + bet_Values = [0] * betCount + + for i in range(betCount): + while(bet_IDs[i] == -1): + try: + inString = input("NUMBER " + str(i + 1) + "? ").split(',') + id,val = int(inString[0]),int(inString[1]) + + # check other bet_IDs + for j in range(i): + if id != -1 and bet_IDs[j] == id: + id = -1 + print("YOU ALREADY MADE THAT BET ONCE, DUM-DUM") + break + + if id > 0 and id <= 50 and val >= 5 and val <= 500: + bet_IDs[i] = id + bet_Values[i] = val + except: + ... + return bet_IDs,bet_Values + +def bet_results(bet_IDs,bet_Values,result): + def get_modifier(id,num): + if id == 37 and num <= 12: + return 2 + elif id == 38 and num > 12 and num <= 24: + return 2 + elif id == 39 and num > 24 and num < 37: + return 2 + elif id == 40 and num < 37 and num % 3 == 1: + return 2 + elif id == 41 and num < 37 and num % 3 == 2: + return 2 + elif id == 42 and num < 37 and num % 3 == 0: + return 2 + elif id == 43 and num <= 18: + return 1 + elif id == 44 and num > 18 and num <= 36: + return 1 + elif id == 45 and num % 2 == 0: + return 1 + elif id == 46 and num % 2 == 1: + return 1 + elif id == 47 and num in RED_NUMBERS: + return 1 + elif id == 48 and num not in RED_NUMBERS: + return 1 + elif id < 37 and id == num: + return 35 + else: + return -1 + + for i in range(len(bet_IDs)): + winnings = bet_Values[i] * get_modifier(bet_IDs[i],result) + + if winnings >= 0: + print("YOU WIN " + str(winnings) + " DOLLARS ON BET " + str(i + 1)) + else: + print("YOU LOSE " + str(winnings * -1) + " DOLLARS ON BET " + str(i + 1)) + +def main(): + ... + +a,b = query_bets() +bet_results(a,b,5) From 614e4740a97008751bf4d11e6a051e07f3cf65a7 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 15:26:53 -0500 Subject: [PATCH 718/749] Added check --- 75_Roulette/python/roulette.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/75_Roulette/python/roulette.py b/75_Roulette/python/roulette.py index db1f5639..c4cb6ccd 100644 --- a/75_Roulette/python/roulette.py +++ b/75_Roulette/python/roulette.py @@ -1,4 +1,5 @@ - +from datetime import date +import random global RED_NUMBERS RED_NUMBERS = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36] @@ -124,8 +125,23 @@ def bet_results(bet_IDs,bet_Values,result): else: print("YOU LOSE " + str(winnings * -1) + " DOLLARS ON BET " + str(i + 1)) +def print_check(amount): + name = input("TO WHOM SHALL I MAKE THE CHECK? ") + + print("-" * 72) + print() + print(" " * 40 + "CHECK NO. " + str(random.randint(0,100))) + print(" " * 40 + str(date.today())) + print() + print("PAY TO THE ORDER OF -----" + name + "----- $" + str(amount)) + print() + print(" " * 40 + "THE MEMORY BANK OF NEW YORK") + print(" " * 40 + "THE COMPUTER") + print(" " * 40 + "----------X-----") + print("-" * 72) + def main(): ... -a,b = query_bets() -bet_results(a,b,5) +# a,b = query_bets() +print_check(5) From 5dff7851296a53d73d4d1e2e5f56604de7cc0d6a Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 15:56:31 -0500 Subject: [PATCH 719/749] Fixed numerical typo --- 75_Roulette/java/src/Roulette.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 5fed5c65..77ea2703 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -211,7 +211,7 @@ public class Roulette { return false; } else if (houseBalance <= 0) { out.println("YOU BROKE THE HOUSE!"); - playerBalance = 10100; + playerBalance = 101000; houseBalance = 0; return false; } else { From ea16d14a9ddb7d72287b9da7c91b6cf9b9563645 Mon Sep 17 00:00:00 2001 From: LittleTealeaf Date: Tue, 11 Jan 2022 16:01:38 -0500 Subject: [PATCH 720/749] Implemented more Roulette.py --- 75_Roulette/python/roulette.py | 66 ++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/75_Roulette/python/roulette.py b/75_Roulette/python/roulette.py index c4cb6ccd..cca991dd 100644 --- a/75_Roulette/python/roulette.py +++ b/75_Roulette/python/roulette.py @@ -87,6 +87,7 @@ def query_bets(): return bet_IDs,bet_Values def bet_results(bet_IDs,bet_Values,result): + total_winnings = 0 def get_modifier(id,num): if id == 37 and num <= 12: return 2 @@ -119,12 +120,15 @@ def bet_results(bet_IDs,bet_Values,result): for i in range(len(bet_IDs)): winnings = bet_Values[i] * get_modifier(bet_IDs[i],result) + total_winnings += winnings if winnings >= 0: print("YOU WIN " + str(winnings) + " DOLLARS ON BET " + str(i + 1)) else: print("YOU LOSE " + str(winnings * -1) + " DOLLARS ON BET " + str(i + 1)) + return winnings + def print_check(amount): name = input("TO WHOM SHALL I MAKE THE CHECK? ") @@ -141,7 +145,65 @@ def print_check(amount): print("-" * 72) def main(): - ... + player_balance = 1000 + host_balance = 100000 + + print(" " * 32 + "ROULETTE") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print() + print() + print() + + if stringtobool(input("DO YOU WANT INSTRUCTIONS? ")): + print_instructions() + + while True: + bet_IDs,bet_Values = query_bets() + + print("SPINNING") + print() + print() + + val = random.randint(0,38) + if val == 38: + print("0") + elif val == 37: + print("00") + elif val in RED_NUMBERS: + print(str(val) + " RED") + else: + print(str(val) + " BLACK") + + print() + total_winnings = bet_results(bet_IDs,bet_Values,val) + player_balance += total_winnings + host_balance -= total_winnings + + print() + print("TOTALS:\tME\t\tYOU") + print("\t\t" + str(host_balance) + "\t" + str(player_balance)) + + if player_balance <= 0: + print("OOPS! YOU JUST SPENT YOUR LAST DOLLAR!") + break + elif host_balance <= 0: + print("YOU BROKE THE HOUSE!") + player_balance = 101000 + break + if not stringtobool(input("PLAY AGAIN? ")): + break + + + if player_balance <= 0: + print("THANKS FOR YOUR MONEY") + print("I'LL USE IT TO BUY A SOLID GOLD ROULETTE WHEEL") + else: + print_check(player_balance) + print("COME BACK SOON!") + + +def stringtobool(string): + return string.lower() in ("yes","y","true","t","yes") # a,b = query_bets() -print_check(5) +main() From 1317d9ee16b15b4f1221955e15e3b7c71d8044f9 Mon Sep 17 00:00:00 2001 From: LittleTealeaf Date: Tue, 11 Jan 2022 16:04:44 -0500 Subject: [PATCH 721/749] Player balance is now deducted on bets --- 75_Roulette/java/src/Roulette.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 5fed5c65..56bcb1e5 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -157,7 +157,8 @@ public class Roulette { } if (betNumber > 0 && betNumber <= 50 && betValue >= 5 && betValue <= 500) { - bets[i] = new Bet(betValue, betNumber); + bets[i] = new Bet(betNumber,betValue); + playerBalance -= betValue; } } catch (Exception ignored) { } From 5c3a7e67fa2ad872eeeff3d094b31602785dec6d Mon Sep 17 00:00:00 2001 From: LittleTealeaf Date: Tue, 11 Jan 2022 16:05:16 -0500 Subject: [PATCH 722/749] Reverting previous commit --- 75_Roulette/java/src/Roulette.java | 1 - 1 file changed, 1 deletion(-) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/src/Roulette.java index 56bcb1e5..30c25091 100644 --- a/75_Roulette/java/src/Roulette.java +++ b/75_Roulette/java/src/Roulette.java @@ -158,7 +158,6 @@ public class Roulette { if (betNumber > 0 && betNumber <= 50 && betValue >= 5 && betValue <= 500) { bets[i] = new Bet(betNumber,betValue); - playerBalance -= betValue; } } catch (Exception ignored) { } From 11fb8f778fab60218f33071068c3cc1141051d7b Mon Sep 17 00:00:00 2001 From: LittleTealeaf Date: Tue, 11 Jan 2022 16:11:10 -0500 Subject: [PATCH 723/749] Added comments --- 75_Roulette/python/roulette.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/75_Roulette/python/roulette.py b/75_Roulette/python/roulette.py index cca991dd..c839adc7 100644 --- a/75_Roulette/python/roulette.py +++ b/75_Roulette/python/roulette.py @@ -56,6 +56,7 @@ THE MINIMUM BET IS $5, THE MAXIMUM IS $500. """) def query_bets(): + """Queries the user to input their bets""" betCount = -1 while betCount <= 0: try: @@ -87,6 +88,7 @@ def query_bets(): return bet_IDs,bet_Values def bet_results(bet_IDs,bet_Values,result): + """Computes the results, prints them, and returns the total net winnings""" total_winnings = 0 def get_modifier(id,num): if id == 37 and num <= 12: @@ -130,6 +132,7 @@ def bet_results(bet_IDs,bet_Values,result): return winnings def print_check(amount): + """Prints a check of a given amount""" name = input("TO WHOM SHALL I MAKE THE CHECK? ") print("-" * 72) @@ -203,7 +206,8 @@ def main(): def stringtobool(string): + """Converts a string to a bool""" return string.lower() in ("yes","y","true","t","yes") -# a,b = query_bets() -main() +if __name__ == '__main__': + main() From 5c632b2d7eada3dab2f28e8ef4f2b603809c3fbf Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 11 Jan 2022 21:14:23 +0000 Subject: [PATCH 724/749] 75_Roulette in java --- 75_Roulette/java/Bet.java | 65 +++++++++ 75_Roulette/java/Roulette.java | 234 +++++++++++++++++++++++++++++++++ 75_Roulette/java/Wheel.java | 69 ++++++++++ 3 files changed, 368 insertions(+) create mode 100644 75_Roulette/java/Bet.java create mode 100644 75_Roulette/java/Roulette.java create mode 100644 75_Roulette/java/Wheel.java diff --git a/75_Roulette/java/Bet.java b/75_Roulette/java/Bet.java new file mode 100644 index 00000000..6d9ea48a --- /dev/null +++ b/75_Roulette/java/Bet.java @@ -0,0 +1,65 @@ +/* A bet has a target (the code entered, which is 1-36, or special values for + * the various groups, zero and double-zero), and an amount in dollars + */ + +public class Bet { + public int target; + public int amount; + + /* bet on a target, of an amount */ + public Bet(int on, int of) { + target = on; amount = of; + } + + /* check if this is a valid bet - on a real target and of a valid amount */ + public boolean isValid() { + return ((target > 0) && (target <= 50) && + (amount >= 5) && (amount <= 500)); + } + + /* utility to return either the odds amount in the case of a win, or zero for a loss */ + private int m(boolean isWon, int odds) { + return isWon? odds: 0; + } + + /* look at the wheel to see if this bet won. + * returns 0 if it didn't, or the odds if it did + */ + public int winsOn(Wheel w) { + if (target < 37) { + // A number bet 1-36 wins at odds of 35 if it is the exact number + return m(w.isNumber() && (w.number() == target), 35); + } else + switch (target) { + case 37: // 1-12, odds of 2 + return m(w.isNumber() && (w.number() <= 12), 2); + case 38: // 13-24, odds of 2 + return m(w.isNumber() && (w.number() > 12) && (w.number() <= 24), 2); + case 39: // 25-36, odds of 2 + return m(w.isNumber() && (w.number() > 24), 2); + case 40: // Column 1, odds of 2 + return m(w.isNumber() && ((w.number() % 3) == 1), 2); + case 41: // Column 2, odds of 2 + return m(w.isNumber() && ((w.number() % 3) == 2), 2); + case 42: // Column 3, odds of 2 + return m(w.isNumber() && ((w.number() % 3) == 0), 2); + case 43: // 1-18, odds of 1 + return m(w.isNumber() && (w.number() <= 18), 1); + case 44: // 19-36, odds of 1 + return m(w.isNumber() && (w.number() > 18), 1); + case 45: // even, odds of 1 + return m(w.isNumber() && ((w.number() %2) == 0), 1); + case 46: // odd, odds of 1 + return m(w.isNumber() && ((w.number() %2) == 1), 1); + case 47: // red, odds of 1 + return m(w.isNumber() && (w.color() == Wheel.BLACK), 1); + case 48: // black, odds of 1 + return m(w.isNumber() && (w.color() == Wheel.RED), 1); + case 49: // single zero, odds of 35 + return m(w.value().equals("0"), 35); + case 50: // double zero, odds of 35 + return m(w.value().equals("00"), 35); + } + throw new RuntimeException("Program Error - invalid bet"); + } +} diff --git a/75_Roulette/java/Roulette.java b/75_Roulette/java/Roulette.java new file mode 100644 index 00000000..77ae3463 --- /dev/null +++ b/75_Roulette/java/Roulette.java @@ -0,0 +1,234 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Random; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; + +public class Roulette { + public static void main(String args[]) throws Exception { + Roulette r = new Roulette(); + r.play(); + } + + private BufferedReader reader; + private PrintStream writer; + + private int house; // how much money does the house have + private int player; // how much money does the player have + private Wheel wheel = new Wheel(); + + public Roulette() { + reader = new BufferedReader(new InputStreamReader(System.in)); + writer = System.out; + house = 100000; + player = 1000; + } + + // for a test / cheat mode -- set the random number generator to a known value + private void setSeed(long l) { + wheel.setSeed(l); + } + + public void play() { + try { + intro(); + writer.println("WELCOME TO THE ROULETTE TABLE\n" + + "DO YOU WANT INSTRUCTIONS"); + String instr = reader.readLine(); + if (!instr.toUpperCase().startsWith("N")) + instructions(); + + while (betAndSpin()) { // returns true if the game is to continue + } + + if (player <= 0) { + // player ran out of money + writer.println("THANKS FOR YOUR MONEY.\nI'LL USE IT TO BUY A SOLID GOLD ROULETTE WHEEL"); + } else { + // player has money -- print them a check + writer.println("TO WHOM SHALL I MAKE THE CHECK"); + + String payee = reader.readLine(); + + writer.println("-".repeat(72)); + tab(50); writer.println("CHECK NO. " + (new Random().nextInt(100) + 1)); + writer.println(); + tab(40); writer.println(LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG))); + writer.println("\n\nPAY TO THE ORDER OF-----" + payee + "-----$ " + player); + writer.print("\n\n"); + tab(10); writer.println("THE MEMORY BANK OF NEW YORK\n"); + tab(40); writer.println("THE COMPUTER"); + tab(40); writer.println("----------X-----\n"); + writer.println("-".repeat(72)); + writer.println("COME BACK SOON!\n"); + } + } + catch (IOException e) { + // this should not happen + System.err.println("System error:\n" + e); + } + } + + /* Write the starting introduction */ + private void intro() throws IOException { + tab(32); writer.println("ROULETTE"); + tab(15); writer.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n"); + } + + /* Display the game instructions */ + private void instructions() { + String[] instLines = new String[] { + "THIS IS THE BETTING LAYOUT", + " (*=RED)", + "" , + " 1* 2 3*", + " 4 5* 6 ", + " 7* 8 9*", + "10 11 12*", + "---------------", + "13 14* 15 ", + "16* 17 18*", + "19* 20 21*", + "22 23* 24 ", + "---------------", + "25* 26 27*", + "28 29 30*", + "31 32* 33 ", + "34* 35 36*", + "---------------", + " 00 0 ", + "" , + "TYPES OF BETS", + "" , + "THE NUMBERS 1 TO 36 SIGNIFY A STRAIGHT BET", + "ON THAT NUMBER.", + "THESE PAY OFF 35:1", + "" , + "THE 2:1 BETS ARE:", + " 37) 1-12 40) FIRST COLUMN", + " 38) 13-24 41) SECOND COLUMN", + " 39) 25-36 42) THIRD COLUMN", + "" , + "THE EVEN MONEY BETS ARE:", + " 43) 1-18 46) ODD", + " 44) 19-36 47) RED", + " 45) EVEN 48) BLACK", + "", + " 49)0 AND 50)00 PAY OFF 35:1", + " NOTE: 0 AND 00 DO NOT COUNT UNDER ANY", + " BETS EXCEPT THEIR OWN.", + "", + "WHEN I ASK FOR EACH BET, TYPE THE NUMBER", + "AND THE AMOUNT, SEPARATED BY A COMMA.", + "FOR EXAMPLE: TO BET $500 ON BLACK, TYPE 48,500", + "WHEN I ASK FOR A BET.", + "", + "THE MINIMUM BET IS $5, THE MAXIMUM IS $500.", + "" }; + writer.println(String.join("\n", instLines)); + } + + /* Take a set of bets from the player, then spin the wheel and work out the winnings * + * This returns true if the game is to continue afterwards + */ + private boolean betAndSpin() throws IOException { + int betCount = 0; + + while (betCount == 0) { // keep asking how many bets until we get a good answer + try { + writer.println("HOW MANY BETS"); + String howMany = reader.readLine(); + betCount = Integer.parseInt(howMany.strip()); + + if ((betCount < 1) || (betCount > 100)) betCount = 0; // bad -- set zero and ask again + } + catch (NumberFormatException e) { + // this happens if the input is not a number + writer.println("INPUT ERROR"); + } + } + + HashSet betsMade = new HashSet<>(); // Bet targets already made, so we can spot repeats + ArrayList bets = new ArrayList<>(); // All the bets for this round + + while (bets.size() < betCount) { + Bet bet = new Bet(0, 0); // an invalid bet to hold the place + while (!bet.isValid()) { // keep asking until it is valid + try { + writer.println("NUMBER " + (bets.size() + 1)); + String fields[] = reader.readLine().split(","); + if (fields.length == 2) { + bet = new Bet(Integer.parseInt(fields[0].strip()), + Integer.parseInt(fields[1].strip())); + } + } + catch (NumberFormatException e) { + writer.println("INPUT ERROR"); + } + } + + // Check if there is already a bet on the same target + if (betsMade.contains(bet.target)) { + writer.println("YOU MADE THAT BET ONCE ALREADY,DUM-DUM"); + } else { + betsMade.add(bet.target); // note this target has now been bet on + bets.add(bet); + } + } + + writer.println("SPINNING\n\n"); + + wheel.spin(); // this deliberately takes some random amount of time + + writer.println(wheel.value()); + + // go through the bets, and evaluate each one + int betNumber = 1; + for (Bet b : bets) { + int multiplier = b.winsOn(wheel); + if (multiplier == 0) { + // lost the amount of the bet + writer.println("YOU LOSE " + b.amount + " DOLLARS ON BET " + betNumber); + house += b.amount; + player -= b.amount; + } else { + // won the amount of the bet, multiplied by the odds + int winnings = b.amount * multiplier; + writer.println("YOU WIN " + winnings + " DOLLARS ON BET " + betNumber); + house -= winnings; + player += winnings; + } + ++betNumber; + } + + writer.println("\nTOTALS:\tME\tYOU\n\t" + house + "\t" + player); + + if (player <= 0) { + writer.println("OOPS! YOU JUST SPENT YOUR LAST DOLLAR"); + return false; // do not repeat since the player has no more money + } + if (house <= 0) { + writer.println("YOU BROKE THE HOUSE!"); + player = 101000; // can't win more than the house started with + return false; // do not repeat since the house has no more money + } + + // player still has money, and the house still has money, so ask the player + // if they want to continue + writer.println("AGAIN"); + String doContinue = reader.readLine(); + + // repeat if the answer was not "n" or "no" + return (!doContinue.toUpperCase().startsWith("N")); + } + + // utility to print n spaces for formatting + private void tab(int n) { + writer.print(" ".repeat(n)); + } +} diff --git a/75_Roulette/java/Wheel.java b/75_Roulette/java/Wheel.java new file mode 100644 index 00000000..497c8b53 --- /dev/null +++ b/75_Roulette/java/Wheel.java @@ -0,0 +1,69 @@ +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; + +// The roulette wheel +public class Wheel { + // List the numbers which are black + private HashSet black = new HashSet<>(Arrays.asList(new Integer[] { 1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36 })); + + private Random random = new Random(); + private int pocket = 38; + + public static final int ZERO=0; + public static final int BLACK=1; + public static final int RED=2; + + // Set up a wheel. You call "spin", and then can check the result. + public Wheel() { + } + + // Cheat / test mode + void setSeed(long l) { + random.setSeed(l); + } + + // Spin the wheel onto a new random value. + public void spin() { + // keep spinning for a while + do { + try { + // 1 second delay. Where it stops, nobody knows + Thread.sleep(1000); + } + catch (InterruptedException e) {} + + pocket = random.nextInt(38) + 1; + } while (random.nextInt(4) > 0); // keep spinning until it stops + } + + // The string representation of the number; 1-36, 0, or 00 + public String value() { + if (pocket == 37) return "0"; + else if (pocket == 38) return "00"; + else return String.valueOf(pocket); + } + + // True if either 0 or 00 is hit + public boolean zero() { + return (pocket > 36); + } + + // True if anything other than 0 or 00 is hit + public boolean isNumber() { + return (pocket < 37); + } + + // The number rolled + public int number() { + if (zero()) return 0; + else return pocket; + } + + // Either ZERO, BLACK, or RED + public int color() { + if (zero()) return ZERO; + else if (black.contains(pocket)) return BLACK; + else return RED; + } +} From 3d46e147f553868eca2b6c854e4eeb106e77d250 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 11 Jan 2022 21:40:31 +0000 Subject: [PATCH 725/749] readme --- 75_Roulette/java/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/75_Roulette/java/README.md b/75_Roulette/java/README.md index 51edd8d4..2f9c97ca 100644 --- a/75_Roulette/java/README.md +++ b/75_Roulette/java/README.md @@ -1,3 +1,6 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Oracle Java](https://openjdk.java.net/) + +Conversion by Andrew McGuinness (andrew@arobeia.co.uk) + From 09b0e972cdf6b2cab7547396685569a0fc4364d4 Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Tue, 11 Jan 2022 17:00:28 -0500 Subject: [PATCH 726/749] Port 75_Roulette to Perl. The directory includes a Perl script to test the port (roulette-test.t) and a Perl script to generate the test based on output from the BASIC implementation (make-roulette-test.pl). --- 75_Roulette/perl/README.md | 12 + 75_Roulette/perl/make-roulette-test.pl | 263 ++++ 75_Roulette/perl/roulette-test.t | 1967 ++++++++++++++++++++++++ 75_Roulette/perl/roulette.pl | 319 ++++ 4 files changed, 2561 insertions(+) create mode 100755 75_Roulette/perl/make-roulette-test.pl create mode 100644 75_Roulette/perl/roulette-test.t create mode 100755 75_Roulette/perl/roulette.pl diff --git a/75_Roulette/perl/README.md b/75_Roulette/perl/README.md index e69c8b81..e7dcb811 100644 --- a/75_Roulette/perl/README.md +++ b/75_Roulette/perl/README.md @@ -1,3 +1,15 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Perl](https://www.perl.org/) + +This conversion consists of three files in `75_Roulette/perl/`: + +- `roulette.pl` is the port of the BASIC to Perl; +- `roulette-test.t` is a Perl test for correctness of display and payout; +- `make-roulette-test.pl` generates roulette-test.t from roulette.bas. + +The ported version of the game numbers the slots from 0 rather than 1, and uses a dispatch table to figure out the payout. + +The Perl test loads `roulette.pl` and verifies the Perl slot display and payout logic against the BASIC for all combinations of slots and bets. If any tests fail that fact will be noted at the end of the output. + +The test code is generated by reading the BASIC, retaining only the slot display and payout logic (based on line numbers), and wrapping this in code that generates all combinations of bet and spin result. The result is run, and the result is captured and parsed to produce `roulette-test.t`. `make-roulette-test.pl` has some command-line options that may be of interest. `--help` will display the documentation. diff --git a/75_Roulette/perl/make-roulette-test.pl b/75_Roulette/perl/make-roulette-test.pl new file mode 100755 index 00000000..100fd8d7 --- /dev/null +++ b/75_Roulette/perl/make-roulette-test.pl @@ -0,0 +1,263 @@ +#!/usr/bin/env perl + +use 5.014; # For s///r + +use strict; +use warnings; + +use File::Temp; +use Getopt::Long 2.33 qw{ :config auto_version }; +use IPC::Cmd qw{ can_run }; # Core as of Perl 5.9.5. +use Pod::Usage; + +our $VERSION = '0.000_01'; + +my %opt = ( + program => find_basic(), + output => make_default_output(), +); + +GetOptions( \%opt, + qw{ output=s program=s }, + help => sub { pod2usage( { -verbose => 2 } ) }, +) or pod2usage( { -verbose => 0 } ); + +die "No default BASIC found; you must specify --program\n" + unless defined $opt{program}; + +my $game_dir = ( File::Spec->splitdir( $0 ) )[0]; +my $basic_file = File::Spec->catfile( $game_dir, 'roulette.bas' ); +open my $basic_handle, '<', $basic_file + or die "Unable to open $basic_file: $!\n"; + +my $munged = File::Temp->new(); + +print { $munged } <<'EOD'; +1000 Y=50 +1010 DIM B(100),C(100),T(100) +1090 FOR S=1 TO 38 +1095 PRINT "SPIN ";S +1100 FOR C=1 TO Y +1110 B(C)=1 +1120 T(C)=C +1130 NEXT C +EOD + +transcribe( $basic_file, $basic_handle, $munged, 1860, 2810 ); +transcribe( $basic_file, $basic_handle, $munged, 2950 ); + +say { $munged } '4000 NEXT S'; + +$munged->flush(); + +if ( $opt{output} ne '-' ) { + my $dir = ( File::Spec->splitpath( $0 ) )[1]; + my $fn = File::Spec->rel2abs( $opt{output}, $dir ); + $fn = File::Spec->abs2rel( $fn ); + open my $fh, '>', $fn + or die "Unable to open $fn: $!\n"; + warn "Writing $fn\n"; + select $fh; +} + +print <<'EOD'; +package main; + +use 5.010; + +use strict; +use warnings; + +use File::Spec; +use Test::More 0.88; # Because of done_testing(); + +EOD + +print <<"EOD"; +# NOTE: This file is generated by $0. +# Any edits made to it will be lost the next time it is regenerated. +# Caveat coder. + +EOD + +print <<'EOD'; +my $dir = ( File::Spec->splitpath( $0 ) )[1]; +my $script = File::Spec->catfile( $dir, 'roulette.pl' ); +{ + # Modern Perls do not have . in @INC, but we need it there to load a + # relative path. + local @INC = ( File::Spec->curdir(), @INC ); + require $script; # Load game as module +} + +EOD + +my $spin; +my $name; +foreach ( `$opt{program} @{[ $munged->filename() ]}` ) { + s/\N{U+1D}/ /smxg; # Artifact of the BASIC I'm using. + s/ \s+ \z //smx; + s/ \A \s+ //smx; + if ( $_ eq '' ) { + # Ignore empty lines. + } elsif ( m/ \A SPIN \s* ( [0-9]+ ) /smx ) { + $spin = $1 - 1; # BASIC is 1-based, but Perl is 0-based + } elsif ( m/ \A YOU \s+ WIN \s* ( [0-9]+ ) \s* + DOLLARS \s+ ON \s+ BET \s* ( [0-9]+ ) /smx ) { + say "is payout( $spin, $2 ), $1, 'Spin $spin ($name), bet $2 pays $1';"; + } elsif ( m/ \A YOU \s+ LOSE \s* ( [0-9]+ ) \s* + DOLLARS \s+ ON \s+ BET \s* ( [0-9]+ ) /smx ) { + say "is payout( $spin, $2 ), -$1, 'Spin $spin ($name), bet $2 pays -$1';"; + } elsif ( m/ \A \s* ( [0-9]+ ) (?: \s* ( [[:alpha:]]+ ) )? \z /smx ) { + $name = $2 ? sprintf( '%d %s', $1, ucfirst lc $2 ) : $1; + say "is format_spin( $spin ), '$name', 'Spin $spin is $name';"; + } else { + die "Unexpected input $_"; + } +} + +print <<'EOD'; + +done_testing; + +1; + +# ex: set textwidth=72 : +EOD + +sub find_basic { + # yabasic seems not to work + foreach my $prog ( qw{ basic cbmbasic } ) { + return $prog if can_run( $prog ) + } + return undef; +} + +sub make_default_output { + ( my $rslt = $0 ) =~ s/ [.] pl \z /.t/smx; + $rslt =~ s/ .* \b make- //smx; + return $rslt; +} + +sub transcribe { + my ( $in_file, $in_handle, $out_handle, $first_line, $last_line ) = @_; + $last_line //= $first_line; + + while ( <$in_handle> ) { + m/ \A \s* ( [0-9]+ )+ \s /smx + or next; + $1 < $first_line + and next; + say { $out_handle } sprintf '%04d REM BEGIN VERBATIM FROM %s', + $first_line - 10, $in_file; + print { $out_handle } $_; + last; + } + while ( <$in_handle> ) { + m/ \A \s* ( [0-9]+ )+ \s /smx + and $1 > $last_line + and last; + print { $out_handle } $_; + } + say { $out_handle } sprintf '%04d REM END VERBATIM FROM %s', + $last_line + 10, $in_file; + + return; +} + +__END__ + +=head1 TITLE + +make-roulette-test.pl - Generate the tests for 75_Roulette/perl/roulette.pl + +=head1 SYNOPSIS + + perl 75_Roulette/perl/make-roulette-test.pl + perl 75_Roulette/perl/make-roulette-test.pl --program mybasic + perl 75_Roulette/perl/make-roulette-test.pl --help + perl 75_Roulette/perl/make-roulette-test.pl --version + +=head1 OPTIONS + +<<< replace boiler plate >>> + +=head2 --help + +This option displays the documentation for this script. The script then +exits. + +=head2 --output + + --output fubar.t + +This option specifies the output file. This needs to be in the same +directory as F, and defaults to that directory. A single +dash (C<'-'>) is special-cased to send the output to standard out. + +The default is C<--output=test-roulette.t>. + +=head2 --program + + --program my_basic + +This option specifies the name of your BASIC interpreter. This must be +the name of an executable file in your PATH (aliases do not work). + +The default is the first-found in the list C. + +=head2 --version + +This option displays the version of this script. The script then exits. + +=head1 DETAILS + +This Perl script generates F, which tests +F. The latter is expected to be written as a modulino. + +This script assumes that: + +=over + +=item * it is in the same directory as F; + +=item * F is in the first-level subdirectory under the current directory; + +=back + +The generated test assumes that it is in the same directory as +F. + +This script works by abstracting the internals of F and +wrapping them in a loop that generates all possible spins, and places +all possible bets on each spin. The generated BASIC is written to a +temporary file, and executed by a BASIC interpreter. The output is +parsed and used to generate the output. + +Obviously there is some ad-hocery going on, and this script has only +been tested under C, which was what I had on hand. + +B the abstraction process is driven by BASIC line numbers. Any +change of these puts the ad-hocery at risk. + +=head1 AUTHOR + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set textwidth=72 : diff --git a/75_Roulette/perl/roulette-test.t b/75_Roulette/perl/roulette-test.t new file mode 100644 index 00000000..6fe43fa7 --- /dev/null +++ b/75_Roulette/perl/roulette-test.t @@ -0,0 +1,1967 @@ +package main; + +use 5.010; + +use strict; +use warnings; + +use File::Spec; +use Test::More 0.88; # Because of done_testing(); + +# NOTE: This file is generated by 75_Roulette/perl/make-roulette-test.pl. +# Any edits made to it will be lost the next time it is regenerated. +# Caveat coder. + +my $dir = ( File::Spec->splitpath( $0 ) )[1]; +my $script = File::Spec->catfile( $dir, 'roulette.pl' ); +{ + # Modern Perls do not have . in @INC, but we need it there to load a + # relative path. + local @INC = ( File::Spec->curdir(), @INC ); + require $script; # Load game as module +} + +is format_spin( 0 ), '1 Red', 'Spin 0 is 1 Red'; +is payout( 0, 1 ), 35, 'Spin 0 (1 Red), bet 1 pays 35'; +is payout( 0, 2 ), -1, 'Spin 0 (1 Red), bet 2 pays -1'; +is payout( 0, 3 ), -1, 'Spin 0 (1 Red), bet 3 pays -1'; +is payout( 0, 4 ), -1, 'Spin 0 (1 Red), bet 4 pays -1'; +is payout( 0, 5 ), -1, 'Spin 0 (1 Red), bet 5 pays -1'; +is payout( 0, 6 ), -1, 'Spin 0 (1 Red), bet 6 pays -1'; +is payout( 0, 7 ), -1, 'Spin 0 (1 Red), bet 7 pays -1'; +is payout( 0, 8 ), -1, 'Spin 0 (1 Red), bet 8 pays -1'; +is payout( 0, 9 ), -1, 'Spin 0 (1 Red), bet 9 pays -1'; +is payout( 0, 10 ), -1, 'Spin 0 (1 Red), bet 10 pays -1'; +is payout( 0, 11 ), -1, 'Spin 0 (1 Red), bet 11 pays -1'; +is payout( 0, 12 ), -1, 'Spin 0 (1 Red), bet 12 pays -1'; +is payout( 0, 13 ), -1, 'Spin 0 (1 Red), bet 13 pays -1'; +is payout( 0, 14 ), -1, 'Spin 0 (1 Red), bet 14 pays -1'; +is payout( 0, 15 ), -1, 'Spin 0 (1 Red), bet 15 pays -1'; +is payout( 0, 16 ), -1, 'Spin 0 (1 Red), bet 16 pays -1'; +is payout( 0, 17 ), -1, 'Spin 0 (1 Red), bet 17 pays -1'; +is payout( 0, 18 ), -1, 'Spin 0 (1 Red), bet 18 pays -1'; +is payout( 0, 19 ), -1, 'Spin 0 (1 Red), bet 19 pays -1'; +is payout( 0, 20 ), -1, 'Spin 0 (1 Red), bet 20 pays -1'; +is payout( 0, 21 ), -1, 'Spin 0 (1 Red), bet 21 pays -1'; +is payout( 0, 22 ), -1, 'Spin 0 (1 Red), bet 22 pays -1'; +is payout( 0, 23 ), -1, 'Spin 0 (1 Red), bet 23 pays -1'; +is payout( 0, 24 ), -1, 'Spin 0 (1 Red), bet 24 pays -1'; +is payout( 0, 25 ), -1, 'Spin 0 (1 Red), bet 25 pays -1'; +is payout( 0, 26 ), -1, 'Spin 0 (1 Red), bet 26 pays -1'; +is payout( 0, 27 ), -1, 'Spin 0 (1 Red), bet 27 pays -1'; +is payout( 0, 28 ), -1, 'Spin 0 (1 Red), bet 28 pays -1'; +is payout( 0, 29 ), -1, 'Spin 0 (1 Red), bet 29 pays -1'; +is payout( 0, 30 ), -1, 'Spin 0 (1 Red), bet 30 pays -1'; +is payout( 0, 31 ), -1, 'Spin 0 (1 Red), bet 31 pays -1'; +is payout( 0, 32 ), -1, 'Spin 0 (1 Red), bet 32 pays -1'; +is payout( 0, 33 ), -1, 'Spin 0 (1 Red), bet 33 pays -1'; +is payout( 0, 34 ), -1, 'Spin 0 (1 Red), bet 34 pays -1'; +is payout( 0, 35 ), -1, 'Spin 0 (1 Red), bet 35 pays -1'; +is payout( 0, 36 ), -1, 'Spin 0 (1 Red), bet 36 pays -1'; +is payout( 0, 37 ), 2, 'Spin 0 (1 Red), bet 37 pays 2'; +is payout( 0, 38 ), -1, 'Spin 0 (1 Red), bet 38 pays -1'; +is payout( 0, 39 ), -1, 'Spin 0 (1 Red), bet 39 pays -1'; +is payout( 0, 40 ), 2, 'Spin 0 (1 Red), bet 40 pays 2'; +is payout( 0, 41 ), -1, 'Spin 0 (1 Red), bet 41 pays -1'; +is payout( 0, 42 ), -1, 'Spin 0 (1 Red), bet 42 pays -1'; +is payout( 0, 43 ), 1, 'Spin 0 (1 Red), bet 43 pays 1'; +is payout( 0, 44 ), -1, 'Spin 0 (1 Red), bet 44 pays -1'; +is payout( 0, 45 ), -1, 'Spin 0 (1 Red), bet 45 pays -1'; +is payout( 0, 46 ), 1, 'Spin 0 (1 Red), bet 46 pays 1'; +is payout( 0, 47 ), 1, 'Spin 0 (1 Red), bet 47 pays 1'; +is payout( 0, 48 ), -1, 'Spin 0 (1 Red), bet 48 pays -1'; +is payout( 0, 49 ), -1, 'Spin 0 (1 Red), bet 49 pays -1'; +is payout( 0, 50 ), -1, 'Spin 0 (1 Red), bet 50 pays -1'; +is format_spin( 1 ), '2 Black', 'Spin 1 is 2 Black'; +is payout( 1, 1 ), -1, 'Spin 1 (2 Black), bet 1 pays -1'; +is payout( 1, 2 ), 35, 'Spin 1 (2 Black), bet 2 pays 35'; +is payout( 1, 3 ), -1, 'Spin 1 (2 Black), bet 3 pays -1'; +is payout( 1, 4 ), -1, 'Spin 1 (2 Black), bet 4 pays -1'; +is payout( 1, 5 ), -1, 'Spin 1 (2 Black), bet 5 pays -1'; +is payout( 1, 6 ), -1, 'Spin 1 (2 Black), bet 6 pays -1'; +is payout( 1, 7 ), -1, 'Spin 1 (2 Black), bet 7 pays -1'; +is payout( 1, 8 ), -1, 'Spin 1 (2 Black), bet 8 pays -1'; +is payout( 1, 9 ), -1, 'Spin 1 (2 Black), bet 9 pays -1'; +is payout( 1, 10 ), -1, 'Spin 1 (2 Black), bet 10 pays -1'; +is payout( 1, 11 ), -1, 'Spin 1 (2 Black), bet 11 pays -1'; +is payout( 1, 12 ), -1, 'Spin 1 (2 Black), bet 12 pays -1'; +is payout( 1, 13 ), -1, 'Spin 1 (2 Black), bet 13 pays -1'; +is payout( 1, 14 ), -1, 'Spin 1 (2 Black), bet 14 pays -1'; +is payout( 1, 15 ), -1, 'Spin 1 (2 Black), bet 15 pays -1'; +is payout( 1, 16 ), -1, 'Spin 1 (2 Black), bet 16 pays -1'; +is payout( 1, 17 ), -1, 'Spin 1 (2 Black), bet 17 pays -1'; +is payout( 1, 18 ), -1, 'Spin 1 (2 Black), bet 18 pays -1'; +is payout( 1, 19 ), -1, 'Spin 1 (2 Black), bet 19 pays -1'; +is payout( 1, 20 ), -1, 'Spin 1 (2 Black), bet 20 pays -1'; +is payout( 1, 21 ), -1, 'Spin 1 (2 Black), bet 21 pays -1'; +is payout( 1, 22 ), -1, 'Spin 1 (2 Black), bet 22 pays -1'; +is payout( 1, 23 ), -1, 'Spin 1 (2 Black), bet 23 pays -1'; +is payout( 1, 24 ), -1, 'Spin 1 (2 Black), bet 24 pays -1'; +is payout( 1, 25 ), -1, 'Spin 1 (2 Black), bet 25 pays -1'; +is payout( 1, 26 ), -1, 'Spin 1 (2 Black), bet 26 pays -1'; +is payout( 1, 27 ), -1, 'Spin 1 (2 Black), bet 27 pays -1'; +is payout( 1, 28 ), -1, 'Spin 1 (2 Black), bet 28 pays -1'; +is payout( 1, 29 ), -1, 'Spin 1 (2 Black), bet 29 pays -1'; +is payout( 1, 30 ), -1, 'Spin 1 (2 Black), bet 30 pays -1'; +is payout( 1, 31 ), -1, 'Spin 1 (2 Black), bet 31 pays -1'; +is payout( 1, 32 ), -1, 'Spin 1 (2 Black), bet 32 pays -1'; +is payout( 1, 33 ), -1, 'Spin 1 (2 Black), bet 33 pays -1'; +is payout( 1, 34 ), -1, 'Spin 1 (2 Black), bet 34 pays -1'; +is payout( 1, 35 ), -1, 'Spin 1 (2 Black), bet 35 pays -1'; +is payout( 1, 36 ), -1, 'Spin 1 (2 Black), bet 36 pays -1'; +is payout( 1, 37 ), 2, 'Spin 1 (2 Black), bet 37 pays 2'; +is payout( 1, 38 ), -1, 'Spin 1 (2 Black), bet 38 pays -1'; +is payout( 1, 39 ), -1, 'Spin 1 (2 Black), bet 39 pays -1'; +is payout( 1, 40 ), -1, 'Spin 1 (2 Black), bet 40 pays -1'; +is payout( 1, 41 ), 2, 'Spin 1 (2 Black), bet 41 pays 2'; +is payout( 1, 42 ), -1, 'Spin 1 (2 Black), bet 42 pays -1'; +is payout( 1, 43 ), 1, 'Spin 1 (2 Black), bet 43 pays 1'; +is payout( 1, 44 ), -1, 'Spin 1 (2 Black), bet 44 pays -1'; +is payout( 1, 45 ), 1, 'Spin 1 (2 Black), bet 45 pays 1'; +is payout( 1, 46 ), -1, 'Spin 1 (2 Black), bet 46 pays -1'; +is payout( 1, 47 ), -1, 'Spin 1 (2 Black), bet 47 pays -1'; +is payout( 1, 48 ), 1, 'Spin 1 (2 Black), bet 48 pays 1'; +is payout( 1, 49 ), -1, 'Spin 1 (2 Black), bet 49 pays -1'; +is payout( 1, 50 ), -1, 'Spin 1 (2 Black), bet 50 pays -1'; +is format_spin( 2 ), '3 Red', 'Spin 2 is 3 Red'; +is payout( 2, 1 ), -1, 'Spin 2 (3 Red), bet 1 pays -1'; +is payout( 2, 2 ), -1, 'Spin 2 (3 Red), bet 2 pays -1'; +is payout( 2, 3 ), 35, 'Spin 2 (3 Red), bet 3 pays 35'; +is payout( 2, 4 ), -1, 'Spin 2 (3 Red), bet 4 pays -1'; +is payout( 2, 5 ), -1, 'Spin 2 (3 Red), bet 5 pays -1'; +is payout( 2, 6 ), -1, 'Spin 2 (3 Red), bet 6 pays -1'; +is payout( 2, 7 ), -1, 'Spin 2 (3 Red), bet 7 pays -1'; +is payout( 2, 8 ), -1, 'Spin 2 (3 Red), bet 8 pays -1'; +is payout( 2, 9 ), -1, 'Spin 2 (3 Red), bet 9 pays -1'; +is payout( 2, 10 ), -1, 'Spin 2 (3 Red), bet 10 pays -1'; +is payout( 2, 11 ), -1, 'Spin 2 (3 Red), bet 11 pays -1'; +is payout( 2, 12 ), -1, 'Spin 2 (3 Red), bet 12 pays -1'; +is payout( 2, 13 ), -1, 'Spin 2 (3 Red), bet 13 pays -1'; +is payout( 2, 14 ), -1, 'Spin 2 (3 Red), bet 14 pays -1'; +is payout( 2, 15 ), -1, 'Spin 2 (3 Red), bet 15 pays -1'; +is payout( 2, 16 ), -1, 'Spin 2 (3 Red), bet 16 pays -1'; +is payout( 2, 17 ), -1, 'Spin 2 (3 Red), bet 17 pays -1'; +is payout( 2, 18 ), -1, 'Spin 2 (3 Red), bet 18 pays -1'; +is payout( 2, 19 ), -1, 'Spin 2 (3 Red), bet 19 pays -1'; +is payout( 2, 20 ), -1, 'Spin 2 (3 Red), bet 20 pays -1'; +is payout( 2, 21 ), -1, 'Spin 2 (3 Red), bet 21 pays -1'; +is payout( 2, 22 ), -1, 'Spin 2 (3 Red), bet 22 pays -1'; +is payout( 2, 23 ), -1, 'Spin 2 (3 Red), bet 23 pays -1'; +is payout( 2, 24 ), -1, 'Spin 2 (3 Red), bet 24 pays -1'; +is payout( 2, 25 ), -1, 'Spin 2 (3 Red), bet 25 pays -1'; +is payout( 2, 26 ), -1, 'Spin 2 (3 Red), bet 26 pays -1'; +is payout( 2, 27 ), -1, 'Spin 2 (3 Red), bet 27 pays -1'; +is payout( 2, 28 ), -1, 'Spin 2 (3 Red), bet 28 pays -1'; +is payout( 2, 29 ), -1, 'Spin 2 (3 Red), bet 29 pays -1'; +is payout( 2, 30 ), -1, 'Spin 2 (3 Red), bet 30 pays -1'; +is payout( 2, 31 ), -1, 'Spin 2 (3 Red), bet 31 pays -1'; +is payout( 2, 32 ), -1, 'Spin 2 (3 Red), bet 32 pays -1'; +is payout( 2, 33 ), -1, 'Spin 2 (3 Red), bet 33 pays -1'; +is payout( 2, 34 ), -1, 'Spin 2 (3 Red), bet 34 pays -1'; +is payout( 2, 35 ), -1, 'Spin 2 (3 Red), bet 35 pays -1'; +is payout( 2, 36 ), -1, 'Spin 2 (3 Red), bet 36 pays -1'; +is payout( 2, 37 ), 2, 'Spin 2 (3 Red), bet 37 pays 2'; +is payout( 2, 38 ), -1, 'Spin 2 (3 Red), bet 38 pays -1'; +is payout( 2, 39 ), -1, 'Spin 2 (3 Red), bet 39 pays -1'; +is payout( 2, 40 ), -1, 'Spin 2 (3 Red), bet 40 pays -1'; +is payout( 2, 41 ), -1, 'Spin 2 (3 Red), bet 41 pays -1'; +is payout( 2, 42 ), 2, 'Spin 2 (3 Red), bet 42 pays 2'; +is payout( 2, 43 ), 1, 'Spin 2 (3 Red), bet 43 pays 1'; +is payout( 2, 44 ), -1, 'Spin 2 (3 Red), bet 44 pays -1'; +is payout( 2, 45 ), -1, 'Spin 2 (3 Red), bet 45 pays -1'; +is payout( 2, 46 ), 1, 'Spin 2 (3 Red), bet 46 pays 1'; +is payout( 2, 47 ), 1, 'Spin 2 (3 Red), bet 47 pays 1'; +is payout( 2, 48 ), -1, 'Spin 2 (3 Red), bet 48 pays -1'; +is payout( 2, 49 ), -1, 'Spin 2 (3 Red), bet 49 pays -1'; +is payout( 2, 50 ), -1, 'Spin 2 (3 Red), bet 50 pays -1'; +is format_spin( 3 ), '4 Black', 'Spin 3 is 4 Black'; +is payout( 3, 1 ), -1, 'Spin 3 (4 Black), bet 1 pays -1'; +is payout( 3, 2 ), -1, 'Spin 3 (4 Black), bet 2 pays -1'; +is payout( 3, 3 ), -1, 'Spin 3 (4 Black), bet 3 pays -1'; +is payout( 3, 4 ), 35, 'Spin 3 (4 Black), bet 4 pays 35'; +is payout( 3, 5 ), -1, 'Spin 3 (4 Black), bet 5 pays -1'; +is payout( 3, 6 ), -1, 'Spin 3 (4 Black), bet 6 pays -1'; +is payout( 3, 7 ), -1, 'Spin 3 (4 Black), bet 7 pays -1'; +is payout( 3, 8 ), -1, 'Spin 3 (4 Black), bet 8 pays -1'; +is payout( 3, 9 ), -1, 'Spin 3 (4 Black), bet 9 pays -1'; +is payout( 3, 10 ), -1, 'Spin 3 (4 Black), bet 10 pays -1'; +is payout( 3, 11 ), -1, 'Spin 3 (4 Black), bet 11 pays -1'; +is payout( 3, 12 ), -1, 'Spin 3 (4 Black), bet 12 pays -1'; +is payout( 3, 13 ), -1, 'Spin 3 (4 Black), bet 13 pays -1'; +is payout( 3, 14 ), -1, 'Spin 3 (4 Black), bet 14 pays -1'; +is payout( 3, 15 ), -1, 'Spin 3 (4 Black), bet 15 pays -1'; +is payout( 3, 16 ), -1, 'Spin 3 (4 Black), bet 16 pays -1'; +is payout( 3, 17 ), -1, 'Spin 3 (4 Black), bet 17 pays -1'; +is payout( 3, 18 ), -1, 'Spin 3 (4 Black), bet 18 pays -1'; +is payout( 3, 19 ), -1, 'Spin 3 (4 Black), bet 19 pays -1'; +is payout( 3, 20 ), -1, 'Spin 3 (4 Black), bet 20 pays -1'; +is payout( 3, 21 ), -1, 'Spin 3 (4 Black), bet 21 pays -1'; +is payout( 3, 22 ), -1, 'Spin 3 (4 Black), bet 22 pays -1'; +is payout( 3, 23 ), -1, 'Spin 3 (4 Black), bet 23 pays -1'; +is payout( 3, 24 ), -1, 'Spin 3 (4 Black), bet 24 pays -1'; +is payout( 3, 25 ), -1, 'Spin 3 (4 Black), bet 25 pays -1'; +is payout( 3, 26 ), -1, 'Spin 3 (4 Black), bet 26 pays -1'; +is payout( 3, 27 ), -1, 'Spin 3 (4 Black), bet 27 pays -1'; +is payout( 3, 28 ), -1, 'Spin 3 (4 Black), bet 28 pays -1'; +is payout( 3, 29 ), -1, 'Spin 3 (4 Black), bet 29 pays -1'; +is payout( 3, 30 ), -1, 'Spin 3 (4 Black), bet 30 pays -1'; +is payout( 3, 31 ), -1, 'Spin 3 (4 Black), bet 31 pays -1'; +is payout( 3, 32 ), -1, 'Spin 3 (4 Black), bet 32 pays -1'; +is payout( 3, 33 ), -1, 'Spin 3 (4 Black), bet 33 pays -1'; +is payout( 3, 34 ), -1, 'Spin 3 (4 Black), bet 34 pays -1'; +is payout( 3, 35 ), -1, 'Spin 3 (4 Black), bet 35 pays -1'; +is payout( 3, 36 ), -1, 'Spin 3 (4 Black), bet 36 pays -1'; +is payout( 3, 37 ), 2, 'Spin 3 (4 Black), bet 37 pays 2'; +is payout( 3, 38 ), -1, 'Spin 3 (4 Black), bet 38 pays -1'; +is payout( 3, 39 ), -1, 'Spin 3 (4 Black), bet 39 pays -1'; +is payout( 3, 40 ), 2, 'Spin 3 (4 Black), bet 40 pays 2'; +is payout( 3, 41 ), -1, 'Spin 3 (4 Black), bet 41 pays -1'; +is payout( 3, 42 ), -1, 'Spin 3 (4 Black), bet 42 pays -1'; +is payout( 3, 43 ), 1, 'Spin 3 (4 Black), bet 43 pays 1'; +is payout( 3, 44 ), -1, 'Spin 3 (4 Black), bet 44 pays -1'; +is payout( 3, 45 ), 1, 'Spin 3 (4 Black), bet 45 pays 1'; +is payout( 3, 46 ), -1, 'Spin 3 (4 Black), bet 46 pays -1'; +is payout( 3, 47 ), -1, 'Spin 3 (4 Black), bet 47 pays -1'; +is payout( 3, 48 ), 1, 'Spin 3 (4 Black), bet 48 pays 1'; +is payout( 3, 49 ), -1, 'Spin 3 (4 Black), bet 49 pays -1'; +is payout( 3, 50 ), -1, 'Spin 3 (4 Black), bet 50 pays -1'; +is format_spin( 4 ), '5 Red', 'Spin 4 is 5 Red'; +is payout( 4, 1 ), -1, 'Spin 4 (5 Red), bet 1 pays -1'; +is payout( 4, 2 ), -1, 'Spin 4 (5 Red), bet 2 pays -1'; +is payout( 4, 3 ), -1, 'Spin 4 (5 Red), bet 3 pays -1'; +is payout( 4, 4 ), -1, 'Spin 4 (5 Red), bet 4 pays -1'; +is payout( 4, 5 ), 35, 'Spin 4 (5 Red), bet 5 pays 35'; +is payout( 4, 6 ), -1, 'Spin 4 (5 Red), bet 6 pays -1'; +is payout( 4, 7 ), -1, 'Spin 4 (5 Red), bet 7 pays -1'; +is payout( 4, 8 ), -1, 'Spin 4 (5 Red), bet 8 pays -1'; +is payout( 4, 9 ), -1, 'Spin 4 (5 Red), bet 9 pays -1'; +is payout( 4, 10 ), -1, 'Spin 4 (5 Red), bet 10 pays -1'; +is payout( 4, 11 ), -1, 'Spin 4 (5 Red), bet 11 pays -1'; +is payout( 4, 12 ), -1, 'Spin 4 (5 Red), bet 12 pays -1'; +is payout( 4, 13 ), -1, 'Spin 4 (5 Red), bet 13 pays -1'; +is payout( 4, 14 ), -1, 'Spin 4 (5 Red), bet 14 pays -1'; +is payout( 4, 15 ), -1, 'Spin 4 (5 Red), bet 15 pays -1'; +is payout( 4, 16 ), -1, 'Spin 4 (5 Red), bet 16 pays -1'; +is payout( 4, 17 ), -1, 'Spin 4 (5 Red), bet 17 pays -1'; +is payout( 4, 18 ), -1, 'Spin 4 (5 Red), bet 18 pays -1'; +is payout( 4, 19 ), -1, 'Spin 4 (5 Red), bet 19 pays -1'; +is payout( 4, 20 ), -1, 'Spin 4 (5 Red), bet 20 pays -1'; +is payout( 4, 21 ), -1, 'Spin 4 (5 Red), bet 21 pays -1'; +is payout( 4, 22 ), -1, 'Spin 4 (5 Red), bet 22 pays -1'; +is payout( 4, 23 ), -1, 'Spin 4 (5 Red), bet 23 pays -1'; +is payout( 4, 24 ), -1, 'Spin 4 (5 Red), bet 24 pays -1'; +is payout( 4, 25 ), -1, 'Spin 4 (5 Red), bet 25 pays -1'; +is payout( 4, 26 ), -1, 'Spin 4 (5 Red), bet 26 pays -1'; +is payout( 4, 27 ), -1, 'Spin 4 (5 Red), bet 27 pays -1'; +is payout( 4, 28 ), -1, 'Spin 4 (5 Red), bet 28 pays -1'; +is payout( 4, 29 ), -1, 'Spin 4 (5 Red), bet 29 pays -1'; +is payout( 4, 30 ), -1, 'Spin 4 (5 Red), bet 30 pays -1'; +is payout( 4, 31 ), -1, 'Spin 4 (5 Red), bet 31 pays -1'; +is payout( 4, 32 ), -1, 'Spin 4 (5 Red), bet 32 pays -1'; +is payout( 4, 33 ), -1, 'Spin 4 (5 Red), bet 33 pays -1'; +is payout( 4, 34 ), -1, 'Spin 4 (5 Red), bet 34 pays -1'; +is payout( 4, 35 ), -1, 'Spin 4 (5 Red), bet 35 pays -1'; +is payout( 4, 36 ), -1, 'Spin 4 (5 Red), bet 36 pays -1'; +is payout( 4, 37 ), 2, 'Spin 4 (5 Red), bet 37 pays 2'; +is payout( 4, 38 ), -1, 'Spin 4 (5 Red), bet 38 pays -1'; +is payout( 4, 39 ), -1, 'Spin 4 (5 Red), bet 39 pays -1'; +is payout( 4, 40 ), -1, 'Spin 4 (5 Red), bet 40 pays -1'; +is payout( 4, 41 ), 2, 'Spin 4 (5 Red), bet 41 pays 2'; +is payout( 4, 42 ), -1, 'Spin 4 (5 Red), bet 42 pays -1'; +is payout( 4, 43 ), 1, 'Spin 4 (5 Red), bet 43 pays 1'; +is payout( 4, 44 ), -1, 'Spin 4 (5 Red), bet 44 pays -1'; +is payout( 4, 45 ), -1, 'Spin 4 (5 Red), bet 45 pays -1'; +is payout( 4, 46 ), 1, 'Spin 4 (5 Red), bet 46 pays 1'; +is payout( 4, 47 ), 1, 'Spin 4 (5 Red), bet 47 pays 1'; +is payout( 4, 48 ), -1, 'Spin 4 (5 Red), bet 48 pays -1'; +is payout( 4, 49 ), -1, 'Spin 4 (5 Red), bet 49 pays -1'; +is payout( 4, 50 ), -1, 'Spin 4 (5 Red), bet 50 pays -1'; +is format_spin( 5 ), '6 Black', 'Spin 5 is 6 Black'; +is payout( 5, 1 ), -1, 'Spin 5 (6 Black), bet 1 pays -1'; +is payout( 5, 2 ), -1, 'Spin 5 (6 Black), bet 2 pays -1'; +is payout( 5, 3 ), -1, 'Spin 5 (6 Black), bet 3 pays -1'; +is payout( 5, 4 ), -1, 'Spin 5 (6 Black), bet 4 pays -1'; +is payout( 5, 5 ), -1, 'Spin 5 (6 Black), bet 5 pays -1'; +is payout( 5, 6 ), 35, 'Spin 5 (6 Black), bet 6 pays 35'; +is payout( 5, 7 ), -1, 'Spin 5 (6 Black), bet 7 pays -1'; +is payout( 5, 8 ), -1, 'Spin 5 (6 Black), bet 8 pays -1'; +is payout( 5, 9 ), -1, 'Spin 5 (6 Black), bet 9 pays -1'; +is payout( 5, 10 ), -1, 'Spin 5 (6 Black), bet 10 pays -1'; +is payout( 5, 11 ), -1, 'Spin 5 (6 Black), bet 11 pays -1'; +is payout( 5, 12 ), -1, 'Spin 5 (6 Black), bet 12 pays -1'; +is payout( 5, 13 ), -1, 'Spin 5 (6 Black), bet 13 pays -1'; +is payout( 5, 14 ), -1, 'Spin 5 (6 Black), bet 14 pays -1'; +is payout( 5, 15 ), -1, 'Spin 5 (6 Black), bet 15 pays -1'; +is payout( 5, 16 ), -1, 'Spin 5 (6 Black), bet 16 pays -1'; +is payout( 5, 17 ), -1, 'Spin 5 (6 Black), bet 17 pays -1'; +is payout( 5, 18 ), -1, 'Spin 5 (6 Black), bet 18 pays -1'; +is payout( 5, 19 ), -1, 'Spin 5 (6 Black), bet 19 pays -1'; +is payout( 5, 20 ), -1, 'Spin 5 (6 Black), bet 20 pays -1'; +is payout( 5, 21 ), -1, 'Spin 5 (6 Black), bet 21 pays -1'; +is payout( 5, 22 ), -1, 'Spin 5 (6 Black), bet 22 pays -1'; +is payout( 5, 23 ), -1, 'Spin 5 (6 Black), bet 23 pays -1'; +is payout( 5, 24 ), -1, 'Spin 5 (6 Black), bet 24 pays -1'; +is payout( 5, 25 ), -1, 'Spin 5 (6 Black), bet 25 pays -1'; +is payout( 5, 26 ), -1, 'Spin 5 (6 Black), bet 26 pays -1'; +is payout( 5, 27 ), -1, 'Spin 5 (6 Black), bet 27 pays -1'; +is payout( 5, 28 ), -1, 'Spin 5 (6 Black), bet 28 pays -1'; +is payout( 5, 29 ), -1, 'Spin 5 (6 Black), bet 29 pays -1'; +is payout( 5, 30 ), -1, 'Spin 5 (6 Black), bet 30 pays -1'; +is payout( 5, 31 ), -1, 'Spin 5 (6 Black), bet 31 pays -1'; +is payout( 5, 32 ), -1, 'Spin 5 (6 Black), bet 32 pays -1'; +is payout( 5, 33 ), -1, 'Spin 5 (6 Black), bet 33 pays -1'; +is payout( 5, 34 ), -1, 'Spin 5 (6 Black), bet 34 pays -1'; +is payout( 5, 35 ), -1, 'Spin 5 (6 Black), bet 35 pays -1'; +is payout( 5, 36 ), -1, 'Spin 5 (6 Black), bet 36 pays -1'; +is payout( 5, 37 ), 2, 'Spin 5 (6 Black), bet 37 pays 2'; +is payout( 5, 38 ), -1, 'Spin 5 (6 Black), bet 38 pays -1'; +is payout( 5, 39 ), -1, 'Spin 5 (6 Black), bet 39 pays -1'; +is payout( 5, 40 ), -1, 'Spin 5 (6 Black), bet 40 pays -1'; +is payout( 5, 41 ), -1, 'Spin 5 (6 Black), bet 41 pays -1'; +is payout( 5, 42 ), 2, 'Spin 5 (6 Black), bet 42 pays 2'; +is payout( 5, 43 ), 1, 'Spin 5 (6 Black), bet 43 pays 1'; +is payout( 5, 44 ), -1, 'Spin 5 (6 Black), bet 44 pays -1'; +is payout( 5, 45 ), 1, 'Spin 5 (6 Black), bet 45 pays 1'; +is payout( 5, 46 ), -1, 'Spin 5 (6 Black), bet 46 pays -1'; +is payout( 5, 47 ), -1, 'Spin 5 (6 Black), bet 47 pays -1'; +is payout( 5, 48 ), 1, 'Spin 5 (6 Black), bet 48 pays 1'; +is payout( 5, 49 ), -1, 'Spin 5 (6 Black), bet 49 pays -1'; +is payout( 5, 50 ), -1, 'Spin 5 (6 Black), bet 50 pays -1'; +is format_spin( 6 ), '7 Red', 'Spin 6 is 7 Red'; +is payout( 6, 1 ), -1, 'Spin 6 (7 Red), bet 1 pays -1'; +is payout( 6, 2 ), -1, 'Spin 6 (7 Red), bet 2 pays -1'; +is payout( 6, 3 ), -1, 'Spin 6 (7 Red), bet 3 pays -1'; +is payout( 6, 4 ), -1, 'Spin 6 (7 Red), bet 4 pays -1'; +is payout( 6, 5 ), -1, 'Spin 6 (7 Red), bet 5 pays -1'; +is payout( 6, 6 ), -1, 'Spin 6 (7 Red), bet 6 pays -1'; +is payout( 6, 7 ), 35, 'Spin 6 (7 Red), bet 7 pays 35'; +is payout( 6, 8 ), -1, 'Spin 6 (7 Red), bet 8 pays -1'; +is payout( 6, 9 ), -1, 'Spin 6 (7 Red), bet 9 pays -1'; +is payout( 6, 10 ), -1, 'Spin 6 (7 Red), bet 10 pays -1'; +is payout( 6, 11 ), -1, 'Spin 6 (7 Red), bet 11 pays -1'; +is payout( 6, 12 ), -1, 'Spin 6 (7 Red), bet 12 pays -1'; +is payout( 6, 13 ), -1, 'Spin 6 (7 Red), bet 13 pays -1'; +is payout( 6, 14 ), -1, 'Spin 6 (7 Red), bet 14 pays -1'; +is payout( 6, 15 ), -1, 'Spin 6 (7 Red), bet 15 pays -1'; +is payout( 6, 16 ), -1, 'Spin 6 (7 Red), bet 16 pays -1'; +is payout( 6, 17 ), -1, 'Spin 6 (7 Red), bet 17 pays -1'; +is payout( 6, 18 ), -1, 'Spin 6 (7 Red), bet 18 pays -1'; +is payout( 6, 19 ), -1, 'Spin 6 (7 Red), bet 19 pays -1'; +is payout( 6, 20 ), -1, 'Spin 6 (7 Red), bet 20 pays -1'; +is payout( 6, 21 ), -1, 'Spin 6 (7 Red), bet 21 pays -1'; +is payout( 6, 22 ), -1, 'Spin 6 (7 Red), bet 22 pays -1'; +is payout( 6, 23 ), -1, 'Spin 6 (7 Red), bet 23 pays -1'; +is payout( 6, 24 ), -1, 'Spin 6 (7 Red), bet 24 pays -1'; +is payout( 6, 25 ), -1, 'Spin 6 (7 Red), bet 25 pays -1'; +is payout( 6, 26 ), -1, 'Spin 6 (7 Red), bet 26 pays -1'; +is payout( 6, 27 ), -1, 'Spin 6 (7 Red), bet 27 pays -1'; +is payout( 6, 28 ), -1, 'Spin 6 (7 Red), bet 28 pays -1'; +is payout( 6, 29 ), -1, 'Spin 6 (7 Red), bet 29 pays -1'; +is payout( 6, 30 ), -1, 'Spin 6 (7 Red), bet 30 pays -1'; +is payout( 6, 31 ), -1, 'Spin 6 (7 Red), bet 31 pays -1'; +is payout( 6, 32 ), -1, 'Spin 6 (7 Red), bet 32 pays -1'; +is payout( 6, 33 ), -1, 'Spin 6 (7 Red), bet 33 pays -1'; +is payout( 6, 34 ), -1, 'Spin 6 (7 Red), bet 34 pays -1'; +is payout( 6, 35 ), -1, 'Spin 6 (7 Red), bet 35 pays -1'; +is payout( 6, 36 ), -1, 'Spin 6 (7 Red), bet 36 pays -1'; +is payout( 6, 37 ), 2, 'Spin 6 (7 Red), bet 37 pays 2'; +is payout( 6, 38 ), -1, 'Spin 6 (7 Red), bet 38 pays -1'; +is payout( 6, 39 ), -1, 'Spin 6 (7 Red), bet 39 pays -1'; +is payout( 6, 40 ), 2, 'Spin 6 (7 Red), bet 40 pays 2'; +is payout( 6, 41 ), -1, 'Spin 6 (7 Red), bet 41 pays -1'; +is payout( 6, 42 ), -1, 'Spin 6 (7 Red), bet 42 pays -1'; +is payout( 6, 43 ), 1, 'Spin 6 (7 Red), bet 43 pays 1'; +is payout( 6, 44 ), -1, 'Spin 6 (7 Red), bet 44 pays -1'; +is payout( 6, 45 ), -1, 'Spin 6 (7 Red), bet 45 pays -1'; +is payout( 6, 46 ), 1, 'Spin 6 (7 Red), bet 46 pays 1'; +is payout( 6, 47 ), 1, 'Spin 6 (7 Red), bet 47 pays 1'; +is payout( 6, 48 ), -1, 'Spin 6 (7 Red), bet 48 pays -1'; +is payout( 6, 49 ), -1, 'Spin 6 (7 Red), bet 49 pays -1'; +is payout( 6, 50 ), -1, 'Spin 6 (7 Red), bet 50 pays -1'; +is format_spin( 7 ), '8 Black', 'Spin 7 is 8 Black'; +is payout( 7, 1 ), -1, 'Spin 7 (8 Black), bet 1 pays -1'; +is payout( 7, 2 ), -1, 'Spin 7 (8 Black), bet 2 pays -1'; +is payout( 7, 3 ), -1, 'Spin 7 (8 Black), bet 3 pays -1'; +is payout( 7, 4 ), -1, 'Spin 7 (8 Black), bet 4 pays -1'; +is payout( 7, 5 ), -1, 'Spin 7 (8 Black), bet 5 pays -1'; +is payout( 7, 6 ), -1, 'Spin 7 (8 Black), bet 6 pays -1'; +is payout( 7, 7 ), -1, 'Spin 7 (8 Black), bet 7 pays -1'; +is payout( 7, 8 ), 35, 'Spin 7 (8 Black), bet 8 pays 35'; +is payout( 7, 9 ), -1, 'Spin 7 (8 Black), bet 9 pays -1'; +is payout( 7, 10 ), -1, 'Spin 7 (8 Black), bet 10 pays -1'; +is payout( 7, 11 ), -1, 'Spin 7 (8 Black), bet 11 pays -1'; +is payout( 7, 12 ), -1, 'Spin 7 (8 Black), bet 12 pays -1'; +is payout( 7, 13 ), -1, 'Spin 7 (8 Black), bet 13 pays -1'; +is payout( 7, 14 ), -1, 'Spin 7 (8 Black), bet 14 pays -1'; +is payout( 7, 15 ), -1, 'Spin 7 (8 Black), bet 15 pays -1'; +is payout( 7, 16 ), -1, 'Spin 7 (8 Black), bet 16 pays -1'; +is payout( 7, 17 ), -1, 'Spin 7 (8 Black), bet 17 pays -1'; +is payout( 7, 18 ), -1, 'Spin 7 (8 Black), bet 18 pays -1'; +is payout( 7, 19 ), -1, 'Spin 7 (8 Black), bet 19 pays -1'; +is payout( 7, 20 ), -1, 'Spin 7 (8 Black), bet 20 pays -1'; +is payout( 7, 21 ), -1, 'Spin 7 (8 Black), bet 21 pays -1'; +is payout( 7, 22 ), -1, 'Spin 7 (8 Black), bet 22 pays -1'; +is payout( 7, 23 ), -1, 'Spin 7 (8 Black), bet 23 pays -1'; +is payout( 7, 24 ), -1, 'Spin 7 (8 Black), bet 24 pays -1'; +is payout( 7, 25 ), -1, 'Spin 7 (8 Black), bet 25 pays -1'; +is payout( 7, 26 ), -1, 'Spin 7 (8 Black), bet 26 pays -1'; +is payout( 7, 27 ), -1, 'Spin 7 (8 Black), bet 27 pays -1'; +is payout( 7, 28 ), -1, 'Spin 7 (8 Black), bet 28 pays -1'; +is payout( 7, 29 ), -1, 'Spin 7 (8 Black), bet 29 pays -1'; +is payout( 7, 30 ), -1, 'Spin 7 (8 Black), bet 30 pays -1'; +is payout( 7, 31 ), -1, 'Spin 7 (8 Black), bet 31 pays -1'; +is payout( 7, 32 ), -1, 'Spin 7 (8 Black), bet 32 pays -1'; +is payout( 7, 33 ), -1, 'Spin 7 (8 Black), bet 33 pays -1'; +is payout( 7, 34 ), -1, 'Spin 7 (8 Black), bet 34 pays -1'; +is payout( 7, 35 ), -1, 'Spin 7 (8 Black), bet 35 pays -1'; +is payout( 7, 36 ), -1, 'Spin 7 (8 Black), bet 36 pays -1'; +is payout( 7, 37 ), 2, 'Spin 7 (8 Black), bet 37 pays 2'; +is payout( 7, 38 ), -1, 'Spin 7 (8 Black), bet 38 pays -1'; +is payout( 7, 39 ), -1, 'Spin 7 (8 Black), bet 39 pays -1'; +is payout( 7, 40 ), -1, 'Spin 7 (8 Black), bet 40 pays -1'; +is payout( 7, 41 ), 2, 'Spin 7 (8 Black), bet 41 pays 2'; +is payout( 7, 42 ), -1, 'Spin 7 (8 Black), bet 42 pays -1'; +is payout( 7, 43 ), 1, 'Spin 7 (8 Black), bet 43 pays 1'; +is payout( 7, 44 ), -1, 'Spin 7 (8 Black), bet 44 pays -1'; +is payout( 7, 45 ), 1, 'Spin 7 (8 Black), bet 45 pays 1'; +is payout( 7, 46 ), -1, 'Spin 7 (8 Black), bet 46 pays -1'; +is payout( 7, 47 ), -1, 'Spin 7 (8 Black), bet 47 pays -1'; +is payout( 7, 48 ), 1, 'Spin 7 (8 Black), bet 48 pays 1'; +is payout( 7, 49 ), -1, 'Spin 7 (8 Black), bet 49 pays -1'; +is payout( 7, 50 ), -1, 'Spin 7 (8 Black), bet 50 pays -1'; +is format_spin( 8 ), '9 Red', 'Spin 8 is 9 Red'; +is payout( 8, 1 ), -1, 'Spin 8 (9 Red), bet 1 pays -1'; +is payout( 8, 2 ), -1, 'Spin 8 (9 Red), bet 2 pays -1'; +is payout( 8, 3 ), -1, 'Spin 8 (9 Red), bet 3 pays -1'; +is payout( 8, 4 ), -1, 'Spin 8 (9 Red), bet 4 pays -1'; +is payout( 8, 5 ), -1, 'Spin 8 (9 Red), bet 5 pays -1'; +is payout( 8, 6 ), -1, 'Spin 8 (9 Red), bet 6 pays -1'; +is payout( 8, 7 ), -1, 'Spin 8 (9 Red), bet 7 pays -1'; +is payout( 8, 8 ), -1, 'Spin 8 (9 Red), bet 8 pays -1'; +is payout( 8, 9 ), 35, 'Spin 8 (9 Red), bet 9 pays 35'; +is payout( 8, 10 ), -1, 'Spin 8 (9 Red), bet 10 pays -1'; +is payout( 8, 11 ), -1, 'Spin 8 (9 Red), bet 11 pays -1'; +is payout( 8, 12 ), -1, 'Spin 8 (9 Red), bet 12 pays -1'; +is payout( 8, 13 ), -1, 'Spin 8 (9 Red), bet 13 pays -1'; +is payout( 8, 14 ), -1, 'Spin 8 (9 Red), bet 14 pays -1'; +is payout( 8, 15 ), -1, 'Spin 8 (9 Red), bet 15 pays -1'; +is payout( 8, 16 ), -1, 'Spin 8 (9 Red), bet 16 pays -1'; +is payout( 8, 17 ), -1, 'Spin 8 (9 Red), bet 17 pays -1'; +is payout( 8, 18 ), -1, 'Spin 8 (9 Red), bet 18 pays -1'; +is payout( 8, 19 ), -1, 'Spin 8 (9 Red), bet 19 pays -1'; +is payout( 8, 20 ), -1, 'Spin 8 (9 Red), bet 20 pays -1'; +is payout( 8, 21 ), -1, 'Spin 8 (9 Red), bet 21 pays -1'; +is payout( 8, 22 ), -1, 'Spin 8 (9 Red), bet 22 pays -1'; +is payout( 8, 23 ), -1, 'Spin 8 (9 Red), bet 23 pays -1'; +is payout( 8, 24 ), -1, 'Spin 8 (9 Red), bet 24 pays -1'; +is payout( 8, 25 ), -1, 'Spin 8 (9 Red), bet 25 pays -1'; +is payout( 8, 26 ), -1, 'Spin 8 (9 Red), bet 26 pays -1'; +is payout( 8, 27 ), -1, 'Spin 8 (9 Red), bet 27 pays -1'; +is payout( 8, 28 ), -1, 'Spin 8 (9 Red), bet 28 pays -1'; +is payout( 8, 29 ), -1, 'Spin 8 (9 Red), bet 29 pays -1'; +is payout( 8, 30 ), -1, 'Spin 8 (9 Red), bet 30 pays -1'; +is payout( 8, 31 ), -1, 'Spin 8 (9 Red), bet 31 pays -1'; +is payout( 8, 32 ), -1, 'Spin 8 (9 Red), bet 32 pays -1'; +is payout( 8, 33 ), -1, 'Spin 8 (9 Red), bet 33 pays -1'; +is payout( 8, 34 ), -1, 'Spin 8 (9 Red), bet 34 pays -1'; +is payout( 8, 35 ), -1, 'Spin 8 (9 Red), bet 35 pays -1'; +is payout( 8, 36 ), -1, 'Spin 8 (9 Red), bet 36 pays -1'; +is payout( 8, 37 ), 2, 'Spin 8 (9 Red), bet 37 pays 2'; +is payout( 8, 38 ), -1, 'Spin 8 (9 Red), bet 38 pays -1'; +is payout( 8, 39 ), -1, 'Spin 8 (9 Red), bet 39 pays -1'; +is payout( 8, 40 ), -1, 'Spin 8 (9 Red), bet 40 pays -1'; +is payout( 8, 41 ), -1, 'Spin 8 (9 Red), bet 41 pays -1'; +is payout( 8, 42 ), 2, 'Spin 8 (9 Red), bet 42 pays 2'; +is payout( 8, 43 ), 1, 'Spin 8 (9 Red), bet 43 pays 1'; +is payout( 8, 44 ), -1, 'Spin 8 (9 Red), bet 44 pays -1'; +is payout( 8, 45 ), -1, 'Spin 8 (9 Red), bet 45 pays -1'; +is payout( 8, 46 ), 1, 'Spin 8 (9 Red), bet 46 pays 1'; +is payout( 8, 47 ), 1, 'Spin 8 (9 Red), bet 47 pays 1'; +is payout( 8, 48 ), -1, 'Spin 8 (9 Red), bet 48 pays -1'; +is payout( 8, 49 ), -1, 'Spin 8 (9 Red), bet 49 pays -1'; +is payout( 8, 50 ), -1, 'Spin 8 (9 Red), bet 50 pays -1'; +is format_spin( 9 ), '10 Black', 'Spin 9 is 10 Black'; +is payout( 9, 1 ), -1, 'Spin 9 (10 Black), bet 1 pays -1'; +is payout( 9, 2 ), -1, 'Spin 9 (10 Black), bet 2 pays -1'; +is payout( 9, 3 ), -1, 'Spin 9 (10 Black), bet 3 pays -1'; +is payout( 9, 4 ), -1, 'Spin 9 (10 Black), bet 4 pays -1'; +is payout( 9, 5 ), -1, 'Spin 9 (10 Black), bet 5 pays -1'; +is payout( 9, 6 ), -1, 'Spin 9 (10 Black), bet 6 pays -1'; +is payout( 9, 7 ), -1, 'Spin 9 (10 Black), bet 7 pays -1'; +is payout( 9, 8 ), -1, 'Spin 9 (10 Black), bet 8 pays -1'; +is payout( 9, 9 ), -1, 'Spin 9 (10 Black), bet 9 pays -1'; +is payout( 9, 10 ), 35, 'Spin 9 (10 Black), bet 10 pays 35'; +is payout( 9, 11 ), -1, 'Spin 9 (10 Black), bet 11 pays -1'; +is payout( 9, 12 ), -1, 'Spin 9 (10 Black), bet 12 pays -1'; +is payout( 9, 13 ), -1, 'Spin 9 (10 Black), bet 13 pays -1'; +is payout( 9, 14 ), -1, 'Spin 9 (10 Black), bet 14 pays -1'; +is payout( 9, 15 ), -1, 'Spin 9 (10 Black), bet 15 pays -1'; +is payout( 9, 16 ), -1, 'Spin 9 (10 Black), bet 16 pays -1'; +is payout( 9, 17 ), -1, 'Spin 9 (10 Black), bet 17 pays -1'; +is payout( 9, 18 ), -1, 'Spin 9 (10 Black), bet 18 pays -1'; +is payout( 9, 19 ), -1, 'Spin 9 (10 Black), bet 19 pays -1'; +is payout( 9, 20 ), -1, 'Spin 9 (10 Black), bet 20 pays -1'; +is payout( 9, 21 ), -1, 'Spin 9 (10 Black), bet 21 pays -1'; +is payout( 9, 22 ), -1, 'Spin 9 (10 Black), bet 22 pays -1'; +is payout( 9, 23 ), -1, 'Spin 9 (10 Black), bet 23 pays -1'; +is payout( 9, 24 ), -1, 'Spin 9 (10 Black), bet 24 pays -1'; +is payout( 9, 25 ), -1, 'Spin 9 (10 Black), bet 25 pays -1'; +is payout( 9, 26 ), -1, 'Spin 9 (10 Black), bet 26 pays -1'; +is payout( 9, 27 ), -1, 'Spin 9 (10 Black), bet 27 pays -1'; +is payout( 9, 28 ), -1, 'Spin 9 (10 Black), bet 28 pays -1'; +is payout( 9, 29 ), -1, 'Spin 9 (10 Black), bet 29 pays -1'; +is payout( 9, 30 ), -1, 'Spin 9 (10 Black), bet 30 pays -1'; +is payout( 9, 31 ), -1, 'Spin 9 (10 Black), bet 31 pays -1'; +is payout( 9, 32 ), -1, 'Spin 9 (10 Black), bet 32 pays -1'; +is payout( 9, 33 ), -1, 'Spin 9 (10 Black), bet 33 pays -1'; +is payout( 9, 34 ), -1, 'Spin 9 (10 Black), bet 34 pays -1'; +is payout( 9, 35 ), -1, 'Spin 9 (10 Black), bet 35 pays -1'; +is payout( 9, 36 ), -1, 'Spin 9 (10 Black), bet 36 pays -1'; +is payout( 9, 37 ), 2, 'Spin 9 (10 Black), bet 37 pays 2'; +is payout( 9, 38 ), -1, 'Spin 9 (10 Black), bet 38 pays -1'; +is payout( 9, 39 ), -1, 'Spin 9 (10 Black), bet 39 pays -1'; +is payout( 9, 40 ), 2, 'Spin 9 (10 Black), bet 40 pays 2'; +is payout( 9, 41 ), -1, 'Spin 9 (10 Black), bet 41 pays -1'; +is payout( 9, 42 ), -1, 'Spin 9 (10 Black), bet 42 pays -1'; +is payout( 9, 43 ), 1, 'Spin 9 (10 Black), bet 43 pays 1'; +is payout( 9, 44 ), -1, 'Spin 9 (10 Black), bet 44 pays -1'; +is payout( 9, 45 ), 1, 'Spin 9 (10 Black), bet 45 pays 1'; +is payout( 9, 46 ), -1, 'Spin 9 (10 Black), bet 46 pays -1'; +is payout( 9, 47 ), -1, 'Spin 9 (10 Black), bet 47 pays -1'; +is payout( 9, 48 ), 1, 'Spin 9 (10 Black), bet 48 pays 1'; +is payout( 9, 49 ), -1, 'Spin 9 (10 Black), bet 49 pays -1'; +is payout( 9, 50 ), -1, 'Spin 9 (10 Black), bet 50 pays -1'; +is format_spin( 10 ), '11 Black', 'Spin 10 is 11 Black'; +is payout( 10, 1 ), -1, 'Spin 10 (11 Black), bet 1 pays -1'; +is payout( 10, 2 ), -1, 'Spin 10 (11 Black), bet 2 pays -1'; +is payout( 10, 3 ), -1, 'Spin 10 (11 Black), bet 3 pays -1'; +is payout( 10, 4 ), -1, 'Spin 10 (11 Black), bet 4 pays -1'; +is payout( 10, 5 ), -1, 'Spin 10 (11 Black), bet 5 pays -1'; +is payout( 10, 6 ), -1, 'Spin 10 (11 Black), bet 6 pays -1'; +is payout( 10, 7 ), -1, 'Spin 10 (11 Black), bet 7 pays -1'; +is payout( 10, 8 ), -1, 'Spin 10 (11 Black), bet 8 pays -1'; +is payout( 10, 9 ), -1, 'Spin 10 (11 Black), bet 9 pays -1'; +is payout( 10, 10 ), -1, 'Spin 10 (11 Black), bet 10 pays -1'; +is payout( 10, 11 ), 35, 'Spin 10 (11 Black), bet 11 pays 35'; +is payout( 10, 12 ), -1, 'Spin 10 (11 Black), bet 12 pays -1'; +is payout( 10, 13 ), -1, 'Spin 10 (11 Black), bet 13 pays -1'; +is payout( 10, 14 ), -1, 'Spin 10 (11 Black), bet 14 pays -1'; +is payout( 10, 15 ), -1, 'Spin 10 (11 Black), bet 15 pays -1'; +is payout( 10, 16 ), -1, 'Spin 10 (11 Black), bet 16 pays -1'; +is payout( 10, 17 ), -1, 'Spin 10 (11 Black), bet 17 pays -1'; +is payout( 10, 18 ), -1, 'Spin 10 (11 Black), bet 18 pays -1'; +is payout( 10, 19 ), -1, 'Spin 10 (11 Black), bet 19 pays -1'; +is payout( 10, 20 ), -1, 'Spin 10 (11 Black), bet 20 pays -1'; +is payout( 10, 21 ), -1, 'Spin 10 (11 Black), bet 21 pays -1'; +is payout( 10, 22 ), -1, 'Spin 10 (11 Black), bet 22 pays -1'; +is payout( 10, 23 ), -1, 'Spin 10 (11 Black), bet 23 pays -1'; +is payout( 10, 24 ), -1, 'Spin 10 (11 Black), bet 24 pays -1'; +is payout( 10, 25 ), -1, 'Spin 10 (11 Black), bet 25 pays -1'; +is payout( 10, 26 ), -1, 'Spin 10 (11 Black), bet 26 pays -1'; +is payout( 10, 27 ), -1, 'Spin 10 (11 Black), bet 27 pays -1'; +is payout( 10, 28 ), -1, 'Spin 10 (11 Black), bet 28 pays -1'; +is payout( 10, 29 ), -1, 'Spin 10 (11 Black), bet 29 pays -1'; +is payout( 10, 30 ), -1, 'Spin 10 (11 Black), bet 30 pays -1'; +is payout( 10, 31 ), -1, 'Spin 10 (11 Black), bet 31 pays -1'; +is payout( 10, 32 ), -1, 'Spin 10 (11 Black), bet 32 pays -1'; +is payout( 10, 33 ), -1, 'Spin 10 (11 Black), bet 33 pays -1'; +is payout( 10, 34 ), -1, 'Spin 10 (11 Black), bet 34 pays -1'; +is payout( 10, 35 ), -1, 'Spin 10 (11 Black), bet 35 pays -1'; +is payout( 10, 36 ), -1, 'Spin 10 (11 Black), bet 36 pays -1'; +is payout( 10, 37 ), 2, 'Spin 10 (11 Black), bet 37 pays 2'; +is payout( 10, 38 ), -1, 'Spin 10 (11 Black), bet 38 pays -1'; +is payout( 10, 39 ), -1, 'Spin 10 (11 Black), bet 39 pays -1'; +is payout( 10, 40 ), -1, 'Spin 10 (11 Black), bet 40 pays -1'; +is payout( 10, 41 ), 2, 'Spin 10 (11 Black), bet 41 pays 2'; +is payout( 10, 42 ), -1, 'Spin 10 (11 Black), bet 42 pays -1'; +is payout( 10, 43 ), 1, 'Spin 10 (11 Black), bet 43 pays 1'; +is payout( 10, 44 ), -1, 'Spin 10 (11 Black), bet 44 pays -1'; +is payout( 10, 45 ), -1, 'Spin 10 (11 Black), bet 45 pays -1'; +is payout( 10, 46 ), 1, 'Spin 10 (11 Black), bet 46 pays 1'; +is payout( 10, 47 ), -1, 'Spin 10 (11 Black), bet 47 pays -1'; +is payout( 10, 48 ), 1, 'Spin 10 (11 Black), bet 48 pays 1'; +is payout( 10, 49 ), -1, 'Spin 10 (11 Black), bet 49 pays -1'; +is payout( 10, 50 ), -1, 'Spin 10 (11 Black), bet 50 pays -1'; +is format_spin( 11 ), '12 Red', 'Spin 11 is 12 Red'; +is payout( 11, 1 ), -1, 'Spin 11 (12 Red), bet 1 pays -1'; +is payout( 11, 2 ), -1, 'Spin 11 (12 Red), bet 2 pays -1'; +is payout( 11, 3 ), -1, 'Spin 11 (12 Red), bet 3 pays -1'; +is payout( 11, 4 ), -1, 'Spin 11 (12 Red), bet 4 pays -1'; +is payout( 11, 5 ), -1, 'Spin 11 (12 Red), bet 5 pays -1'; +is payout( 11, 6 ), -1, 'Spin 11 (12 Red), bet 6 pays -1'; +is payout( 11, 7 ), -1, 'Spin 11 (12 Red), bet 7 pays -1'; +is payout( 11, 8 ), -1, 'Spin 11 (12 Red), bet 8 pays -1'; +is payout( 11, 9 ), -1, 'Spin 11 (12 Red), bet 9 pays -1'; +is payout( 11, 10 ), -1, 'Spin 11 (12 Red), bet 10 pays -1'; +is payout( 11, 11 ), -1, 'Spin 11 (12 Red), bet 11 pays -1'; +is payout( 11, 12 ), 35, 'Spin 11 (12 Red), bet 12 pays 35'; +is payout( 11, 13 ), -1, 'Spin 11 (12 Red), bet 13 pays -1'; +is payout( 11, 14 ), -1, 'Spin 11 (12 Red), bet 14 pays -1'; +is payout( 11, 15 ), -1, 'Spin 11 (12 Red), bet 15 pays -1'; +is payout( 11, 16 ), -1, 'Spin 11 (12 Red), bet 16 pays -1'; +is payout( 11, 17 ), -1, 'Spin 11 (12 Red), bet 17 pays -1'; +is payout( 11, 18 ), -1, 'Spin 11 (12 Red), bet 18 pays -1'; +is payout( 11, 19 ), -1, 'Spin 11 (12 Red), bet 19 pays -1'; +is payout( 11, 20 ), -1, 'Spin 11 (12 Red), bet 20 pays -1'; +is payout( 11, 21 ), -1, 'Spin 11 (12 Red), bet 21 pays -1'; +is payout( 11, 22 ), -1, 'Spin 11 (12 Red), bet 22 pays -1'; +is payout( 11, 23 ), -1, 'Spin 11 (12 Red), bet 23 pays -1'; +is payout( 11, 24 ), -1, 'Spin 11 (12 Red), bet 24 pays -1'; +is payout( 11, 25 ), -1, 'Spin 11 (12 Red), bet 25 pays -1'; +is payout( 11, 26 ), -1, 'Spin 11 (12 Red), bet 26 pays -1'; +is payout( 11, 27 ), -1, 'Spin 11 (12 Red), bet 27 pays -1'; +is payout( 11, 28 ), -1, 'Spin 11 (12 Red), bet 28 pays -1'; +is payout( 11, 29 ), -1, 'Spin 11 (12 Red), bet 29 pays -1'; +is payout( 11, 30 ), -1, 'Spin 11 (12 Red), bet 30 pays -1'; +is payout( 11, 31 ), -1, 'Spin 11 (12 Red), bet 31 pays -1'; +is payout( 11, 32 ), -1, 'Spin 11 (12 Red), bet 32 pays -1'; +is payout( 11, 33 ), -1, 'Spin 11 (12 Red), bet 33 pays -1'; +is payout( 11, 34 ), -1, 'Spin 11 (12 Red), bet 34 pays -1'; +is payout( 11, 35 ), -1, 'Spin 11 (12 Red), bet 35 pays -1'; +is payout( 11, 36 ), -1, 'Spin 11 (12 Red), bet 36 pays -1'; +is payout( 11, 37 ), 2, 'Spin 11 (12 Red), bet 37 pays 2'; +is payout( 11, 38 ), -1, 'Spin 11 (12 Red), bet 38 pays -1'; +is payout( 11, 39 ), -1, 'Spin 11 (12 Red), bet 39 pays -1'; +is payout( 11, 40 ), -1, 'Spin 11 (12 Red), bet 40 pays -1'; +is payout( 11, 41 ), -1, 'Spin 11 (12 Red), bet 41 pays -1'; +is payout( 11, 42 ), 2, 'Spin 11 (12 Red), bet 42 pays 2'; +is payout( 11, 43 ), 1, 'Spin 11 (12 Red), bet 43 pays 1'; +is payout( 11, 44 ), -1, 'Spin 11 (12 Red), bet 44 pays -1'; +is payout( 11, 45 ), 1, 'Spin 11 (12 Red), bet 45 pays 1'; +is payout( 11, 46 ), -1, 'Spin 11 (12 Red), bet 46 pays -1'; +is payout( 11, 47 ), 1, 'Spin 11 (12 Red), bet 47 pays 1'; +is payout( 11, 48 ), -1, 'Spin 11 (12 Red), bet 48 pays -1'; +is payout( 11, 49 ), -1, 'Spin 11 (12 Red), bet 49 pays -1'; +is payout( 11, 50 ), -1, 'Spin 11 (12 Red), bet 50 pays -1'; +is format_spin( 12 ), '13 Black', 'Spin 12 is 13 Black'; +is payout( 12, 1 ), -1, 'Spin 12 (13 Black), bet 1 pays -1'; +is payout( 12, 2 ), -1, 'Spin 12 (13 Black), bet 2 pays -1'; +is payout( 12, 3 ), -1, 'Spin 12 (13 Black), bet 3 pays -1'; +is payout( 12, 4 ), -1, 'Spin 12 (13 Black), bet 4 pays -1'; +is payout( 12, 5 ), -1, 'Spin 12 (13 Black), bet 5 pays -1'; +is payout( 12, 6 ), -1, 'Spin 12 (13 Black), bet 6 pays -1'; +is payout( 12, 7 ), -1, 'Spin 12 (13 Black), bet 7 pays -1'; +is payout( 12, 8 ), -1, 'Spin 12 (13 Black), bet 8 pays -1'; +is payout( 12, 9 ), -1, 'Spin 12 (13 Black), bet 9 pays -1'; +is payout( 12, 10 ), -1, 'Spin 12 (13 Black), bet 10 pays -1'; +is payout( 12, 11 ), -1, 'Spin 12 (13 Black), bet 11 pays -1'; +is payout( 12, 12 ), -1, 'Spin 12 (13 Black), bet 12 pays -1'; +is payout( 12, 13 ), 35, 'Spin 12 (13 Black), bet 13 pays 35'; +is payout( 12, 14 ), -1, 'Spin 12 (13 Black), bet 14 pays -1'; +is payout( 12, 15 ), -1, 'Spin 12 (13 Black), bet 15 pays -1'; +is payout( 12, 16 ), -1, 'Spin 12 (13 Black), bet 16 pays -1'; +is payout( 12, 17 ), -1, 'Spin 12 (13 Black), bet 17 pays -1'; +is payout( 12, 18 ), -1, 'Spin 12 (13 Black), bet 18 pays -1'; +is payout( 12, 19 ), -1, 'Spin 12 (13 Black), bet 19 pays -1'; +is payout( 12, 20 ), -1, 'Spin 12 (13 Black), bet 20 pays -1'; +is payout( 12, 21 ), -1, 'Spin 12 (13 Black), bet 21 pays -1'; +is payout( 12, 22 ), -1, 'Spin 12 (13 Black), bet 22 pays -1'; +is payout( 12, 23 ), -1, 'Spin 12 (13 Black), bet 23 pays -1'; +is payout( 12, 24 ), -1, 'Spin 12 (13 Black), bet 24 pays -1'; +is payout( 12, 25 ), -1, 'Spin 12 (13 Black), bet 25 pays -1'; +is payout( 12, 26 ), -1, 'Spin 12 (13 Black), bet 26 pays -1'; +is payout( 12, 27 ), -1, 'Spin 12 (13 Black), bet 27 pays -1'; +is payout( 12, 28 ), -1, 'Spin 12 (13 Black), bet 28 pays -1'; +is payout( 12, 29 ), -1, 'Spin 12 (13 Black), bet 29 pays -1'; +is payout( 12, 30 ), -1, 'Spin 12 (13 Black), bet 30 pays -1'; +is payout( 12, 31 ), -1, 'Spin 12 (13 Black), bet 31 pays -1'; +is payout( 12, 32 ), -1, 'Spin 12 (13 Black), bet 32 pays -1'; +is payout( 12, 33 ), -1, 'Spin 12 (13 Black), bet 33 pays -1'; +is payout( 12, 34 ), -1, 'Spin 12 (13 Black), bet 34 pays -1'; +is payout( 12, 35 ), -1, 'Spin 12 (13 Black), bet 35 pays -1'; +is payout( 12, 36 ), -1, 'Spin 12 (13 Black), bet 36 pays -1'; +is payout( 12, 37 ), -1, 'Spin 12 (13 Black), bet 37 pays -1'; +is payout( 12, 38 ), 2, 'Spin 12 (13 Black), bet 38 pays 2'; +is payout( 12, 39 ), -1, 'Spin 12 (13 Black), bet 39 pays -1'; +is payout( 12, 40 ), 2, 'Spin 12 (13 Black), bet 40 pays 2'; +is payout( 12, 41 ), -1, 'Spin 12 (13 Black), bet 41 pays -1'; +is payout( 12, 42 ), -1, 'Spin 12 (13 Black), bet 42 pays -1'; +is payout( 12, 43 ), 1, 'Spin 12 (13 Black), bet 43 pays 1'; +is payout( 12, 44 ), -1, 'Spin 12 (13 Black), bet 44 pays -1'; +is payout( 12, 45 ), -1, 'Spin 12 (13 Black), bet 45 pays -1'; +is payout( 12, 46 ), 1, 'Spin 12 (13 Black), bet 46 pays 1'; +is payout( 12, 47 ), -1, 'Spin 12 (13 Black), bet 47 pays -1'; +is payout( 12, 48 ), 1, 'Spin 12 (13 Black), bet 48 pays 1'; +is payout( 12, 49 ), -1, 'Spin 12 (13 Black), bet 49 pays -1'; +is payout( 12, 50 ), -1, 'Spin 12 (13 Black), bet 50 pays -1'; +is format_spin( 13 ), '14 Red', 'Spin 13 is 14 Red'; +is payout( 13, 1 ), -1, 'Spin 13 (14 Red), bet 1 pays -1'; +is payout( 13, 2 ), -1, 'Spin 13 (14 Red), bet 2 pays -1'; +is payout( 13, 3 ), -1, 'Spin 13 (14 Red), bet 3 pays -1'; +is payout( 13, 4 ), -1, 'Spin 13 (14 Red), bet 4 pays -1'; +is payout( 13, 5 ), -1, 'Spin 13 (14 Red), bet 5 pays -1'; +is payout( 13, 6 ), -1, 'Spin 13 (14 Red), bet 6 pays -1'; +is payout( 13, 7 ), -1, 'Spin 13 (14 Red), bet 7 pays -1'; +is payout( 13, 8 ), -1, 'Spin 13 (14 Red), bet 8 pays -1'; +is payout( 13, 9 ), -1, 'Spin 13 (14 Red), bet 9 pays -1'; +is payout( 13, 10 ), -1, 'Spin 13 (14 Red), bet 10 pays -1'; +is payout( 13, 11 ), -1, 'Spin 13 (14 Red), bet 11 pays -1'; +is payout( 13, 12 ), -1, 'Spin 13 (14 Red), bet 12 pays -1'; +is payout( 13, 13 ), -1, 'Spin 13 (14 Red), bet 13 pays -1'; +is payout( 13, 14 ), 35, 'Spin 13 (14 Red), bet 14 pays 35'; +is payout( 13, 15 ), -1, 'Spin 13 (14 Red), bet 15 pays -1'; +is payout( 13, 16 ), -1, 'Spin 13 (14 Red), bet 16 pays -1'; +is payout( 13, 17 ), -1, 'Spin 13 (14 Red), bet 17 pays -1'; +is payout( 13, 18 ), -1, 'Spin 13 (14 Red), bet 18 pays -1'; +is payout( 13, 19 ), -1, 'Spin 13 (14 Red), bet 19 pays -1'; +is payout( 13, 20 ), -1, 'Spin 13 (14 Red), bet 20 pays -1'; +is payout( 13, 21 ), -1, 'Spin 13 (14 Red), bet 21 pays -1'; +is payout( 13, 22 ), -1, 'Spin 13 (14 Red), bet 22 pays -1'; +is payout( 13, 23 ), -1, 'Spin 13 (14 Red), bet 23 pays -1'; +is payout( 13, 24 ), -1, 'Spin 13 (14 Red), bet 24 pays -1'; +is payout( 13, 25 ), -1, 'Spin 13 (14 Red), bet 25 pays -1'; +is payout( 13, 26 ), -1, 'Spin 13 (14 Red), bet 26 pays -1'; +is payout( 13, 27 ), -1, 'Spin 13 (14 Red), bet 27 pays -1'; +is payout( 13, 28 ), -1, 'Spin 13 (14 Red), bet 28 pays -1'; +is payout( 13, 29 ), -1, 'Spin 13 (14 Red), bet 29 pays -1'; +is payout( 13, 30 ), -1, 'Spin 13 (14 Red), bet 30 pays -1'; +is payout( 13, 31 ), -1, 'Spin 13 (14 Red), bet 31 pays -1'; +is payout( 13, 32 ), -1, 'Spin 13 (14 Red), bet 32 pays -1'; +is payout( 13, 33 ), -1, 'Spin 13 (14 Red), bet 33 pays -1'; +is payout( 13, 34 ), -1, 'Spin 13 (14 Red), bet 34 pays -1'; +is payout( 13, 35 ), -1, 'Spin 13 (14 Red), bet 35 pays -1'; +is payout( 13, 36 ), -1, 'Spin 13 (14 Red), bet 36 pays -1'; +is payout( 13, 37 ), -1, 'Spin 13 (14 Red), bet 37 pays -1'; +is payout( 13, 38 ), 2, 'Spin 13 (14 Red), bet 38 pays 2'; +is payout( 13, 39 ), -1, 'Spin 13 (14 Red), bet 39 pays -1'; +is payout( 13, 40 ), -1, 'Spin 13 (14 Red), bet 40 pays -1'; +is payout( 13, 41 ), 2, 'Spin 13 (14 Red), bet 41 pays 2'; +is payout( 13, 42 ), -1, 'Spin 13 (14 Red), bet 42 pays -1'; +is payout( 13, 43 ), 1, 'Spin 13 (14 Red), bet 43 pays 1'; +is payout( 13, 44 ), -1, 'Spin 13 (14 Red), bet 44 pays -1'; +is payout( 13, 45 ), 1, 'Spin 13 (14 Red), bet 45 pays 1'; +is payout( 13, 46 ), -1, 'Spin 13 (14 Red), bet 46 pays -1'; +is payout( 13, 47 ), 1, 'Spin 13 (14 Red), bet 47 pays 1'; +is payout( 13, 48 ), -1, 'Spin 13 (14 Red), bet 48 pays -1'; +is payout( 13, 49 ), -1, 'Spin 13 (14 Red), bet 49 pays -1'; +is payout( 13, 50 ), -1, 'Spin 13 (14 Red), bet 50 pays -1'; +is format_spin( 14 ), '15 Black', 'Spin 14 is 15 Black'; +is payout( 14, 1 ), -1, 'Spin 14 (15 Black), bet 1 pays -1'; +is payout( 14, 2 ), -1, 'Spin 14 (15 Black), bet 2 pays -1'; +is payout( 14, 3 ), -1, 'Spin 14 (15 Black), bet 3 pays -1'; +is payout( 14, 4 ), -1, 'Spin 14 (15 Black), bet 4 pays -1'; +is payout( 14, 5 ), -1, 'Spin 14 (15 Black), bet 5 pays -1'; +is payout( 14, 6 ), -1, 'Spin 14 (15 Black), bet 6 pays -1'; +is payout( 14, 7 ), -1, 'Spin 14 (15 Black), bet 7 pays -1'; +is payout( 14, 8 ), -1, 'Spin 14 (15 Black), bet 8 pays -1'; +is payout( 14, 9 ), -1, 'Spin 14 (15 Black), bet 9 pays -1'; +is payout( 14, 10 ), -1, 'Spin 14 (15 Black), bet 10 pays -1'; +is payout( 14, 11 ), -1, 'Spin 14 (15 Black), bet 11 pays -1'; +is payout( 14, 12 ), -1, 'Spin 14 (15 Black), bet 12 pays -1'; +is payout( 14, 13 ), -1, 'Spin 14 (15 Black), bet 13 pays -1'; +is payout( 14, 14 ), -1, 'Spin 14 (15 Black), bet 14 pays -1'; +is payout( 14, 15 ), 35, 'Spin 14 (15 Black), bet 15 pays 35'; +is payout( 14, 16 ), -1, 'Spin 14 (15 Black), bet 16 pays -1'; +is payout( 14, 17 ), -1, 'Spin 14 (15 Black), bet 17 pays -1'; +is payout( 14, 18 ), -1, 'Spin 14 (15 Black), bet 18 pays -1'; +is payout( 14, 19 ), -1, 'Spin 14 (15 Black), bet 19 pays -1'; +is payout( 14, 20 ), -1, 'Spin 14 (15 Black), bet 20 pays -1'; +is payout( 14, 21 ), -1, 'Spin 14 (15 Black), bet 21 pays -1'; +is payout( 14, 22 ), -1, 'Spin 14 (15 Black), bet 22 pays -1'; +is payout( 14, 23 ), -1, 'Spin 14 (15 Black), bet 23 pays -1'; +is payout( 14, 24 ), -1, 'Spin 14 (15 Black), bet 24 pays -1'; +is payout( 14, 25 ), -1, 'Spin 14 (15 Black), bet 25 pays -1'; +is payout( 14, 26 ), -1, 'Spin 14 (15 Black), bet 26 pays -1'; +is payout( 14, 27 ), -1, 'Spin 14 (15 Black), bet 27 pays -1'; +is payout( 14, 28 ), -1, 'Spin 14 (15 Black), bet 28 pays -1'; +is payout( 14, 29 ), -1, 'Spin 14 (15 Black), bet 29 pays -1'; +is payout( 14, 30 ), -1, 'Spin 14 (15 Black), bet 30 pays -1'; +is payout( 14, 31 ), -1, 'Spin 14 (15 Black), bet 31 pays -1'; +is payout( 14, 32 ), -1, 'Spin 14 (15 Black), bet 32 pays -1'; +is payout( 14, 33 ), -1, 'Spin 14 (15 Black), bet 33 pays -1'; +is payout( 14, 34 ), -1, 'Spin 14 (15 Black), bet 34 pays -1'; +is payout( 14, 35 ), -1, 'Spin 14 (15 Black), bet 35 pays -1'; +is payout( 14, 36 ), -1, 'Spin 14 (15 Black), bet 36 pays -1'; +is payout( 14, 37 ), -1, 'Spin 14 (15 Black), bet 37 pays -1'; +is payout( 14, 38 ), 2, 'Spin 14 (15 Black), bet 38 pays 2'; +is payout( 14, 39 ), -1, 'Spin 14 (15 Black), bet 39 pays -1'; +is payout( 14, 40 ), -1, 'Spin 14 (15 Black), bet 40 pays -1'; +is payout( 14, 41 ), -1, 'Spin 14 (15 Black), bet 41 pays -1'; +is payout( 14, 42 ), 2, 'Spin 14 (15 Black), bet 42 pays 2'; +is payout( 14, 43 ), 1, 'Spin 14 (15 Black), bet 43 pays 1'; +is payout( 14, 44 ), -1, 'Spin 14 (15 Black), bet 44 pays -1'; +is payout( 14, 45 ), -1, 'Spin 14 (15 Black), bet 45 pays -1'; +is payout( 14, 46 ), 1, 'Spin 14 (15 Black), bet 46 pays 1'; +is payout( 14, 47 ), -1, 'Spin 14 (15 Black), bet 47 pays -1'; +is payout( 14, 48 ), 1, 'Spin 14 (15 Black), bet 48 pays 1'; +is payout( 14, 49 ), -1, 'Spin 14 (15 Black), bet 49 pays -1'; +is payout( 14, 50 ), -1, 'Spin 14 (15 Black), bet 50 pays -1'; +is format_spin( 15 ), '16 Red', 'Spin 15 is 16 Red'; +is payout( 15, 1 ), -1, 'Spin 15 (16 Red), bet 1 pays -1'; +is payout( 15, 2 ), -1, 'Spin 15 (16 Red), bet 2 pays -1'; +is payout( 15, 3 ), -1, 'Spin 15 (16 Red), bet 3 pays -1'; +is payout( 15, 4 ), -1, 'Spin 15 (16 Red), bet 4 pays -1'; +is payout( 15, 5 ), -1, 'Spin 15 (16 Red), bet 5 pays -1'; +is payout( 15, 6 ), -1, 'Spin 15 (16 Red), bet 6 pays -1'; +is payout( 15, 7 ), -1, 'Spin 15 (16 Red), bet 7 pays -1'; +is payout( 15, 8 ), -1, 'Spin 15 (16 Red), bet 8 pays -1'; +is payout( 15, 9 ), -1, 'Spin 15 (16 Red), bet 9 pays -1'; +is payout( 15, 10 ), -1, 'Spin 15 (16 Red), bet 10 pays -1'; +is payout( 15, 11 ), -1, 'Spin 15 (16 Red), bet 11 pays -1'; +is payout( 15, 12 ), -1, 'Spin 15 (16 Red), bet 12 pays -1'; +is payout( 15, 13 ), -1, 'Spin 15 (16 Red), bet 13 pays -1'; +is payout( 15, 14 ), -1, 'Spin 15 (16 Red), bet 14 pays -1'; +is payout( 15, 15 ), -1, 'Spin 15 (16 Red), bet 15 pays -1'; +is payout( 15, 16 ), 35, 'Spin 15 (16 Red), bet 16 pays 35'; +is payout( 15, 17 ), -1, 'Spin 15 (16 Red), bet 17 pays -1'; +is payout( 15, 18 ), -1, 'Spin 15 (16 Red), bet 18 pays -1'; +is payout( 15, 19 ), -1, 'Spin 15 (16 Red), bet 19 pays -1'; +is payout( 15, 20 ), -1, 'Spin 15 (16 Red), bet 20 pays -1'; +is payout( 15, 21 ), -1, 'Spin 15 (16 Red), bet 21 pays -1'; +is payout( 15, 22 ), -1, 'Spin 15 (16 Red), bet 22 pays -1'; +is payout( 15, 23 ), -1, 'Spin 15 (16 Red), bet 23 pays -1'; +is payout( 15, 24 ), -1, 'Spin 15 (16 Red), bet 24 pays -1'; +is payout( 15, 25 ), -1, 'Spin 15 (16 Red), bet 25 pays -1'; +is payout( 15, 26 ), -1, 'Spin 15 (16 Red), bet 26 pays -1'; +is payout( 15, 27 ), -1, 'Spin 15 (16 Red), bet 27 pays -1'; +is payout( 15, 28 ), -1, 'Spin 15 (16 Red), bet 28 pays -1'; +is payout( 15, 29 ), -1, 'Spin 15 (16 Red), bet 29 pays -1'; +is payout( 15, 30 ), -1, 'Spin 15 (16 Red), bet 30 pays -1'; +is payout( 15, 31 ), -1, 'Spin 15 (16 Red), bet 31 pays -1'; +is payout( 15, 32 ), -1, 'Spin 15 (16 Red), bet 32 pays -1'; +is payout( 15, 33 ), -1, 'Spin 15 (16 Red), bet 33 pays -1'; +is payout( 15, 34 ), -1, 'Spin 15 (16 Red), bet 34 pays -1'; +is payout( 15, 35 ), -1, 'Spin 15 (16 Red), bet 35 pays -1'; +is payout( 15, 36 ), -1, 'Spin 15 (16 Red), bet 36 pays -1'; +is payout( 15, 37 ), -1, 'Spin 15 (16 Red), bet 37 pays -1'; +is payout( 15, 38 ), 2, 'Spin 15 (16 Red), bet 38 pays 2'; +is payout( 15, 39 ), -1, 'Spin 15 (16 Red), bet 39 pays -1'; +is payout( 15, 40 ), 2, 'Spin 15 (16 Red), bet 40 pays 2'; +is payout( 15, 41 ), -1, 'Spin 15 (16 Red), bet 41 pays -1'; +is payout( 15, 42 ), -1, 'Spin 15 (16 Red), bet 42 pays -1'; +is payout( 15, 43 ), 1, 'Spin 15 (16 Red), bet 43 pays 1'; +is payout( 15, 44 ), -1, 'Spin 15 (16 Red), bet 44 pays -1'; +is payout( 15, 45 ), 1, 'Spin 15 (16 Red), bet 45 pays 1'; +is payout( 15, 46 ), -1, 'Spin 15 (16 Red), bet 46 pays -1'; +is payout( 15, 47 ), 1, 'Spin 15 (16 Red), bet 47 pays 1'; +is payout( 15, 48 ), -1, 'Spin 15 (16 Red), bet 48 pays -1'; +is payout( 15, 49 ), -1, 'Spin 15 (16 Red), bet 49 pays -1'; +is payout( 15, 50 ), -1, 'Spin 15 (16 Red), bet 50 pays -1'; +is format_spin( 16 ), '17 Black', 'Spin 16 is 17 Black'; +is payout( 16, 1 ), -1, 'Spin 16 (17 Black), bet 1 pays -1'; +is payout( 16, 2 ), -1, 'Spin 16 (17 Black), bet 2 pays -1'; +is payout( 16, 3 ), -1, 'Spin 16 (17 Black), bet 3 pays -1'; +is payout( 16, 4 ), -1, 'Spin 16 (17 Black), bet 4 pays -1'; +is payout( 16, 5 ), -1, 'Spin 16 (17 Black), bet 5 pays -1'; +is payout( 16, 6 ), -1, 'Spin 16 (17 Black), bet 6 pays -1'; +is payout( 16, 7 ), -1, 'Spin 16 (17 Black), bet 7 pays -1'; +is payout( 16, 8 ), -1, 'Spin 16 (17 Black), bet 8 pays -1'; +is payout( 16, 9 ), -1, 'Spin 16 (17 Black), bet 9 pays -1'; +is payout( 16, 10 ), -1, 'Spin 16 (17 Black), bet 10 pays -1'; +is payout( 16, 11 ), -1, 'Spin 16 (17 Black), bet 11 pays -1'; +is payout( 16, 12 ), -1, 'Spin 16 (17 Black), bet 12 pays -1'; +is payout( 16, 13 ), -1, 'Spin 16 (17 Black), bet 13 pays -1'; +is payout( 16, 14 ), -1, 'Spin 16 (17 Black), bet 14 pays -1'; +is payout( 16, 15 ), -1, 'Spin 16 (17 Black), bet 15 pays -1'; +is payout( 16, 16 ), -1, 'Spin 16 (17 Black), bet 16 pays -1'; +is payout( 16, 17 ), 35, 'Spin 16 (17 Black), bet 17 pays 35'; +is payout( 16, 18 ), -1, 'Spin 16 (17 Black), bet 18 pays -1'; +is payout( 16, 19 ), -1, 'Spin 16 (17 Black), bet 19 pays -1'; +is payout( 16, 20 ), -1, 'Spin 16 (17 Black), bet 20 pays -1'; +is payout( 16, 21 ), -1, 'Spin 16 (17 Black), bet 21 pays -1'; +is payout( 16, 22 ), -1, 'Spin 16 (17 Black), bet 22 pays -1'; +is payout( 16, 23 ), -1, 'Spin 16 (17 Black), bet 23 pays -1'; +is payout( 16, 24 ), -1, 'Spin 16 (17 Black), bet 24 pays -1'; +is payout( 16, 25 ), -1, 'Spin 16 (17 Black), bet 25 pays -1'; +is payout( 16, 26 ), -1, 'Spin 16 (17 Black), bet 26 pays -1'; +is payout( 16, 27 ), -1, 'Spin 16 (17 Black), bet 27 pays -1'; +is payout( 16, 28 ), -1, 'Spin 16 (17 Black), bet 28 pays -1'; +is payout( 16, 29 ), -1, 'Spin 16 (17 Black), bet 29 pays -1'; +is payout( 16, 30 ), -1, 'Spin 16 (17 Black), bet 30 pays -1'; +is payout( 16, 31 ), -1, 'Spin 16 (17 Black), bet 31 pays -1'; +is payout( 16, 32 ), -1, 'Spin 16 (17 Black), bet 32 pays -1'; +is payout( 16, 33 ), -1, 'Spin 16 (17 Black), bet 33 pays -1'; +is payout( 16, 34 ), -1, 'Spin 16 (17 Black), bet 34 pays -1'; +is payout( 16, 35 ), -1, 'Spin 16 (17 Black), bet 35 pays -1'; +is payout( 16, 36 ), -1, 'Spin 16 (17 Black), bet 36 pays -1'; +is payout( 16, 37 ), -1, 'Spin 16 (17 Black), bet 37 pays -1'; +is payout( 16, 38 ), 2, 'Spin 16 (17 Black), bet 38 pays 2'; +is payout( 16, 39 ), -1, 'Spin 16 (17 Black), bet 39 pays -1'; +is payout( 16, 40 ), -1, 'Spin 16 (17 Black), bet 40 pays -1'; +is payout( 16, 41 ), 2, 'Spin 16 (17 Black), bet 41 pays 2'; +is payout( 16, 42 ), -1, 'Spin 16 (17 Black), bet 42 pays -1'; +is payout( 16, 43 ), 1, 'Spin 16 (17 Black), bet 43 pays 1'; +is payout( 16, 44 ), -1, 'Spin 16 (17 Black), bet 44 pays -1'; +is payout( 16, 45 ), -1, 'Spin 16 (17 Black), bet 45 pays -1'; +is payout( 16, 46 ), 1, 'Spin 16 (17 Black), bet 46 pays 1'; +is payout( 16, 47 ), -1, 'Spin 16 (17 Black), bet 47 pays -1'; +is payout( 16, 48 ), 1, 'Spin 16 (17 Black), bet 48 pays 1'; +is payout( 16, 49 ), -1, 'Spin 16 (17 Black), bet 49 pays -1'; +is payout( 16, 50 ), -1, 'Spin 16 (17 Black), bet 50 pays -1'; +is format_spin( 17 ), '18 Red', 'Spin 17 is 18 Red'; +is payout( 17, 1 ), -1, 'Spin 17 (18 Red), bet 1 pays -1'; +is payout( 17, 2 ), -1, 'Spin 17 (18 Red), bet 2 pays -1'; +is payout( 17, 3 ), -1, 'Spin 17 (18 Red), bet 3 pays -1'; +is payout( 17, 4 ), -1, 'Spin 17 (18 Red), bet 4 pays -1'; +is payout( 17, 5 ), -1, 'Spin 17 (18 Red), bet 5 pays -1'; +is payout( 17, 6 ), -1, 'Spin 17 (18 Red), bet 6 pays -1'; +is payout( 17, 7 ), -1, 'Spin 17 (18 Red), bet 7 pays -1'; +is payout( 17, 8 ), -1, 'Spin 17 (18 Red), bet 8 pays -1'; +is payout( 17, 9 ), -1, 'Spin 17 (18 Red), bet 9 pays -1'; +is payout( 17, 10 ), -1, 'Spin 17 (18 Red), bet 10 pays -1'; +is payout( 17, 11 ), -1, 'Spin 17 (18 Red), bet 11 pays -1'; +is payout( 17, 12 ), -1, 'Spin 17 (18 Red), bet 12 pays -1'; +is payout( 17, 13 ), -1, 'Spin 17 (18 Red), bet 13 pays -1'; +is payout( 17, 14 ), -1, 'Spin 17 (18 Red), bet 14 pays -1'; +is payout( 17, 15 ), -1, 'Spin 17 (18 Red), bet 15 pays -1'; +is payout( 17, 16 ), -1, 'Spin 17 (18 Red), bet 16 pays -1'; +is payout( 17, 17 ), -1, 'Spin 17 (18 Red), bet 17 pays -1'; +is payout( 17, 18 ), 35, 'Spin 17 (18 Red), bet 18 pays 35'; +is payout( 17, 19 ), -1, 'Spin 17 (18 Red), bet 19 pays -1'; +is payout( 17, 20 ), -1, 'Spin 17 (18 Red), bet 20 pays -1'; +is payout( 17, 21 ), -1, 'Spin 17 (18 Red), bet 21 pays -1'; +is payout( 17, 22 ), -1, 'Spin 17 (18 Red), bet 22 pays -1'; +is payout( 17, 23 ), -1, 'Spin 17 (18 Red), bet 23 pays -1'; +is payout( 17, 24 ), -1, 'Spin 17 (18 Red), bet 24 pays -1'; +is payout( 17, 25 ), -1, 'Spin 17 (18 Red), bet 25 pays -1'; +is payout( 17, 26 ), -1, 'Spin 17 (18 Red), bet 26 pays -1'; +is payout( 17, 27 ), -1, 'Spin 17 (18 Red), bet 27 pays -1'; +is payout( 17, 28 ), -1, 'Spin 17 (18 Red), bet 28 pays -1'; +is payout( 17, 29 ), -1, 'Spin 17 (18 Red), bet 29 pays -1'; +is payout( 17, 30 ), -1, 'Spin 17 (18 Red), bet 30 pays -1'; +is payout( 17, 31 ), -1, 'Spin 17 (18 Red), bet 31 pays -1'; +is payout( 17, 32 ), -1, 'Spin 17 (18 Red), bet 32 pays -1'; +is payout( 17, 33 ), -1, 'Spin 17 (18 Red), bet 33 pays -1'; +is payout( 17, 34 ), -1, 'Spin 17 (18 Red), bet 34 pays -1'; +is payout( 17, 35 ), -1, 'Spin 17 (18 Red), bet 35 pays -1'; +is payout( 17, 36 ), -1, 'Spin 17 (18 Red), bet 36 pays -1'; +is payout( 17, 37 ), -1, 'Spin 17 (18 Red), bet 37 pays -1'; +is payout( 17, 38 ), 2, 'Spin 17 (18 Red), bet 38 pays 2'; +is payout( 17, 39 ), -1, 'Spin 17 (18 Red), bet 39 pays -1'; +is payout( 17, 40 ), -1, 'Spin 17 (18 Red), bet 40 pays -1'; +is payout( 17, 41 ), -1, 'Spin 17 (18 Red), bet 41 pays -1'; +is payout( 17, 42 ), 2, 'Spin 17 (18 Red), bet 42 pays 2'; +is payout( 17, 43 ), 1, 'Spin 17 (18 Red), bet 43 pays 1'; +is payout( 17, 44 ), -1, 'Spin 17 (18 Red), bet 44 pays -1'; +is payout( 17, 45 ), 1, 'Spin 17 (18 Red), bet 45 pays 1'; +is payout( 17, 46 ), -1, 'Spin 17 (18 Red), bet 46 pays -1'; +is payout( 17, 47 ), 1, 'Spin 17 (18 Red), bet 47 pays 1'; +is payout( 17, 48 ), -1, 'Spin 17 (18 Red), bet 48 pays -1'; +is payout( 17, 49 ), -1, 'Spin 17 (18 Red), bet 49 pays -1'; +is payout( 17, 50 ), -1, 'Spin 17 (18 Red), bet 50 pays -1'; +is format_spin( 18 ), '19 Red', 'Spin 18 is 19 Red'; +is payout( 18, 1 ), -1, 'Spin 18 (19 Red), bet 1 pays -1'; +is payout( 18, 2 ), -1, 'Spin 18 (19 Red), bet 2 pays -1'; +is payout( 18, 3 ), -1, 'Spin 18 (19 Red), bet 3 pays -1'; +is payout( 18, 4 ), -1, 'Spin 18 (19 Red), bet 4 pays -1'; +is payout( 18, 5 ), -1, 'Spin 18 (19 Red), bet 5 pays -1'; +is payout( 18, 6 ), -1, 'Spin 18 (19 Red), bet 6 pays -1'; +is payout( 18, 7 ), -1, 'Spin 18 (19 Red), bet 7 pays -1'; +is payout( 18, 8 ), -1, 'Spin 18 (19 Red), bet 8 pays -1'; +is payout( 18, 9 ), -1, 'Spin 18 (19 Red), bet 9 pays -1'; +is payout( 18, 10 ), -1, 'Spin 18 (19 Red), bet 10 pays -1'; +is payout( 18, 11 ), -1, 'Spin 18 (19 Red), bet 11 pays -1'; +is payout( 18, 12 ), -1, 'Spin 18 (19 Red), bet 12 pays -1'; +is payout( 18, 13 ), -1, 'Spin 18 (19 Red), bet 13 pays -1'; +is payout( 18, 14 ), -1, 'Spin 18 (19 Red), bet 14 pays -1'; +is payout( 18, 15 ), -1, 'Spin 18 (19 Red), bet 15 pays -1'; +is payout( 18, 16 ), -1, 'Spin 18 (19 Red), bet 16 pays -1'; +is payout( 18, 17 ), -1, 'Spin 18 (19 Red), bet 17 pays -1'; +is payout( 18, 18 ), -1, 'Spin 18 (19 Red), bet 18 pays -1'; +is payout( 18, 19 ), 35, 'Spin 18 (19 Red), bet 19 pays 35'; +is payout( 18, 20 ), -1, 'Spin 18 (19 Red), bet 20 pays -1'; +is payout( 18, 21 ), -1, 'Spin 18 (19 Red), bet 21 pays -1'; +is payout( 18, 22 ), -1, 'Spin 18 (19 Red), bet 22 pays -1'; +is payout( 18, 23 ), -1, 'Spin 18 (19 Red), bet 23 pays -1'; +is payout( 18, 24 ), -1, 'Spin 18 (19 Red), bet 24 pays -1'; +is payout( 18, 25 ), -1, 'Spin 18 (19 Red), bet 25 pays -1'; +is payout( 18, 26 ), -1, 'Spin 18 (19 Red), bet 26 pays -1'; +is payout( 18, 27 ), -1, 'Spin 18 (19 Red), bet 27 pays -1'; +is payout( 18, 28 ), -1, 'Spin 18 (19 Red), bet 28 pays -1'; +is payout( 18, 29 ), -1, 'Spin 18 (19 Red), bet 29 pays -1'; +is payout( 18, 30 ), -1, 'Spin 18 (19 Red), bet 30 pays -1'; +is payout( 18, 31 ), -1, 'Spin 18 (19 Red), bet 31 pays -1'; +is payout( 18, 32 ), -1, 'Spin 18 (19 Red), bet 32 pays -1'; +is payout( 18, 33 ), -1, 'Spin 18 (19 Red), bet 33 pays -1'; +is payout( 18, 34 ), -1, 'Spin 18 (19 Red), bet 34 pays -1'; +is payout( 18, 35 ), -1, 'Spin 18 (19 Red), bet 35 pays -1'; +is payout( 18, 36 ), -1, 'Spin 18 (19 Red), bet 36 pays -1'; +is payout( 18, 37 ), -1, 'Spin 18 (19 Red), bet 37 pays -1'; +is payout( 18, 38 ), 2, 'Spin 18 (19 Red), bet 38 pays 2'; +is payout( 18, 39 ), -1, 'Spin 18 (19 Red), bet 39 pays -1'; +is payout( 18, 40 ), 2, 'Spin 18 (19 Red), bet 40 pays 2'; +is payout( 18, 41 ), -1, 'Spin 18 (19 Red), bet 41 pays -1'; +is payout( 18, 42 ), -1, 'Spin 18 (19 Red), bet 42 pays -1'; +is payout( 18, 43 ), -1, 'Spin 18 (19 Red), bet 43 pays -1'; +is payout( 18, 44 ), 1, 'Spin 18 (19 Red), bet 44 pays 1'; +is payout( 18, 45 ), -1, 'Spin 18 (19 Red), bet 45 pays -1'; +is payout( 18, 46 ), 1, 'Spin 18 (19 Red), bet 46 pays 1'; +is payout( 18, 47 ), 1, 'Spin 18 (19 Red), bet 47 pays 1'; +is payout( 18, 48 ), -1, 'Spin 18 (19 Red), bet 48 pays -1'; +is payout( 18, 49 ), -1, 'Spin 18 (19 Red), bet 49 pays -1'; +is payout( 18, 50 ), -1, 'Spin 18 (19 Red), bet 50 pays -1'; +is format_spin( 19 ), '20 Black', 'Spin 19 is 20 Black'; +is payout( 19, 1 ), -1, 'Spin 19 (20 Black), bet 1 pays -1'; +is payout( 19, 2 ), -1, 'Spin 19 (20 Black), bet 2 pays -1'; +is payout( 19, 3 ), -1, 'Spin 19 (20 Black), bet 3 pays -1'; +is payout( 19, 4 ), -1, 'Spin 19 (20 Black), bet 4 pays -1'; +is payout( 19, 5 ), -1, 'Spin 19 (20 Black), bet 5 pays -1'; +is payout( 19, 6 ), -1, 'Spin 19 (20 Black), bet 6 pays -1'; +is payout( 19, 7 ), -1, 'Spin 19 (20 Black), bet 7 pays -1'; +is payout( 19, 8 ), -1, 'Spin 19 (20 Black), bet 8 pays -1'; +is payout( 19, 9 ), -1, 'Spin 19 (20 Black), bet 9 pays -1'; +is payout( 19, 10 ), -1, 'Spin 19 (20 Black), bet 10 pays -1'; +is payout( 19, 11 ), -1, 'Spin 19 (20 Black), bet 11 pays -1'; +is payout( 19, 12 ), -1, 'Spin 19 (20 Black), bet 12 pays -1'; +is payout( 19, 13 ), -1, 'Spin 19 (20 Black), bet 13 pays -1'; +is payout( 19, 14 ), -1, 'Spin 19 (20 Black), bet 14 pays -1'; +is payout( 19, 15 ), -1, 'Spin 19 (20 Black), bet 15 pays -1'; +is payout( 19, 16 ), -1, 'Spin 19 (20 Black), bet 16 pays -1'; +is payout( 19, 17 ), -1, 'Spin 19 (20 Black), bet 17 pays -1'; +is payout( 19, 18 ), -1, 'Spin 19 (20 Black), bet 18 pays -1'; +is payout( 19, 19 ), -1, 'Spin 19 (20 Black), bet 19 pays -1'; +is payout( 19, 20 ), 35, 'Spin 19 (20 Black), bet 20 pays 35'; +is payout( 19, 21 ), -1, 'Spin 19 (20 Black), bet 21 pays -1'; +is payout( 19, 22 ), -1, 'Spin 19 (20 Black), bet 22 pays -1'; +is payout( 19, 23 ), -1, 'Spin 19 (20 Black), bet 23 pays -1'; +is payout( 19, 24 ), -1, 'Spin 19 (20 Black), bet 24 pays -1'; +is payout( 19, 25 ), -1, 'Spin 19 (20 Black), bet 25 pays -1'; +is payout( 19, 26 ), -1, 'Spin 19 (20 Black), bet 26 pays -1'; +is payout( 19, 27 ), -1, 'Spin 19 (20 Black), bet 27 pays -1'; +is payout( 19, 28 ), -1, 'Spin 19 (20 Black), bet 28 pays -1'; +is payout( 19, 29 ), -1, 'Spin 19 (20 Black), bet 29 pays -1'; +is payout( 19, 30 ), -1, 'Spin 19 (20 Black), bet 30 pays -1'; +is payout( 19, 31 ), -1, 'Spin 19 (20 Black), bet 31 pays -1'; +is payout( 19, 32 ), -1, 'Spin 19 (20 Black), bet 32 pays -1'; +is payout( 19, 33 ), -1, 'Spin 19 (20 Black), bet 33 pays -1'; +is payout( 19, 34 ), -1, 'Spin 19 (20 Black), bet 34 pays -1'; +is payout( 19, 35 ), -1, 'Spin 19 (20 Black), bet 35 pays -1'; +is payout( 19, 36 ), -1, 'Spin 19 (20 Black), bet 36 pays -1'; +is payout( 19, 37 ), -1, 'Spin 19 (20 Black), bet 37 pays -1'; +is payout( 19, 38 ), 2, 'Spin 19 (20 Black), bet 38 pays 2'; +is payout( 19, 39 ), -1, 'Spin 19 (20 Black), bet 39 pays -1'; +is payout( 19, 40 ), -1, 'Spin 19 (20 Black), bet 40 pays -1'; +is payout( 19, 41 ), 2, 'Spin 19 (20 Black), bet 41 pays 2'; +is payout( 19, 42 ), -1, 'Spin 19 (20 Black), bet 42 pays -1'; +is payout( 19, 43 ), -1, 'Spin 19 (20 Black), bet 43 pays -1'; +is payout( 19, 44 ), 1, 'Spin 19 (20 Black), bet 44 pays 1'; +is payout( 19, 45 ), 1, 'Spin 19 (20 Black), bet 45 pays 1'; +is payout( 19, 46 ), -1, 'Spin 19 (20 Black), bet 46 pays -1'; +is payout( 19, 47 ), -1, 'Spin 19 (20 Black), bet 47 pays -1'; +is payout( 19, 48 ), 1, 'Spin 19 (20 Black), bet 48 pays 1'; +is payout( 19, 49 ), -1, 'Spin 19 (20 Black), bet 49 pays -1'; +is payout( 19, 50 ), -1, 'Spin 19 (20 Black), bet 50 pays -1'; +is format_spin( 20 ), '21 Red', 'Spin 20 is 21 Red'; +is payout( 20, 1 ), -1, 'Spin 20 (21 Red), bet 1 pays -1'; +is payout( 20, 2 ), -1, 'Spin 20 (21 Red), bet 2 pays -1'; +is payout( 20, 3 ), -1, 'Spin 20 (21 Red), bet 3 pays -1'; +is payout( 20, 4 ), -1, 'Spin 20 (21 Red), bet 4 pays -1'; +is payout( 20, 5 ), -1, 'Spin 20 (21 Red), bet 5 pays -1'; +is payout( 20, 6 ), -1, 'Spin 20 (21 Red), bet 6 pays -1'; +is payout( 20, 7 ), -1, 'Spin 20 (21 Red), bet 7 pays -1'; +is payout( 20, 8 ), -1, 'Spin 20 (21 Red), bet 8 pays -1'; +is payout( 20, 9 ), -1, 'Spin 20 (21 Red), bet 9 pays -1'; +is payout( 20, 10 ), -1, 'Spin 20 (21 Red), bet 10 pays -1'; +is payout( 20, 11 ), -1, 'Spin 20 (21 Red), bet 11 pays -1'; +is payout( 20, 12 ), -1, 'Spin 20 (21 Red), bet 12 pays -1'; +is payout( 20, 13 ), -1, 'Spin 20 (21 Red), bet 13 pays -1'; +is payout( 20, 14 ), -1, 'Spin 20 (21 Red), bet 14 pays -1'; +is payout( 20, 15 ), -1, 'Spin 20 (21 Red), bet 15 pays -1'; +is payout( 20, 16 ), -1, 'Spin 20 (21 Red), bet 16 pays -1'; +is payout( 20, 17 ), -1, 'Spin 20 (21 Red), bet 17 pays -1'; +is payout( 20, 18 ), -1, 'Spin 20 (21 Red), bet 18 pays -1'; +is payout( 20, 19 ), -1, 'Spin 20 (21 Red), bet 19 pays -1'; +is payout( 20, 20 ), -1, 'Spin 20 (21 Red), bet 20 pays -1'; +is payout( 20, 21 ), 35, 'Spin 20 (21 Red), bet 21 pays 35'; +is payout( 20, 22 ), -1, 'Spin 20 (21 Red), bet 22 pays -1'; +is payout( 20, 23 ), -1, 'Spin 20 (21 Red), bet 23 pays -1'; +is payout( 20, 24 ), -1, 'Spin 20 (21 Red), bet 24 pays -1'; +is payout( 20, 25 ), -1, 'Spin 20 (21 Red), bet 25 pays -1'; +is payout( 20, 26 ), -1, 'Spin 20 (21 Red), bet 26 pays -1'; +is payout( 20, 27 ), -1, 'Spin 20 (21 Red), bet 27 pays -1'; +is payout( 20, 28 ), -1, 'Spin 20 (21 Red), bet 28 pays -1'; +is payout( 20, 29 ), -1, 'Spin 20 (21 Red), bet 29 pays -1'; +is payout( 20, 30 ), -1, 'Spin 20 (21 Red), bet 30 pays -1'; +is payout( 20, 31 ), -1, 'Spin 20 (21 Red), bet 31 pays -1'; +is payout( 20, 32 ), -1, 'Spin 20 (21 Red), bet 32 pays -1'; +is payout( 20, 33 ), -1, 'Spin 20 (21 Red), bet 33 pays -1'; +is payout( 20, 34 ), -1, 'Spin 20 (21 Red), bet 34 pays -1'; +is payout( 20, 35 ), -1, 'Spin 20 (21 Red), bet 35 pays -1'; +is payout( 20, 36 ), -1, 'Spin 20 (21 Red), bet 36 pays -1'; +is payout( 20, 37 ), -1, 'Spin 20 (21 Red), bet 37 pays -1'; +is payout( 20, 38 ), 2, 'Spin 20 (21 Red), bet 38 pays 2'; +is payout( 20, 39 ), -1, 'Spin 20 (21 Red), bet 39 pays -1'; +is payout( 20, 40 ), -1, 'Spin 20 (21 Red), bet 40 pays -1'; +is payout( 20, 41 ), -1, 'Spin 20 (21 Red), bet 41 pays -1'; +is payout( 20, 42 ), 2, 'Spin 20 (21 Red), bet 42 pays 2'; +is payout( 20, 43 ), -1, 'Spin 20 (21 Red), bet 43 pays -1'; +is payout( 20, 44 ), 1, 'Spin 20 (21 Red), bet 44 pays 1'; +is payout( 20, 45 ), -1, 'Spin 20 (21 Red), bet 45 pays -1'; +is payout( 20, 46 ), 1, 'Spin 20 (21 Red), bet 46 pays 1'; +is payout( 20, 47 ), 1, 'Spin 20 (21 Red), bet 47 pays 1'; +is payout( 20, 48 ), -1, 'Spin 20 (21 Red), bet 48 pays -1'; +is payout( 20, 49 ), -1, 'Spin 20 (21 Red), bet 49 pays -1'; +is payout( 20, 50 ), -1, 'Spin 20 (21 Red), bet 50 pays -1'; +is format_spin( 21 ), '22 Black', 'Spin 21 is 22 Black'; +is payout( 21, 1 ), -1, 'Spin 21 (22 Black), bet 1 pays -1'; +is payout( 21, 2 ), -1, 'Spin 21 (22 Black), bet 2 pays -1'; +is payout( 21, 3 ), -1, 'Spin 21 (22 Black), bet 3 pays -1'; +is payout( 21, 4 ), -1, 'Spin 21 (22 Black), bet 4 pays -1'; +is payout( 21, 5 ), -1, 'Spin 21 (22 Black), bet 5 pays -1'; +is payout( 21, 6 ), -1, 'Spin 21 (22 Black), bet 6 pays -1'; +is payout( 21, 7 ), -1, 'Spin 21 (22 Black), bet 7 pays -1'; +is payout( 21, 8 ), -1, 'Spin 21 (22 Black), bet 8 pays -1'; +is payout( 21, 9 ), -1, 'Spin 21 (22 Black), bet 9 pays -1'; +is payout( 21, 10 ), -1, 'Spin 21 (22 Black), bet 10 pays -1'; +is payout( 21, 11 ), -1, 'Spin 21 (22 Black), bet 11 pays -1'; +is payout( 21, 12 ), -1, 'Spin 21 (22 Black), bet 12 pays -1'; +is payout( 21, 13 ), -1, 'Spin 21 (22 Black), bet 13 pays -1'; +is payout( 21, 14 ), -1, 'Spin 21 (22 Black), bet 14 pays -1'; +is payout( 21, 15 ), -1, 'Spin 21 (22 Black), bet 15 pays -1'; +is payout( 21, 16 ), -1, 'Spin 21 (22 Black), bet 16 pays -1'; +is payout( 21, 17 ), -1, 'Spin 21 (22 Black), bet 17 pays -1'; +is payout( 21, 18 ), -1, 'Spin 21 (22 Black), bet 18 pays -1'; +is payout( 21, 19 ), -1, 'Spin 21 (22 Black), bet 19 pays -1'; +is payout( 21, 20 ), -1, 'Spin 21 (22 Black), bet 20 pays -1'; +is payout( 21, 21 ), -1, 'Spin 21 (22 Black), bet 21 pays -1'; +is payout( 21, 22 ), 35, 'Spin 21 (22 Black), bet 22 pays 35'; +is payout( 21, 23 ), -1, 'Spin 21 (22 Black), bet 23 pays -1'; +is payout( 21, 24 ), -1, 'Spin 21 (22 Black), bet 24 pays -1'; +is payout( 21, 25 ), -1, 'Spin 21 (22 Black), bet 25 pays -1'; +is payout( 21, 26 ), -1, 'Spin 21 (22 Black), bet 26 pays -1'; +is payout( 21, 27 ), -1, 'Spin 21 (22 Black), bet 27 pays -1'; +is payout( 21, 28 ), -1, 'Spin 21 (22 Black), bet 28 pays -1'; +is payout( 21, 29 ), -1, 'Spin 21 (22 Black), bet 29 pays -1'; +is payout( 21, 30 ), -1, 'Spin 21 (22 Black), bet 30 pays -1'; +is payout( 21, 31 ), -1, 'Spin 21 (22 Black), bet 31 pays -1'; +is payout( 21, 32 ), -1, 'Spin 21 (22 Black), bet 32 pays -1'; +is payout( 21, 33 ), -1, 'Spin 21 (22 Black), bet 33 pays -1'; +is payout( 21, 34 ), -1, 'Spin 21 (22 Black), bet 34 pays -1'; +is payout( 21, 35 ), -1, 'Spin 21 (22 Black), bet 35 pays -1'; +is payout( 21, 36 ), -1, 'Spin 21 (22 Black), bet 36 pays -1'; +is payout( 21, 37 ), -1, 'Spin 21 (22 Black), bet 37 pays -1'; +is payout( 21, 38 ), 2, 'Spin 21 (22 Black), bet 38 pays 2'; +is payout( 21, 39 ), -1, 'Spin 21 (22 Black), bet 39 pays -1'; +is payout( 21, 40 ), 2, 'Spin 21 (22 Black), bet 40 pays 2'; +is payout( 21, 41 ), -1, 'Spin 21 (22 Black), bet 41 pays -1'; +is payout( 21, 42 ), -1, 'Spin 21 (22 Black), bet 42 pays -1'; +is payout( 21, 43 ), -1, 'Spin 21 (22 Black), bet 43 pays -1'; +is payout( 21, 44 ), 1, 'Spin 21 (22 Black), bet 44 pays 1'; +is payout( 21, 45 ), 1, 'Spin 21 (22 Black), bet 45 pays 1'; +is payout( 21, 46 ), -1, 'Spin 21 (22 Black), bet 46 pays -1'; +is payout( 21, 47 ), -1, 'Spin 21 (22 Black), bet 47 pays -1'; +is payout( 21, 48 ), 1, 'Spin 21 (22 Black), bet 48 pays 1'; +is payout( 21, 49 ), -1, 'Spin 21 (22 Black), bet 49 pays -1'; +is payout( 21, 50 ), -1, 'Spin 21 (22 Black), bet 50 pays -1'; +is format_spin( 22 ), '23 Red', 'Spin 22 is 23 Red'; +is payout( 22, 1 ), -1, 'Spin 22 (23 Red), bet 1 pays -1'; +is payout( 22, 2 ), -1, 'Spin 22 (23 Red), bet 2 pays -1'; +is payout( 22, 3 ), -1, 'Spin 22 (23 Red), bet 3 pays -1'; +is payout( 22, 4 ), -1, 'Spin 22 (23 Red), bet 4 pays -1'; +is payout( 22, 5 ), -1, 'Spin 22 (23 Red), bet 5 pays -1'; +is payout( 22, 6 ), -1, 'Spin 22 (23 Red), bet 6 pays -1'; +is payout( 22, 7 ), -1, 'Spin 22 (23 Red), bet 7 pays -1'; +is payout( 22, 8 ), -1, 'Spin 22 (23 Red), bet 8 pays -1'; +is payout( 22, 9 ), -1, 'Spin 22 (23 Red), bet 9 pays -1'; +is payout( 22, 10 ), -1, 'Spin 22 (23 Red), bet 10 pays -1'; +is payout( 22, 11 ), -1, 'Spin 22 (23 Red), bet 11 pays -1'; +is payout( 22, 12 ), -1, 'Spin 22 (23 Red), bet 12 pays -1'; +is payout( 22, 13 ), -1, 'Spin 22 (23 Red), bet 13 pays -1'; +is payout( 22, 14 ), -1, 'Spin 22 (23 Red), bet 14 pays -1'; +is payout( 22, 15 ), -1, 'Spin 22 (23 Red), bet 15 pays -1'; +is payout( 22, 16 ), -1, 'Spin 22 (23 Red), bet 16 pays -1'; +is payout( 22, 17 ), -1, 'Spin 22 (23 Red), bet 17 pays -1'; +is payout( 22, 18 ), -1, 'Spin 22 (23 Red), bet 18 pays -1'; +is payout( 22, 19 ), -1, 'Spin 22 (23 Red), bet 19 pays -1'; +is payout( 22, 20 ), -1, 'Spin 22 (23 Red), bet 20 pays -1'; +is payout( 22, 21 ), -1, 'Spin 22 (23 Red), bet 21 pays -1'; +is payout( 22, 22 ), -1, 'Spin 22 (23 Red), bet 22 pays -1'; +is payout( 22, 23 ), 35, 'Spin 22 (23 Red), bet 23 pays 35'; +is payout( 22, 24 ), -1, 'Spin 22 (23 Red), bet 24 pays -1'; +is payout( 22, 25 ), -1, 'Spin 22 (23 Red), bet 25 pays -1'; +is payout( 22, 26 ), -1, 'Spin 22 (23 Red), bet 26 pays -1'; +is payout( 22, 27 ), -1, 'Spin 22 (23 Red), bet 27 pays -1'; +is payout( 22, 28 ), -1, 'Spin 22 (23 Red), bet 28 pays -1'; +is payout( 22, 29 ), -1, 'Spin 22 (23 Red), bet 29 pays -1'; +is payout( 22, 30 ), -1, 'Spin 22 (23 Red), bet 30 pays -1'; +is payout( 22, 31 ), -1, 'Spin 22 (23 Red), bet 31 pays -1'; +is payout( 22, 32 ), -1, 'Spin 22 (23 Red), bet 32 pays -1'; +is payout( 22, 33 ), -1, 'Spin 22 (23 Red), bet 33 pays -1'; +is payout( 22, 34 ), -1, 'Spin 22 (23 Red), bet 34 pays -1'; +is payout( 22, 35 ), -1, 'Spin 22 (23 Red), bet 35 pays -1'; +is payout( 22, 36 ), -1, 'Spin 22 (23 Red), bet 36 pays -1'; +is payout( 22, 37 ), -1, 'Spin 22 (23 Red), bet 37 pays -1'; +is payout( 22, 38 ), 2, 'Spin 22 (23 Red), bet 38 pays 2'; +is payout( 22, 39 ), -1, 'Spin 22 (23 Red), bet 39 pays -1'; +is payout( 22, 40 ), -1, 'Spin 22 (23 Red), bet 40 pays -1'; +is payout( 22, 41 ), 2, 'Spin 22 (23 Red), bet 41 pays 2'; +is payout( 22, 42 ), -1, 'Spin 22 (23 Red), bet 42 pays -1'; +is payout( 22, 43 ), -1, 'Spin 22 (23 Red), bet 43 pays -1'; +is payout( 22, 44 ), 1, 'Spin 22 (23 Red), bet 44 pays 1'; +is payout( 22, 45 ), -1, 'Spin 22 (23 Red), bet 45 pays -1'; +is payout( 22, 46 ), 1, 'Spin 22 (23 Red), bet 46 pays 1'; +is payout( 22, 47 ), 1, 'Spin 22 (23 Red), bet 47 pays 1'; +is payout( 22, 48 ), -1, 'Spin 22 (23 Red), bet 48 pays -1'; +is payout( 22, 49 ), -1, 'Spin 22 (23 Red), bet 49 pays -1'; +is payout( 22, 50 ), -1, 'Spin 22 (23 Red), bet 50 pays -1'; +is format_spin( 23 ), '24 Black', 'Spin 23 is 24 Black'; +is payout( 23, 1 ), -1, 'Spin 23 (24 Black), bet 1 pays -1'; +is payout( 23, 2 ), -1, 'Spin 23 (24 Black), bet 2 pays -1'; +is payout( 23, 3 ), -1, 'Spin 23 (24 Black), bet 3 pays -1'; +is payout( 23, 4 ), -1, 'Spin 23 (24 Black), bet 4 pays -1'; +is payout( 23, 5 ), -1, 'Spin 23 (24 Black), bet 5 pays -1'; +is payout( 23, 6 ), -1, 'Spin 23 (24 Black), bet 6 pays -1'; +is payout( 23, 7 ), -1, 'Spin 23 (24 Black), bet 7 pays -1'; +is payout( 23, 8 ), -1, 'Spin 23 (24 Black), bet 8 pays -1'; +is payout( 23, 9 ), -1, 'Spin 23 (24 Black), bet 9 pays -1'; +is payout( 23, 10 ), -1, 'Spin 23 (24 Black), bet 10 pays -1'; +is payout( 23, 11 ), -1, 'Spin 23 (24 Black), bet 11 pays -1'; +is payout( 23, 12 ), -1, 'Spin 23 (24 Black), bet 12 pays -1'; +is payout( 23, 13 ), -1, 'Spin 23 (24 Black), bet 13 pays -1'; +is payout( 23, 14 ), -1, 'Spin 23 (24 Black), bet 14 pays -1'; +is payout( 23, 15 ), -1, 'Spin 23 (24 Black), bet 15 pays -1'; +is payout( 23, 16 ), -1, 'Spin 23 (24 Black), bet 16 pays -1'; +is payout( 23, 17 ), -1, 'Spin 23 (24 Black), bet 17 pays -1'; +is payout( 23, 18 ), -1, 'Spin 23 (24 Black), bet 18 pays -1'; +is payout( 23, 19 ), -1, 'Spin 23 (24 Black), bet 19 pays -1'; +is payout( 23, 20 ), -1, 'Spin 23 (24 Black), bet 20 pays -1'; +is payout( 23, 21 ), -1, 'Spin 23 (24 Black), bet 21 pays -1'; +is payout( 23, 22 ), -1, 'Spin 23 (24 Black), bet 22 pays -1'; +is payout( 23, 23 ), -1, 'Spin 23 (24 Black), bet 23 pays -1'; +is payout( 23, 24 ), 35, 'Spin 23 (24 Black), bet 24 pays 35'; +is payout( 23, 25 ), -1, 'Spin 23 (24 Black), bet 25 pays -1'; +is payout( 23, 26 ), -1, 'Spin 23 (24 Black), bet 26 pays -1'; +is payout( 23, 27 ), -1, 'Spin 23 (24 Black), bet 27 pays -1'; +is payout( 23, 28 ), -1, 'Spin 23 (24 Black), bet 28 pays -1'; +is payout( 23, 29 ), -1, 'Spin 23 (24 Black), bet 29 pays -1'; +is payout( 23, 30 ), -1, 'Spin 23 (24 Black), bet 30 pays -1'; +is payout( 23, 31 ), -1, 'Spin 23 (24 Black), bet 31 pays -1'; +is payout( 23, 32 ), -1, 'Spin 23 (24 Black), bet 32 pays -1'; +is payout( 23, 33 ), -1, 'Spin 23 (24 Black), bet 33 pays -1'; +is payout( 23, 34 ), -1, 'Spin 23 (24 Black), bet 34 pays -1'; +is payout( 23, 35 ), -1, 'Spin 23 (24 Black), bet 35 pays -1'; +is payout( 23, 36 ), -1, 'Spin 23 (24 Black), bet 36 pays -1'; +is payout( 23, 37 ), -1, 'Spin 23 (24 Black), bet 37 pays -1'; +is payout( 23, 38 ), 2, 'Spin 23 (24 Black), bet 38 pays 2'; +is payout( 23, 39 ), -1, 'Spin 23 (24 Black), bet 39 pays -1'; +is payout( 23, 40 ), -1, 'Spin 23 (24 Black), bet 40 pays -1'; +is payout( 23, 41 ), -1, 'Spin 23 (24 Black), bet 41 pays -1'; +is payout( 23, 42 ), 2, 'Spin 23 (24 Black), bet 42 pays 2'; +is payout( 23, 43 ), -1, 'Spin 23 (24 Black), bet 43 pays -1'; +is payout( 23, 44 ), 1, 'Spin 23 (24 Black), bet 44 pays 1'; +is payout( 23, 45 ), 1, 'Spin 23 (24 Black), bet 45 pays 1'; +is payout( 23, 46 ), -1, 'Spin 23 (24 Black), bet 46 pays -1'; +is payout( 23, 47 ), -1, 'Spin 23 (24 Black), bet 47 pays -1'; +is payout( 23, 48 ), 1, 'Spin 23 (24 Black), bet 48 pays 1'; +is payout( 23, 49 ), -1, 'Spin 23 (24 Black), bet 49 pays -1'; +is payout( 23, 50 ), -1, 'Spin 23 (24 Black), bet 50 pays -1'; +is format_spin( 24 ), '25 Red', 'Spin 24 is 25 Red'; +is payout( 24, 1 ), -1, 'Spin 24 (25 Red), bet 1 pays -1'; +is payout( 24, 2 ), -1, 'Spin 24 (25 Red), bet 2 pays -1'; +is payout( 24, 3 ), -1, 'Spin 24 (25 Red), bet 3 pays -1'; +is payout( 24, 4 ), -1, 'Spin 24 (25 Red), bet 4 pays -1'; +is payout( 24, 5 ), -1, 'Spin 24 (25 Red), bet 5 pays -1'; +is payout( 24, 6 ), -1, 'Spin 24 (25 Red), bet 6 pays -1'; +is payout( 24, 7 ), -1, 'Spin 24 (25 Red), bet 7 pays -1'; +is payout( 24, 8 ), -1, 'Spin 24 (25 Red), bet 8 pays -1'; +is payout( 24, 9 ), -1, 'Spin 24 (25 Red), bet 9 pays -1'; +is payout( 24, 10 ), -1, 'Spin 24 (25 Red), bet 10 pays -1'; +is payout( 24, 11 ), -1, 'Spin 24 (25 Red), bet 11 pays -1'; +is payout( 24, 12 ), -1, 'Spin 24 (25 Red), bet 12 pays -1'; +is payout( 24, 13 ), -1, 'Spin 24 (25 Red), bet 13 pays -1'; +is payout( 24, 14 ), -1, 'Spin 24 (25 Red), bet 14 pays -1'; +is payout( 24, 15 ), -1, 'Spin 24 (25 Red), bet 15 pays -1'; +is payout( 24, 16 ), -1, 'Spin 24 (25 Red), bet 16 pays -1'; +is payout( 24, 17 ), -1, 'Spin 24 (25 Red), bet 17 pays -1'; +is payout( 24, 18 ), -1, 'Spin 24 (25 Red), bet 18 pays -1'; +is payout( 24, 19 ), -1, 'Spin 24 (25 Red), bet 19 pays -1'; +is payout( 24, 20 ), -1, 'Spin 24 (25 Red), bet 20 pays -1'; +is payout( 24, 21 ), -1, 'Spin 24 (25 Red), bet 21 pays -1'; +is payout( 24, 22 ), -1, 'Spin 24 (25 Red), bet 22 pays -1'; +is payout( 24, 23 ), -1, 'Spin 24 (25 Red), bet 23 pays -1'; +is payout( 24, 24 ), -1, 'Spin 24 (25 Red), bet 24 pays -1'; +is payout( 24, 25 ), 35, 'Spin 24 (25 Red), bet 25 pays 35'; +is payout( 24, 26 ), -1, 'Spin 24 (25 Red), bet 26 pays -1'; +is payout( 24, 27 ), -1, 'Spin 24 (25 Red), bet 27 pays -1'; +is payout( 24, 28 ), -1, 'Spin 24 (25 Red), bet 28 pays -1'; +is payout( 24, 29 ), -1, 'Spin 24 (25 Red), bet 29 pays -1'; +is payout( 24, 30 ), -1, 'Spin 24 (25 Red), bet 30 pays -1'; +is payout( 24, 31 ), -1, 'Spin 24 (25 Red), bet 31 pays -1'; +is payout( 24, 32 ), -1, 'Spin 24 (25 Red), bet 32 pays -1'; +is payout( 24, 33 ), -1, 'Spin 24 (25 Red), bet 33 pays -1'; +is payout( 24, 34 ), -1, 'Spin 24 (25 Red), bet 34 pays -1'; +is payout( 24, 35 ), -1, 'Spin 24 (25 Red), bet 35 pays -1'; +is payout( 24, 36 ), -1, 'Spin 24 (25 Red), bet 36 pays -1'; +is payout( 24, 37 ), -1, 'Spin 24 (25 Red), bet 37 pays -1'; +is payout( 24, 38 ), -1, 'Spin 24 (25 Red), bet 38 pays -1'; +is payout( 24, 39 ), 2, 'Spin 24 (25 Red), bet 39 pays 2'; +is payout( 24, 40 ), 2, 'Spin 24 (25 Red), bet 40 pays 2'; +is payout( 24, 41 ), -1, 'Spin 24 (25 Red), bet 41 pays -1'; +is payout( 24, 42 ), -1, 'Spin 24 (25 Red), bet 42 pays -1'; +is payout( 24, 43 ), -1, 'Spin 24 (25 Red), bet 43 pays -1'; +is payout( 24, 44 ), 1, 'Spin 24 (25 Red), bet 44 pays 1'; +is payout( 24, 45 ), -1, 'Spin 24 (25 Red), bet 45 pays -1'; +is payout( 24, 46 ), 1, 'Spin 24 (25 Red), bet 46 pays 1'; +is payout( 24, 47 ), 1, 'Spin 24 (25 Red), bet 47 pays 1'; +is payout( 24, 48 ), -1, 'Spin 24 (25 Red), bet 48 pays -1'; +is payout( 24, 49 ), -1, 'Spin 24 (25 Red), bet 49 pays -1'; +is payout( 24, 50 ), -1, 'Spin 24 (25 Red), bet 50 pays -1'; +is format_spin( 25 ), '26 Black', 'Spin 25 is 26 Black'; +is payout( 25, 1 ), -1, 'Spin 25 (26 Black), bet 1 pays -1'; +is payout( 25, 2 ), -1, 'Spin 25 (26 Black), bet 2 pays -1'; +is payout( 25, 3 ), -1, 'Spin 25 (26 Black), bet 3 pays -1'; +is payout( 25, 4 ), -1, 'Spin 25 (26 Black), bet 4 pays -1'; +is payout( 25, 5 ), -1, 'Spin 25 (26 Black), bet 5 pays -1'; +is payout( 25, 6 ), -1, 'Spin 25 (26 Black), bet 6 pays -1'; +is payout( 25, 7 ), -1, 'Spin 25 (26 Black), bet 7 pays -1'; +is payout( 25, 8 ), -1, 'Spin 25 (26 Black), bet 8 pays -1'; +is payout( 25, 9 ), -1, 'Spin 25 (26 Black), bet 9 pays -1'; +is payout( 25, 10 ), -1, 'Spin 25 (26 Black), bet 10 pays -1'; +is payout( 25, 11 ), -1, 'Spin 25 (26 Black), bet 11 pays -1'; +is payout( 25, 12 ), -1, 'Spin 25 (26 Black), bet 12 pays -1'; +is payout( 25, 13 ), -1, 'Spin 25 (26 Black), bet 13 pays -1'; +is payout( 25, 14 ), -1, 'Spin 25 (26 Black), bet 14 pays -1'; +is payout( 25, 15 ), -1, 'Spin 25 (26 Black), bet 15 pays -1'; +is payout( 25, 16 ), -1, 'Spin 25 (26 Black), bet 16 pays -1'; +is payout( 25, 17 ), -1, 'Spin 25 (26 Black), bet 17 pays -1'; +is payout( 25, 18 ), -1, 'Spin 25 (26 Black), bet 18 pays -1'; +is payout( 25, 19 ), -1, 'Spin 25 (26 Black), bet 19 pays -1'; +is payout( 25, 20 ), -1, 'Spin 25 (26 Black), bet 20 pays -1'; +is payout( 25, 21 ), -1, 'Spin 25 (26 Black), bet 21 pays -1'; +is payout( 25, 22 ), -1, 'Spin 25 (26 Black), bet 22 pays -1'; +is payout( 25, 23 ), -1, 'Spin 25 (26 Black), bet 23 pays -1'; +is payout( 25, 24 ), -1, 'Spin 25 (26 Black), bet 24 pays -1'; +is payout( 25, 25 ), -1, 'Spin 25 (26 Black), bet 25 pays -1'; +is payout( 25, 26 ), 35, 'Spin 25 (26 Black), bet 26 pays 35'; +is payout( 25, 27 ), -1, 'Spin 25 (26 Black), bet 27 pays -1'; +is payout( 25, 28 ), -1, 'Spin 25 (26 Black), bet 28 pays -1'; +is payout( 25, 29 ), -1, 'Spin 25 (26 Black), bet 29 pays -1'; +is payout( 25, 30 ), -1, 'Spin 25 (26 Black), bet 30 pays -1'; +is payout( 25, 31 ), -1, 'Spin 25 (26 Black), bet 31 pays -1'; +is payout( 25, 32 ), -1, 'Spin 25 (26 Black), bet 32 pays -1'; +is payout( 25, 33 ), -1, 'Spin 25 (26 Black), bet 33 pays -1'; +is payout( 25, 34 ), -1, 'Spin 25 (26 Black), bet 34 pays -1'; +is payout( 25, 35 ), -1, 'Spin 25 (26 Black), bet 35 pays -1'; +is payout( 25, 36 ), -1, 'Spin 25 (26 Black), bet 36 pays -1'; +is payout( 25, 37 ), -1, 'Spin 25 (26 Black), bet 37 pays -1'; +is payout( 25, 38 ), -1, 'Spin 25 (26 Black), bet 38 pays -1'; +is payout( 25, 39 ), 2, 'Spin 25 (26 Black), bet 39 pays 2'; +is payout( 25, 40 ), -1, 'Spin 25 (26 Black), bet 40 pays -1'; +is payout( 25, 41 ), 2, 'Spin 25 (26 Black), bet 41 pays 2'; +is payout( 25, 42 ), -1, 'Spin 25 (26 Black), bet 42 pays -1'; +is payout( 25, 43 ), -1, 'Spin 25 (26 Black), bet 43 pays -1'; +is payout( 25, 44 ), 1, 'Spin 25 (26 Black), bet 44 pays 1'; +is payout( 25, 45 ), 1, 'Spin 25 (26 Black), bet 45 pays 1'; +is payout( 25, 46 ), -1, 'Spin 25 (26 Black), bet 46 pays -1'; +is payout( 25, 47 ), -1, 'Spin 25 (26 Black), bet 47 pays -1'; +is payout( 25, 48 ), 1, 'Spin 25 (26 Black), bet 48 pays 1'; +is payout( 25, 49 ), -1, 'Spin 25 (26 Black), bet 49 pays -1'; +is payout( 25, 50 ), -1, 'Spin 25 (26 Black), bet 50 pays -1'; +is format_spin( 26 ), '27 Red', 'Spin 26 is 27 Red'; +is payout( 26, 1 ), -1, 'Spin 26 (27 Red), bet 1 pays -1'; +is payout( 26, 2 ), -1, 'Spin 26 (27 Red), bet 2 pays -1'; +is payout( 26, 3 ), -1, 'Spin 26 (27 Red), bet 3 pays -1'; +is payout( 26, 4 ), -1, 'Spin 26 (27 Red), bet 4 pays -1'; +is payout( 26, 5 ), -1, 'Spin 26 (27 Red), bet 5 pays -1'; +is payout( 26, 6 ), -1, 'Spin 26 (27 Red), bet 6 pays -1'; +is payout( 26, 7 ), -1, 'Spin 26 (27 Red), bet 7 pays -1'; +is payout( 26, 8 ), -1, 'Spin 26 (27 Red), bet 8 pays -1'; +is payout( 26, 9 ), -1, 'Spin 26 (27 Red), bet 9 pays -1'; +is payout( 26, 10 ), -1, 'Spin 26 (27 Red), bet 10 pays -1'; +is payout( 26, 11 ), -1, 'Spin 26 (27 Red), bet 11 pays -1'; +is payout( 26, 12 ), -1, 'Spin 26 (27 Red), bet 12 pays -1'; +is payout( 26, 13 ), -1, 'Spin 26 (27 Red), bet 13 pays -1'; +is payout( 26, 14 ), -1, 'Spin 26 (27 Red), bet 14 pays -1'; +is payout( 26, 15 ), -1, 'Spin 26 (27 Red), bet 15 pays -1'; +is payout( 26, 16 ), -1, 'Spin 26 (27 Red), bet 16 pays -1'; +is payout( 26, 17 ), -1, 'Spin 26 (27 Red), bet 17 pays -1'; +is payout( 26, 18 ), -1, 'Spin 26 (27 Red), bet 18 pays -1'; +is payout( 26, 19 ), -1, 'Spin 26 (27 Red), bet 19 pays -1'; +is payout( 26, 20 ), -1, 'Spin 26 (27 Red), bet 20 pays -1'; +is payout( 26, 21 ), -1, 'Spin 26 (27 Red), bet 21 pays -1'; +is payout( 26, 22 ), -1, 'Spin 26 (27 Red), bet 22 pays -1'; +is payout( 26, 23 ), -1, 'Spin 26 (27 Red), bet 23 pays -1'; +is payout( 26, 24 ), -1, 'Spin 26 (27 Red), bet 24 pays -1'; +is payout( 26, 25 ), -1, 'Spin 26 (27 Red), bet 25 pays -1'; +is payout( 26, 26 ), -1, 'Spin 26 (27 Red), bet 26 pays -1'; +is payout( 26, 27 ), 35, 'Spin 26 (27 Red), bet 27 pays 35'; +is payout( 26, 28 ), -1, 'Spin 26 (27 Red), bet 28 pays -1'; +is payout( 26, 29 ), -1, 'Spin 26 (27 Red), bet 29 pays -1'; +is payout( 26, 30 ), -1, 'Spin 26 (27 Red), bet 30 pays -1'; +is payout( 26, 31 ), -1, 'Spin 26 (27 Red), bet 31 pays -1'; +is payout( 26, 32 ), -1, 'Spin 26 (27 Red), bet 32 pays -1'; +is payout( 26, 33 ), -1, 'Spin 26 (27 Red), bet 33 pays -1'; +is payout( 26, 34 ), -1, 'Spin 26 (27 Red), bet 34 pays -1'; +is payout( 26, 35 ), -1, 'Spin 26 (27 Red), bet 35 pays -1'; +is payout( 26, 36 ), -1, 'Spin 26 (27 Red), bet 36 pays -1'; +is payout( 26, 37 ), -1, 'Spin 26 (27 Red), bet 37 pays -1'; +is payout( 26, 38 ), -1, 'Spin 26 (27 Red), bet 38 pays -1'; +is payout( 26, 39 ), 2, 'Spin 26 (27 Red), bet 39 pays 2'; +is payout( 26, 40 ), -1, 'Spin 26 (27 Red), bet 40 pays -1'; +is payout( 26, 41 ), -1, 'Spin 26 (27 Red), bet 41 pays -1'; +is payout( 26, 42 ), 2, 'Spin 26 (27 Red), bet 42 pays 2'; +is payout( 26, 43 ), -1, 'Spin 26 (27 Red), bet 43 pays -1'; +is payout( 26, 44 ), 1, 'Spin 26 (27 Red), bet 44 pays 1'; +is payout( 26, 45 ), -1, 'Spin 26 (27 Red), bet 45 pays -1'; +is payout( 26, 46 ), 1, 'Spin 26 (27 Red), bet 46 pays 1'; +is payout( 26, 47 ), 1, 'Spin 26 (27 Red), bet 47 pays 1'; +is payout( 26, 48 ), -1, 'Spin 26 (27 Red), bet 48 pays -1'; +is payout( 26, 49 ), -1, 'Spin 26 (27 Red), bet 49 pays -1'; +is payout( 26, 50 ), -1, 'Spin 26 (27 Red), bet 50 pays -1'; +is format_spin( 27 ), '28 Black', 'Spin 27 is 28 Black'; +is payout( 27, 1 ), -1, 'Spin 27 (28 Black), bet 1 pays -1'; +is payout( 27, 2 ), -1, 'Spin 27 (28 Black), bet 2 pays -1'; +is payout( 27, 3 ), -1, 'Spin 27 (28 Black), bet 3 pays -1'; +is payout( 27, 4 ), -1, 'Spin 27 (28 Black), bet 4 pays -1'; +is payout( 27, 5 ), -1, 'Spin 27 (28 Black), bet 5 pays -1'; +is payout( 27, 6 ), -1, 'Spin 27 (28 Black), bet 6 pays -1'; +is payout( 27, 7 ), -1, 'Spin 27 (28 Black), bet 7 pays -1'; +is payout( 27, 8 ), -1, 'Spin 27 (28 Black), bet 8 pays -1'; +is payout( 27, 9 ), -1, 'Spin 27 (28 Black), bet 9 pays -1'; +is payout( 27, 10 ), -1, 'Spin 27 (28 Black), bet 10 pays -1'; +is payout( 27, 11 ), -1, 'Spin 27 (28 Black), bet 11 pays -1'; +is payout( 27, 12 ), -1, 'Spin 27 (28 Black), bet 12 pays -1'; +is payout( 27, 13 ), -1, 'Spin 27 (28 Black), bet 13 pays -1'; +is payout( 27, 14 ), -1, 'Spin 27 (28 Black), bet 14 pays -1'; +is payout( 27, 15 ), -1, 'Spin 27 (28 Black), bet 15 pays -1'; +is payout( 27, 16 ), -1, 'Spin 27 (28 Black), bet 16 pays -1'; +is payout( 27, 17 ), -1, 'Spin 27 (28 Black), bet 17 pays -1'; +is payout( 27, 18 ), -1, 'Spin 27 (28 Black), bet 18 pays -1'; +is payout( 27, 19 ), -1, 'Spin 27 (28 Black), bet 19 pays -1'; +is payout( 27, 20 ), -1, 'Spin 27 (28 Black), bet 20 pays -1'; +is payout( 27, 21 ), -1, 'Spin 27 (28 Black), bet 21 pays -1'; +is payout( 27, 22 ), -1, 'Spin 27 (28 Black), bet 22 pays -1'; +is payout( 27, 23 ), -1, 'Spin 27 (28 Black), bet 23 pays -1'; +is payout( 27, 24 ), -1, 'Spin 27 (28 Black), bet 24 pays -1'; +is payout( 27, 25 ), -1, 'Spin 27 (28 Black), bet 25 pays -1'; +is payout( 27, 26 ), -1, 'Spin 27 (28 Black), bet 26 pays -1'; +is payout( 27, 27 ), -1, 'Spin 27 (28 Black), bet 27 pays -1'; +is payout( 27, 28 ), 35, 'Spin 27 (28 Black), bet 28 pays 35'; +is payout( 27, 29 ), -1, 'Spin 27 (28 Black), bet 29 pays -1'; +is payout( 27, 30 ), -1, 'Spin 27 (28 Black), bet 30 pays -1'; +is payout( 27, 31 ), -1, 'Spin 27 (28 Black), bet 31 pays -1'; +is payout( 27, 32 ), -1, 'Spin 27 (28 Black), bet 32 pays -1'; +is payout( 27, 33 ), -1, 'Spin 27 (28 Black), bet 33 pays -1'; +is payout( 27, 34 ), -1, 'Spin 27 (28 Black), bet 34 pays -1'; +is payout( 27, 35 ), -1, 'Spin 27 (28 Black), bet 35 pays -1'; +is payout( 27, 36 ), -1, 'Spin 27 (28 Black), bet 36 pays -1'; +is payout( 27, 37 ), -1, 'Spin 27 (28 Black), bet 37 pays -1'; +is payout( 27, 38 ), -1, 'Spin 27 (28 Black), bet 38 pays -1'; +is payout( 27, 39 ), 2, 'Spin 27 (28 Black), bet 39 pays 2'; +is payout( 27, 40 ), 2, 'Spin 27 (28 Black), bet 40 pays 2'; +is payout( 27, 41 ), -1, 'Spin 27 (28 Black), bet 41 pays -1'; +is payout( 27, 42 ), -1, 'Spin 27 (28 Black), bet 42 pays -1'; +is payout( 27, 43 ), -1, 'Spin 27 (28 Black), bet 43 pays -1'; +is payout( 27, 44 ), 1, 'Spin 27 (28 Black), bet 44 pays 1'; +is payout( 27, 45 ), 1, 'Spin 27 (28 Black), bet 45 pays 1'; +is payout( 27, 46 ), -1, 'Spin 27 (28 Black), bet 46 pays -1'; +is payout( 27, 47 ), -1, 'Spin 27 (28 Black), bet 47 pays -1'; +is payout( 27, 48 ), 1, 'Spin 27 (28 Black), bet 48 pays 1'; +is payout( 27, 49 ), -1, 'Spin 27 (28 Black), bet 49 pays -1'; +is payout( 27, 50 ), -1, 'Spin 27 (28 Black), bet 50 pays -1'; +is format_spin( 28 ), '29 Black', 'Spin 28 is 29 Black'; +is payout( 28, 1 ), -1, 'Spin 28 (29 Black), bet 1 pays -1'; +is payout( 28, 2 ), -1, 'Spin 28 (29 Black), bet 2 pays -1'; +is payout( 28, 3 ), -1, 'Spin 28 (29 Black), bet 3 pays -1'; +is payout( 28, 4 ), -1, 'Spin 28 (29 Black), bet 4 pays -1'; +is payout( 28, 5 ), -1, 'Spin 28 (29 Black), bet 5 pays -1'; +is payout( 28, 6 ), -1, 'Spin 28 (29 Black), bet 6 pays -1'; +is payout( 28, 7 ), -1, 'Spin 28 (29 Black), bet 7 pays -1'; +is payout( 28, 8 ), -1, 'Spin 28 (29 Black), bet 8 pays -1'; +is payout( 28, 9 ), -1, 'Spin 28 (29 Black), bet 9 pays -1'; +is payout( 28, 10 ), -1, 'Spin 28 (29 Black), bet 10 pays -1'; +is payout( 28, 11 ), -1, 'Spin 28 (29 Black), bet 11 pays -1'; +is payout( 28, 12 ), -1, 'Spin 28 (29 Black), bet 12 pays -1'; +is payout( 28, 13 ), -1, 'Spin 28 (29 Black), bet 13 pays -1'; +is payout( 28, 14 ), -1, 'Spin 28 (29 Black), bet 14 pays -1'; +is payout( 28, 15 ), -1, 'Spin 28 (29 Black), bet 15 pays -1'; +is payout( 28, 16 ), -1, 'Spin 28 (29 Black), bet 16 pays -1'; +is payout( 28, 17 ), -1, 'Spin 28 (29 Black), bet 17 pays -1'; +is payout( 28, 18 ), -1, 'Spin 28 (29 Black), bet 18 pays -1'; +is payout( 28, 19 ), -1, 'Spin 28 (29 Black), bet 19 pays -1'; +is payout( 28, 20 ), -1, 'Spin 28 (29 Black), bet 20 pays -1'; +is payout( 28, 21 ), -1, 'Spin 28 (29 Black), bet 21 pays -1'; +is payout( 28, 22 ), -1, 'Spin 28 (29 Black), bet 22 pays -1'; +is payout( 28, 23 ), -1, 'Spin 28 (29 Black), bet 23 pays -1'; +is payout( 28, 24 ), -1, 'Spin 28 (29 Black), bet 24 pays -1'; +is payout( 28, 25 ), -1, 'Spin 28 (29 Black), bet 25 pays -1'; +is payout( 28, 26 ), -1, 'Spin 28 (29 Black), bet 26 pays -1'; +is payout( 28, 27 ), -1, 'Spin 28 (29 Black), bet 27 pays -1'; +is payout( 28, 28 ), -1, 'Spin 28 (29 Black), bet 28 pays -1'; +is payout( 28, 29 ), 35, 'Spin 28 (29 Black), bet 29 pays 35'; +is payout( 28, 30 ), -1, 'Spin 28 (29 Black), bet 30 pays -1'; +is payout( 28, 31 ), -1, 'Spin 28 (29 Black), bet 31 pays -1'; +is payout( 28, 32 ), -1, 'Spin 28 (29 Black), bet 32 pays -1'; +is payout( 28, 33 ), -1, 'Spin 28 (29 Black), bet 33 pays -1'; +is payout( 28, 34 ), -1, 'Spin 28 (29 Black), bet 34 pays -1'; +is payout( 28, 35 ), -1, 'Spin 28 (29 Black), bet 35 pays -1'; +is payout( 28, 36 ), -1, 'Spin 28 (29 Black), bet 36 pays -1'; +is payout( 28, 37 ), -1, 'Spin 28 (29 Black), bet 37 pays -1'; +is payout( 28, 38 ), -1, 'Spin 28 (29 Black), bet 38 pays -1'; +is payout( 28, 39 ), 2, 'Spin 28 (29 Black), bet 39 pays 2'; +is payout( 28, 40 ), -1, 'Spin 28 (29 Black), bet 40 pays -1'; +is payout( 28, 41 ), 2, 'Spin 28 (29 Black), bet 41 pays 2'; +is payout( 28, 42 ), -1, 'Spin 28 (29 Black), bet 42 pays -1'; +is payout( 28, 43 ), -1, 'Spin 28 (29 Black), bet 43 pays -1'; +is payout( 28, 44 ), 1, 'Spin 28 (29 Black), bet 44 pays 1'; +is payout( 28, 45 ), -1, 'Spin 28 (29 Black), bet 45 pays -1'; +is payout( 28, 46 ), 1, 'Spin 28 (29 Black), bet 46 pays 1'; +is payout( 28, 47 ), -1, 'Spin 28 (29 Black), bet 47 pays -1'; +is payout( 28, 48 ), 1, 'Spin 28 (29 Black), bet 48 pays 1'; +is payout( 28, 49 ), -1, 'Spin 28 (29 Black), bet 49 pays -1'; +is payout( 28, 50 ), -1, 'Spin 28 (29 Black), bet 50 pays -1'; +is format_spin( 29 ), '30 Red', 'Spin 29 is 30 Red'; +is payout( 29, 1 ), -1, 'Spin 29 (30 Red), bet 1 pays -1'; +is payout( 29, 2 ), -1, 'Spin 29 (30 Red), bet 2 pays -1'; +is payout( 29, 3 ), -1, 'Spin 29 (30 Red), bet 3 pays -1'; +is payout( 29, 4 ), -1, 'Spin 29 (30 Red), bet 4 pays -1'; +is payout( 29, 5 ), -1, 'Spin 29 (30 Red), bet 5 pays -1'; +is payout( 29, 6 ), -1, 'Spin 29 (30 Red), bet 6 pays -1'; +is payout( 29, 7 ), -1, 'Spin 29 (30 Red), bet 7 pays -1'; +is payout( 29, 8 ), -1, 'Spin 29 (30 Red), bet 8 pays -1'; +is payout( 29, 9 ), -1, 'Spin 29 (30 Red), bet 9 pays -1'; +is payout( 29, 10 ), -1, 'Spin 29 (30 Red), bet 10 pays -1'; +is payout( 29, 11 ), -1, 'Spin 29 (30 Red), bet 11 pays -1'; +is payout( 29, 12 ), -1, 'Spin 29 (30 Red), bet 12 pays -1'; +is payout( 29, 13 ), -1, 'Spin 29 (30 Red), bet 13 pays -1'; +is payout( 29, 14 ), -1, 'Spin 29 (30 Red), bet 14 pays -1'; +is payout( 29, 15 ), -1, 'Spin 29 (30 Red), bet 15 pays -1'; +is payout( 29, 16 ), -1, 'Spin 29 (30 Red), bet 16 pays -1'; +is payout( 29, 17 ), -1, 'Spin 29 (30 Red), bet 17 pays -1'; +is payout( 29, 18 ), -1, 'Spin 29 (30 Red), bet 18 pays -1'; +is payout( 29, 19 ), -1, 'Spin 29 (30 Red), bet 19 pays -1'; +is payout( 29, 20 ), -1, 'Spin 29 (30 Red), bet 20 pays -1'; +is payout( 29, 21 ), -1, 'Spin 29 (30 Red), bet 21 pays -1'; +is payout( 29, 22 ), -1, 'Spin 29 (30 Red), bet 22 pays -1'; +is payout( 29, 23 ), -1, 'Spin 29 (30 Red), bet 23 pays -1'; +is payout( 29, 24 ), -1, 'Spin 29 (30 Red), bet 24 pays -1'; +is payout( 29, 25 ), -1, 'Spin 29 (30 Red), bet 25 pays -1'; +is payout( 29, 26 ), -1, 'Spin 29 (30 Red), bet 26 pays -1'; +is payout( 29, 27 ), -1, 'Spin 29 (30 Red), bet 27 pays -1'; +is payout( 29, 28 ), -1, 'Spin 29 (30 Red), bet 28 pays -1'; +is payout( 29, 29 ), -1, 'Spin 29 (30 Red), bet 29 pays -1'; +is payout( 29, 30 ), 35, 'Spin 29 (30 Red), bet 30 pays 35'; +is payout( 29, 31 ), -1, 'Spin 29 (30 Red), bet 31 pays -1'; +is payout( 29, 32 ), -1, 'Spin 29 (30 Red), bet 32 pays -1'; +is payout( 29, 33 ), -1, 'Spin 29 (30 Red), bet 33 pays -1'; +is payout( 29, 34 ), -1, 'Spin 29 (30 Red), bet 34 pays -1'; +is payout( 29, 35 ), -1, 'Spin 29 (30 Red), bet 35 pays -1'; +is payout( 29, 36 ), -1, 'Spin 29 (30 Red), bet 36 pays -1'; +is payout( 29, 37 ), -1, 'Spin 29 (30 Red), bet 37 pays -1'; +is payout( 29, 38 ), -1, 'Spin 29 (30 Red), bet 38 pays -1'; +is payout( 29, 39 ), 2, 'Spin 29 (30 Red), bet 39 pays 2'; +is payout( 29, 40 ), -1, 'Spin 29 (30 Red), bet 40 pays -1'; +is payout( 29, 41 ), -1, 'Spin 29 (30 Red), bet 41 pays -1'; +is payout( 29, 42 ), 2, 'Spin 29 (30 Red), bet 42 pays 2'; +is payout( 29, 43 ), -1, 'Spin 29 (30 Red), bet 43 pays -1'; +is payout( 29, 44 ), 1, 'Spin 29 (30 Red), bet 44 pays 1'; +is payout( 29, 45 ), 1, 'Spin 29 (30 Red), bet 45 pays 1'; +is payout( 29, 46 ), -1, 'Spin 29 (30 Red), bet 46 pays -1'; +is payout( 29, 47 ), 1, 'Spin 29 (30 Red), bet 47 pays 1'; +is payout( 29, 48 ), -1, 'Spin 29 (30 Red), bet 48 pays -1'; +is payout( 29, 49 ), -1, 'Spin 29 (30 Red), bet 49 pays -1'; +is payout( 29, 50 ), -1, 'Spin 29 (30 Red), bet 50 pays -1'; +is format_spin( 30 ), '31 Black', 'Spin 30 is 31 Black'; +is payout( 30, 1 ), -1, 'Spin 30 (31 Black), bet 1 pays -1'; +is payout( 30, 2 ), -1, 'Spin 30 (31 Black), bet 2 pays -1'; +is payout( 30, 3 ), -1, 'Spin 30 (31 Black), bet 3 pays -1'; +is payout( 30, 4 ), -1, 'Spin 30 (31 Black), bet 4 pays -1'; +is payout( 30, 5 ), -1, 'Spin 30 (31 Black), bet 5 pays -1'; +is payout( 30, 6 ), -1, 'Spin 30 (31 Black), bet 6 pays -1'; +is payout( 30, 7 ), -1, 'Spin 30 (31 Black), bet 7 pays -1'; +is payout( 30, 8 ), -1, 'Spin 30 (31 Black), bet 8 pays -1'; +is payout( 30, 9 ), -1, 'Spin 30 (31 Black), bet 9 pays -1'; +is payout( 30, 10 ), -1, 'Spin 30 (31 Black), bet 10 pays -1'; +is payout( 30, 11 ), -1, 'Spin 30 (31 Black), bet 11 pays -1'; +is payout( 30, 12 ), -1, 'Spin 30 (31 Black), bet 12 pays -1'; +is payout( 30, 13 ), -1, 'Spin 30 (31 Black), bet 13 pays -1'; +is payout( 30, 14 ), -1, 'Spin 30 (31 Black), bet 14 pays -1'; +is payout( 30, 15 ), -1, 'Spin 30 (31 Black), bet 15 pays -1'; +is payout( 30, 16 ), -1, 'Spin 30 (31 Black), bet 16 pays -1'; +is payout( 30, 17 ), -1, 'Spin 30 (31 Black), bet 17 pays -1'; +is payout( 30, 18 ), -1, 'Spin 30 (31 Black), bet 18 pays -1'; +is payout( 30, 19 ), -1, 'Spin 30 (31 Black), bet 19 pays -1'; +is payout( 30, 20 ), -1, 'Spin 30 (31 Black), bet 20 pays -1'; +is payout( 30, 21 ), -1, 'Spin 30 (31 Black), bet 21 pays -1'; +is payout( 30, 22 ), -1, 'Spin 30 (31 Black), bet 22 pays -1'; +is payout( 30, 23 ), -1, 'Spin 30 (31 Black), bet 23 pays -1'; +is payout( 30, 24 ), -1, 'Spin 30 (31 Black), bet 24 pays -1'; +is payout( 30, 25 ), -1, 'Spin 30 (31 Black), bet 25 pays -1'; +is payout( 30, 26 ), -1, 'Spin 30 (31 Black), bet 26 pays -1'; +is payout( 30, 27 ), -1, 'Spin 30 (31 Black), bet 27 pays -1'; +is payout( 30, 28 ), -1, 'Spin 30 (31 Black), bet 28 pays -1'; +is payout( 30, 29 ), -1, 'Spin 30 (31 Black), bet 29 pays -1'; +is payout( 30, 30 ), -1, 'Spin 30 (31 Black), bet 30 pays -1'; +is payout( 30, 31 ), 35, 'Spin 30 (31 Black), bet 31 pays 35'; +is payout( 30, 32 ), -1, 'Spin 30 (31 Black), bet 32 pays -1'; +is payout( 30, 33 ), -1, 'Spin 30 (31 Black), bet 33 pays -1'; +is payout( 30, 34 ), -1, 'Spin 30 (31 Black), bet 34 pays -1'; +is payout( 30, 35 ), -1, 'Spin 30 (31 Black), bet 35 pays -1'; +is payout( 30, 36 ), -1, 'Spin 30 (31 Black), bet 36 pays -1'; +is payout( 30, 37 ), -1, 'Spin 30 (31 Black), bet 37 pays -1'; +is payout( 30, 38 ), -1, 'Spin 30 (31 Black), bet 38 pays -1'; +is payout( 30, 39 ), 2, 'Spin 30 (31 Black), bet 39 pays 2'; +is payout( 30, 40 ), 2, 'Spin 30 (31 Black), bet 40 pays 2'; +is payout( 30, 41 ), -1, 'Spin 30 (31 Black), bet 41 pays -1'; +is payout( 30, 42 ), -1, 'Spin 30 (31 Black), bet 42 pays -1'; +is payout( 30, 43 ), -1, 'Spin 30 (31 Black), bet 43 pays -1'; +is payout( 30, 44 ), 1, 'Spin 30 (31 Black), bet 44 pays 1'; +is payout( 30, 45 ), -1, 'Spin 30 (31 Black), bet 45 pays -1'; +is payout( 30, 46 ), 1, 'Spin 30 (31 Black), bet 46 pays 1'; +is payout( 30, 47 ), -1, 'Spin 30 (31 Black), bet 47 pays -1'; +is payout( 30, 48 ), 1, 'Spin 30 (31 Black), bet 48 pays 1'; +is payout( 30, 49 ), -1, 'Spin 30 (31 Black), bet 49 pays -1'; +is payout( 30, 50 ), -1, 'Spin 30 (31 Black), bet 50 pays -1'; +is format_spin( 31 ), '32 Red', 'Spin 31 is 32 Red'; +is payout( 31, 1 ), -1, 'Spin 31 (32 Red), bet 1 pays -1'; +is payout( 31, 2 ), -1, 'Spin 31 (32 Red), bet 2 pays -1'; +is payout( 31, 3 ), -1, 'Spin 31 (32 Red), bet 3 pays -1'; +is payout( 31, 4 ), -1, 'Spin 31 (32 Red), bet 4 pays -1'; +is payout( 31, 5 ), -1, 'Spin 31 (32 Red), bet 5 pays -1'; +is payout( 31, 6 ), -1, 'Spin 31 (32 Red), bet 6 pays -1'; +is payout( 31, 7 ), -1, 'Spin 31 (32 Red), bet 7 pays -1'; +is payout( 31, 8 ), -1, 'Spin 31 (32 Red), bet 8 pays -1'; +is payout( 31, 9 ), -1, 'Spin 31 (32 Red), bet 9 pays -1'; +is payout( 31, 10 ), -1, 'Spin 31 (32 Red), bet 10 pays -1'; +is payout( 31, 11 ), -1, 'Spin 31 (32 Red), bet 11 pays -1'; +is payout( 31, 12 ), -1, 'Spin 31 (32 Red), bet 12 pays -1'; +is payout( 31, 13 ), -1, 'Spin 31 (32 Red), bet 13 pays -1'; +is payout( 31, 14 ), -1, 'Spin 31 (32 Red), bet 14 pays -1'; +is payout( 31, 15 ), -1, 'Spin 31 (32 Red), bet 15 pays -1'; +is payout( 31, 16 ), -1, 'Spin 31 (32 Red), bet 16 pays -1'; +is payout( 31, 17 ), -1, 'Spin 31 (32 Red), bet 17 pays -1'; +is payout( 31, 18 ), -1, 'Spin 31 (32 Red), bet 18 pays -1'; +is payout( 31, 19 ), -1, 'Spin 31 (32 Red), bet 19 pays -1'; +is payout( 31, 20 ), -1, 'Spin 31 (32 Red), bet 20 pays -1'; +is payout( 31, 21 ), -1, 'Spin 31 (32 Red), bet 21 pays -1'; +is payout( 31, 22 ), -1, 'Spin 31 (32 Red), bet 22 pays -1'; +is payout( 31, 23 ), -1, 'Spin 31 (32 Red), bet 23 pays -1'; +is payout( 31, 24 ), -1, 'Spin 31 (32 Red), bet 24 pays -1'; +is payout( 31, 25 ), -1, 'Spin 31 (32 Red), bet 25 pays -1'; +is payout( 31, 26 ), -1, 'Spin 31 (32 Red), bet 26 pays -1'; +is payout( 31, 27 ), -1, 'Spin 31 (32 Red), bet 27 pays -1'; +is payout( 31, 28 ), -1, 'Spin 31 (32 Red), bet 28 pays -1'; +is payout( 31, 29 ), -1, 'Spin 31 (32 Red), bet 29 pays -1'; +is payout( 31, 30 ), -1, 'Spin 31 (32 Red), bet 30 pays -1'; +is payout( 31, 31 ), -1, 'Spin 31 (32 Red), bet 31 pays -1'; +is payout( 31, 32 ), 35, 'Spin 31 (32 Red), bet 32 pays 35'; +is payout( 31, 33 ), -1, 'Spin 31 (32 Red), bet 33 pays -1'; +is payout( 31, 34 ), -1, 'Spin 31 (32 Red), bet 34 pays -1'; +is payout( 31, 35 ), -1, 'Spin 31 (32 Red), bet 35 pays -1'; +is payout( 31, 36 ), -1, 'Spin 31 (32 Red), bet 36 pays -1'; +is payout( 31, 37 ), -1, 'Spin 31 (32 Red), bet 37 pays -1'; +is payout( 31, 38 ), -1, 'Spin 31 (32 Red), bet 38 pays -1'; +is payout( 31, 39 ), 2, 'Spin 31 (32 Red), bet 39 pays 2'; +is payout( 31, 40 ), -1, 'Spin 31 (32 Red), bet 40 pays -1'; +is payout( 31, 41 ), 2, 'Spin 31 (32 Red), bet 41 pays 2'; +is payout( 31, 42 ), -1, 'Spin 31 (32 Red), bet 42 pays -1'; +is payout( 31, 43 ), -1, 'Spin 31 (32 Red), bet 43 pays -1'; +is payout( 31, 44 ), 1, 'Spin 31 (32 Red), bet 44 pays 1'; +is payout( 31, 45 ), 1, 'Spin 31 (32 Red), bet 45 pays 1'; +is payout( 31, 46 ), -1, 'Spin 31 (32 Red), bet 46 pays -1'; +is payout( 31, 47 ), 1, 'Spin 31 (32 Red), bet 47 pays 1'; +is payout( 31, 48 ), -1, 'Spin 31 (32 Red), bet 48 pays -1'; +is payout( 31, 49 ), -1, 'Spin 31 (32 Red), bet 49 pays -1'; +is payout( 31, 50 ), -1, 'Spin 31 (32 Red), bet 50 pays -1'; +is format_spin( 32 ), '33 Black', 'Spin 32 is 33 Black'; +is payout( 32, 1 ), -1, 'Spin 32 (33 Black), bet 1 pays -1'; +is payout( 32, 2 ), -1, 'Spin 32 (33 Black), bet 2 pays -1'; +is payout( 32, 3 ), -1, 'Spin 32 (33 Black), bet 3 pays -1'; +is payout( 32, 4 ), -1, 'Spin 32 (33 Black), bet 4 pays -1'; +is payout( 32, 5 ), -1, 'Spin 32 (33 Black), bet 5 pays -1'; +is payout( 32, 6 ), -1, 'Spin 32 (33 Black), bet 6 pays -1'; +is payout( 32, 7 ), -1, 'Spin 32 (33 Black), bet 7 pays -1'; +is payout( 32, 8 ), -1, 'Spin 32 (33 Black), bet 8 pays -1'; +is payout( 32, 9 ), -1, 'Spin 32 (33 Black), bet 9 pays -1'; +is payout( 32, 10 ), -1, 'Spin 32 (33 Black), bet 10 pays -1'; +is payout( 32, 11 ), -1, 'Spin 32 (33 Black), bet 11 pays -1'; +is payout( 32, 12 ), -1, 'Spin 32 (33 Black), bet 12 pays -1'; +is payout( 32, 13 ), -1, 'Spin 32 (33 Black), bet 13 pays -1'; +is payout( 32, 14 ), -1, 'Spin 32 (33 Black), bet 14 pays -1'; +is payout( 32, 15 ), -1, 'Spin 32 (33 Black), bet 15 pays -1'; +is payout( 32, 16 ), -1, 'Spin 32 (33 Black), bet 16 pays -1'; +is payout( 32, 17 ), -1, 'Spin 32 (33 Black), bet 17 pays -1'; +is payout( 32, 18 ), -1, 'Spin 32 (33 Black), bet 18 pays -1'; +is payout( 32, 19 ), -1, 'Spin 32 (33 Black), bet 19 pays -1'; +is payout( 32, 20 ), -1, 'Spin 32 (33 Black), bet 20 pays -1'; +is payout( 32, 21 ), -1, 'Spin 32 (33 Black), bet 21 pays -1'; +is payout( 32, 22 ), -1, 'Spin 32 (33 Black), bet 22 pays -1'; +is payout( 32, 23 ), -1, 'Spin 32 (33 Black), bet 23 pays -1'; +is payout( 32, 24 ), -1, 'Spin 32 (33 Black), bet 24 pays -1'; +is payout( 32, 25 ), -1, 'Spin 32 (33 Black), bet 25 pays -1'; +is payout( 32, 26 ), -1, 'Spin 32 (33 Black), bet 26 pays -1'; +is payout( 32, 27 ), -1, 'Spin 32 (33 Black), bet 27 pays -1'; +is payout( 32, 28 ), -1, 'Spin 32 (33 Black), bet 28 pays -1'; +is payout( 32, 29 ), -1, 'Spin 32 (33 Black), bet 29 pays -1'; +is payout( 32, 30 ), -1, 'Spin 32 (33 Black), bet 30 pays -1'; +is payout( 32, 31 ), -1, 'Spin 32 (33 Black), bet 31 pays -1'; +is payout( 32, 32 ), -1, 'Spin 32 (33 Black), bet 32 pays -1'; +is payout( 32, 33 ), 35, 'Spin 32 (33 Black), bet 33 pays 35'; +is payout( 32, 34 ), -1, 'Spin 32 (33 Black), bet 34 pays -1'; +is payout( 32, 35 ), -1, 'Spin 32 (33 Black), bet 35 pays -1'; +is payout( 32, 36 ), -1, 'Spin 32 (33 Black), bet 36 pays -1'; +is payout( 32, 37 ), -1, 'Spin 32 (33 Black), bet 37 pays -1'; +is payout( 32, 38 ), -1, 'Spin 32 (33 Black), bet 38 pays -1'; +is payout( 32, 39 ), 2, 'Spin 32 (33 Black), bet 39 pays 2'; +is payout( 32, 40 ), -1, 'Spin 32 (33 Black), bet 40 pays -1'; +is payout( 32, 41 ), -1, 'Spin 32 (33 Black), bet 41 pays -1'; +is payout( 32, 42 ), 2, 'Spin 32 (33 Black), bet 42 pays 2'; +is payout( 32, 43 ), -1, 'Spin 32 (33 Black), bet 43 pays -1'; +is payout( 32, 44 ), 1, 'Spin 32 (33 Black), bet 44 pays 1'; +is payout( 32, 45 ), -1, 'Spin 32 (33 Black), bet 45 pays -1'; +is payout( 32, 46 ), 1, 'Spin 32 (33 Black), bet 46 pays 1'; +is payout( 32, 47 ), -1, 'Spin 32 (33 Black), bet 47 pays -1'; +is payout( 32, 48 ), 1, 'Spin 32 (33 Black), bet 48 pays 1'; +is payout( 32, 49 ), -1, 'Spin 32 (33 Black), bet 49 pays -1'; +is payout( 32, 50 ), -1, 'Spin 32 (33 Black), bet 50 pays -1'; +is format_spin( 33 ), '34 Red', 'Spin 33 is 34 Red'; +is payout( 33, 1 ), -1, 'Spin 33 (34 Red), bet 1 pays -1'; +is payout( 33, 2 ), -1, 'Spin 33 (34 Red), bet 2 pays -1'; +is payout( 33, 3 ), -1, 'Spin 33 (34 Red), bet 3 pays -1'; +is payout( 33, 4 ), -1, 'Spin 33 (34 Red), bet 4 pays -1'; +is payout( 33, 5 ), -1, 'Spin 33 (34 Red), bet 5 pays -1'; +is payout( 33, 6 ), -1, 'Spin 33 (34 Red), bet 6 pays -1'; +is payout( 33, 7 ), -1, 'Spin 33 (34 Red), bet 7 pays -1'; +is payout( 33, 8 ), -1, 'Spin 33 (34 Red), bet 8 pays -1'; +is payout( 33, 9 ), -1, 'Spin 33 (34 Red), bet 9 pays -1'; +is payout( 33, 10 ), -1, 'Spin 33 (34 Red), bet 10 pays -1'; +is payout( 33, 11 ), -1, 'Spin 33 (34 Red), bet 11 pays -1'; +is payout( 33, 12 ), -1, 'Spin 33 (34 Red), bet 12 pays -1'; +is payout( 33, 13 ), -1, 'Spin 33 (34 Red), bet 13 pays -1'; +is payout( 33, 14 ), -1, 'Spin 33 (34 Red), bet 14 pays -1'; +is payout( 33, 15 ), -1, 'Spin 33 (34 Red), bet 15 pays -1'; +is payout( 33, 16 ), -1, 'Spin 33 (34 Red), bet 16 pays -1'; +is payout( 33, 17 ), -1, 'Spin 33 (34 Red), bet 17 pays -1'; +is payout( 33, 18 ), -1, 'Spin 33 (34 Red), bet 18 pays -1'; +is payout( 33, 19 ), -1, 'Spin 33 (34 Red), bet 19 pays -1'; +is payout( 33, 20 ), -1, 'Spin 33 (34 Red), bet 20 pays -1'; +is payout( 33, 21 ), -1, 'Spin 33 (34 Red), bet 21 pays -1'; +is payout( 33, 22 ), -1, 'Spin 33 (34 Red), bet 22 pays -1'; +is payout( 33, 23 ), -1, 'Spin 33 (34 Red), bet 23 pays -1'; +is payout( 33, 24 ), -1, 'Spin 33 (34 Red), bet 24 pays -1'; +is payout( 33, 25 ), -1, 'Spin 33 (34 Red), bet 25 pays -1'; +is payout( 33, 26 ), -1, 'Spin 33 (34 Red), bet 26 pays -1'; +is payout( 33, 27 ), -1, 'Spin 33 (34 Red), bet 27 pays -1'; +is payout( 33, 28 ), -1, 'Spin 33 (34 Red), bet 28 pays -1'; +is payout( 33, 29 ), -1, 'Spin 33 (34 Red), bet 29 pays -1'; +is payout( 33, 30 ), -1, 'Spin 33 (34 Red), bet 30 pays -1'; +is payout( 33, 31 ), -1, 'Spin 33 (34 Red), bet 31 pays -1'; +is payout( 33, 32 ), -1, 'Spin 33 (34 Red), bet 32 pays -1'; +is payout( 33, 33 ), -1, 'Spin 33 (34 Red), bet 33 pays -1'; +is payout( 33, 34 ), 35, 'Spin 33 (34 Red), bet 34 pays 35'; +is payout( 33, 35 ), -1, 'Spin 33 (34 Red), bet 35 pays -1'; +is payout( 33, 36 ), -1, 'Spin 33 (34 Red), bet 36 pays -1'; +is payout( 33, 37 ), -1, 'Spin 33 (34 Red), bet 37 pays -1'; +is payout( 33, 38 ), -1, 'Spin 33 (34 Red), bet 38 pays -1'; +is payout( 33, 39 ), 2, 'Spin 33 (34 Red), bet 39 pays 2'; +is payout( 33, 40 ), 2, 'Spin 33 (34 Red), bet 40 pays 2'; +is payout( 33, 41 ), -1, 'Spin 33 (34 Red), bet 41 pays -1'; +is payout( 33, 42 ), -1, 'Spin 33 (34 Red), bet 42 pays -1'; +is payout( 33, 43 ), -1, 'Spin 33 (34 Red), bet 43 pays -1'; +is payout( 33, 44 ), 1, 'Spin 33 (34 Red), bet 44 pays 1'; +is payout( 33, 45 ), 1, 'Spin 33 (34 Red), bet 45 pays 1'; +is payout( 33, 46 ), -1, 'Spin 33 (34 Red), bet 46 pays -1'; +is payout( 33, 47 ), 1, 'Spin 33 (34 Red), bet 47 pays 1'; +is payout( 33, 48 ), -1, 'Spin 33 (34 Red), bet 48 pays -1'; +is payout( 33, 49 ), -1, 'Spin 33 (34 Red), bet 49 pays -1'; +is payout( 33, 50 ), -1, 'Spin 33 (34 Red), bet 50 pays -1'; +is format_spin( 34 ), '35 Black', 'Spin 34 is 35 Black'; +is payout( 34, 1 ), -1, 'Spin 34 (35 Black), bet 1 pays -1'; +is payout( 34, 2 ), -1, 'Spin 34 (35 Black), bet 2 pays -1'; +is payout( 34, 3 ), -1, 'Spin 34 (35 Black), bet 3 pays -1'; +is payout( 34, 4 ), -1, 'Spin 34 (35 Black), bet 4 pays -1'; +is payout( 34, 5 ), -1, 'Spin 34 (35 Black), bet 5 pays -1'; +is payout( 34, 6 ), -1, 'Spin 34 (35 Black), bet 6 pays -1'; +is payout( 34, 7 ), -1, 'Spin 34 (35 Black), bet 7 pays -1'; +is payout( 34, 8 ), -1, 'Spin 34 (35 Black), bet 8 pays -1'; +is payout( 34, 9 ), -1, 'Spin 34 (35 Black), bet 9 pays -1'; +is payout( 34, 10 ), -1, 'Spin 34 (35 Black), bet 10 pays -1'; +is payout( 34, 11 ), -1, 'Spin 34 (35 Black), bet 11 pays -1'; +is payout( 34, 12 ), -1, 'Spin 34 (35 Black), bet 12 pays -1'; +is payout( 34, 13 ), -1, 'Spin 34 (35 Black), bet 13 pays -1'; +is payout( 34, 14 ), -1, 'Spin 34 (35 Black), bet 14 pays -1'; +is payout( 34, 15 ), -1, 'Spin 34 (35 Black), bet 15 pays -1'; +is payout( 34, 16 ), -1, 'Spin 34 (35 Black), bet 16 pays -1'; +is payout( 34, 17 ), -1, 'Spin 34 (35 Black), bet 17 pays -1'; +is payout( 34, 18 ), -1, 'Spin 34 (35 Black), bet 18 pays -1'; +is payout( 34, 19 ), -1, 'Spin 34 (35 Black), bet 19 pays -1'; +is payout( 34, 20 ), -1, 'Spin 34 (35 Black), bet 20 pays -1'; +is payout( 34, 21 ), -1, 'Spin 34 (35 Black), bet 21 pays -1'; +is payout( 34, 22 ), -1, 'Spin 34 (35 Black), bet 22 pays -1'; +is payout( 34, 23 ), -1, 'Spin 34 (35 Black), bet 23 pays -1'; +is payout( 34, 24 ), -1, 'Spin 34 (35 Black), bet 24 pays -1'; +is payout( 34, 25 ), -1, 'Spin 34 (35 Black), bet 25 pays -1'; +is payout( 34, 26 ), -1, 'Spin 34 (35 Black), bet 26 pays -1'; +is payout( 34, 27 ), -1, 'Spin 34 (35 Black), bet 27 pays -1'; +is payout( 34, 28 ), -1, 'Spin 34 (35 Black), bet 28 pays -1'; +is payout( 34, 29 ), -1, 'Spin 34 (35 Black), bet 29 pays -1'; +is payout( 34, 30 ), -1, 'Spin 34 (35 Black), bet 30 pays -1'; +is payout( 34, 31 ), -1, 'Spin 34 (35 Black), bet 31 pays -1'; +is payout( 34, 32 ), -1, 'Spin 34 (35 Black), bet 32 pays -1'; +is payout( 34, 33 ), -1, 'Spin 34 (35 Black), bet 33 pays -1'; +is payout( 34, 34 ), -1, 'Spin 34 (35 Black), bet 34 pays -1'; +is payout( 34, 35 ), 35, 'Spin 34 (35 Black), bet 35 pays 35'; +is payout( 34, 36 ), -1, 'Spin 34 (35 Black), bet 36 pays -1'; +is payout( 34, 37 ), -1, 'Spin 34 (35 Black), bet 37 pays -1'; +is payout( 34, 38 ), -1, 'Spin 34 (35 Black), bet 38 pays -1'; +is payout( 34, 39 ), 2, 'Spin 34 (35 Black), bet 39 pays 2'; +is payout( 34, 40 ), -1, 'Spin 34 (35 Black), bet 40 pays -1'; +is payout( 34, 41 ), 2, 'Spin 34 (35 Black), bet 41 pays 2'; +is payout( 34, 42 ), -1, 'Spin 34 (35 Black), bet 42 pays -1'; +is payout( 34, 43 ), -1, 'Spin 34 (35 Black), bet 43 pays -1'; +is payout( 34, 44 ), 1, 'Spin 34 (35 Black), bet 44 pays 1'; +is payout( 34, 45 ), -1, 'Spin 34 (35 Black), bet 45 pays -1'; +is payout( 34, 46 ), 1, 'Spin 34 (35 Black), bet 46 pays 1'; +is payout( 34, 47 ), -1, 'Spin 34 (35 Black), bet 47 pays -1'; +is payout( 34, 48 ), 1, 'Spin 34 (35 Black), bet 48 pays 1'; +is payout( 34, 49 ), -1, 'Spin 34 (35 Black), bet 49 pays -1'; +is payout( 34, 50 ), -1, 'Spin 34 (35 Black), bet 50 pays -1'; +is format_spin( 35 ), '36 Red', 'Spin 35 is 36 Red'; +is payout( 35, 1 ), -1, 'Spin 35 (36 Red), bet 1 pays -1'; +is payout( 35, 2 ), -1, 'Spin 35 (36 Red), bet 2 pays -1'; +is payout( 35, 3 ), -1, 'Spin 35 (36 Red), bet 3 pays -1'; +is payout( 35, 4 ), -1, 'Spin 35 (36 Red), bet 4 pays -1'; +is payout( 35, 5 ), -1, 'Spin 35 (36 Red), bet 5 pays -1'; +is payout( 35, 6 ), -1, 'Spin 35 (36 Red), bet 6 pays -1'; +is payout( 35, 7 ), -1, 'Spin 35 (36 Red), bet 7 pays -1'; +is payout( 35, 8 ), -1, 'Spin 35 (36 Red), bet 8 pays -1'; +is payout( 35, 9 ), -1, 'Spin 35 (36 Red), bet 9 pays -1'; +is payout( 35, 10 ), -1, 'Spin 35 (36 Red), bet 10 pays -1'; +is payout( 35, 11 ), -1, 'Spin 35 (36 Red), bet 11 pays -1'; +is payout( 35, 12 ), -1, 'Spin 35 (36 Red), bet 12 pays -1'; +is payout( 35, 13 ), -1, 'Spin 35 (36 Red), bet 13 pays -1'; +is payout( 35, 14 ), -1, 'Spin 35 (36 Red), bet 14 pays -1'; +is payout( 35, 15 ), -1, 'Spin 35 (36 Red), bet 15 pays -1'; +is payout( 35, 16 ), -1, 'Spin 35 (36 Red), bet 16 pays -1'; +is payout( 35, 17 ), -1, 'Spin 35 (36 Red), bet 17 pays -1'; +is payout( 35, 18 ), -1, 'Spin 35 (36 Red), bet 18 pays -1'; +is payout( 35, 19 ), -1, 'Spin 35 (36 Red), bet 19 pays -1'; +is payout( 35, 20 ), -1, 'Spin 35 (36 Red), bet 20 pays -1'; +is payout( 35, 21 ), -1, 'Spin 35 (36 Red), bet 21 pays -1'; +is payout( 35, 22 ), -1, 'Spin 35 (36 Red), bet 22 pays -1'; +is payout( 35, 23 ), -1, 'Spin 35 (36 Red), bet 23 pays -1'; +is payout( 35, 24 ), -1, 'Spin 35 (36 Red), bet 24 pays -1'; +is payout( 35, 25 ), -1, 'Spin 35 (36 Red), bet 25 pays -1'; +is payout( 35, 26 ), -1, 'Spin 35 (36 Red), bet 26 pays -1'; +is payout( 35, 27 ), -1, 'Spin 35 (36 Red), bet 27 pays -1'; +is payout( 35, 28 ), -1, 'Spin 35 (36 Red), bet 28 pays -1'; +is payout( 35, 29 ), -1, 'Spin 35 (36 Red), bet 29 pays -1'; +is payout( 35, 30 ), -1, 'Spin 35 (36 Red), bet 30 pays -1'; +is payout( 35, 31 ), -1, 'Spin 35 (36 Red), bet 31 pays -1'; +is payout( 35, 32 ), -1, 'Spin 35 (36 Red), bet 32 pays -1'; +is payout( 35, 33 ), -1, 'Spin 35 (36 Red), bet 33 pays -1'; +is payout( 35, 34 ), -1, 'Spin 35 (36 Red), bet 34 pays -1'; +is payout( 35, 35 ), -1, 'Spin 35 (36 Red), bet 35 pays -1'; +is payout( 35, 36 ), 35, 'Spin 35 (36 Red), bet 36 pays 35'; +is payout( 35, 37 ), -1, 'Spin 35 (36 Red), bet 37 pays -1'; +is payout( 35, 38 ), -1, 'Spin 35 (36 Red), bet 38 pays -1'; +is payout( 35, 39 ), 2, 'Spin 35 (36 Red), bet 39 pays 2'; +is payout( 35, 40 ), -1, 'Spin 35 (36 Red), bet 40 pays -1'; +is payout( 35, 41 ), -1, 'Spin 35 (36 Red), bet 41 pays -1'; +is payout( 35, 42 ), 2, 'Spin 35 (36 Red), bet 42 pays 2'; +is payout( 35, 43 ), -1, 'Spin 35 (36 Red), bet 43 pays -1'; +is payout( 35, 44 ), 1, 'Spin 35 (36 Red), bet 44 pays 1'; +is payout( 35, 45 ), 1, 'Spin 35 (36 Red), bet 45 pays 1'; +is payout( 35, 46 ), -1, 'Spin 35 (36 Red), bet 46 pays -1'; +is payout( 35, 47 ), 1, 'Spin 35 (36 Red), bet 47 pays 1'; +is payout( 35, 48 ), -1, 'Spin 35 (36 Red), bet 48 pays -1'; +is payout( 35, 49 ), -1, 'Spin 35 (36 Red), bet 49 pays -1'; +is payout( 35, 50 ), -1, 'Spin 35 (36 Red), bet 50 pays -1'; +is format_spin( 36 ), '0', 'Spin 36 is 0'; +is payout( 36, 1 ), -1, 'Spin 36 (0), bet 1 pays -1'; +is payout( 36, 2 ), -1, 'Spin 36 (0), bet 2 pays -1'; +is payout( 36, 3 ), -1, 'Spin 36 (0), bet 3 pays -1'; +is payout( 36, 4 ), -1, 'Spin 36 (0), bet 4 pays -1'; +is payout( 36, 5 ), -1, 'Spin 36 (0), bet 5 pays -1'; +is payout( 36, 6 ), -1, 'Spin 36 (0), bet 6 pays -1'; +is payout( 36, 7 ), -1, 'Spin 36 (0), bet 7 pays -1'; +is payout( 36, 8 ), -1, 'Spin 36 (0), bet 8 pays -1'; +is payout( 36, 9 ), -1, 'Spin 36 (0), bet 9 pays -1'; +is payout( 36, 10 ), -1, 'Spin 36 (0), bet 10 pays -1'; +is payout( 36, 11 ), -1, 'Spin 36 (0), bet 11 pays -1'; +is payout( 36, 12 ), -1, 'Spin 36 (0), bet 12 pays -1'; +is payout( 36, 13 ), -1, 'Spin 36 (0), bet 13 pays -1'; +is payout( 36, 14 ), -1, 'Spin 36 (0), bet 14 pays -1'; +is payout( 36, 15 ), -1, 'Spin 36 (0), bet 15 pays -1'; +is payout( 36, 16 ), -1, 'Spin 36 (0), bet 16 pays -1'; +is payout( 36, 17 ), -1, 'Spin 36 (0), bet 17 pays -1'; +is payout( 36, 18 ), -1, 'Spin 36 (0), bet 18 pays -1'; +is payout( 36, 19 ), -1, 'Spin 36 (0), bet 19 pays -1'; +is payout( 36, 20 ), -1, 'Spin 36 (0), bet 20 pays -1'; +is payout( 36, 21 ), -1, 'Spin 36 (0), bet 21 pays -1'; +is payout( 36, 22 ), -1, 'Spin 36 (0), bet 22 pays -1'; +is payout( 36, 23 ), -1, 'Spin 36 (0), bet 23 pays -1'; +is payout( 36, 24 ), -1, 'Spin 36 (0), bet 24 pays -1'; +is payout( 36, 25 ), -1, 'Spin 36 (0), bet 25 pays -1'; +is payout( 36, 26 ), -1, 'Spin 36 (0), bet 26 pays -1'; +is payout( 36, 27 ), -1, 'Spin 36 (0), bet 27 pays -1'; +is payout( 36, 28 ), -1, 'Spin 36 (0), bet 28 pays -1'; +is payout( 36, 29 ), -1, 'Spin 36 (0), bet 29 pays -1'; +is payout( 36, 30 ), -1, 'Spin 36 (0), bet 30 pays -1'; +is payout( 36, 31 ), -1, 'Spin 36 (0), bet 31 pays -1'; +is payout( 36, 32 ), -1, 'Spin 36 (0), bet 32 pays -1'; +is payout( 36, 33 ), -1, 'Spin 36 (0), bet 33 pays -1'; +is payout( 36, 34 ), -1, 'Spin 36 (0), bet 34 pays -1'; +is payout( 36, 35 ), -1, 'Spin 36 (0), bet 35 pays -1'; +is payout( 36, 36 ), -1, 'Spin 36 (0), bet 36 pays -1'; +is payout( 36, 37 ), -1, 'Spin 36 (0), bet 37 pays -1'; +is payout( 36, 38 ), -1, 'Spin 36 (0), bet 38 pays -1'; +is payout( 36, 39 ), -1, 'Spin 36 (0), bet 39 pays -1'; +is payout( 36, 40 ), -1, 'Spin 36 (0), bet 40 pays -1'; +is payout( 36, 41 ), -1, 'Spin 36 (0), bet 41 pays -1'; +is payout( 36, 42 ), -1, 'Spin 36 (0), bet 42 pays -1'; +is payout( 36, 43 ), -1, 'Spin 36 (0), bet 43 pays -1'; +is payout( 36, 44 ), -1, 'Spin 36 (0), bet 44 pays -1'; +is payout( 36, 45 ), -1, 'Spin 36 (0), bet 45 pays -1'; +is payout( 36, 46 ), -1, 'Spin 36 (0), bet 46 pays -1'; +is payout( 36, 47 ), -1, 'Spin 36 (0), bet 47 pays -1'; +is payout( 36, 48 ), -1, 'Spin 36 (0), bet 48 pays -1'; +is payout( 36, 49 ), 35, 'Spin 36 (0), bet 49 pays 35'; +is payout( 36, 50 ), -1, 'Spin 36 (0), bet 50 pays -1'; +is format_spin( 37 ), '00', 'Spin 37 is 00'; +is payout( 37, 1 ), -1, 'Spin 37 (00), bet 1 pays -1'; +is payout( 37, 2 ), -1, 'Spin 37 (00), bet 2 pays -1'; +is payout( 37, 3 ), -1, 'Spin 37 (00), bet 3 pays -1'; +is payout( 37, 4 ), -1, 'Spin 37 (00), bet 4 pays -1'; +is payout( 37, 5 ), -1, 'Spin 37 (00), bet 5 pays -1'; +is payout( 37, 6 ), -1, 'Spin 37 (00), bet 6 pays -1'; +is payout( 37, 7 ), -1, 'Spin 37 (00), bet 7 pays -1'; +is payout( 37, 8 ), -1, 'Spin 37 (00), bet 8 pays -1'; +is payout( 37, 9 ), -1, 'Spin 37 (00), bet 9 pays -1'; +is payout( 37, 10 ), -1, 'Spin 37 (00), bet 10 pays -1'; +is payout( 37, 11 ), -1, 'Spin 37 (00), bet 11 pays -1'; +is payout( 37, 12 ), -1, 'Spin 37 (00), bet 12 pays -1'; +is payout( 37, 13 ), -1, 'Spin 37 (00), bet 13 pays -1'; +is payout( 37, 14 ), -1, 'Spin 37 (00), bet 14 pays -1'; +is payout( 37, 15 ), -1, 'Spin 37 (00), bet 15 pays -1'; +is payout( 37, 16 ), -1, 'Spin 37 (00), bet 16 pays -1'; +is payout( 37, 17 ), -1, 'Spin 37 (00), bet 17 pays -1'; +is payout( 37, 18 ), -1, 'Spin 37 (00), bet 18 pays -1'; +is payout( 37, 19 ), -1, 'Spin 37 (00), bet 19 pays -1'; +is payout( 37, 20 ), -1, 'Spin 37 (00), bet 20 pays -1'; +is payout( 37, 21 ), -1, 'Spin 37 (00), bet 21 pays -1'; +is payout( 37, 22 ), -1, 'Spin 37 (00), bet 22 pays -1'; +is payout( 37, 23 ), -1, 'Spin 37 (00), bet 23 pays -1'; +is payout( 37, 24 ), -1, 'Spin 37 (00), bet 24 pays -1'; +is payout( 37, 25 ), -1, 'Spin 37 (00), bet 25 pays -1'; +is payout( 37, 26 ), -1, 'Spin 37 (00), bet 26 pays -1'; +is payout( 37, 27 ), -1, 'Spin 37 (00), bet 27 pays -1'; +is payout( 37, 28 ), -1, 'Spin 37 (00), bet 28 pays -1'; +is payout( 37, 29 ), -1, 'Spin 37 (00), bet 29 pays -1'; +is payout( 37, 30 ), -1, 'Spin 37 (00), bet 30 pays -1'; +is payout( 37, 31 ), -1, 'Spin 37 (00), bet 31 pays -1'; +is payout( 37, 32 ), -1, 'Spin 37 (00), bet 32 pays -1'; +is payout( 37, 33 ), -1, 'Spin 37 (00), bet 33 pays -1'; +is payout( 37, 34 ), -1, 'Spin 37 (00), bet 34 pays -1'; +is payout( 37, 35 ), -1, 'Spin 37 (00), bet 35 pays -1'; +is payout( 37, 36 ), -1, 'Spin 37 (00), bet 36 pays -1'; +is payout( 37, 37 ), -1, 'Spin 37 (00), bet 37 pays -1'; +is payout( 37, 38 ), -1, 'Spin 37 (00), bet 38 pays -1'; +is payout( 37, 39 ), -1, 'Spin 37 (00), bet 39 pays -1'; +is payout( 37, 40 ), -1, 'Spin 37 (00), bet 40 pays -1'; +is payout( 37, 41 ), -1, 'Spin 37 (00), bet 41 pays -1'; +is payout( 37, 42 ), -1, 'Spin 37 (00), bet 42 pays -1'; +is payout( 37, 43 ), -1, 'Spin 37 (00), bet 43 pays -1'; +is payout( 37, 44 ), -1, 'Spin 37 (00), bet 44 pays -1'; +is payout( 37, 45 ), -1, 'Spin 37 (00), bet 45 pays -1'; +is payout( 37, 46 ), -1, 'Spin 37 (00), bet 46 pays -1'; +is payout( 37, 47 ), -1, 'Spin 37 (00), bet 47 pays -1'; +is payout( 37, 48 ), -1, 'Spin 37 (00), bet 48 pays -1'; +is payout( 37, 49 ), -1, 'Spin 37 (00), bet 49 pays -1'; +is payout( 37, 50 ), 35, 'Spin 37 (00), bet 50 pays 35'; + +done_testing; + +1; + +# ex: set textwidth=72 : diff --git a/75_Roulette/perl/roulette.pl b/75_Roulette/perl/roulette.pl new file mode 100755 index 00000000..ad3ce965 --- /dev/null +++ b/75_Roulette/perl/roulette.pl @@ -0,0 +1,319 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use POSIX qw{ strftime }; # Time formatting +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +# A main() function is not usual in Perl scripts. I have installed one +# here to make the script into a "modulino." The next line executes +# main() if and only if caller() returns false. It will do this if we +# were loaded by another Perl script but not otherwise. This was done so +# I could test the payout and spin formatting logic. +main() unless caller; + +sub main { + + print <<'EOD'; + ROULETTE + Creative Computing Morristown, New Jersey + + + + +Welcome to the roulette table. + +EOD + + if ( get_yes_no( 'Do you want instructions' ) ) { + print <<'EOD'; + +This is the betting layout + (*=red) + + 1* 2 3* + 4 5* 6 + 7* 8 9* +10 11 12* +--------------- +13 14* 15 +16* 17 18* +19* 20 21* +22 23* 24 +--------------- +25* 26 27* +28 29 30* +31 32* 33 +34* 35 36* +--------------- + 00 0 + +Types of bets: + +The numbers 1 to 36 signify a straight bet +on that number. +These pay off 35:1 + +The 2:1 bets are: + 37) 1-12 40) first column + 38) 13-24 41) second column + 39) 25-36 42) third column + +The even money bets are: + 43) 1-18 46) odd + 44) 19-36 47) red + 45) even 48) black + + 49) 0 and 50) 00 pay off 35:1 + Note: 0 and 00 do not count under any + bets except their own. + +When I ask for each bet, type the number +and the amount, separated by a comma. +For example: to bet $500 on black, type 48,500 +when I ask for a bet. + +The minimum bet is $5, the maximum is $500. + +EOD +} + + my $P = 1000; + my $D = 100000.; + + while ( 1 ) { # Iterate indefinitely + + my $Y = get_input( 'How many bets? ', + sub { m/ \A [0-9]+ \z /smx && $ARG > 0 && $ARG <= 50 }, + "Please enter a positive integer no greater than 50\n", + ); + my @B; + my @T; + foreach my $C ( 1 .. $Y ) { + my ( $X, $Z ) = split qr< , >smx, get_input( + "Number $C: ", + sub { m/ \A ( [0-9]+ ) , ( [0-9]+ ) \z /smx + && $1 > 0 && $1 <= 50 && $2 >= 5 && $2 <= 500 }, + "Please enter two comma-separated positive numbers\n", + ); + if ( $B[$X] ) { + say 'You made that bet once already, dum-dum.'; + redo; + } + $B[$X] = $Z; # BASIC does $B[$C] = $Z + $T[$C] = $X; + } + + print <<'EOD'; + + Spinning ... + +EOD + my $S = int rand 38; # Zero-based, versus 1-based in BASIC + + say format_spin( $S ); + + say ''; + + foreach my $C ( 1 .. $Y ) { + my $X = $T[$C]; + my $payout = payout( $S, $X ) * $B[$X]; + $D -= $payout; + $P += $payout; + if ( $payout > 0 ) { + say "You win $payout dollars on bet $C"; + } else { + $payout = -$payout; + say "You lose $payout dollars on bet $C"; + } + } + say "Totals\tMe\tYou"; + say "\t$D\t$P"; + say ''; + + + last unless get_yes_no( 'Again' ); + } + + say ''; + + if ( $P > 0 ) { + my $B = get_input( + 'To whom shall I make out the check? ', + ); + my $check_number = 1000 + int rand 9000; + my $todays_date = strftime( '%B %d, %Y', localtime ); + print <<"EOD"; + +------------------------------------------------------------ Check number $check_number + + $todays_date + +Pay to the order of ------ $B ----- \$$P + + The Memory Bank of New York + + The Computer + ---------X----- + +------------------------------------------------------------------------------- + +Come back soon! +EOD + } else { + print <<'EOD'; +Thanks for your money. +I'll use it to buy a solid gold roulette wheel +EOD + } +} + +{ + # Define the kind of each possible spin. 0 is '0' or '00', 1 is + # black, and 2 is red. We assign the values in a BEGIN block because + # execution never actually reaches this point in the script. + my @kind; + BEGIN { + @kind = ( 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, + 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 0, + 0 ); + } + + # Convert the spin (0-37) to its name on the wheel. + sub format_spin { + my ( $number ) = @_; + state $format = [ + sub { '0' x ( $_[0] - 35 ) }, + sub { sprintf '%s Black', $_[0] + 1 }, + sub { sprintf '%s Red', $_[0] + 1 }, + ]; + return $format->[$kind[$number]]( $number ); + } + + # Compute the payout given the spin (0-37) and the bet (1-50). + sub payout { + my ( $number, $bet ) = @_; + # We compute the payout on '0' and '00' directly, since under + # our rules they are only eligible for the 35-to-1 bet. + $kind[$number] + or return $number == $bet - 49 + 36 ? 35 : -1; + --$bet; # #bet is 1-based coming in + # Dispatch table for computing the payout for spins 0-36. + state $payout = [ + ( sub { $_[0] == $_[1] ? 35 : -1 } ) x 36, + ( sub { int( $_[0] / 12 ) == $_[1] - 36 ? 2 : -1 } ) x 3, + ( sub { $_[0] % 3 == $_[1] - 39 ? 2 : -1 } ) x 3, + ( sub { int( $_[0] / 18 ) == $_[1] - 42 ? 1 : -1 } ) x 2, + ( sub { $_[0] % 2 == 45 - $_[1] ? 1 : -1 } ) x 2, + ( sub { $kind[$_[0]] == 48 - $_[1] ? 1 : -1 } ) x 2, + ( sub { -1 } ) x 2, # Bet on '0' or '00' loses + ]; + return $payout->[$bet]->( $number, $bet ); + } +} + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +__END__ + +=head1 TITLE + +roulette - Play the game 'Roulette' from Basic Computer Games + +=head1 SYNOPSIS + + roulette.pl + +=head1 DETAILS + +This Perl script is a port of roulette, which is the 75th +entry in Basic Computer Games. + +The main internal changes are converting the roulette slot numbering to +0-based and replacing most of the payout logic with a dispatch table. +These changes were tested for correctness against the original BASIC. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From 71bc3b95f4ae936ef00b034a41d8dd07bb9edb15 Mon Sep 17 00:00:00 2001 From: Mark Wieder Date: Tue, 11 Jan 2022 15:12:06 -0800 Subject: [PATCH 727/749] Slot machine in ruby --- 80_Slots/ruby/slots.rb | 152 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 80_Slots/ruby/slots.rb diff --git a/80_Slots/ruby/slots.rb b/80_Slots/ruby/slots.rb new file mode 100644 index 00000000..a4c3e7ef --- /dev/null +++ b/80_Slots/ruby/slots.rb @@ -0,0 +1,152 @@ +$pot = 0 + +def greeting + puts "SLOTS".center(80) + puts "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".center(80) + puts "\n\n" + + # PRODUCED BY FRED MIRABELLE AND BOB HARPER ON JAN 29, 1973 + # IT SIMULATES THE SLOT MACHINE. + + puts "You are in the H&M Casino, in front of one of our" + puts "one-arm bandits. You can bet from $1 to $100." + puts "To pull the arm, punch the return key after making your bet." + puts "\nBet zero to end the game." +end + +def overLimit + puts "House Limit is $100" +end + +def underMinimum + puts "Minimum Bet is $1" +end + +# bells don't work on my machine. YMMV +# I'm displaying dashes between the reels + +def tenBells + 10.times do + # beep if you can + print "-" + end +end + +def fiveBells + "-----" +end + +def goodbye + puts "\n\n\n" + # end the game + exit +end + +def payUp + puts "PAY UP! PLEASE LEAVE YOUR MONEY ON THE TERMINAL." +end + +def brokeEven + puts "HEY, YOU BROKE EVEN." +end + +def collectWinnings + puts "COLLECT YOUR WINNINGS FROM THE H&M CASHIER." +end + +def win winType, bet + case winType + when "jackpot" + winMessage = "***JACKPOT***" + winnings = 101 + when "topDollar" + winMessage = "**TOP DOLLAR**" + winnings = 11 + when "doubleBar" + winMessage = "*DOUBLE BAR!!*" + winnings = 6 + when "double" + winMessage = "DOUBLE!!" + winnings = 3 + end + puts "\nYou won: " + winMessage + $pot += (winnings * bet) +end + +greeting + +#$pot = 0 +while true + reelArray = ["BAR","BELL","ORANGE","LEMON","PLUM","CHERRY"] + print "\nYOUR BET? " + # get input, remove leading and trailing whitespace, cast to integer + bet = gets.strip.to_i + + if bet == 0 then + goodbye + elsif bet > 100 then + overLimit # error if more than $100 + elsif bet < 1 then + underMinimum # have to bet at least a dollar + else + # valid bet, continue + tenBells # ding + + # assign a random value from the array to each of the three reels + reel1 = reelArray[rand(5)] + reel2 = reelArray[rand(5)] + reel3 = reelArray[rand(5)] + + # print the slot machine reels + puts "\n\n" + reel1 + fiveBells + reel2 + fiveBells + reel3 + + # see if we have a match in the first two reels + if reel1 == reel2 then + if reel2 == reel3 then + if reel3 == "BAR" then + # all three reels are "BAR" + win "jackpot", bet + else + # all three reels match but aren't "BAR" + win "topDollar", bet + end + elsif reel2 == "BAR" then + # reels 1 and 2 are both "BAR" + win "doubleBar", bet + else + # reels 1 and 2 match but aren't "BAR" + win "double", bet + end + # otherwise see if there's a match in the remaining reels + elsif reel1 == reel3 or reel2 == reel3 then + if reel3 == "BAR" then + # two reels match, both "BAR" + win "doubleBar", bet + else + # two reels match, but not "BAR" + win "double", bet + end + else + # bad news - no matches + puts "\nYou lost" + # decrement your standings by the bet amount + $pot -= bet + end + + puts "Your standings are: " + $pot.to_s + print "\nAgain? " # YES to continue + # get input, remove leading and trailing whitespace, make uppercase + again = gets.strip.upcase + if again != "Y" && again != "YES" then + # that's enough... evaluate the pot and quit + if $pot < 0 then + payUp + elsif $pot == 0 then + brokeEven + else # yay! + collectWinnings + end + goodbye + end + end +end From 1c1276778b562850563d6391c0c89eb056844f30 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:40:05 -0300 Subject: [PATCH 728/749] Just starting out. --- 55_Life/csharp/.gitignore | 509 +++++++++++++++++++++++++++++++++++++ 55_Life/csharp/Life.csproj | 9 + 55_Life/csharp/Life.sln | 16 ++ 55_Life/csharp/Program.cs | 37 +++ 4 files changed, 571 insertions(+) create mode 100644 55_Life/csharp/.gitignore create mode 100644 55_Life/csharp/Life.csproj create mode 100644 55_Life/csharp/Life.sln create mode 100644 55_Life/csharp/Program.cs diff --git a/55_Life/csharp/.gitignore b/55_Life/csharp/.gitignore new file mode 100644 index 00000000..e96e7522 --- /dev/null +++ b/55_Life/csharp/.gitignore @@ -0,0 +1,509 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/dotnetcore,rider,visualstudio,visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=dotnetcore,rider,visualstudio,visualstudiocode + +### DotnetCore ### +# .NET Core build folders +bin/ +obj/ + +# Common node modules locations +/node_modules +/wwwroot/node_modules + +### Rider ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +*.code-workspace + +# Local History for Visual Studio Code + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/dotnetcore,rider,visualstudio,visualstudiocode diff --git a/55_Life/csharp/Life.csproj b/55_Life/csharp/Life.csproj new file mode 100644 index 00000000..7311ef16 --- /dev/null +++ b/55_Life/csharp/Life.csproj @@ -0,0 +1,9 @@ + + + + Exe + net6.0 + enable + + + diff --git a/55_Life/csharp/Life.sln b/55_Life/csharp/Life.sln new file mode 100644 index 00000000..1f6131b8 --- /dev/null +++ b/55_Life/csharp/Life.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Life", "Life.csproj", "{28B02688-78D1-4B3E-B998-BCC78C292D03}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {28B02688-78D1-4B3E-B998-BCC78C292D03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28B02688-78D1-4B3E-B998-BCC78C292D03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28B02688-78D1-4B3E-B998-BCC78C292D03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28B02688-78D1-4B3E-B998-BCC78C292D03}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs new file mode 100644 index 00000000..e12d5b7d --- /dev/null +++ b/55_Life/csharp/Program.cs @@ -0,0 +1,37 @@ +// See https://aka.ms/new-console-template for more information + +const int MaxWidth = 70; +const int MaxHeight = 24; + +PrintHeader(); + +int x1 = 1, y1 = 1; +int x2 = 24, y2 = 70; +var a = new float[24, 70]; +var b = new string[24]; +var c = 1; + +Console.WriteLine("ENTER YOUR PATTERN:"); +b[c] = Console.ReadLine(); +if (b[c] == "DONE") + b[c] = "" + + +void PrintHeader() +{ + const int pageWidth = 64; + + void PrintCentered(string text) + { + var spaceCount = (pageWidth - text.Length) / 2; + Console.Write(new string(' ', spaceCount)); + Console.WriteLine(text); + } + + PrintCentered("LIFE"); + PrintCentered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); +} + From ade38d696998a222e693a37916132c2cdc8dbffd Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:40:50 -0300 Subject: [PATCH 729/749] Another step. --- 55_Life/csharp/Program.cs | 151 ++++++++++++++++++++++++++++++++++---- 1 file changed, 137 insertions(+), 14 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index e12d5b7d..6a8ed618 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -1,21 +1,23 @@ // See https://aka.ms/new-console-template for more information -const int MaxWidth = 70; -const int MaxHeight = 24; +IEnumerable ReadPattern(int limitHeight) +{ + for (var i = 0; i < limitHeight; i++) + { + var input = Console.ReadLine(); + if (input.ToUpper() == "DONE") + { + yield return string.Empty; + break; + } -PrintHeader(); - -int x1 = 1, y1 = 1; -int x2 = 24, y2 = 70; -var a = new float[24, 70]; -var b = new string[24]; -var c = 1; - -Console.WriteLine("ENTER YOUR PATTERN:"); -b[c] = Console.ReadLine(); -if (b[c] == "DONE") - b[c] = "" + // kept for compatibility + if (input.StartsWith('.')) + yield return input.Substring(1, input.Length - 2); + yield return input; + } +} void PrintHeader() { @@ -35,3 +37,124 @@ void PrintHeader() Console.WriteLine(); } +(int index, string value) GetLongestInput(IEnumerable strings) +{ + return strings + .Select((value, index) => (index, value)) + .OrderByDescending(input => input.value.Length) + .First(); +} + + +PrintHeader(); + +Console.WriteLine("ENTER YOUR PATTERN:"); +// var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); +var pattern = new string[] { "a", "bdc", "", "pattern" }; // FOR DEBUGGING PURPOSES +var (index, value) = GetLongestInput(pattern); +Console.WriteLine("" + index + ", " + value); + +// B = pattern + +int x1 = (11 - index / 2) - 1; +int y1 = (33 - value.Length / 2) - 1; +const int MaxWidth = 70; // Y2 +const int MaxHeight = 24; // X2 + +var a = new int[24, 70]; // TODO understand it +int population = 0; + +// count initial population? +for (var x = 0; x < pattern.Length; x++) +{ + for (var y = 0; y < pattern[x].Length; y++) + { + if (pattern[x][y] != ' ') + { + a[x1 + x, y1 + y] = 1; + population++; + } + } +} + +void ProcessGeneration() +{ + void PrintPopulation(int generation, int population) + { + Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); + var i9 = false; // TODO understand + if (i9) + Console.WriteLine("INVALID!"); + } + int generation = 1; + PrintPopulation(generation, population); + + int x3 = MaxHeight, y3 = MaxWidth; + int x4 = 1, y4 = 1; + + for (int x = 0; x < x1; x++) + { + Console.WriteLine(); + } + + for (var x = x1; x < MaxHeight; x++) + { + Console.WriteLine(); + for (var y = y1; y < MaxWidth; y++) + { + if (a[x, y] == 2) + { + a[x, y] = 0; // birth? + continue; + } + + if (a[x, y] == 3) + { + a[x, y] = 1; + Console.WriteLine(new string('\t', y+1) + "*"); + continue; + } + + // TODO understand what it does + if (x < x3) x3 = x; + if (x > x4) x4 = x; + if (y < y3) y3 = y; + if (y < y4) y4 = y; + } + } + +} + +PrintMatrix(a); +void PrintMatrix(int[,] matrix) +{ + Console.WriteLine("Matrix:"); + for (int x = 0; x < matrix.GetLength(0); x++) + { + for (int y = 0; y < matrix.GetLength(1); y++) + { + Console.Write(matrix[x, y].ToString()); + } + Console.WriteLine(); + } +} + +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); +ProcessGeneration(); + + + + + + +// int x1 = 1, y1 = 1; +// int x2 = 24, y2 = 70; + +// var b = new string[24]; + + + + + From 53d2943f934dbbb38e78ae3e9d1d0d81e6fcfefd Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:41:28 -0300 Subject: [PATCH 730/749] Not working yet. --- 55_Life/csharp/Program.cs | 204 +++++++++++++++++++++++++++----------- 1 file changed, 148 insertions(+), 56 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 6a8ed618..ab995aa5 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -1,5 +1,7 @@ // See https://aka.ms/new-console-template for more information +using System.Xml; + IEnumerable ReadPattern(int limitHeight) { for (var i = 0; i < limitHeight; i++) @@ -50,82 +52,43 @@ PrintHeader(); Console.WriteLine("ENTER YOUR PATTERN:"); // var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); -var pattern = new string[] { "a", "bdc", "", "pattern" }; // FOR DEBUGGING PURPOSES +var pattern = new[] +{ + " ", + " * ", + " * ", + " * ", + " " +}; // FOR DEBUGGING PURPOSES var (index, value) = GetLongestInput(pattern); Console.WriteLine("" + index + ", " + value); // B = pattern -int x1 = (11 - index / 2) - 1; -int y1 = (33 - value.Length / 2) - 1; + const int MaxWidth = 70; // Y2 const int MaxHeight = 24; // X2 -var a = new int[24, 70]; // TODO understand it +var matrix = new int[24, 70]; // TODO understand it int population = 0; +var isInvalid = false; // TODO understand -// count initial population? + +int x1 = (11 - index / 2) - 1; // middle x +int y1 = (33 - value.Length / 2) - 1; // middle y for (var x = 0; x < pattern.Length; x++) { for (var y = 0; y < pattern[x].Length; y++) { if (pattern[x][y] != ' ') { - a[x1 + x, y1 + y] = 1; - population++; + matrix[x1 + x, y1 + y] = 1; // copy the pattern to the middle of the simulation + population++; // increments the population } } } -void ProcessGeneration() -{ - void PrintPopulation(int generation, int population) - { - Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); - var i9 = false; // TODO understand - if (i9) - Console.WriteLine("INVALID!"); - } - int generation = 1; - PrintPopulation(generation, population); - - int x3 = MaxHeight, y3 = MaxWidth; - int x4 = 1, y4 = 1; - - for (int x = 0; x < x1; x++) - { - Console.WriteLine(); - } - - for (var x = x1; x < MaxHeight; x++) - { - Console.WriteLine(); - for (var y = y1; y < MaxWidth; y++) - { - if (a[x, y] == 2) - { - a[x, y] = 0; // birth? - continue; - } - - if (a[x, y] == 3) - { - a[x, y] = 1; - Console.WriteLine(new string('\t', y+1) + "*"); - continue; - } - - // TODO understand what it does - if (x < x3) x3 = x; - if (x > x4) x4 = x; - if (y < y3) y3 = y; - if (y < y4) y4 = y; - } - } - -} - -PrintMatrix(a); +PrintMatrix(matrix); void PrintMatrix(int[,] matrix) { Console.WriteLine("Matrix:"); @@ -139,6 +102,135 @@ void PrintMatrix(int[,] matrix) } } + + +int generation = 0; + +void ProcessGeneration() +{ + generation++; + void PrintPopulation(int generation, int population) + { + Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); + if (isInvalid) + Console.WriteLine("INVALID!"); + } + PrintPopulation(generation, population); + + int nextMaxX = MaxHeight, nextMaxY = MaxWidth; + int nextMinX = 1, nextMinY = 1; + + for (int x = 0; x < x1; x++) + { + Console.WriteLine(); + } + + for (var x = x1; x < MaxHeight; x++) + { + Console.WriteLine(); + for (var y = y1; y < MaxWidth; y++) + { + if (matrix[x, y] == 2) + { + matrix[x, y] = 0; + continue; + } + + if (matrix[x, y] == 3) + { + matrix[x, y] = 1; // birth? + Console.WriteLine(new string(' ', y+1) + "*"); + continue; + } + + nextMinX = Math.Min(x, nextMinX); + nextMaxX = Math.Max(x, nextMaxX); + nextMinY = Math.Min(y, nextMinY); + nextMaxY = Math.Max(y, nextMaxY); + } + } + + var x2 = MaxHeight; + for (int x = x2 + 1; x < MaxHeight; x++) // TODO test +1 + { + Console.WriteLine(); + } + + x1 = nextMaxX; + x2 = nextMinX; + y1 = nextMaxY; + var y2 = nextMinY; + + // TODO boundaries? review + if (x1 < 3) + { + x1 = 3; + isInvalid = true; + } + + if (x2 > 22) + { + x2 = 22; + isInvalid = true; + } + + if (y1 < 3) + { + y1 = 3; + isInvalid = true; + } + + if (y2 > 68) + { + y2 = 68; + isInvalid = true; + } + + ProcessPopulation(); + // TODO line 635 + + void ProcessPopulation() + { + var population = 0; + for (int x = x1 - 1; x < x2 + 1; x++) // TODO review indices + { + for (int y = y1 - 1; y < y2 + 1; y++) // TODO review indices + { + var counter = 0; + for (int i = x - 1; i < x + 1; i++) + { + for (int j = y - 1; j < y + 1; j++) + { + if (matrix[i, j] == 1 || matrix[i, j] == 2) + counter++; + } + } + + if (matrix[x, y] == 0) + { + if (counter == 3) + { + matrix[x, y] = 2; + population++; + } + } + else if (counter is < 3 or > 4) + { + matrix[x, y] = 2; + } + else + { + population++; + } + } + } + } + PrintMatrix(matrix); + ProcessGeneration(); +} + + + Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); From be5e35f7e0c887b53304543d1a055326c12b9c3c Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:42:40 -0300 Subject: [PATCH 731/749] Got it working. --- 55_Life/csharp/Program.cs | 347 ++++++++++++++++++++++++-------------- 1 file changed, 216 insertions(+), 131 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index ab995aa5..0f78a6e4 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -1,6 +1,6 @@ // See https://aka.ms/new-console-template for more information -using System.Xml; +using System.Text; IEnumerable ReadPattern(int limitHeight) { @@ -47,6 +47,10 @@ void PrintHeader() .First(); } +try +{ + + PrintHeader(); @@ -54,11 +58,9 @@ Console.WriteLine("ENTER YOUR PATTERN:"); // var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); var pattern = new[] { - " ", - " * ", - " * ", - " * ", - " " + "*", + "*", + "*" }; // FOR DEBUGGING PURPOSES var (index, value) = GetLongestInput(pattern); Console.WriteLine("" + index + ", " + value); @@ -69,26 +71,42 @@ Console.WriteLine("" + index + ", " + value); const int MaxWidth = 70; // Y2 const int MaxHeight = 24; // X2 -var matrix = new int[24, 70]; // TODO understand it -int population = 0; +// var matrix = new int[24, 70]; // TODO understand it +var matrixSpace = new MatrixSpace(height: 24, width: 70); +// int population = 0; var isInvalid = false; // TODO understand -int x1 = (11 - index / 2) - 1; // middle x -int y1 = (33 - value.Length / 2) - 1; // middle y -for (var x = 0; x < pattern.Length; x++) -{ - for (var y = 0; y < pattern[x].Length; y++) + +int minX = (11 - index / 2) - 1; // middle x +int minY = (33 - value.Length / 2) - 1; // middle y +int maxX = MaxHeight; +int maxY = MaxWidth; +var simulation = InitializeSimulation(pattern, matrixSpace); + + + +Simulation InitializeSimulation(string[] inputPattern, MatrixSpace matrixToInitialize) { + var newSimulation = new Simulation(); + + for (var x = 0; x < inputPattern.Length; x++) { - if (pattern[x][y] != ' ') + for (var y = 0; y < inputPattern[x].Length; y++) { - matrix[x1 + x, y1 + y] = 1; // copy the pattern to the middle of the simulation - population++; // increments the population + if (inputPattern[x][y] != ' ') + { + matrixToInitialize.Matrix[minX + x, minY + y] = 1; // copy the pattern to the middle of the simulation + // population++; // increments the population + newSimulation.IncreasePopulation(); + } } } + + return newSimulation; } -PrintMatrix(matrix); + +// PrintMatrix(matrixSpace.Matrix); void PrintMatrix(int[,] matrix) { Console.WriteLine("Matrix:"); @@ -96,149 +114,191 @@ void PrintMatrix(int[,] matrix) { for (int y = 0; y < matrix.GetLength(1); y++) { - Console.Write(matrix[x, y].ToString()); + var character = matrix[x, y] == 0 ? ' ' : '*'; + Console.Write(character); } Console.WriteLine(); } } - - -int generation = 0; - -void ProcessGeneration() -{ - generation++; - void PrintPopulation(int generation, int population) + void ProcessGeneration() { - Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); - if (isInvalid) - Console.WriteLine("INVALID!"); - } - PrintPopulation(generation, population); - - int nextMaxX = MaxHeight, nextMaxY = MaxWidth; - int nextMinX = 1, nextMinY = 1; - - for (int x = 0; x < x1; x++) - { - Console.WriteLine(); - } - - for (var x = x1; x < MaxHeight; x++) - { - Console.WriteLine(); - for (var y = y1; y < MaxWidth; y++) + var matrix = matrixSpace.Matrix; // TODO refactor + + // generation++; + + void PrintPopulation(int generation, int population) { - if (matrix[x, y] == 2) - { - matrix[x, y] = 0; - continue; - } - - if (matrix[x, y] == 3) - { - matrix[x, y] = 1; // birth? - Console.WriteLine(new string(' ', y+1) + "*"); - continue; - } - - nextMinX = Math.Min(x, nextMinX); - nextMaxX = Math.Max(x, nextMaxX); - nextMinY = Math.Min(y, nextMinY); - nextMaxY = Math.Max(y, nextMaxY); + Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); + if (isInvalid) + Console.WriteLine("INVALID!"); } - } + PrintPopulation(simulation.Generation, simulation.Population); - var x2 = MaxHeight; - for (int x = x2 + 1; x < MaxHeight; x++) // TODO test +1 - { - Console.WriteLine(); - } + simulation.StartNewGeneration(); - x1 = nextMaxX; - x2 = nextMinX; - y1 = nextMaxY; - var y2 = nextMinY; - - // TODO boundaries? review - if (x1 < 3) - { - x1 = 3; - isInvalid = true; - } + // LINE 215 + // x3 = 24 = MaxHeight + // y3 = 70 = MaxWidth + // x4 = 1 + // y4 = 1 + // g = g + 1 - if (x2 > 22) - { - x2 = 22; - isInvalid = true; - } - - if (y1 < 3) - { - y1 = 3; - isInvalid = true; - } - - if (y2 > 68) - { - y2 = 68; - isInvalid = true; - } - - ProcessPopulation(); - // TODO line 635 - - void ProcessPopulation() - { - var population = 0; - for (int x = x1 - 1; x < x2 + 1; x++) // TODO review indices + int nextMinX = MaxHeight - 1; // x4 + int nextMinY = MaxWidth - 1; // y4 + int nextMaxX = 0; // x3 + int nextMaxY = 0; // y3 + + + // prints lines before + for (int x = 0; x < minX; x++) { - for (int y = y1 - 1; y < y2 + 1; y++) // TODO review indices + Console.WriteLine(); + } + + // prints matrix and + for (var x = minX; x < maxX; x++) + { + var printedLine = Enumerable.Repeat(' ', MaxWidth).ToList(); + for (var y = minY; y < maxY; y++) { - var counter = 0; - for (int i = x - 1; i < x + 1; i++) + if (matrix[x, y] == 2) { - for (int j = y - 1; j < y + 1; j++) - { - if (matrix[i, j] == 1 || matrix[i, j] == 2) - counter++; - } + matrix[x, y] = 0; + continue; + } + if (matrix[x, y] == 3) + { + matrix[x, y] = 1; + } + else if (matrix[x, y] != 1) + { + continue; } - if (matrix[x, y] == 0) + printedLine[y] = '*'; + + nextMinX = Math.Min(x, nextMinX); + nextMaxX = Math.Max(x+1, nextMaxX); + nextMinY = Math.Min(y, nextMinY); + nextMaxY = Math.Max(y+1, nextMaxY); + } + Console.WriteLine(string.Join(separator: null, values: printedLine)); + } + + // prints lines after + for (int x = maxX + 1; x < MaxHeight; x++) // TODO test +1 + { + Console.WriteLine(); + } + Console.WriteLine(); + + minX = nextMinX; + maxX = nextMaxX; + minY = nextMinY; + maxY = nextMaxY; + + // TODO boundaries? review + if (minX < 3) + { + minX = 3; + isInvalid = true; + } + if (maxX > 22) + { + maxX = 22; + isInvalid = true; + } + if (minY < 3) + { + minY = 3; + isInvalid = true; + } + if (maxY > 68) + { + maxY = 68; + isInvalid = true; + } + + // LINE 309 + ProcessPopulation(); + + void ProcessPopulation() + { + // var population = 0; + for (int x = minX - 1; x < maxX + 2; x++) // TODO review indices + { + for (int y = minY - 1; y < maxY + 2; y++) // TODO review indices { - if (counter == 3) + var neighbors = 0; + for (int i = x - 1; i < x + 2; i++) // TODO review indices + { + for (int j = y - 1; j < y + 2; j++) // TODO review indices + { + if (matrix[i, j] == 1 || matrix[i, j] == 2) + neighbors++; + } + } + // PrintMatrix(matrix); + if (matrix[x, y] == 0) + { + if (neighbors == 3) + { + matrix[x, y] = 3; + // population++; + simulation.IncreasePopulation(); + } + } + else if (neighbors is < 3 or > 4) { matrix[x, y] = 2; - population++; + } + else + { + // population++; + simulation.IncreasePopulation(); } } - else if (counter is < 3 or > 4) - { - matrix[x, y] = 2; - } - else - { - population++; - } } + + // LINE 635 + minX--; + minY--; + maxX++; + maxY++; } + // PrintMatrix(matrix); + ProcessGeneration(); } - PrintMatrix(matrix); + + + + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); ProcessGeneration(); } +catch (Exception e) +{ + Console.WriteLine(e); +} +public class Simulation +{ + public int Generation { get; private set; } + public int Population { get; private set; } + public void StartNewGeneration() + { + Generation++; + Population = 0; + } -Console.WriteLine(); -Console.WriteLine(); -Console.WriteLine(); -ProcessGeneration(); - - - - + public void IncreasePopulation() + { + Population++; + } +} // int x1 = 1, y1 = 1; @@ -250,3 +310,28 @@ ProcessGeneration(); +public class MatrixSpace +{ + public int[,] Matrix { get; } + + public MatrixSpace(int height, int width) + { + Matrix = new int[height, width]; + } + + public override string ToString() + { + var stringBuilder = new StringBuilder(); + for (var x = 0; x < Matrix.GetLength(0); x++) + { + for (var y = 0; y < Matrix.GetLength(1); y++) + { + var character = Matrix[x, y] == 0 ? " ": Matrix[x, y].ToString(); + stringBuilder.Append(character); + } + + stringBuilder.AppendLine(); + } + return stringBuilder.ToString(); + } +} From 44b1ada7d4882f59cd8b51b33c2deb221722de31 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:43:14 -0300 Subject: [PATCH 732/749] Eliminated StackOverflow bug. --- 55_Life/csharp/Program.cs | 66 +++++++++++++++------------------------ 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 0f78a6e4..0496fd91 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -47,10 +47,6 @@ void PrintHeader() .First(); } -try -{ - - PrintHeader(); @@ -106,33 +102,22 @@ Simulation InitializeSimulation(string[] inputPattern, MatrixSpace matrixToIniti } -// PrintMatrix(matrixSpace.Matrix); -void PrintMatrix(int[,] matrix) +void ProcessGeneration() { - Console.WriteLine("Matrix:"); - for (int x = 0; x < matrix.GetLength(0); x++) - { - for (int y = 0; y < matrix.GetLength(1); y++) - { - var character = matrix[x, y] == 0 ? ' ' : '*'; - Console.Write(character); - } - Console.WriteLine(); - } -} + var matrix = matrixSpace.Matrix; // TODO refactor - void ProcessGeneration() + while (true) { - var matrix = matrixSpace.Matrix; // TODO refactor - + // generation++; - + void PrintPopulation(int generation, int population) { Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); if (isInvalid) Console.WriteLine("INVALID!"); } + PrintPopulation(simulation.Generation, simulation.Population); simulation.StartNewGeneration(); @@ -148,14 +133,14 @@ void PrintMatrix(int[,] matrix) int nextMinY = MaxWidth - 1; // y4 int nextMaxX = 0; // x3 int nextMaxY = 0; // y3 - - + + // prints lines before for (int x = 0; x < minX; x++) { Console.WriteLine(); } - + // prints matrix and for (var x = minX; x < maxX; x++) { @@ -164,9 +149,10 @@ void PrintMatrix(int[,] matrix) { if (matrix[x, y] == 2) { - matrix[x, y] = 0; + matrix[x, y] = 0; continue; } + if (matrix[x, y] == 3) { matrix[x, y] = 1; @@ -179,10 +165,11 @@ void PrintMatrix(int[,] matrix) printedLine[y] = '*'; nextMinX = Math.Min(x, nextMinX); - nextMaxX = Math.Max(x+1, nextMaxX); + nextMaxX = Math.Max(x + 1, nextMaxX); nextMinY = Math.Min(y, nextMinY); - nextMaxY = Math.Max(y+1, nextMaxY); + nextMaxY = Math.Max(y + 1, nextMaxY); } + Console.WriteLine(string.Join(separator: null, values: printedLine)); } @@ -191,29 +178,33 @@ void PrintMatrix(int[,] matrix) { Console.WriteLine(); } + Console.WriteLine(); minX = nextMinX; maxX = nextMaxX; minY = nextMinY; maxY = nextMaxY; - + // TODO boundaries? review if (minX < 3) { minX = 3; isInvalid = true; } + if (maxX > 22) { maxX = 22; isInvalid = true; } + if (minY < 3) { minY = 3; isInvalid = true; } + if (maxY > 68) { maxY = 68; @@ -239,6 +230,7 @@ void PrintMatrix(int[,] matrix) neighbors++; } } + // PrintMatrix(matrix); if (matrix[x, y] == 0) { @@ -268,20 +260,14 @@ void PrintMatrix(int[,] matrix) maxY++; } // PrintMatrix(matrix); - ProcessGeneration(); } - - - - Console.WriteLine(); - Console.WriteLine(); - Console.WriteLine(); - ProcessGeneration(); -} -catch (Exception e) -{ - Console.WriteLine(e); } + +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); +ProcessGeneration(); + public class Simulation { public int Generation { get; private set; } From d9ab235585aab5558a2c10d6211ad192bf9e7c27 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:43:44 -0300 Subject: [PATCH 733/749] Some initial refactorings. --- 55_Life/csharp/Program.cs | 201 +++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 111 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 0496fd91..ec925faa 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -39,16 +39,10 @@ void PrintHeader() Console.WriteLine(); } -(int index, string value) GetLongestInput(IEnumerable strings) -{ - return strings - .Select((value, index) => (index, value)) - .OrderByDescending(input => input.value.Length) - .First(); -} -PrintHeader(); + + Console.WriteLine("ENTER YOUR PATTERN:"); // var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); @@ -58,59 +52,59 @@ var pattern = new[] "*", "*" }; // FOR DEBUGGING PURPOSES +// var pattern = new[] +// { +// "**", +// "**", +// }; // FOR DEBUGGING PURPOSES +// var pattern = new[] +// { +// "***", +// "*", +// }; // FOR DEBUGGING PURPOSES + + +const int MaxWidth = 70; +const int MaxHeight = 24; + +var isInvalid = false; + var (index, value) = GetLongestInput(pattern); -Console.WriteLine("" + index + ", " + value); - -// B = pattern - - -const int MaxWidth = 70; // Y2 -const int MaxHeight = 24; // X2 - -// var matrix = new int[24, 70]; // TODO understand it -var matrixSpace = new MatrixSpace(height: 24, width: 70); -// int population = 0; -var isInvalid = false; // TODO understand - - - int minX = (11 - index / 2) - 1; // middle x int minY = (33 - value.Length / 2) - 1; // middle y int maxX = MaxHeight; int maxY = MaxWidth; -var simulation = InitializeSimulation(pattern, matrixSpace); +var matrix = new Matrix(height: MaxHeight, width: MaxWidth); +var simulation = InitializeSimulation(pattern, matrix); + +PrintHeader(); +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); +ProcessGeneration(); - -Simulation InitializeSimulation(string[] inputPattern, MatrixSpace matrixToInitialize) { +Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matrixToInitialize) { var newSimulation = new Simulation(); - for (var x = 0; x < inputPattern.Length; x++) + for (var x = 0; x < inputPattern.Count; x++) { for (var y = 0; y < inputPattern[x].Length; y++) { - if (inputPattern[x][y] != ' ') - { - matrixToInitialize.Matrix[minX + x, minY + y] = 1; // copy the pattern to the middle of the simulation - // population++; // increments the population - newSimulation.IncreasePopulation(); - } + if (inputPattern[x][y] == ' ') continue; + + matrixToInitialize[minX + x, minY + y] = 1; // copy the pattern to the middle of the simulation + newSimulation.IncreasePopulation(); } } return newSimulation; } - void ProcessGeneration() { - var matrix = matrixSpace.Matrix; // TODO refactor - while (true) { - - // generation++; - void PrintPopulation(int generation, int population) { Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); @@ -123,25 +117,18 @@ void ProcessGeneration() simulation.StartNewGeneration(); // LINE 215 - // x3 = 24 = MaxHeight - // y3 = 70 = MaxWidth - // x4 = 1 - // y4 = 1 - // g = g + 1 + var nextMinX = MaxHeight - 1; + var nextMinY = MaxWidth - 1; + var nextMaxX = 0; + var nextMaxY = 0; - int nextMinX = MaxHeight - 1; // x4 - int nextMinY = MaxWidth - 1; // y4 - int nextMaxX = 0; // x3 - int nextMaxY = 0; // y3 - - - // prints lines before - for (int x = 0; x < minX; x++) + // prints empty lines before alive cells + for (var x = 0; x < minX; x++) { Console.WriteLine(); } - // prints matrix and + // refreshes the matrix and updates search area for (var x = minX; x < maxX; x++) { var printedLine = Enumerable.Repeat(' ', MaxWidth).ToList(); @@ -152,7 +139,6 @@ void ProcessGeneration() matrix[x, y] = 0; continue; } - if (matrix[x, y] == 3) { matrix[x, y] = 1; @@ -173,12 +159,11 @@ void ProcessGeneration() Console.WriteLine(string.Join(separator: null, values: printedLine)); } - // prints lines after - for (int x = maxX + 1; x < MaxHeight; x++) // TODO test +1 + // prints empty lines after alive cells + for (int x = maxX + 1; x < MaxHeight; x++) { Console.WriteLine(); } - Console.WriteLine(); minX = nextMinX; @@ -211,62 +196,60 @@ void ProcessGeneration() isInvalid = true; } - // LINE 309 - ProcessPopulation(); - - void ProcessPopulation() + for (var x = minX - 1; x < maxX + 2; x++) { - // var population = 0; - for (int x = minX - 1; x < maxX + 2; x++) // TODO review indices + for (var y = minY - 1; y < maxY + 2; y++) { - for (int y = minY - 1; y < maxY + 2; y++) // TODO review indices + int CountNeighbors() { var neighbors = 0; - for (int i = x - 1; i < x + 2; i++) // TODO review indices + for (var i = x - 1; i < x + 2; i++) { - for (int j = y - 1; j < y + 2; j++) // TODO review indices + for (var j = y - 1; j < y + 2; j++) { if (matrix[i, j] == 1 || matrix[i, j] == 2) neighbors++; } } - // PrintMatrix(matrix); - if (matrix[x, y] == 0) + return neighbors; + } + + var neighbors = CountNeighbors(); + if (matrix[x, y] == 0) + { + if (neighbors == 3) { - if (neighbors == 3) - { - matrix[x, y] = 3; - // population++; - simulation.IncreasePopulation(); - } - } - else if (neighbors is < 3 or > 4) - { - matrix[x, y] = 2; - } - else - { - // population++; + matrix[x, y] = 3; simulation.IncreasePopulation(); } } + else if (neighbors is < 3 or > 4) + { + matrix[x, y] = 2; + } + else + { + simulation.IncreasePopulation(); + } } - - // LINE 635 - minX--; - minY--; - maxX++; - maxY++; } - // PrintMatrix(matrix); + + // expands search area to accommodate new cells + minX--; + minY--; + maxX++; + maxY++; } } -Console.WriteLine(); -Console.WriteLine(); -Console.WriteLine(); -ProcessGeneration(); +(int index, string value) GetLongestInput(IEnumerable strings) +{ + return strings + .Select((value, index) => (index, value)) + .OrderByDescending(input => input.value.Length) + .First(); +} public class Simulation { @@ -286,33 +269,29 @@ public class Simulation } } - -// int x1 = 1, y1 = 1; -// int x2 = 24, y2 = 70; - -// var b = new string[24]; - - - - - -public class MatrixSpace +class Matrix { - public int[,] Matrix { get; } + private readonly int[,] _matrix; - public MatrixSpace(int height, int width) + public Matrix(int height, int width) { - Matrix = new int[height, width]; + _matrix = new int[height, width]; } + public int this[int x, int y] + { + get => _matrix[x, y]; + set => _matrix[x, y] = value; + } + public override string ToString() { var stringBuilder = new StringBuilder(); - for (var x = 0; x < Matrix.GetLength(0); x++) + for (var x = 0; x < _matrix.GetLength(0); x++) { - for (var y = 0; y < Matrix.GetLength(1); y++) + for (var y = 0; y < _matrix.GetLength(1); y++) { - var character = Matrix[x, y] == 0 ? " ": Matrix[x, y].ToString(); + var character = _matrix[x, y] == 0 ? " ": _matrix[x, y].ToString(); stringBuilder.Append(character); } @@ -320,4 +299,4 @@ public class MatrixSpace } return stringBuilder.ToString(); } -} +} \ No newline at end of file From e53b9d9cf18fc89e6aa34130b5eb1b16cd8e782b Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:44:13 -0300 Subject: [PATCH 734/749] Further refactoring, naming procedures. --- 55_Life/csharp/Program.cs | 186 ++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 97 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index ec925faa..cc594435 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -2,47 +2,8 @@ using System.Text; -IEnumerable ReadPattern(int limitHeight) -{ - for (var i = 0; i < limitHeight; i++) - { - var input = Console.ReadLine(); - if (input.ToUpper() == "DONE") - { - yield return string.Empty; - break; - } - - // kept for compatibility - if (input.StartsWith('.')) - yield return input.Substring(1, input.Length - 2); - - yield return input; - } -} - -void PrintHeader() -{ - const int pageWidth = 64; - - void PrintCentered(string text) - { - var spaceCount = (pageWidth - text.Length) / 2; - Console.Write(new string(' ', spaceCount)); - Console.WriteLine(text); - } - - PrintCentered("LIFE"); - PrintCentered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - Console.WriteLine(); - Console.WriteLine(); - Console.WriteLine(); -} - - - - - +const int MaxWidth = 70; +const int MaxHeight = 24; Console.WriteLine("ENTER YOUR PATTERN:"); // var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); @@ -63,26 +24,63 @@ var pattern = new[] // "*", // }; // FOR DEBUGGING PURPOSES - -const int MaxWidth = 70; -const int MaxHeight = 24; - var isInvalid = false; -var (index, value) = GetLongestInput(pattern); -int minX = (11 - index / 2) - 1; // middle x -int minY = (33 - value.Length / 2) - 1; // middle y -int maxX = MaxHeight; -int maxY = MaxWidth; +var (index, value) = FindLongestInput(pattern); +var minX = (11 - index / 2) - 1; // middle x +var minY = (33 - value.Length / 2) - 1; // middle y +var maxX = MaxHeight; +var maxY = MaxWidth; var matrix = new Matrix(height: MaxHeight, width: MaxWidth); var simulation = InitializeSimulation(pattern, matrix); PrintHeader(); -Console.WriteLine(); -Console.WriteLine(); -Console.WriteLine(); ProcessGeneration(); +IEnumerable ReadPattern(int limitHeight) +{ + for (var i = 0; i < limitHeight; i++) + { + var input = Console.ReadLine(); + if (input.ToUpper() == "DONE") + { + yield return string.Empty; + break; + } + + // kept for compatibility + if (input.StartsWith('.')) + yield return input.Substring(1, input.Length - 2); + + yield return input; + } +} + +(int index, string value) FindLongestInput(IEnumerable strings) +{ + return strings + .Select((value, index) => (index, value)) + .OrderByDescending(input => input.value.Length) + .First(); +} + +void PrintHeader() +{ + void PrintCentered(string text) + { + const int pageWidth = 64; + + var spaceCount = (pageWidth - text.Length) / 2; + Console.Write(new string(' ', spaceCount)); + Console.WriteLine(text); + } + + PrintCentered("LIFE"); + PrintCentered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); +} Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matrixToInitialize) { var newSimulation = new Simulation(); @@ -103,26 +101,24 @@ Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matri void ProcessGeneration() { + void PrintPopulation(int generation, int population) + { + Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); + if (isInvalid) + Console.WriteLine("INVALID!"); + } + while (true) { - void PrintPopulation(int generation, int population) - { - Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); - if (isInvalid) - Console.WriteLine("INVALID!"); - } - PrintPopulation(simulation.Generation, simulation.Population); - simulation.StartNewGeneration(); - // LINE 215 var nextMinX = MaxHeight - 1; var nextMinY = MaxWidth - 1; var nextMaxX = 0; var nextMaxY = 0; - // prints empty lines before alive cells + // prints the empty lines before search area for (var x = 0; x < minX; x++) { Console.WriteLine(); @@ -159,42 +155,46 @@ void ProcessGeneration() Console.WriteLine(string.Join(separator: null, values: printedLine)); } - // prints empty lines after alive cells - for (int x = maxX + 1; x < MaxHeight; x++) + // prints empty lines after search area + for (var x = maxX + 1; x < MaxHeight; x++) { Console.WriteLine(); } Console.WriteLine(); - minX = nextMinX; - maxX = nextMaxX; - minY = nextMinY; - maxY = nextMaxY; - - // TODO boundaries? review - if (minX < 3) + void UpdateSearchArea() { - minX = 3; - isInvalid = true; - } + minX = nextMinX; + maxX = nextMaxX; + minY = nextMinY; + maxY = nextMaxY; - if (maxX > 22) - { - maxX = 22; - isInvalid = true; - } + // TODO boundaries? review + if (minX < 3) + { + minX = 3; + isInvalid = true; + } - if (minY < 3) - { - minY = 3; - isInvalid = true; - } + if (maxX > 22) + { + maxX = 22; + isInvalid = true; + } - if (maxY > 68) - { - maxY = 68; - isInvalid = true; + if (minY < 3) + { + minY = 3; + isInvalid = true; + } + + if (maxY > 68) + { + maxY = 68; + isInvalid = true; + } } + UpdateSearchArea(); for (var x = minX - 1; x < maxX + 2; x++) { @@ -243,14 +243,6 @@ void ProcessGeneration() } } -(int index, string value) GetLongestInput(IEnumerable strings) -{ - return strings - .Select((value, index) => (index, value)) - .OrderByDescending(input => input.value.Length) - .First(); -} - public class Simulation { public int Generation { get; private set; } From 778af346d723fec512d30e451ad84a22ab1cb9a6 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:45:00 -0300 Subject: [PATCH 735/749] Added enum Cell to enhance clarity. --- 55_Life/csharp/Program.cs | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index cc594435..0abb68f1 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -1,10 +1,13 @@ // See https://aka.ms/new-console-template for more information +using System.Drawing; using System.Text; const int MaxWidth = 70; const int MaxHeight = 24; + + Console.WriteLine("ENTER YOUR PATTERN:"); // var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); var pattern = new[] @@ -91,7 +94,7 @@ Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matri { if (inputPattern[x][y] == ' ') continue; - matrixToInitialize[minX + x, minY + y] = 1; // copy the pattern to the middle of the simulation + matrixToInitialize[minX + x, minY + y] = Cell.NeutralCell; // copy the pattern to the middle of the simulation newSimulation.IncreasePopulation(); } } @@ -130,16 +133,16 @@ void ProcessGeneration() var printedLine = Enumerable.Repeat(' ', MaxWidth).ToList(); for (var y = minY; y < maxY; y++) { - if (matrix[x, y] == 2) + if (matrix[x, y] == Cell.DyingCel) { matrix[x, y] = 0; continue; } - if (matrix[x, y] == 3) + if (matrix[x, y] == Cell.NewCell) { - matrix[x, y] = 1; + matrix[x, y] = Cell.NeutralCell; } - else if (matrix[x, y] != 1) + else if (matrix[x, y] != Cell.NeutralCell) { continue; } @@ -207,7 +210,7 @@ void ProcessGeneration() { for (var j = y - 1; j < y + 2; j++) { - if (matrix[i, j] == 1 || matrix[i, j] == 2) + if (matrix[i, j] == Cell.NeutralCell || matrix[i, j] == Cell.DyingCel) neighbors++; } } @@ -220,13 +223,13 @@ void ProcessGeneration() { if (neighbors == 3) { - matrix[x, y] = 3; + matrix[x, y] = Cell.NewCell; simulation.IncreasePopulation(); } } else if (neighbors is < 3 or > 4) { - matrix[x, y] = 2; + matrix[x, y] = Cell.DyingCel; } else { @@ -243,6 +246,14 @@ void ProcessGeneration() } } +internal enum Cell +{ + EmptyCell = 0, + NeutralCell = 1, + DyingCel = 2, + NewCell =3 +} + public class Simulation { public int Generation { get; private set; } @@ -263,14 +274,14 @@ public class Simulation class Matrix { - private readonly int[,] _matrix; + private readonly Cell[,] _matrix; public Matrix(int height, int width) { - _matrix = new int[height, width]; + _matrix = new Cell[height, width]; } - public int this[int x, int y] + public Cell this[int x, int y] { get => _matrix[x, y]; set => _matrix[x, y] = value; @@ -283,7 +294,7 @@ class Matrix { for (var y = 0; y < _matrix.GetLength(1); y++) { - var character = _matrix[x, y] == 0 ? " ": _matrix[x, y].ToString(); + var character = _matrix[x, y] == 0 ? " ": ((int)_matrix[x, y]).ToString(); stringBuilder.Append(character); } From 4870a14909b6055440c0445b5db1571004353518 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:45:34 -0300 Subject: [PATCH 736/749] Refactoring, plus adding real user input again. --- 55_Life/csharp/Program.cs | 72 ++++++++++++++------------------------- 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 0abb68f1..b9aef5dd 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -1,40 +1,16 @@ -// See https://aka.ms/new-console-template for more information - -using System.Drawing; -using System.Text; - -const int MaxWidth = 70; -const int MaxHeight = 24; - +using System.Text; +const int maxWidth = 70; +const int maxHeight = 24; Console.WriteLine("ENTER YOUR PATTERN:"); -// var pattern = ReadPattern(limitHeight: MaxHeight).ToArray(); -var pattern = new[] -{ - "*", - "*", - "*" -}; // FOR DEBUGGING PURPOSES -// var pattern = new[] -// { -// "**", -// "**", -// }; // FOR DEBUGGING PURPOSES -// var pattern = new[] -// { -// "***", -// "*", -// }; // FOR DEBUGGING PURPOSES +var pattern = ReadPattern(limitHeight: maxHeight).ToArray(); -var isInvalid = false; +var (minX, minY) = FindTopLeftCorner(pattern); +var maxX = maxHeight; +var maxY = maxWidth; -var (index, value) = FindLongestInput(pattern); -var minX = (11 - index / 2) - 1; // middle x -var minY = (33 - value.Length / 2) - 1; // middle y -var maxX = MaxHeight; -var maxY = MaxWidth; -var matrix = new Matrix(height: MaxHeight, width: MaxWidth); +var matrix = new Matrix(height: maxHeight, width: maxWidth); var simulation = InitializeSimulation(pattern, matrix); PrintHeader(); @@ -59,12 +35,15 @@ IEnumerable ReadPattern(int limitHeight) } } -(int index, string value) FindLongestInput(IEnumerable strings) +(int minX, int minY) FindTopLeftCorner(IEnumerable patternLines) { - return strings + var longestInput = patternLines .Select((value, index) => (index, value)) .OrderByDescending(input => input.value.Length) .First(); + var centerX = (11 - longestInput.index / 2) - 1; + var centerY = (33 - longestInput.value.Length / 2) - 1; + return (centerX, centerY); } void PrintHeader() @@ -88,13 +67,14 @@ void PrintHeader() Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matrixToInitialize) { var newSimulation = new Simulation(); + // copies the pattern to the middle of the simulation and counts initial population for (var x = 0; x < inputPattern.Count; x++) { for (var y = 0; y < inputPattern[x].Length; y++) { if (inputPattern[x][y] == ' ') continue; - matrixToInitialize[minX + x, minY + y] = Cell.NeutralCell; // copy the pattern to the middle of the simulation + matrixToInitialize[minX + x, minY + y] = Cell.NeutralCell; newSimulation.IncreasePopulation(); } } @@ -104,20 +84,19 @@ Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matri void ProcessGeneration() { - void PrintPopulation(int generation, int population) - { - Console.WriteLine($"GENERATION: {generation}\tPOPULATION: {population}"); - if (isInvalid) - Console.WriteLine("INVALID!"); - } + var isInvalid = false; while (true) { - PrintPopulation(simulation.Generation, simulation.Population); + // Thread.Sleep(millisecondsTimeout: 1000); + Console.WriteLine($"GENERATION: {simulation.Generation}\tPOPULATION: {simulation.Population}"); + if (isInvalid) + Console.WriteLine("INVALID!"); + simulation.StartNewGeneration(); - var nextMinX = MaxHeight - 1; - var nextMinY = MaxWidth - 1; + var nextMinX = maxHeight - 1; + var nextMinY = maxWidth - 1; var nextMaxX = 0; var nextMaxY = 0; @@ -130,7 +109,7 @@ void ProcessGeneration() // refreshes the matrix and updates search area for (var x = minX; x < maxX; x++) { - var printedLine = Enumerable.Repeat(' ', MaxWidth).ToList(); + var printedLine = Enumerable.Repeat(' ', maxWidth).ToList(); for (var y = minY; y < maxY; y++) { if (matrix[x, y] == Cell.DyingCel) @@ -159,7 +138,7 @@ void ProcessGeneration() } // prints empty lines after search area - for (var x = maxX + 1; x < MaxHeight; x++) + for (var x = maxX + 1; x < maxHeight; x++) { Console.WriteLine(); } @@ -172,7 +151,6 @@ void ProcessGeneration() minY = nextMinY; maxY = nextMaxY; - // TODO boundaries? review if (minX < 3) { minX = 3; From cd478a4a948d575ebb0ab55f34f555ac95c93bd8 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:46:07 -0300 Subject: [PATCH 737/749] Added argument to configure a pause in between iterations, allowing the player to enjoy watching the evolution of the game of life. --- 55_Life/csharp/Program.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index b9aef5dd..07a06eac 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -82,13 +82,32 @@ Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matri return newSimulation; } +TimeSpan GetPauseBetweenIterations() +{ + if (args.Length == 2) + { + var parameter = args[0].ToLower(); + if (parameter.Contains("wait")) + { + var value = args[1]; + if (int.TryParse(value, out var sleepMilliseconds)) + return TimeSpan.FromMilliseconds(sleepMilliseconds); + } + } + + return TimeSpan.Zero; +} + void ProcessGeneration() { + var pauseBetweenIterations = GetPauseBetweenIterations(); var isInvalid = false; while (true) { - // Thread.Sleep(millisecondsTimeout: 1000); + if (pauseBetweenIterations > TimeSpan.Zero) + Thread.Sleep(pauseBetweenIterations); + Console.WriteLine($"GENERATION: {simulation.Generation}\tPOPULATION: {simulation.Population}"); if (isInvalid) Console.WriteLine("INVALID!"); From 3ffd2fdc520145d42b65becb51b6ae9cc87163aa Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:46:39 -0300 Subject: [PATCH 738/749] Refactoring and documenting the solution. --- 55_Life/csharp/Program.cs | 50 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 07a06eac..f2b66b88 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -14,7 +14,7 @@ var matrix = new Matrix(height: maxHeight, width: maxWidth); var simulation = InitializeSimulation(pattern, matrix); PrintHeader(); -ProcessGeneration(); +ProcessSimulation(); IEnumerable ReadPattern(int limitHeight) { @@ -27,7 +27,9 @@ IEnumerable ReadPattern(int limitHeight) break; } - // kept for compatibility + // In the original version, BASIC would trim the spaces in the beginning of an input, so the original + // game allowed you to input an '.' before the spaces to circumvent this limitation. This behavior was + // kept for compatibility. if (input.StartsWith('.')) yield return input.Substring(1, input.Length - 2); @@ -67,14 +69,14 @@ void PrintHeader() Simulation InitializeSimulation(IReadOnlyList inputPattern, Matrix matrixToInitialize) { var newSimulation = new Simulation(); - // copies the pattern to the middle of the simulation and counts initial population + // translates the pattern to the middle of the simulation and counts initial population for (var x = 0; x < inputPattern.Count; x++) { for (var y = 0; y < inputPattern[x].Length; y++) { if (inputPattern[x][y] == ' ') continue; - matrixToInitialize[minX + x, minY + y] = Cell.NeutralCell; + matrixToInitialize[minX + x, minY + y] = CellState.Stable; newSimulation.IncreasePopulation(); } } @@ -98,7 +100,7 @@ TimeSpan GetPauseBetweenIterations() return TimeSpan.Zero; } -void ProcessGeneration() +void ProcessSimulation() { var pauseBetweenIterations = GetPauseBetweenIterations(); var isInvalid = false; @@ -131,16 +133,16 @@ void ProcessGeneration() var printedLine = Enumerable.Repeat(' ', maxWidth).ToList(); for (var y = minY; y < maxY; y++) { - if (matrix[x, y] == Cell.DyingCel) + if (matrix[x, y] == CellState.Dying) { - matrix[x, y] = 0; + matrix[x, y] = CellState.Empty; continue; } - if (matrix[x, y] == Cell.NewCell) + if (matrix[x, y] == CellState.New) { - matrix[x, y] = Cell.NeutralCell; + matrix[x, y] = CellState.Stable; } - else if (matrix[x, y] != Cell.NeutralCell) + else if (matrix[x, y] != CellState.Stable) { continue; } @@ -207,7 +209,7 @@ void ProcessGeneration() { for (var j = y - 1; j < y + 2; j++) { - if (matrix[i, j] == Cell.NeutralCell || matrix[i, j] == Cell.DyingCel) + if (matrix[i, j] == CellState.Stable || matrix[i, j] == CellState.Dying) neighbors++; } } @@ -220,13 +222,13 @@ void ProcessGeneration() { if (neighbors == 3) { - matrix[x, y] = Cell.NewCell; + matrix[x, y] = CellState.New; simulation.IncreasePopulation(); } } else if (neighbors is < 3 or > 4) { - matrix[x, y] = Cell.DyingCel; + matrix[x, y] = CellState.Dying; } else { @@ -243,12 +245,15 @@ void ProcessGeneration() } } -internal enum Cell +/// +/// Indicates the state of a given cell in the simulation. +/// +internal enum CellState { - EmptyCell = 0, - NeutralCell = 1, - DyingCel = 2, - NewCell =3 + Empty = 0, + Stable = 1, + Dying = 2, + New = 3 } public class Simulation @@ -269,16 +274,19 @@ public class Simulation } } +/// +/// This class was created to aid debugging, through the implementation of the ToString() method. +/// class Matrix { - private readonly Cell[,] _matrix; + private readonly CellState[,] _matrix; public Matrix(int height, int width) { - _matrix = new Cell[height, width]; + _matrix = new CellState[height, width]; } - public Cell this[int x, int y] + public CellState this[int x, int y] { get => _matrix[x, y]; set => _matrix[x, y] = value; From c7c3d68a2eed69735ae4664f3c0d7925f9545464 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:47:08 -0300 Subject: [PATCH 739/749] Moving pause location to the end of iteration. --- 55_Life/csharp/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index f2b66b88..1c21b5f7 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -107,9 +107,6 @@ void ProcessSimulation() while (true) { - if (pauseBetweenIterations > TimeSpan.Zero) - Thread.Sleep(pauseBetweenIterations); - Console.WriteLine($"GENERATION: {simulation.Generation}\tPOPULATION: {simulation.Population}"); if (isInvalid) Console.WriteLine("INVALID!"); @@ -242,6 +239,9 @@ void ProcessSimulation() minY--; maxX++; maxY++; + + if (pauseBetweenIterations > TimeSpan.Zero) + Thread.Sleep(pauseBetweenIterations); } } From 985e1886ac32763896a363f585e7c7f5618b3a31 Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:48:13 -0300 Subject: [PATCH 740/749] Adding comment about the port. --- 55_Life/csharp/Program.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 1c21b5f7..2ed1ec62 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -1,4 +1,16 @@ -using System.Text; +/* + * LIFE + * An implementation of John Conway's popular cellular automaton + * Ported by Dyego Alekssander Maas + * + * An example pattern would be: + * " * " + * "***" + * "DONE" (indicates that the simulation can start) + * + * You can find patterns to play with here: http://pi.math.cornell.edu/~lipa/mec/lesson6.html +*/ +using System.Text; const int maxWidth = 70; const int maxHeight = 24; From 8c02ea39d272a157613318a0884cea6fc734faca Mon Sep 17 00:00:00 2001 From: Dyego Maas Date: Tue, 11 Jan 2022 20:58:07 -0300 Subject: [PATCH 741/749] Documented the --wait argument. --- 55_Life/csharp/Program.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/55_Life/csharp/Program.cs b/55_Life/csharp/Program.cs index 2ed1ec62..47ed7386 100644 --- a/55_Life/csharp/Program.cs +++ b/55_Life/csharp/Program.cs @@ -9,6 +9,10 @@ * "DONE" (indicates that the simulation can start) * * You can find patterns to play with here: http://pi.math.cornell.edu/~lipa/mec/lesson6.html + * + * Optionally, you can run this program with the "--wait 1000" argument, the number being the time in milliseconds + * that the application will pause between each iteration. This is enables you to watch the simulation unfolding. + * By default, there is no pause between iterations. */ using System.Text; From b28a12f52afec5cd5955190dbd189015d8c05f78 Mon Sep 17 00:00:00 2001 From: Tim Buchalka <70119791+journich@users.noreply.github.com> Date: Wed, 12 Jan 2022 12:22:37 +1030 Subject: [PATCH 742/749] Document both contributions of this game Notes relating to both contributed versions of Acey Ducey for Java. --- 01_Acey_Ducey/java/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/01_Acey_Ducey/java/README.md b/01_Acey_Ducey/java/README.md index 51edd8d4..4153020a 100644 --- a/01_Acey_Ducey/java/README.md +++ b/01_Acey_Ducey/java/README.md @@ -1,3 +1,9 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Oracle Java](https://openjdk.java.net/) + +Two versions of Acey Ducey have been contributed. + +The original upload supported JDK 8/JDK 11 and uses multiple files and the second uses features in JDK 17 and is implemented in a single file AceyDucey17.java. + +Both are in the src folder. From daa06846bf2de4b3e57ba10c1e0c0b8491a0dae5 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 20:59:56 -0500 Subject: [PATCH 743/749] moved implementations to individual folders --- 75_Roulette/java/{src => iterative}/Roulette.java | 0 75_Roulette/java/{ => oop}/Bet.java | 0 75_Roulette/java/{ => oop}/Roulette.java | 0 75_Roulette/java/{ => oop}/Wheel.java | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename 75_Roulette/java/{src => iterative}/Roulette.java (100%) rename 75_Roulette/java/{ => oop}/Bet.java (100%) rename 75_Roulette/java/{ => oop}/Roulette.java (100%) rename 75_Roulette/java/{ => oop}/Wheel.java (100%) diff --git a/75_Roulette/java/src/Roulette.java b/75_Roulette/java/iterative/Roulette.java similarity index 100% rename from 75_Roulette/java/src/Roulette.java rename to 75_Roulette/java/iterative/Roulette.java diff --git a/75_Roulette/java/Bet.java b/75_Roulette/java/oop/Bet.java similarity index 100% rename from 75_Roulette/java/Bet.java rename to 75_Roulette/java/oop/Bet.java diff --git a/75_Roulette/java/Roulette.java b/75_Roulette/java/oop/Roulette.java similarity index 100% rename from 75_Roulette/java/Roulette.java rename to 75_Roulette/java/oop/Roulette.java diff --git a/75_Roulette/java/Wheel.java b/75_Roulette/java/oop/Wheel.java similarity index 100% rename from 75_Roulette/java/Wheel.java rename to 75_Roulette/java/oop/Wheel.java From 76d5f2dde2dfc0422895aa6f9b93fc59ba9dd3ba Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 21:03:33 -0500 Subject: [PATCH 744/749] Expanded README to describe different implementations --- 75_Roulette/java/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/75_Roulette/java/README.md b/75_Roulette/java/README.md index 2f9c97ca..8514a9ad 100644 --- a/75_Roulette/java/README.md +++ b/75_Roulette/java/README.md @@ -2,5 +2,7 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/gam Conversion to [Oracle Java](https://openjdk.java.net/) -Conversion by Andrew McGuinness (andrew@arobeia.co.uk) +Two versions of Roulette has been contributed. They are indicated within given sub-folders +- [oop](./oop) - Conversion by Andrew McGuinness (andrew@arobeia.co.uk) +- [iterative](./iterative) - Conversion by Thomas Kwashnak ([Github](https://github.com/LittleTealeaf)). Implements features from JDK 17 \ No newline at end of file From f87d306b0f5ba33047320c586dc7445d48bccf62 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Tue, 11 Jan 2022 21:05:35 -0500 Subject: [PATCH 745/749] Added some descriptors to iterative --- 75_Roulette/java/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/75_Roulette/java/README.md b/75_Roulette/java/README.md index 8514a9ad..bc05d92c 100644 --- a/75_Roulette/java/README.md +++ b/75_Roulette/java/README.md @@ -5,4 +5,6 @@ Conversion to [Oracle Java](https://openjdk.java.net/) Two versions of Roulette has been contributed. They are indicated within given sub-folders - [oop](./oop) - Conversion by Andrew McGuinness (andrew@arobeia.co.uk) -- [iterative](./iterative) - Conversion by Thomas Kwashnak ([Github](https://github.com/LittleTealeaf)). Implements features from JDK 17 \ No newline at end of file +- [iterative](./iterative) - Conversion by Thomas Kwashnak ([Github](https://github.com/LittleTealeaf)). + - Implements features from JDK 17. + - Does make use of some object oriented programming, but acts as a more iterative solution. \ No newline at end of file From f61148b2e4c7608c5d7cbbf08ddfcbfd9c5afebf Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Tue, 11 Jan 2022 21:19:47 -0500 Subject: [PATCH 746/749] Convert 21_Calendar to Perl. This is pretty much a complete rewrite. It displays the current year, but that can be changed by specifying the desired year on the command line. It MAY even be sensitive enough to locale to produce output in languages other than English. --- 21_Calendar/perl/README.md | 10 +++ 21_Calendar/perl/calendar.pl | 130 +++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100755 21_Calendar/perl/calendar.pl diff --git a/21_Calendar/perl/README.md b/21_Calendar/perl/README.md index e69c8b81..043be194 100644 --- a/21_Calendar/perl/README.md +++ b/21_Calendar/perl/README.md @@ -1,3 +1,13 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Perl](https://www.perl.org/) + +Actually, this is not so much a port as a complete rewrite, making use of +Perl's Posix time functionality. The calendar is for the current year (not +1979), but you can get another year by specifying it on the command line, e.g. + + `perl 21_Calendar/perl/calendar.pl 2001` + +It *may* even produce output in languages other than English. But the +leftmost column will still be Sunday, even in locales where it is +typically Monday. diff --git a/21_Calendar/perl/calendar.pl b/21_Calendar/perl/calendar.pl new file mode 100755 index 00000000..96ba387b --- /dev/null +++ b/21_Calendar/perl/calendar.pl @@ -0,0 +1,130 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use POSIX qw{ strftime }; +use Term::ReadLine; # Prompt and return user input +use Time::Local (); + +BEGIN { + *time_gm = + Time::Local->can( 'timegm_modern' ) || + Time::Local->can( 'timegm' ); +} + +our $VERSION = '0.000_01'; + +use constant COLUMN_WIDTH => 6; +use constant SECONDS_PER_DAY => 86400; + +binmode STDOUT, ':encoding(utf-8)'; + +my $year = @ARGV ? $ARGV[0] : ( localtime )[5] + 1900; +my $is_leap_year = is_leap_year( $year ); +my $year_len = 365 + $is_leap_year; +print <<'EOD'; + CALENDAR + Creative Computing Morristown, New Jersey + + +EOD + +my @mon_len = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); +$mon_len[1] += $is_leap_year; + +foreach my $month ( 0 .. 11 ) { + my $epoch = time_gm( 0, 0, 0, 1, $month, $year ); + my @start_time = gmtime( $epoch ); + my ( $week_day, $year_day ) = @start_time[ 6, 7 ]; + my $label = strftime( '%B %Y', @start_time ); + $label .= ' ' x ( ( 14 - length $label ) / 2 ); + printf "\n** %3d ****** %14s ****** %3d **\n", + $year_day, $label, $year_len - $year_day; + { + my $day = 1 + ( 7 - $week_day ) % 7; + foreach my $wd ( 0 .. 6 ) { + my $ep = time_gm( 0, 0, 0, $day + $wd, $month, $year ); + printf '%*s', COLUMN_WIDTH, strftime( '%a', gmtime $ep ); + } + print "\n"; + } + say '*' x ( COLUMN_WIDTH * 7 ); + print ' ' x ( COLUMN_WIDTH * $week_day ); + my $month_day = 1; + while ( $week_day < 7 ) { + printf '%*d', COLUMN_WIDTH, $month_day++; + $week_day++; + } + print "\n"; + $week_day = 0; + while ( $month_day <= $mon_len[$month] ) { + printf '%*d', COLUMN_WIDTH, $month_day++; + $week_day++; + unless ( $week_day % 7 ) { + print "\n"; + $week_day = 0; + } + } + print "\n" if $week_day; + +} + +sub is_leap_year { + my ( $year ) = 1; + return 0 if $year % 4; + return 1 if $year % 100; + return 0 if $year % 400; + return 1; +} + +__END__ + +=head1 TITLE + +calendar - Play the game 'Calendar' from Basic Computer Games + +=head1 SYNOPSIS + + calendar.pl + +=head1 DETAILS + +This Perl script is a port of calendar, which is the 21st +entry in Basic Computer Games. + +Actually, it is not so much a port as a complete rewrite, making use of +Perl's Posix time functionality. The calendar is for the current year +(not 1979), but you can get another year by specifying it on the command +line, e.g. + + perl 21_Calendar/perl/calendar.pl 2001 + +It B even produce output in languages other than English. But the +leftmost column will still be Sunday, even in locales where it is +typically Monday. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From 3e9f1354b3de2b202c4fd8f0861c1fc0ae687f55 Mon Sep 17 00:00:00 2001 From: "Brax Antti (Oy Samlink Ab)" Date: Wed, 12 Jan 2022 14:26:18 +0200 Subject: [PATCH 747/749] Convert 20_Buzzword to Java The original version was a straight forward monolithic BASIC-to-Java conversion. Updated to use common Java coding conventions. - Split the single static main method into classes. The static part only contains the bootstrap code for the game. - Split the word list into three arrays so that there is no need to use error-prone calculations when choosing the random words. - Placed the Scanner in a try-with-resources block to ensure that the scanner gets closed when it is no longer needed. --- 20_Buzzword/java/src/Buzzword.java | 44 ++++------------- 20_Buzzword/java/src/BuzzwordSupplier.java | 39 +++++++++++++++ 20_Buzzword/java/src/UserInterface.java | 57 ++++++++++++++++++++++ 3 files changed, 106 insertions(+), 34 deletions(-) create mode 100644 20_Buzzword/java/src/BuzzwordSupplier.java create mode 100644 20_Buzzword/java/src/UserInterface.java diff --git a/20_Buzzword/java/src/Buzzword.java b/20_Buzzword/java/src/Buzzword.java index 82ed9100..248b4a77 100755 --- a/20_Buzzword/java/src/Buzzword.java +++ b/20_Buzzword/java/src/Buzzword.java @@ -1,41 +1,17 @@ import java.util.Scanner; -import static java.lang.System.out; -// This is very close to the original BASIC. Changes: -// 1) the array indexing is adjusted by 1 -// 2) the user can enter a lower case "y" -// 3) moved the word list to the top 8~) public class Buzzword { - private static final String[] A = { - "ABILITY","BASAL","BEHAVIORAL","CHILD-CENTERED", - "DIFFERENTIATED","DISCOVERY","FLEXIBLE","HETEROGENEOUS", - "HOMOGENEOUS","MANIPULATIVE","MODULAR","TAVISTOCK", - "INDIVIDUALIZED","LEARNING","EVALUATIVE","OBJECTIVE", - "COGNITIVE","ENRICHMENT","SCHEDULING","HUMANISTIC", - "INTEGRATED","NON-GRADED","TRAINING","VERTICAL AGE", - "MOTIVATIONAL","CREATIVE","GROUPING","MODIFICATION", - "ACCOUNTABILITY","PROCESS","CORE CURRICULUM","ALGORITHM", - "PERFORMANCE","REINFORCEMENT","OPEN CLASSROOM","RESOURCE", - "STRUCTURE","FACILITY","ENVIRONMENT" - }; - private static Scanner scanner = new Scanner( System.in ); - public static void main( final String [] args ) { - out.println( " BUZZWORD GENERATOR" ); - out.println( " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" ); - out.println();out.println();out.println(); - out.println( "THIS PROGRAM PRINTS HIGHLY ACCEPTABLE PHRASES IN" ); - out.println( "'EDUCATOR-SPEAK' THAT YOU CAN WORK INTO REPORTS" ); - out.println( "AND SPEECHES. WHENEVER A QUESTION MARK IS PRINTED," ); - out.println( "TYPE A 'Y' FOR ANOTHER PHRASE OR 'N' TO QUIT." ); - out.println();out.println();out.println( "HERE'S THE FIRST PHRASE:" ); - do { - out.print( A[ (int)( 13 * Math.random() ) ] + " " ); - out.print( A[ (int)( 13 * Math.random() + 13 ) ] + " " ); - out.print( A[ (int)( 13 * Math.random() + 26 ) ] ); out.println(); - out.print( "?" ); + public static void main(final String[] args) { + try ( + // Scanner is a Closeable so it must be closed + // before the program ends. + final Scanner scanner = new Scanner(System.in); + ) { + final BuzzwordSupplier buzzwords = new BuzzwordSupplier(); + final UserInterface userInterface = new UserInterface( + scanner, buzzwords); + userInterface.run(); } - while ( "Y".equals( scanner.nextLine().toUpperCase() ) ); - out.println( "COME BACK WHEN YOU NEED HELP WITH ANOTHER REPORT!" ); } } diff --git a/20_Buzzword/java/src/BuzzwordSupplier.java b/20_Buzzword/java/src/BuzzwordSupplier.java new file mode 100644 index 00000000..679969f9 --- /dev/null +++ b/20_Buzzword/java/src/BuzzwordSupplier.java @@ -0,0 +1,39 @@ +import java.util.Random; +import java.util.function.Supplier; + +/** + * A string supplier that provides an endless stream of random buzzwords. + */ +public class BuzzwordSupplier implements Supplier { + + private static final String[] SET_1 = { + "ABILITY","BASAL","BEHAVIORAL","CHILD-CENTERED", + "DIFFERENTIATED","DISCOVERY","FLEXIBLE","HETEROGENEOUS", + "HOMOGENEOUS","MANIPULATIVE","MODULAR","TAVISTOCK", + "INDIVIDUALIZED" }; + + private static final String[] SET_2 = { + "LEARNING","EVALUATIVE","OBJECTIVE", + "COGNITIVE","ENRICHMENT","SCHEDULING","HUMANISTIC", + "INTEGRATED","NON-GRADED","TRAINING","VERTICAL AGE", + "MOTIVATIONAL","CREATIVE" }; + + private static final String[] SET_3 = { + "GROUPING","MODIFICATION", "ACCOUNTABILITY","PROCESS", + "CORE CURRICULUM","ALGORITHM", "PERFORMANCE", + "REINFORCEMENT","OPEN CLASSROOM","RESOURCE", "STRUCTURE", + "FACILITY","ENVIRONMENT" }; + + private final Random random = new Random(); + + /** + * Create a buzzword by concatenating a random word from each of the + * three word sets. + */ + @Override + public String get() { + return SET_1[random.nextInt(SET_1.length)] + ' ' + + SET_2[random.nextInt(SET_2.length)] + ' ' + + SET_3[random.nextInt(SET_3.length)]; + } +} diff --git a/20_Buzzword/java/src/UserInterface.java b/20_Buzzword/java/src/UserInterface.java new file mode 100644 index 00000000..cbfbe3eb --- /dev/null +++ b/20_Buzzword/java/src/UserInterface.java @@ -0,0 +1,57 @@ +import static java.lang.System.out; + +import java.util.Scanner; +import java.util.function.Supplier; + +/** + * A command line user interface that outputs a buzzword every + * time the user requests a new one. + */ +public class UserInterface implements Runnable { + + /** + * Input from the user. + */ + private final Scanner input; + + /** + * The buzzword generator. + */ + private final Supplier buzzwords; + + /** + * Create a new user interface. + * + * @param input The input scanner with which the user gives commands. + * @param buzzwords The buzzword supplier. + */ + public UserInterface(final Scanner input, + final Supplier buzzwords) { + this.input = input; + this.buzzwords = buzzwords; + } + + @Override + public void run() { + out.println(" BUZZWORD GENERATOR"); + out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + out.println(); + out.println(); + out.println(); + out.println("THIS PROGRAM PRINTS HIGHLY ACCEPTABLE PHRASES IN"); + out.println("'EDUCATOR-SPEAK' THAT YOU CAN WORK INTO REPORTS"); + out.println("AND SPEECHES. WHENEVER A QUESTION MARK IS PRINTED,"); + out.println("TYPE A 'Y' FOR ANOTHER PHRASE OR 'N' TO QUIT."); + out.println(); + out.println(); + out.println("HERE'S THE FIRST PHRASE:"); + + do { + out.println(buzzwords.get()); + out.println(); + out.print("?"); + } while ("Y".equals(input.nextLine().toUpperCase())); + + out.println("COME BACK WHEN YOU NEED HELP WITH ANOTHER REPORT!"); + } +} From c8633c6051a665bcaaae6a69eec20b14b2adf5fe Mon Sep 17 00:00:00 2001 From: "Brax Antti (Oy Samlink Ab)" Date: Wed, 12 Jan 2022 14:33:55 +0200 Subject: [PATCH 748/749] Convert 20_Buzzword to Java Provide the output PrintStream dependency to UserInterface in the constructor instead of have it hard coded to System.out. --- 20_Buzzword/java/src/Buzzword.java | 2 +- 20_Buzzword/java/src/UserInterface.java | 45 ++++++++++++++----------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/20_Buzzword/java/src/Buzzword.java b/20_Buzzword/java/src/Buzzword.java index 248b4a77..85fecfd3 100755 --- a/20_Buzzword/java/src/Buzzword.java +++ b/20_Buzzword/java/src/Buzzword.java @@ -10,7 +10,7 @@ public class Buzzword { ) { final BuzzwordSupplier buzzwords = new BuzzwordSupplier(); final UserInterface userInterface = new UserInterface( - scanner, buzzwords); + scanner, System.out, buzzwords); userInterface.run(); } } diff --git a/20_Buzzword/java/src/UserInterface.java b/20_Buzzword/java/src/UserInterface.java index cbfbe3eb..103e88c8 100644 --- a/20_Buzzword/java/src/UserInterface.java +++ b/20_Buzzword/java/src/UserInterface.java @@ -1,5 +1,4 @@ -import static java.lang.System.out; - +import java.io.PrintStream; import java.util.Scanner; import java.util.function.Supplier; @@ -14,6 +13,11 @@ public class UserInterface implements Runnable { */ private final Scanner input; + /** + * Output to the user. + */ + private final PrintStream output; + /** * The buzzword generator. */ @@ -23,35 +27,38 @@ public class UserInterface implements Runnable { * Create a new user interface. * * @param input The input scanner with which the user gives commands. + * @param output The output to show messages to the user. * @param buzzwords The buzzword supplier. */ public UserInterface(final Scanner input, - final Supplier buzzwords) { + final PrintStream output, + final Supplier buzzwords) { this.input = input; + this.output = output; this.buzzwords = buzzwords; } @Override public void run() { - out.println(" BUZZWORD GENERATOR"); - out.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); - out.println(); - out.println(); - out.println(); - out.println("THIS PROGRAM PRINTS HIGHLY ACCEPTABLE PHRASES IN"); - out.println("'EDUCATOR-SPEAK' THAT YOU CAN WORK INTO REPORTS"); - out.println("AND SPEECHES. WHENEVER A QUESTION MARK IS PRINTED,"); - out.println("TYPE A 'Y' FOR ANOTHER PHRASE OR 'N' TO QUIT."); - out.println(); - out.println(); - out.println("HERE'S THE FIRST PHRASE:"); + output.println(" BUZZWORD GENERATOR"); + output.println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + output.println(); + output.println(); + output.println(); + output.println("THIS PROGRAM PRINTS HIGHLY ACCEPTABLE PHRASES IN"); + output.println("'EDUCATOR-SPEAK' THAT YOU CAN WORK INTO REPORTS"); + output.println("AND SPEECHES. WHENEVER A QUESTION MARK IS PRINTED,"); + output.println("TYPE A 'Y' FOR ANOTHER PHRASE OR 'N' TO QUIT."); + output.println(); + output.println(); + output.println("HERE'S THE FIRST PHRASE:"); do { - out.println(buzzwords.get()); - out.println(); - out.print("?"); + output.println(buzzwords.get()); + output.println(); + output.print("?"); } while ("Y".equals(input.nextLine().toUpperCase())); - out.println("COME BACK WHEN YOU NEED HELP WITH ANOTHER REPORT!"); + output.println("COME BACK WHEN YOU NEED HELP WITH ANOTHER REPORT!"); } } From b0da05a04e1b83ae1857cb41d81470c6253ccc08 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Wed, 12 Jan 2022 10:27:50 -0800 Subject: [PATCH 749/749] Update README.md add Emulation and Bugfixes section --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 266aaac8..6ed7cb51 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Each project has subfolders corresponding to the languages we'd like to see the - Delphi / Object Pascal - Perl + + ### Project goals Feel free to begin converting these classic games into the above list of modern, memory safe languages. But first, a few guidelines: @@ -39,6 +41,16 @@ Feel free to begin converting these classic games into the above list of modern, - **Don't get _too_ fancy**. Definitely use the most recent versions and features of the target language, but also try to keep the code samples simple and explainable -- the goal is to teach programming in the target language, not necessarily demonstrate the cleverest one-line tricks. +### Emulation and Bugfixes + +We want the general behavior of the original programs to be preserved, _however_, we also want to update them, specifically: + +- allow both UPPERCASE and lowercase input and display +- incorporate any bugfixes to the original programs; see the `readme.md` in the game folder +- improved error handling for bad or erroneous input + +Please note that on the back of the Basic Computer Games book it says **Microsoft 8K Basic, Rev 4.0 was the version David Ahl used to test**, so that is the level of compatibility we are looking for.  QBasic on the DOS emulation is a later version of Basic but one that retains downwards compatibility so far in our testing. We're working on a recommended emulation to verify behavior. + ### Have fun! Thank you for taking part in this project to update a classic programming book -- one of the most influential programming books in computing history -- for 2022 and beyond!

+ * Based on game of Cube at: + * https://github.com/coding-horror/basic-computer-games/blob/main/30_Cube/cube.bas + * + * + */ public class Cube { + //Current player location private Location playerLocation; + + //Current list of mines private Set mines; + + //System input / output objects private PrintStream out; private Scanner scanner; + //Player's current money private int money; - + /** + * Entry point, creates a new Cube object and calls the play method + * @param args Java execution arguments, not used in application + */ public static void main(String[] args) { new Cube().play(); } @@ -22,9 +39,12 @@ public class Cube { out = System.out; scanner = new Scanner(System.in); money = 500; - mines = new HashSet<>(); + mines = new HashSet<>(5); } + /** + * Clears mines and places 5 new mines on the board + */ private void placeMines() { mines.clear(); Random random = new Random(); @@ -36,6 +56,9 @@ public class Cube { } } + /** + * Runs the entire game until the player runs out of money or chooses to stop + */ public void play() { out.println("DO YOU WANT TO SEE INSTRUCTIONS? (YES--1,NO--0)"); if(readParsedBoolean()) { @@ -99,6 +122,11 @@ public class Cube { out.println("\nGOODBYE."); } + /** + * Queries the user whether they want to play another round + * @return True if the player decides to play another round, + * False if the player would not like to play again + */ private boolean doAnotherRound() { if(money > 0) { out.println("DO YOU WANT TO TRY AGAIN?"); @@ -108,6 +136,9 @@ public class Cube { } } + /** + * Prints the instructions to the game, copied from the original code. + */ public void printInstructions() { out.println("THIS IS A GAME IN WHICH YOU WILL BE PLAYING AGAINST THE"); out.println("RANDOM DECISION OF THE COMPUTER. THE FIELD OF PLAY IS A"); @@ -133,6 +164,11 @@ public class Cube { out.println("GOOD LUCK!"); } + /** + * Waits for the user to input a boolean value. This could either be (true,false), (1,0), (y,n), (yes,no), etc. + * By default, it will return false + * @return Parsed boolean value of the user input + */ private boolean readParsedBoolean() { String in = scanner.nextLine(); try { @@ -155,6 +191,9 @@ public class Cube { this.z = z; } + /* + For use in HashSet and checking if two Locations are the same + */ @Override public boolean equals(Object o) { if (this == o) return true; @@ -167,6 +206,9 @@ public class Cube { return z == location.z; } + /* + For use in the HashSet to accordingly index the set + */ @Override public int hashCode() { int result = x; From d2495a55aad12e1cad51b0497bf2eac74c5ab9c0 Mon Sep 17 00:00:00 2001 From: Thomas Kwashnak Date: Thu, 6 Jan 2022 16:12:04 -0500 Subject: [PATCH 629/749] Added Comments --- 30_Cube/java/src/Cube.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/30_Cube/java/src/Cube.java b/30_Cube/java/src/Cube.java index 1237a49d..0100682a 100644 --- a/30_Cube/java/src/Cube.java +++ b/30_Cube/java/src/Cube.java @@ -178,6 +178,12 @@ public class Cube { } } + /** + * Checks if a move is valid + * @param from The point that the player is at + * @param to The point that the player wishes to move to + * @return True if the player is only moving, at most, 1 location in any direction, False if the move is invalid + */ private boolean isMoveValid(Location from, Location to) { return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) + Math.abs(from.z - to.z) <= 1; } From d2bf2e2e3b476d1c200cecc7f2d523bc4a92393d Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Thu, 6 Jan 2022 17:17:39 -0600 Subject: [PATCH 630/749] Fix issues with spacing in intro section And bug with justification of the first two lines --- 11_Bombardment/perl/bombardment.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/11_Bombardment/perl/bombardment.pl b/11_Bombardment/perl/bombardment.pl index 593bd9fa..0641102e 100644 --- a/11_Bombardment/perl/bombardment.pl +++ b/11_Bombardment/perl/bombardment.pl @@ -112,8 +112,8 @@ sub populate_computer_bases { } sub print_intro { - print "" * 33 + "BOMBARDMENT\n"; - print "" * 15 + " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; + print " " x 33, "BOMBARDMENT\n"; + print " " x 15, " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; print "\n\n"; print "YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU\n"; print "HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED.\n"; @@ -122,8 +122,8 @@ sub print_intro { print "THE OBJECT OF THE GAME IS TO FIRE MISSLES AT THE\n"; print "OUTPOSTS OF THE COMPUTER. IT WILL DO THE SAME TO YOU.\n"; print "THE ONE WHO DESTROYS ALL FOUR OF THE ENEMY'S PLATOONS\n"; - print "FIRST IS THE WINNER.\n"; - print "GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT!\n"; + print "FIRST IS THE WINNER.\n\n"; + print "GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT!\n\n"; print "TEAR OFF MATRIX AND USE IT TO CHECK OFF THE NUMBERS.\n"; print "\n\n\n\n"; } From dd7def55f3c637cd25629c1b810935a9ade97303 Mon Sep 17 00:00:00 2001 From: Flavio Poletti Date: Fri, 7 Jan 2022 03:11:52 +0100 Subject: [PATCH 631/749] Add 12_Bombs_Away in Perl --- 12_Bombs_Away/perl/bombsaway.pl | 140 ++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 12_Bombs_Away/perl/bombsaway.pl diff --git a/12_Bombs_Away/perl/bombsaway.pl b/12_Bombs_Away/perl/bombsaway.pl new file mode 100644 index 00000000..dd4c4674 --- /dev/null +++ b/12_Bombs_Away/perl/bombsaway.pl @@ -0,0 +1,140 @@ +#!/usr/bin/env perl +use v5.24; +use warnings; +use experimental 'signatures'; +no warnings 'experimental::signatures'; + +exit main(@ARGV); + +sub main { + $|++; + my $mission = 'y'; + + my @choices = ( + { # 1 - Italy + ask => 'YOUR TARGET -- ALBANIA(1), GREECE(2), NORTH AFRICA(3)', + comments => [ + q{SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE.}, + 'BE CAREFUL!!!', + q{YOU'RE GOING FOR THE OIL, EH?}, + ], + }, + { # 2 - Allies + ask => 'AIRCRAFT -- LIBERATOR(1), B-29(2), B-17(3), LANCASTER(4)', + comments => [ + q{YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI.}, + q{YOU'RE DUMPING THE A-BOMB ON HIROSHIMA.}, + q{YOU'RE CHASING THE BISMARK IN THE NORTH SEA.}, + q{YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR.}, + ], + }, + \&japan, + { # 4 - Germany + ask => "A NAZI, EH? OH WELL. ARE YOU GOING FOR RUSSIA(1),\n" + . 'ENGLAND(2), OR FRANCE(3)', + comments => [ + q{YOU'RE NEARING STALINGRAD.}, + q{NEARING LONDON. BE CAREFUL, THEY'VE GOT RADAR.}, + q{NEARING VERSAILLES. DUCK SOUP. THEY'RE NEARLY DEFENSELESS.}, + ], + }, + ); + + while (fc($mission // 'n') eq fc('y')) { + say 'YOU ARE A PILOT IN A WORLD WAR II BOMBER.'; + + my $side = choose( + 'WHAT SIDE -- ITALY(1), ALLIES(2), JAPAN(3), GERMANY(4)? ', 4); + my $choice = $choices[$side - 1]; + ref($choice) eq 'HASH' ? multiple($choice) : $choice->(); + + print "\n\n\nANOTHER MISSION (Y OR N)? "; + chomp($mission = ); + } + say "CHICKEN !!!\n"; + return 0; +} + +sub choose ($prompt, $n_max) { + while ('necessary') { + print "$prompt? "; + chomp(my $side = ); + return $side if $side =~ m{\A [1-9]\d* \z}mxs && $side <= $n_max; + say 'TRY AGAIN...'; + } +} + +sub multiple ($spec) { + my $target = choose("$spec->{ask}? ", scalar $spec->{comments}->@*); + say $spec->{comments}->[$target - 1]; + say ''; + + my $missions; + while ('necessary') { + print 'HOW MANY MISSIONS HAVE YOU FLOWN? '; + chomp($missions = ); + last if $missions < 160; + print 'MISSIONS, NOT MILES... +150 MISSIONS IS HIGH EVEN FOR OLD-TIMERS. +NOW THEN, '; + } + if ($missions < 25) { say 'FRESH OUT OF TRANING, EH?' } + elsif ($missions >= 100) { say q{THAT'S PUSHING THE ODDS!} } + + return direct_hit() if $missions >= rand(160); + + my $miss = 2 + int rand(30); + say "MISSED TARGET BY $miss MILES!"; + say "NOW YOU'RE REALLY IN FOR IT !!\n"; + our $double_fire = 0; + my $response = choose( + 'DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3)', 3); + if ($response < 2) { + print q{WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)? }; + chomp (our $hit_rate = ); + if ($hit_rate < 10) { + say q{YOU LIE, BUT YOU'LL PAY...}; + return endgame('fail'); # sure failure + } + say ''; + } + else { + $double_fire = 35; + } + return endgame(); +} + +sub direct_hit { + my $killed = int rand(100); + say "DIRECT HIT!!!! $killed KILLED.\nMISSION SUCCESSFUL"; + return; +} + +sub endgame ($fail = 0) { + our $double_fire //= 0; + our $hit_rate //= 0; + $fail ||= ($double_fire + $hit_rate) > rand(100); + if ($fail) { + say '* * * * BOOM * * * * +YOU HAVE BEEN SHOT DOWN..... +DEARLY BELOVED, WE ARE GATHERED HERE TODAY TO PAY OUR +LAST TRIBUTE...'; + } + else { + say 'YOU MADE IT THROUGH TREMENDOUS FLAK!!'; + } + return; +} + +sub japan { + say q{YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON.}; + print q{YOUR FIRST KAMIKAZE MISSION(Y OR N)? }; + chomp(my $is_first_kamikaze = ); + if (fc($is_first_kamikaze) eq fc('n')) { + our $hit_rate = 0; + say ''; + return endgame(); + } + return direct_hit() if rand(1) > 0.65; + return endgame('fail'); +} From 5b0d5e1221490818c433e4a19d97f450f2a61e58 Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Thu, 6 Jan 2022 19:49:26 -0600 Subject: [PATCH 632/749] Fix misspelling General code cleanup, including * Address code indendation * Condense print statments * Add spaces before = signs * Add spaces around operators * Simplify a few things * Use full variable names instead of single letters --- 54_Letter/perl/letter.pl | 41 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/54_Letter/perl/letter.pl b/54_Letter/perl/letter.pl index 54fb5fe0..56acf533 100755 --- a/54_Letter/perl/letter.pl +++ b/54_Letter/perl/letter.pl @@ -5,40 +5,37 @@ print ' 'x33 . "LETTER\n"; print ' 'x15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"; print "\n\n\n"; -print "LETTER GUESSING GAME\n"; print "\n"; +print "LETTER GUESSING GAME\n\n"; print "I'LL THINK OF A LETTER OF THE ALPHABET, A TO Z.\n"; print "TRY TO GUESS MY LETTER AND I'LL GIVE YOU CLUES\n"; print "AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER.\n"; -my $A; while (1) { - my $L= 65+int(rand(1)*26); - my $G= 0; - print "\n"; print "O.K., I HAVE A LETTER. START GUESSING.\n"; + my $letter = 65 + int(rand(26)); + my $guesses = 0; + print "\nO.K., I HAVE A LETTER. START GUESSING.\n"; + my $answer; do { - print "\n"; print "WHAT IS YOUR GUESS? "; - $G=$G+1; - chomp($A= ); - $A= ord($A); + print "\nWHAT IS YOUR GUESS? "; + $guesses++; + chomp($answer = ); + $answer = ord($answer); print "\n"; - if ($A<$L) { print "TOO LOW. TRY A HIGHER LETTER.\n"; } - if ($A>$L) { print "TOO HIGH. TRY A LOWER LETTER.\n"; } - } until($A eq $L); + print "TOO LOW. TRY A HIGHER LETTER.\n" if $answer < $letter; + print "TOO HIGH. TRY A LOWER LETTER.\n" if $answer > $letter; + } until($answer eq $letter); - print "\n"; print "YOU GOT IT IN $G GUESSES!!\n"; + print "\nYOU GOT IT IN $guesses GUESSES!!\n"; - if ($G<=5) { + if ($guesses <= 5) { print "GOOD JOB !!!!!\n"; - for (my $N=1; $N<=15; $N++) { print chr(7); } #ASCII Bell. - } else { + print chr(7) x 15; # ASCII Bell + } else { print "BUT IT SHOULDN'T TAKE MORE THAN 5 GUESSES!\n"; - } - - print "\n"; - print "LET'S PLAN AGAIN.....\n"; } + print "\nLET'S PLAY AGAIN.....\n"; +} + exit; - - From c2358069574050e33ee4fbb101594d246828099f Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Thu, 6 Jan 2022 20:23:53 -0600 Subject: [PATCH 633/749] Initial commit --- 62_Mugwump/perl/mugwump.pl | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 62_Mugwump/perl/mugwump.pl diff --git a/62_Mugwump/perl/mugwump.pl b/62_Mugwump/perl/mugwump.pl new file mode 100755 index 00000000..356c9983 --- /dev/null +++ b/62_Mugwump/perl/mugwump.pl @@ -0,0 +1,96 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +# global variables defined here +my(@MUGWUMP) = (); + +# subroutines defined here + +# init_mugwump: pick the random places for the Mugwumps +sub init_mugwump() { + @MUGWUMP = (); + for (1 .. 4) { + push @MUGWUMP, [ int(rand 10), int(rand 10) ]; + } +} + + +# main code starts here + +# print introductory text +print <); + my($M,$N) = split(/,/,$in); + $M = int($M); + $N = int($N); + + for my $i (0 .. $#MUGWUMP) { + # -1 indicates a Mugwump that was already found + next if $MUGWUMP[$i]->[0] == -1; + + if ($MUGWUMP[$i]->[0] == $M && $MUGWUMP[$i]->[1] == $N) { + $MUGWUMP[$i]->[0] = -1; + printf("You have found Mugwump %d\n", $i+1); + } else { + my $d = sqrt(($MUGWUMP[$i]->[0] - $M) ** 2 + ($MUGWUMP[$i]->[1] - $N) ** 2); + printf("You are %.1f units away from Mugwump %d\n", $d, $i+1); + } + } + + # If a Mugwump still has not been found, + # go to the next turn + for my $j (0 .. $#MUGWUMP) { + if ($MUGWUMP[$j]->[0] != -1) { + next TURN; + } + } + # You win! + printf("You got all of them in %d %s!\n\n", $turn, ($turn == 1 ? 'turn' : 'turns')); + # Pass execution down to the continue block + next PLAY; + + } # end of TURN loop + + print "\nSorry, that's 10 tries. Here's where they're hiding:\n"; + for my $i (0 .. $#MUGWUMP) { + printf("Mugwump %d is at (%d, %d)\n", $i+1, $MUGWUMP[$i]->[0], $MUGWUMP[$i]->[1]) + if $MUGWUMP[$i]->[0] != -1; + } +} +continue { + print "\nThat was fun! Let's play again.......\n"; + print "Four more Mugwumps are now in hiding.\n\n"; +} + From dbc02ecf611f001fe434a7b343be61d8d76e19ae Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Thu, 6 Jan 2022 20:25:06 -0600 Subject: [PATCH 634/749] typo --- 62_Mugwump/perl/mugwump.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/62_Mugwump/perl/mugwump.pl b/62_Mugwump/perl/mugwump.pl index 356c9983..d02a9036 100755 --- a/62_Mugwump/perl/mugwump.pl +++ b/62_Mugwump/perl/mugwump.pl @@ -33,7 +33,7 @@ number between 0 and 9, inclusive. First number is distance to right of homebase and second number is distance above homebase. -You get 10 tries. After each try, i will tell +You get 10 tries. After each try, I will tell you how far you are from each Mugwump. HERE From 03a18e473ab64753262d9099569534edf64775f3 Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Thu, 6 Jan 2022 22:09:04 -0600 Subject: [PATCH 635/749] Fix enemy fire Choice 3, both should apply both $double_fire and $hit_rate --- 12_Bombs_Away/perl/bombsaway.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/12_Bombs_Away/perl/bombsaway.pl b/12_Bombs_Away/perl/bombsaway.pl index dd4c4674..478d01a7 100644 --- a/12_Bombs_Away/perl/bombsaway.pl +++ b/12_Bombs_Away/perl/bombsaway.pl @@ -89,7 +89,7 @@ NOW THEN, '; our $double_fire = 0; my $response = choose( 'DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3)', 3); - if ($response < 2) { + if ($response != 2) { print q{WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)? }; chomp (our $hit_rate = ); if ($hit_rate < 10) { @@ -98,7 +98,7 @@ NOW THEN, '; } say ''; } - else { + if ($response > 1) { $double_fire = 35; } return endgame(); From 6dda7ce25a7311af6acca01554249a5074f77588 Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Fri, 7 Jan 2022 02:46:39 -0500 Subject: [PATCH 636/749] 89_TicTacToe in perl --- 89_Tic-Tac-Toe/perl/tictactoe2.pl | 197 ++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 89_Tic-Tac-Toe/perl/tictactoe2.pl diff --git a/89_Tic-Tac-Toe/perl/tictactoe2.pl b/89_Tic-Tac-Toe/perl/tictactoe2.pl new file mode 100644 index 00000000..4bd12cf7 --- /dev/null +++ b/89_Tic-Tac-Toe/perl/tictactoe2.pl @@ -0,0 +1,197 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +#GLOBALs +my %board = ( + 1 => 0, + 2 => 0, + 3 => 0, + 4 => 0, + 5 => 0, + 6 => 0, + 7 => 0, + 8 => 0, + 9 => 0, +); + +my %winning_combos = ( + 1 => [1,2,3], + 2 => [4,5,6], + 3 => [7,8,9], + 4 => [1,4,7], + 5 => [2,5,8], + 6 => [3,6,9], + 7 => [1,5,9], + 8 => [7,5,3], +); + +my $player=100; +my $player_goal=0; +my $computer=100; +my $computer_goal=0; +my $count=0; + +&main; + +sub main { + &print_intro; + print "DO YOU WANT 'X' OR 'O'\n"; + chomp(my $ans = ); + &assign_X_and_O($ans); + if ($ans eq "X") { + until ($count >= 9) { + &player_choice; + $count++; + &print_board; + &check_for_winners; + &computer_choice; + $count++; + &print_board; + &check_for_winners; + } + } + else { + until ($count >= 9) { + &computer_choice; + $count++; + &print_board; + &check_for_winners; + &player_choice; + $count++; + &print_board; + &check_for_winners; + } + } + print "IT'S A DRAW. THANK YOU.\n"; +} + +sub check_for_winners { + my %tally; + foreach my $key (keys %winning_combos) { + foreach my $val (@{$winning_combos{$key}}) { + $tally{$key}+=$board{$val}; + } + } + foreach my $key (keys %tally) { + if ($tally{$key} == $player_goal) { + print "YOU BEAT ME!! GOOD GAME.\n"; + exit; + } + if ($tally{$key} == $computer_goal) { + print "I WIN, TURKEY!!!\n"; + exit; + } + } +} + +sub computer_choice { + my $move; + $move=&check_for_blocks_or_wins;; + if ($move > 9) { + $move=&check_for_corners; + } + print "THE COMPUTER MOVES TO...\n"; + $board{$move}=$computer; +} + +sub check_for_corners { + my @precedence; + if ($count == 0) { + @precedence=(1,9,7,3,5,2,4,6,8); + } + else { + @precedence=(5,1,9,7,3,2,4,6,8); + } + foreach my $move (@precedence) { + my $validity=&check_occupation($move); + if ($validity eq "valid") { + return $move; + } + } +} + +sub check_for_blocks_or_wins { + my %tally; + my $validity = "invalid"; + my $move = 10; + foreach my $key (keys %winning_combos) { + foreach my $val (@{$winning_combos{$key}}) { + $tally{$key}+=$board{$val}; + } + } + foreach my $key (keys %tally) { + if (abs($tally{$key}) == 2) { + until ($validity eq "valid") { + foreach my $val (@{$winning_combos{$key}}) { + $validity=&check_occupation($val); + if ($validity eq "valid") { + $move = $val; + last; + } + } + } + return $move; + } + } + return $move; +} + +sub player_choice { + my $validity = "invalid"; + my $ans = ""; + until ($validity eq "valid") { + print "WHERE DO YOU MOVE? "; + chomp($ans = ); + $validity=&check_occupation($ans); + if ($validity eq "invalid") {print "THAT SQUARE IS OCCUPIED.\n\n"} + } + $board{$ans}=$player; +} + +sub check_occupation { + my $space = shift; + if ($board{$space}==0) { return "valid" } + else {return "invalid"}; +} + +sub print_board { + foreach my $num (1..9) { + my $char = &which_char($board{$num}); + if ($num == 4 || $num == 7) { print "\n---+---+---\n";} + print "$char"; + if ($num % 3 > 0) { print "!" } + } + print "\n"; +} + +sub which_char { + my $val=shift; + if ($val == 0) {return " ";} + elsif ($val == 1) {return " X ";} + else {return " O ";} +} + +sub assign_X_and_O { + my $ans = shift; + if ($ans eq "X") { + $player = 1; + $computer = -1; + $player_goal=3; + $computer_goal=-3; + } + else { + $player = -1; + $computer = 1; + $player_goal=-3; + $computer_goal=3; + } +} + +sub print_intro { + print ' ' x 30 . "TIC-TAC-TOE\n"; + print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n"; + print "THE BOARD IS NUMBERED:\n"; + print "1 2 3\n4 5 6\n7 8 9\n\n\n"; +} From 8c8a00df0f94d5b7f1d3e315eef0381ce051af93 Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Fri, 7 Jan 2022 02:58:35 -0500 Subject: [PATCH 637/749] 89_TicTacToe2 in perl --- 89_Tic-Tac-Toe/perl/tictactoe2.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/89_Tic-Tac-Toe/perl/tictactoe2.pl b/89_Tic-Tac-Toe/perl/tictactoe2.pl index 4bd12cf7..e7448e3e 100644 --- a/89_Tic-Tac-Toe/perl/tictactoe2.pl +++ b/89_Tic-Tac-Toe/perl/tictactoe2.pl @@ -67,6 +67,7 @@ sub main { print "IT'S A DRAW. THANK YOU.\n"; } +# This will check to see if anyone has won by adding up the various 3-in-a-row lines. sub check_for_winners { my %tally; foreach my $key (keys %winning_combos) { @@ -86,6 +87,8 @@ sub check_for_winners { } } +#On the computer's turn it will first check to see if it should block the player. If it finds it isn't going to win or need to block a player, the it will choose a spot to place it's X or O. + sub computer_choice { my $move; $move=&check_for_blocks_or_wins;; From 1348086a12806a12caacfcc958909f21b8b91e09 Mon Sep 17 00:00:00 2001 From: Flavio Poletti Date: Fri, 7 Jan 2022 09:34:08 +0100 Subject: [PATCH 638/749] Commented and fixed code --- 12_Bombs_Away/perl/bombsaway.pl | 225 ++++++++++++++++++++++---------- 1 file changed, 156 insertions(+), 69 deletions(-) diff --git a/12_Bombs_Away/perl/bombsaway.pl b/12_Bombs_Away/perl/bombsaway.pl index 478d01a7..70d8850e 100644 --- a/12_Bombs_Away/perl/bombsaway.pl +++ b/12_Bombs_Away/perl/bombsaway.pl @@ -10,97 +10,192 @@ sub main { $|++; my $mission = 'y'; - my @choices = ( - { # 1 - Italy - ask => 'YOUR TARGET -- ALBANIA(1), GREECE(2), NORTH AFRICA(3)', - comments => [ - q{SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE.}, - 'BE CAREFUL!!!', - q{YOU'RE GOING FOR THE OIL, EH?}, - ], - }, - { # 2 - Allies - ask => 'AIRCRAFT -- LIBERATOR(1), B-29(2), B-17(3), LANCASTER(4)', - comments => [ - q{YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI.}, - q{YOU'RE DUMPING THE A-BOMB ON HIROSHIMA.}, - q{YOU'RE CHASING THE BISMARK IN THE NORTH SEA.}, - q{YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR.}, - ], - }, - \&japan, - { # 4 - Germany - ask => "A NAZI, EH? OH WELL. ARE YOU GOING FOR RUSSIA(1),\n" - . 'ENGLAND(2), OR FRANCE(3)', - comments => [ - q{YOU'RE NEARING STALINGRAD.}, - q{NEARING LONDON. BE CAREFUL, THEY'VE GOT RADAR.}, - q{NEARING VERSAILLES. DUCK SOUP. THEY'RE NEARLY DEFENSELESS.}, - ], - }, - ); + # first-level choices will allow us to select the "right" callback + # function to start each mission + my @choices = (\&italy, \&allies, \&japan, \&germany); + # to support being case-insensitive "the right way" we apply the fc() + # function (i.e. "fold case"). This is slightly overkill in this case + # but it's better to stick to good habits. while (fc($mission // 'n') eq fc('y')) { say 'YOU ARE A PILOT IN A WORLD WAR II BOMBER.'; my $side = choose( - 'WHAT SIDE -- ITALY(1), ALLIES(2), JAPAN(3), GERMANY(4)? ', 4); - my $choice = $choices[$side - 1]; - ref($choice) eq 'HASH' ? multiple($choice) : $choice->(); + 'WHAT SIDE -- ITALY(1), ALLIES(2), JAPAN(3), GERMANY(4)', 4); - print "\n\n\nANOTHER MISSION (Y OR N)? "; - chomp($mission = ); + # arrays start from 0 in Perl, so our starting-from-1 side value + # has to be offset by 1. + $choices[$side - 1]->(); + + $mission = get_input("\n\n\nANOTHER MISSION (Y OR N)"); } - say "CHICKEN !!!\n"; - return 0; + __exit(); } +# unified exit function, make sure to shame the desertor! +sub __exit ($prefix = '') { + say $prefix, "CHICKEN !!!\n"; + exit 0; +} + +# unified input gathering. Checks if the input is closed (e.g. because the +# player hit CTRL-D) and __exit()s in case. Gets a prompt for asking a +# question, returns whatever is input (except spaces). +sub get_input ($prompt) { + print "$prompt? "; + defined(my $input = ) or __exit("\n"); + + # remove spaces from the input (including newlines), they are not used + + $input =~ s{\s+}{}gmxs; + return $input; +} + +# structured choosing function, gets a $prompt for asking a question and +# will iterate asking until the input is a number between 1 and $n_max. sub choose ($prompt, $n_max) { while ('necessary') { - print "$prompt? "; - chomp(my $side = ); + my $side = get_input($prompt); return $side if $side =~ m{\A [1-9]\d* \z}mxs && $side <= $n_max; say 'TRY AGAIN...'; } } -sub multiple ($spec) { - my $target = choose("$spec->{ask}? ", scalar $spec->{comments}->@*); - say $spec->{comments}->[$target - 1]; - say ''; +# Italy mission has the same structure as Allies and Germany, so it's been +# refactored into a single "multiple()" (pun intended) function, providing +# the right messaging. +sub italy { + return multiple( + 'YOUR TARGET -- ALBANIA(1), GREECE(2), NORTH AFRICA(3)', + q{SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE.}, + 'BE CAREFUL!!!', + q{YOU'RE GOING FOR THE OIL, EH?}, + ); +} + +# Allies mission has the same structure as Italy and Germany, so it's been +# refactored into a single "multiple()" (pun intended) function, providing +# the right messaging. +sub allies { + return multiple( + 'AIRCRAFT -- LIBERATOR(1), B-29(2), B-17(3), LANCASTER(4)', + q{YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI.}, + q{YOU'RE DUMPING THE A-BOMB ON HIROSHIMA.}, + q{YOU'RE CHASING THE BISMARK IN THE NORTH SEA.}, + q{YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR.}, + ); +} + +# Japan mission is different from the other three and is coded... +# differently. The end game phases are the same as other missions though, +# hence the calls to "direct_hit()" and "endgame()" functions. +sub japan { + say q{YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON.}; + my $is_first_kamikaze = get_input(q{YOUR FIRST KAMIKAZE MISSION(Y OR N)}); + if (fc($is_first_kamikaze) eq fc('n')) { + our $guns_hit_rate = 0; + say ''; + return endgame(); + } + return direct_hit() if rand(1) > 0.65; + return endgame('fail'); +} + +# Germany mission has the same structure as Italy and Allies, so it's been +# refactored into a single "multiple()" (pun intended) function, providing +# the right messaging. +sub germany { + return multiple( + "A NAZI, EH? OH WELL. ARE YOU GOING FOR RUSSIA(1),\n" + . 'ENGLAND(2), OR FRANCE(3)', + q{YOU'RE NEARING STALINGRAD.}, + q{NEARING LONDON. BE CAREFUL, THEY'VE GOT RADAR.}, + q{NEARING VERSAILLES. DUCK SOUP. THEY'RE NEARLY DEFENSELESS.} + ); +} + +# This function implements the workhorse for Italy, Allies and Germany +# missions, which all have the same structure. It starts with a $question +# and a few @comments, each commenting every different answer to the +# $question. +sub multiple ($question, @comments) { + my $target = choose($question, scalar @comments); + say "\n", $comments[$target - 1], "\n"; + + # we gather the number of missions flown so far so that we can + # use it to figure out if *this* mission will be successful. The more + # the missions flown, the higher the probability of success. my $missions; while ('necessary') { - print 'HOW MANY MISSIONS HAVE YOU FLOWN? '; - chomp($missions = ); + $missions = get_input('HOW MANY MISSIONS HAVE YOU FLOWN'); last if $missions < 160; print 'MISSIONS, NOT MILES... 150 MISSIONS IS HIGH EVEN FOR OLD-TIMERS. NOW THEN, '; } - if ($missions < 25) { say 'FRESH OUT OF TRANING, EH?' } - elsif ($missions >= 100) { say q{THAT'S PUSHING THE ODDS!} } + say ''; + # a little intermediate comment based on the value of $missions + if ($missions < 25) { say "FRESH OUT OF TRANING, EH?\n" } + elsif ($missions >= 100) { say "THAT'S PUSHING THE ODDS!\n" } + + # let's roll a 160-faced die and compare to the missions flown so far, + # player might not even have to engage in combat! return direct_hit() if $missions >= rand(160); + # player didn't get a direct hit on the target, so we provide a + # feedback about how much it was apart. This is part of the story. my $miss = 2 + int rand(30); say "MISSED TARGET BY $miss MILES!"; say "NOW YOU'RE REALLY IN FOR IT !!\n"; - our $double_fire = 0; + + # here is where the game shows a little "weakness", although it might + # have been done on purpose. We use "our" variables $missiles_hit_rate + # and $guns_hit_rate here because the original BASIC code did not reset + # the associated variables (respectively T and S) at every mission, thus + # leaking state from one mission to the following ones. + # + # In particular, both are leaked to the Japan mission(s), and + # $guns_hit_rate is leaked to future "multiple()" missions that have + # missiles only. + # + # This is what you get when your language only has global variables. + # + # Of course, this might have been done on purpose, and we'll replicate + # this behaviour here because it adds some randomness to the game. + our $missiles_hit_rate = 0; my $response = choose( 'DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3)', 3); - if ($response != 2) { - print q{WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)? }; - chomp (our $hit_rate = ); - if ($hit_rate < 10) { + + if ($response != 2) { # there's some guns involved, ask more + say ''; + + # see comment above as to why we have a "our" variable here + our $guns_hit_rate = + get_input(q{WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)}); + + # let's normalize the input a bit + $guns_hit_rate = 0 unless $guns_hit_rate =~ m{\A [1-9]\d* \z}mxs; + + # a hit rate this low is not reasonable and is immediately punished! + if ($guns_hit_rate < 10) { say q{YOU LIE, BUT YOU'LL PAY...}; + + # function endgame() provides the... end game messaging, which is + # also used by the Japan mission, so it's been factored out. + # Passing 'fail' (or any true value) makes sure that is' a + # failure. return endgame('fail'); # sure failure } say ''; } - if ($response > 1) { - $double_fire = 35; + else { + $missiles_hit_rate = 35; # remember... this is a global variable } + + # hand control over to the "endgame()" refactored function (also shared + # by the Japan mission). return endgame(); } @@ -110,10 +205,15 @@ sub direct_hit { return; } +# This function provides the end game randomization and messages, shared +# across all missions. If passed a true value $fail, it will make sure that +# the outcome is... a failure. This allows coping with a few ad-hoc +# GOTO:s in the original BASIC code, while still preserving a refactored +# code. sub endgame ($fail = 0) { - our $double_fire //= 0; - our $hit_rate //= 0; - $fail ||= ($double_fire + $hit_rate) > rand(100); + our $missiles_hit_rate //= 0; + our $guns_hit_rate //= 0; + $fail ||= ($missiles_hit_rate + $guns_hit_rate) > rand(100); if ($fail) { say '* * * * BOOM * * * * YOU HAVE BEEN SHOT DOWN..... @@ -125,16 +225,3 @@ LAST TRIBUTE...'; } return; } - -sub japan { - say q{YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON.}; - print q{YOUR FIRST KAMIKAZE MISSION(Y OR N)? }; - chomp(my $is_first_kamikaze = ); - if (fc($is_first_kamikaze) eq fc('n')) { - our $hit_rate = 0; - say ''; - return endgame(); - } - return direct_hit() if rand(1) > 0.65; - return endgame('fail'); -} From 74326a5c08320a72e8782b6672d9a5b9b546a178 Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Fri, 7 Jan 2022 07:07:33 -0500 Subject: [PATCH 639/749] Port of 81_Splat to Perl. Pretty much a straight port -- just straightened out the spaghetti in the original BASIC. --- 81_Splat/perl/splat.pl | 597 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100755 81_Splat/perl/splat.pl diff --git a/81_Splat/perl/splat.pl b/81_Splat/perl/splat.pl new file mode 100755 index 00000000..459bc790 --- /dev/null +++ b/81_Splat/perl/splat.pl @@ -0,0 +1,597 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use List::Util qw{ shuffle }; # Shuffle an array. +use Scalar::Util qw{ looks_like_number }; +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +use constant ROW_TPLT => ( '%4d' x 8 ) . "\n"; + +print <<'EOD'; + SPLAT + Creative Computing Morristown, New Jersey + + + +Welcome to 'Splat' -- the game that simulates a parachute +jump. Try to open your chute at the last possible +moment without going splat. +EOD + +while ( 1 ) { + say ''; + my $initial_altitude = int( 9001 * rand() + 1000 ); + + my $nominal_terminal_velocity; + if ( get_yes_no( 'Select your own terminal velocity' ) ) { + $nominal_terminal_velocity = get_input( + 'What terminal velocity (mi/hr)? ', + sub { looks_like_number( $ARG ) && $ARG > 0 }, + 'Please enter a positive number', + ); + # Convert miles per hour to feet per second + $nominal_terminal_velocity = $nominal_terminal_velocity * 5280 / 3600; + } else { + $nominal_terminal_velocity = int( 1000 * rand() ); + say "OK. Terminal velocity = $nominal_terminal_velocity mi/hr" + } + my $terminal_velocity = dither( $nominal_terminal_velocity ); + + my $nominal_gravity; # Acceleration due to gravity + if ( get_yes_no( 'Want to select acceleration due to gravity' ) ) { + } else { + state $body = [ + [ q, + 12.2 ], + [ q, + 28.3 ], + [ q, + 32.16 ], + [ q, + 5.15 ], + [ q, + 12.5 ], + [ q, + 85.2 ], + [ q, + 37.6 ], + [ q, + 33.8 ], + [ q, + 39.6 ], + [ q, + 896 ], + ]; + my $pick = $body->[ rand scalar @{ $body } ]; + say $pick->[0]; + $nominal_gravity = $pick->[1]; + } + my $gravity = dither( $nominal_gravity ); + + print <<"EOD"; + + Altitude = $initial_altitude ft + Term. velocity = $nominal_terminal_velocity ft/sec +/- 5% + Acceleration = $nominal_gravity ft/sec/sec +/- 5% +Set the timer for your freefall +EOD + + my $drop_time = get_input( + 'How many seconds? ', + sub { m/ \A [0-9]+ \z /smx }, + "Please enter an unsigned integer\n", + ); + + print <<'EOD'; +Here we go. + +Time (sec) Dist to fall (ft) +========== ================= +EOD + + if ( defined( my $altitude = make_jump( + $initial_altitude, + $gravity, + $terminal_velocity, + $drop_time ) ) + ) { + # Successful jump + state $succesful = []; + state $ordinal = [ qw{ 1st 2nd 3rd } ]; + if ( defined( my $ord = $ordinal->[ @{ $succesful } ] ) ) { + say "Amazing!!! Not nad for your $ord successful jump!!!"; + } else { + my $jumps = @{ $succesful }; + my $worse = grep { $_ > $altitude } @{ $succesful }; + my $fractile = 1 - $worse / $jumps; + my $better = $jumps - $worse; + if ( $fractile <= 0.1 ) { + print <<"EOD"; +Wow! That's some jumping. Of the $jumps successful jumps +before yours, only $better opened their chutes lower than +you did. +EOD + } elsif ( $fractile <= 0.25 ) { + print <<"EOD"; +Pretty good! $jumps successful jumps preceded yours and only +$better of them got lower than you did before their chutes +opened. +EOD + } elsif ( $fractile <= 0.5 ) { + print <<"EOD"; +Not bad. There have been $jumps successful jumps before yours. +You were beaten out by $better of them. +EOD + } elsif ( $fractile <= 0.75 ) { + print <<"EOD"; +Conservative, aren't you? You ranked only $better in the +$jumps successful jumps before yours. +EOD + } elsif ( $fractile <= 0.9 ) { + print <<"EOD"; +Humph! Don't you have any sporting blood? There were +$jumps successful jumps before yours and you came in $worse jumps +better than the worst. Shape up!!! +EOD + } else { + print <<"EOD"; +Hey! You pulled the rip cord much too soon. $jumps successful +jumps before yours and you came in number $better! Get with it! +EOD + } + } + push @{ $succesful }, $altitude; + } else { + # Splat + + say q; + } + + next if get_yes_no( 'Do you want to play again' ); + next if get_yes_no( 'Please' ); + + print <<'EOD'; +Ssssssssss. + +EOD + last; + +} + +# Return the first argument modified by up to plus or minus some +# fraction specified by the second argument (default 0.05) +sub dither { + my ( $arg, $fract ) = @_; + $fract //= 1 / 20; + return $arg + ( $arg * rand() * $fract ) - ( $arg * rand() * $fract ); +} + +use constant FORMAT_FALL => "%10.1f %10d\n"; +use constant FORMAT_SPLAT => "%10.1f %s\n"; +sub make_jump { + my ( $initial_altitude, $gravity, $terminal_velocity, $drop_time ) = @_; + my $altitude; + foreach my $step ( 0 .. 8 ) { + my $time = $step * $drop_time / 8; + if ( $time > $terminal_velocity / $gravity ) { + # Terminal velocity reached + printf "Terminal velocity reached at T plus %.2f seconds.\n", + $terminal_velocity / $gravity; + for my $step ( $step .. 8 ) { + my $time = $step * $drop_time / 8; + $altitude = $initial_altitude - ( + $terminal_velocity * $terminal_velocity / + ( 2 * $gravity ) + $terminal_velocity * ( + $time - $terminal_velocity / $gravity ) ); + if ( $altitude > 0 ) { + printf FORMAT_FALL, $time, $altitude; + } else { + splat( + $terminal_velocity / $gravity + ( + $initial_altitude - + $terminal_velocity * $terminal_velocity / + ( 2 * $gravity ) ) / $terminal_velocity, + ); + return; + } + } + last; + } else { + $altitude = $initial_altitude - $gravity / 2 * $time * $time; + if ( $altitude > 0 ) { + printf FORMAT_FALL, $time, $altitude; + } else { + splat( sqrt( 2 * $initial_altitude / $gravity ) ); + return; + } + } + } + + say 'Chute open.'; + return $altitude; +} + +sub splat { + my ( $time ) = @_; + printf FORMAT_SPLAT, $time, 'Splat!'; + state $rip = [ + q, + q, + q, + q, + q<#$%&&%!$>, + q, + q, + q, + q, + q, + ]; + say $rip->[ rand scalar @{ $rip } ]; + return; +} + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +__END__ + +print <<'EOD' if get_yes_no( 'Do you want instructions' ); +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. + + +EOD + +while ( 1 ) { + + say ''; + + foreach my $row ( 0 .. 7 ) { + printf ROW_TPLT, map { ( $_ + $row ) * 10 + $row + 1 } reverse 1 .. 8; + } + +} + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +__END__ +# Display the rules if desired. There is no straightforward way to +# interpolate a manifest constant into a string, but @{[ ... ]} will +# interpolate any expression. +print <<"EOD" if get_yes_no( 'Do you want the rules' ); + +This is the game of 'Reverse'. To win, all you have +to do is arrange a list of numbers (1 through @{[ NUMBER_OF_NUMBERS ]}) +in numerical order from left to right. To move, you +tell me how many numbers (counting from the left) to +reverse. For example, if the current list is: + +2 3 4 5 1 6 7 8 9 + +and you reverse 4, the result will be: + +5 4 3 2 1 6 7 8 9 + +Now if you reverse 5, you win! + +1 2 3 4 5 6 7 8 9 + +No doubt you will like this game, but +if you want to quit, reverse 0 (zero). + +EOD + +while ( 1 ) { # Iterate until something interrupts us. + + # Populate the list with the integers from 1, shuffled. If we + # accidentally generate a winning list, just redo the loop. + my @list = shuffle( 1 .. NUMBER_OF_NUMBERS ); + redo if is_win( \@list ); + + print <<"EOD"; + +Here we go ... The list is: +EOD + + my $moves = 0; # Move counter + + while ( 1 ) { # Iterate until something interrupts us. + print <<"EOD"; + +@list + +EOD + + # Read the number of values to reverse. Zero is special-cased to + # take us out of this loop. + last unless my $max_index = get_input( + 'How many shall I reverse (0 to quit)? ', + sub { + return m/ \A [0-9]+ \z /smx && + $ARG <= NUMBER_OF_NUMBERS; + }, + "Oops! Too many! I can reverse at most " . + NUMBER_OF_NUMBERS, + ); + + --$max_index; # Convert number to reverse to upper index + + # Use a Perl array slice and the reverse() built-in to reverse + # the beginning of the list. + @list[ 0 .. $max_index ] = reverse @list[ 0 .. $max_index ]; + + $moves++; # Count a move + + # If we have not won, iterate again. + next unless is_win( \@list ); + + # Announce the win, and drop out of the loop. + print <<"EOD"; + +You won it in $moves moves!!! +EOD + last; + } + + # Drop out of this loop unless the player wants to play again. + say ''; + last unless get_yes_no( 'Try again' ); +} + +print <<'EOD'; + +O.K. Hope you had fun!! +EOD + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +# Determine if a given list represents a win. The argument is a +# reference to the array containing the list. We return a true value for +# a win, or a false value otherwise. +sub is_win { + my ( $list ) = @_; + my $expect = 1; # We expect the first element to be 1; + + # Iterate over the array. + foreach my $element ( @{ $list } ) { + + # If the element does not have the expected value, we return + # false. We post-increment the expected value en passant. + $element == $expect++ + or return 0; + } + + # All elements had the expected value, so we won. Return a true + # value. + return 1; +} + +__END__ + +=head1 TITLE + +reverse.pl - Play the game 'reverse' from Basic Computer Games + +=head1 SYNOPSIS + + reverse.pl + +=head1 DETAILS + +This Perl script is a port of C, which is the 73rd entry in +Basic Computer Games. + +The cool thing about this port is the fact that, in a language with +array slices, list assignments, and a C built-in, the +reversal is a single assignment statement. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From b473fffc4a3720d78c79abc1d1763c85321f2328 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Sat, 8 Jan 2022 00:44:18 +1100 Subject: [PATCH 640/749] formatted version of battle.bas --- 09_Battle/battle_formatted.bas | 223 +++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 09_Battle/battle_formatted.bas diff --git a/09_Battle/battle_formatted.bas b/09_Battle/battle_formatted.bas new file mode 100644 index 00000000..9c292bd9 --- /dev/null +++ b/09_Battle/battle_formatted.bas @@ -0,0 +1,223 @@ +5 PRINT TAB(33);"BATTLE" +7 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" +10 REM -- BATTLE WRITTEN BY RAY WESTERGARD 10/70 +20 REM COPYRIGHT 1971 BY THE REGENTS OF THE UNIV. OF CALIF. +30 REM PRODUCED AT THE LAWRENCE HALL OF SCIENCE, BERKELEY +40 DIM PLAYFIELD(6,6),HITS(6,6),ROW(4),COLUMN(4),SHIP_HITS(6),LOSSES(3) + +50 FOR X=1 TO 6 + 51 FOR Y=1 TO 6 + 52 PLAYFIELD(X,Y)=0 + 53 NEXT Y +54 NEXT X + +60 FOR I=1 TO 3 + 70 N=4-I + 80 FOR J=1 TO 2 + + 90 A=INT(6*RND(1)+1) + 100 B=INT(6*RND(1)+1) + 110 D=INT(4*RND(1)+1) + + 120 IF PLAYFIELD(A,B)>0 THEN 90 + 130 M=0 + 140 ON D GOTO 150,340,550,740 + + 150 COLUMN(1)=B + 160 COLUMN(2)=7:COLUMN(3)=7 + 170 FOR K=1 TO N + 180 IF M>1 THEN 240 + 190 IF COLUMN(K)=6 THEN 230 + 200 IF PLAYFIELD(A,COLUMN(K)+1)>0 THEN 230 + 210 COLUMN(K+1)=COLUMN(K)+1 + 220 GOTO 280 + 230 M=2 + 240 IF COLUMN(1)0 THEN 90 + 270 COLUMN(K+1)=Z-1 + 280 NEXT K + 290 PLAYFIELD(A,B)=9-2*I-J + 300 FOR K=1 TO N + 310 PLAYFIELD(A,COLUMN(K+1))=PLAYFIELD(A,B) + 320 NEXT K + 330 GOTO 990 + + 340 ROW(1)=A + 350 COLUMN(1)=B + 360 ROW(2)=0:ROW(3)=0:COLUMN(2)=0:COLUMN(3)=0 + 370 FOR K=1 TO N + 380 IF M>1 THEN 460 + 390 IF ROW(K)=1 OR COLUMN(K)=1 THEN 450 + 400 IF PLAYFIELD(ROW(K)-1,COLUMN(K)-1)>0 THEN 450 + 410 IF PLAYFIELD(ROW(K)-1,COLUMN(K))>0 AND PLAYFIELD(ROW(K)-1,COLUMN(K))=PLAYFIELD(ROW(K),COLUMN(K)-1) THEN 450 + 420 ROW(K+1)=ROW(K)-1 + 430 COLUMN(K+1)=COLUMN(K)-1 + 440 GOTO 530 + 450 M=2 + 460 IF ROW(1)>ROW(2) AND ROW(1)>ROW(3) THEN Z1=ROW(1) + 462 IF ROW(2)>ROW(1) AND ROW(2)>ROW(3) THEN Z1=ROW(2) + 464 IF ROW(3)>ROW(1) AND ROW(3)>ROW(2) THEN Z1=ROW(3) + 470 IF COLUMN(1)>COLUMN(2) AND COLUMN(1)>COLUMN(3) THEN Z2=COLUMN(1) + 474 IF COLUMN(2)>COLUMN(1) AND COLUMN(2)>COLUMN(3) THEN Z2=COLUMN(2) + 476 IF COLUMN(3)>COLUMN(1) AND COLUMN(3)>COLUMN(2) THEN Z2=COLUMN(3) + + 480 IF Z1=6 OR Z2=6 THEN 90 + 490 IF PLAYFIELD(Z1+1,Z2+1)>0 THEN 90 + 500 IF PLAYFIELD(Z1,Z2+1)>0 AND PLAYFIELD(Z1,Z2+1)=PLAYFIELD(Z1+1,Z2) THEN 90 + + 510 ROW(K+1)=Z1+1 + 520 COLUMN(K+1)=Z2+1 + 530 NEXT K + 540 GOTO 950 + + 550 ROW(1)=A + 560 ROW(2)=7:ROW(3)=7 + 570 FOR K=1 TO N + 580 IF M>1 THEN 640 + 590 IF ROW(K)=6 THEN 630 + 600 IF PLAYFIELD(ROW(K)+1,B)>0 THEN 630 + 610 ROW(K+1)=ROW(K)+1 + 620 GOTO 680 + 630 M=2 + 640 IF ROW(1)0 THEN 90 + + 670 ROW(K+1)=Z-1 + 680 NEXT K + 690 PLAYFIELD(A,B)=9-2*I-J + 700 FOR K=1 TO N + 710 PLAYFIELD(ROW(K+1),B)=PLAYFIELD(A,B) + 720 NEXT K + 730 GOTO 990 + + 740 ROW(1)=A + 750 COLUMN(1)=B + 760 ROW(2)=7:ROW(3)=7 + 770 COLUMN(2)=0:COLUMN(3)=0 + 780 FOR K=1 TO N + 790 IF M>1 THEN 870 + 800 IF ROW(K)=6 OR COLUMN(K)=1 THEN 860 + 810 IF PLAYFIELD(ROW(K)+1,COLUMN(K)-1)>0 THEN 860 + 820 IF PLAYFIELD(ROW(K)+1,COLUMN(K))>0 AND PLAYFIELD(ROW(K)+1,COLUMN(K))=PLAYFIELD(ROW(K),COLUMN(K)-1) THEN 860 + 830 ROW(K+1)=ROW(K)+1 + 840 COLUMN(K+1)=COLUMN(K)-1 + 850 GOTO 940 + 860 M=2 + 870 IF ROW(1)COLUMN(2) AND COLUMN(1)>COLUMN(3) THEN Z2=COLUMN(1) + 882 IF COLUMN(2)>COLUMN(1) AND COLUMN(2)>COLUMN(3) THEN Z2=COLUMN(2) + 884 IF COLUMN(3)>COLUMN(1) AND COLUMN(3)>COLUMN(2) THEN Z2=COLUMN(3) + + 890 IF Z1=1 OR Z2=6 THEN 90 + 900 IF PLAYFIELD(Z1-1,Z2+1)>0 THEN 90 + 910 IF PLAYFIELD(Z1,Z2+1)>0 AND PLAYFIELD(Z1,Z2+1)=PLAYFIELD(Z1-1,Z2) THEN 90 + + 920 ROW(K+1)=Z1-1 + 930 COLUMN(K+1)=Z2+1 + 940 NEXT K + + 950 PLAYFIELD(A,B)=9-2*I-J + 960 FOR K=1 TO N + 970 PLAYFIELD(ROW(K+1),COLUMN(K+1))=PLAYFIELD(A,B) + 980 NEXT K + + 990 NEXT J +1000 NEXT I + +1010 PRINT +1020 PRINT "THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION" +1030 PRINT "HAS BEEN CAPTURED BUT NOT DECODED:" +1040 PRINT +1050 FOR I=1 TO 6 + 1051 FOR J=1 TO 6 + 1052 HITS(I,J)=PLAYFIELD(J,I) + 1053 NEXT J +1054 NEXT I +1060 FOR I=1 TO 6 + 1061 FOR J=1 TO 6 + 1062 PRINT HITS(I,J); + 1063 NEXT J + 1064 PRINT +1065 NEXT I +1070 PRINT +1080 PRINT "DE-CODE IT AND USE IT IF YOU CAN" +1090 PRINT "BUT KEEP THE DE-CODING METHOD A SECRET." +1100 PRINT +1110 FOR I=1 TO 6 + 1111 FOR J=1 TO 6 + 1112 HITS(I,J)=0 + 1113 NEXT J +1114 NEXT I +1120 FOR I=1 TO 3 + 1121 LOSSES(I)=0 +1122 NEXT I + +1130 SHIP_HITS(1)=2:SHIP_HITS(2)=2 +1140 SHIP_HITS(3)=1:SHIP_HITS(4)=1 +1150 SHIP_HITS(5)=0:SHIP_HITS(6)=0 +1160 S=0:HITS=0 + +1170 PRINT "START GAME" + +1180 INPUT X,Y +1190 IF X<1 OR X>6 OR INT(X)<>ABS(X) THEN 1210 +1200 IF Y>0 AND Y<7 AND INT(Y)=ABS(Y) THEN 1230 +1210 PRINT "INVALID INPUT. TRY AGAIN." +1220 GOTO 1180 + +1230 R=7-Y +1240 C=X +1250 IF PLAYFIELD(R,C)>0 THEN 1290 +1260 S=S+1 +1270 PRINT "SPLASH! TRY AGAIN." +1280 GOTO 1180 + +1290 IF SHIP_HITS(PLAYFIELD(R,C))<4 THEN 1340 +1300 PRINT "THERE USED TO BE A SHIP AT THAT POINT, BUT YOU SUNK IT." +1310 PRINT "SPLASH! TRY AGAIN." +1320 S=S+1 +1330 GOTO 1180 + +1340 IF HITS(R,C)>0 THEN 1420 +1350 HITS=HITS+1 +1360 HITS(R,C)=PLAYFIELD(R,C) +1370 PRINT "A DIRECT HIT ON SHIP NUMBER";PLAYFIELD(R,C) +1380 SHIP_HITS(PLAYFIELD(R,C))=SHIP_HITS(PLAYFIELD(R,C))+1 +1390 IF SHIP_HITS(PLAYFIELD(R,C))>=4 THEN 1470 +1400 PRINT "TRY AGAIN." +1410 GOTO 1180 + +1420 PRINT "YOU ALREADY PUT A HOLE IN SHIP NUMBER";PLAYFIELD(R,C); +1430 PRINT "AT THAT POINT." +1440 PRINT "SPLASH! TRY AGAIN." +1450 S=S+1 +1460 GOTO 1180 + +1470 LOSSES((INT(PLAYFIELD(R,C)-1)/2)+1)=LOSSES((INT(PLAYFIELD(R,C)-1)/2)+1)+1 + +1480 PRINT "AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS." +1490 PRINT "SO FAR, THE BAD GUYS HAVE LOST" +1500 PRINT LOSSES(1);"DESTROYER(S),";LOSSES(2);"CRUISER(S), AND"; +1510 PRINT LOSSES(3);"AIRCRAFT CARRIER(S)." +1520 PRINT "YOUR CURRENT SPLASH/HIT RATIO IS";S/HITS +1530 IF (LOSSES(1)+LOSSES(2)+LOSSES(3))<6 THEN 1180 + +1540 PRINT +1550 PRINT "YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET" +1560 PRINT "WITH A FINAL SPLASH/HIT RATIO OF";S/HITS +1570 IF S/HITS>0 THEN 1590 +1580 PRINT "CONGRATULATIONS -- A DIRECT HIT EVERY TIME." +1590 PRINT +1600 PRINT "****************************" +1610 PRINT +1620 GOTO 50 +1630 END From d7b8976a20e5243f776efdf730790e204dbe3713 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Sat, 8 Jan 2022 01:45:49 +1100 Subject: [PATCH 641/749] All games now have the correct gameMain defined in gradle.properties --- 89_Tic-Tac-Toe/java/src/{TicTacToe2.java => TicTacToe.java} | 2 +- 89_Tic-Tac-Toe/kotlin/{TicTacToe2.kt => TicTacToe.kt} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename 89_Tic-Tac-Toe/java/src/{TicTacToe2.java => TicTacToe.java} (99%) rename 89_Tic-Tac-Toe/kotlin/{TicTacToe2.kt => TicTacToe.kt} (100%) diff --git a/89_Tic-Tac-Toe/java/src/TicTacToe2.java b/89_Tic-Tac-Toe/java/src/TicTacToe.java similarity index 99% rename from 89_Tic-Tac-Toe/java/src/TicTacToe2.java rename to 89_Tic-Tac-Toe/java/src/TicTacToe.java index bda3793c..c8fa2d03 100644 --- a/89_Tic-Tac-Toe/java/src/TicTacToe2.java +++ b/89_Tic-Tac-Toe/java/src/TicTacToe.java @@ -4,7 +4,7 @@ import java.util.Random; /** * @author Ollie Hensman-Crook */ -public class TicTacToe2 { +public class TicTacToe { public static void main(String[] args) { Board gameBoard = new Board(); Random compChoice = new Random(); diff --git a/89_Tic-Tac-Toe/kotlin/TicTacToe2.kt b/89_Tic-Tac-Toe/kotlin/TicTacToe.kt similarity index 100% rename from 89_Tic-Tac-Toe/kotlin/TicTacToe2.kt rename to 89_Tic-Tac-Toe/kotlin/TicTacToe.kt From a1bc1b4fd9841cad7c2ebbb4c74e184ddd263e20 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Sat, 8 Jan 2022 01:57:12 +1100 Subject: [PATCH 642/749] oops revert renaming TicTacToe2 --- 89_Tic-Tac-Toe/java/src/{TicTacToe.java => TicTacToe2.java} | 2 +- 89_Tic-Tac-Toe/kotlin/{TicTacToe.kt => TicTacToe2.kt} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename 89_Tic-Tac-Toe/java/src/{TicTacToe.java => TicTacToe2.java} (99%) rename 89_Tic-Tac-Toe/kotlin/{TicTacToe.kt => TicTacToe2.kt} (100%) diff --git a/89_Tic-Tac-Toe/java/src/TicTacToe.java b/89_Tic-Tac-Toe/java/src/TicTacToe2.java similarity index 99% rename from 89_Tic-Tac-Toe/java/src/TicTacToe.java rename to 89_Tic-Tac-Toe/java/src/TicTacToe2.java index c8fa2d03..bda3793c 100644 --- a/89_Tic-Tac-Toe/java/src/TicTacToe.java +++ b/89_Tic-Tac-Toe/java/src/TicTacToe2.java @@ -4,7 +4,7 @@ import java.util.Random; /** * @author Ollie Hensman-Crook */ -public class TicTacToe { +public class TicTacToe2 { public static void main(String[] args) { Board gameBoard = new Board(); Random compChoice = new Random(); diff --git a/89_Tic-Tac-Toe/kotlin/TicTacToe.kt b/89_Tic-Tac-Toe/kotlin/TicTacToe2.kt similarity index 100% rename from 89_Tic-Tac-Toe/kotlin/TicTacToe.kt rename to 89_Tic-Tac-Toe/kotlin/TicTacToe2.kt From a7f05d150183fb35e890b3d53aa70381e873e9d2 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Sat, 8 Jan 2022 02:15:40 +1100 Subject: [PATCH 643/749] README.md --- buildJvm/README.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 buildJvm/README.md diff --git a/buildJvm/README.md b/buildJvm/README.md new file mode 100644 index 00000000..f0046ab3 --- /dev/null +++ b/buildJvm/README.md @@ -0,0 +1,63 @@ +# JVM gradle scripts + +## Quickstart + +Build all the games: + + cd buildJvm + ./gradlew -q assemble installDist distributeBin distributeLib + +Then, run a game + +### Mac or linux: + + build/distrib/bin/build_53_King_kotlin + +### Windows +[not tested yet] + + build\distrib\bin\build_53_King_kotlin.bat + +You will need to install openjdk 17, because some games use advanced Java features. +We should be using version 17 anyway, because anything less than 17 is deprecated. + +--- +## Adding a new game + +These are build scripts for all JVM games contributed so far. +New games can be added by: +- Creating a `build_NUMBER_NAME_[java/kotlin]` directory +- Adding a `build.gradle` file to that directory. +All `build.gradle` files under `build_NUMBER_*` should be nearly identical, unless +there is some special requirement. +- Adding a `gradle.properties` file to that directory, defining the source +directory for the java or kotlin file, and the class that contains the `main` method. + +The `build.gradle` file will normally be identical to this: + + plugins { + id 'application' + } + + sourceSets { + main { + java { + srcDirs "../../$gameSource" + } + } + } + + repositories { + mavenCentral() + } + + application { + mainClass = gameMain + } + +And the `gradle.properties` file should look like this: + + gameSource=91_Train/java/src + gameMain=Train + +where `gameSource` is the root of the source code directory, and `gameMain` is the main class. From 9f1b12d61cb883247efc021659778c9921b07527 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Sat, 8 Jan 2022 02:26:18 +1100 Subject: [PATCH 644/749] Delete old and experimental code --- 09_Battle/battle_formatted.bas | 223 --------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 09_Battle/battle_formatted.bas diff --git a/09_Battle/battle_formatted.bas b/09_Battle/battle_formatted.bas deleted file mode 100644 index 9c292bd9..00000000 --- a/09_Battle/battle_formatted.bas +++ /dev/null @@ -1,223 +0,0 @@ -5 PRINT TAB(33);"BATTLE" -7 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" -10 REM -- BATTLE WRITTEN BY RAY WESTERGARD 10/70 -20 REM COPYRIGHT 1971 BY THE REGENTS OF THE UNIV. OF CALIF. -30 REM PRODUCED AT THE LAWRENCE HALL OF SCIENCE, BERKELEY -40 DIM PLAYFIELD(6,6),HITS(6,6),ROW(4),COLUMN(4),SHIP_HITS(6),LOSSES(3) - -50 FOR X=1 TO 6 - 51 FOR Y=1 TO 6 - 52 PLAYFIELD(X,Y)=0 - 53 NEXT Y -54 NEXT X - -60 FOR I=1 TO 3 - 70 N=4-I - 80 FOR J=1 TO 2 - - 90 A=INT(6*RND(1)+1) - 100 B=INT(6*RND(1)+1) - 110 D=INT(4*RND(1)+1) - - 120 IF PLAYFIELD(A,B)>0 THEN 90 - 130 M=0 - 140 ON D GOTO 150,340,550,740 - - 150 COLUMN(1)=B - 160 COLUMN(2)=7:COLUMN(3)=7 - 170 FOR K=1 TO N - 180 IF M>1 THEN 240 - 190 IF COLUMN(K)=6 THEN 230 - 200 IF PLAYFIELD(A,COLUMN(K)+1)>0 THEN 230 - 210 COLUMN(K+1)=COLUMN(K)+1 - 220 GOTO 280 - 230 M=2 - 240 IF COLUMN(1)0 THEN 90 - 270 COLUMN(K+1)=Z-1 - 280 NEXT K - 290 PLAYFIELD(A,B)=9-2*I-J - 300 FOR K=1 TO N - 310 PLAYFIELD(A,COLUMN(K+1))=PLAYFIELD(A,B) - 320 NEXT K - 330 GOTO 990 - - 340 ROW(1)=A - 350 COLUMN(1)=B - 360 ROW(2)=0:ROW(3)=0:COLUMN(2)=0:COLUMN(3)=0 - 370 FOR K=1 TO N - 380 IF M>1 THEN 460 - 390 IF ROW(K)=1 OR COLUMN(K)=1 THEN 450 - 400 IF PLAYFIELD(ROW(K)-1,COLUMN(K)-1)>0 THEN 450 - 410 IF PLAYFIELD(ROW(K)-1,COLUMN(K))>0 AND PLAYFIELD(ROW(K)-1,COLUMN(K))=PLAYFIELD(ROW(K),COLUMN(K)-1) THEN 450 - 420 ROW(K+1)=ROW(K)-1 - 430 COLUMN(K+1)=COLUMN(K)-1 - 440 GOTO 530 - 450 M=2 - 460 IF ROW(1)>ROW(2) AND ROW(1)>ROW(3) THEN Z1=ROW(1) - 462 IF ROW(2)>ROW(1) AND ROW(2)>ROW(3) THEN Z1=ROW(2) - 464 IF ROW(3)>ROW(1) AND ROW(3)>ROW(2) THEN Z1=ROW(3) - 470 IF COLUMN(1)>COLUMN(2) AND COLUMN(1)>COLUMN(3) THEN Z2=COLUMN(1) - 474 IF COLUMN(2)>COLUMN(1) AND COLUMN(2)>COLUMN(3) THEN Z2=COLUMN(2) - 476 IF COLUMN(3)>COLUMN(1) AND COLUMN(3)>COLUMN(2) THEN Z2=COLUMN(3) - - 480 IF Z1=6 OR Z2=6 THEN 90 - 490 IF PLAYFIELD(Z1+1,Z2+1)>0 THEN 90 - 500 IF PLAYFIELD(Z1,Z2+1)>0 AND PLAYFIELD(Z1,Z2+1)=PLAYFIELD(Z1+1,Z2) THEN 90 - - 510 ROW(K+1)=Z1+1 - 520 COLUMN(K+1)=Z2+1 - 530 NEXT K - 540 GOTO 950 - - 550 ROW(1)=A - 560 ROW(2)=7:ROW(3)=7 - 570 FOR K=1 TO N - 580 IF M>1 THEN 640 - 590 IF ROW(K)=6 THEN 630 - 600 IF PLAYFIELD(ROW(K)+1,B)>0 THEN 630 - 610 ROW(K+1)=ROW(K)+1 - 620 GOTO 680 - 630 M=2 - 640 IF ROW(1)0 THEN 90 - - 670 ROW(K+1)=Z-1 - 680 NEXT K - 690 PLAYFIELD(A,B)=9-2*I-J - 700 FOR K=1 TO N - 710 PLAYFIELD(ROW(K+1),B)=PLAYFIELD(A,B) - 720 NEXT K - 730 GOTO 990 - - 740 ROW(1)=A - 750 COLUMN(1)=B - 760 ROW(2)=7:ROW(3)=7 - 770 COLUMN(2)=0:COLUMN(3)=0 - 780 FOR K=1 TO N - 790 IF M>1 THEN 870 - 800 IF ROW(K)=6 OR COLUMN(K)=1 THEN 860 - 810 IF PLAYFIELD(ROW(K)+1,COLUMN(K)-1)>0 THEN 860 - 820 IF PLAYFIELD(ROW(K)+1,COLUMN(K))>0 AND PLAYFIELD(ROW(K)+1,COLUMN(K))=PLAYFIELD(ROW(K),COLUMN(K)-1) THEN 860 - 830 ROW(K+1)=ROW(K)+1 - 840 COLUMN(K+1)=COLUMN(K)-1 - 850 GOTO 940 - 860 M=2 - 870 IF ROW(1)COLUMN(2) AND COLUMN(1)>COLUMN(3) THEN Z2=COLUMN(1) - 882 IF COLUMN(2)>COLUMN(1) AND COLUMN(2)>COLUMN(3) THEN Z2=COLUMN(2) - 884 IF COLUMN(3)>COLUMN(1) AND COLUMN(3)>COLUMN(2) THEN Z2=COLUMN(3) - - 890 IF Z1=1 OR Z2=6 THEN 90 - 900 IF PLAYFIELD(Z1-1,Z2+1)>0 THEN 90 - 910 IF PLAYFIELD(Z1,Z2+1)>0 AND PLAYFIELD(Z1,Z2+1)=PLAYFIELD(Z1-1,Z2) THEN 90 - - 920 ROW(K+1)=Z1-1 - 930 COLUMN(K+1)=Z2+1 - 940 NEXT K - - 950 PLAYFIELD(A,B)=9-2*I-J - 960 FOR K=1 TO N - 970 PLAYFIELD(ROW(K+1),COLUMN(K+1))=PLAYFIELD(A,B) - 980 NEXT K - - 990 NEXT J -1000 NEXT I - -1010 PRINT -1020 PRINT "THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION" -1030 PRINT "HAS BEEN CAPTURED BUT NOT DECODED:" -1040 PRINT -1050 FOR I=1 TO 6 - 1051 FOR J=1 TO 6 - 1052 HITS(I,J)=PLAYFIELD(J,I) - 1053 NEXT J -1054 NEXT I -1060 FOR I=1 TO 6 - 1061 FOR J=1 TO 6 - 1062 PRINT HITS(I,J); - 1063 NEXT J - 1064 PRINT -1065 NEXT I -1070 PRINT -1080 PRINT "DE-CODE IT AND USE IT IF YOU CAN" -1090 PRINT "BUT KEEP THE DE-CODING METHOD A SECRET." -1100 PRINT -1110 FOR I=1 TO 6 - 1111 FOR J=1 TO 6 - 1112 HITS(I,J)=0 - 1113 NEXT J -1114 NEXT I -1120 FOR I=1 TO 3 - 1121 LOSSES(I)=0 -1122 NEXT I - -1130 SHIP_HITS(1)=2:SHIP_HITS(2)=2 -1140 SHIP_HITS(3)=1:SHIP_HITS(4)=1 -1150 SHIP_HITS(5)=0:SHIP_HITS(6)=0 -1160 S=0:HITS=0 - -1170 PRINT "START GAME" - -1180 INPUT X,Y -1190 IF X<1 OR X>6 OR INT(X)<>ABS(X) THEN 1210 -1200 IF Y>0 AND Y<7 AND INT(Y)=ABS(Y) THEN 1230 -1210 PRINT "INVALID INPUT. TRY AGAIN." -1220 GOTO 1180 - -1230 R=7-Y -1240 C=X -1250 IF PLAYFIELD(R,C)>0 THEN 1290 -1260 S=S+1 -1270 PRINT "SPLASH! TRY AGAIN." -1280 GOTO 1180 - -1290 IF SHIP_HITS(PLAYFIELD(R,C))<4 THEN 1340 -1300 PRINT "THERE USED TO BE A SHIP AT THAT POINT, BUT YOU SUNK IT." -1310 PRINT "SPLASH! TRY AGAIN." -1320 S=S+1 -1330 GOTO 1180 - -1340 IF HITS(R,C)>0 THEN 1420 -1350 HITS=HITS+1 -1360 HITS(R,C)=PLAYFIELD(R,C) -1370 PRINT "A DIRECT HIT ON SHIP NUMBER";PLAYFIELD(R,C) -1380 SHIP_HITS(PLAYFIELD(R,C))=SHIP_HITS(PLAYFIELD(R,C))+1 -1390 IF SHIP_HITS(PLAYFIELD(R,C))>=4 THEN 1470 -1400 PRINT "TRY AGAIN." -1410 GOTO 1180 - -1420 PRINT "YOU ALREADY PUT A HOLE IN SHIP NUMBER";PLAYFIELD(R,C); -1430 PRINT "AT THAT POINT." -1440 PRINT "SPLASH! TRY AGAIN." -1450 S=S+1 -1460 GOTO 1180 - -1470 LOSSES((INT(PLAYFIELD(R,C)-1)/2)+1)=LOSSES((INT(PLAYFIELD(R,C)-1)/2)+1)+1 - -1480 PRINT "AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS." -1490 PRINT "SO FAR, THE BAD GUYS HAVE LOST" -1500 PRINT LOSSES(1);"DESTROYER(S),";LOSSES(2);"CRUISER(S), AND"; -1510 PRINT LOSSES(3);"AIRCRAFT CARRIER(S)." -1520 PRINT "YOUR CURRENT SPLASH/HIT RATIO IS";S/HITS -1530 IF (LOSSES(1)+LOSSES(2)+LOSSES(3))<6 THEN 1180 - -1540 PRINT -1550 PRINT "YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET" -1560 PRINT "WITH A FINAL SPLASH/HIT RATIO OF";S/HITS -1570 IF S/HITS>0 THEN 1590 -1580 PRINT "CONGRATULATIONS -- A DIRECT HIT EVERY TIME." -1590 PRINT -1600 PRINT "****************************" -1610 PRINT -1620 GOTO 50 -1630 END From e666dcfbdcca28040ed96f89560720b4d597d0a9 Mon Sep 17 00:00:00 2001 From: Paul Holt Date: Sat, 8 Jan 2022 02:26:18 +1100 Subject: [PATCH 645/749] Delete old and experimental code --- 09_Battle/battle_formatted.bas | 223 --------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 09_Battle/battle_formatted.bas diff --git a/09_Battle/battle_formatted.bas b/09_Battle/battle_formatted.bas deleted file mode 100644 index 9c292bd9..00000000 --- a/09_Battle/battle_formatted.bas +++ /dev/null @@ -1,223 +0,0 @@ -5 PRINT TAB(33);"BATTLE" -7 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" -10 REM -- BATTLE WRITTEN BY RAY WESTERGARD 10/70 -20 REM COPYRIGHT 1971 BY THE REGENTS OF THE UNIV. OF CALIF. -30 REM PRODUCED AT THE LAWRENCE HALL OF SCIENCE, BERKELEY -40 DIM PLAYFIELD(6,6),HITS(6,6),ROW(4),COLUMN(4),SHIP_HITS(6),LOSSES(3) - -50 FOR X=1 TO 6 - 51 FOR Y=1 TO 6 - 52 PLAYFIELD(X,Y)=0 - 53 NEXT Y -54 NEXT X - -60 FOR I=1 TO 3 - 70 N=4-I - 80 FOR J=1 TO 2 - - 90 A=INT(6*RND(1)+1) - 100 B=INT(6*RND(1)+1) - 110 D=INT(4*RND(1)+1) - - 120 IF PLAYFIELD(A,B)>0 THEN 90 - 130 M=0 - 140 ON D GOTO 150,340,550,740 - - 150 COLUMN(1)=B - 160 COLUMN(2)=7:COLUMN(3)=7 - 170 FOR K=1 TO N - 180 IF M>1 THEN 240 - 190 IF COLUMN(K)=6 THEN 230 - 200 IF PLAYFIELD(A,COLUMN(K)+1)>0 THEN 230 - 210 COLUMN(K+1)=COLUMN(K)+1 - 220 GOTO 280 - 230 M=2 - 240 IF COLUMN(1)0 THEN 90 - 270 COLUMN(K+1)=Z-1 - 280 NEXT K - 290 PLAYFIELD(A,B)=9-2*I-J - 300 FOR K=1 TO N - 310 PLAYFIELD(A,COLUMN(K+1))=PLAYFIELD(A,B) - 320 NEXT K - 330 GOTO 990 - - 340 ROW(1)=A - 350 COLUMN(1)=B - 360 ROW(2)=0:ROW(3)=0:COLUMN(2)=0:COLUMN(3)=0 - 370 FOR K=1 TO N - 380 IF M>1 THEN 460 - 390 IF ROW(K)=1 OR COLUMN(K)=1 THEN 450 - 400 IF PLAYFIELD(ROW(K)-1,COLUMN(K)-1)>0 THEN 450 - 410 IF PLAYFIELD(ROW(K)-1,COLUMN(K))>0 AND PLAYFIELD(ROW(K)-1,COLUMN(K))=PLAYFIELD(ROW(K),COLUMN(K)-1) THEN 450 - 420 ROW(K+1)=ROW(K)-1 - 430 COLUMN(K+1)=COLUMN(K)-1 - 440 GOTO 530 - 450 M=2 - 460 IF ROW(1)>ROW(2) AND ROW(1)>ROW(3) THEN Z1=ROW(1) - 462 IF ROW(2)>ROW(1) AND ROW(2)>ROW(3) THEN Z1=ROW(2) - 464 IF ROW(3)>ROW(1) AND ROW(3)>ROW(2) THEN Z1=ROW(3) - 470 IF COLUMN(1)>COLUMN(2) AND COLUMN(1)>COLUMN(3) THEN Z2=COLUMN(1) - 474 IF COLUMN(2)>COLUMN(1) AND COLUMN(2)>COLUMN(3) THEN Z2=COLUMN(2) - 476 IF COLUMN(3)>COLUMN(1) AND COLUMN(3)>COLUMN(2) THEN Z2=COLUMN(3) - - 480 IF Z1=6 OR Z2=6 THEN 90 - 490 IF PLAYFIELD(Z1+1,Z2+1)>0 THEN 90 - 500 IF PLAYFIELD(Z1,Z2+1)>0 AND PLAYFIELD(Z1,Z2+1)=PLAYFIELD(Z1+1,Z2) THEN 90 - - 510 ROW(K+1)=Z1+1 - 520 COLUMN(K+1)=Z2+1 - 530 NEXT K - 540 GOTO 950 - - 550 ROW(1)=A - 560 ROW(2)=7:ROW(3)=7 - 570 FOR K=1 TO N - 580 IF M>1 THEN 640 - 590 IF ROW(K)=6 THEN 630 - 600 IF PLAYFIELD(ROW(K)+1,B)>0 THEN 630 - 610 ROW(K+1)=ROW(K)+1 - 620 GOTO 680 - 630 M=2 - 640 IF ROW(1)0 THEN 90 - - 670 ROW(K+1)=Z-1 - 680 NEXT K - 690 PLAYFIELD(A,B)=9-2*I-J - 700 FOR K=1 TO N - 710 PLAYFIELD(ROW(K+1),B)=PLAYFIELD(A,B) - 720 NEXT K - 730 GOTO 990 - - 740 ROW(1)=A - 750 COLUMN(1)=B - 760 ROW(2)=7:ROW(3)=7 - 770 COLUMN(2)=0:COLUMN(3)=0 - 780 FOR K=1 TO N - 790 IF M>1 THEN 870 - 800 IF ROW(K)=6 OR COLUMN(K)=1 THEN 860 - 810 IF PLAYFIELD(ROW(K)+1,COLUMN(K)-1)>0 THEN 860 - 820 IF PLAYFIELD(ROW(K)+1,COLUMN(K))>0 AND PLAYFIELD(ROW(K)+1,COLUMN(K))=PLAYFIELD(ROW(K),COLUMN(K)-1) THEN 860 - 830 ROW(K+1)=ROW(K)+1 - 840 COLUMN(K+1)=COLUMN(K)-1 - 850 GOTO 940 - 860 M=2 - 870 IF ROW(1)COLUMN(2) AND COLUMN(1)>COLUMN(3) THEN Z2=COLUMN(1) - 882 IF COLUMN(2)>COLUMN(1) AND COLUMN(2)>COLUMN(3) THEN Z2=COLUMN(2) - 884 IF COLUMN(3)>COLUMN(1) AND COLUMN(3)>COLUMN(2) THEN Z2=COLUMN(3) - - 890 IF Z1=1 OR Z2=6 THEN 90 - 900 IF PLAYFIELD(Z1-1,Z2+1)>0 THEN 90 - 910 IF PLAYFIELD(Z1,Z2+1)>0 AND PLAYFIELD(Z1,Z2+1)=PLAYFIELD(Z1-1,Z2) THEN 90 - - 920 ROW(K+1)=Z1-1 - 930 COLUMN(K+1)=Z2+1 - 940 NEXT K - - 950 PLAYFIELD(A,B)=9-2*I-J - 960 FOR K=1 TO N - 970 PLAYFIELD(ROW(K+1),COLUMN(K+1))=PLAYFIELD(A,B) - 980 NEXT K - - 990 NEXT J -1000 NEXT I - -1010 PRINT -1020 PRINT "THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION" -1030 PRINT "HAS BEEN CAPTURED BUT NOT DECODED:" -1040 PRINT -1050 FOR I=1 TO 6 - 1051 FOR J=1 TO 6 - 1052 HITS(I,J)=PLAYFIELD(J,I) - 1053 NEXT J -1054 NEXT I -1060 FOR I=1 TO 6 - 1061 FOR J=1 TO 6 - 1062 PRINT HITS(I,J); - 1063 NEXT J - 1064 PRINT -1065 NEXT I -1070 PRINT -1080 PRINT "DE-CODE IT AND USE IT IF YOU CAN" -1090 PRINT "BUT KEEP THE DE-CODING METHOD A SECRET." -1100 PRINT -1110 FOR I=1 TO 6 - 1111 FOR J=1 TO 6 - 1112 HITS(I,J)=0 - 1113 NEXT J -1114 NEXT I -1120 FOR I=1 TO 3 - 1121 LOSSES(I)=0 -1122 NEXT I - -1130 SHIP_HITS(1)=2:SHIP_HITS(2)=2 -1140 SHIP_HITS(3)=1:SHIP_HITS(4)=1 -1150 SHIP_HITS(5)=0:SHIP_HITS(6)=0 -1160 S=0:HITS=0 - -1170 PRINT "START GAME" - -1180 INPUT X,Y -1190 IF X<1 OR X>6 OR INT(X)<>ABS(X) THEN 1210 -1200 IF Y>0 AND Y<7 AND INT(Y)=ABS(Y) THEN 1230 -1210 PRINT "INVALID INPUT. TRY AGAIN." -1220 GOTO 1180 - -1230 R=7-Y -1240 C=X -1250 IF PLAYFIELD(R,C)>0 THEN 1290 -1260 S=S+1 -1270 PRINT "SPLASH! TRY AGAIN." -1280 GOTO 1180 - -1290 IF SHIP_HITS(PLAYFIELD(R,C))<4 THEN 1340 -1300 PRINT "THERE USED TO BE A SHIP AT THAT POINT, BUT YOU SUNK IT." -1310 PRINT "SPLASH! TRY AGAIN." -1320 S=S+1 -1330 GOTO 1180 - -1340 IF HITS(R,C)>0 THEN 1420 -1350 HITS=HITS+1 -1360 HITS(R,C)=PLAYFIELD(R,C) -1370 PRINT "A DIRECT HIT ON SHIP NUMBER";PLAYFIELD(R,C) -1380 SHIP_HITS(PLAYFIELD(R,C))=SHIP_HITS(PLAYFIELD(R,C))+1 -1390 IF SHIP_HITS(PLAYFIELD(R,C))>=4 THEN 1470 -1400 PRINT "TRY AGAIN." -1410 GOTO 1180 - -1420 PRINT "YOU ALREADY PUT A HOLE IN SHIP NUMBER";PLAYFIELD(R,C); -1430 PRINT "AT THAT POINT." -1440 PRINT "SPLASH! TRY AGAIN." -1450 S=S+1 -1460 GOTO 1180 - -1470 LOSSES((INT(PLAYFIELD(R,C)-1)/2)+1)=LOSSES((INT(PLAYFIELD(R,C)-1)/2)+1)+1 - -1480 PRINT "AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS." -1490 PRINT "SO FAR, THE BAD GUYS HAVE LOST" -1500 PRINT LOSSES(1);"DESTROYER(S),";LOSSES(2);"CRUISER(S), AND"; -1510 PRINT LOSSES(3);"AIRCRAFT CARRIER(S)." -1520 PRINT "YOUR CURRENT SPLASH/HIT RATIO IS";S/HITS -1530 IF (LOSSES(1)+LOSSES(2)+LOSSES(3))<6 THEN 1180 - -1540 PRINT -1550 PRINT "YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET" -1560 PRINT "WITH A FINAL SPLASH/HIT RATIO OF";S/HITS -1570 IF S/HITS>0 THEN 1590 -1580 PRINT "CONGRATULATIONS -- A DIRECT HIT EVERY TIME." -1590 PRINT -1600 PRINT "****************************" -1610 PRINT -1620 GOTO 50 -1630 END From 016ad4f825fd69c1b7a1bc4056f1b7a05aa79490 Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Fri, 7 Jan 2022 10:49:49 -0500 Subject: [PATCH 646/749] Clean up dead code left over from cut-and-paste development. --- 81_Splat/perl/splat.pl | 269 +---------------------------------------- 1 file changed, 4 insertions(+), 265 deletions(-) diff --git a/81_Splat/perl/splat.pl b/81_Splat/perl/splat.pl index 459bc790..eebfcb6b 100755 --- a/81_Splat/perl/splat.pl +++ b/81_Splat/perl/splat.pl @@ -298,281 +298,20 @@ sub get_yes_no { __END__ -print <<'EOD' if get_yes_no( 'Do you want instructions' ); -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. - - -EOD - -while ( 1 ) { - - say ''; - - foreach my $row ( 0 .. 7 ) { - printf ROW_TPLT, map { ( $_ + $row ) * 10 + $row + 1 } reverse 1 .. 8; - } - -} - -# Get input from the user. The arguments are: -# * The prompt -# * A reference to validation code. This code receives the response in -# $ARG and returns true for a valid response. -# * A warning to print if the response is not valid. This must end in a -# return. -# The first valid response is returned. An end-of-file terminates the -# script. -sub get_input { - my ( $prompt, $validate, $warning ) = @ARG; - - # If no validator is passed, default to one that always returns - # true. - $validate ||= sub { 1 }; - - # Create the readline object. The 'state' causes the variable to be - # initialized only once, no matter how many times this subroutine is - # called. The do { ... } is a compound statement used because we - # need to tweak the created object before we store it. - state $term = do { - my $obj = Term::ReadLine->new( 'reverse' ); - $obj->ornaments( 0 ); - $obj; - }; - - while ( 1 ) { # Iterate indefinitely - - # Read the input into the topic variable, localized to prevent - # Spooky Action at a Distance. We exit on undef, which signals - # end-of-file. - exit unless defined( local $ARG = $term->readline( $prompt ) ); - - # Return the input if it is valid. - return $ARG if $validate->(); - - # Issue the warning, and go around the merry-go-round again. - warn $warning; - } -} - -# Get a yes-or-no answer. The argument is the prompt, which will have -# '? [y/n]: ' appended. The donkey work is done by get_input(), which is -# requested to validate the response as beginning with 'y' or 'n', -# case-insensitive. The return is a true value for 'y' and a false value -# for 'n'. -sub get_yes_no { - my ( $prompt ) = @ARG; - state $map_answer = { - n => 0, - y => 1, - }; - my $resp = lc get_input( - "$prompt? [y/n]: ", - sub { m/ \A [yn] /smxi }, - "Please respond 'y' or 'n'\n", - ); - return $map_answer->{ substr $resp, 0, 1 }; -} - -__END__ -# Display the rules if desired. There is no straightforward way to -# interpolate a manifest constant into a string, but @{[ ... ]} will -# interpolate any expression. -print <<"EOD" if get_yes_no( 'Do you want the rules' ); - -This is the game of 'Reverse'. To win, all you have -to do is arrange a list of numbers (1 through @{[ NUMBER_OF_NUMBERS ]}) -in numerical order from left to right. To move, you -tell me how many numbers (counting from the left) to -reverse. For example, if the current list is: - -2 3 4 5 1 6 7 8 9 - -and you reverse 4, the result will be: - -5 4 3 2 1 6 7 8 9 - -Now if you reverse 5, you win! - -1 2 3 4 5 6 7 8 9 - -No doubt you will like this game, but -if you want to quit, reverse 0 (zero). - -EOD - -while ( 1 ) { # Iterate until something interrupts us. - - # Populate the list with the integers from 1, shuffled. If we - # accidentally generate a winning list, just redo the loop. - my @list = shuffle( 1 .. NUMBER_OF_NUMBERS ); - redo if is_win( \@list ); - - print <<"EOD"; - -Here we go ... The list is: -EOD - - my $moves = 0; # Move counter - - while ( 1 ) { # Iterate until something interrupts us. - print <<"EOD"; - -@list - -EOD - - # Read the number of values to reverse. Zero is special-cased to - # take us out of this loop. - last unless my $max_index = get_input( - 'How many shall I reverse (0 to quit)? ', - sub { - return m/ \A [0-9]+ \z /smx && - $ARG <= NUMBER_OF_NUMBERS; - }, - "Oops! Too many! I can reverse at most " . - NUMBER_OF_NUMBERS, - ); - - --$max_index; # Convert number to reverse to upper index - - # Use a Perl array slice and the reverse() built-in to reverse - # the beginning of the list. - @list[ 0 .. $max_index ] = reverse @list[ 0 .. $max_index ]; - - $moves++; # Count a move - - # If we have not won, iterate again. - next unless is_win( \@list ); - - # Announce the win, and drop out of the loop. - print <<"EOD"; - -You won it in $moves moves!!! -EOD - last; - } - - # Drop out of this loop unless the player wants to play again. - say ''; - last unless get_yes_no( 'Try again' ); -} - -print <<'EOD'; - -O.K. Hope you had fun!! -EOD - -# Get input from the user. The arguments are: -# * The prompt -# * A reference to validation code. This code receives the response in -# $ARG and returns true for a valid response. -# * A warning to print if the response is not valid. This must end in a -# return. -# The first valid response is returned. An end-of-file terminates the -# script. -sub get_input { - my ( $prompt, $validate, $warning ) = @ARG; - - # If no validator is passed, default to one that always returns - # true. - $validate ||= sub { 1 }; - - # Create the readline object. The 'state' causes the variable to be - # initialized only once, no matter how many times this subroutine is - # called. The do { ... } is a compound statement used because we - # need to tweak the created object before we store it. - state $term = do { - my $obj = Term::ReadLine->new( 'reverse' ); - $obj->ornaments( 0 ); - $obj; - }; - - while ( 1 ) { # Iterate indefinitely - - # Read the input into the topic variable, localized to prevent - # Spooky Action at a Distance. We exit on undef, which signals - # end-of-file. - exit unless defined( local $ARG = $term->readline( $prompt ) ); - - # Return the input if it is valid. - return $ARG if $validate->(); - - # Issue the warning, and go around the merry-go-round again. - warn $warning; - } -} - -# Get a yes-or-no answer. The argument is the prompt, which will have -# '? [y/n]: ' appended. The donkey work is done by get_input(), which is -# requested to validate the response as beginning with 'y' or 'n', -# case-insensitive. The return is a true value for 'y' and a false value -# for 'n'. -sub get_yes_no { - my ( $prompt ) = @ARG; - state $map_answer = { - n => 0, - y => 1, - }; - my $resp = lc get_input( - "$prompt? [y/n]: ", - sub { m/ \A [yn] /smxi }, - "Please respond 'y' or 'n'\n", - ); - return $map_answer->{ substr $resp, 0, 1 }; -} - -# Determine if a given list represents a win. The argument is a -# reference to the array containing the list. We return a true value for -# a win, or a false value otherwise. -sub is_win { - my ( $list ) = @_; - my $expect = 1; # We expect the first element to be 1; - - # Iterate over the array. - foreach my $element ( @{ $list } ) { - - # If the element does not have the expected value, we return - # false. We post-increment the expected value en passant. - $element == $expect++ - or return 0; - } - - # All elements had the expected value, so we won. Return a true - # value. - return 1; -} - -__END__ - =head1 TITLE -reverse.pl - Play the game 'reverse' from Basic Computer Games +splat.pl - Play the game 'splat' from Basic Computer Games =head1 SYNOPSIS - reverse.pl + splat.pl =head1 DETAILS -This Perl script is a port of C, which is the 73rd entry in +This Perl script is a port of C, which is the 73rd entry in Basic Computer Games. -The cool thing about this port is the fact that, in a language with -array slices, list assignments, and a C built-in, the -reversal is a single assignment statement. +This is a very basic port. All I really did was untangle the spaghetti. =head1 PORTED BY From 501deb035ce5f759deedd6d4d992299f7b12634c Mon Sep 17 00:00:00 2001 From: RibTips <36372030+ribtips@users.noreply.github.com> Date: Fri, 7 Jan 2022 10:59:03 -0500 Subject: [PATCH 647/749] Fixed game termination bug Fixed issue where the game wouldn't terminate properly if the computer goes first. --- 89_Tic-Tac-Toe/perl/tictactoe2.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/89_Tic-Tac-Toe/perl/tictactoe2.pl b/89_Tic-Tac-Toe/perl/tictactoe2.pl index e7448e3e..0cbf4c10 100644 --- a/89_Tic-Tac-Toe/perl/tictactoe2.pl +++ b/89_Tic-Tac-Toe/perl/tictactoe2.pl @@ -58,6 +58,10 @@ sub main { $count++; &print_board; &check_for_winners; + if ($count >= 9) { + print "IT'S A DRAW. THANK YOU.\n"; + exit; + } &player_choice; $count++; &print_board; @@ -65,6 +69,7 @@ sub main { } } print "IT'S A DRAW. THANK YOU.\n"; + exit; } # This will check to see if anyone has won by adding up the various 3-in-a-row lines. From e8c2638b98ffb8de51075c7418c46973c99d4dc9 Mon Sep 17 00:00:00 2001 From: jcoehoorn Date: Fri, 7 Jan 2022 09:59:29 -0600 Subject: [PATCH 648/749] Create program.vb --- 33_Dice/vbnet/program.vb | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 33_Dice/vbnet/program.vb diff --git a/33_Dice/vbnet/program.vb b/33_Dice/vbnet/program.vb new file mode 100644 index 00000000..977a5344 --- /dev/null +++ b/33_Dice/vbnet/program.vb @@ -0,0 +1,38 @@ +Imports System + +Module Program + Sub Main(args As String()) + Const header As String = +" DICE +CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + +THIS PROGRAM SIMULATES THE ROLLING OF A +PAIR OF DICE. +YOU ENTER THE NUMBER OF TIMES YOU WANT THE COMPUTER TO +/ROLL/ THE DICE. WATCH OUT, VERY LARGE NUMBERS TAKE +A LONG TIME. IN PARTICULAR, NUMBERS OVER 5000." + + Console.WriteLine(header) + + Dim D6 As New Random() + Dim continuePrompt As String = "YES" + While continuePrompt = "YES" + Console.Write($"{vbCrLf}HOW MANY ROLLS? ") + Dim x As Integer = Convert.ToInt32(Console.ReadLine()) + Dim F = Enumerable.Repeat(0, 11).ToList() + For s As Integer = 0 To x - 1 + F(D6.Next(6) + D6.Next(6)) += 1 + Next + + Console.WriteLine($"{vbCrLf}TOTAL SPOTS NUMBER OF TIMES") + For V As Integer = 0 To 10 + Console.WriteLine($" {V + 2}{vbTab,-8}{F(V)}") + Next + + Console.Write($"{vbCrLf}TRY AGAIN ") + continuePrompt = Console.ReadLine().ToUpper() + End While + End Sub +End Module From 96ef2628668db806928d6709ff934b1aafc1c44e Mon Sep 17 00:00:00 2001 From: Flavio Poletti Date: Fri, 7 Jan 2022 18:41:41 +0100 Subject: [PATCH 649/749] Update AI for Awari --- 04_Awari/perl/awari.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/04_Awari/perl/awari.pl b/04_Awari/perl/awari.pl index 3d70452c..b3e30b54 100644 --- a/04_Awari/perl/awari.pl +++ b/04_Awari/perl/awari.pl @@ -190,7 +190,8 @@ sub computer_move ($board, $failures, $moves) { # be obtained by setting the ORIGINAL environment variable to a # "true" value (in Perl terms). Otherwise it is calculated # according to the real rules for the game. - my $p_score = $ENV{ORIGINAL} ? $landing > 13 : int(($landing - 5) / 14); + my $p_score = $ENV{ORIGINAL} ? $landing > 13 + : ($landing + 1) % 14 > 6; # whatever, the landing position must be within the bounds $landing %= 14; From 1dbd2704553224f232bee1a4f9d40233ea37eb5f Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Fri, 7 Jan 2022 14:42:32 -0500 Subject: [PATCH 650/749] Port 88_Slots to Perl. I have made a change in the payout table versus the BASIC, since I presume the failure to pay a double on LEMON CHERRY LEMON is a bug. See the documentation in the module for why. --- 80_Slots/perl/slots.pl | 238 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100755 80_Slots/perl/slots.pl diff --git a/80_Slots/perl/slots.pl b/80_Slots/perl/slots.pl new file mode 100755 index 00000000..b5c1ee39 --- /dev/null +++ b/80_Slots/perl/slots.pl @@ -0,0 +1,238 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use List::Util qw{ shuffle }; # Shuffle an array. +use Scalar::Util qw{ looks_like_number }; +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +print <<'EOD'; + SLOTS + Creative Computing Morristown, New Jersey + + + +You are in the H&M casino, in front of one of our +one-arm bandits. Bet from $1 to $100. +To pull the arm, punch the return key after making your bet. +EOD + +my $winnings = 0; # Winnings + +while ( 1 ) { # Iterate indefinitely + + say ''; + + my $bet = get_input( 'Your bet? ', + sub { m/ \A [0-9]+ \z /smx }, + 'Please enter a whole number between 0 and 100', + ); + if ( $bet > 100 ) { + say 'The house limit is $100'; + next; + } + if ( $bet < 1 ) { + say 'The minimum bet is $1'; + next; + } + + say "\a" x 10; + my $reel_x = int( 6 * rand() ); + my $reel_y = int( 6 * rand() ); + my $reel_z = int( 6 * rand() ); + foreach my $column ( $reel_x, $reel_y, $reel_z ) { + state $symbol = [ qw{ Bar Bell Orange Lemon Plum Cherry } ]; + print $symbol->[$column], "\a" x 5, ' '; + } + + use constant YOU_WON => 'You won!'; + use constant YOU_LOST => 'You lost.'; + + say ''; + if ( $reel_x == $reel_y ) { + if ( $reel_y == $reel_z ) { + if ( $reel_z ) { + say '** TOP DOLLAR **'; + $winnings += 11 * $bet; + } else { + say '*** JACKPOT ***'; + $winnings += 101 * $bet; + } + say YOU_WON; + } elsif ( $reel_y ) { + $winnings += double( $bet ); + } else { + $winnings += double_bar( $bet ); + } + } elsif ( $reel_x == $reel_z ) { + if ( $reel_z ) { + $winnings += double( $bet ); + # NOTE that the below code is what is actually implemented + # in the basic, but it is implemented strangely enough (a + # GOTO a line that contains a test that, if I understand the + # control flow, must fail) that I wonder if it is an error. + # I know nothing about slot machines, but research suggests + # the payoff table is fairly arbitrary. The code above makes + # code above makes the game orthogonal. + # $winnings += you_lost( $bet ); + } else { + $winnings += double_bar( $bet ); + } + } elsif ( $reel_y == $reel_z ) { + if ( $reel_z ) { + $winnings += double( $bet ); + } else { + $winnings += double_bar( $bet ); + } + } else { + $winnings += you_lost( $bet ); + } + + say 'Your standings are $', $winnings; + + last unless get_yes_no( 'Again' ); + +} + +if ( $winnings < 0 ) { + say 'Pay up! Please leave your money on the terminal.'; +} elsif ( $winnings > 0 ) { + say 'Collect your winnings from the H&M cashier.'; +} else { + say 'Hey, you broke even.'; +} + +sub double { + my ( $bet ) = @_; + say 'DOUBLE!'; + say YOU_WON; + return 3 * $bet; +} + +sub double_bar { + my ( $bet ) = @_; + say '* DOUBLE BAR *'; + say YOU_WON; + return 6 * $bet; +} + +sub you_lost { + my ( $bet ) = @_; + say YOU_LOST; + return -$bet; +} + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +__END__ + +=head1 TITLE + +slots - Play the game 'Slots' from Basic Computer Games + +=head1 SYNOPSIS + + slots.pl + +=head1 DETAILS + +This Perl script is a port of C, which is the 80th entry in Basic +Computer Games. + +I know nothing about slot machines, and my research into them says to me +that the payout tables can be fairly arbitrary. But I have taken the +liberty of deeming the BASIC program's refusal to pay on LEMON CHERRY +LEMON a bug, and made that case a double. + +My justification for this is that at the point where the BASIC has +detected the double in the first and third reels it has already detected +that there is no double in the first and second reels. After the check +for a bar (and therefore a double bar) fails it goes back and checks for +a double on the second and third reels. But we know this check will +fail, since the check for a double on the first and second reels failed. +So if a loss was intended at this point, why not just call it a loss? + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From ae903a3b62dec4ef5f3bf2cda6e22e32cb885958 Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Fri, 7 Jan 2022 14:03:15 -0600 Subject: [PATCH 651/749] Apply Both damage correctly Choices 2 and 3 should both have missile damage applied. --- 12_Bombs_Away/perl/bombsaway.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/12_Bombs_Away/perl/bombsaway.pl b/12_Bombs_Away/perl/bombsaway.pl index 70d8850e..1b4989f6 100644 --- a/12_Bombs_Away/perl/bombsaway.pl +++ b/12_Bombs_Away/perl/bombsaway.pl @@ -168,6 +168,7 @@ NOW THEN, '; my $response = choose( 'DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3)', 3); + # Apply Gun damage for responses 1 and 3 if ($response != 2) { # there's some guns involved, ask more say ''; @@ -190,7 +191,8 @@ NOW THEN, '; } say ''; } - else { + # Apply missile damage for responses 2 and 3 + if ($response > 1 ) { $missiles_hit_rate = 35; # remember... this is a global variable } From d88d3b298785c41537ac225b612d0ac457bca446 Mon Sep 17 00:00:00 2001 From: Bill Cruise Date: Fri, 7 Jan 2022 15:48:09 -0500 Subject: [PATCH 652/749] Fixed bug in acey-ducey range. --- 01_Acey_Ducey/python/acey_ducey_oo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01_Acey_Ducey/python/acey_ducey_oo.py b/01_Acey_Ducey/python/acey_ducey_oo.py index 325af4b4..3e05387f 100644 --- a/01_Acey_Ducey/python/acey_ducey_oo.py +++ b/01_Acey_Ducey/python/acey_ducey_oo.py @@ -36,7 +36,7 @@ class Deck: def build(self): for suit in ['\u2665', '\u2666', '\u2663', '\u2660']: - for rank in range(1, 14): + for rank in range(2, 15): self.cards.append(Card(suit, rank)) def shuffle(self): From c9f9f9bcdd36e1faaa59807cfbf01dd51bc394b5 Mon Sep 17 00:00:00 2001 From: zoot661 Date: Fri, 7 Jan 2022 21:40:42 +0000 Subject: [PATCH 653/749] Create Program.cs Add initial implementation Working version but requires commenting and maybe some better error handling --- 92_Trap/csharp/Program.cs | 119 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 92_Trap/csharp/Program.cs 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; + } + } +} From ab5301151e064a395410efc0f198f1406f94ca37 Mon Sep 17 00:00:00 2001 From: Robert Flach Date: Fri, 7 Jan 2022 16:38:29 -0600 Subject: [PATCH 654/749] Fixed 2 bugs. 1 yes and no both restarted the game 2. zero is supposed to skip the third card but was treated as an invalid bet. 1. In trying as keep as close to the spirit of the original game as possible, there is no handling for an invalidly low number. A zero input prints "chicken" and skips the third card and starts over with 2 new initial cards. 2. After the wad is blown, anything but a yes answer to the "Try again" question ends the game --- 01_Acey_Ducey/javascript/aceyducey.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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!'); From a14a7bea3cfe411f1ce704cd12f911aa93b240d7 Mon Sep 17 00:00:00 2001 From: simonskrede Date: Sat, 8 Jan 2022 00:42:53 +0100 Subject: [PATCH 655/749] Initial port of Poker to plain Java --- 71_Poker/java/Poker.java | 851 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 851 insertions(+) create mode 100644 71_Poker/java/Poker.java 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; + } + } + +} From 8db8272d0b088749867350f1674ec8369d0ae259 Mon Sep 17 00:00:00 2001 From: Flavio Poletti Date: Sat, 8 Jan 2022 02:14:33 +0100 Subject: [PATCH 656/749] Add 72_Queen in Perl --- 72_Queen/perl/queen.pl | 209 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 72_Queen/perl/queen.pl 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 ''; +} From 9f636574a41084dd4284f0c4b4066611f96d3a65 Mon Sep 17 00:00:00 2001 From: Alvaro Frias Garay Date: Fri, 7 Jan 2022 22:49:51 -0300 Subject: [PATCH 657/749] Added ruby version of russian roulette --- 76_Russian_Roulette/ruby/russianroulette.rb | 73 +++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 76_Russian_Roulette/ruby/russianroulette.rb 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 From 32eee996546c66d3b21004b535da4abd01837c4a Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Fri, 7 Jan 2022 21:26:46 -0600 Subject: [PATCH 658/749] Fix exception if choice 2 for damage is selected Initialize the variables. --- 12_Bombs_Away/javascript/bombsaway.js | 2 ++ 1 file changed, 2 insertions(+) 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) { From ab2b9d0c3425e5d14fd6cbed4f8be1e71741ada7 Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Fri, 7 Jan 2022 21:51:00 -0600 Subject: [PATCH 659/749] Initial commit --- 51_Hurkle/perl/hurkle.pl | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 51_Hurkle/perl/hurkle.pl diff --git a/51_Hurkle/perl/hurkle.pl b/51_Hurkle/perl/hurkle.pl new file mode 100755 index 00000000..abb42d5a --- /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 gueses.\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"; +} \ No newline at end of file From 4d66d18e714e08384395a03775d6f1756ef43bc8 Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Fri, 7 Jan 2022 21:51:56 -0600 Subject: [PATCH 660/749] typo --- 51_Hurkle/perl/hurkle.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/51_Hurkle/perl/hurkle.pl b/51_Hurkle/perl/hurkle.pl index abb42d5a..52d7e853 100755 --- a/51_Hurkle/perl/hurkle.pl +++ b/51_Hurkle/perl/hurkle.pl @@ -72,7 +72,7 @@ PLAY: while (1) { } # tries loop # No more guesses - printf("Sorry, that's %d gueses.\n", $TRIES); + printf("Sorry, that's %d guesses.\n", $TRIES); printf("The Hurkle is at %d, %d\n", $H1, $H2); } From 83a9d95fc43f65233719434f2af5f4039aec50ab Mon Sep 17 00:00:00 2001 From: James Allenspach Date: Fri, 7 Jan 2022 21:52:30 -0600 Subject: [PATCH 661/749] add line break at eof --- 51_Hurkle/perl/hurkle.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/51_Hurkle/perl/hurkle.pl b/51_Hurkle/perl/hurkle.pl index 52d7e853..1497e50c 100755 --- a/51_Hurkle/perl/hurkle.pl +++ b/51_Hurkle/perl/hurkle.pl @@ -81,4 +81,4 @@ PLAY: while (1) { # after the player has lost. continue { print "\nLet's play again. Hurkle is hiding.\n\n"; -} \ No newline at end of file +} From 42ed63d175cd387e5505485d7c80b9bd78e32766 Mon Sep 17 00:00:00 2001 From: Pat Ludwig Date: Fri, 7 Jan 2022 22:03:14 -0600 Subject: [PATCH 662/749] Add *.class to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4707e8fb..d2115efc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.class */.vs *.suo From bc6580f2098dce0f215e0821ed87c68dd2ec951d Mon Sep 17 00:00:00 2001 From: Tim Buchalka <70119791+journich@users.noreply.github.com> Date: Sat, 8 Jan 2022 17:28:18 +1030 Subject: [PATCH 663/749] Fix for gunner rate being incorrectly asked for when missiles selected - see issue #457. Add test for player entering an amount for the percentage hit rate of gunners less than the minimum. It now shoots down the player as per the original game. --- 12_Bombs_Away/java/src/BombsAway.java | 51 +++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) 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 From 5caa02958ef28d925406a024a4ab87e84987c003 Mon Sep 17 00:00:00 2001 From: Yash Chauhan <68198489+ITrustNumbers@users.noreply.github.com> Date: Sat, 8 Jan 2022 15:11:02 +0530 Subject: [PATCH 664/749] Ported 83_Stock_Market to Python I've used an Object-Oriented Approach. The code's a little messy, We'll clean it up later. --- 83_Stock_Market/python/Stock_Market.py | 208 +++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 83_Stock_Market/python/Stock_Market.py diff --git a/83_Stock_Market/python/Stock_Market.py b/83_Stock_Market/python/Stock_Market.py new file mode 100644 index 00000000..98386cc1 --- /dev/null +++ b/83_Stock_Market/python/Stock_Market.py @@ -0,0 +1,208 @@ +import random + +#Stock_Market +class Stock_Market(): + + def __init__(self): + + #Hard Coded Names + short_names = ['IBM', 'RCA', 'LBJ', 'ABC', 'CBS'] + full_names = ['INT. BALLISTIC MISSLES', 'RED CROSS OF AMERICA', + 'LICHTENSTEIN, BUMRAP & JOKE', 'AMERICAN BANKRUPT CO.', + 'CENSURED BOOKS STORE'] + + #Initializing Dictionary to hold all the information systematically + self.data = {} + for sn, fn in zip(short_names, full_names): + #A dictionary for each stock + temp = {'Name' : fn, 'Price' : None, 'Holdings' : 0} + #Nested outer dictionary for all stocks + self.data[sn] = temp + + #Initializing Randomly generated initial prices + for stock in self.data.values(): + stock['Price'] = round(random.uniform(80,120),2) #Price b/w 60 and 120 + + #Initialize Assets + self.cash_assets = 10000 + self.stock_assets = 0 + + def total_assets(self): + + return self.cash_assets + self.stock_assets + + def _generate_day_change(self): + + self.changes = [] + for _ in range(len(self.data)): + self.changes.append(round(random.uniform(-5,5),2)) #Random % Change b/w -5 and 5 + + def update_prices(self): + + self._generate_day_change() + for stock, change in zip(self.data.values(), self.changes): + stock['Price'] = round(stock['Price'] + (change/100)*stock['Price'], 2) + + def print_exchange_average(self): + + sum = 0 + for stock in self.data.values(): + sum += stock['Price'] + + print('\nNEW YORK STOCK EXCHANGE AVERAGE: ${:.2f}'.format(sum/5)) + + def get_average_change(self): + + sum = 0 + for change in self.changes: + sum += change + + return round(sum/5,2) + + def print_first_day(self): + + print('\nSTOCK\t\t\t\t\tINITIALS\tPRICE/SHARE($)') + for stock, data in self.data.items(): + if stock != 'LBJ': + print('{}\t\t\t{}\t\t{}'.format(data['Name'], stock, data['Price'])) + else: + print('{}\t\t{}\t\t{}'.format(data['Name'], stock, data['Price'])) + + self.print_exchange_average() + self.print_assets() + + def take_inputs(self): + + print('\nWHAT IS YOUR TRANSACTION IN') + flag = False + while flag != True: + new_holdings = [] + for stock in self.data.keys(): + try: + new_holdings.append(int(input('{}? '.format(stock)))) + except: + print('\nINVALID ENTRY, TRY AGAIN\n') + break + if len(new_holdings) == 5: + flag = self._check_transaction(new_holdings) + + return new_holdings + + def print_trading_day(self): + + print("STOCK\tPRICE/SHARE\tHOLDINGS\tNET. Value\tPRICE CHANGE") + for stock, data, change in zip(self.data.keys(), self.data.values(),self.changes): + value = data['Price'] * data['Holdings'] + print('{}\t{}\t\t{}\t\t{:.2f}\t\t{}'.format(stock, data['Price'], data['Holdings'], value, change)) + + def update_cash_assets(self, new_holdings): + + sell=0 + buy=0 + for stock, holding in zip(self.data.values(), new_holdings): + if holding > 0: + buy += stock['Price']*holding + + elif holding < 0: + sell += stock['Price']*abs(holding) + + self.cash_assets = self.cash_assets + sell - buy + + def update_stock_assets(self): + + sum=0 + for data in self.data.values(): + sum += data['Price']*data['Holdings'] + + self.stock_assets = round(sum,2) + + def print_assets(self): + + print('\nTOTAL STOCK ASSETS ARE: ${:.2f}'.format(self.stock_assets)) + print('TOTAL CASH ASSETS ARE: ${:.2f}'.format(self.cash_assets)) + print('TOTAL ASSETS ARE: ${:.2f}'.format(self.total_assets())) + + def _check_transaction(self, new_holdings): + + sum = 0 + for stock, holding in zip(self.data.values(), new_holdings): + if holding > 0: + sum += stock['Price']*holding + + elif holding < 0: + if abs(holding) > stock['Holdings']: + print('\nYOU HAVE OVERSOLD SOME STOCKS, TRY AGAIN\n') + return False + + if sum > self.cash_assets: + print('\nYOU HAVE USED ${:.2f} MORE THAN YOU HAVE, TRY AGAIN\n'.format(sum - self.cash_assets)) + return False + + return True + + def update_holdings(self, new_holdings): + + for stock, new_holding in zip(self.data.values(), new_holdings): + stock['Holdings'] += new_holding + +def print_instruction(): + + print(''' +THIS PROGRAM PLAYS THE STOCK MARKET. YOU WILL BE GIVEN +$10,000 AND MAY BUY OR SELL STOCKS. THE STOCK PRICES WILL +BE GENERATED RANDOMLY AND THEREFORE THIS MODEL DOES NOT +REPRESENT EXACTLY WHAT HAPPENS ON THE EXCHANGE. A TABLE +OF AVAILABLE STOCKS, THEIR PRICES, AND THE NUMBER OF SHARES +IN YOUR PORTFOLIO WILL BE PRINTED. FOLLOWING THIS, THE +INITIALS OF EACH STOCK WILL BE PRINTED WITH A QUESTION +MARK. HERE YOU INDICATE A TRANSACTION. TO BUY A STOCK +TYPE +NNN, TO SELL A STOCK TYPE -NNN, WHERE NNN IS THE +NUMBER OF SHARES. A BROKERAGE FEE OF 1% WILL BE CHARGED +ON ALL TRANSACTIONS. NOTE THAT IF A STOCK'S VALUE DROPS +TO ZERO IT MAY REBOUND TO A POSITIVE VALUE AGAIN. YOU +HAVE $10,000 TO INVEST. USE INTEGERS FOR ALL YOUR INPUTS. +(NOTE: TO GET A 'FEEL' FOR THE MARKET RUN FOR AT LEAST +10 DAYS) + ------------GOOD LUCK!------------\n + ''') + +if __name__ == "__main__": + + print('\t\t STOCK MARKET') + help = input('\nDO YOU WANT INSTRUCTIONS(YES OR NO)? ') + + #Printing Instruction + if help == 'YES' or help == 'yes' or help == 'Yes': + print_instruction() + + #Initialize Game + Game = Stock_Market() + + #Do first day + Game.print_first_day() + new_holdings = Game.take_inputs() + Game.update_holdings(new_holdings) + Game.update_cash_assets(new_holdings) + print('\n------------END OF TRADING DAY--------------\n') + + response = 1 + while response == 1: + + #Simulate a DAY + Game.update_prices() + Game.print_trading_day() + Game.print_exchange_average() + Game.update_stock_assets() + Game.print_assets() + + response = int(input('\nDO YOU WISH TO CONTINUE (YES-TYPE 1, NO-TYPE 0)? ')) + if response == 0: + break + + new_holdings = Game.take_inputs() + Game.update_holdings(new_holdings) + Game.update_cash_assets(new_holdings) + print('\n------------END OF TRADING DAY--------------\n') + + print('\nHOPE YOU HAD FUN!!!!') + input('') From d5a226079606527aeca533b1de9a49f03bdea739 Mon Sep 17 00:00:00 2001 From: Bill Cruise Date: Sat, 8 Jan 2022 12:56:44 -0500 Subject: [PATCH 665/749] Reformat to make code more Pythonic and (hopefully) readable. --- 43_Hammurabi/python/hamurabi.py | 369 +++++++++++++++++--------------- 1 file changed, 194 insertions(+), 175 deletions(-) diff --git a/43_Hammurabi/python/hamurabi.py b/43_Hammurabi/python/hamurabi.py index 24ebe581..39ac4cd1 100644 --- a/43_Hammurabi/python/hamurabi.py +++ b/43_Hammurabi/python/hamurabi.py @@ -1,183 +1,202 @@ -def GenRandom(C): - C=int(random()*5)+1 -def BadInput850(): - print ( "\nHAMURABI: I CANNOT DO WHAT YOU WISH.") - print ( "GET YOURSELF ANOTHER STEWARD!!!!!") - Z=99 -def BadInput710(S): - print ( "HAMURABI: THINK AGAIN. YOU HAVE ONLY") - print ( S,"BUSHELS OF GRAIN. NOW THEN,") -def BadInput720(A): - print ( "HAMURABI: THINK AGAIN. YOU OWN ONLY",A,"ACRES. NOW THEN,") -def BadInput710(S): - print ( "HAMURABI: THINK AGAIN. YOU HAVE ONLY") - print ( S,"BUSHELS OF GRAIN. NOW THEN,") -def NationalFink(): - print ( "DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY") - print ( "BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE") - print ( "ALSO BEEN DECLARED NATIONAL FINK!!!!") - -def B_input(promptstring): #emulate BASIC input. It rejects non-numeric values - x=input(promptstring) - while x.isalpha(): - x=input("?REDO FROM START\n? ") - return int(x) - from random import random from random import seed + + +def gen_random(C): + C = int(random() * 5) + 1 + + +def bad_input_850(): + print("\nHAMURABI: I CANNOT DO WHAT YOU WISH.") + print("GET YOURSELF ANOTHER STEWARD!!!!!") + Z = 99 + + +def bad_input_710(S): + print("HAMURABI: THINK AGAIN. YOU HAVE ONLY") + print(S, "BUSHELS OF GRAIN. NOW THEN,") + + +def bad_input_720(A): + print("HAMURABI: THINK AGAIN. YOU OWN ONLY", A, "ACRES. NOW THEN,") + + +def national_fink(): + print("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY") + print("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE") + print("ALSO BEEN DECLARED NATIONAL FINK!!!!") + + +def b_input(promptstring): # emulate BASIC input. It rejects non-numeric values + x = input(promptstring) + while x.isalpha(): + x = input("?REDO FROM START\n? ") + return int(x) + + seed() title = "HAMURABI" -title = title.rjust(32,' ') -print (title) +title = title.rjust(32, ' ') +print(title) attribution = "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" -attribution = attribution.rjust(15," ") -print (attribution) -print ('\n\n\n') -print ("TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA") -print ("FOR A TEN-YEAR TERM OF OFFICE.\n") -D1=0 -P1=0 -Z=0 #year -P=95 #population -S=2800 #grain stores -H=3000 -E=H-S #rats eaten -Y=3 #yield (amount of production from land). Reused as price per acre -A=H/Y #acres of land -I=5 #immigrants -Q=1 #boolean for plague, also input for buy/sell land -D=0 # people -while (Z<11): #line 270. main loop. while the year is less than 11 - print ("\n\n\nHAMURABI: I BEG TO REPORT TO YOU") - Z=Z+1 #year - print ( "IN YEAR",Z,",",D,"PEOPLE STARVED,",I,"CAME TO THE CITY,") - P=P+I - if Q==0: - P=int(P/2) - print ("A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED.") - print ("POPULATION IS NOW",P) - print ("THE CITY NOW OWNS",A,"ACRES.") - print ("YOU HARVESTED",Y,"BUSHELS PER ACRE.") - print ("THE RATS ATE",E,"BUSHELS.") - print ("YOU NOW HAVE ",S,"BUSHELS IN STORE.\n") - C=int(10*random()) #random number between 1 and 10 - Y=C+17 - print ("LAND IS TRADING AT",Y,"BUSHELS PER ACRE.") - Q=-99 #dummy value to track status - while Q==-99: #always run the loop once - Q = B_input("HOW MANY ACRES DO YOU WISH TO BUY? ") - if Q<0: - Q = -1 #to avoid the corner case of Q=-99 - BadInput850() - Z=99 #jump out of main loop and exit - elif Y*Q>S: #can't afford it - BadInput710(S) - Q=-99 # give'm a second change to get it right - elif Y*Q<=S: #normal case, can afford it - A=A+Q #increase the number of acres by Q - S=S-Y*Q #decrease the amount of grain in store to pay for it - C=0 #WTF is C for? - if Q ==0 and Z!=99: #maybe you want to sell some land? +attribution = attribution.rjust(15, " ") +print(attribution) +print('\n\n\n') +print("TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA") +print("FOR A TEN-YEAR TERM OF OFFICE.\n") + +D1 = 0 +P1 = 0 +Z = 0 # year +P = 95 # population +S = 2800 # grain stores +H = 3000 +E = H - S # rats eaten +Y = 3 # yield (amount of production from land). Reused as price per acre +A = H / Y # acres of land +I = 5 # immigrants +Q = 1 # boolean for plague, also input for buy/sell land +D = 0 # people + +while Z < 11: # line 270. main loop. while the year is less than 11 + print("\n\n\nHAMURABI: I BEG TO REPORT TO YOU") + Z = Z + 1 # year + print("IN YEAR", Z, ",", D, "PEOPLE STARVED,", I, "CAME TO THE CITY,") + P = P + I + + if Q == 0: + P = int(P / 2) + print("A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED.") + + print("POPULATION IS NOW", P) + print("THE CITY NOW OWNS", A, "ACRES.") + print("YOU HARVESTED", Y, "BUSHELS PER ACRE.") + print("THE RATS ATE", E, "BUSHELS.") + print("YOU NOW HAVE ", S, "BUSHELS IN STORE.\n") + C = int(10 * random()) # random number between 1 and 10 + Y = C + 17 + print("LAND IS TRADING AT", Y, "BUSHELS PER ACRE.") + + Q = -99 # dummy value to track status + while Q == -99: # always run the loop once + Q = b_input("HOW MANY ACRES DO YOU WISH TO BUY? ") + if Q < 0: + Q = -1 # to avoid the corner case of Q=-99 + bad_input_850() + Z = 99 # jump out of main loop and exit + elif Y * Q > S: # can't afford it + bad_input_710(S) + Q = -99 # give'm a second change to get it right + elif Y * Q <= S: # normal case, can afford it + A = A + Q # increase the number of acres by Q + S = S - Y * Q # decrease the amount of grain in store to pay for it + C = 0 # WTF is C for? + + if Q == 0 and Z != 99: # maybe you want to sell some land? Q = -99 - while Q==-99: - Q = B_input( "HOW MANY ACRES DO YOU WISH TO SELL? ") - if Q<0: - BadInput850() - Z=99 #jump out of main loop and exit - elif Q<=A:#normal case - A=A-Q # reduce the acres - S=S+Y*Q #add to grain stores - C=0 #still don't know what C is for - else: #Q>A error! - BadInput720() - Q=-99 #reloop - print ("\n") - Q=-99 - while Q==-99 and Z!=99: - Q = B_input("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? ") - if Q<0: - BadInput850() - #REM *** TRYING TO USE MORE GRAIN THAN IS IN SILOS? - elif Q>S: - BadInput710 - Q=-99 #try again! - else: #we're good. do the transaction - S=S-Q #remove the grain from the stores - C=1 #set the speed of light to 1. jk - print ("\n") - D=-99 #dummy value to force at least one loop - while D == -99 and Z!=99: - D = B_input("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? ") - if D<0: - BadInput850() - Z=99 - elif D>0: - if D>A: - #REM *** TRYING TO PLANT MORE ACRES THAN YOU OWN? - BadInput720(A) - D = -99 - elif int(D/2)>S: - #REM *** ENOUGH GRAIN FOR SEED? - BadInput710(S) + while Q == -99: + Q = b_input("HOW MANY ACRES DO YOU WISH TO SELL? ") + if Q < 0: + bad_input_850() + Z = 99 # jump out of main loop and exit + elif Q <= A: # normal case + A = A - Q # reduce the acres + S = S + Y * Q # add to grain stores + C = 0 # still don't know what C is for + else: # Q>A error! + bad_input_720(A) + Q = -99 # reloop + print("\n") + + Q = -99 + while Q == -99 and Z != 99: + Q = b_input("HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? ") + if Q < 0: + bad_input_850() + # REM *** TRYING TO USE MORE GRAIN THAN IS IN SILOS? + elif Q > S: + bad_input_710(S) + Q = -99 # try again! + else: # we're good. do the transaction + S = S - Q # remove the grain from the stores + C = 1 # set the speed of light to 1. jk + + print("\n") + D = -99 # dummy value to force at least one loop + while D == -99 and Z != 99: + D = b_input("HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? ") + if D < 0: + bad_input_850() + Z = 99 + elif D > 0: + if D > A: + # REM *** TRYING TO PLANT MORE ACRES THAN YOU OWN? + bad_input_720(A) D = -99 - elif D>=10*P: - #REM *** ENOUGH PEOPLE TO TEND THE CROPS? - print ("BUT YOU HAVE ONLY",P,"PEOPLE TO TEND THE FIELDS! NOW THEN,") - D=-99 - else: #we're good. decrement the grain store - S=S-int(D/2) - GenRandom(C) - #REM *** A BOUNTIFUL HARVEST! - Y=C - H=D*Y - E=0 - GenRandom(C) - if int(C/2)==C/2: #even number. 50/50 chance - #REM *** RATS ARE RUNNING WILD!! - E=int(S/C) #calc losses due to rats, based on previous random number - S=S-E+H #deduct losses from stores - GenRandom(C) - #REM *** LET'S HAVE SOME BABIES - I=int(C*(20*A+S)/P/100+1) - #REM *** HOW MANY PEOPLE HAD FULL TUMMIES? - C=int(Q/20) - #REM *** HORROS, A 15% CHANCE OF PLAGUE - #yeah, should be HORRORS, but left it - Q=int(10*(2*random()-.3)) - if P>=C and Z!=99: #if there are some people without full bellies... - #REM *** STARVE ENOUGH FOR IMPEACHMENT? - D=P-C - if D>.45*P: - print ("\nYOU STARVED",D,"PEOPLE IN ONE YEAR!!!") - NationalFink() - Z=99 #exit the loop - P1=((Z-1)*P1+D*100/P)/Z - P=C - D1=D1+D -if Z!=99: - print ( "IN YOUR 10-YEAR TERM OF OFFICE,",P1,"PERCENT OF THE") - print ( "POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF") - print ( D1,"PEOPLE DIED!!") - L=A/P - print ( "YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH") - print ( L,"ACRES PER PERSON.\n") - if (P1>33 or L<7): - NationalFink() - elif (P1>10 or L<9): - print ( "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.") - print ( "THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,") - print ( "FRANKLY, HATE YOUR GUTS!!") - elif (P1>3 or L<10): - print ( "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT") - print ( "REALLY WASN'T TOO BAD AT ALL. ",int(P*.8*random()),"PEOPLE") - print ( "WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR") - print ( "TRIVIAL PROBLEMS.") - else: - print ( "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND") - print ( "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!\n") - for N in range(1,10): - print ( '\a') + elif int(D / 2) > S: + # REM *** ENOUGH GRAIN FOR SEED? + bad_input_710(S) + D = -99 + elif D >= 10 * P: + # REM *** ENOUGH PEOPLE TO TEND THE CROPS? + print("BUT YOU HAVE ONLY", P, "PEOPLE TO TEND THE FIELDS! NOW THEN,") + D = -99 + else: # we're good. decrement the grain store + S = S - int(D / 2) + + gen_random(C) + # REM *** A BOUNTIFUL HARVEST! + Y = C + H = D * Y + E = 0 + + gen_random(C) + if int(C / 2) == C / 2: # even number. 50/50 chance + # REM *** RATS ARE RUNNING WILD!! + E = int(S / C) # calc losses due to rats, based on previous random number + S = S - E + H # deduct losses from stores + + gen_random(C) + # REM *** LET'S HAVE SOME BABIES + I = int(C * (20 * A + S) / P / 100 + 1) + # REM *** HOW MANY PEOPLE HAD FULL TUMMIES? + C = int(Q / 20) + # REM *** HORROS, A 15% CHANCE OF PLAGUE + # yeah, should be HORRORS, but left it + Q = int(10 * (2 * random() - .3)) + if P >= C and Z != 99: # if there are some people without full bellies... + # REM *** STARVE ENOUGH FOR IMPEACHMENT? + D = P - C + if D > .45 * P: + print("\nYOU STARVED", D, "PEOPLE IN ONE YEAR!!!") + national_fink() + Z = 99 # exit the loop + P1 = ((Z - 1) * P1 + D * 100 / P) / Z + P = C + D1 = D1 + D + +if Z != 99: + print("IN YOUR 10-YEAR TERM OF OFFICE,", P1, "PERCENT OF THE") + print("POPULATION STARVED PER YEAR ON THE AVERAGE, I.E. A TOTAL OF") + print(D1, "PEOPLE DIED!!") + L = A / P + print("YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH") + print(L, "ACRES PER PERSON.\n") + if P1 > 33 or L < 7: + national_fink() + elif P1 > 10 or L < 9: + print("YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.") + print("THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,") + print("FRANKLY, HATE YOUR GUTS!!") + elif P1 > 3 or L < 10: + print("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT") + print("REALLY WASN'T TOO BAD AT ALL. ", int(P * .8 * random()), "PEOPLE") + print("WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR") + print("TRIVIAL PROBLEMS.") + else: + print("A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND") + print("JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!\n") + for N in range(1, 10): + print('\a') + print("\nSO LONG FOR NOW.\n") - - - From a360ca17ca8315b28ee40a4829f786cf88c55529 Mon Sep 17 00:00:00 2001 From: Bill Cruise Date: Sat, 8 Jan 2022 13:18:09 -0500 Subject: [PATCH 666/749] Return a value from gen_random function. --- 43_Hammurabi/python/hamurabi.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/43_Hammurabi/python/hamurabi.py b/43_Hammurabi/python/hamurabi.py index 39ac4cd1..7c18f892 100644 --- a/43_Hammurabi/python/hamurabi.py +++ b/43_Hammurabi/python/hamurabi.py @@ -2,8 +2,8 @@ from random import random from random import seed -def gen_random(C): - C = int(random() * 5) + 1 +def gen_random(): + return int(random() * 5) + 1 def bad_input_850(): @@ -144,19 +144,19 @@ while Z < 11: # line 270. main loop. while the year is less than 11 else: # we're good. decrement the grain store S = S - int(D / 2) - gen_random(C) + C = gen_random() # REM *** A BOUNTIFUL HARVEST! Y = C H = D * Y E = 0 - gen_random(C) + C = gen_random() if int(C / 2) == C / 2: # even number. 50/50 chance # REM *** RATS ARE RUNNING WILD!! E = int(S / C) # calc losses due to rats, based on previous random number S = S - E + H # deduct losses from stores - gen_random(C) + C = gen_random() # REM *** LET'S HAVE SOME BABIES I = int(C * (20 * A + S) / P / 100 + 1) # REM *** HOW MANY PEOPLE HAD FULL TUMMIES? From a78c1e812209d2a5f6f20afb0207725a4aba0442 Mon Sep 17 00:00:00 2001 From: Tim Buchalka <70119791+journich@users.noreply.github.com> Date: Sun, 9 Jan 2022 06:50:24 +1030 Subject: [PATCH 667/749] Another issue #457 bugfix. Player selecting enemy weapons option BOTH (GUNS and MISSILES) now calculates amount correctly resulting in a higher likelyhood of being shot down. Added comments to make it clearer how the calculation worked for all enemy weapons. --- 12_Bombs_Away/java/src/BombsAway.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/12_Bombs_Away/java/src/BombsAway.java b/12_Bombs_Away/java/src/BombsAway.java index b084ddcb..290b2c6d 100644 --- a/12_Bombs_Away/java/src/BombsAway.java +++ b/12_Bombs_Away/java/src/BombsAway.java @@ -281,18 +281,20 @@ public class BombsAway { if(enemyDefences == null) { System.out.println("TRY AGAIN..."); } else { + chanceToBeHit = 35; switch(enemyDefences) { case MISSILES: - chanceToBeHit = 35; + // MISSILES... An extra 35 but cannot specify percentage hit rate for gunners break; case GUNS: - - // fall through (no break) on purpose to case BOTH - // since it's identical code for GUNS or BOTH weapons + // GUNS... No extra 35 but can specify percentage hit rate for gunners + chanceToBeHit = 0; + // fall through (no break) on purpose because remaining code is applicable + // for both GUNS and BOTH options. case BOTH: - chanceToBeHit = 0; + // BOTH... An extra 35 and percentage hit rate for gunners can be specified. 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..."); From 7274cf82dd2835b681884e873f969ed10315e1c8 Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Sat, 8 Jan 2022 15:42:01 -0500 Subject: [PATCH 668/749] Port 67_One_Check to Perl. This is pretty much a straight port to idiomatic Perl. --- 67_One_Check/perl/onecheck.pl | 252 ++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100755 67_One_Check/perl/onecheck.pl diff --git a/67_One_Check/perl/onecheck.pl b/67_One_Check/perl/onecheck.pl new file mode 100755 index 00000000..62f1f0be --- /dev/null +++ b/67_One_Check/perl/onecheck.pl @@ -0,0 +1,252 @@ +#!/usr/bin/env perl + +use 5.010; # To get 'state' and 'say' + +use strict; # Require explicit declaration of variables +use warnings; # Enable optional compiler warnings + +use English; # Use more friendly names for Perl's magic variables +use List::Util qw{ sum }; # Add all its arguments +use Term::ReadLine; # Prompt and return user input + +our $VERSION = '0.000_01'; + +print <<'EOD'; + ONE CHECK + Creative Computing Morristown, New Jersey + + + +Solitaire checker puzzle by David Ahl + +48 checkers are placed on the 2 outside spaces of a +standard 64-square checkerboard. The object is to +remove as many checkers as possible by diagonal jumps +(as in standard checkers). Use the numbered board to +indicate the square you wish to jump from and to. On +the board printed out on each turn '1' indicates a +checker and '0' an empty square. When you have no +possible jumps remaining, input a '0' in response to +question 'Jump from?' +EOD + +while ( 1 ) { # Iterate indefinitely + + board_num(); # Display the numerical board. + + # Initialize the board, which is a two-dimensional array. + my @board = map { [ ( 1 ) x 8 ] } 0 .. 7; # Initialize to all 1. + for my $row ( 2 .. 5 ) { # Set the center section to 0 + for my $col ( 2 .. 5 ) { + $board[$row][$col] = 0; + } + } + + print <<'EOD'; +And here is the opening position of the checkers. + +EOD + board_pos( \@board ); + + my $moves = 0; # Number of moves made. + + # A game proceeds while 'Jump from' is a true value. We make use of + # the fact that of the possible returns, only 0 evaluates false. + while ( my $jump_from = get_input( + 'Jump from? ', + sub { + $ARG = lc; # The caller sees this. + return 1 if $ARG eq 'b'; + return unless m/ \A [0-9]+ \z /smx; + $ARG += 0; # Numify, because string '00' is true. + return $ARG < 65; + }, + "Please enter a number from 0 to 64, or 'b' to re-display the numeric board\n" + ) + ) { + if ( $jump_from eq 'b' ) { + board_num(); + board_pos( \@board ); + next; + } + + my $jump_to = get_input( + ' to? ', + sub { m/ \A [0-9]+ \z /smx }, + "Please enter a number from 1 to 64\n", + ); + + if ( make_move( \@board, $jump_from, $jump_to ) ) { + $moves++; + board_pos( \@board ); + } else { + say 'Illegal move. Try again.'; + } + } + + my $checkers_left = sum( map { sum( @{ $board[$_] } ) } 0 .. 7 ); + print <<"EOD"; + +You made $moves jumps and had $checkers_left pieces +remaining on the board. + +EOD + + last unless get_yes_no( 'Try again' ); + +} + +print <<'EOD'; + +O.K. Hope you had fun!! +EOD + +# Print the numerical board +sub board_num { + print <<'EOD'; + +Here is the numerical board: + +EOD + foreach my $row ( 0 .. 7 ) { + state $tplt = ( '%3d' x 8 ) . "\n"; + my $inx = $row * 8; + printf $tplt, map { $inx + $_ } 1 .. 8; + } + say ''; + return; +} + +# Print the board position +sub board_pos { + my ( $board ) = @_; + for my $row ( 0 .. 7 ) { + state $tplt = ( '%2d' x 8 ) . "\n"; + printf $tplt, @{ $board->[$row] }; + } + say ''; + return; +} + +# Make the move. This is a subroutine for convenience in control flow. +# We return a true value for success, and false for failure. +sub make_move { + my ( $board, $jump_from, $jump_to ) = @_; + $jump_from -= 1; + $jump_to -= 1; + my $from_row = int( $jump_from / 8 ); # Truncates toward 0 + my $from_col = $jump_from % 8; + my $to_row = int( $jump_to / 8 ); # Truncates toward 0 + my $to_col = $jump_to % 8; + return unless $board->[$from_row][$from_col]; # From must be occupied + return if $board->[$to_row][$to_col]; # To must be vacant + return unless abs( $from_row - $to_row ) == 2; # Must cross two rows + return unless abs( $from_col - $to_col ) == 2; # Must cross two cols + my $over_row = ( $from_row + $to_row ) / 2; # The row jumped over + my $over_col = ( $from_col + $to_col ) / 2; # The col jumped over + $board->[$from_row][$from_col] = # Clear the from cell + $board->[$over_row][$over_col] = 0; # and the jumped cell + $board->[$to_row][$to_col] = 1; # Occupy the to cell + return 1; +} + +# Get input from the user. The arguments are: +# * The prompt +# * A reference to validation code. This code receives the response in +# $ARG and returns true for a valid response. +# * A warning to print if the response is not valid. This must end in a +# return. +# The first valid response is returned. An end-of-file terminates the +# script. +sub get_input { + my ( $prompt, $validate, $warning ) = @ARG; + + # If no validator is passed, default to one that always returns + # true. + $validate ||= sub { 1 }; + + # Create the readline object. The 'state' causes the variable to be + # initialized only once, no matter how many times this subroutine is + # called. The do { ... } is a compound statement used because we + # need to tweak the created object before we store it. + state $term = do { + my $obj = Term::ReadLine->new( 'reverse' ); + $obj->ornaments( 0 ); + $obj; + }; + + while ( 1 ) { # Iterate indefinitely + + # Read the input into the topic variable, localized to prevent + # Spooky Action at a Distance. We exit on undef, which signals + # end-of-file. + exit unless defined( local $ARG = $term->readline( $prompt ) ); + + # Return the input if it is valid. + return $ARG if $validate->(); + + # Issue the warning, and go around the merry-go-round again. + warn $warning; + } +} + +# Get a yes-or-no answer. The argument is the prompt, which will have +# '? [y/n]: ' appended. The donkey work is done by get_input(), which is +# requested to validate the response as beginning with 'y' or 'n', +# case-insensitive. The return is a true value for 'y' and a false value +# for 'n'. +sub get_yes_no { + my ( $prompt ) = @ARG; + state $map_answer = { + n => 0, + y => 1, + }; + my $resp = lc get_input( + "$prompt? [y/n]: ", + sub { m/ \A [yn] /smxi }, + "Please respond 'y' or 'n'\n", + ); + return $map_answer->{ substr $resp, 0, 1 }; +} + +__END__ + +=head1 TITLE + +one check - Play the game 'One Check' from Basic Computer Games + +=head1 SYNOPSIS + + one check.pl + +=head1 DETAILS + +This Perl script is a port of onecheck. + +This is a solitaire game played on a checker board, where the object is +to eliminate as many checkers as possible by making diagonal jumps and +removing the jumped checkers. + +It is pretty much a straight port of the BASIC original. + +=head1 PORTED BY + +Thomas R. Wyant, III F + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2022 by Thomas R. Wyant, III + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl 5.10.0. For more details, see the Artistic +License 1.0 at +L, and/or the +Gnu GPL at L. + +This program is distributed in the hope that it will be useful, but +without any warranty; without even the implied warranty of +merchantability or fitness for a particular purpose. + +=cut + +# ex: set expandtab tabstop=4 textwidth=72 : From c8fccde8892305549e689e4eb353ee86a57dd0f5 Mon Sep 17 00:00:00 2001 From: Yuriy Lyeshchenko Date: Sat, 8 Jan 2022 19:00:19 -0600 Subject: [PATCH 669/749] Implementing https://github.com/coding-horror/basic-computer-games/blob/main/15_Boxing/boxing.bas in C# --- 15_Boxing/csharp/AttackStrategy.cs | 48 ++++++++ 15_Boxing/csharp/Boxer.cs | 45 ++++++++ 15_Boxing/csharp/Boxing.csproj | 10 ++ 15_Boxing/csharp/Boxing.sln | 22 ++++ 15_Boxing/csharp/OpponentAttackStrategy.cs | 115 ++++++++++++++++++++ 15_Boxing/csharp/PlayerAttackStrategy.cs | 121 +++++++++++++++++++++ 15_Boxing/csharp/Program.cs | 29 +++++ 15_Boxing/csharp/Punch.cs | 9 ++ 15_Boxing/csharp/Round.cs | 96 ++++++++++++++++ 15_Boxing/csharp/Utils.cs | 35 ++++++ 10 files changed, 530 insertions(+) create mode 100644 15_Boxing/csharp/AttackStrategy.cs create mode 100644 15_Boxing/csharp/Boxer.cs create mode 100644 15_Boxing/csharp/Boxing.csproj create mode 100644 15_Boxing/csharp/Boxing.sln create mode 100644 15_Boxing/csharp/OpponentAttackStrategy.cs create mode 100644 15_Boxing/csharp/PlayerAttackStrategy.cs create mode 100644 15_Boxing/csharp/Program.cs create mode 100644 15_Boxing/csharp/Punch.cs create mode 100644 15_Boxing/csharp/Round.cs create mode 100644 15_Boxing/csharp/Utils.cs diff --git a/15_Boxing/csharp/AttackStrategy.cs b/15_Boxing/csharp/AttackStrategy.cs new file mode 100644 index 00000000..5ffdb2cc --- /dev/null +++ b/15_Boxing/csharp/AttackStrategy.cs @@ -0,0 +1,48 @@ +namespace Boxing; + +public abstract class AttackStrategy +{ + protected const int KnockoutDamageThreshold = 35; + protected readonly Boxer Other; + protected readonly Stack Work; + private readonly Action _notifyGameEnded; + + public AttackStrategy(Boxer other, Stack work, Action notifyGameEnded) + { + Other = other; + Work = work; + _notifyGameEnded = notifyGameEnded; + } + + public void Attack() + { + var punch = GetPunch(); + if (punch.IsBestPunch) + { + Other.DamageTaken += 2; + } + + Work.Push(punch.Punch switch + { + Punch.FullSwing => FullSwing, + Punch.Hook => Hook, + Punch.Uppercut => Uppercut, + _ => Jab + }); + } + + protected abstract AttackPunch GetPunch(); + protected abstract void FullSwing(); + protected abstract void Hook(); + protected abstract void Uppercut(); + protected abstract void Jab(); + + protected void RegisterKnockout(string knockoutMessage) + { + Work.Clear(); + _notifyGameEnded(); + Console.WriteLine(knockoutMessage); + } + + protected record AttackPunch(Punch Punch, bool IsBestPunch); +} \ No newline at end of file diff --git a/15_Boxing/csharp/Boxer.cs b/15_Boxing/csharp/Boxer.cs new file mode 100644 index 00000000..3f5fdd26 --- /dev/null +++ b/15_Boxing/csharp/Boxer.cs @@ -0,0 +1,45 @@ +namespace Boxing; + +public class Boxer +{ + private int _wins; + + private string Name { get; set; } = string.Empty; + + public Punch BestPunch { get; set; } + + public Punch Vulnerability { get; set; } + + public void SetName(string prompt) + { + Console.WriteLine(prompt); + string? name; + do + { + name = Console.ReadLine(); + } while (string.IsNullOrWhiteSpace(name)); + Name = name; + } + + public int DamageTaken { get; set; } + + public void ResetForNewRound() => DamageTaken = 0; + + public void RecordWin() => _wins += 1; + + public bool IsWinner => _wins >= 2; + + public override string ToString() => Name; +} + +public class Opponent : Boxer +{ + public void SetRandomPunches() + { + do + { + BestPunch = (Punch) GameUtils.Roll(4); // B1 + Vulnerability = (Punch) GameUtils.Roll(4); // D1 + } while (BestPunch == Vulnerability); + } +} \ No newline at end of file diff --git a/15_Boxing/csharp/Boxing.csproj b/15_Boxing/csharp/Boxing.csproj new file mode 100644 index 00000000..74abf5c9 --- /dev/null +++ b/15_Boxing/csharp/Boxing.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/15_Boxing/csharp/Boxing.sln b/15_Boxing/csharp/Boxing.sln new file mode 100644 index 00000000..6202b593 --- /dev/null +++ b/15_Boxing/csharp/Boxing.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30114.105 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Boxing", "Boxing.csproj", "{52A7BDE5-3085-4F58-AC57-2BA4E65212D8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52A7BDE5-3085-4F58-AC57-2BA4E65212D8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/15_Boxing/csharp/OpponentAttackStrategy.cs b/15_Boxing/csharp/OpponentAttackStrategy.cs new file mode 100644 index 00000000..c5bf3e38 --- /dev/null +++ b/15_Boxing/csharp/OpponentAttackStrategy.cs @@ -0,0 +1,115 @@ +using static Boxing.GameUtils; +using static System.Console; + +namespace Boxing; + +public class OpponentAttackStrategy : AttackStrategy +{ + private readonly Opponent _opponent; + + public OpponentAttackStrategy(Opponent opponent, Boxer player, Action notifyGameEnded, Stack work) : base(player, work, notifyGameEnded) + { + _opponent = opponent; + } + + protected override AttackPunch GetPunch() + { + var punch = (Punch)Roll(4); + return new AttackPunch(punch, punch == _opponent.BestPunch); + } + + protected override void FullSwing() // 720 + { + Write($"{_opponent} TAKES A FULL SWING AND"); + if (Other.Vulnerability == Punch.FullSwing) + { + ScoreFullSwing(); + } + else + { + if (RollSatisfies(60, x => x < 30)) + { + WriteLine(" IT'S BLOCKED!"); + } + else + { + ScoreFullSwing(); + } + } + + void ScoreFullSwing() + { + WriteLine(" POW!!!!! HE HITS HIM RIGHT IN THE FACE!"); + if (Other.DamageTaken > KnockoutDamageThreshold) + { + Work.Push(RegisterOtherKnockedOut); + } + Other.DamageTaken += 15; + } + } + + protected override void Hook() // 810 + { + Write($"{_opponent} GETS {Other} IN THE JAW (OUCH!)"); + Other.DamageTaken += 7; + WriteLine("....AND AGAIN!"); + Other.DamageTaken += 5; + if (Other.DamageTaken > KnockoutDamageThreshold) + { + Work.Push(RegisterOtherKnockedOut); + } + } + + protected override void Uppercut() // 860 + { + Write($"{Other} IS ATTACKED BY AN UPPERCUT (OH,OH)..."); + if (Other.Vulnerability == Punch.Uppercut) + { + ScoreUppercut(); + } + else + { + if (RollSatisfies(200, x => x > 75)) + { + WriteLine($" BLOCKS AND HITS {_opponent} WITH A HOOK."); + _opponent.DamageTaken += 5; + } + else + { + ScoreUppercut(); + } + } + + void ScoreUppercut() + { + WriteLine($"AND {_opponent} CONNECTS..."); + Other.DamageTaken += 8; + } + } + + protected override void Jab() // 640 + { + Write($"{_opponent} JABS AND "); + if (Other.Vulnerability == Punch.Jab) + { + ScoreJab(); + } + else + { + if (RollSatisfies(7, x => x > 4)) + { + WriteLine("BLOOD SPILLS !!!"); + ScoreJab(); + } + else + { + WriteLine("IT'S BLOCKED!"); + } + } + + void ScoreJab() => Other.DamageTaken += 5; + } + + private void RegisterOtherKnockedOut() + => RegisterKnockout($"{Other} IS KNOCKED COLD AND {_opponent} IS THE WINNER AND CHAMP!"); +} \ No newline at end of file diff --git a/15_Boxing/csharp/PlayerAttackStrategy.cs b/15_Boxing/csharp/PlayerAttackStrategy.cs new file mode 100644 index 00000000..fd43c0ed --- /dev/null +++ b/15_Boxing/csharp/PlayerAttackStrategy.cs @@ -0,0 +1,121 @@ +using static Boxing.GameUtils; +using static System.Console; +namespace Boxing; + +public class PlayerAttackStrategy : AttackStrategy +{ + private readonly Boxer _player; + + public PlayerAttackStrategy(Boxer player, Opponent opponent, Action notifyGameEnded, Stack work) + : base(opponent, work, notifyGameEnded) => _player = player; + + protected override AttackPunch GetPunch() + { + var punch = GameUtils.GetPunch($"{_player}'S PUNCH"); + return new AttackPunch(punch, punch == _player.BestPunch); + } + + protected override void FullSwing() // 340 + { + Write($"{_player} SWINGS AND "); + if (Other.Vulnerability == Punch.FullSwing) + { + ScoreFullSwing(); + } + else + { + if (RollSatisfies(30, x => x < 10)) + { + ScoreFullSwing(); + } + else + { + WriteLine("HE MISSES"); + } + } + + void ScoreFullSwing() + { + WriteLine("HE CONNECTS!"); + if (Other.DamageTaken > KnockoutDamageThreshold) + { + Work.Push(() => RegisterKnockout($"{Other} IS KNOCKED COLD AND {_player} IS THE WINNER AND CHAMP!")); + } + Other.DamageTaken += 15; + } + } + + protected override void Uppercut() // 520 + { + Write($"{_player} TRIES AN UPPERCUT "); + if (Other.Vulnerability == Punch.Uppercut) + { + ScoreUpperCut(); + } + else + { + if (RollSatisfies(100, x => x < 51)) + { + ScoreUpperCut(); + } + else + { + WriteLine("AND IT'S BLOCKED (LUCKY BLOCK!)"); + } + } + + void ScoreUpperCut() + { + WriteLine("AND HE CONNECTS!"); + Other.DamageTaken += 4; + } + } + + protected override void Hook() // 450 + { + Write($"{_player} GIVES THE HOOK... "); + if (Other.Vulnerability == Punch.Hook) + { + ScoreHookOnOpponent(); + } + else + { + if (RollSatisfies(2, x => x == 1)) + { + WriteLine("BUT IT'S BLOCKED!!!!!!!!!!!!!"); + } + else + { + ScoreHookOnOpponent(); + } + } + + void ScoreHookOnOpponent() + { + WriteLine("CONNECTS..."); + Other.DamageTaken += 7; + } + } + + protected override void Jab() + { + WriteLine($"{_player} JABS AT {Other}'S HEAD"); + if (Other.Vulnerability == Punch.Jab) + { + ScoreJabOnOpponent(); + } + else + { + if (RollSatisfies(8, x => x < 4)) + { + WriteLine("IT'S BLOCKED."); + } + else + { + ScoreJabOnOpponent(); + } + } + + void ScoreJabOnOpponent() => Other.DamageTaken += 3; + } +} \ No newline at end of file diff --git a/15_Boxing/csharp/Program.cs b/15_Boxing/csharp/Program.cs new file mode 100644 index 00000000..57923de0 --- /dev/null +++ b/15_Boxing/csharp/Program.cs @@ -0,0 +1,29 @@ +using Boxing; +using static Boxing.GameUtils; +using static System.Console; + +WriteLine(new string('\t', 33) + "BOXING"); +WriteLine(new string('\t', 15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); +WriteLine("{0}{0}{0}BOXING OLYMPIC STYLE (3 ROUNDS -- 2 OUT OF 3 WINS){0}", Environment.NewLine); + +var opponent = new Opponent(); +opponent.SetName("WHAT IS YOUR OPPONENT'S NAME"); // J$ +var player = new Boxer(); +player.SetName("INPUT YOUR MAN'S NAME"); // L$ + +PrintPunchDescription(); +player.BestPunch = GetPunch("WHAT IS YOUR MANS BEST"); // B +player.Vulnerability = GetPunch("WHAT IS HIS VULNERABILITY"); // D +opponent.SetRandomPunches(); +WriteLine($"{opponent}'S ADVANTAGE IS {opponent.BestPunch.ToFriendlyString()} AND VULNERABILITY IS SECRET."); + + +for (var i = 1; i <= 3; i ++) // R +{ + var round = new Round(player, opponent, i); + round.Start(); + round.CheckOpponentWin(); + round.CheckPlayerWin(); + if (round.GameEnded) break; +} +WriteLine("{0}{0}AND NOW GOODBYE FROM THE OLYMPIC ARENA.{0}", Environment.NewLine); \ No newline at end of file diff --git a/15_Boxing/csharp/Punch.cs b/15_Boxing/csharp/Punch.cs new file mode 100644 index 00000000..add2003a --- /dev/null +++ b/15_Boxing/csharp/Punch.cs @@ -0,0 +1,9 @@ +namespace Boxing; + +public enum Punch +{ + FullSwing = 1, + Hook = 2, + Uppercut = 3, + Jab = 4 +} \ No newline at end of file diff --git a/15_Boxing/csharp/Round.cs b/15_Boxing/csharp/Round.cs new file mode 100644 index 00000000..dfa1e26b --- /dev/null +++ b/15_Boxing/csharp/Round.cs @@ -0,0 +1,96 @@ +namespace Boxing; + +class Round +{ + + private readonly Boxer _player; + private readonly Boxer _opponent; + private readonly int _round; + private Stack _work = new(); + private readonly PlayerAttackStrategy _playerAttackStrategy; + private readonly OpponentAttackStrategy _opponentAttackStrategy; + + public bool GameEnded { get; private set; } + + public Round(Boxer player, Opponent opponent, int round) + { + _player = player; + _opponent = opponent; + _round = round; + _work.Push(ResetPlayers); + _work.Push(CheckOpponentWin); + _work.Push(CheckPlayerWin); + + void NotifyGameEnded() => GameEnded = true; + _playerAttackStrategy = new PlayerAttackStrategy(player, opponent, NotifyGameEnded, _work); + _opponentAttackStrategy = new OpponentAttackStrategy(opponent, player, NotifyGameEnded, _work); + } + + public void Start() + { + while (_work.Count > 0) + { + var action = _work.Pop(); + // This delay does not exist in the VB code but it makes a bit easier to follow the game. + // I assume the computers at the time were slow enough + // so that they did not need this delay... + Thread.Sleep(300); + action(); + } + } + + public void CheckOpponentWin() + { + if (_opponent.IsWinner) + { + Console.WriteLine($"{_opponent} WINS (NICE GOING, {_opponent})."); + GameEnded = true; + } + } + + public void CheckPlayerWin() + { + if (_player.IsWinner) + { + Console.WriteLine($"{_player} AMAZINGLY WINS!!"); + GameEnded = true; + } + } + + private void ResetPlayers() + { + _player.ResetForNewRound(); + _opponent.ResetForNewRound(); + _work.Push(RoundBegins); + } + + private void RoundBegins() + { + Console.WriteLine(); + Console.WriteLine($"ROUND {_round} BEGINS..."); + _work.Push(CheckRoundWinner); + for (var i = 0; i < 7; i++) + { + _work.Push(DecideWhoAttacks); + } + } + + private void CheckRoundWinner() + { + if (_opponent.DamageTaken > _player.DamageTaken) + { + Console.WriteLine($"{_player} WINS ROUND {_round}"); + _player.RecordWin(); + } + else + { + Console.WriteLine($"{_opponent} WINS ROUND {_round}"); + _opponent.RecordWin(); + } + } + + private void DecideWhoAttacks() + { + _work.Push( GameUtils.RollSatisfies(10, x => x > 5) ? _opponentAttackStrategy.Attack : _playerAttackStrategy.Attack ); + } +} \ No newline at end of file diff --git a/15_Boxing/csharp/Utils.cs b/15_Boxing/csharp/Utils.cs new file mode 100644 index 00000000..1ada516c --- /dev/null +++ b/15_Boxing/csharp/Utils.cs @@ -0,0 +1,35 @@ +namespace Boxing; +public static class GameUtils +{ + private static readonly Random Rnd = new((int) DateTime.UtcNow.Ticks); + public static void PrintPunchDescription() => + Console.WriteLine($"DIFFERENT PUNCHES ARE: {PunchDesc(Punch.FullSwing)}; {PunchDesc(Punch.Hook)}; {PunchDesc(Punch.Uppercut)}; {PunchDesc(Punch.Jab)}."); + + private static string PunchDesc(Punch punch) => $"({(int)punch}) {punch.ToFriendlyString()}"; + + public static Punch GetPunch(string prompt) + { + Console.WriteLine(prompt); + Punch result; + while (!Enum.TryParse(Console.ReadLine(), out result) || !Enum.IsDefined(typeof(Punch), result)) + { + PrintPunchDescription(); + } + return result; + } + + public static Func Roll { get; } = upperLimit => (int) (upperLimit * Rnd.NextSingle()) + 1; + + public static bool RollSatisfies(int upperLimit, Predicate predicate) => predicate(Roll(upperLimit)); + + public static string ToFriendlyString(this Punch punch) + => punch switch + { + Punch.FullSwing => "FULL SWING", + Punch.Hook => "HOOK", + Punch.Uppercut => "UPPERCUT", + Punch.Jab => "JAB", + _ => throw new ArgumentOutOfRangeException(nameof(punch), punch, null) + }; + +} \ No newline at end of file From 40617fa4fc357a94b58141e15980efd50382105f Mon Sep 17 00:00:00 2001 From: Mark Wieder Date: Sat, 8 Jan 2022 17:20:53 -0800 Subject: [PATCH 670/749] implementation of game 73 (Reverse) in ruby --- 73_Reverse/ruby/reverse.rb | 111 +++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 73_Reverse/ruby/reverse.rb diff --git a/73_Reverse/ruby/reverse.rb b/73_Reverse/ruby/reverse.rb new file mode 100644 index 00000000..0e2f7934 --- /dev/null +++ b/73_Reverse/ruby/reverse.rb @@ -0,0 +1,111 @@ +ARRAYSIZE = 9 +$digitArray = Array.new(ARRAYSIZE) +$winningArray = Array.new(ARRAYSIZE) + +# Method to print the rules +def displayTheRules + puts "This is the game of 'Reverse'. to win, all you have" + puts "to do is arrange a list of numbers (1 through " + ARRAYSIZE.to_s + ")" + puts "in numerical order from left to right. to move, you" + puts "tell me how many numbers (counting from the left) to" + puts "reverse. For example, if the current list is:" + puts "2 3 4 5 1 6 7 8 9" + puts "and you reverse 4, the result will be:" + puts "5 4 3 2 1 6 7 8 9" + puts "Now if you reverse 5, you win!" + puts "1 2 3 4 5 6 7 8 9" + puts "No doubt you will like this game, but" + puts "if you want to quit, reverse 0 (zero)." +end + +# Method to print the list +def printList + puts "\n" + $digitArray.join(" ") + "\n\n" +end + +# Zero-based arrays contain digits 1-9 +# Make a random array and an ordered winning answer array A[0] to A[N] +def makeRandomList + for kIndex in 0..ARRAYSIZE-1 do + $digitArray[kIndex] = kIndex+1 + $winningArray[kIndex] = kIndex+1 + end + # now randomize the digit array order + $digitArray.shuffle! +end + +def checkForWin? (triesSoFar) + # Check for a win (all array elements in order) + if $digitArray == $winningArray then + puts "You won it in " + triesSoFar.to_s + " moves!!!\n\n" + puts "try again (yes or no)?" + tryAgain = gets.strip.upcase + if tryAgain == "YES" then + return true + end + puts "\nO.K. Hope you had fun!!" + exit + end + return false +end + +def reverseIt (howManyToReverse, triesSoFar) + # REVERSE R NUMBERS AND PRINT NEW LIST + + # extract and reverse the first howManyToReverse elements of the array + subArray = $digitArray.take(howManyToReverse) + subArray.reverse! + + # get the remaining elements of the original array + endArray = $digitArray.slice(howManyToReverse, ARRAYSIZE) + # append those elements to the reversed elements + $digitArray = subArray.concat(endArray) + + # if we got all in order, randomize again + isWinner = checkForWin?(triesSoFar) + if isWinner == true then + makeRandomList + end + printList # always print the newly ordered list + return isWinner +end + +def askHowManyToReverse + puts "How many shall I reverse?"; + rNumber = gets.to_i + if rNumber > 0 then + if rNumber > ARRAYSIZE then + puts "Oops! Too many! I can reverse at most " + ARRAYSIZE.to_s + end + else + rNumber = 0 # zero or negative values end the game + end + return rNumber +end + +puts "REVERSE" +puts "Creative Computing Morristown, New Jersey\n\n\n" +puts "REVERSE -- A game of skill\n\n" + +puts "Do you want the rules?" +wantRules = gets.strip.upcase +if wantRules == "YES" then + displayTheRules +end + +makeRandomList +howManyTries = 0 +puts "\nHere we go ... the list is:" +printList # display the initial list +# start the game loop +r = askHowManyToReverse +while r != 0 do # zero will end the game + if r <= ARRAYSIZE then + howManyTries = howManyTries+1 + if reverseIt(r, howManyTries) then + howManyTries = 0 + end + end + r = askHowManyToReverse +end + From ccb2e5a7c422b61572d1f6b9b22a70a38442add0 Mon Sep 17 00:00:00 2001 From: "Eric S. Weilnau" Date: Sat, 8 Jan 2022 20:51:33 -0500 Subject: [PATCH 671/749] Add link to PowerShell implementation --- 01_Acey_Ducey/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/01_Acey_Ducey/README.md b/01_Acey_Ducey/README.md index 77ff8621..f8e16312 100644 --- a/01_Acey_Ducey/README.md +++ b/01_Acey_Ducey/README.md @@ -17,3 +17,4 @@ http://www.vintage-basic.net/games.html #### External Links - Common Lisp: https://github.com/koalahedron/lisp-computer-games/blob/master/01%20Acey%20Ducey/common-lisp/acey-deucy.lisp + - PowerShell: https://github.com/eweilnau/basic-computer-games-powershell/blob/main/AceyDucey.ps1 From 52cbd74d19496d7bf33ea5627690b52082b87f13 Mon Sep 17 00:00:00 2001 From: Kanykei Akmatova Date: Sat, 8 Jan 2022 21:55:47 -0500 Subject: [PATCH 672/749] FlipFlop port to csharp --- 36_Flip_Flop/csharp/FlipFlop.cs | 197 ++++++++++++++++++++++++++++ 36_Flip_Flop/csharp/FlipFlop.csproj | 10 ++ 36_Flip_Flop/csharp/FlipFlop.sln | 25 ++++ 3 files changed, 232 insertions(+) create mode 100644 36_Flip_Flop/csharp/FlipFlop.cs create mode 100644 36_Flip_Flop/csharp/FlipFlop.csproj create mode 100644 36_Flip_Flop/csharp/FlipFlop.sln diff --git a/36_Flip_Flop/csharp/FlipFlop.cs b/36_Flip_Flop/csharp/FlipFlop.cs new file mode 100644 index 00000000..53c613e8 --- /dev/null +++ b/36_Flip_Flop/csharp/FlipFlop.cs @@ -0,0 +1,197 @@ +// Flip Flop Game + +PrintGameInfo(); + +bool startNewGame = true; + +string[] board = new string[] { "X", "X", "X", "X", "X", "X", "X", "X", "X", "X" }; + +do +{ + int stepsCount = 0; + int lastMove = -1; + int moveIndex; + int gameSum; + double gameEntropyRate = Rnd(); + bool toPlay = false; + bool setNewBoard = true; + + Print(); + Print("HERE IS THE STARTING LINE OF X'S."); + Print(); + + do + { + bool illegalEntry; + bool equalToLastMove; + + if (setNewBoard) + { + PrintNewBoard(); + board = new string[] { "X", "X", "X", "X", "X", "X", "X", "X", "X", "X" }; + setNewBoard = false; + toPlay = true; + } + + stepsCount++; + gameSum = 0; + + // Read User's move + do + { + Write("INPUT THE NUMBER? "); + var input = Console.ReadLine(); + illegalEntry = !int.TryParse(input, out moveIndex); + + if (illegalEntry || moveIndex > 11) + { + illegalEntry = true; + Print("ILLEGAL ENTRY--TRY AGAIN."); + } + } + while (illegalEntry); + + if (moveIndex == 11) + { + // Run new game, To start a new game at any point + toPlay = false; + stepsCount = 12; + startNewGame = true; + } + + + if (moveIndex == 0) + { + // To reset the line to all X, same game + setNewBoard = true; + toPlay = false; + } + + if (toPlay) + { + board[moveIndex - 1] = board[moveIndex - 1] == "O" ? "X" : "O"; + + if (lastMove == moveIndex) + { + equalToLastMove = true; + } + else + { + equalToLastMove = false; + lastMove = moveIndex; + } + + do + { + moveIndex = equalToLastMove + ? GetMoveIndexWhenEqualeLastMove(moveIndex, gameEntropyRate) + : GetMoveIndex(moveIndex, gameEntropyRate); + + board[moveIndex] = board[moveIndex] == "O" ? "X" : "O"; + } + while (lastMove == moveIndex && board[moveIndex] == "X"); + + PrintGameBoard(board); + + foreach (var item in board) + { + if (item == "O") + { + gameSum++; + } + } + } + } + while (stepsCount < 12 && gameSum < 10); + + if (toPlay) + { + PrintGameResult(gameSum, stepsCount); + + Write("DO YOU WANT TO TRY ANOTHER PUZZLE "); + + var toContinue = Console.ReadLine(); + + if (!string.IsNullOrEmpty(toContinue) && toContinue?.ToUpper()[0] == 'N') + { + startNewGame = false; + } + + Print(); + } +} +while (startNewGame); + +void Print(string str = "") => Console.WriteLine(str); + +void Write(string value) => Console.Write(value); + +string Tab(int pos) => new(' ', pos); + +double Rnd() => new Random().NextDouble(); + +int GetMoveIndex(int moveIndex, double gameEntropyRate) +{ + double rate = Math.Tan(gameEntropyRate + moveIndex / gameEntropyRate - moveIndex) - Math.Sin(gameEntropyRate / moveIndex) + 336 * Math.Sin(8 * moveIndex); + return Convert.ToInt32(Math.Floor(10 * (rate - Math.Floor(rate)))); +} + +int GetMoveIndexWhenEqualeLastMove(int moveIndex, double gameEntropyRate) +{ + double rate = 0.592 * (1 / Math.Tan(gameEntropyRate / moveIndex + gameEntropyRate)) / Math.Sin(moveIndex * 2 + gameEntropyRate) - Math.Cos(moveIndex); + return Convert.ToInt32(Math.Floor(10 * (rate - Math.Floor(rate)))); +} + +void PrintNewBoard() +{ + Print("1 2 3 4 5 6 7 8 9 10"); + Print("X X X X X X X X X X"); + Print(); +} + +void PrintGameBoard(string[] board) +{ + Print("1 2 3 4 5 6 7 8 9 10"); + + foreach (var item in board) + { + Write($"{item} "); + } + + Print(); + Print(); +} + +void PrintGameResult(int gameSum, int stepsCount) +{ + if (gameSum == 10) + { + Print($"VERY GOOD. YOU GUESSED IT IN ONLY {stepsCount} GUESSES."); + } + else + { + Print($"TRY HARDER NEXT TIME. IT TOOK YOU {stepsCount} GUESSES."); + } +} + +void PrintGameInfo() +{ + Print(Tab(32) + "FLIPFLOP"); + Print(Tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Print(); + Print("THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:"); + Print(); + + Print("X X X X X X X X X X"); + Print(); + Print("TO THIS:"); + Print(); + Print("O O O O O O O O O O"); + Print(); + + Print("BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE"); + Print("LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON"); + Print("OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0"); + Print("(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE "); + Print("11 (ELEVEN)."); +} \ No newline at end of file diff --git a/36_Flip_Flop/csharp/FlipFlop.csproj b/36_Flip_Flop/csharp/FlipFlop.csproj new file mode 100644 index 00000000..74abf5c9 --- /dev/null +++ b/36_Flip_Flop/csharp/FlipFlop.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/36_Flip_Flop/csharp/FlipFlop.sln b/36_Flip_Flop/csharp/FlipFlop.sln new file mode 100644 index 00000000..a26f312e --- /dev/null +++ b/36_Flip_Flop/csharp/FlipFlop.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FlipFlop", "FlipFlop.csproj", "{192EDAD4-5EF5-4B11-9EB3-B17FFAD0861F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {192EDAD4-5EF5-4B11-9EB3-B17FFAD0861F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {192EDAD4-5EF5-4B11-9EB3-B17FFAD0861F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {192EDAD4-5EF5-4B11-9EB3-B17FFAD0861F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {192EDAD4-5EF5-4B11-9EB3-B17FFAD0861F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {108E5099-D7AA-4260-B587-1B1FE1AF6B54} + EndGlobalSection +EndGlobal From 68e278095d8168d821eb91fafa8a714240a7708c Mon Sep 17 00:00:00 2001 From: Joseph Nellis Date: Sat, 8 Jan 2022 20:24:12 -0800 Subject: [PATCH 673/749] Add files via upload --- 01_Acey_Ducey/java/src/AceyDucey17.java | 196 ++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 01_Acey_Ducey/java/src/AceyDucey17.java diff --git a/01_Acey_Ducey/java/src/AceyDucey17.java b/01_Acey_Ducey/java/src/AceyDucey17.java new file mode 100644 index 00000000..9b229f0b --- /dev/null +++ b/01_Acey_Ducey/java/src/AceyDucey17.java @@ -0,0 +1,196 @@ +import java.util.Random; +import java.util.Scanner; + +/** + * A modern version (JDK17) of ACEY DUCEY using post Java 8 features. Notes + * regarding new java features or differences in the original basic + * implementation are numbered and at the bottom of this code. + * The goal is to recreate the exact look and feel of the original program + * minus a large glaring bug in the original code that lets you cheat. + */ +public class AceyDucey17 { + + public static void main(String[] args) { + // notes [1] + System.out.println(""" + ACEY DUCEY CARD GAME + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER + THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP + YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING + ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE + A VALUE BETWEEN THE FIRST TWO. + IF YOU DO NOT WANT TO BET, INPUT A 0"""); + + do { + playGame(); + } while (stillInterested()); + System.out.println("O.K., HOPE YOU HAD FUN!"); + } + + public static void playGame() { + int cashOnHand = 100; // our only mutable variable note [11] + System.out.println("YOU NOW HAVE "+ cashOnHand +" DOLLARS.");// note [6] + while (cashOnHand > 0) { + System.out.println(); + System.out.println("HERE ARE YOUR NEXT TWO CARDS:"); + + final Card lowCard = Card.getRandomCard(2, Card.KING); //note [3] + System.out.println(lowCard); + final Card highCard = Card.getRandomCard(lowCard.rank() + 1, Card.ACE); + System.out.println(highCard); + + final int bet = getBet(cashOnHand); + final int winnings = determineWinnings(lowCard,highCard,bet); + cashOnHand += winnings; + if(winnings != 0){ //note [2] + System.out.println("YOU NOW HAVE "+ cashOnHand +" DOLLARS.");//note [6] + } + } + } + + public static int determineWinnings(Card lowCard, Card highCard, int bet){ + if (bet <= 0) { // note [5] + System.out.println("CHICKEN!!"); + return 0; + } + Card nextCard = Card.getRandomCard(2, Card.ACE); + System.out.println(nextCard); + if(nextCard.between(lowCard,highCard)){ + System.out.println("YOU WIN!!!"); + return bet; + } + System.out.println("SORRY, YOU LOSE"); + return -bet; + } + + public static boolean stillInterested(){ + System.out.println(); + System.out.println(); + System.out.println("SORRY, FRIEND, BUT YOU BLEW YOUR WAD."); + System.out.println(); + System.out.println(); + System.out.println("TRY AGAIN (YES OR NO)"); + Scanner input = new Scanner(System.in); + return input.nextLine() + .toUpperCase() + .startsWith("Y"); // note [9] + } + + public static int getBet(int cashOnHand){ + int bet; + do{ + System.out.println(); + System.out.print("WHAT IS YOUR BET? "); + bet = inputNumber(); + if (bet > cashOnHand) { + System.out.println("SORRY, MY FRIEND, BUT YOU BET TOO MUCH."); + System.out.println("YOU HAVE ONLY "+cashOnHand+" DOLLARS TO BET."); + } + }while(bet > cashOnHand); + return bet; + } + + public static int inputNumber() { + final Scanner input = new Scanner(System.in); + // set to negative to mark as not entered yet in case of input error. + int number = -1; + while (number < 0) { + try { + number = input.nextInt(); + } catch(Exception ex) { // note [7] + System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE"); + System.out.print("? "); + try{ + input.nextLine(); + } + catch(Exception ns_ex){ // received EOF (ctrl-d or ctrl-z if windows) + System.out.println("END OF INPUT, STOPPING PROGRAM."); + System.exit(1); + } + } + } + return number; + } + + record Card(int rank){ + // Some constants to describe face cards. + public static final int JACK = 11, QUEEN = 12, KING = 13, ACE = 14; + private static final Random random = new Random(); + + public static Card getRandomCard(int from, int to){ + return new Card(random.nextInt(from, to+1)); // note [4] + } + + public boolean between(Card lower, Card higher){ + return lower.rank() < this.rank() && this.rank() < higher.rank(); + } + + @Override + public String toString() { // note [13] + return switch (rank) { + case JACK -> "JACK"; + case QUEEN -> "QUEEN"; + case KING -> "KING"; + case ACE -> "ACE\n"; // note [10] + default -> " "+rank+" "; // note [6] + }; + } + } + + /* + Notes: + 1. Multiline strings, a.k.a. text blocks, were added in JDK15. + 2. The original game only displays the players balance if it changed, + which it does not when the player chickens out and bets zero. + 3. To pick two cards to show, the original BASIC implementation has a + bug that could cause a race condition if the RND function never chose + a lower number first and higher number second. It loops infinitely + re-choosing random numbers until the condition is met of the first + one being lower. The logic is changed a bit here so that the first + card picked is anything but an ACE, the highest possible card, + and then the second card is between the just picked first card upto + and including the ACE. + 4. Random.nextInt(origin, bound) was added in JDK17, and allows to + directly pick a range for a random integer to be generated. The second + parameter is exclusive of the range and thus why they are stated with + +1's to the face card. + 5. The original BASIC implementation has a bug that allows negative value + bets. Since you can't bet MORE cash than you have you can always bet + less including a very, very large negative value. You would do this when + the chances of winning are slim or zero since losing a hand SUBTRACTS + your bet from your cash; subtracting a negative number actually ADDS + to your cash, potentially making you an instant billionaire. + This loophole is now closed. + 6. The subtle behavior of the BASIC PRINT command causes a space to be + printed before all positive numbers as well as a trailing space. Any + place a non-face card or the players balance is printed has extra space + to mimic this behavior. + 7. Errors on input were probably specific to the interpreter. This program + tries to match the Vintage Basic interpreter's error messages. The final + input.nextLine() command exists to clear the blockage of whatever + non-number input was entered. But even that could fail if the user + types Ctrl-D (windows Ctrl-Z), signifying an EOF (end of file) and thus + the closing of STDIN channel. The original program on an EOF signal prints + "END OF INPUT IN LINE 660" and thus we cover it roughly the same way. + All of this is necessary to avoid a messy stack trace from being + printed as the program crashes. + 9. The original game only accepted a full upper case "YES" to continue + playing if bankrupted. This program is more lenient and will accept + any input that starts with the letter 'y', uppercase or not. + 10. The original game prints an extra blank line if the card is an ACE. There + is seemingly no rationale for this. + 11. Modern java best practices are edging toward a more functional paradigm + and as such, mutating state is discouraged. All other variables besides + the cashOnHand are final and initialized only once. + 12. Refactoring of the concept of a card is done with a record. Records were + introduced in JDK14. Card functionality is encapsulated in this example + of a record. An enum could be a better alternative since there are + technically only 13 cards possible. + 13. Switch expressions were introduced as far back as JDK12 but continue to + be refined for clarity, exhaustiveness. As of JDK17 pattern matching + for switch expressions can be accessed by enabling preview features. + */ +} From f9a884e22a20edfcfe4753f4bc25d398f44a1ba4 Mon Sep 17 00:00:00 2001 From: xl-c7b3 Date: Sun, 9 Jan 2022 02:49:50 -0500 Subject: [PATCH 674/749] added non-source code exclusions to .gitignore --- .gitignore | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.gitignore b/.gitignore index d2115efc..9dda64ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,18 @@ +.local/ +.vscode/ +.gradle/ +node_modules/ +buildJvm/ + +build.gradle + +.classpath +.project +.settings +.metadata +*.iml +*.ipr + *.class */.vs *.suo @@ -12,6 +27,7 @@ obj/ out/ *.py[co] + Pipfile .DS_Store From 00d6881194180555073ad75736673631b920f1ba Mon Sep 17 00:00:00 2001 From: Joe Nellis Date: Sun, 9 Jan 2022 00:48:55 -0800 Subject: [PATCH 675/749] Only display player balance if balance isn't zero. Small formatting change with replay text. --- 01_Acey_Ducey/java/src/AceyDucey17.java | 397 ++++++++++++------------ 1 file changed, 201 insertions(+), 196 deletions(-) diff --git a/01_Acey_Ducey/java/src/AceyDucey17.java b/01_Acey_Ducey/java/src/AceyDucey17.java index 9b229f0b..6192fc14 100644 --- a/01_Acey_Ducey/java/src/AceyDucey17.java +++ b/01_Acey_Ducey/java/src/AceyDucey17.java @@ -1,196 +1,201 @@ -import java.util.Random; -import java.util.Scanner; - -/** - * A modern version (JDK17) of ACEY DUCEY using post Java 8 features. Notes - * regarding new java features or differences in the original basic - * implementation are numbered and at the bottom of this code. - * The goal is to recreate the exact look and feel of the original program - * minus a large glaring bug in the original code that lets you cheat. - */ -public class AceyDucey17 { - - public static void main(String[] args) { - // notes [1] - System.out.println(""" - ACEY DUCEY CARD GAME - CREATIVE COMPUTING MORRISTOWN, NEW JERSEY - - - ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER - THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP - YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING - ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE - A VALUE BETWEEN THE FIRST TWO. - IF YOU DO NOT WANT TO BET, INPUT A 0"""); - - do { - playGame(); - } while (stillInterested()); - System.out.println("O.K., HOPE YOU HAD FUN!"); - } - - public static void playGame() { - int cashOnHand = 100; // our only mutable variable note [11] - System.out.println("YOU NOW HAVE "+ cashOnHand +" DOLLARS.");// note [6] - while (cashOnHand > 0) { - System.out.println(); - System.out.println("HERE ARE YOUR NEXT TWO CARDS:"); - - final Card lowCard = Card.getRandomCard(2, Card.KING); //note [3] - System.out.println(lowCard); - final Card highCard = Card.getRandomCard(lowCard.rank() + 1, Card.ACE); - System.out.println(highCard); - - final int bet = getBet(cashOnHand); - final int winnings = determineWinnings(lowCard,highCard,bet); - cashOnHand += winnings; - if(winnings != 0){ //note [2] - System.out.println("YOU NOW HAVE "+ cashOnHand +" DOLLARS.");//note [6] - } - } - } - - public static int determineWinnings(Card lowCard, Card highCard, int bet){ - if (bet <= 0) { // note [5] - System.out.println("CHICKEN!!"); - return 0; - } - Card nextCard = Card.getRandomCard(2, Card.ACE); - System.out.println(nextCard); - if(nextCard.between(lowCard,highCard)){ - System.out.println("YOU WIN!!!"); - return bet; - } - System.out.println("SORRY, YOU LOSE"); - return -bet; - } - - public static boolean stillInterested(){ - System.out.println(); - System.out.println(); - System.out.println("SORRY, FRIEND, BUT YOU BLEW YOUR WAD."); - System.out.println(); - System.out.println(); - System.out.println("TRY AGAIN (YES OR NO)"); - Scanner input = new Scanner(System.in); - return input.nextLine() - .toUpperCase() - .startsWith("Y"); // note [9] - } - - public static int getBet(int cashOnHand){ - int bet; - do{ - System.out.println(); - System.out.print("WHAT IS YOUR BET? "); - bet = inputNumber(); - if (bet > cashOnHand) { - System.out.println("SORRY, MY FRIEND, BUT YOU BET TOO MUCH."); - System.out.println("YOU HAVE ONLY "+cashOnHand+" DOLLARS TO BET."); - } - }while(bet > cashOnHand); - return bet; - } - - public static int inputNumber() { - final Scanner input = new Scanner(System.in); - // set to negative to mark as not entered yet in case of input error. - int number = -1; - while (number < 0) { - try { - number = input.nextInt(); - } catch(Exception ex) { // note [7] - System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE"); - System.out.print("? "); - try{ - input.nextLine(); - } - catch(Exception ns_ex){ // received EOF (ctrl-d or ctrl-z if windows) - System.out.println("END OF INPUT, STOPPING PROGRAM."); - System.exit(1); - } - } - } - return number; - } - - record Card(int rank){ - // Some constants to describe face cards. - public static final int JACK = 11, QUEEN = 12, KING = 13, ACE = 14; - private static final Random random = new Random(); - - public static Card getRandomCard(int from, int to){ - return new Card(random.nextInt(from, to+1)); // note [4] - } - - public boolean between(Card lower, Card higher){ - return lower.rank() < this.rank() && this.rank() < higher.rank(); - } - - @Override - public String toString() { // note [13] - return switch (rank) { - case JACK -> "JACK"; - case QUEEN -> "QUEEN"; - case KING -> "KING"; - case ACE -> "ACE\n"; // note [10] - default -> " "+rank+" "; // note [6] - }; - } - } - - /* - Notes: - 1. Multiline strings, a.k.a. text blocks, were added in JDK15. - 2. The original game only displays the players balance if it changed, - which it does not when the player chickens out and bets zero. - 3. To pick two cards to show, the original BASIC implementation has a - bug that could cause a race condition if the RND function never chose - a lower number first and higher number second. It loops infinitely - re-choosing random numbers until the condition is met of the first - one being lower. The logic is changed a bit here so that the first - card picked is anything but an ACE, the highest possible card, - and then the second card is between the just picked first card upto - and including the ACE. - 4. Random.nextInt(origin, bound) was added in JDK17, and allows to - directly pick a range for a random integer to be generated. The second - parameter is exclusive of the range and thus why they are stated with - +1's to the face card. - 5. The original BASIC implementation has a bug that allows negative value - bets. Since you can't bet MORE cash than you have you can always bet - less including a very, very large negative value. You would do this when - the chances of winning are slim or zero since losing a hand SUBTRACTS - your bet from your cash; subtracting a negative number actually ADDS - to your cash, potentially making you an instant billionaire. - This loophole is now closed. - 6. The subtle behavior of the BASIC PRINT command causes a space to be - printed before all positive numbers as well as a trailing space. Any - place a non-face card or the players balance is printed has extra space - to mimic this behavior. - 7. Errors on input were probably specific to the interpreter. This program - tries to match the Vintage Basic interpreter's error messages. The final - input.nextLine() command exists to clear the blockage of whatever - non-number input was entered. But even that could fail if the user - types Ctrl-D (windows Ctrl-Z), signifying an EOF (end of file) and thus - the closing of STDIN channel. The original program on an EOF signal prints - "END OF INPUT IN LINE 660" and thus we cover it roughly the same way. - All of this is necessary to avoid a messy stack trace from being - printed as the program crashes. - 9. The original game only accepted a full upper case "YES" to continue - playing if bankrupted. This program is more lenient and will accept - any input that starts with the letter 'y', uppercase or not. - 10. The original game prints an extra blank line if the card is an ACE. There - is seemingly no rationale for this. - 11. Modern java best practices are edging toward a more functional paradigm - and as such, mutating state is discouraged. All other variables besides - the cashOnHand are final and initialized only once. - 12. Refactoring of the concept of a card is done with a record. Records were - introduced in JDK14. Card functionality is encapsulated in this example - of a record. An enum could be a better alternative since there are - technically only 13 cards possible. - 13. Switch expressions were introduced as far back as JDK12 but continue to - be refined for clarity, exhaustiveness. As of JDK17 pattern matching - for switch expressions can be accessed by enabling preview features. - */ -} +import java.util.Random; +import java.util.Scanner; + +/** + * A modern version (JDK17) of ACEY DUCEY using post Java 8 features. Notes + * regarding new java features or differences in the original basic + * implementation are numbered and at the bottom of this code. + * The goal is to recreate the exact look and feel of the original program + * minus a large glaring bug in the original code that lets you cheat. + */ +public class AceyDucey17 { + + public static void main(String[] args) { + // notes [1] + System.out.println(""" + ACEY DUCEY CARD GAME + CREATIVE COMPUTING MORRISTOWN, NEW JERSEY + + + ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER + THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP + YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING + ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE + A VALUE BETWEEN THE FIRST TWO. + IF YOU DO NOT WANT TO BET, INPUT A 0"""); + + do { + playGame(); + } while (stillInterested()); + System.out.println("O.K., HOPE YOU HAD FUN!"); + } + + public static void playGame() { + int cashOnHand = 100; // our only mutable variable note [11] + System.out.println("YOU NOW HAVE "+ cashOnHand +" DOLLARS.");// note [6] + while (cashOnHand > 0) { + System.out.println(); + System.out.println("HERE ARE YOUR NEXT TWO CARDS:"); + + final Card lowCard = Card.getRandomCard(2, Card.KING); //note [3] + System.out.println(lowCard); + final Card highCard = Card.getRandomCard(lowCard.rank() + 1, Card.ACE); + System.out.println(highCard); + + final int bet = getBet(cashOnHand); + final int winnings = determineWinnings(lowCard,highCard,bet); + cashOnHand += winnings; + if(winnings != 0 || cashOnHand != 0){ //note [2] + System.out.println("YOU NOW HAVE "+ cashOnHand +" DOLLARS.");//note [6] + } + } + } + + public static int determineWinnings(Card lowCard, Card highCard, int bet){ + if (bet <= 0) { // note [5] + System.out.println("CHICKEN!!"); + return 0; + } + Card nextCard = Card.getRandomCard(2, Card.ACE); + System.out.println(nextCard); + if(nextCard.between(lowCard,highCard)){ + System.out.println("YOU WIN!!!"); + return bet; + } + System.out.println("SORRY, YOU LOSE"); + return -bet; + } + + public static boolean stillInterested(){ + System.out.println(); + System.out.println(); + System.out.println("SORRY, FRIEND, BUT YOU BLEW YOUR WAD."); + System.out.println(); + System.out.println(); + System.out.print("TRY AGAIN (YES OR NO)? "); + Scanner input = new Scanner(System.in); + boolean playAgain = input.nextLine() + .toUpperCase() + .startsWith("Y"); // note [9] + System.out.println(); + System.out.println(); + return playAgain; + } + + public static int getBet(int cashOnHand){ + int bet; + do{ + System.out.println(); + System.out.print("WHAT IS YOUR BET? "); + bet = inputNumber(); + if (bet > cashOnHand) { + System.out.println("SORRY, MY FRIEND, BUT YOU BET TOO MUCH."); + System.out.println("YOU HAVE ONLY "+cashOnHand+" DOLLARS TO BET."); + } + }while(bet > cashOnHand); + return bet; + } + + public static int inputNumber() { + final Scanner input = new Scanner(System.in); + // set to negative to mark as not entered yet in case of input error. + int number = -1; + while (number < 0) { + try { + number = input.nextInt(); + } catch(Exception ex) { // note [7] + System.out.println("!NUMBER EXPECTED - RETRY INPUT LINE"); + System.out.print("? "); + try{ + input.nextLine(); + } + catch(Exception ns_ex){ // received EOF (ctrl-d or ctrl-z if windows) + System.out.println("END OF INPUT, STOPPING PROGRAM."); + System.exit(1); + } + } + } + return number; + } + + record Card(int rank){ + // Some constants to describe face cards. + public static final int JACK = 11, QUEEN = 12, KING = 13, ACE = 14; + private static final Random random = new Random(); + + public static Card getRandomCard(int from, int to){ + return new Card(random.nextInt(from, to+1)); // note [4] + } + + public boolean between(Card lower, Card higher){ + return lower.rank() < this.rank() && this.rank() < higher.rank(); + } + + @Override + public String toString() { // note [13] + return switch (rank) { + case JACK -> "JACK"; + case QUEEN -> "QUEEN"; + case KING -> "KING"; + case ACE -> "ACE\n"; // note [10] + default -> " "+rank+" "; // note [6] + }; + } + } + + /* + Notes: + 1. Multiline strings, a.k.a. text blocks, were added in JDK15. + 2. The original game only displays the players balance if it changed, + which it does not when the player chickens out and bets zero. + It also doesn't display the balance when it becomes zero because it has + a more appropriate message: Sorry, You Lose. + 3. To pick two cards to show, the original BASIC implementation has a + bug that could cause a race condition if the RND function never chose + a lower number first and higher number second. It loops infinitely + re-choosing random numbers until the condition is met of the first + one being lower. The logic is changed a bit here so that the first + card picked is anything but an ACE, the highest possible card, + and then the second card is between the just picked first card upto + and including the ACE. + 4. Random.nextInt(origin, bound) was added in JDK17, and allows to + directly pick a range for a random integer to be generated. The second + parameter is exclusive of the range and thus why they are stated with + +1's to the face card. + 5. The original BASIC implementation has a bug that allows negative value + bets. Since you can't bet MORE cash than you have you can always bet + less including a very, very large negative value. You would do this when + the chances of winning are slim or zero since losing a hand SUBTRACTS + your bet from your cash; subtracting a negative number actually ADDS + to your cash, potentially making you an instant billionaire. + This loophole is now closed. + 6. The subtle behavior of the BASIC PRINT command causes a space to be + printed before all positive numbers as well as a trailing space. Any + place a non-face card or the players balance is printed has extra space + to mimic this behavior. + 7. Errors on input were probably specific to the interpreter. This program + tries to match the Vintage Basic interpreter's error messages. The final + input.nextLine() command exists to clear the blockage of whatever + non-number input was entered. But even that could fail if the user + types Ctrl-D (windows Ctrl-Z), signifying an EOF (end of file) and thus + the closing of STDIN channel. The original program on an EOF signal prints + "END OF INPUT IN LINE 660" and thus we cover it roughly the same way. + All of this is necessary to avoid a messy stack trace from being + printed as the program crashes. + 9. The original game only accepted a full upper case "YES" to continue + playing if bankrupted. This program is more lenient and will accept + any input that starts with the letter 'y', uppercase or not. + 10. The original game prints an extra blank line if the card is an ACE. There + is seemingly no rationale for this. + 11. Modern java best practices are edging toward a more functional paradigm + and as such, mutating state is discouraged. All other variables besides + the cashOnHand are final and initialized only once. + 12. Refactoring of the concept of a card is done with a record. Records were + introduced in JDK14. Card functionality is encapsulated in this example + of a record. An enum could be a better alternative since there are + technically only 13 cards possible. + 13. Switch expressions were introduced as far back as JDK12 but continue to + be refined for clarity, exhaustiveness. As of JDK17 pattern matching + for switch expressions can be accessed by enabling preview features. + */ +} From 513892322e9eef7888f65196b07b38f82a1299bd Mon Sep 17 00:00:00 2001 From: Joseph Nellis Date: Sun, 9 Jan 2022 01:32:41 -0800 Subject: [PATCH 676/749] Update HOW_TO_RUN_THE_GAMES.md Add notice that you really don't need to compile single java files anymore. --- HOW_TO_RUN_THE_GAMES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HOW_TO_RUN_THE_GAMES.md b/HOW_TO_RUN_THE_GAMES.md index 44d82e98..6df23205 100644 --- a/HOW_TO_RUN_THE_GAMES.md +++ b/HOW_TO_RUN_THE_GAMES.md @@ -32,6 +32,8 @@ To run from the command line, you will need a Java SDK (eg. [Oracle JDK](https:/ * eg. `javac AceyDuceyGame.java` 1. Run the compiled program with `java`: * eg. `java AceyDuceyGame` + +or if you are **using JDK11 or later** you can now execute a self contained java file that has a main method directly with `java .java`. ## javascript From 5bb1bb5c384a8ac27519570bd2d5e68cc0343472 Mon Sep 17 00:00:00 2001 From: Ahmad Masykur Date: Sun, 9 Jan 2022 16:43:31 +0700 Subject: [PATCH 677/749] Add tictactoe1 in C# --- 89_Tic-Tac-Toe/csharp/tictactoe1/Program.cs | 75 +++++++++++++++++++ .../csharp/tictactoe1/tictactoe1.csproj | 10 +++ 2 files changed, 85 insertions(+) create mode 100644 89_Tic-Tac-Toe/csharp/tictactoe1/Program.cs create mode 100644 89_Tic-Tac-Toe/csharp/tictactoe1/tictactoe1.csproj diff --git a/89_Tic-Tac-Toe/csharp/tictactoe1/Program.cs b/89_Tic-Tac-Toe/csharp/tictactoe1/Program.cs new file mode 100644 index 00000000..58f7d36f --- /dev/null +++ b/89_Tic-Tac-Toe/csharp/tictactoe1/Program.cs @@ -0,0 +1,75 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); +// Print text on the screen with 30 spaces before text +Console.WriteLine("TIC TAC TOE".PadLeft(30)); +// Print text on screen with 15 spaces before text +Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".PadLeft(15)); +// Print three blank lines on screen +Console.WriteLine("\n\n\n"); +// THIS PROGRAM PLAYS TIC TAC TOE +// THE MACHINE GOES FIRST +Console.WriteLine("THE GAME BOARD IS NUMBERED:\n"); +Console.WriteLine("1 2 3"); +Console.WriteLine("8 9 4"); +Console.WriteLine("7 6 5"); + +// Main program +while(true) { + int a, b, c, d, e; + int p, q, r, s; + a = 9; + Console.WriteLine("\n\n"); + computerMoves(a); + p = readYourMove(); + b = move(p + 1); + computerMoves(b); + q = readYourMove(); + if (q == move(b + 4)) { + c = move(b + 2); + computerMoves(c); + r = readYourMove(); + if (r == move(c + 4)) { + if (p % 2 != 0) { + d = move(c + 3); + computerMoves(d); + s = readYourMove(); + if (s != move(d + 4)) { + e = move(d + 4); + computerMoves(e); + } + e = move(d + 6); + computerMoves(e); + Console.WriteLine("THE GAME IS A DRAW."); + } else { + d = move(c + 7); + computerMoves(d); + Console.WriteLine("AND WINS ********"); + } + } else { + d = move(c + 4); + computerMoves(d); + Console.WriteLine("AND WINS ********"); + } + } else { + c = move(b + 4); + computerMoves(c); + Console.WriteLine("AND WINS ********"); + } +} + +void computerMoves(int move) { + Console.WriteLine("COMPUTER MOVES " + move); +} +int readYourMove() { + while(true) { + Console.Write("YOUR MOVE?"); + string input = Console.ReadLine(); + if (int.TryParse(input, out int number)) { + return number; + } + } +} + +int move(int number) { + return number - 8 * (int)((number - 1) / 8); +} diff --git a/89_Tic-Tac-Toe/csharp/tictactoe1/tictactoe1.csproj b/89_Tic-Tac-Toe/csharp/tictactoe1/tictactoe1.csproj new file mode 100644 index 00000000..74abf5c9 --- /dev/null +++ b/89_Tic-Tac-Toe/csharp/tictactoe1/tictactoe1.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + From b492671bf038d204abb3218e8a2579523b2ccdec Mon Sep 17 00:00:00 2001 From: Tom Wyant Date: Sun, 9 Jan 2022 08:59:40 -0500 Subject: [PATCH 678/749] Revise the documentation for 80_Slots/perl Add instructions on how to restore the BASIC behavior to 80_Slots/perl/slots.pl Add the entire description section of the Perl documentation (including the change I made because I thought the original was a bug, and how to restore the original behavior) to 80_Slots/perl/README.md --- 80_Slots/perl/README.md | 20 ++++++++++++++++++++ 80_Slots/perl/slots.pl | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/80_Slots/perl/README.md b/80_Slots/perl/README.md index e69c8b81..3a14d6cf 100644 --- a/80_Slots/perl/README.md +++ b/80_Slots/perl/README.md @@ -1,3 +1,23 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) Conversion to [Perl](https://www.perl.org/) + +This Perl script is a port of slots, which is the 80th entry in Basic +Computer Games. + +I know nothing about slot machines, and my research into them says to me +that the payout tables can be fairly arbitrary. But I have taken the +liberty of deeming the BASIC program's refusal to pay on LEMON CHERRY +LEMON a bug, and made that case a double. + +My justification for this is that at the point where the BASIC has +detected the double in the first and third reels it has already detected +that there is no double in the first and second reels. After the check +for a bar (and therefore a double bar) fails it goes back and checks for +a double on the second and third reels. But we know this check will +fail, since the check for a double on the first and second reels failed. +So if a loss was intended at this point, why not just call it a loss? + +To restore the original behavior, comment out the entire line commented +'# Bug fix?' (about line 75) and uncomment the line with the trailing +comment '# Bug?' (about line 83). diff --git a/80_Slots/perl/slots.pl b/80_Slots/perl/slots.pl index b5c1ee39..b6749606 100755 --- a/80_Slots/perl/slots.pl +++ b/80_Slots/perl/slots.pl @@ -72,7 +72,7 @@ while ( 1 ) { # Iterate indefinitely } } elsif ( $reel_x == $reel_z ) { if ( $reel_z ) { - $winnings += double( $bet ); + $winnings += double( $bet ); # Bug fix? # NOTE that the below code is what is actually implemented # in the basic, but it is implemented strangely enough (a # GOTO a line that contains a test that, if I understand the @@ -80,7 +80,7 @@ while ( 1 ) { # Iterate indefinitely # I know nothing about slot machines, but research suggests # the payoff table is fairly arbitrary. The code above makes # code above makes the game orthogonal. - # $winnings += you_lost( $bet ); + # $winnings += you_lost( $bet ); # Bug? } else { $winnings += double_bar( $bet ); } @@ -215,6 +215,10 @@ a double on the second and third reels. But we know this check will fail, since the check for a double on the first and second reels failed. So if a loss was intended at this point, why not just call it a loss? +To restore the original behavior, comment out the entire line commented +C<'# Bug fix?'> (about line 75) and uncomment the line with the trailing +comment C<'# Bug?'> (about line 83). + =head1 PORTED BY Thomas R. Wyant, III F From d0c124a31257fef31d319ed33f166e8f4c32e87b Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sat, 8 Jan 2022 20:11:47 +0000 Subject: [PATCH 679/749] Initial port Game works, but AI behaves differently to the original. Need to try and remove the globals. --- 04_Awari/ruby/README.md | 2 +- 04_Awari/ruby/awari.rb | 286 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 04_Awari/ruby/awari.rb diff --git a/04_Awari/ruby/README.md b/04_Awari/ruby/README.md index fb32811e..9c8c96bf 100644 --- a/04_Awari/ruby/README.md +++ b/04_Awari/ruby/README.md @@ -1,3 +1,3 @@ Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) -Conversion to [Ruby](https://www.ruby-lang.org/en/) +Conversion to [Ruby](https://www.ruby-lang.org/en/) by [Alex Scown](https://github.com/TheScown) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb new file mode 100644 index 00000000..aaf29632 --- /dev/null +++ b/04_Awari/ruby/awari.rb @@ -0,0 +1,286 @@ +require 'strscan' + +def print_beans(beans) + puts + + # Print computer beans + print " " + beans[7..12].reverse.each {|bean_count| print_bean(bean_count)} + puts + + # Print home beans + print_bean(beans[13]) + print ' ' + print_number(beans[6]) # This is not print_bean in line with the original version + puts + + # Print player beans + print " " + beans[0..5].each {|bean_count| print_bean(bean_count)} + puts + + puts +end + +def print_bean(bean_count) + print ' ' if bean_count < 10 + print_number(bean_count) +end + +def print_number(n) + # PRINT adds padding after a number and before a positive number + print ' ' if n >= 0 + print n.to_s + print ' ' +end + +def get_move(prompt, beans) + move = get_integer_input(prompt) + + while move < 1 || move > 6 || beans[move - 1] == 0 + puts "ILLEGAL MOVE" + move = get_integer_input("AGAIN") + end + + move - 1 +end + +def get_integer_input(prompt) + integer_value = nil + + input_values = input(prompt) + + while integer_value.nil? + print '!EXTRA INPUT IGNORED' if (input_values.size > 1) + + value = input_values.first + + begin + integer_value = Integer(value) + rescue + puts '!NUMBER EXPECTED - RETRY INPUT LINE' + input_values = input('') + end + end + + integer_value +end + +def input(prompt) + prompt_suffix = '? ' + print "#{prompt}#{prompt_suffix}" + + input = gets.chomp.strip + scanner = StringScanner.new(input) + input_values = [] + + until scanner.eos? + scanner.scan(/\s+/) + + if scanner.check(/"/) + scanner.scan(/"/) + next_string = scanner.scan_until(/"/) + + if next_string + # Remove the trailing close quote + next_string.chomp!('"') + else + # No close quote – Vintage Basic crashes in this case + raise ArgumentError('Unmatched quotes in input') + end + elsif scanner.exist?(/,/) + next_string = scanner.scan_until(/,/).chomp(',') + else + next_string = scanner.scan_until(/\s+|$/).rstrip + end + + input_values << next_string + end + + input_values << '' if input_values.empty? + + input_values +end + + +def distribute_beans(beans, start_pit, home_pit) + beans_to_distribute = beans[start_pit] + beans[start_pit] = 0 + + current_pit = start_pit + + (0...beans_to_distribute).each do + current_pit = (current_pit + 1) % beans.size + beans[current_pit] += 1 + end + + # If the last pit was empty before we put a bean in it (and it's not a scoring pit), add beans to score + if beans[current_pit] == 1 && current_pit != 6 && current_pit != 13 && beans[12 - current_pit] != 0 + beans[home_pit] = beans[home_pit] + beans[12 - current_pit] + 1 + beans[current_pit] = 0 + beans[12 - current_pit] = 0 + end + + current_pit +end + +def update_internals(beans) + $k = $k - 7 if $k > 6 + $c = $c + 1 + + $f[$n] = $f[$n] * 6 + $k if $c < 9 + + unless beans[0...6].find { |b| b != 0 } && beans[7...13].find { |b| b != 0 } + $game_over = true + end +end + +# @param [Array] beans +# @param [Integer] move +# @param [Integer] home_pit +def perform_move(beans, move, home_pit) + last_pit = distribute_beans(beans, move, home_pit) + + update_internals(beans) + + last_pit +end + +def end_game(beans) + puts + puts "GAME OVER" + + difference = beans[6] - beans[13] + + if difference < 0 + puts "I WIN BY #{-difference} POINTS" + + return + end + + $n += 1 + + puts "YOU WIN BY #{difference} POINTS" if difference > 0 + puts "DRAWN GAME" if difference == 0 +end + +# @param [Array] beans +def get_computer_move(beans) + d = -99 + home_pit = 13 + beans_copy = beans.dup + + move_to_do = 0 + + (7..12).each do |move_under_test| + if beans[move_under_test] == 0 + next + end + + max_score = 0 + + distribute_beans(beans_copy, move_under_test, home_pit) + + (0...6).each do |i| + next if beans_copy[i] == 0 + + l = beans_copy[i] + i + r = l / 14 + l_mod_14 = l % 14 + + r = beans_copy[12 - l_mod_14] + r if beans_copy[l_mod_14] == 0 && l_mod_14 != 6 && l_mod_14 != 13 + + max_score = r if r > max_score + end + + final_score = beans_copy[13] - beans_copy[6] - max_score + + if $c <=8 + $k = move_under_test + $k = $k - 7 if $k > 6 + end + + (1...$n).each do |i| + final_score = final_score - 2 if $f[$n] * 6 + $k == (($f[i]/6 ** (7-$c)) + 0.1).floor + end + + if final_score >= d + move_to_do = move_under_test + d = final_score + end + end + + last_pit = perform_move(beans, move_to_do, home_pit) + + [move_to_do, last_pit] +end + +puts 'AWARI'.center(80) +puts 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'.center(80) + +# Initialise stable variables +$f = Array.new(50) +$n = 0 + +# APPLICATION LOOP +:game +while true + print "\n", "\n" + beans = Array.new(13, 3) + beans[6] = 0 + beans[13] = 0 + + $f[$n] = 0 + $game_over = false + $c = 0 + + until $game_over + print_beans(beans) + + move = get_move("YOUR MOVE", beans) + home_pit = 6 + computer_home_pit = 13 + $k = move + + last_pit = perform_move(beans, move, home_pit) + + print_beans(beans) + + if $game_over + end_game(beans) + next :game + end + + if home_pit == last_pit + second_move = get_move("AGAIN", beans) + $k = second_move + + perform_move(beans, second_move, home_pit) + + print_beans(beans) + + if $game_over + end_game(beans) + next :game + end + end + + computer_move, computer_last_pit = get_computer_move(beans) + print "MY MOVE IS #{computer_move - 6}" + + if $game_over + end_game(beans) + next :game + end + + if computer_last_pit == computer_home_pit + second_computer_move, _ = get_computer_move(beans) + print ",#{second_computer_move - 6}" + + if $game_over + end_game(beans) + next :game + end + end + end +end From 7239ca244ef590a1a6c4d28b143ca9c4f764e401 Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sun, 9 Jan 2022 12:41:49 +0000 Subject: [PATCH 680/749] Fix AI The issue was not resetting the clone array for every test move. Clarify some variable names. Shout out to Flavio Poletti for the comments on the Perl translation. --- 04_Awari/ruby/awari.rb | 56 ++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb index aaf29632..fa149d5f 100644 --- a/04_Awari/ruby/awari.rb +++ b/04_Awari/ruby/awari.rb @@ -125,7 +125,7 @@ def distribute_beans(beans, start_pit, home_pit) end def update_internals(beans) - $k = $k - 7 if $k > 6 + $k = $k % 7 $c = $c + 1 $f[$n] = $f[$n] * 6 + $k if $c < 9 @@ -168,51 +168,65 @@ end def get_computer_move(beans) d = -99 home_pit = 13 - beans_copy = beans.dup - move_to_do = 0 + chosen_move = 7 - (7..12).each do |move_under_test| - if beans[move_under_test] == 0 - next - end + # Test all possible moves + (7...13).each do |move_under_test| + # Create a copy of the beans to test against + beans_copy = beans.dup - max_score = 0 + # If the move is not legal, skip it + next if beans[move_under_test] == 0 + # Determine the best response the player may make to this move + player_max_score = 0 + + # Make the move under test against the copy distribute_beans(beans_copy, move_under_test, home_pit) + # Test every player response (0...6).each do |i| + # Skip the move if it would be illegal next if beans_copy[i] == 0 - l = beans_copy[i] + i - r = l / 14 - l_mod_14 = l % 14 + # Determine the last + landing_with_overflow = beans_copy[i] + i + # If landing > 13 the player has put a bean in both home pits + player_move_score = (landing_with_overflow > 14) ? 1 : 0 + # Find the actual pit + landing = landing_with_overflow % 14 - r = beans_copy[12 - l_mod_14] + r if beans_copy[l_mod_14] == 0 && l_mod_14 != 6 && l_mod_14 != 13 + # If the landing pit is empty, the player will steal beans + if beans_copy[landing] == 0 && landing != 6 && landing != 13 + player_move_score = beans_copy[12 - landing] + player_move_score + end - max_score = r if r > max_score + # Update the max score if this move is the best player move + player_max_score = player_move_score if player_move_score > player_max_score end - final_score = beans_copy[13] - beans_copy[6] - max_score + # Final score for move is computer score, minus the player's score and any player gains from their best move + final_score = beans_copy[13] - beans_copy[6] - player_max_score if $c <=8 - $k = move_under_test - $k = $k - 7 if $k > 6 + $k = move_under_test % 7 end - (1...$n).each do |i| - final_score = final_score - 2 if $f[$n] * 6 + $k == (($f[i]/6 ** (7-$c)) + 0.1).floor + (0...$n).each do |i| + final_score = final_score - 2 if $f[$n] * 6 + $k == ((Float($f[i])/6 ** (7-$c)) + 0.1).floor end + # Choose the move if it is the best move found so far if final_score >= d - move_to_do = move_under_test + chosen_move = move_under_test d = final_score end end - last_pit = perform_move(beans, move_to_do, home_pit) + last_pit = perform_move(beans, chosen_move, home_pit) - [move_to_do, last_pit] + [chosen_move, last_pit] end puts 'AWARI'.center(80) From 2fa142a246be226b4779e93fef5e7d8e9803f075 Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sun, 9 Jan 2022 12:51:48 +0000 Subject: [PATCH 681/749] Remove k global --- 04_Awari/ruby/awari.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb index fa149d5f..466f1c71 100644 --- a/04_Awari/ruby/awari.rb +++ b/04_Awari/ruby/awari.rb @@ -124,11 +124,11 @@ def distribute_beans(beans, start_pit, home_pit) current_pit end -def update_internals(beans) - $k = $k % 7 +def update_internals(beans, current_move) + k = current_move % 7 $c = $c + 1 - $f[$n] = $f[$n] * 6 + $k if $c < 9 + $f[$n] = $f[$n] * 6 + k if $c < 9 unless beans[0...6].find { |b| b != 0 } && beans[7...13].find { |b| b != 0 } $game_over = true @@ -141,7 +141,7 @@ end def perform_move(beans, move, home_pit) last_pit = distribute_beans(beans, move, home_pit) - update_internals(beans) + update_internals(beans, move) last_pit end @@ -210,11 +210,11 @@ def get_computer_move(beans) final_score = beans_copy[13] - beans_copy[6] - player_max_score if $c <=8 - $k = move_under_test % 7 - end + k = move_under_test % 7 - (0...$n).each do |i| - final_score = final_score - 2 if $f[$n] * 6 + $k == ((Float($f[i])/6 ** (7-$c)) + 0.1).floor + (0...$n).each do |i| + final_score = final_score - 2 if $f[$n] * 6 + k == ((Float($f[i])/6 ** (7-$c)) + 0.1).floor + end end # Choose the move if it is the best move found so far @@ -254,7 +254,6 @@ while true move = get_move("YOUR MOVE", beans) home_pit = 6 computer_home_pit = 13 - $k = move last_pit = perform_move(beans, move, home_pit) @@ -267,7 +266,6 @@ while true if home_pit == last_pit second_move = get_move("AGAIN", beans) - $k = second_move perform_move(beans, second_move, home_pit) From a0fdf42166232e7825cbfd7dcbbb6e496f94b084 Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sun, 9 Jan 2022 13:19:18 +0000 Subject: [PATCH 682/749] Initial conversion to class --- 04_Awari/ruby/awari.rb | 150 ++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 68 deletions(-) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb index 466f1c71..cd57132c 100644 --- a/04_Awari/ruby/awari.rb +++ b/04_Awari/ruby/awari.rb @@ -5,7 +5,7 @@ def print_beans(beans) # Print computer beans print " " - beans[7..12].reverse.each {|bean_count| print_bean(bean_count)} + beans[7..12].reverse.each { |bean_count| print_bean(bean_count) } puts # Print home beans @@ -16,7 +16,7 @@ def print_beans(beans) # Print player beans print " " - beans[0..5].each {|bean_count| print_bean(bean_count)} + beans[0..5].each { |bean_count| print_bean(bean_count) } puts puts @@ -102,7 +102,6 @@ def input(prompt) input_values end - def distribute_beans(beans, start_pit, home_pit) beans_to_distribute = beans[start_pit] beans[start_pit] = 0 @@ -124,15 +123,11 @@ def distribute_beans(beans, start_pit, home_pit) current_pit end -def update_internals(beans, current_move) +def update_history(current_move) k = current_move % 7 $c = $c + 1 - $f[$n] = $f[$n] * 6 + k if $c < 9 - - unless beans[0...6].find { |b| b != 0 } && beans[7...13].find { |b| b != 0 } - $game_over = true - end + $history[$non_win_count] = $history[$non_win_count] * 6 + k if $c < 9 end # @param [Array] beans @@ -141,11 +136,12 @@ end def perform_move(beans, move, home_pit) last_pit = distribute_beans(beans, move, home_pit) - update_internals(beans, move) + update_history(move) last_pit end +# @return [Boolean] True if the computer did not win def end_game(beans) puts puts "GAME OVER" @@ -158,10 +154,12 @@ def end_game(beans) return end - $n += 1 + $non_win_count += 1 puts "YOU WIN BY #{difference} POINTS" if difference > 0 puts "DRAWN GAME" if difference == 0 + + difference >= 0 end # @param [Array] beans @@ -209,11 +207,11 @@ def get_computer_move(beans) # Final score for move is computer score, minus the player's score and any player gains from their best move final_score = beans_copy[13] - beans_copy[6] - player_max_score - if $c <=8 + if $c < 9 k = move_under_test % 7 - (0...$n).each do |i| - final_score = final_score - 2 if $f[$n] * 6 + k == ((Float($f[i])/6 ** (7-$c)) + 0.1).floor + (0...$non_win_count).each do |i| + final_score = final_score - 2 if $history[$non_win_count] * 6 + k == ((Float($history[i]) / 6 ** (7 - $c)) + 0.1).floor end end @@ -229,70 +227,86 @@ def get_computer_move(beans) [chosen_move, last_pit] end +class Game + def initialize(history, non_win_count) + @beans = Array.new(13, 3) + @beans[6] = 0 + @beans[13] = 0 + + @turn_counter = 0 + + @history = history + @non_win_count = non_win_count + end + + def game_over + @beans[0...6].all? { |b| b == 0 } || @beans[7...13].all? { |b| b == 0 } + end + + def play + until game_over + print_beans(@beans) + + move = get_move("YOUR MOVE", @beans) + home_pit = 6 + computer_home_pit = 13 + + last_pit = perform_move(@beans, move, home_pit) + + print_beans(@beans) + + if game_over + return end_game(@beans) + end + + if home_pit == last_pit + second_move = get_move("AGAIN", @beans) + + perform_move(@beans, second_move, home_pit) + + print_beans(@beans) + + if game_over + return end_game(@beans) + end + end + + computer_move, computer_last_pit = get_computer_move(@beans) + print "MY MOVE IS #{computer_move - 6}" + + if game_over + return end_game(@beans) + end + + if computer_last_pit == computer_home_pit + second_computer_move, _ = get_computer_move(@beans) + print ",#{second_computer_move - 6}" + + if game_over + return end_game(@beans) + end + end + end + end + +end + puts 'AWARI'.center(80) puts 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'.center(80) # Initialise stable variables -$f = Array.new(50) -$n = 0 +$history = Array.new(50) +$non_win_count = 0 # APPLICATION LOOP -:game while true print "\n", "\n" - beans = Array.new(13, 3) - beans[6] = 0 - beans[13] = 0 - $f[$n] = 0 - $game_over = false + $history[$non_win_count] = 0 $c = 0 - until $game_over - print_beans(beans) + game = Game.new($history, $non_win_count) - move = get_move("YOUR MOVE", beans) - home_pit = 6 - computer_home_pit = 13 - - last_pit = perform_move(beans, move, home_pit) - - print_beans(beans) - - if $game_over - end_game(beans) - next :game - end - - if home_pit == last_pit - second_move = get_move("AGAIN", beans) - - perform_move(beans, second_move, home_pit) - - print_beans(beans) - - if $game_over - end_game(beans) - next :game - end - end - - computer_move, computer_last_pit = get_computer_move(beans) - print "MY MOVE IS #{computer_move - 6}" - - if $game_over - end_game(beans) - next :game - end - - if computer_last_pit == computer_home_pit - second_computer_move, _ = get_computer_move(beans) - print ",#{second_computer_move - 6}" - - if $game_over - end_game(beans) - next :game - end - end - end + computer_didnt_win = game.play + $non_win_count += 1 if computer_didnt_win end From 5195ef74c673094e2290ea38f3f77b5af7102865 Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sun, 9 Jan 2022 13:55:27 +0000 Subject: [PATCH 683/749] Move remaining functions into class --- 04_Awari/ruby/awari.rb | 453 ++++++++++++++++++++--------------------- 1 file changed, 223 insertions(+), 230 deletions(-) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb index cd57132c..a9864dc7 100644 --- a/04_Awari/ruby/awari.rb +++ b/04_Awari/ruby/awari.rb @@ -1,32 +1,5 @@ require 'strscan' -def print_beans(beans) - puts - - # Print computer beans - print " " - beans[7..12].reverse.each { |bean_count| print_bean(bean_count) } - puts - - # Print home beans - print_bean(beans[13]) - print ' ' - print_number(beans[6]) # This is not print_bean in line with the original version - puts - - # Print player beans - print " " - beans[0..5].each { |bean_count| print_bean(bean_count) } - puts - - puts -end - -def print_bean(bean_count) - print ' ' if bean_count < 10 - print_number(bean_count) -end - def print_number(n) # PRINT adds padding after a number and before a positive number print ' ' if n >= 0 @@ -34,38 +7,6 @@ def print_number(n) print ' ' end -def get_move(prompt, beans) - move = get_integer_input(prompt) - - while move < 1 || move > 6 || beans[move - 1] == 0 - puts "ILLEGAL MOVE" - move = get_integer_input("AGAIN") - end - - move - 1 -end - -def get_integer_input(prompt) - integer_value = nil - - input_values = input(prompt) - - while integer_value.nil? - print '!EXTRA INPUT IGNORED' if (input_values.size > 1) - - value = input_values.first - - begin - integer_value = Integer(value) - rescue - puts '!NUMBER EXPECTED - RETRY INPUT LINE' - input_values = input('') - end - end - - integer_value -end - def input(prompt) prompt_suffix = '? ' print "#{prompt}#{prompt_suffix}" @@ -102,131 +43,6 @@ def input(prompt) input_values end -def distribute_beans(beans, start_pit, home_pit) - beans_to_distribute = beans[start_pit] - beans[start_pit] = 0 - - current_pit = start_pit - - (0...beans_to_distribute).each do - current_pit = (current_pit + 1) % beans.size - beans[current_pit] += 1 - end - - # If the last pit was empty before we put a bean in it (and it's not a scoring pit), add beans to score - if beans[current_pit] == 1 && current_pit != 6 && current_pit != 13 && beans[12 - current_pit] != 0 - beans[home_pit] = beans[home_pit] + beans[12 - current_pit] + 1 - beans[current_pit] = 0 - beans[12 - current_pit] = 0 - end - - current_pit -end - -def update_history(current_move) - k = current_move % 7 - $c = $c + 1 - - $history[$non_win_count] = $history[$non_win_count] * 6 + k if $c < 9 -end - -# @param [Array] beans -# @param [Integer] move -# @param [Integer] home_pit -def perform_move(beans, move, home_pit) - last_pit = distribute_beans(beans, move, home_pit) - - update_history(move) - - last_pit -end - -# @return [Boolean] True if the computer did not win -def end_game(beans) - puts - puts "GAME OVER" - - difference = beans[6] - beans[13] - - if difference < 0 - puts "I WIN BY #{-difference} POINTS" - - return - end - - $non_win_count += 1 - - puts "YOU WIN BY #{difference} POINTS" if difference > 0 - puts "DRAWN GAME" if difference == 0 - - difference >= 0 -end - -# @param [Array] beans -def get_computer_move(beans) - d = -99 - home_pit = 13 - - chosen_move = 7 - - # Test all possible moves - (7...13).each do |move_under_test| - # Create a copy of the beans to test against - beans_copy = beans.dup - - # If the move is not legal, skip it - next if beans[move_under_test] == 0 - - # Determine the best response the player may make to this move - player_max_score = 0 - - # Make the move under test against the copy - distribute_beans(beans_copy, move_under_test, home_pit) - - # Test every player response - (0...6).each do |i| - # Skip the move if it would be illegal - next if beans_copy[i] == 0 - - # Determine the last - landing_with_overflow = beans_copy[i] + i - # If landing > 13 the player has put a bean in both home pits - player_move_score = (landing_with_overflow > 14) ? 1 : 0 - # Find the actual pit - landing = landing_with_overflow % 14 - - # If the landing pit is empty, the player will steal beans - if beans_copy[landing] == 0 && landing != 6 && landing != 13 - player_move_score = beans_copy[12 - landing] + player_move_score - end - - # Update the max score if this move is the best player move - player_max_score = player_move_score if player_move_score > player_max_score - end - - # Final score for move is computer score, minus the player's score and any player gains from their best move - final_score = beans_copy[13] - beans_copy[6] - player_max_score - - if $c < 9 - k = move_under_test % 7 - - (0...$non_win_count).each do |i| - final_score = final_score - 2 if $history[$non_win_count] * 6 + k == ((Float($history[i]) / 6 ** (7 - $c)) + 0.1).floor - end - end - - # Choose the move if it is the best move found so far - if final_score >= d - chosen_move = move_under_test - d = final_score - end - end - - last_pit = perform_move(beans, chosen_move, home_pit) - - [chosen_move, last_pit] -end - class Game def initialize(history, non_win_count) @beans = Array.new(13, 3) @@ -239,74 +55,251 @@ class Game @non_win_count = non_win_count end + def play + while true + print_beans + + move = get_move("YOUR MOVE") + home_pit = 6 + computer_home_pit = 13 + + last_pit = perform_move(move, home_pit) + + print_beans + + break if game_over + + if home_pit == last_pit + second_move = get_move("AGAIN") + + perform_move(second_move, home_pit) + + print_beans + + break if game_over + end + + computer_move, computer_last_pit = get_computer_move + print "MY MOVE IS #{computer_move - 6}" + + break if game_over + + if computer_last_pit == computer_home_pit + second_computer_move, _ = get_computer_move + print ",#{second_computer_move - 6}" + + break if game_over + end + end + + end_game + end + + private + def game_over @beans[0...6].all? { |b| b == 0 } || @beans[7...13].all? { |b| b == 0 } end - def play - until game_over - print_beans(@beans) + # @return [Boolean] True if the computer did not win + def end_game + puts + puts "GAME OVER" - move = get_move("YOUR MOVE", @beans) - home_pit = 6 - computer_home_pit = 13 + difference = @beans[6] - @beans[13] - last_pit = perform_move(@beans, move, home_pit) + if difference < 0 + puts "I WIN BY #{-difference} POINTS" - print_beans(@beans) - - if game_over - return end_game(@beans) - end - - if home_pit == last_pit - second_move = get_move("AGAIN", @beans) - - perform_move(@beans, second_move, home_pit) - - print_beans(@beans) - - if game_over - return end_game(@beans) - end - end - - computer_move, computer_last_pit = get_computer_move(@beans) - print "MY MOVE IS #{computer_move - 6}" - - if game_over - return end_game(@beans) - end - - if computer_last_pit == computer_home_pit - second_computer_move, _ = get_computer_move(@beans) - print ",#{second_computer_move - 6}" - - if game_over - return end_game(@beans) - end - end + return end + + puts "YOU WIN BY #{difference} POINTS" if difference > 0 + puts "DRAWN GAME" if difference == 0 + + difference >= 0 end + # @param [Integer] move + # @param [Integer] home_pit + def perform_move(move, home_pit) + last_pit = distribute_beans(move, home_pit) + + update_history(move) + + last_pit + end + + def update_history(current_move) + k = current_move % 7 + @turn_counter += 1 + + # Add the move to the history + @history[@non_win_count] = @history[@non_win_count] * 6 + k if @turn_counter < 9 + end + + def print_beans + puts + + # Print computer beans + print ' ' * 3 + @beans[7...13].reverse.each { |bean_count| print_bean(bean_count) } + puts + + # Print home beans + print_bean(@beans[13]) + print ' ' * 23 + print_number(@beans[6]) # This is not print_bean in line with the original version + puts + + # Print player beans + print ' ' * 3 + @beans[0...6].each { |bean_count| print_bean(bean_count) } + puts + + puts + end + + def get_move(prompt) + move = get_integer_input(prompt) + + while move < 1 || move > 6 || @beans[move - 1] == 0 + puts "ILLEGAL MOVE" + move = get_integer_input("AGAIN") + end + + move - 1 + end + + def distribute_beans(start_pit, home_pit, beans = @beans) + beans_to_distribute = beans[start_pit] + beans[start_pit] = 0 + + current_pit = start_pit + + (0...beans_to_distribute).each do + current_pit = (current_pit + 1) % beans.size + beans[current_pit] += 1 + end + + # If the last pit was empty before we put a bean in it (and it's not a scoring pit), add beans to score + if beans[current_pit] == 1 && current_pit != 6 && current_pit != 13 && beans[12 - current_pit] != 0 + beans[home_pit] = beans[home_pit] + beans[12 - current_pit] + 1 + beans[current_pit] = 0 + beans[12 - current_pit] = 0 + end + + current_pit + end + + def print_bean(bean_count) + print ' ' if bean_count < 10 + print_number(bean_count) + end + + def get_integer_input(prompt) + integer_value = nil + + input_values = input(prompt) + + while integer_value.nil? + print '!EXTRA INPUT IGNORED' if (input_values.size > 1) + + value = input_values.first + + begin + integer_value = Integer(value) + rescue + puts '!NUMBER EXPECTED - RETRY INPUT LINE' + input_values = input('') + end + end + + integer_value + end + + # @param [Array] beans + def get_computer_move + d = -99 + home_pit = 13 + + chosen_move = 7 + + # Test all possible moves + (7...13).each do |move_under_test| + # Create a copy of the beans to test against + beans_copy = @beans.dup + + # If the move is not legal, skip it + next if beans_copy[move_under_test] == 0 + + # Determine the best response the player may make to this move + player_max_score = 0 + + # Make the move under test against the copy + distribute_beans(move_under_test, home_pit, beans_copy) + + # Test every player response + (0...6).each do |i| + # Skip the move if it would be illegal + next if beans_copy[i] == 0 + + # Determine the last + landing_with_overflow = beans_copy[i] + i + # If landing > 13 the player has put a bean in both home pits + player_move_score = (landing_with_overflow > 14) ? 1 : 0 + # Find the actual pit + landing = landing_with_overflow % 14 + + # If the landing pit is empty, the player will steal beans + if beans_copy[landing] == 0 && landing != 6 && landing != 13 + player_move_score = beans_copy[12 - landing] + player_move_score + end + + # Update the max score if this move is the best player move + player_max_score = player_move_score if player_move_score > player_max_score + end + + # Final score for move is computer score, minus the player's score and any player gains from their best move + final_score = beans_copy[13] - beans_copy[6] - player_max_score + + if @turn_counter < 9 + k = move_under_test % 7 + + (0...@non_win_count).each do |i| + # Penalise move if it was used in a losing game + final_score = final_score - 2 if @history[@non_win_count] * 6 + k == ((Float(@history[i]) / 6 ** (7 - @turn_counter)) + 0.1).floor + end + end + + # Choose the move if it is the best move found so far + if final_score >= d + chosen_move = move_under_test + d = final_score + end + end + + last_pit = perform_move(chosen_move, home_pit) + + [chosen_move, last_pit] + end end puts 'AWARI'.center(80) puts 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'.center(80) # Initialise stable variables -$history = Array.new(50) -$non_win_count = 0 +history = Array.new(50) +non_win_count = 0 # APPLICATION LOOP while true print "\n", "\n" - $history[$non_win_count] = 0 - $c = 0 + history[non_win_count] = 0 - game = Game.new($history, $non_win_count) + game = Game.new(history, non_win_count) computer_didnt_win = game.play - $non_win_count += 1 if computer_didnt_win + non_win_count += 1 if computer_didnt_win end From 10a2f535ebed117a68e8782dfe1edd24d612529e Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sun, 9 Jan 2022 14:12:00 +0000 Subject: [PATCH 684/749] Final tidy --- 04_Awari/ruby/awari.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb index a9864dc7..65e27c25 100644 --- a/04_Awari/ruby/awari.rb +++ b/04_Awari/ruby/awari.rb @@ -1,5 +1,7 @@ require 'strscan' +# Prints a number according to Vintage Basic's PRINT statement +# @param n The number to print def print_number(n) # PRINT adds padding after a number and before a positive number print ' ' if n >= 0 @@ -7,6 +9,9 @@ def print_number(n) print ' ' end +# Mimic the INPUT statement using Vintage Basic as a reference +# @param prompt The prompt to show to the user +# @return An array of strings representing the inputted values def input(prompt) prompt_suffix = '? ' print "#{prompt}#{prompt_suffix}" @@ -55,6 +60,7 @@ class Game @non_win_count = non_win_count end + # @return [Boolean] True if the computer did not win the game def play while true print_beans @@ -218,7 +224,6 @@ class Game integer_value end - # @param [Array] beans def get_computer_move d = -99 home_pit = 13 @@ -294,7 +299,8 @@ non_win_count = 0 # APPLICATION LOOP while true - print "\n", "\n" + puts + puts history[non_win_count] = 0 From 63100a55921e863064de7fe7f7e09c848c13b29d Mon Sep 17 00:00:00 2001 From: Alex Scown Date: Sun, 9 Jan 2022 14:29:39 +0000 Subject: [PATCH 685/749] Fix unmatched quotes error --- 04_Awari/ruby/awari.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04_Awari/ruby/awari.rb b/04_Awari/ruby/awari.rb index 65e27c25..6c68a4e0 100644 --- a/04_Awari/ruby/awari.rb +++ b/04_Awari/ruby/awari.rb @@ -32,7 +32,7 @@ def input(prompt) next_string.chomp!('"') else # No close quote – Vintage Basic crashes in this case - raise ArgumentError('Unmatched quotes in input') + raise 'Unmatched quotes in input' end elsif scanner.exist?(/,/) next_string = scanner.scan_until(/,/).chomp(',') From 3dacdcc878e4c74e80c7027e60639d4760a1cae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=8C=AF=E8=80=80?= Date: Sun, 9 Jan 2022 23:51:08 +0800 Subject: [PATCH 686/749] Ignore program-independent content generated by VisualStudio --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d2115efc..c3aa9f13 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ out/ Pipfile .DS_Store +/.vs/basic-computer-games/v16 +/.vs From d2e2b920f1fced0d6d3c049e349c3b8017718a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=8C=AF=E8=80=80?= Date: Sun, 9 Jan 2022 23:54:29 +0800 Subject: [PATCH 687/749] 93_23_Matches\csharp The program is available in two versions, a "goto" version that mimics the original program and an "object-oriented" version. --- 93_23_Matches/csharp/23matches.csproj | 9 + 93_23_Matches/csharp/23matches.sln | 25 +++ 93_23_Matches/csharp/Goto.Program.cs | 129 ++++++++++++++ .../csharp/ObjectOrientedVersion.Program.cs | 161 ++++++++++++++++++ 93_23_Matches/csharp/README.md | 2 + 5 files changed, 326 insertions(+) create mode 100644 93_23_Matches/csharp/23matches.csproj create mode 100644 93_23_Matches/csharp/23matches.sln create mode 100644 93_23_Matches/csharp/Goto.Program.cs create mode 100644 93_23_Matches/csharp/ObjectOrientedVersion.Program.cs diff --git a/93_23_Matches/csharp/23matches.csproj b/93_23_Matches/csharp/23matches.csproj new file mode 100644 index 00000000..11091f71 --- /dev/null +++ b/93_23_Matches/csharp/23matches.csproj @@ -0,0 +1,9 @@ + + + + Exe + netcoreapp3.1 + _23matches + + + diff --git a/93_23_Matches/csharp/23matches.sln b/93_23_Matches/csharp/23matches.sln new file mode 100644 index 00000000..78fce16e --- /dev/null +++ b/93_23_Matches/csharp/23matches.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32002.261 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "23matches", "23matches.csproj", "{9DBE7354-0749-4750-9224-5F9F95C64905}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9DBE7354-0749-4750-9224-5F9F95C64905}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DBE7354-0749-4750-9224-5F9F95C64905}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DBE7354-0749-4750-9224-5F9F95C64905}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DBE7354-0749-4750-9224-5F9F95C64905}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0A87AE2F-68AC-4354-9C8D-578209D41174} + EndGlobalSection +EndGlobal diff --git a/93_23_Matches/csharp/Goto.Program.cs b/93_23_Matches/csharp/Goto.Program.cs new file mode 100644 index 00000000..e23be8a4 --- /dev/null +++ b/93_23_Matches/csharp/Goto.Program.cs @@ -0,0 +1,129 @@ +using System; +using System.Threading; + +namespace _23matches +{ + class Program + { + ///

+
aceyducey_literal.d
+
A largely literal transcription of the original Basic source. All unnecessary uglyness is preserved.
+
aceyducey.d
+
An idiomatic D refactoring of the original, with a focus on increasing the readability and robustness. + Memory-safety is ensured by the language, thanks to the + @safe annotation.
+
+
+
+
+
+

Super Star Trek

+

+ Originally found in + David Ahl's BASIC Computer Games (1978) +

+

+ Converted to JavaScript + in February 2021 + by Les Orchard + <me@lmorchard.com> +

+ +
+      INSTRUCTIONS FOR 'SUPER STAR TREK'
+
+1. WHEN YOU SEE \COMMAND ?\ PRINTED, ENTER ONE OF THE LEGAL
+     COMMANDS (NAV,SRS,LRS,PHA,TOR,SHE,DAM,COM, OR XXX).
+
+2. IF YOU SHOULD TYPE IN AN ILLEGAL COMMAND, YOU'LL GET A SHORT
+     LIST OF THE LEGAL COMMANDS PRINTED OUT.
+
+3. SOME COMMANDS REQUIRE YOU TO ENTER DATA (FOR EXAMPLE, THE
+     'NAV' COMMAND COMES BACK WITH 'COURSE (1-9) ?'.)  IF YOU
+     TYPE IN ILLEGAL DATA (LIKE NEGATIVE NUMBERS), THAN COMMAND
+     WILL BE ABORTED
+     THE GALAXY IS DIVIDED INTO AN 8 X 8 QUADRANT GRID,
+AND EACH QUADRANT IS FURTHER DIVIDED INTO AN 8 X 8 SECTOR GRID.
+     YOU WILL BE ASSIGNED A STARTING POINT SOMEWHERE IN THE
+GALAXY TO BEGIN A TOUR OF DUTY AS COMANDER OF THE STARSHIP
+\ENTERPRISE\; YOUR MISSION: TO SEEK AND DESTROY THE FLEET OF
+KLINGON WARWHIPS WHICH ARE MENACING THE UNITED FEDERATION OF
+PLANETS.
+
+     YOU HAVE THE FOLLOWING COMMANDS AVAILABLE TO YOU AS CAPTAIN
+OF THE STARSHIP ENTERPRISE:
+
+\NAV\ COMMAND = WARP ENGINE CONTROL --
+     COURSE IS IN A CIRCULAR NUMERICAL      4  3  2
+     VECTOR ARRANGEMENT AS SHOWN             . . .
+     INTEGER AND REAL VALUES MAY BE           ...
+     USED.  (THUS COURSE 1.5 IS HALF-     5 ---*--- 1
+     WAY BETWEEN 1 AND 2                      ...
+                                             . . .
+     VALUES MAY APPROACH 9.0, WHICH         6  7  8
+     ITSELF IS EQUIVALENT TO 1.0"         
+                                            COURSE
+     ONE WARP FACTOR IS THE SIZE OF 
+     ONE QUADTANT.  THEREFORE, TO GET
+     FROM QUADRANT 6,5 TO 5,5, YOU WOULD
+     USE COURSE 3, WARP FACTOR 1.
+
+\SRS\ COMMAND = SHORT RANGE SENSOR SCAN
+     SHOWS YOU A SCAN OF YOUR PRESENT QUADRANT.
+     SYMBOLOGY ON YOUR SENSOR SCREEN IS AS FOLLOWS:
+        <*> = YOUR STARSHIP'S POSITION
+        +K+ = KLINGON BATTLE CRUISER
+        >!< = FEDERATION STARBASE (REFUEL/REPAIR/RE-ARM HERE!)
+         *  = STAR
+     A CONDENSED 'STATUS REPORT' WILL ALSO BE PRESENTED.
+
+\LRS\ COMMAND = LONG RANGE SENSOR SCAN
+     SHOWS CONDITIONS IN SPACE FOR ONE QUADRANT ON EACH SIDE
+     OF THE ENTERPRISE (WHICH IS IN THE MIDDLE OF THE SCAN)
+     THE SCAN IS CODED IN THE FORM \###\, WHERE TH UNITS DIGIT
+     IS THE NUMBER OF STARS, THE TENS DIGIT IS THE NUMBER OF
+     STARBASES, AND THE HUNDRESDS DIGIT IS THE NUMBER OF
+     KLINGONS.
+     EXAMPLE - 207 = 2 KLINGONS, NO STARBASES, & 7 STARS.
+
+\PHA\ COMMAND = PHASER CONTROL.
+     ALLOWS YOU TO DESTROY THE KLINGON BATTLE CRUISERS BY 
+     ZAPPING THEM WITH SUITABLY LARGE UNITS OF ENERGY TO
+     DEPLETE THEIR SHIELD POWER.  (REMBER, KLINGONS HAVE
+     PHASERS TOO!)
+
+\TOR\ COMMAND = PHOTON TORPEDO CONTROL
+     TORPEDO COURSE IS THE SAME AS USED IN WARP ENGINE CONTROL
+     IF YOU HIT THE KLINGON VESSEL, HE IS DESTROYED AND
+     CANNOT FIRE BACK AT YOU.  IF YOU MISS, YOU ARE SUBJECT TO
+     HIS PHASER FIRE.  IN EITHER CASE, YOU ARE ALSO SUBJECT TO
+     THE PHASER FIRE OF ALL OTHER KLINGONS IN THE QUADRANT.
+     THE LIBRARY-COMPUTER (\COM\ COMMAND) HAS AN OPTION TO
+     COMPUTE TORPEDO TRAJECTORY FOR YOU (OPTION 2)
+
+\SHE\ COMMAND = SHIELD CONTROL
+     DEFINES THE NUMBER OF ENERGY UNITS TO BE ASSIGNED TO THE
+     SHIELDS.  ENERGY IS TAKEN FROM TOTAL SHIP'S ENERGY.  NOTE
+     THAN THE STATUS DISPLAY TOTAL ENERGY INCLUDES SHIELD ENERGY
+
+\DAM\ COMMAND = DAMMAGE CONTROL REPORT
+     GIVES THE STATE OF REPAIR OF ALL DEVICES.  WHERE A NEGATIVE
+     'STATE OF REPAIR' SHOWS THAT THE DEVICE IS TEMPORARILY
+     DAMAGED."
+
+\COM\ COMMAND = LIBRARY-COMPUTER
+     THE LIBRARY-COMPUTER CONTAINS SIX OPTIONS:
+     OPTION 0 = CUMULATIVE GALACTIC RECORD
+        THIS OPTION SHOWES COMPUTER MEMORY OF THE RESULTS OF ALL
+        PREVIOUS SHORT AND LONG RANGE SENSOR SCANS        
+     OPTION 1 = STATUS REPORT
+        THIS OPTION SHOWS THE NUMBER OF KLINGONS, STARDATES,
+        AND STARBASES REMAINING IN THE GAME.
+     OPTION 2 = PHOTON TORPEDO DATA
+        WHICH GIVES DIRECTIONS AND DISTANCE FROM THE ENTERPRISE
+        TO ALL KLINGONS IN YOUR QUADRANT
+     OPTION 3 = STARBASE NAV DATA
+        THIS OPTION GIVES DIRECTION AND DISTANCE TO ANY
+        STARBASE WITHIN YOUR QUADRANT
+     OPTION 4 = DIRECTION/DISTANCE CALCULATOR
+        THIS OPTION ALLOWS YOU TO ENTER COORDINATES FOR
+        DIRECTION/DISTANCE CALCULATIONS
+     OPTION 5 = GALACTIC /REGION NAME/ MAP
+        THIS OPTION PRINTS THE NAMES OF THE SIXTEEN MAJOR
+        GALACTIC REGIONS REFERRED TO IN THE GAME.
+    
+
+

+ * 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 RussianRoulette { + + public static final int BULLETS_IN_CHAMBER = 10; + public static final double CHANCE_OF_GETTING_SHOT = .833333d; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + INIT, + GAME_START, + FIRE_BULLET, + NEXT_VICTIM + } + + // Current game state + private GAME_STATE gameState; + + int bulletsShot; + + public RussianRoulette() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.INIT; + } + + /** + * Main game loop + */ + public void play() { + + do { + switch (gameState) { + + case INIT: + intro(); + gameState = GAME_STATE.GAME_START; + + break; + + case GAME_START: + bulletsShot = 0; + System.out.println(); + System.out.println("HERE IS A REVOLVER."); + System.out.println("TYPE '1' TO SPIN CHAMBER AND PULL TRIGGER."); + System.out.println("TYPE '2' TO GIVE UP."); + gameState = GAME_STATE.FIRE_BULLET; + break; + + case FIRE_BULLET: + + int choice = displayTextAndGetNumber("GO "); + + // Anything but selecting give up = have a shot + if (choice != 2) { + bulletsShot++; + if (Math.random() > CHANCE_OF_GETTING_SHOT) { + System.out.println(" BANG!!!!! YOU'RE DEAD!"); + System.out.println("CONDOLENCES WILL BE SENT TO YOUR RELATIVES."); + gameState = GAME_STATE.NEXT_VICTIM; + } else if (bulletsShot > BULLETS_IN_CHAMBER) { + System.out.println("YOU WIN!!!!!"); + System.out.println("LET SOMEONE ELSE BLOW HIS BRAINS OUT."); + gameState = GAME_STATE.GAME_START; + } else { + // Phew player survived this round + System.out.println("- CLICK -"); + } + } else { + // Player gave up + System.out.println(" CHICKEN!!!!!"); + gameState = GAME_STATE.NEXT_VICTIM; + + } + break; + + case NEXT_VICTIM: + System.out.println("...NEXT VICTIM..."); + gameState = GAME_STATE.GAME_START; + } + // Infinite loop - based on original basic version + } while (true); + } + + private void intro() { + System.out.println(addSpaces(28) + "RUSSIAN ROULETTE"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("THIS IS A GAME OF >>>>>>>>>>RUSSIAN ROULETTE."); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.nextLine(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + public static void main(String[] args) { + + RussianRoulette russianRoulette = new RussianRoulette(); + russianRoulette.play(); + } +} \ No newline at end of file From 0a4e66a6e7540ed74d5fdee2d452f0722d4bbc4d Mon Sep 17 00:00:00 2001 From: Todd Kaiser Date: Tue, 2 Mar 2021 19:32:02 -0700 Subject: [PATCH 189/749] Added ship placement logic without checks for existing ships. Need to add existing ship check. --- 77 Salvo/python/salvo.ipynb | 141 +++++++++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 19 deletions(-) diff --git a/77 Salvo/python/salvo.ipynb b/77 Salvo/python/salvo.ipynb index 9b2479db..d1681dfb 100644 --- a/77 Salvo/python/salvo.ipynb +++ b/77 Salvo/python/salvo.ipynb @@ -15,12 +15,8 @@ "orig_nbformat": 2, "kernelspec": { "name": "python3", - "display_name": "Python 3.7.3 64-bit ('python': venv)", - "metadata": { - "interpreter": { - "hash": "d99f099520c2505e9f745916a84fcd3ec6a6f02f993bb8e12b586a85fced6daa" - } - } + "display_name": "Python 3", + "language": "python" } }, "nbformat": 4, @@ -28,7 +24,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 225, "metadata": {}, "outputs": [], "source": [ @@ -37,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 226, "metadata": {}, "outputs": [], "source": [ @@ -54,14 +50,14 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 227, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "5 2\n" + "7 2\n" ] } ], @@ -72,25 +68,25 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 228, "metadata": {}, "outputs": [], "source": [ "def random_direction(valid_directions):\n", - " idx = random.ran range(len(valid_directions))\n", + " idx = random.randrange(len(valid_directions))\n", " return valid_directions[idx]" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 229, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "1\n" + "0\n" ] } ], @@ -100,7 +96,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 230, "metadata": {}, "outputs": [], "source": [ @@ -134,7 +130,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 231, "metadata": {}, "outputs": [ { @@ -156,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 232, "metadata": {}, "outputs": [], "source": [ @@ -187,14 +183,17 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 233, "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "('BATTLESHIP', 5) 5 7 6 [(5, 7), (5, 6), (5, 5), (5, 4), (5, 3)]\n('CRUISER', 3) 1 3 3 [(1, 3), (2, 4), (3, 5)]\n('DESTROYER', 2) 5 9 6 [(5, 9), (5, 8)]\n('DESTROYER', 2) 3 4 3 [(3, 4), (4, 5)]\n" + "('BATTLESHIP', 5) 2 2 4 [(2, 2), (3, 2), (4, 2), (5, 2), (6, 2)]\n", + "('CRUISER', 3) 6 7 3 [(6, 7), (7, 8), (8, 9)]\n", + "('DESTROYER', 2) 1 1 3 [(1, 1), (2, 2)]\n", + "('DESTROYER', 2) 8 3 6 [(8, 3), (8, 2)]\n" ] } ], @@ -208,6 +207,110 @@ " print(SHIPS[ship],x,y,direction,coords)" ] }, + { + "cell_type": "code", + "execution_count": 234, + "metadata": {}, + "outputs": [], + "source": [ + "computer_board = [ [ -1 for y in range(BOARD_WIDTH)] \n", + " for x in range(BOARD_HEIGHT)]\n", + "player_board = [ [ -1 for y in range(BOARD_WIDTH)] \n", + " for x in range(BOARD_HEIGHT)]" + ] + }, + { + "cell_type": "code", + "execution_count": 235, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + " 1 2 3 4 5 6 7 8 9 10\n", + " 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 3 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 5 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 6 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 7 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + "10 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n" + ] + } + ], + "source": [ + "def print_board(board):\n", + "\n", + " print(' ',end='')\n", + " for z in range(BOARD_WIDTH):\n", + " print(f'{z+1:3}',end='')\n", + " print('')\n", + "\n", + " for x in range(len(board)):\n", + " print(f'{x+1:2}',end='')\n", + " for y in range(len(board[x])):\n", + " print(f\"{board[x][y]:3}\",end='')\n", + " print('')\n", + "\n", + "print_board(computer_board)" + ] + }, + { + "cell_type": "code", + "execution_count": 236, + "metadata": {}, + "outputs": [], + "source": [ + "def place_ship(board,coords,ship):\n", + " for coord in coords:\n", + " print(\"--->\",coord)\n", + " board[coord[0]-1][coord[1]-1] = 0" + ] + }, + { + "cell_type": "code", + "execution_count": 237, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[(7, 5), (6, 4), (5, 3), (4, 2), (3, 1)]\n", + "---> (7, 5)\n", + "---> (6, 4)\n", + "---> (5, 3)\n", + "---> (4, 2)\n", + "---> (3, 1)\n", + " 1 2 3 4 5 6 7 8 9 10\n", + " 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 3 0 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 4 -1 0 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 5 -1 -1 0 -1 -1 -1 -1 -1 -1 -1\n", + " 6 -1 -1 -1 0 -1 -1 -1 -1 -1 -1\n", + " 7 -1 -1 -1 -1 0 -1 -1 -1 -1 -1\n", + " 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + " 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n", + "10 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n" + ] + } + ], + "source": [ + "x,y = random_x_y()\n", + "ship = 0\n", + "directions = get_possible_directions(x,y,ship)\n", + "direction = random_direction(directions)\n", + "coords = generate_ship_coordinates(x,y,direction,ship)\n", + "print(coords)\n", + "place_ship(computer_board,coords,0)\n", + "print_board(computer_board)" + ] + }, { "cell_type": "code", "execution_count": null, From 37a9f5203d3d5b8b677b3fedf34070c4d22527c7 Mon Sep 17 00:00:00 2001 From: journich <70119791+journich@users.noreply.github.com> Date: Wed, 3 Mar 2021 13:56:21 +1030 Subject: [PATCH 190/749] Java port of Mugwump --- 62 Mugwump/java/src/Mugwump.java | 186 +++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 62 Mugwump/java/src/Mugwump.java diff --git a/62 Mugwump/java/src/Mugwump.java b/62 Mugwump/java/src/Mugwump.java new file mode 100644 index 00000000..6dbefef1 --- /dev/null +++ b/62 Mugwump/java/src/Mugwump.java @@ -0,0 +1,186 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Mugwump + *