*
* Any resemblance to persons living or dead is strictly coincidental. And
* if you believe *that*...
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
*/
-#include <stdio.h>
#include <ctype.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <time.h>
#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
static int path[5];
static int j, k, scratchloc, pies;
-static char inp[BUFSIZ]; /* common input buffer */
+static char inp[BUFSIZ]; /* common input buffer */
#define NUMBERS "0123456789"
-#define YOU 0
-#define RMS 1
-#define STARLET1 2
-#define STARLET2 3
-#define DROID1 4
-#define DROID2 5
-#define LUSER1 6
-#define LUSER2 7
-#define LOCS 8
+#define YOU 0
+#define RMS 1
+#define STARLET1 2
+#define STARLET2 3
+#define DROID1 4
+#define DROID2 5
+#define LUSER1 6
+#define LUSER2 7
+#define LOCS 8
static int loc[LOCS];
-#define NOT 0
-#define WIN 1
-#define LOSE -1
+#define NOT 0
+#define WIN 1
+#define LOSE -1
static int finished;
-#define IGNORE(r) do{if(r);}while(0)
-
-static int cave[20][3] =
-{
- {1,4,7},
- {0,2,9},
- {1,3,11},
- {2,4,13},
- {0,3,5},
- {4,6,14},
- {5,7,16},
- {0,6,8},
- {7,9,17},
- {1,8,10},
- {9,11,18},
- {2,10,12},
- {11,13,19},
- {3,12,14},
- {5,13,15},
- {14,16,19},
- {6,15,17},
- {8,16,18},
- {10,17,19},
- {12,15,18},
+#define IGNORE(r) \
+ do { \
+ if (r) \
+ ; \
+ } while (0)
+
+static int cave[20][3] = {
+ {1, 4, 7}, {0, 2, 9}, {1, 3, 11}, {2, 4, 13}, {0, 3, 5},
+ {4, 6, 14}, {5, 7, 16}, {0, 6, 8}, {7, 9, 17}, {1, 8, 10},
+ {9, 11, 18}, {2, 10, 12}, {11, 13, 19}, {3, 12, 14}, {5, 13, 15},
+ {14, 16, 19}, {6, 15, 17}, {8, 16, 18}, {10, 17, 19}, {12, 15, 18},
};
-#define FNA() (rand() % 20)
+#define FNA() (rand() % 20)
-#define FNB() (rand() % 3)
+#define FNB() (rand() % 3)
-#define FNC() (rand() % 4)
+#define FNC() (rand() % 4)
int getlet(prompt)
char *prompt;
{
- (void) printf("%s? ", prompt);
- if (fgets(inp, sizeof(inp), stdin))
- return(tolower(inp[0]));
- else {
- fputs("\n",stdout);
- exit(1);
- }
+ (void)printf("%s? ", prompt);
+ if (fgets(inp, sizeof(inp), stdin)) {
+ return (tolower(inp[0]));
+ } else {
+ fputs("\n", stdout);
+ exit(1);
+ }
}
-#define PM(x) puts(x);
-
-void print_instructions()
-{
- PM("Welcome to `Hunt the Superhack'\n")
-
-PM(" The superhack lives on the 9th floor of 45 Technology Square in");
-PM("Cambridge, Massachusetts. Your mission is to throw a pie in his face.\n");
-
- PM(" First, you'll have to find him. A botched experiment by an MIT");
- PM("physics group has regularized the floor's topology, so that each");
- PM("room has exits to three other rooms. (Look at a dodecahedron to");
- PM("see how this works --- if you don't know what a dodecahedron is,");
- PM("ask someone.)\n");
-
- PM("You:");
- PM(" Each turn you may move to an adjacent room or throw a pie. If");
- PM("you run out of pies, you lose. Each pie can pass through up to");
- PM("five rooms (connected by a continuous path from where you are). You");
- PM("aim by telling the computer which rooms you want to throw through.");
- PM("If the path is incorrect (presumes a nonexistent connection) the ");
- PM("pie moves at random.");
-
- PM(" If a pie hits the superhack, you win. If it hits you, you lose!\n");
-
- (void) fputs("<Press return to continue>", stdout);
- IGNORE(fgets(inp, sizeof(inp), stdin));
- (void) putchar('\n');
-
- PM("Hazards:");
- PM(" Starlets --- two rooms contain lonely, beautiful women. If you");
- PM("enter these, you will become fascinated and forget your mission as");
- PM("you engage in futile efforts to pick one up. You weenie.");
- PM(" Droids --- two rooms are guarded by experimental AI security ");
- PM("droids. If you enter either, the droid will grab you and hustle");
- PM("you off to somewhere else, at random.");
- PM(" Lusers --- two rooms contain hungry lusers. If you blunder into");
- PM("either, they will eat one of your pies.");
- PM(" Superhack --- the superhack is not bothered by hazards (the");
- PM("lusers are in awe of him, he's programmed the droids to ignore him,");
- PM("and he has no sex life). Usually he is hacking. Two things can");
- PM("interrupt him; you throwing a pie or you entering his room.\n");
- PM(" On an interrupt, the superhack moves (3/4 chance) or stays where");
- PM("he is (1/4 chance). After that, if he is where you are, he flames");
- PM("you and you lose!\n");
-
- (void) fputs("<Press return to continue>", stdout);
- (void) fgets(inp, sizeof(inp), stdin);
- (void) putchar('\n');
-
- PM("Warnings:");
- PM(" When you are one room away from the superhack or a hazard,");
- PM("the computer says:");
- PM(" superhack: \"I smell a superhack!\"");
- PM(" security droid: \"Droids nearby!\"");
- PM(" starlet: \"I smell perfume!\"");
- PM(" luser: \"Lusers nearby!\"");
-
- PM("If you take too long finding the superhack, hazards may move. You");
- PM("will get a warning when this happens.\n");
-
- PM("Commands:");
- PM(" Available commands are:\n");
- PM(" ? --- print long instructions.");
- PM(" m <number> --- move to room with given number.");
- PM(" t <numbers> --- throw through given rooms.");
+#define PM(x) puts(x);
+
+void print_instructions() {
+ PM("Welcome to `Hunt the Superhack'\n")
+
+ PM(" The superhack lives on the 9th floor of 45 Technology Square "
+ "in");
+ PM("Cambridge, Massachusetts. Your mission is to throw a pie in his "
+ "face.\n");
+
+ PM(" First, you'll have to find him. A botched experiment by an "
+ "MIT");
+ PM("physics group has regularized the floor's topology, so that each");
+ PM("room has exits to three other rooms. (Look at a dodecahedron to");
+ PM("see how this works --- if you don't know what a dodecahedron is,");
+ PM("ask someone.)\n");
+
+ PM("You:");
+ PM(" Each turn you may move to an adjacent room or throw a pie. If");
+ PM("you run out of pies, you lose. Each pie can pass through up to");
+ PM("five rooms (connected by a continuous path from where you are). "
+ "You");
+ PM("aim by telling the computer which rooms you want to throw "
+ "through.");
+ PM("If the path is incorrect (presumes a nonexistent connection) the ");
+ PM("pie moves at random.");
+
+ PM(" If a pie hits the superhack, you win. If it hits you, you "
+ "lose!\n");
+
+ (void)fputs("<Press return to continue>", stdout);
+ IGNORE(fgets(inp, sizeof(inp), stdin));
+ (void)putchar('\n');
+
+ PM("Hazards:");
+ PM(" Starlets --- two rooms contain lonely, beautiful women. If "
+ "you");
+ PM("enter these, you will become fascinated and forget your mission "
+ "as");
+ PM("you engage in futile efforts to pick one up. You weenie.");
+ PM(" Droids --- two rooms are guarded by experimental AI security ");
+ PM("droids. If you enter either, the droid will grab you and hustle");
+ PM("you off to somewhere else, at random.");
+ PM(" Lusers --- two rooms contain hungry lusers. If you blunder "
+ "into");
+ PM("either, they will eat one of your pies.");
+ PM(" Superhack --- the superhack is not bothered by hazards (the");
+ PM("lusers are in awe of him, he's programmed the droids to ignore "
+ "him,");
+ PM("and he has no sex life). Usually he is hacking. Two things can");
+ PM("interrupt him; you throwing a pie or you entering his room.\n");
+ PM(" On an interrupt, the superhack moves (3/4 chance) or stays "
+ "where");
+ PM("he is (1/4 chance). After that, if he is where you are, he "
+ "flames");
+ PM("you and you lose!\n");
+
+ (void)fputs("<Press return to continue>", stdout);
+ (void)fgets(inp, sizeof(inp), stdin);
+ (void)putchar('\n');
+
+ PM("Warnings:");
+ PM(" When you are one room away from the superhack or a hazard,");
+ PM("the computer says:");
+ PM(" superhack: \"I smell a superhack!\"");
+ PM(" security droid: \"Droids nearby!\"");
+ PM(" starlet: \"I smell perfume!\"");
+ PM(" luser: \"Lusers nearby!\"");
+
+ PM("If you take too long finding the superhack, hazards may move. "
+ "You");
+ PM("will get a warning when this happens.\n");
+
+ PM("Commands:");
+ PM(" Available commands are:\n");
+ PM(" ? --- print long instructions.");
+ PM(" m <number> --- move to room with given number.");
+ PM(" t <numbers> --- throw through given rooms.");
#ifdef DEBUG
- PM(" d --- dump hazard locations.");
+ PM(" d --- dump hazard locations.");
#endif /* DEBUG */
- PM("\nThe list of room numbers after t must be space-separated. Anything");
- PM("other than one of these commands displays a short help message.");
+ PM("\nThe list of room numbers after t must be space-separated. "
+ "Anything");
+ PM("other than one of these commands displays a short help message.");
}
-void move_hazard(where)
-int where;
+void move_hazard(where) int where;
{
- int newloc;
-
- retry:
- newloc = FNA();
- for (j = 0; j < LOCS; j++)
- if (loc[j] == newloc)
- goto retry;
+ int newloc;
+
+retry:
+ newloc = FNA();
+ for (j = 0; j < LOCS; j++) {
+ if (loc[j] == newloc) {
+ goto retry;
+ }
+ }
- loc[where] = newloc;
+ loc[where] = newloc;
}
-void check_hazards()
-{
- /* basic status report */
- (void) printf("You are in room %d. Exits lead to %d, %d, %d. You have %d pies left.\n",
- loc[YOU]+1,
- cave[loc[YOU]][0]+1,
- cave[loc[YOU]][1]+1,
- cave[loc[YOU]][2]+1,
- pies);
-
- /* maybe it's migration time */
- if (FNA() == 0)
- switch(2 + FNB())
- {
- case STARLET1:
- case STARLET2:
- PM("Swish, swish, swish --- starlets are moving!");
- move_hazard(STARLET1);
- move_hazard(STARLET2);
- break;
-
- case DROID1:
- case DROID2:
- PM("Clank, clank, clank --- droids are moving!");
- move_hazard(DROID1);
- move_hazard(DROID2);
- break;
-
- case LUSER1:
- case LUSER2:
- PM("Grumble, grumble, grumble --- lusers are moving!");
- move_hazard(LUSER1);
- move_hazard(LUSER2);
- break;
+void check_hazards() {
+ /* basic status report */
+ (void)printf("You are in room %d. Exits lead to %d, %d, %d. You have "
+ "%d pies left.\n",
+ loc[YOU] + 1, cave[loc[YOU]][0] + 1, cave[loc[YOU]][1] + 1,
+ cave[loc[YOU]][2] + 1, pies);
+
+ /* maybe it's migration time */
+ if (FNA() == 0)
+ switch (2 + FNB()) {
+ case STARLET1:
+ case STARLET2:
+ PM("Swish, swish, swish --- starlets are moving!");
+ move_hazard(STARLET1);
+ move_hazard(STARLET2);
+ break;
+
+ case DROID1:
+ case DROID2:
+ PM("Clank, clank, clank --- droids are moving!");
+ move_hazard(DROID1);
+ move_hazard(DROID2);
+ break;
+
+ case LUSER1:
+ case LUSER2:
+ PM("Grumble, grumble, grumble --- lusers are moving!");
+ move_hazard(LUSER1);
+ move_hazard(LUSER2);
+ break;
+ }
+
+ /* display hazard warnings */
+ for (k = 0; k < 3; k++) {
+ int room = cave[loc[YOU]][k];
+
+ if (room == loc[RMS]) {
+ (void)puts("I smell a superhack!");
+ } else if (room == loc[STARLET1] || room == loc[STARLET2]) {
+ (void)puts("I smell perfume!");
+ } else if (room == loc[DROID1] || room == loc[DROID2]) {
+ (void)puts("Droids nearby!");
+ } else if (room == loc[LUSER1] || room == loc[LUSER2]) {
+ (void)puts("Lusers nearby!");
+ }
}
-
- /* display hazard warnings */
- for (k = 0; k < 3; k++)
- {
- int room = cave[loc[YOU]][k];
-
- if (room == loc[RMS])
- (void) puts("I smell a superhack!");
- else if (room == loc[STARLET1] || room == loc[STARLET2])
- (void) puts("I smell perfume!");
- else if (room == loc[DROID1] || room == loc[DROID2])
- (void) puts("Droids nearby!");
- else if (room == loc[LUSER1] || room == loc[LUSER2])
- (void) puts("Lusers nearby!");
- }
}
-void throw()
-{
- extern void check_shot(), move_superhack();
- int j9;
+void throw() {
+ extern void check_shot(), move_superhack();
+ int j9;
- j9 = sscanf(inp + strcspn(inp, NUMBERS), "%d %d %d %d %d",
- &path[0], &path[1], &path[2], &path[3], &path[4]);
+ j9 = sscanf(inp + strcspn(inp, NUMBERS), "%d %d %d %d %d", &path[0],
+ &path[1], &path[2], &path[3], &path[4]);
- if (j9 < 1)
- {
- PM("Sorry, I didn't see any room numbers after your throw command.");
- return;
- }
-
- for (k = 0; k < j9; k++)
- if (k >= 2 && path[k] == path[k - 2])
- {
- (void) puts("Pies can't fly that crookedly --- try again.");
- return;
+ if (j9 < 1) {
+ PM("Sorry, I didn't see any room numbers after your throw "
+ "command.");
+ return;
}
- scratchloc = loc[YOU];
-
- for (k = 0; k < j9; k++)
- {
- int k1;
-
- for (k1 = 0; k1 < 3; k1++)
- {
- if (cave[scratchloc][k1] == path[k])
- {
- scratchloc = path[k];
- check_shot();
- if (finished != NOT)
- return;
- }
-
+ for (k = 0; k < j9; k++) {
+ if (k >= 2 && path[k] == path[k - 2]) {
+ (void)puts(
+ "Pies can't fly that crookedly --- try again.");
+ return;
+ }
}
- scratchloc = cave[scratchloc][FNB()];
+ scratchloc = loc[YOU];
- check_shot();
+ for (k = 0; k < j9; k++) {
+ int k1;
- }
+ for (k1 = 0; k1 < 3; k1++) {
+ if (cave[scratchloc][k1] == path[k]) {
+ scratchloc = path[k];
+ check_shot();
+ if (finished != NOT) {
+ return;
+ }
+ }
+ }
- if (finished == NOT)
- {
- (void) puts("You missed.");
+ scratchloc = cave[scratchloc][FNB()];
- scratchloc = loc[YOU];
+ check_shot();
+ }
- move_superhack();
+ if (finished == NOT) {
+ (void)puts("You missed.");
- if (--pies <= 0)
- finished = LOSE;
- }
+ scratchloc = loc[YOU];
-}
+ move_superhack();
-void check_shot()
-{
- if (scratchloc == loc[RMS])
- {
- (void) puts("Splat! You got the superhack! You win.");
- finished = WIN;
- }
-
- else if (scratchloc == loc[YOU])
- {
- (void) puts("Ugh! The pie hit you! You lose.");
- finished = LOSE;
- }
+ if (--pies <= 0) {
+ finished = LOSE;
+ }
+ }
}
-void move_superhack()
-{
- k = FNC();
+void check_shot() {
+ if (scratchloc == loc[RMS]) {
+ (void)puts("Splat! You got the superhack! You win.");
+ finished = WIN;
+ }
+
+ else if (scratchloc == loc[YOU]) {
+ (void)puts("Ugh! The pie hit you! You lose.");
+ finished = LOSE;
+ }
+}
- if (k < 3)
- loc[RMS] = cave[loc[RMS]][k];
+void move_superhack() {
+ k = FNC();
- if (loc[RMS] != loc[YOU])
- return;
+ if (k < 3) {
+ loc[RMS] = cave[loc[RMS]][k];
+ }
- (void) puts("The superhack flames you to a crisp. You lose!");
+ if (loc[RMS] != loc[YOU]) {
+ return;
+ }
- finished = LOSE;
+ (void)puts("The superhack flames you to a crisp. You lose!");
+ finished = LOSE;
}
-void move()
-{
- if (sscanf(inp + strcspn(inp, NUMBERS), "%d", &scratchloc) < 1)
- {
- PM("Sorry, I didn't see a room number after your `m' command.");
- return;
- }
+void move() {
+ if (sscanf(inp + strcspn(inp, NUMBERS), "%d", &scratchloc) < 1) {
+ PM("Sorry, I didn't see a room number after your `m' command.");
+ return;
+ }
- scratchloc--;
+ scratchloc--;
- for (k = 0; k < 3; k++)
- if (cave[loc[YOU]][k] == scratchloc)
- goto goodmove;
+ for (k = 0; k < 3; k++) {
+ if (cave[loc[YOU]][k] == scratchloc) {
+ goto goodmove;
+ }
+ }
- PM("You can't get there from here!");
- return;
+ PM("You can't get there from here!");
+ return;
goodmove:
- loc[YOU] = scratchloc;
-
- if (scratchloc == loc[RMS])
- {
- PM("Yow! You interrupted the superhack.");
- move_superhack();
- }
- else if (scratchloc == loc[STARLET1] || scratchloc == loc[STARLET2])
- {
- PM("You begin to babble at an unimpressed starlet. You lose!");
- finished = LOSE;
- }
- else if (scratchloc == loc[DROID1] || scratchloc == loc[DROID2])
- {
- PM("Zap --- security droid snatch. Elsewheresville for you!");
- scratchloc = loc[YOU] = FNA();
- goto goodmove;
- }
- else if (scratchloc == loc[LUSER1] || scratchloc == loc[LUSER2])
- {
- PM("Munch --- lusers ate one of your pies!");
- pies--;
- }
+ loc[YOU] = scratchloc;
+
+ if (scratchloc == loc[RMS]) {
+ PM("Yow! You interrupted the superhack.");
+ move_superhack();
+ } else if (scratchloc == loc[STARLET1] || scratchloc == loc[STARLET2]) {
+ PM("You begin to babble at an unimpressed starlet. You lose!");
+ finished = LOSE;
+ } else if (scratchloc == loc[DROID1] || scratchloc == loc[DROID2]) {
+ PM("Zap --- security droid snatch. Elsewheresville for you!");
+ scratchloc = loc[YOU] = FNA();
+ goto goodmove;
+ } else if (scratchloc == loc[LUSER1] || scratchloc == loc[LUSER2]) {
+ PM("Munch --- lusers ate one of your pies!");
+ pies--;
+ }
}
-int main(int argc, char *argv[])
-{
- if (argc >= 2 && strcmp(argv[1], "-s") == 0)
- srand(atoi(argv[2]));
- else
- srand((int)time((long *) 0));
-
- for (;;)
- {
- badlocs:
- for (j = 0; j < LOCS; j++)
- loc[j] = FNA();
-
- for (j = 0; j < LOCS; j++)
- for (k = 0; k < LOCS; k++)
- if (j == k)
- continue;
- else if (loc[j] == loc[k])
- goto badlocs;
-
- (void) puts("Hunt the Superhack");
-
- pies = 5;
- scratchloc = loc[YOU];
- finished = NOT;
-
- while (finished == NOT)
- {
- int c;
-
- check_hazards();
-
- c = getlet("Throw, move or help [t,m,?]");
+int main(int argc, char *argv[]) {
+ if (argc >= 2 && strcmp(argv[1], "-s") == 0) {
+ srand(atoi(argv[2]));
+ } else {
+ srand((int)time((long *)0));
+ }
- if (c == 't')
- throw();
- else if (c == 'm')
- move();
- else if (c == '?')
- print_instructions();
+ for (;;) {
+ badlocs:
+ for (j = 0; j < LOCS; j++) {
+ loc[j] = FNA();
+ }
+
+ for (j = 0; j < LOCS; j++) {
+ for (k = 0; k < LOCS; k++) {
+ if (j == k) {
+ continue;
+ } else if (loc[j] == loc[k]) {
+ goto badlocs;
+ }
+ }
+ }
+
+ (void)puts("Hunt the Superhack");
+
+ pies = 5;
+ scratchloc = loc[YOU];
+ finished = NOT;
+
+ while (finished == NOT) {
+ int c;
+
+ check_hazards();
+
+ c = getlet("Throw, move or help [t,m,?]");
+
+ if (c == 't') {
+ throw();
+ } else if (c == 'm') {
+ move();
+ } else if (c == '?') {
+ print_instructions();
+ }
#ifdef DEBUG
- else if (c == 'd')
- {
- (void) printf("RMS is at %d, starlets at %d/%d, droids %d/%d, lusers %d/%d\n",
- loc[RMS] + 1,
- loc[STARLET1] + 1, loc[STARLET2] + 1,
- loc[DROID1] + 1, loc[DROID2] + 1,
- loc[LUSER1] + 1, loc[LUSER2] + 1);
- }
+ else if (c == 'd') {
+ (void)printf("RMS is at %d, starlets at %d/%d, "
+ "droids %d/%d, lusers %d/%d\n",
+ loc[RMS] + 1, loc[STARLET1] + 1,
+ loc[STARLET2] + 1, loc[DROID1] + 1,
+ loc[DROID2] + 1, loc[LUSER1] + 1,
+ loc[LUSER2] + 1);
+ }
#endif /* DEBUG */
- else
- {
- PM("Available commands are:\n");
- PM(" ? --- print long instructions.");
- PM(" m <number> --- move to room with given number.");
- PM(" t <numbers> --- throw through given rooms.");
+ else {
+ PM("Available commands are:\n");
+ PM(" ? --- print long "
+ "instructions.");
+ PM(" m <number> --- move to room with given "
+ "number.");
+ PM(" t <numbers> --- throw through given "
+ "rooms.");
#ifdef DEBUG
- PM(" d --- dump hazard locations.");
+ PM(" d --- dump hazard locations.");
#endif /* DEBUG */
- PM("The list of room numbers after t must be space-separated");
- }
+ PM("The list of room numbers after t must be "
+ "space-separated");
+ }
- (void) putchar('\n');
- }
+ (void)putchar('\n');
+ }
- if (getlet("Play again") != 'y')
- {
- PM("Happy hacking!");
- break;
+ if (getlet("Play again") != 'y') {
+ PM("Happy hacking!");
+ break;
+ }
}
- }
- return 0;
+ return 0;
}
/* superhack.c ends here */