mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-01-18 15:56:46 -08:00
Removed spaces from top-level directory names.
Spaces tend to cause annoyances in a Unix-style shell environment. This change fixes that.
This commit is contained in:
7
31_Depth_Charge/README.md
Normal file
7
31_Depth_Charge/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
### Depth Charge
|
||||
|
||||
As published in Basic Computer Games (1978)
|
||||
https://www.atariarchives.org/basicgames/showpage.php?page=55
|
||||
|
||||
Downloaded from Vintage Basic at
|
||||
http://www.vintage-basic.net/games.html
|
||||
25
31_Depth_Charge/csharp/DepthCharge.sln
Normal file
25
31_Depth_Charge/csharp/DepthCharge.sln
Normal file
@@ -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
|
||||
9
31_Depth_Charge/csharp/Game.csproj
Normal file
9
31_Depth_Charge/csharp/Game.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>DepthCharge</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
3
31_Depth_Charge/csharp/README.md
Normal file
3
31_Depth_Charge/csharp/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
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/)
|
||||
85
31_Depth_Charge/csharp/src/Controller.cs
Normal file
85
31_Depth_Charge/csharp/src/Controller.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
|
||||
namespace DepthCharge
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains functions for reading input from the user.
|
||||
/// </summary>
|
||||
static class Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrives a dimension for the play area from the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a set of coordinates from the user.
|
||||
/// </summary>
|
||||
/// <param name="trailNumber">
|
||||
/// The current trail number.
|
||||
/// </param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user's intention to play again (or not).
|
||||
/// </summary>
|
||||
public static bool InputPlayAgain()
|
||||
{
|
||||
View.PromptPlayAgain();
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (Console.ReadLine())
|
||||
{
|
||||
case "Y":
|
||||
return true;
|
||||
case "N":
|
||||
return false;
|
||||
default:
|
||||
View.ShowInvalidYesOrNo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
31_Depth_Charge/csharp/src/Program.cs
Normal file
47
31_Depth_Charge/csharp/src/Program.cs
Normal file
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
121
31_Depth_Charge/csharp/src/View.cs
Normal file
121
31_Depth_Charge/csharp/src/View.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
|
||||
namespace DepthCharge
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains methods for displaying information to the user.
|
||||
/// </summary>
|
||||
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)? ");
|
||||
}
|
||||
}
|
||||
}
|
||||
33
31_Depth_Charge/depthcharge.bas
Normal file
33
31_Depth_Charge/depthcharge.bas
Normal file
@@ -0,0 +1,33 @@
|
||||
2 PRINT TAB(30);"DEPTH CHARGE"
|
||||
4 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
|
||||
6 PRINT: PRINT: PRINT
|
||||
20 INPUT "DIMENSION OF SEARCH AREA";G: PRINT
|
||||
30 N=INT(LOG(G)/LOG(2))+1
|
||||
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
|
||||
110 A=INT(G*RND(1)) : B=INT(G*RND(1)) : C=INT(G*RND(1))
|
||||
120 FOR D=1 TO N : PRINT : PRINT "TRIAL #";D; : INPUT X,Y,Z
|
||||
130 IF ABS(X-A)+ABS(Y-B)+ABS(Z-C)=0 THEN 300
|
||||
140 GOSUB 500 : PRINT : NEXT D
|
||||
200 PRINT : PRINT "YOU HAVE BEEN TORPEDOED! ABANDON SHIP!"
|
||||
210 PRINT "THE SUBMARINE WAS AT";A;",";B;",";C : GOTO 400
|
||||
300 PRINT : PRINT "B O O M ! ! YOU FOUND IT IN";D;"TRIES!"
|
||||
400 PRINT : PRINT: INPUT "ANOTHER GAME (Y OR N)";A$
|
||||
410 IF A$="Y" THEN 100
|
||||
420 PRINT "OK. HOPE YOU ENJOYED YOURSELF." : GOTO 600
|
||||
500 PRINT "SONAR REPORTS SHOT WAS ";
|
||||
510 IF Y>B THEN PRINT "NORTH";
|
||||
520 IF Y<B THEN PRINT "SOUTH";
|
||||
530 IF X>A THEN PRINT "EAST";
|
||||
540 IF X<A THEN PRINT "WEST";
|
||||
550 IF Y<>B OR X<>A THEN PRINT " AND";
|
||||
560 IF Z>C THEN PRINT " TOO LOW."
|
||||
570 IF Z<C THEN PRINT " TOO HIGH."
|
||||
580 IF Z=C THEN PRINT " DEPTH OK."
|
||||
590 RETURN
|
||||
600 END
|
||||
186
31_Depth_Charge/java/DepthCharge.java
Normal file
186
31_Depth_Charge/java/DepthCharge.java
Normal file
@@ -0,0 +1,186 @@
|
||||
import java.util.Scanner;
|
||||
import java.lang.Math;
|
||||
|
||||
/**
|
||||
* Game of Depth Charge
|
||||
* <p>
|
||||
* Based on the BASIC game of Depth Charge here
|
||||
* https://github.com/coding-horror/basic-computer-games/blob/main/31%20Depth%20Charge/depthcharge.bas
|
||||
* <p>
|
||||
* 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
|
||||
3
31_Depth_Charge/java/README.md
Normal file
3
31_Depth_Charge/java/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [Oracle Java](https://openjdk.java.net/)
|
||||
3
31_Depth_Charge/javascript/README.md
Normal file
3
31_Depth_Charge/javascript/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Shells)
|
||||
9
31_Depth_Charge/javascript/depthcharge.html
Normal file
9
31_Depth_Charge/javascript/depthcharge.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>DEPTH CHARGE</title>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="output" style="font-size: 12pt;"></pre>
|
||||
<script src="depthcharge.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
112
31_Depth_Charge/javascript/depthcharge.js
Normal file
112
31_Depth_Charge/javascript/depthcharge.js
Normal file
@@ -0,0 +1,112 @@
|
||||
// DEPTH CHARGE
|
||||
//
|
||||
// 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) + "DEPTH CHARGE\n");
|
||||
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
|
||||
print("\n");
|
||||
print("\n");
|
||||
print("\n");
|
||||
print("DIMENSION OF THE SEARCH AREA");
|
||||
g = Math.floor(await input());
|
||||
n = Math.floor(Math.log(g) / Math.log(2)) + 1;
|
||||
print("YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER\n");
|
||||
print("AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR\n");
|
||||
print("MISSION IS TO DESTROY IT. YOU HAVE " + n + " SHOTS.\n");
|
||||
print("SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A\n");
|
||||
print("TRIO OF NUMBERS -- THE FIRST TWO ARE THE\n");
|
||||
print("SURFACE COORDINATES; THE THIRD IS THE DEPTH.\n");
|
||||
do {
|
||||
print("\n");
|
||||
print("GOOD LUCK !\n");
|
||||
print("\n");
|
||||
a = Math.floor(Math.random() * g);
|
||||
b = Math.floor(Math.random() * g);
|
||||
c = Math.floor(Math.random() * g);
|
||||
for (d = 1; d <= n; d++) {
|
||||
print("\n");
|
||||
print("TRIAL #" + d + " ");
|
||||
str = await input();
|
||||
x = parseInt(str);
|
||||
y = parseInt(str.substr(str.indexOf(",") + 1));
|
||||
z = parseInt(str.substr(str.lastIndexOf(",") + 1));
|
||||
if (Math.abs(x - a) + Math.abs(y - b) + Math.abs(z - c) == 0)
|
||||
break;
|
||||
if (y > b)
|
||||
print("NORTH");
|
||||
if (y < b)
|
||||
print("SOUTH");
|
||||
if (x > a)
|
||||
print("EAST");
|
||||
if (x < a)
|
||||
print("WEST");
|
||||
if (y != b || x != a)
|
||||
print(" AND");
|
||||
if (z > c)
|
||||
print(" TOO LOW.\n");
|
||||
if (z < c)
|
||||
print(" TOO HIGH.\n");
|
||||
if (z == c)
|
||||
print(" DEPTH OK.\n");
|
||||
print("\n");
|
||||
}
|
||||
if (d <= n) {
|
||||
print("\n");
|
||||
print("B O O M ! ! YOU FOUND IT IN " + d + " TRIES!\n");
|
||||
} else {
|
||||
print("\n");
|
||||
print("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!\n");
|
||||
print("THE SUBMARINE WAS AT " + a + "," + b + "," + c + "\n");
|
||||
}
|
||||
print("\n");
|
||||
print("\n");
|
||||
print("ANOTHER GAME (Y OR N)");
|
||||
str = await input();
|
||||
} while (str.substr(0, 1) == "Y") ;
|
||||
print("OK. HOPE YOU ENJOYED YOURSELF.\n");
|
||||
}
|
||||
|
||||
main();
|
||||
3
31_Depth_Charge/pascal/README.md
Normal file
3
31_Depth_Charge/pascal/README.md
Normal file
@@ -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))
|
||||
17
31_Depth_Charge/perl/README.md
Normal file
17
31_Depth_Charge/perl/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [Perl](https://www.perl.org/)
|
||||
|
||||
## Conversion
|
||||
|
||||
Not a difficult conversion - but a chance to throw in a few ways
|
||||
Perl makes life easy.
|
||||
|
||||
* To get the sub permission which is a random location in the g x g x g grid we can use:
|
||||
* assigning multiple variables in list form ($a,$b,$c) = (?,?,?)
|
||||
* where the list on the right hand side is generated with a map function
|
||||
|
||||
* We use ternarys to generate the message if you miss the sub.
|
||||
* We use join to stitch the pieces of the string together.
|
||||
* If we have a ternary where we don't want to return anything we return an empty list rather than an empty string - if you return the latter you still get the padding spaces.
|
||||
|
||||
52
31_Depth_Charge/perl/depth-charge.pl
Executable file
52
31_Depth_Charge/perl/depth-charge.pl
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
print ' Depth Charge
|
||||
Creative Computing Morristown, New Jersey
|
||||
|
||||
|
||||
Depth Charge Game
|
||||
|
||||
Dimensions of Search Area? ';
|
||||
|
||||
my $g = <STDIN>;
|
||||
my $n = int( log($g) / log 2 ) + 1;
|
||||
print '
|
||||
You are the captain of the Destroyer USS Computer
|
||||
an enemy sub has been causing you trouble. Your
|
||||
mission is to destroy it. You have ',$n,' shots.
|
||||
Specify depth charge explosion point with a
|
||||
trio of number -- the first two are the surface
|
||||
co-ordinates; the third is the depth.
|
||||
';
|
||||
|
||||
while(1) { ## Repeat until we say no....
|
||||
print "\nGood luck!\n\n";
|
||||
my ($a,$b,$c) = map { int rand $g } 1..3; ## Get the location
|
||||
my $hit = 0; ## Keep track if we have won yet!
|
||||
foreach ( 1..$n ) {
|
||||
print "\nTrial # $_ ? ";
|
||||
my ( $x, $y, $z ) = split m{\D+}, <STDIN>;
|
||||
if( $x==$a && $y==$b && $z==$c ) {
|
||||
$hit = 1; ## We have won
|
||||
print "\n\nB O O M ! ! You found it in $_ tries!\n";
|
||||
last;
|
||||
}
|
||||
print join q( ), 'Sonar reports show was',
|
||||
$y < $b ? 'South' : $y > $b ? 'North' : (),
|
||||
$x < $a ? 'West' : $x > $a ? 'East' : (),
|
||||
$x == $a && $y == $b ? () : 'and' ,
|
||||
$z < $c ? 'too high' : $z > $c ? 'too low' : 'depth OK',
|
||||
".\n";
|
||||
}
|
||||
|
||||
## Only show message if we haven't won...
|
||||
print "\nYou have been torpedoed! Abandon ship!\nThe submarine was at $a, $b, $c\n" unless $hit;
|
||||
|
||||
print "\n\nAnother game (Y or N)? ";
|
||||
last unless <STDIN> =~ m{Y}i; ## Y or y not typed so leave loop
|
||||
}
|
||||
## Say good bye
|
||||
print "OK. Hope you enjoyed yourself.\n\n";
|
||||
3
31_Depth_Charge/python/README.md
Normal file
3
31_Depth_Charge/python/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [Python](https://www.python.org/about/)
|
||||
120
31_Depth_Charge/python/depth_charge.py
Normal file
120
31_Depth_Charge/python/depth_charge.py
Normal file
@@ -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()
|
||||
3
31_Depth_Charge/ruby/README.md
Normal file
3
31_Depth_Charge/ruby/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [Ruby](https://www.ruby-lang.org/en/)
|
||||
3
31_Depth_Charge/vbnet/README.md
Normal file
3
31_Depth_Charge/vbnet/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original BASIC source [downloaded from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [Visual Basic .NET](https://en.wikipedia.org/wiki/Visual_Basic_.NET)
|
||||
Reference in New Issue
Block a user