mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-01-16 23:12:08 -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
86_Target/README.md
Normal file
7
86_Target/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
### Target
|
||||
|
||||
As published in Basic Computer Games (1978)
|
||||
https://www.atariarchives.org/basicgames/showpage.php?page=165
|
||||
|
||||
Downloaded from Vintage Basic at
|
||||
http://www.vintage-basic.net/games.html
|
||||
3
86_Target/csharp/README.md
Normal file
3
86_Target/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/)
|
||||
34
86_Target/csharp/Target.sln
Normal file
34
86_Target/csharp/Target.sln
Normal file
@@ -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
|
||||
18
86_Target/csharp/Target/Angle.cs
Normal file
18
86_Target/csharp/Target/Angle.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
22
86_Target/csharp/Target/Explosion.cs
Normal file
22
86_Target/csharp/Target/Explosion.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
26
86_Target/csharp/Target/FiringRange.cs
Normal file
26
86_Target/csharp/Target/FiringRange.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
86_Target/csharp/Target/Game.cs
Normal file
89
86_Target/csharp/Target/Game.cs
Normal file
@@ -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.";
|
||||
}
|
||||
}
|
||||
59
86_Target/csharp/Target/Input.cs
Normal file
59
86_Target/csharp/Target/Input.cs
Normal file
@@ -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<float> ReadNumbers(string prompt, int requiredCount)
|
||||
{
|
||||
var numbers = new List<float>();
|
||||
|
||||
while (!TryReadNumbers(prompt, requiredCount, numbers))
|
||||
{
|
||||
numbers.Clear();
|
||||
prompt = "";
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
private static bool TryReadNumbers(string prompt, int requiredCount, List<float> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
86_Target/csharp/Target/Offset.cs
Normal file
21
86_Target/csharp/Target/Offset.cs
Normal file
@@ -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; }
|
||||
}
|
||||
}
|
||||
47
86_Target/csharp/Target/Point.cs
Normal file
47
86_Target/csharp/Target/Point.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
39
86_Target/csharp/Target/Program.cs
Normal file
39
86_Target/csharp/Target/Program.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
86_Target/csharp/Target/RandomExtensions.cs
Normal file
14
86_Target/csharp/Target/RandomExtensions.cs
Normal file
@@ -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());
|
||||
}
|
||||
}
|
||||
18
86_Target/csharp/Target/Strings/TitleAndInstructions.txt
Normal file
18
86_Target/csharp/Target/Strings/TitleAndInstructions.txt
Normal file
@@ -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!!
|
||||
|
||||
|
||||
12
86_Target/csharp/Target/Target.csproj
Normal file
12
86_Target/csharp/Target/Target.csproj
Normal file
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Strings\TitleAndInstructions.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
3
86_Target/java/README.md
Normal file
3
86_Target/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/)
|
||||
146
86_Target/java/Target.java
Normal file
146
86_Target/java/Target.java
Normal file
@@ -0,0 +1,146 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* TARGET
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
86_Target/javascript/README.md
Normal file
3
86_Target/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
86_Target/javascript/target.html
Normal file
9
86_Target/javascript/target.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>TARGET</title>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="output" style="font-size: 12pt;"></pre>
|
||||
<script src="target.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
157
86_Target/javascript/target.js
Normal file
157
86_Target/javascript/target.js
Normal file
@@ -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();
|
||||
3
86_Target/pascal/README.md
Normal file
3
86_Target/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))
|
||||
3
86_Target/perl/README.md
Normal file
3
86_Target/perl/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Conversion to [Perl](https://www.perl.org/)
|
||||
3
86_Target/python/README.md
Normal file
3
86_Target/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/)
|
||||
172
86_Target/python/target.py
Normal file
172
86_Target/python/target.py
Normal file
@@ -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()
|
||||
3
86_Target/ruby/README.md
Normal file
3
86_Target/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/)
|
||||
51
86_Target/target.bas
Normal file
51
86_Target/target.bas
Normal file
@@ -0,0 +1,51 @@
|
||||
10 PRINT TAB(33);"TARGET"
|
||||
20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
|
||||
30 PRINT: PRINT: PRINT
|
||||
100 R=1: R1=57.296: P=3.14159
|
||||
110 PRINT "YOU ARE THE WEAPONS OFFICER ON THE STARSHIP ENTERPRISE"
|
||||
120 PRINT "AND THIS IS A TEST TO SEE HOW ACCURATE A SHOT YOU"
|
||||
130 PRINT "ARE IN A THREE-DIMENSIONAL RANGE. YOU WILL BE TOLD"
|
||||
140 PRINT "THE RADIAN OFFSET FOR THE X AND Z AXES, THE LOCATION"
|
||||
150 PRINT "OF THE TARGET IN THREE DIMENSIONAL RECTANGULAR COORDINATES,"
|
||||
160 PRINT "THE APPROXIMATE NUMBER OF DEGREES FROM THE X AND Z"
|
||||
170 PRINT "AXES, AND THE APPROXIMATE DISTANCE TO THE TARGET."
|
||||
180 PRINT "YOU WILL THEN PROCEEED TO SHOOT AT THE TARGET UNTIL IT IS"
|
||||
190 PRINT "DESTROYED!": PRINT: PRINT "GOOD LUCK!!":PRINT: PRINT
|
||||
220 A=RND(1)*2*P: B=RND(1)*2*P: Q=INT(A*R1): W=INT(B*R1)
|
||||
260 PRINT "RADIANS FROM X AXIS =";A;" FROM Z AXIS =";B
|
||||
280 P1=100000*RND(1)+RND(1): X=SIN(B)*COS(A)*P1: Y=SIN(B)*SIN(A)*P1
|
||||
290 Z=COS(B)*P1
|
||||
340 PRINT "TARGET SIGHTED: APPROXIMATE COORDINATES: X=";X;" Y=";Y;" Z=";Z
|
||||
345 R=R+1: IF R>5 THEN 390
|
||||
350 ON R GOTO 355,360,365,370,375
|
||||
355 P3=INT(P1*.05)*20: GOTO 390
|
||||
360 P3=INT(P1*.1)*10: GOTO 390
|
||||
365 P3=INT(P1*.5)*2: GOTO 390
|
||||
370 P3=INT(P1): GOTO 390
|
||||
375 P3=P1
|
||||
390 PRINT " ESTIMATED DISTANCE:";P3
|
||||
400 PRINT:PRINT "INPUT ANGLE DEVIATION FROM X, DEVIATION FROM Z, DISTANCE";
|
||||
405 INPUT A1,B1,P2
|
||||
410 PRINT: IF P2<20 THEN PRINT "YOU BLEW YOURSELF UP!!": GOTO 580
|
||||
420 A1=A1/R1: B1=B1/R1: PRINT "RADIANS FROM X AXIS =";A1;" ";
|
||||
425 PRINT "FROM Z AXIS =";B1
|
||||
480 X1=P2*SIN(B1)*COS(A1): Y1=P2*SIN(B1)*SIN(A1): Z1=P2*COS(B1)
|
||||
510 D=((X1-X)^2+(Y1-Y)^2+(Z1-Z)^2)^(1/2)
|
||||
520 IF D>20 THEN 670
|
||||
530 PRINT: PRINT " * * * HIT * * * TARGET IS NON-FUNCTIONAL": PRINT
|
||||
550 PRINT "DISTANCE OF EXPLOSION FROM TARGET WAS";D;"KILOMETERS."
|
||||
570 PRINT: PRINT "MISSION ACCOMPLISHED IN ";R;" SHOTS."
|
||||
580 R=0: FOR I=1 TO 5: PRINT: NEXT I: PRINT "NEXT TARGET...": PRINT
|
||||
590 GOTO 220
|
||||
670 X2=X1-X: Y2=Y1-Y: Z2=Z1-Z: IF X2<0 THEN 730
|
||||
710 PRINT "SHOT IN FRONT OF TARGET";X2;"KILOMETERS.": GOTO 740
|
||||
730 PRINT "SHOT BEHIND TARGET";-X2;"KILOMETERS."
|
||||
740 IF Y2<0 THEN 770
|
||||
750 PRINT "SHOT TO LEFT OF TARGET";Y2;"KILOMETERS.": GOTO 780
|
||||
770 PRINT "SHOT TO RIGHT OF TARGET";-Y2;"KILOMETERS."
|
||||
780 IF Z2<0 THEN 810
|
||||
790 PRINT "SHOT ABOVE TARGET";Z2;"KILOMETERS.": GOTO 820
|
||||
810 PRINT "SHOT BELOW TARGET";-Z2;"KILOMETERS."
|
||||
820 PRINT "APPROX POSITION OF EXPLOSION: X=";X1;" Y=";Y1;" Z=";Z1
|
||||
830 PRINT " DISTANCE FROM TARGET =";D: PRINT: PRINT: PRINT: GOTO 345
|
||||
999 END
|
||||
3
86_Target/vbnet/README.md
Normal file
3
86_Target/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