diff --git a/03_Animal/java/Animal.java b/03_Animal/java/Animal.java
index 11e9e889..681425c1 100644
--- a/03_Animal/java/Animal.java
+++ b/03_Animal/java/Animal.java
@@ -2,159 +2,244 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
+import java.util.stream.Collectors;
/**
* ANIMAL
*
* Converted from BASIC to Java by Aldrin Misquitta (@aldrinm)
+ * The original BASIC program uses an array to maintain the questions and answers and to decide which question to
+ * ask next. Updated this Java implementation to use a tree instead of the earlier faulty one based on a list (thanks @patimen).
*/
public class Animal {
- public static void main(String[] args) {
- printIntro();
- Scanner scan = new Scanner(System.in);
+ 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"));
+ Node root = new QuestionNode("DOES IT SWIM",
+ new AnimalNode("FISH"), new AnimalNode("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++;
- }
- }
+ boolean stopGame = false;
+ while (!stopGame) {
+ String choice = readMainChoice(scan);
+ switch (choice) {
+ case "TREE":
+ printTree(root);
+ break;
+ case "LIST":
+ printKnownAnimals(root);
+ break;
+ case "Q":
+ case "QUIT":
+ stopGame = true;
+ break;
+ default:
+ if (choice.toUpperCase(Locale.ROOT).startsWith("Y")) {
+ Node current = root; //where we are in the question tree
+ Node previous; //keep track of parent of current in order to place new questions later on.
- if (!correctGuess) {
- askForInformationAndSave(scan, questions);
- }
- }
- }
- }
+ while (current instanceof QuestionNode) {
+ var currentQuestion = (QuestionNode) current;
+ var reply = askQuestionAndGetReply(currentQuestion, scan);
- }
+ previous = current;
+ current = reply ? currentQuestion.getTrueAnswer() : currentQuestion.getFalseAnswer();
+ if (current instanceof AnimalNode) {
+ //We have reached a animal node, so offer it as the guess
+ var currentAnimal = (AnimalNode) current;
+ System.out.printf("IS IT A %s ? ", currentAnimal.getAnimal());
+ var animalGuessResponse = readYesOrNo(scan);
+ if (animalGuessResponse) {
+ //we guessed right! end this round
+ System.out.println("WHY NOT TRY ANOTHER ANIMAL?");
+ } else {
+ //we guessed wrong :(, ask for feedback
+ //cast previous to QuestionNode since we know at this point that it is not a leaf node
+ askForInformationAndSave(scan, currentAnimal, (QuestionNode) previous, reply);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
- 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);
- }
+ /**
+ * Prompt for information about the animal we got wrong
+ * @param current The animal that we guessed wrong
+ * @param previous The root of current
+ * @param previousToCurrentDecisionChoice Whether it was a Y or N answer that got us here. true = Y, false = N
+ */
+ private static void askForInformationAndSave(Scanner scan, AnimalNode current, QuestionNode previous, boolean previousToCurrentDecisionChoice) {
+ //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, current.getAnimal());
+ String newQuestion = scan.nextLine();
+ System.out.printf("FOR A %s THE ANSWER WOULD BE ", animal);
+ boolean newAnswer = readYesOrNo(scan);
+ //Add it to our question store
+ addNewAnimal(current, previous, animal, newQuestion, newAnswer, previousToCurrentDecisionChoice);
+ }
- 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
+ private static void addNewAnimal(Node current,
+ QuestionNode previous,
+ String animal,
+ String newQuestion,
+ boolean newAnswer,
+ boolean previousToCurrentDecisionChoice) {
+ var animalNode = new AnimalNode(animal);
+ var questionNode = new QuestionNode(newQuestion,
+ newAnswer ? animalNode : current,
+ !newAnswer ? animalNode : current);
- Question newOption;
- if (newAnswer) {
- newOption = new Question(newQuestion, animal, lastAnimal);
- } else {
- newOption = new Question(newQuestion, lastAnimal, animal);
- }
- questions.add(newOption);
- }
+ if (previous != null) {
+ if (previousToCurrentDecisionChoice) {
+ previous.setTrueAnswer(questionNode);
+ } else {
+ previous.setFalseAnswer(questionNode);
+ }
+ }
+ }
- private static boolean askQuestion(Question question, Scanner scanner) {
- System.out.printf("%s ? ", question.question);
+ private static boolean askQuestionAndGetReply(QuestionNode questionNode, Scanner scanner) {
+ System.out.printf("%s ? ", questionNode.question);
+ return readYesOrNo(scanner);
+ }
- 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 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(Node root) {
+ System.out.println("\nANIMALS I ALREADY KNOW ARE:");
- 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));
- }
+ List leafNodes = collectLeafNodes(root);
+ String allAnimalsString = leafNodes.stream().map(AnimalNode::getAnimal).collect(Collectors.joining("\t\t"));
- private static String readMainChoice(Scanner scan) {
- System.out.print("ARE YOU THINKING OF AN ANIMAL ? ");
- return scan.nextLine();
- }
+ System.out.println(allAnimalsString);
+ }
- 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.");
- }
+ //Traverse the tree and collect all the leaf nodes, which basically have all the animals.
+ private static List collectLeafNodes(Node root) {
+ List collectedNodes = new ArrayList<>();
+ if (root instanceof AnimalNode) {
+ collectedNodes.add((AnimalNode) root);
+ } else {
+ var q = (QuestionNode) root;
+ collectedNodes.addAll(collectLeafNodes(q.getTrueAnswer()));
+ collectedNodes.addAll(collectLeafNodes(q.getFalseAnswer()));
+ }
+ return collectedNodes;
+ }
+
+ 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.");
+ }
+
+ //Based on https://stackoverflow.com/a/8948691/74057
+ private static void printTree(Node root) {
+ StringBuilder buffer = new StringBuilder(50);
+ print(root, buffer, "", "");
+ System.out.println(buffer);
+ }
+
+ private static void print(Node root, StringBuilder buffer, String prefix, String childrenPrefix) {
+ buffer.append(prefix);
+ buffer.append(root.toString());
+ buffer.append('\n');
+
+ if (root instanceof QuestionNode) {
+ var questionNode = (QuestionNode) root;
+ print(questionNode.getTrueAnswer(), buffer, childrenPrefix + "├─Y─ ", childrenPrefix + "│ ");
+ print(questionNode.getFalseAnswer(), buffer, childrenPrefix + "└─N─ ", childrenPrefix + " ");
+ }
+ }
- public static class Question {
- String question;
- String trueAnswer;
- String falseAnswer;
+ /**
+ * Base interface for all nodes in our question tree
+ */
+ private interface Node {
+ }
- public Question(String question, String trueAnswer, String falseAnswer) {
- this.question = question;
- this.trueAnswer = trueAnswer;
- this.falseAnswer = falseAnswer;
- }
- }
+ private static class QuestionNode implements Node {
+ private final String question;
+ private Node trueAnswer;
+ private Node falseAnswer;
+
+ public QuestionNode(String question, Node trueAnswer, Node falseAnswer) {
+ this.question = question;
+ this.trueAnswer = trueAnswer;
+ this.falseAnswer = falseAnswer;
+ }
+
+ public String getQuestion() {
+ return question;
+ }
+
+ public Node getTrueAnswer() {
+ return trueAnswer;
+ }
+
+ public void setTrueAnswer(Node trueAnswer) {
+ this.trueAnswer = trueAnswer;
+ }
+
+ public Node getFalseAnswer() {
+ return falseAnswer;
+ }
+
+ public void setFalseAnswer(Node falseAnswer) {
+ this.falseAnswer = falseAnswer;
+ }
+
+ @Override
+ public String toString() {
+ return "Question{'" + question + "'}";
+ }
+ }
+
+ private static class AnimalNode implements Node {
+ private final String animal;
+
+ public AnimalNode(String animal) {
+ this.animal = animal;
+ }
+
+ public String getAnimal() {
+ return animal;
+ }
+
+ @Override
+ public String toString() {
+ return "Animal{'" + animal + "'}";
+ }
+ }
}
diff --git a/29_Craps/ruby/craps.rb b/29_Craps/ruby/craps.rb
new file mode 100644
index 00000000..dc53813b
--- /dev/null
+++ b/29_Craps/ruby/craps.rb
@@ -0,0 +1,125 @@
+class CRAPSGAME
+
+ # class variables start with a double "@"
+ @@standings = 0
+
+ def displayHeading
+ puts "CRAPS".center(80)
+ puts "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".center(80)
+ puts "\n\n\n"
+ puts "2,3,12 are losers"
+ puts "4,5,6,8,9,10 are points"
+ puts "7,11 are natural winners.\n\n"
+ end
+
+ def displayStanding
+ if @@standings < 0
+ print "you are in the hole by "
+ elsif @@standings == 0
+ print "you currently have "
+ else
+ # show how much money we currently have
+ print "you now have won "
+ end
+ # print the absolute value of the amount in the standings
+ puts @@standings.abs.to_s + " dollars"
+ end
+
+ # dice can come up 2 through 12
+ # so return a minimum of 2 and add 0 through 10 to that
+ def rollDice
+ puts "I will now throw the dice"
+ return rand(5) + rand(5) + 2
+ end
+
+ def placeBet
+ print "How much do you want to wager? "
+ wager = gets.strip.to_i
+ return wager
+ end
+
+ def loseBetBy amount
+ @@standings -= amount
+ end
+
+ def winBetBy amount
+ @@standings += amount
+ end
+
+ def askQuit?
+ print "\nDo you want to play again? "
+ # just the first character, make it uppercase
+ again = gets.strip.upcase[0]
+ return again != "Y"
+ end
+
+ def pointRoll point, wager
+ while true do
+ puts " is the point."
+ puts " I will roll again when you press Enter."
+ waitForIt = gets
+ roll = rollDice
+ print roll.to_s
+
+ # the only critical rolls here are 7 and the previous roll
+ # if anything else comes up we roll again.
+ case roll.to_i
+ when 7
+ puts " craps - you lose"
+ loseBetBy wager
+ break
+ when point
+ puts " is a winner! congrats!"
+ puts "at 2 to 1 odds pays you " + (2 * wager).to_s + " dollars"
+ winBetBy 2 * wager
+ break
+ else
+ print " no point - " + point.to_s
+ end
+ end
+ end
+
+ def play
+ displayHeading
+
+ while true do
+ wagerAmount = placeBet
+ roll = rollDice
+ print roll.to_s
+ case roll
+ when 2
+ puts " snake eyes - you lose"
+ loseBetBy wagerAmount
+ when 3, 12
+ puts " craps - you lose"
+ loseBetBy wagerAmount
+ when 4, 5, 6, 8, 9, 10
+ pointRoll roll, wagerAmount
+ when 7, 11
+ puts " a natural - a winner"
+ puts "pays even money: " + wagerAmount.to_s + " dollars"
+ winBetBy wagerAmount
+ end
+ displayStanding
+ if askQuit?
+ endPlay
+ end
+ end
+ end
+
+ def endPlay
+ case
+ when @@standings < 0
+ puts "Too bad. You are in the hole " + @@standings.abs.to_s + " dollars. Come again."
+ when @@standings > 0
+ puts "Congratulations --- You came out a winner of " + @@standings.to_s + " dollars. Come again!"
+ when @@standings == 0
+ puts "Congratulations --- You came out even, not bad for an amateur"
+ end
+ exit
+ end
+end
+
+craps = CRAPSGAME.new
+craps.play
+
diff --git a/41_Guess/ruby/guess.rb b/41_Guess/ruby/guess.rb
new file mode 100644
index 00000000..cf2deea2
--- /dev/null
+++ b/41_Guess/ruby/guess.rb
@@ -0,0 +1,48 @@
+def print_intro
+ print " " * 31 + "GUESS\n"
+ print " " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"
+ print "THIS IS A NUMBER GUESSING GAME. I'LL THINK\nOF A NUMBER BETWEEN 1 AND ANY LIMIT YOU WANT.\nTHEN YOU HAVE TO GUESS WHAT IT IS.\n"
+end
+
+def game_play(limit,choice_limit)
+ random = rand(limit.to_i)+1
+ puts "I'M THINKING OF A NUMBER BETWEEN 1 and #{limit}"
+ puts "NOW YOU TRY TO GUESS WHAT IT IS."
+ print "? "
+ ans=0
+ guesses=0
+ until ans.to_i == random.to_i
+ ans = gets.chomp
+ guesses += 1
+ if ans.to_i > random.to_i
+ puts "TOO HIGH. TRY A SMALLER ANSWER."
+ print "? "
+ elsif ans.to_i < random.to_i
+ puts "TOO LOW. TRY A BIGGER ANSWER."
+ print "? "
+ elsif ans.to_i == random.to_i
+ puts "THAT'S IT! YOU GOT IT IN #{guesses} TRIES."
+ if guesses.to_i < choice_limit.to_i
+ puts "VERY GOOD."
+ elsif guesses.to_i == choice_limit.to_i
+ puts "GOOD."
+ else
+ puts "YOU SHOULD HAVE BEEN ABLE TO GET IT IN ONLY #{choice_limit}"
+ end
+ print "\n\n\n\n\n"
+ end
+ end
+end
+
+
+def main
+ print_intro
+ puts "WHAT LIMIT DO YOU WANT"
+ limit = gets.chomp
+ choice_limit = (Math.log(limit.to_i)/Math.log(2)+1).to_i
+ while 1
+ game_play(limit,choice_limit)
+ end
+end
+
+main
diff --git a/61_Math_Dice/ruby/mathdice.rb b/61_Math_Dice/ruby/mathdice.rb
new file mode 100644
index 00000000..60853d45
--- /dev/null
+++ b/61_Math_Dice/ruby/mathdice.rb
@@ -0,0 +1,115 @@
+def intro
+ puts " MATH DICE
+ CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
+
+THIS PROGRAM GENERATES SUCCESSIVE PICTURES OF TWO DICE.
+WHEN TWO DICE AND AN EQUAL SIGN FOLLOWED BY A QUESTION
+MARK HAVE BEEN PRINTED, TYPE YOUR ANSWER AND THE RETURN KEY.
+TO CONCLUDE THE LESSON, TYPE '0' AS YOUR ANSWER.
+"
+end
+
+def game_play
+ num = 0
+ sum = 0
+ tries = 0
+ until num == 2 do
+ num+=1
+ roll = rand(6) + 1
+ print_dice(roll)
+ sum = sum + roll
+ if num == 1
+ print "\n +\n\n"
+ end
+ if num == 2
+ print "\n =? "
+ ans = gets.chomp
+ if ans.to_i == 0
+ #END GAME
+ exit(0)
+ elsif ans.to_i == sum
+ puts "RIGHT!"
+ puts "THE DICE ROLL AGAIN"
+ else
+ puts "NO, COUNT THE SPOTS AND GIVE ANOTHER ANSWER"
+ print "\n =? "
+ ans = gets.chomp
+ if ans.to_i == sum
+ puts "RIGHT!"
+ puts "THE DICE ROLL AGAIN"
+ elsif ans.to_i == 0
+ exit(0)
+ else
+ puts "NO, THE ANSWER IS #{sum}"
+ end
+ end
+ end
+ end
+end
+
+
+
+def print_dice(roll)
+ puts " -----"
+ if roll == 1
+ print_blank
+ print_one_mid
+ print_blank
+ elsif roll == 2
+ print_one_left
+ print_blank
+ print_one_right
+ elsif roll == 3
+ print_one_left
+ print_one_mid
+ print_one_right
+ elsif roll == 4
+ print_two
+ print_blank
+ print_two
+ elsif roll == 5
+ print_two
+ print_one_mid
+ print_two
+ elsif roll == 6
+ print_two
+ print_two
+ print_two
+ else
+ puts "not a legit dice roll"
+ end
+ puts " -----"
+end
+
+
+def print_one_left
+ puts "I * I"
+end
+
+def print_one_mid
+ puts "I * I"
+end
+
+def print_one_right
+ puts "I * I"
+end
+
+def print_two
+ puts "I * * I"
+end
+
+def print_blank
+ puts "I I"
+end
+
+
+
+def main
+ intro
+ #Continue playing forever until it terminates with exit in game_play
+ while 1 == 1 do
+ game_play
+ end
+end
+
+main
diff --git a/84_Super_Star_Trek/superstartrek.bas b/84_Super_Star_Trek/superstartrek.bas
index 74300763..efd74cb0 100644
--- a/84_Super_Star_Trek/superstartrek.bas
+++ b/84_Super_Star_Trek/superstartrek.bas
@@ -21,12 +21,12 @@
210 REM *** BY USING "?" INSTEAD OF "PRINT" WHEN ENTERING LINES
215 REM ***
220 PRINT:PRINT:PRINT:PRINT:PRINT:PRINT:PRINT:PRINT:PRINT:PRINT:PRINT
-221 PRINT" ,------*------,"
-222 PRINT" ,------------- '--- ------'"
-223 PRINT" '-------- --' / /"
-224 PRINT" ,---' '-------/ /--,"
-225 PRINT" '----------------'":PRINT
-226 PRINT" THE USS ENTERPRISE --- NCC-1701"
+221 PRINT " ,------*------,"
+222 PRINT " ,------------- '--- ------'"
+223 PRINT " '-------- --' / /"
+224 PRINT " ,---' '-------/ /--,"
+225 PRINT " '----------------'":PRINT
+226 PRINT " THE USS ENTERPRISE --- NCC-1701"
227 PRINT:PRINT:PRINT:PRINT:PRINT
260 REM CLEAR 600
270 Z$=" "
@@ -37,353 +37,353 @@
475 DEF FNR(R)=INT(RND(R)*7.98+1.01)
480 REM INITIALIZE ENTERPRIZE'S POSITION
490 Q1=FNR(1):Q2=FNR(1):S1=FNR(1):S2=FNR(1)
-530 FORI=1TO9:C(I,1)=0:C(I,2)=0:NEXTI
+530 FOR I=1 TO 9:C(I,1)=0:C(I,2)=0:NEXT I
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
-670 FORI=1TO8:D(I)=0:NEXTI
+670 FOR I=1 TO 8:D(I)=0:NEXT I
710 A1$="NAVSRSLRSPHATORSHEDAMCOMXXX"
810 REM SETUP WHAT EXHISTS IN GALAXY . . .
815 REM K3= # KLINGONS B3= # STARBASES S3 = # STARS
-820 FORI=1TO8:FORJ=1TO8:K3=0:Z(I,J)=0:R1=RND(1)
-850 IFR1>.98THENK3=3:K9=K9+3:GOTO980
-860 IFR1>.95THENK3=2:K9=K9+2:GOTO980
-870 IFR1>.80THENK3=1:K9=K9+1
-980 B3=0:IFRND(1)>.96THENB3=1:B9=B9+1
-1040 G(I,J)=K3*100+B3*10+FNR(1):NEXTJ:NEXTI:IFK9>T9THENT9=K9+1
-1100 IFB9<>0THEN1200
-1150 IFG(Q1,Q2)<200THENG(Q1,Q2)=G(Q1,Q2)+120:K9=K9+1
+820 FOR I=1 TO 8:FOR J=1 TO 8:K3=0:Z(I,J)=0:R1=RND(1)
+850 IF R1>.98 THEN K3=3:K9=K9+3:GOTO 980
+860 IF R1>.95 THEN K3=2:K9=K9+2:GOTO 980
+870 IF R1>.80 THEN K3=1:K9=K9+1
+980 B3=0:IF RND(1)>.96 THEN B3=1:B9=B9+1
+1040 G(I,J)=K3*100+B3*10+FNR(1):NEXT J:NEXT I:IF K9>T9 THEN T9=K9+1
+1100 IF B9<>0 THEN 1200
+1150 IF G(Q1,Q2)<200 THEN G(Q1,Q2)=G(Q1,Q2)+120:K9=K9+1
1160 B9=1:G(Q1,Q2)=G(Q1,Q2)+10:Q1=FNR(1):Q2=FNR(1)
-1200 K7=K9:IFB9<>1THENX$="S":X0$=" ARE "
-1230 PRINT"YOUR ORDERS ARE AS FOLLOWS:"
-1240 PRINT" DESTROY THE";K9;"KLINGON WARSHIPS WHICH HAVE INVADED"
-1252 PRINT" THE GALAXY BEFORE THEY CAN ATTACK FEDERATION HEADQUARTERS"
-1260 PRINT" ON STARDATE";T0+T9;" THIS GIVES YOU";T9;"DAYS. THERE";X0$
-1272 PRINT" ";B9;"STARBASE";X$;" IN THE GALAXY FOR RESUPPLYING YOUR SHIP"
-1280 PRINT:REM PRINT"HIT ANY KEY EXCEPT RETURN WHEN READY TO ACCEPT COMMAND"
+1200 K7=K9:IF B9<>1 THEN X$="S":X0$=" ARE "
+1230 PRINT "YOUR ORDERS ARE AS FOLLOWS:"
+1240 PRINT " DESTROY THE";K9;"KLINGON WARSHIPS WHICH HAVE INVADED"
+1252 PRINT " THE GALAXY BEFORE THEY CAN ATTACK FEDERATION HEADQUARTERS"
+1260 PRINT " ON STARDATE";T0+T9;" THIS GIVES YOU";T9;"DAYS. THERE";X0$
+1272 PRINT " ";B9;"STARBASE";X$;" IN THE GALAXY FOR RESUPPLYING YOUR SHIP"
+1280 PRINT:REM PRINT "HIT ANY KEY EXCEPT RETURN WHEN READY TO ACCEPT COMMAND"
1300 I=RND(1):REM IF INP(1)=13 THEN 1300
1310 REM HERE ANY TIME NEW QUADRANT ENTERED
1320 Z4=Q1:Z5=Q2:K3=0:B3=0:S3=0:G5=0:D4=.5*RND(1):Z(Q1,Q2)=G(Q1,Q2)
-1390 IFQ1<1ORQ1>8ORQ2<1ORQ2>8THEN1600
+1390 IF Q1<1 OR Q1>8 OR Q2<1 OR Q2>8 THEN 1600
1430 GOSUB 9030:PRINT:IF T0<>T THEN 1490
-1460 PRINT"YOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED"
-1470 PRINT"IN THE GALACTIC QUADRANT, '";G2$;"'.":GOTO 1500
-1490 PRINT"NOW ENTERING ";G2$;" QUADRANT . . ."
+1460 PRINT "YOUR MISSION BEGINS WITH YOUR STARSHIP LOCATED"
+1470 PRINT "IN THE GALACTIC QUADRANT, '";G2$;"'.":GOTO 1500
+1490 PRINT "NOW ENTERING ";G2$;" QUADRANT . . ."
1500 PRINT:K3=INT(G(Q1,Q2)*.01):B3=INT(G(Q1,Q2)*.1)-10*K3
-1540 S3=G(Q1,Q2)-100*K3-10*B3:IFK3=0THEN1590
-1560 PRINT"COMBAT AREA CONDITION RED":IFS>200THEN1590
-1580 PRINT" SHIELDS DANGEROUSLY LOW"
-1590 FORI=1TO3:K(I,1)=0:K(I,2)=0:NEXTI
-1600 FORI=1TO3:K(I,3)=0:NEXTI:Q$=Z$+Z$+Z$+Z$+Z$+Z$+Z$+LEFT$(Z$,17)
+1540 S3=G(Q1,Q2)-100*K3-10*B3:IF K3=0 THEN 1590
+1560 PRINT "COMBAT AREA CONDITION RED":IF S>200 THEN 1590
+1580 PRINT " SHIELDS DANGEROUSLY LOW"
+1590 FOR I=1 TO 3:K(I,1)=0:K(I,2)=0:NEXT I
+1600 FOR I=1 TO 3:K(I,3)=0:NEXT I:Q$=Z$+Z$+Z$+Z$+Z$+Z$+Z$+LEFT$(Z$,17)
1660 REM POSITION ENTERPRISE IN QUADRANT, THEN PLACE "K3" KLINGONS, &
1670 REM "B3" STARBASES, & "S3" STARS ELSEWHERE.
-1680 A$="<*>":Z1=S1:Z2=S2:GOSUB8670:IFK3<1THEN1820
-1720 FORI=1TOK3:GOSUB8590:A$="+K+":Z1=R1:Z2=R2
-1780 GOSUB8670:K(I,1)=R1:K(I,2)=R2:K(I,3)=S9*(0.5+RND(1)):NEXTI
-1820 IFB3<1THEN1910
-1880 GOSUB8590:A$=">!<":Z1=R1:B4=R1:Z2=R2:B5=R2:GOSUB8670
-1910 FORI=1TOS3:GOSUB8590:A$=" * ":Z1=R1:Z2=R2:GOSUB8670:NEXTI
-1980 GOSUB6430
-1990 IFS+E>10THENIFE>10ORD(7)=0THEN2060
-2020 PRINT:PRINT"** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP IN "
-2030 PRINT"SPACE":PRINT"YOU HAVE INSUFFICIENT MANEUVERING ENERGY,";
-2040 PRINT" AND SHIELD CONTROL":PRINT"IS PRESENTLY INCAPABLE OF CROSS";
-2050 PRINT"-CIRCUITING TO ENGINE ROOM!!":GOTO6220
+1680 A$="<*>":Z1=S1:Z2=S2:GOSUB 8670:IF K3<1 THEN 1820
+1720 FOR I=1 TO K3:GOSUB 8590:A$="+K+":Z1=R1:Z2=R2
+1780 GOSUB 8670:K(I,1)=R1:K(I,2)=R2:K(I,3)=S9*(0.5+RND(1)):NEXT I
+1820 IF B3<1 THEN 1910
+1880 GOSUB 8590:A$=">!<":Z1=R1:B4=R1:Z2=R2:B5=R2:GOSUB 8670
+1910 FOR I=1 TO S3:GOSUB 8590:A$=" * ":Z1=R1:Z2=R2:GOSUB 8670:NEXT I
+1980 GOSUB 6430
+1990 IF S+E>10 THEN IF E>10 OR D(7)=0 THEN 2060
+2020 PRINT:PRINT "** FATAL ERROR ** YOU'VE JUST STRANDED YOUR SHIP IN "
+2030 PRINT "SPACE":PRINT "YOU HAVE INSUFFICIENT MANEUVERING ENERGY,";
+2040 PRINT " AND SHIELD CONTROL":PRINT "IS PRESENTLY INCAPABLE OF CROSS";
+2050 PRINT "-CIRCUITING TO ENGINE ROOM!!":GOTO 6220
2060 INPUT"COMMAND";A$
-2080 FORI=1TO9:IFLEFT$(A$,3)<>MID$(A1$,3*I-2,3)THEN2160
-2140 ONIGOTO2300,1980,4000,4260,4700,5530,5690,7290,6270
-2160 NEXTI:PRINT"ENTER ONE OF THE FOLLOWING:"
-2180 PRINT" NAV (TO SET COURSE)"
-2190 PRINT" SRS (FOR SHORT RANGE SENSOR SCAN)"
-2200 PRINT" LRS (FOR LONG RANGE SENSOR SCAN)"
-2210 PRINT" PHA (TO FIRE PHASERS)"
-2220 PRINT" TOR (TO FIRE PHOTON TORPEDOES)"
-2230 PRINT" SHE (TO RAISE OR LOWER SHIELDS)"
-2240 PRINT" DAM (FOR DAMAGE CONTROL REPORTS)"
-2250 PRINT" COM (TO CALL ON LIBRARY-COMPUTER)"
-2260 PRINT" XXX (TO RESIGN YOUR COMMAND)":PRINT:GOTO 1990
+2080 FOR I=1 TO 9:IF LEFT$(A$,3)<>MID$(A1$,3*I-2,3) THEN 2160
+2140 ON I GOTO 2300,1980,4000,4260,4700,5530,5690,7290,6270
+2160 NEXT I:PRINT "ENTER ONE OF THE FOLLOWING:"
+2180 PRINT " NAV (TO SET COURSE)"
+2190 PRINT " SRS (FOR SHORT RANGE SENSOR SCAN)"
+2200 PRINT " LRS (FOR LONG RANGE SENSOR SCAN)"
+2210 PRINT " PHA (TO FIRE PHASERS)"
+2220 PRINT " TOR (TO FIRE PHOTON TORPEDOES)"
+2230 PRINT " SHE (TO RAISE OR LOWER SHIELDS)"
+2240 PRINT " DAM (FOR DAMAGE CONTROL REPORTS)"
+2250 PRINT " COM (TO CALL ON LIBRARY-COMPUTER)"
+2260 PRINT " XXX (TO RESIGN YOUR COMMAND)":PRINT:GOTO 1990
2290 REM COURSE CONTROL BEGINS HERE
-2300 INPUT"COURSE (0-9)";C1:IFC1=9THENC1=1
-2310 IFC1>=1ANDC1<9THEN2350
-2330 PRINT" LT. SULU REPORTS, 'INCORRECT COURSE DATA, SIR!'":GOTO1990
-2350 X$="8":IFD(1)<0THENX$="0.2"
-2360 PRINT"WARP FACTOR (0-";X$;")";:INPUTW1:IFD(1)<0ANDW1>.2THEN2470
-2380 IFW1>0ANDW1<=8THEN2490
-2390 IFW1=0THEN1990
-2420 PRINT" CHIEF ENGINEER SCOTT REPORTS 'THE ENGINES WON'T TAKE";
-2430 PRINT" WARP ";W1;"!'":GOTO1990
-2470 PRINT"WARP ENGINES ARE DAMAGED. MAXIUM SPEED = WARP 0.2":GOTO1990
-2490 N=INT(W1*8+.5):IFE-N>=0THEN2590
-2500 PRINT"ENGINEERING REPORTS 'INSUFFICIENT ENERGY AVAILABLE"
-2510 PRINT" FOR MANEUVERING AT WARP";W1;"!'"
-2530 IFS=1 AND C1<9 THEN 2350
+2330 PRINT " LT. SULU REPORTS, 'INCORRECT COURSE DATA, SIR!'":GOTO 1990
+2350 X$="8":IF D(1)<0 THEN X$="0.2"
+2360 PRINT "WARP FACTOR (0-";X$;")";:INPUT W1:IF D(1)<0 AND W1>.2 THEN 2470
+2380 IF W1>0 AND W1<=8 THEN 2490
+2390 IF W1=0 THEN 1990
+2420 PRINT " CHIEF ENGINEER SCOTT REPORTS 'THE ENGINES WON'T TAKE";
+2430 PRINT " WARP ";W1;"!'":GOTO 1990
+2470 PRINT "WARP ENGINES ARE DAMAGED. MAXIUM SPEED = WARP 0.2":GOTO 1990
+2490 N=INT(W1*8+.5):IF E-N>=0 THEN 2590
+2500 PRINT "ENGINEERING REPORTS 'INSUFFICIENT ENERGY AVAILABLE"
+2510 PRINT " FOR MANEUVERING AT WARP";W1;"!'"
+2530 IF S=1THEND6=1
-2770 FORI=1TO8:IFD(I)>=0THEN2880
-2790 D(I)=D(I)+D6:IFD(I)>-.1ANDD(I)<0THEND(I)=-.1:GOTO2880
-2800 IFD(I)<0THEN2880
-2810 IFD1<>1THEND1=1:PRINT"DAMAGE CONTROL REPORT: ";
-2840 PRINTTAB(8);:R1=I:GOSUB8790:PRINTG2$;" REPAIR COMPLETED."
-2880 NEXTI:IFRND(1)>.2THEN3070
-2910 R1=FNR(1):IFRND(1)>=.6THEN3000
-2930 D(R1)=D(R1)-(RND(1)*5+1):PRINT"DAMAGE CONTROL REPORT: ";
-2960 GOSUB8790:PRINTG2$;" DAMAGED":PRINT:GOTO3070
-3000 D(R1)=D(R1)+RND(1)*3+1:PRINT"DAMAGE CONTROL REPORT: ";
-3030 GOSUB8790:PRINTG2$;" STATE OF REPAIR IMPROVED":PRINT
+2590 FOR I=1 TO K3:IF K(I,3)=0 THEN 2700
+2610 A$=" ":Z1=K(I,1):Z2=K(I,2):GOSUB 8670:GOSUB 8590
+2660 K(I,1)=Z1:K(I,2)=Z2:A$="+K+":GOSUB 8670
+2700 NEXT I:GOSUB 6000:D1=0:D6=W1:IF W1>=1 THEN D6=1
+2770 FOR I=1 TO 8:IF D(I)>=0 THEN 2880
+2790 D(I)=D(I)+D6:IF D(I)>-.1 AND D(I)<0 THEN D(I)=-.1:GOTO 2880
+2800 IF D(I)<0 THEN 2880
+2810 IF D1<>1 THEN D1=1:PRINT "DAMAGE CONTROL REPORT: ";
+2840 PRINT TAB(8);:R1=I:GOSUB 8790:PRINT G2$;" REPAIR COMPLETED."
+2880 NEXT I:IF RND(1)>.2 THEN 3070
+2910 R1=FNR(1):IF RND(1)>=.6 THEN 3000
+2930 D(R1)=D(R1)-(RND(1)*5+1):PRINT "DAMAGE CONTROL REPORT: ";
+2960 GOSUB 8790:PRINT G2$;" DAMAGED":PRINT:GOTO 3070
+3000 D(R1)=D(R1)+RND(1)*3+1:PRINT "DAMAGE CONTROL REPORT: ";
+3030 GOSUB 8790:PRINT G2$;" STATE OF REPAIR IMPROVED":PRINT
3060 REM BEGIN MOVING STARSHIP
-3070 A$=" ":Z1=INT(S1):Z2=INT(S2):GOSUB8670
+3070 A$=" ":Z1=INT(S1):Z2=INT(S2):GOSUB 8670
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
-3170 FORI=1TON:S1=S1+X1:S2=S2+X2:IFS1<1ORS1>=9ORS2<1ORS2>=9THEN3500
-3240 S8=INT(S1)*24+INT(S2)*3-26:IFMID$(Q$,S8,2)=" "THEN3360
-3320 S1=INT(S1-X1):S2=INT(S2-X2):PRINT"WARP ENGINES SHUT DOWN AT ";
-3350 PRINT"SECTOR";S1;",";S2;"DUE TO BAD NAVAGATION":GOTO3370
-3360 NEXTI:S1=INT(S1):S2=INT(S2)
-3370 A$="<*>":Z1=INT(S1):Z2=INT(S2):GOSUB8670:GOSUB3910:T8=1
-3430 IFW1<1THENT8=.1*INT(10*W1)
-3450 T=T+T8:IFT>T0+T9THEN6220
+3170 FOR I=1 TO N:S1=S1+X1:S2=S2+X2:IF S1<1 OR S1>=9 OR S2<1 OR S2>=9 THEN 3500
+3240 S8=INT(S1)*24+INT(S2)*3-26:IF MID$(Q$,S8,2)=" " THEN 3360
+3320 S1=INT(S1-X1):S2=INT(S2-X2):PRINT "WARP ENGINES SHUT DOWN AT ";
+3350 PRINT "SECTOR";S1;",";S2;"DUE TO BAD NAVAGATION":GOTO 3370
+3360 NEXT I:S1=INT(S1):S2=INT(S2)
+3370 A$="<*>":Z1=INT(S1):Z2=INT(S2):GOSUB 8670:GOSUB 3910:T8=1
+3430 IF W1<1 THEN T8=.1*INT(10*W1)
+3450 T=T+T8:IF T>T0+T9 THEN 6220
3470 REM SEE IF DOCKED, THEN GET COMMAND
-3480 GOTO1980
+3480 GOTO 1980
3490 REM EXCEEDED QUADRANT LIMITS
3500 X=8*Q1+X+N*X1:Y=8*Q2+Y+N*X2:Q1=INT(X/8):Q2=INT(Y/8):S1=INT(X-Q1*8)
-3550 S2=INT(Y-Q2*8):IFS1=0THENQ1=Q1-1:S1=8
-3590 IFS2=0THENQ2=Q2-1:S2=8
-3620 X5=0:IFQ1<1THENX5=1:Q1=1:S1=1
-3670 IFQ1>8THENX5=1:Q1=8:S1=8
-3710 IFQ2<1THENX5=1:Q2=1:S2=1
-3750 IFQ2>8THENX5=1:Q2=8:S2=8
-3790 IFX5=0THEN3860
-3800 PRINT"LT. UHURA REPORTS MESSAGE FROM STARFLEET COMMAND:"
-3810 PRINT" 'PERMISSION TO ATTEMPT CROSSING OF GALACTIC PERIMETER"
-3820 PRINT" IS HEREBY *DENIED*. SHUT DOWN YOUR ENGINES.'"
-3830 PRINT"CHIEF ENGINEER SCOTT REPORTS 'WARP ENGINES SHUT DOWN"
-3840 PRINT" AT SECTOR";S1;",";S2;"OF QUADRANT";Q1;",";Q2;".'"
-3850 IFT>T0+T9THEN6220
-3860 IF8*Q1+Q2=8*Q4+Q5THEN3370
-3870 T=T+1:GOSUB3910:GOTO1320
+3550 S2=INT(Y-Q2*8):IF S1=0 THEN Q1=Q1-1:S1=8
+3590 IF S2=0 THEN Q2=Q2-1:S2=8
+3620 X5=0:IF Q1<1 THEN X5=1:Q1=1:S1=1
+3670 IF Q1>8 THEN X5=1:Q1=8:S1=8
+3710 IF Q2<1 THEN X5=1:Q2=1:S2=1
+3750 IF Q2>8 THEN X5=1:Q2=8:S2=8
+3790 IF X5=0 THEN 3860
+3800 PRINT "LT. UHURA REPORTS MESSAGE FROM STARFLEET COMMAND:"
+3810 PRINT " 'PERMISSION TO ATTEMPT CROSSING OF GALACTIC PERIMETER"
+3820 PRINT " IS HEREBY *DENIED*. SHUT DOWN YOUR ENGINES.'"
+3830 PRINT "CHIEF ENGINEER SCOTT REPORTS 'WARP ENGINES SHUT DOWN"
+3840 PRINT " AT SECTOR";S1;",";S2;"OF QUADRANT";Q1;",";Q2;".'"
+3850 IF T>T0+T9 THEN 6220
+3860 IF 8*Q1+Q2=8*Q4+Q5 THEN 3370
+3870 T=T+1:GOSUB 3910:GOTO 1320
3900 REM MANEUVER ENERGY S/R **
-3910 E=E-N-10:IFE>=0THENRETURN
-3930 PRINT"SHIELD CONTROL SUPPLIES ENERGY TO COMPLETE THE MANEUVER."
-3940 S=S+E:E=0:IFS<=0THENS=0
+3910 E=E-N-10:IF E>=0 THEN RETURN
+3930 PRINT "SHIELD CONTROL SUPPLIES ENERGY TO COMPLETE THE MANEUVER."
+3940 S=S+E:E=0:IF S<=0 THEN S=0
3980 RETURN
3990 REM LONG RANGE SENSOR SCAN CODE
-4000 IFD(3)<0THENPRINT"LONG RANGE SENSORS ARE INOPERABLE":GOTO1990
-4030 PRINT"LONG RANGE SCAN FOR QUADRANT";Q1;",";Q2
-4040 O1$="-------------------":PRINTO1$
-4060 FORI=Q1-1TOQ1+1:N(1)=-1:N(2)=-2:N(3)=-3:FORJ=Q2-1TOQ2+1
-4120 IFI>0ANDI<9ANDJ>0ANDJ<9THENN(J-Q2+2)=G(I,J):Z(I,J)=G(I,J)
-4180 NEXTJ:FORL=1TO3:PRINT": ";:IFN(L)<0THENPRINT"*** ";:GOTO4230
-4210 PRINTRIGHT$(STR$(N(L)+1000),3);" ";
-4230 NEXTL:PRINT":":PRINTO1$:NEXTI:GOTO1990
+4000 IF D(3)<0 THEN PRINT "LONG RANGE SENSORS ARE INOPERABLE":GOTO 1990
+4030 PRINT "LONG RANGE SCAN FOR QUADRANT";Q1;",";Q2
+4040 O1$="-------------------":PRINT O1$
+4060 FOR I=Q1-1TOQ1+1:N(1)=-1:N(2)=-2:N(3)=-3:FOR J=Q2-1TOQ2+1
+4120 IF I>0 AND I<9 AND J>0 AND J<9 THEN N(J-Q2+2)=G(I,J):Z(I,J)=G(I,J)
+4180 NEXT J:FOR L=1 TO 3:PRINT ": ";:IF N(L)<0 THEN PRINT "*** ";:GOTO 4230
+4210 PRINT RIGHT$(STR$(N(L)+1000),3);" ";
+4230 NEXT L:PRINT ":":PRINT O1$:NEXT I:GOTO 1990
4250 REM PHASER CONTROL CODE BEGINS HERE
-4260 IFD(4)<0THENPRINT"PHASERS INOPERATIVE":GOTO1990
-4265 IFK3>0THEN4330
-4270 PRINT"SCIENCE OFFICER SPOCK REPORTS 'SENSORS SHOW NO ENEMY SHIPS"
-4280 PRINT" IN THIS QUADRANT'":GOTO1990
-4330 IFD(8)<0THENPRINT"COMPUTER FAILURE HAMPERS ACCURACY"
-4350 PRINT"PHASERS LOCKED ON TARGET; ";
-4360 PRINT"ENERGY AVAILABLE =";E;"UNITS"
-4370 INPUT"NUMBER OF UNITS TO FIRE";X:IFX<=0THEN1990
-4400 IFE-X<0THEN4360
-4410 E=E-X:IFD(7)<0THENX=X*RND(1)
-4450 H1=INT(X/K3):FORI=1TO3:IFK(I,3)<=0THEN4670
-4480 H=INT((H1/FND(0))*(RND(1)+2)):IFH>.15*K(I,3)THEN4530
-4500 PRINT"SENSORS SHOW NO DAMAGE TO ENEMY AT ";K(I,1);",";K(I,2):GOTO4670
-4530 K(I,3)=K(I,3)-H:PRINTH;"UNIT HIT ON KLINGON AT SECTOR";K(I,1);",";
-4550 PRINTK(I,2):IFK(I,3)<=0THENPRINT"*** KLINGON DESTROYED ***":GOTO4580
-4560 PRINT" (SENSORS SHOW";K(I,3);"UNITS REMAINING)":GOTO4670
-4580 K3=K3-1:K9=K9-1:Z1=K(I,1):Z2=K(I,2):A$=" ":GOSUB8670
-4650 K(I,3)=0:G(Q1,Q2)=G(Q1,Q2)-100:Z(Q1,Q2)=G(Q1,Q2):IFK9<=0THEN6370
-4670 NEXTI:GOSUB6000:GOTO1990
+4260 IF D(4)<0 THEN PRINT "PHASERS INOPERATIVE":GOTO 1990
+4265 IF K3>0 THEN 4330
+4270 PRINT "SCIENCE OFFICER SPOCK REPORTS 'SENSORS SHOW NO ENEMY SHIPS"
+4280 PRINT " IN THIS QUADRANT'":GOTO 1990
+4330 IF D(8)<0 THEN PRINT "COMPUTER FAILURE HAMPERS ACCURACY"
+4350 PRINT "PHASERS LOCKED ON TARGET; ";
+4360 PRINT "ENERGY AVAILABLE =";E;"UNITS"
+4370 INPUT"NUMBER OF UNITS TO FIRE";X:IF X<=0 THEN 1990
+4400 IF E-X<0 THEN 4360
+4410 E=E-X:IF D(7)<0 THEN X=X*RND(1)
+4450 H1=INT(X/K3):FOR I=1TO3:IF K(I,3)<=0 THEN 4670
+4480 H=INT((H1/FND(0))*(RND(1)+2)):IF H>.15*K(I,3) THEN 4530
+4500 PRINT "SENSORS SHOW NO DAMAGE TO ENEMY AT ";K(I,1);",";K(I,2):GOTO 4670
+4530 K(I,3)=K(I,3)-H:PRINT H;"UNIT HIT ON KLINGON AT SECTOR";K(I,1);",";
+4550 PRINT K(I,2):IF K(I,3)<=0 THEN PRINT "*** KLINGON DESTROYED ***":GOTO 4580
+4560 PRINT " (SENSORS SHOW";K(I,3);"UNITS REMAINING)":GOTO 4670
+4580 K3=K3-1:K9=K9-1:Z1=K(I,1):Z2=K(I,2):A$=" ":GOSUB 8670
+4650 K(I,3)=0:G(Q1,Q2)=G(Q1,Q2)-100:Z(Q1,Q2)=G(Q1,Q2):IF K9<=0 THEN 6370
+4670 NEXT I:GOSUB 6000:GOTO 1990
4690 REM PHOTON TORPEDO CODE BEGINS HERE
-4700 IFP<=0THENPRINT"ALL PHOTON TORPEDOES EXPENDED":GOTO 1990
-4730 IFD(5)<0THENPRINT"PHOTON TUBES ARE NOT OPERATIONAL":GOTO1990
-4760 INPUT"PHOTON TORPEDO COURSE (1-9)";C1:IFC1=9THENC1=1
-4780 IFC1>=1ANDC1<9THEN4850
-4790 PRINT"ENSIGN CHEKOV REPORTS, 'INCORRECT COURSE DATA, SIR!'"
-4800 GOTO1990
+4700 IF P<=0 THEN PRINT "ALL PHOTON TORPEDOES EXPENDED":GOTO 1990
+4730 IF D(5)<0 THEN PRINT "PHOTON TUBES ARE NOT OPERATIONAL":GOTO 1990
+4760 INPUT"PHOTON TORPEDO COURSE (1-9)";C1:IF C1=9 THEN C1=1
+4780 IF C1>=1ANDC1<9 THEN 4850
+4790 PRINT "ENSIGN CHEKOV REPORTS, 'INCORRECT COURSE DATA, SIR!'"
+4800 GOTO 1990
4850 X1=C(C1,1)+(C(C1+1,1)-C(C1,1))*(C1-INT(C1)):E=E-2:P=P-1
4860 X2=C(C1,2)+(C(C1+1,2)-C(C1,2))*(C1-INT(C1)):X=S1:Y=S2
-4910 PRINT"TORPEDO TRACK:"
+4910 PRINT "TORPEDO TRACK:"
4920 X=X+X1:Y=Y+X2:X3=INT(X+.5):Y3=INT(Y+.5)
-4960 IFX3<1ORX3>8ORY3<1ORY3>8THEN5490
-5000 PRINT" ";X3;",";Y3:A$=" ":Z1=X:Z2=Y:GOSUB8830
-5050 IFZ3<>0THEN4920
-5060 A$="+K+":Z1=X:Z2=Y:GOSUB8830:IFZ3=0THEN5210
-5110 PRINT"*** KLINGON DESTROYED ***":K3=K3-1:K9=K9-1:IFK9<=0THEN6370
-5150 FORI=1TO3:IFX3=K(I,1)ANDY3=K(I,2)THEN5190
-5180 NEXTI:I=3
-5190 K(I,3)=0:GOTO5430
-5210 A$=" * ":Z1=X:Z2=Y:GOSUB8830:IFZ3=0THEN5280
-5260 PRINT"STAR AT";X3;",";Y3;"ABSORBED TORPEDO ENERGY.":GOSUB6000:GOTO1990
-5280 A$=">!<":Z1=X:Z2=Y:GOSUB8830:IFZ3=0THEN4760
-5330 PRINT"*** STARBASE DESTROYED ***":B3=B3-1:B9=B9-1
-5360 IFB9>0ORK9>T-T0-T9THEN5400
-5370 PRINT"THAT DOES IT, CAPTAIN!! YOU ARE HEREBY RELIEVED OF COMMAND"
-5380 PRINT"AND SENTENCED TO 99 STARDATES AT HARD LABOR ON CYGNUS 12!!"
+4960 IF X3<1 OR X3>8 OR Y3<1 OR Y3>8 THEN 5490
+5000 PRINT " ";X3;",";Y3:A$=" ":Z1=X:Z2=Y:GOSUB 8830
+5050 IF Z3<>0 THEN 4920
+5060 A$="+K+":Z1=X:Z2=Y:GOSUB 8830:IF Z3=0 THEN 5210
+5110 PRINT "*** KLINGON DESTROYED ***":K3=K3-1:K9=K9-1:IF K9<=0 THEN 6370
+5150 FOR I=1TO3:IF X3=K(I,1) AND Y3=K(I,2) THEN 5190
+5180 NEXT I:I=3
+5190 K(I,3)=0:GOTO 5430
+5210 A$=" * ":Z1=X:Z2=Y:GOSUB 8830:IF Z3=0 THEN 5280
+5260 PRINT "STAR AT";X3;",";Y3;"ABSORBED TORPEDO ENERGY.":GOSUB 6000:GOTO 1990
+5280 A$=">!<":Z1=X:Z2=Y:GOSUB 8830:IF Z3=0 THEN 4760
+5330 PRINT "*** STARBASE DESTROYED ***":B3=B3-1:B9=B9-1
+5360 IF B9>0 OR K9>T-T0-T9 THEN 5400
+5370 PRINT "THAT DOES IT, CAPTAIN!! YOU ARE HEREBY RELIEVED OF COMMAND"
+5380 PRINT "AND SENTENCED TO 99 STARDATES AT HARD LABOR ON CYGNUS 12!!"
5390 GOTO 6270
-5400 PRINT"STARFLEET COMMAND REVIEWING YOUR RECORD TO CONSIDER"
-5410 PRINT"COURT MARTIAL!":D0=0
-5430 Z1=X:Z2=Y:A$=" ":GOSUB8670
-5470 G(Q1,Q2)=K3*100+B3*10+S3:Z(Q1,Q2)=G(Q1,Q2):GOSUB6000:GOTO1990
-5490 PRINT"TORPEDO MISSED":GOSUB6000:GOTO1990
+5400 PRINT "STARFLEET COMMAND REVIEWING YOUR RECORD TO CONSIDER"
+5410 PRINT "COURT MARTIAL!":D0=0
+5430 Z1=X:Z2=Y:A$=" ":GOSUB 8670
+5470 G(Q1,Q2)=K3*100+B3*10+S3:Z(Q1,Q2)=G(Q1,Q2):GOSUB 6000:GOTO 1990
+5490 PRINT "TORPEDO MISSED":GOSUB 6000:GOTO 1990
5520 REM SHIELD CONTROL
-5530 IFD(7)<0THENPRINT"SHIELD CONTROL INOPERABLE":GOTO1990
-5560 PRINT"ENERGY AVAILABLE =";E+S;:INPUT"NUMBER OF UNITS TO SHIELDS";X
-5580 IFX<0ORS=XTHENPRINT"":GOTO1990
-5590 IFX<=E+STHEN5630
-5600 PRINT"SHIELD CONTROL REPORTS 'THIS IS NOT THE FEDERATION TREASURY.'"
-5610 PRINT"":GOTO1990
-5630 E=E+S-X:S=X:PRINT"DEFLECTOR CONTROL ROOM REPORT:"
-5660 PRINT" 'SHIELDS NOW AT";INT(S);"UNITS PER YOUR COMMAND.'":GOTO1990
+5530 IF D(7)<0 THEN PRINT "SHIELD CONTROL INOPERABLE":GOTO 1990
+5560 PRINT "ENERGY AVAILABLE =";E+S;:INPUT"NUMBER OF UNITS TO SHIELDS";X
+5580 IF X<0 OR S=X THEN PRINT "":GOTO 1990
+5590 IF X<=E+S THEN 5630
+5600 PRINT "SHIELD CONTROL REPORTS 'THIS IS NOT THE FEDERATION TREASURY.'"
+5610 PRINT "":GOTO 1990
+5630 E=E+S-X:S=X:PRINT "DEFLECTOR CONTROL ROOM REPORT:"
+5660 PRINT " 'SHIELDS NOW AT";INT(S);"UNITS PER YOUR COMMAND.'":GOTO 1990
5680 REM DAMAGE CONTROL
-5690 IFD(6)>=0THEN5910
-5700 PRINT"DAMAGE CONTROL REPORT NOT AVAILABLE":IFD0=0THEN1990
-5720 D3=0:FORI=1TO8:IFD(I)<0THEND3=D3+.1
-5760 NEXTI:IFD3=0THEN1990
-5780 PRINT:D3=D3+D4:IFD3>=1THEND3=.9
-5810 PRINT"TECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;"
-5820 PRINT"ESTIMATED TIME TO REPAIR:";.01*INT(100*D3);"STARDATES"
+5690 IF D(6)>=0 THEN 5910
+5700 PRINT "DAMAGE CONTROL REPORT NOT AVAILABLE":IF D0=0 THEN 1990
+5720 D3=0:FOR I=1TO8:IF D(I)<0 THEN D3=D3+.1
+5760 NEXT I:IF D3=0 THEN 1990
+5780 PRINT:D3=D3+D4:IF D3>=1 THEN D3=.9
+5810 PRINT "TECHNICIANS STANDING BY TO EFFECT REPAIRS TO YOUR SHIP;"
+5820 PRINT "ESTIMATED TIME TO REPAIR:";.01*INT(100*D3);"STARDATES"
5840 INPUT "WILL YOU AUTHORIZE THE REPAIR ORDER (Y/N)";A$
-5860 IFA$<>"Y"THEN 1990
-5870 FORI=1TO8:IFD(I)<0THEND(I)=0
-5890 NEXTI:T=T+D3+.1
-5910 PRINT:PRINT"DEVICE STATE OF REPAIR":FORR1=1TO8
-5920 GOSUB8790:PRINTG2$;LEFT$(Z$,25-LEN(G2$));INT(D(R1)*100)*.01
-5950 NEXTR1:PRINT:IFD0<>0THEN5720
+5860 IF A$<>"Y" THEN 1990
+5870 FOR I=1TO8:IF D(I)<0 THEN D(I)=0
+5890 NEXT I:T=T+D3+.1
+5910 PRINT:PRINT "DEVICE STATE OF REPAIR":FOR R1=1TO8
+5920 GOSUB 8790:PRINT G2$;LEFT$(Z$,25-LEN(G2$));INT(D(R1)*100)*.01
+5950 NEXT R1:PRINT:IF D0<>0 THEN 5720
5980 GOTO 1990
5990 REM KLINGONS SHOOTING
-6000 IFK3<=0THENRETURN
-6010 IFD0<>0THENPRINT"STARBASE SHIELDS PROTECT THE ENTERPRISE":RETURN
-6040 FORI=1TO3:IFK(I,3)<=0THEN6200
+6000 IF K3<=0 THEN RETURN
+6010 IF D0<>0 THEN PRINT "STARBASE SHIELDS PROTECT THE ENTERPRISE":RETURN
+6040 FOR I=1TO3:IF K(I,3)<=0 THEN 6200
6060 H=INT((K(I,3)/FND(1))*(2+RND(1))):S=S-H:K(I,3)=K(I,3)/(3+RND(0))
-6080 PRINTH;"UNIT HIT ON ENTERPRISE FROM SECTOR";K(I,1);",";K(I,2)
-6090 IFS<=0THEN6240
-6100 PRINT" ":IFH<20THEN6200
-6120 IFRND(1)>.6ORH/S<=.02THEN6200
-6140 R1=FNR(1):D(R1)=D(R1)-H/S-.5*RND(1):GOSUB8790
-6170 PRINT"DAMAGE CONTROL REPORTS ";G2$;" DAMAGED BY THE HIT'"
-6200 NEXTI:RETURN
+6080 PRINT H;"UNIT HIT ON ENTERPRISE FROM SECTOR";K(I,1);",";K(I,2)
+6090 IF S<=0 THEN 6240
+6100 PRINT " ":IF H<20 THEN 6200
+6120 IF RND(1)>.6 OR H/S<=.02 THEN 6200
+6140 R1=FNR(1):D(R1)=D(R1)-H/S-.5*RND(1):GOSUB 8790
+6170 PRINT "DAMAGE CONTROL REPORTS ";G2$;" DAMAGED BY THE HIT'"
+6200 NEXT I:RETURN
6210 REM END OF GAME
-6220 PRINT"IT IS STARDATE";T:GOTO 6270
-6240 PRINT:PRINT"THE ENTERPRISE HAS BEEN DESTROYED. THEN FEDERATION ";
-6250 PRINT"WILL BE CONQUERED":GOTO 6220
-6270 PRINT"THERE WERE";K9;"KLINGON BATTLE CRUISERS LEFT AT"
-6280 PRINT"THE END OF YOUR MISSION."
-6290 PRINT:PRINT:IFB9=0THEN6360
-6310 PRINT"THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER"
-6320 PRINT"FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,"
-6330 INPUT"LET HIM STEP FORWARD AND ENTER 'AYE'";A$:IFA$="AYE"THEN10
+6220 PRINT "IT IS STARDATE";T:GOTO 6270
+6240 PRINT:PRINT "THE ENTERPRISE HAS BEEN DESTROYED. THEN FEDERATION ";
+6250 PRINT "WILL BE CONQUERED":GOTO 6220
+6270 PRINT "THERE WERE";K9;"KLINGON BATTLE CRUISERS LEFT AT"
+6280 PRINT "THE END OF YOUR MISSION."
+6290 PRINT:PRINT:IF B9=0 THEN 6360
+6310 PRINT "THE FEDERATION IS IN NEED OF A NEW STARSHIP COMMANDER"
+6320 PRINT "FOR A SIMILAR MISSION -- IF THERE IS A VOLUNTEER,"
+6330 INPUT"LET HIM STEP FORWARD AND ENTER 'AYE'";A$:IF A$="AYE" THEN 10
6360 END
-6370 PRINT"CONGRULATION, CAPTAIN! THEN LAST KLINGON BATTLE CRUISER"
-6380 PRINT"MENACING THE FDERATION HAS BEEN DESTROYED.":PRINT
-6400 PRINT"YOUR EFFICIENCY RATING IS";1000*(K7/(T-T0))^2:GOTO6290
+6370 PRINT "CONGRULATION, CAPTAIN! THEN LAST KLINGON BATTLE CRUISER"
+6380 PRINT "MENACING THE FDERATION HAS BEEN DESTROYED.":PRINT
+6400 PRINT "YOUR EFFICIENCY RATING IS";1000*(K7/(T-T0))^2:GOTO 6290
6420 REM SHORT RANGE SENSOR SCAN & STARTUP SUBROUTINE
-6430 FORI=S1-1TOS1+1:FORJ=S2-1TOS2+1
-6450 IFINT(I+.5)<1ORINT(I+.5)>8ORINT(J+.5)<1ORINT(J+.5)>8THEN6540
-6490 A$=">!<":Z1=I:Z2=J:GOSUB8830:IFZ3=1THEN6580
-6540 NEXTJ:NEXTI:D0=0:GOTO6650
+6430 FOR I=S1-1TOS1+1:FOR J=S2-1 TO S2+1
+6450 IF INT(I+.5)<1 OR INT(I+.5)>8 OR INT(J+.5)<1 OR INT(J+.5)>8 THEN 6540
+6490 A$=">!<":Z1=I:Z2=J:GOSUB 8830:IF Z3=1 THEN 6580
+6540 NEXT J:NEXT I:D0=0:GOTO 6650
6580 D0=1:C$="DOCKED":E=E0:P=P0
-6620 PRINT"SHIELDS DROPPED FOR DOCKING PURPOSES":S=0:GOTO6720
-6650 IFK3>0THENC$="*RED*":GOTO6720
-6660 C$="GREEN":IFE=0THEN6770
-6730 PRINT:PRINT"*** SHORT RANGE SENSORS ARE OUT ***":PRINT:RETURN
-6770 O1$="---------------------------------":PRINTO1$:FORI=1TO8
-6820 FORJ=(I-1)*24+1TO(I-1)*24+22STEP3:PRINT" ";MID$(Q$,J,3);:NEXTJ
-6830 ONIGOTO6850,6900,6960,7020,7070,7120,7180,7240
-6850 PRINT" STARDATE ";INT(T*10)*.1:GOTO7260
-6900 PRINT" CONDITION ";C$:GOTO7260
-6960 PRINT" QUADRANT ";Q1;",";Q2:GOTO7260
-7020 PRINT" SECTOR ";S1;",";S2:GOTO7260
-7070 PRINT" PHOTON TORPEDOES ";INT(P):GOTO7260
-7120 PRINT" TOTAL ENERGY ";INT(E+S):GOTO7260
-7180 PRINT" SHIELDS ";INT(S):GOTO7260
-7240 PRINT" KLINGONS REMAINING";INT(K9)
-7260 NEXTI:PRINTO1$:RETURN
+6620 PRINT "SHIELDS DROPPED FOR DOCKING PURPOSES":S=0:GOTO 6720
+6650 IF K3>0 THEN C$="*RED*":GOTO 6720
+6660 C$="GREEN":IF E=0 THEN 6770
+6730 PRINT:PRINT "*** SHORT RANGE SENSORS ARE OUT ***":PRINT:RETURN
+6770 O1$="---------------------------------":PRINT O1$:FOR I=1 TO 8
+6820 FOR J=(I-1)*24+1 TO (I-1)*24+22STEP3:PRINT " ";MID$(Q$,J,3);:NEXT J
+6830 ON I GOTO 6850,6900,6960,7020,7070,7120,7180,7240
+6850 PRINT " STARDATE ";INT(T*10)*.1:GOTO 7260
+6900 PRINT " CONDITION ";C$:GOTO 7260
+6960 PRINT " QUADRANT ";Q1;",";Q2:GOTO 7260
+7020 PRINT " SECTOR ";S1;",";S2:GOTO 7260
+7070 PRINT " PHOTON TORPEDOES ";INT(P):GOTO 7260
+7120 PRINT " TOTAL ENERGY ";INT(E+S):GOTO 7260
+7180 PRINT " SHIELDS ";INT(S):GOTO 7260
+7240 PRINT " KLINGONS REMAINING";INT(K9)
+7260 NEXT I:PRINT O1$:RETURN
7280 REM LIBRARY COMPUTER CODE
-7290 IFD(8)<0THENPRINT"COMPUTER DISABLED":GOTO1990
-7320 INPUT"COMPUTER ACTIVE AND AWAITING COMMAND";A:IFA<0THEN1990
-7350 PRINT:H8=1:ONA+1GOTO7540,7900,8070,8500,8150,7400
-7360 PRINT"FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:"
-7370 PRINT" 0 = CUMULATIVE GALACTIC RECORD"
-7372 PRINT" 1 = STATUS REPORT"
-7374 PRINT" 2 = PHOTON TORPEDO DATA"
-7376 PRINT" 3 = STARBASE NAV DATA"
-7378 PRINT" 4 = DIRECTION/DISTANCE CALCULATOR"
-7380 PRINT" 5 = GALAXY 'REGION NAME' MAP":PRINT:GOTO7320
+7290 IF D(8)<0 THEN PRINT "COMPUTER DISABLED":GOTO 1990
+7320 INPUT"COMPUTER ACTIVE AND AWAITING COMMAND";A:IF A<0 THEN 1990
+7350 PRINT:H8=1:ON A+1 GOTO 7540,7900,8070,8500,8150,7400
+7360 PRINT "FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:"
+7370 PRINT " 0 = CUMULATIVE GALACTIC RECORD"
+7372 PRINT " 1 = STATUS REPORT"
+7374 PRINT " 2 = PHOTON TORPEDO DATA"
+7376 PRINT " 3 = STARBASE NAV DATA"
+7378 PRINT " 4 = DIRECTION/DISTANCE CALCULATOR"
+7380 PRINT " 5 = GALAXY 'REGION NAME' MAP":PRINT:GOTO 7320
7390 REM SETUP TO CHANGE CUM GAL RECORD TO GALAXY MAP
-7400 H8=0:G5=1:PRINT" THE GALAXY":GOTO7550
+7400 H8=0:G5=1:PRINT " THE GALAXY":GOTO 7550
7530 REM CUM GALACTIC RECORD
7540 REM INPUT"DO YOU WANT A HARDCOPY? IS THE TTY ON (Y/N)";A$
-7542 REM IFA$="Y"THENPOKE1229,2:POKE1237,3:NULL1
-7543 PRINT:PRINT" ";
-7544 PRINT"COMPUTER RECORD OF GALAXY FOR QUADRANT";Q1;",";Q2
+7542 REM IF A$="Y" THEN POKE1229,2:POKE1237,3:NULL1
+7543 PRINT:PRINT " ";
+7544 PRINT "COMPUTER RECORD OF GALAXY FOR QUADRANT";Q1;",";Q2
7546 PRINT
-7550 PRINT" 1 2 3 4 5 6 7 8"
+7550 PRINT " 1 2 3 4 5 6 7 8"
7560 O1$=" ----- ----- ----- ----- ----- ----- ----- -----"
-7570 PRINTO1$:FORI=1TO8:PRINTI;:IFH8=0THEN7740
-7630 FORJ=1TO8:PRINT" ";:IFZ(I,J)=0THENPRINT"***";:GOTO7720
-7700 PRINTRIGHT$(STR$(Z(I,J)+1000),3);
-7720 NEXTJ:GOTO7850
-7740 Z4=I:Z5=1:GOSUB9030:J0=INT(15-.5*LEN(G2$)):PRINTTAB(J0);G2$;
-7800 Z5=5:GOSUB 9030:J0=INT(39-.5*LEN(G2$)):PRINTTAB(J0);G2$;
-7850 PRINT:PRINTO1$:NEXTI:PRINT:GOTO1990
+7570 PRINT O1$:FOR I=1 TO 8:PRINT I;:IF H8=0 THEN 7740
+7630 FOR J=1 TO 8:PRINT " ";:IF Z(I,J)=0 THEN PRINT "***";:GOTO 7720
+7700 PRINT RIGHT$(STR$(Z(I,J)+1000),3);
+7720 NEXT J:GOTO 7850
+7740 Z4=I:Z5=1:GOSUB 9030:J0=INT(15-.5*LEN(G2$)):PRINT TAB(J0);G2$;
+7800 Z5=5:GOSUB 9030:J0=INT(39-.5*LEN(G2$)):PRINT TAB(J0);G2$;
+7850 PRINT:PRINT O1$:NEXT I:PRINT:GOTO 1990
7890 REM STATUS REPORT
-7900 PRINT " STATUS REPORT:":X$="":IFK9>1THENX$="S"
-7940 PRINT"KLINGON";X$;" LEFT: ";K9
-7960 PRINT"MISSION MUST BE COMPLETED IN";.1*INT((T0+T9-T)*10);"STARDATES"
-7970 X$="S":IFB9<2THENX$="":IFB9<1THEN8010
-7980 PRINT"THE FEDERATION IS MAINTAINING";B9;"STARBASE";X$;" IN THE GALAXY"
-7990 GOTO5690
-8010 PRINT"YOUR STUPIDITY HAS LEFT YOU ON YOUR ON IN"
-8020 PRINT" THE GALAXY -- YOU HAVE NO STARBASES LEFT!":GOTO5690
+7900 PRINT " STATUS REPORT:":X$="":IF K9>1 THEN X$="S"
+7940 PRINT "KLINGON";X$;" LEFT: ";K9
+7960 PRINT "MISSION MUST BE COMPLETED IN";.1*INT((T0+T9-T)*10);"STARDATES"
+7970 X$="S":IF B9<2 THEN X$="":IF B9<1 THEN 8010
+7980 PRINT "THE FEDERATION IS MAINTAINING";B9;"STARBASE";X$;" IN THE GALAXY"
+7990 GOTO 5690
+8010 PRINT "YOUR STUPIDITY HAS LEFT YOU ON YOUR ON IN"
+8020 PRINT " THE GALAXY -- YOU HAVE NO STARBASES LEFT!":GOTO 5690
8060 REM TORPEDO, BASE NAV, D/D CALCULATOR
-8070 IFK3<=0THEN4270
-8080 X$="":IFK3>1THENX$="S"
-8090 PRINT"FROM ENTERPRISE TO KLINGON BATTLE CRUSER";X$
-8100 H8=0:FORI=1TO3:IFK(I,3)<=0THEN8480
+8070 IF K3<=0 THEN 4270
+8080 X$="":IF K3>1 THEN X$="S"
+8090 PRINT "FROM ENTERPRISE TO KLINGON BATTLE CRUSER";X$
+8100 H8=0:FOR I=1 TO 3:IF K(I,3)<=0 THEN 8480
8110 W1=K(I,1):X=K(I,2)
-8120 C1=S1:A=S2:GOTO8220
-8150 PRINT"DIRECTION/DISTANCE CALCULATOR:"
-8160 PRINT"YOU ARE AT QUADRANT ";Q1;",";Q2;" SECTOR ";S1;",";S2
-8170 PRINT"PLEASE ENTER":INPUT" INITIAL COORDINATES (X,Y)";C1,A
+8120 C1=S1:A=S2:GOTO 8220
+8150 PRINT "DIRECTION/DISTANCE CALCULATOR:"
+8160 PRINT "YOU ARE AT QUADRANT ";Q1;",";Q2;" SECTOR ";S1;",";S2
+8170 PRINT "PLEASE ENTER":INPUT" INITIAL COORDINATES (X,Y)";C1,A
8200 INPUT" FINAL COORDINATES (X,Y)";W1,X
-8220 X=X-A:A=C1-W1:IFX<0THEN8350
-8250 IFA<0THEN8410
-8260 IFX>0THEN8280
-8270 IFA=0THENC1=5:GOTO8290
+8220 X=X-A:A=C1-W1:IF X<0 THEN 8350
+8250 IF A<0 THEN 8410
+8260 IF X>0 THEN 8280
+8270 IF A=0 THEN C1=5:GOTO 8290
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
+8290 IF ABS(A)<=ABS(X) THEN 8330
+8310 PRINT "DIRECTION =";C1+(((ABS(A)-ABS(X))+ABS(A))/ABS(A)):GOTO 8460
+8330 PRINT "DIRECTION =";C1+(ABS(A)/ABS(X)):GOTO 8460
+8350 IF A>0 THEN C1=3:GOTO 8420
+8360 IF X<>0 THEN C1=5:GOTO 8290
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
-8480 NEXTI:GOTO1990
-8500 IFB3<>0THENPRINT"FROM ENTERPRISE TO STARBASE:":W1=B4:X=B5:GOTO8120
-8510 PRINT"MR. SPOCK REPORTS, 'SENSORS SHOW NO STARBASES IN THIS";
-8520 PRINT" QUADRANT.'":GOTO1990
+8420 IF ABS(A)>=ABS(X) THEN 8450
+8430 PRINT "DIRECTION =";C1+(((ABS(X)-ABS(A))+ABS(X))/ABS(X)):GOTO 8460
+8450 PRINT "DIRECTION =";C1+(ABS(X)/ABS(A))
+8460 PRINT "DISTANCE =";SQR(X^2+A^2):IF H8=1 THEN 1990
+8480 NEXT I:GOTO 1990
+8500 IF B3<>0 THEN PRINT "FROM ENTERPRISE TO STARBASE:":W1=B4:X=B5:GOTO 8120
+8510 PRINT "MR. SPOCK REPORTS, 'SENSORS SHOW NO STARBASES IN THIS";
+8520 PRINT " QUADRANT.'":GOTO 1990
8580 REM FIND EMPTY PLACE IN QUADRANT (FOR THINGS)
-8590 R1=FNR(1):R2=FNR(1):A$=" ":Z1=R1:Z2=R2:GOSUB8830:IFZ3=0THEN8590
+8590 R1=FNR(1):R2=FNR(1):A$=" ":Z1=R1:Z2=R2:GOSUB 8830:IF Z3=0 THEN 8590
8600 RETURN
8660 REM INSERT IN STRING ARRAY FOR QUADRANT
8670 S8=INT(Z2-.5)*3+INT(Z1-.5)*24+1
-8675 IF LEN(A$)<>3THEN PRINT"ERROR":STOP
-8680 IFS8=1THENQ$=A$+RIGHT$(Q$,189):RETURN
-8690 IFS8=190THENQ$=LEFT$(Q$,189)+A$:RETURN
+8675 IF LEN(A$)<>3 THEN PRINT "ERROR":STOP
+8680 IF S8=1 THEN Q$=A$+RIGHT$(Q$,189):RETURN
+8690 IF S8=190 THEN Q$=LEFT$(Q$,189)+A$:RETURN
8700 Q$=LEFT$(Q$,S8-1)+A$+RIGHT$(Q$,190-S8):RETURN
8780 REM PRINTS DEVICE NAME
-8790 ONR1GOTO8792,8794,8796,8798,8800,8802,8804,8806
+8790 ON R1 GOTO 8792,8794,8796,8798,8800,8802,8804,8806
8792 G2$="WARP ENGINES":RETURN
8794 G2$="SHORT RANGE SENSORS":RETURN
8796 G2$="LONG RANGE SENSORS":RETURN
@@ -394,30 +394,30 @@
8806 G2$="LIBRARY-COMPUTER":RETURN
8820 REM STRING COMPARISON IN QUADRANT ARRAY
8830 Z1=INT(Z1+.5):Z2=INT(Z2+.5):S8=(Z2-1)*3+(Z1-1)*24+1:Z3=0
-8890 IFMID$(Q$,S8,3)<>A$THENRETURN
+8890 IF MID$(Q$,S8,3)<>A$ THEN RETURN
8900 Z3=1:RETURN
9010 REM QUADRANT NAME IN G2$ FROM Z4,Z5 (=Q1,Q2)
9020 REM CALL WITH G5=1 TO GET REGION NAME ONLY
-9030 IFZ5<=4THENONZ4GOTO9040,9050,9060,9070,9080,9090,9100,9110
-9035 GOTO9120
-9040 G2$="ANTARES":GOTO9210
-9050 G2$="RIGEL":GOTO9210
-9060 G2$="PROCYON":GOTO9210
-9070 G2$="VEGA":GOTO9210
-9080 G2$="CANOPUS":GOTO9210
-9090 G2$="ALTAIR":GOTO9210
-9100 G2$="SAGITTARIUS":GOTO9210
-9110 G2$="POLLUX":GOTO9210
-9120 ONZ4GOTO9130,9140,9150,9160,9170,9180,9190,9200
-9130 G2$="SIRIUS":GOTO9210
-9140 G2$="DENEB":GOTO9210
-9150 G2$="CAPELLA":GOTO9210
-9160 G2$="BETELGEUSE":GOTO9210
-9170 G2$="ALDEBARAN":GOTO9210
-9180 G2$="REGULUS":GOTO9210
-9190 G2$="ARCTURUS":GOTO9210
+9030 IF Z5<=4 THEN ON Z4 GOTO 9040,9050,9060,9070,9080,9090,9100,9110
+9035 GOTO 9120
+9040 G2$="ANTARES":GOTO 9210
+9050 G2$="RIGEL":GOTO 9210
+9060 G2$="PROCYON":GOTO 9210
+9070 G2$="VEGA":GOTO 9210
+9080 G2$="CANOPUS":GOTO 9210
+9090 G2$="ALTAIR":GOTO 9210
+9100 G2$="SAGITTARIUS":GOTO 9210
+9110 G2$="POLLUX":GOTO 9210
+9120 ON Z4 GOTO 9130,9140,9150,9160,9170,9180,9190,9200
+9130 G2$="SIRIUS":GOTO 9210
+9140 G2$="DENEB":GOTO 9210
+9150 G2$="CAPELLA":GOTO 9210
+9160 G2$="BETELGEUSE":GOTO 9210
+9170 G2$="ALDEBARAN":GOTO 9210
+9180 G2$="REGULUS":GOTO 9210
+9190 G2$="ARCTURUS":GOTO 9210
9200 G2$="SPICA"
-9210 IFG5<>1THENONZ5GOTO9230,9240,9250,9260,9230,9240,9250,9260
+9210 IF G5<>1 THEN ON Z5 GOTO 9230,9240,9250,9260,9230,9240,9250,9260
9220 RETURN
9230 G2$=G2$+" I":RETURN
9240 G2$=G2$+" II":RETURN
diff --git a/94_War/d/.gitignore b/94_War/d/.gitignore
new file mode 100644
index 00000000..d969f6b2
--- /dev/null
+++ b/94_War/d/.gitignore
@@ -0,0 +1,2 @@
+*.exe
+*.obj
diff --git a/94_War/d/README.md b/94_War/d/README.md
new file mode 100644
index 00000000..2bc48a12
--- /dev/null
+++ b/94_War/d/README.md
@@ -0,0 +1,125 @@
+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 -preview=dip1000 -run war.d
+```
+
+[Other compilers](https://dlang.org/download.html) also exist.
+
+## Specialties explained
+
+This game code contains some specialties that you might want to know more about. Here goes.
+
+### Suits
+
+Most modern consoles are capable of displaying more than just ASCII, and so I have chosen to display the actual ♠, ♥, ♦
+and ♣ instead of substituting them by letters like the BASIC original did. Only the Windows console needs a nudge in
+the right direction with these instructions:
+```d
+SetConsoleOutputCP(CP_UTF8); // Set code page
+SetConsoleOutputCP(GetACP); // Restore the default
+```
+Instead of cluttering the `main()` function with these lesser important details, we can move them into a
+[module constructor and module destructor](https://dlang.org/spec/module.html#staticorder), which run before and after
+`main()` respectively. And because order of declaration is irrelevant in a D module, we can push those all the way
+down to the bottom of the file. This is of course only necessary on Windows (and won't even work anywhere else) so
+we'll need to wrap this in a `version (Windows)` conditional code block:
+```d
+version (Windows)
+{
+ import core.sys.windows.windows;
+
+ shared static this() @trusted
+ {
+ SetConsoleOutputCP(CP_UTF8);
+ }
+
+ shared static ~this() @trusted
+ {
+ SetConsoleOutputCP(GetACP);
+ }
+}
+```
+Although it doesn't matter much in this single-threaded program, the `shared` attribute makes that these
+constructors/destructors are run once per program invocation; non-shared module constructors and module destructors are
+run for every thread. The `@trusted` annotation is necessary because these are system API calls; The compiler cannot
+check these for memory-safety, and so we must indicate that we have reviewed the safety manually.
+
+### Uniform Function Call Syntax
+
+In case you wonder why this line works:
+```d
+if ("Do you want instructions?".yes)
+ // ...
+```
+then it is because this is equivalent to
+```d
+if (yes("Do you want instructions?"))
+ // ...
+```
+where `yes()` is a Boolean function that is defined below `main()`. This is made possible by the language feature that
+is called [uniform function call syntax (UFCS)](https://dlang.org/spec/function.html#pseudo-member). UFCS works by
+passing what is in front of the dot as the first parameter to the function, and it was invented to make it possible to
+call free functions on objects as if they were member functions. UFCS can also be used to obtain a more natural order
+of function calls, such as this line inside `yes()`:
+```d
+return trustedReadln.strip.toLower.startsWith("y");
+```
+which reads easier than the equivalent
+```d
+return startsWith(toLower(strip(trustedReadln())), "y");
+```
+
+### Type a lot or not?
+
+It would have been straight forward to define the `cards` array explicitly like so:
+```d
+const cards = ["2♠", "2♥", "2♦", "2♣", "3♠", "3♥", "3♦", "3♣",
+ "4♠", "4♥", "4♦", "4♣", "5♠", "5♥", "5♦", "5♣",
+ "6♠", "6♥", "6♦", "6♣", "7♠", "7♥", "7♦", "7♣",
+ "8♠", "8♥", "8♦", "8♣", "9♠", "9♥", "9♦", "9♣",
+ "10♠", "10♥", "10♦", "10♣", "J♥", "J♦", "J♣", "J♣",
+ "Q♠", "Q♥", "Q♦", "Q♣", "K♠", "K♥", "K♦", "K♣",
+ "A♠", "A♥", "A♦", "A♣"];
+```
+but that's tedious, difficult to spot errors in (*can you?*) and looks like something a computer can automate. Indeed
+it can:
+```d
+static const cards = cartesianProduct(["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"],
+ ["♠", "♥", "♦", "♣"]).map!(a => a.expand.only.join).array;
+```
+The function [`cartesianProduct`](https://dlang.org/phobos/std_algorithm_setops.html#cartesianProduct) takes two
+ranges, like the horizontal and vertical headers of a spreadsheet, and fills the table with the combinations that form
+the coordinates of the cells. But the output of that function is in the form of an array of
+[`Tuple`](https://dlang.org/phobos/std_typecons.html#Tuple)s, which looks like `[Tuple!(string, string)("2", "♠"),
+Tuple!(string, string)("2", "♥"), ... etc]`. [`map`](https://dlang.org/phobos/std_algorithm_iteration.html#map)
+comes to the rescue, converting each Tuple to a string, by calling
+[`expand`](https://dlang.org/phobos/std_typecons.html#.Tuple.expand), then
+[`only`](https://dlang.org/phobos/std_range.html#only) and then [`join`](https://dlang.org/phobos/std_array.html#join)
+on them. The result is a lazily evaluated range of strings. Finally,
+[`array`](https://dlang.org/phobos/std_array.html#array) turns the range into a random access array. The `static`
+attribute makes that all this is performed at compile-time, so the result is exactly the same as the manually entered
+data, but without the typo's.
+
+### Shuffle the cards or not?
+
+The original BASIC code works with a constant array of cards, ordered by increasing numerical value, and indexing it
+with indices that have been shuffled. This is efficient because in comparing who wins, the indices can be compared
+directly, since a higher index correlates to a card with a higher numerical value (when divided by the number of suits,
+4). Some of the other reimplementations in other languages have been written in a lesser efficient way by shuffling the
+array of cards itself. This then requires the use of a lookup table or searching for equality in an auxiliary array
+when comparing cards.
+
+I find the original more elegant, so that's what you see here:
+```d
+const indices = iota(0, cards.length).array.randomShuffle;
+```
+[`iota`](https://dlang.org/phobos/std_range.html#iota) produces a range of integers, in this case starting at 0 and
+increasing up to the number of cards in the deck (exclusive). [`array`](https://dlang.org/phobos/std_array.html#array)
+turns the range into an array, so that [`randomShuffle`](https://dlang.org/phobos/std_random.html#randomShuffle) can
+do its work.
diff --git a/94_War/d/war.d b/94_War/d/war.d
new file mode 100644
index 00000000..d5a453fa
--- /dev/null
+++ b/94_War/d/war.d
@@ -0,0 +1,80 @@
+@safe: // Make @safe the default for this file, enforcing memory-safety.
+import std;
+
+void main()
+{
+ enum width = 50;
+ writeln(center("War", width));
+ writeln(center("(After Creative Computing Morristown, New Jersey)\n\n", width));
+ writeln(wrap("This is the card game of war. Each card is given by suit-# " ~
+ "as 7♠ for seven of spades. ", width));
+
+ if ("Do you want instructions?".yes)
+ writeln("\n", wrap("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.\n", width));
+
+ static const cards = cartesianProduct(["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"],
+ ["♠", "♥", "♦", "♣"]).map!(a => a.expand.only.join).array;
+ const indices = iota(0, cards.length).array.randomShuffle;
+ int yourScore = 0, compScore = 0, i = 0;
+ while (i < indices.length)
+ {
+ size_t your = indices[i++], comp = indices[i++];
+ writeln("\nYou: ", cards[your].leftJustify(9), "Computer: ", cards[comp]);
+ your /= 4; comp /= 4;
+ if (your == comp)
+ writeln("Tie. No score change.");
+ else if (your < comp)
+ writeln("The computer wins!!! You have ", yourScore,
+ " and the computer has ", ++compScore, ".");
+ else
+ writeln("You win. You have ", ++yourScore,
+ " and the computer has ", compScore, ".");
+ if (i == indices.length)
+ writeln("\nWe have run out of cards. Final score: You: ", yourScore,
+ ", the computer: ", compScore, ".");
+ else if (!"Do you want to continue?".yes)
+ break;
+ }
+ writeln("\nThanks for playing. It was fun.");
+}
+
+/// Returns whether question was answered positively.
+bool yes(string question)
+{
+ writef!"%s "(question);
+ try
+ return trustedReadln.strip.toLower.startsWith("y");
+ catch (Exception) // readln throws on I/O and Unicode errors, which we handle here.
+ return false;
+}
+
+/** 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);
+ }
+}