Ready to ship 1.10
[wumpus.git] / wumpus.c
1 /*
2  * wumpus.c --- a faithful translation of the classic "Hunt The Wumpus" game.
3  *
4  * Translator: Eric S. Raymond <esr@snark.thyrsus.com>
5  * Version: $Id: wumpus.c,v 1.4 1996/05/17 17:30:35 esr Exp esr $
6  *
7  * The BASIC source is that posted by Magnus Olsson in USENET article
8  * <9207071854.AA21847@thep.lu.se>: he wrote
9  *
10  * >Below is the source code for _one_ (rather simple) Wumpus version,
11  * >which I found in the PC-BLUE collection on SIMTEL20. I believe this is
12  * >pretty much the same version that was published in David Ahl's "101
13  * >Basic Computer Games" (or, possibly, in the sequel).
14  *
15  * I have staunchly resisted the temptation to "improve" this game.  It
16  * is functionally identical to the BASIC version (source for which
17  * appears in the comments).  I fixed some typos in the help text.
18  *
19  * Language hackers may be interested to know that he most difficult thing
20  * about the translation was tracking the details required to translate from
21  * 1-origin to 0-origin array indexing.
22  *
23  * The only enhancement is a an -s command-line switch for setting the
24  * random number seed.
25  *
26  * So, pretend for a little while that your workstation is an ASR-33 and
27  * limber up your fingers for a trip to nostalgia-land...
28  *
29  * SPDX-License-Identifier: BSD-2-Clause
30  * SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
31  */
32
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/socket.h>
38 #include <time.h>
39 #include <unistd.h>
40
41 /* 5 REM *** HUNT THE WUMPUS ***                                        */
42
43 /* 10 DIM P(5)                                                          */
44 static int path[5];
45
46 static int j, k, arrows, scratchloc;
47 static char inp[BUFSIZ]; /* common input buffer */
48
49 #define YOU 0
50 #define WUMPUS 1
51 #define PIT1 2
52 #define PIT2 3
53 #define BATS1 4
54 #define BATS2 5
55 #define LOCS 6
56 static int loc[LOCS], save[LOCS]; /* locations */
57
58 #define NOT 0
59 #define WIN 1
60 #define LOSE -1
61 static int finished;
62
63 /* 80 REM *** SET UP CAVE (DODECAHEDRAL NODE LIST) ***          */
64 /* 85 DIM S(20,3)                                                       */
65 /* 90 FOR J=1 TO 20                                                     */
66 /* 95 FOR K=1 TO 3                                                      */
67 /* 100 READ S(J,K)                                                      */
68 /* 105 NEXT K                                                   */
69 /* 110 NEXT J                                                   */
70 /* 115 DATA 2,5,8,1,3,10,2,4,12,3,5,14,1,4,6                    */
71 /* 120 DATA 5,7,15,6,8,17,1,7,9,8,10,18,2,9,11                  */
72 /* 125 DATA 10,12,19,3,11,13,12,14,20,4,13,15,6,14,16           */
73 /* 130 DATA 15,17,20,7,16,18,9,17,19,11,18,20,13,16,19          */
74 static int cave[20][3] = {
75     {1, 4, 7},    {0, 2, 9},   {1, 3, 11},   {2, 4, 13},   {0, 3, 5},
76     {4, 6, 14},   {5, 7, 16},  {0, 6, 8},    {7, 9, 17},   {1, 8, 10},
77     {9, 11, 18},  {2, 10, 12}, {11, 13, 19}, {3, 12, 14},  {5, 13, 15},
78     {14, 16, 19}, {6, 15, 17}, {8, 16, 18},  {10, 17, 19}, {12, 15, 18},
79 };
80
81 /* 135 DEF FNA(X)=INT(20*RND(1))+1                                      */
82 #define FNA() (rand() % 20)
83
84 /* 140 DEF FNB(X)=INT(3*RND(1))+1                                       */
85 #define FNB() (rand() % 3)
86
87 /* 145 DEF FNC(X)=INT(4*RND(1))+1                                       */
88 #define FNC() (rand() % 4)
89
90 int getnum(prompt)
91 char *prompt;
92 {
93         (void)printf("%s\n?", prompt);
94         if (fgets(inp, sizeof(inp), stdin))
95                 return (atoi(inp));
96         else {
97                 fputs("\n", stdout);
98                 exit(1);
99         }
100 }
101
102 int getlet(prompt)
103 char *prompt;
104 {
105         (void)printf("%s\n?", prompt);
106         if (fgets(inp, sizeof(inp), stdin))
107                 return (toupper(inp[0]));
108         else {
109                 fputs("\n", stdout);
110                 exit(1);
111         }
112 }
113
114 void print_instructions() {
115         /* 375 REM *** INSTRUCTIONS *** */
116         /* 380 PRINT "WELCOME TO 'HUNT THE WUMPUS'" */
117         puts("WELCOME TO 'HUNT THE WUMPUS'");
118         /* 385 PRINT "  THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM"
119          */
120         puts("  THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM");
121         /* 390 PRINT "HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A"
122          */
123         puts("HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A");
124         /* 395 PRINT "DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOW"
125          */
126         puts("DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOW");
127         /* 400 PRINT "WHAT A DODECAHEDRON IS, ASK SOMEONE)" */
128         puts("WHAT A DODECAHEDRON IS, ASK SOMEONE)");
129         /* 405 PRINT */
130         puts("");
131         /* 410 PRINT "     HAZARDS:" */
132         puts("     HAZARDS:");
133         /* 415 PRINT " BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM
134          */
135         puts(" BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM");
136         /* 420 PRINT "     IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)"
137          */
138         puts("     IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)");
139         /* 425 PRINT " SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU"
140          */
141         puts(" SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU");
142         /* 430 PRINT "     GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME
143          * OTHER"       */
144         puts("     GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER");
145         /* 435 PRINT "     ROOM AT RANDOM. (WHICH MAY BE TROUBLESOME)"
146          */
147         puts("     ROOM AT RANDOM. (WHICH MAY BE TROUBLESOME)");
148         /* 440 INPUT "TYPE AN E THEN RETURN ";W9 */
149         (void)getlet("TYPE AN E THEN RETURN ");
150         /* 445 PRINT "     WUMPUS:" */
151         puts("     WUMPUS:");
152         /* 450 PRINT " THE WUMPUS IS NOT BOTHERED BY HAZARDS (HE HAS SUCKER"
153          */
154         puts(" THE WUMPUS IS NOT BOTHERED BY HAZARDS (HE HAS SUCKER");
155         /* 455 PRINT " FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY"
156          */
157         puts(" FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY");
158         /* 460 PRINT " HE IS ASLEEP.  TWO THINGS WAKE HIM UP: YOU SHOOTING AN"
159          */
160         puts(" HE IS ASLEEP.  TWO THINGS WAKE HIM UP: YOU SHOOTING AN");
161         /* 465 PRINT "ARROW OR YOU ENTERING HIS ROOM." */
162         puts("ARROW OR YOU ENTERING HIS ROOM.");
163         /* 470 PRINT "     IF THE WUMPUS WAKES HE MOVES (P=.75) ONE ROOM"
164          */
165         puts("     IF THE WUMPUS WAKES HE MOVES (P=.75) ONE ROOM");
166         /* 475 PRINT " OR STAYS STILL (P=.25).  AFTER THAT, IF HE IS WHERE YOU"
167          */
168         puts(" OR STAYS STILL (P=.25).  AFTER THAT, IF HE IS WHERE YOU");
169         /* 480 PRINT " ARE, HE EATS YOU UP AND YOU LOSE!" */
170         puts(" ARE, HE EATS YOU UP AND YOU LOSE!");
171         /* 485 PRINT */
172         puts("");
173         /* 490 PRINT "     YOU:" */
174         puts("     YOU:");
175         /* 495 PRINT " EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW"
176          */
177         puts(" EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW");
178         /* 500 PRINT "   MOVING:  YOU CAN MOVE ONE ROOM (THRU ONE TUNNEL)"
179          */
180         puts("   MOVING:  YOU CAN MOVE ONE ROOM (THRU ONE TUNNEL)");
181         /* 505 PRINT "   ARROWS:  YOU HAVE 5 ARROWS.  YOU LOSE WHEN YOU RUN OUT
182          */
183         puts("   ARROWS:  YOU HAVE 5 ARROWS.  YOU LOSE WHEN YOU RUN OUT");
184         /* 510 PRINT "   EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY
185          * TELLING*/
186         puts("   EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING");
187         /* 515 PRINT "   THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO."
188          */
189         puts("   THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO.");
190         /* 520 PRINT "   IF THE ARROW CAN'T GO THAT WAY (IF NO TUNNEL) IT
191          * MOVES"*/
192         puts("   IF THE ARROW CAN'T GO THAT WAY (IF NO TUNNEL) IT MOVES");
193         /* 525 PRINT "   AT RANDOM TO THE NEXT ROOM." */
194         puts("   AT RANDOM TO THE NEXT ROOM.");
195         /* 530 PRINT "     IF THE ARROW HITS THE WUMPUS, YOU WIN."
196          */
197         puts("     IF THE ARROW HITS THE WUMPUS, YOU WIN.");
198         /* 535 PRINT "     IF THE ARROW HITS YOU, YOU LOSE." */
199         puts("     IF THE ARROW HITS YOU, YOU LOSE.");
200         /* 540 INPUT "TYPE AN E THEN RETURN ";W9 */
201         (void)getlet("TYPE AN E THEN RETURN ");
202         /* 545 PRINT "    WARNINGS:" */
203         puts("    WARNINGS:");
204         /* 550 PRINT "     WHEN YOU ARE ONE ROOM AWAY FROM A WUMPUS OR HAZARD,"
205          */
206         puts("     WHEN YOU ARE ONE ROOM AWAY FROM A WUMPUS OR HAZARD,");
207         /* 555 PRINT "     THE COMPUTER SAYS:" */
208         puts("     THE COMPUTER SAYS:");
209         /* 560 PRINT " WUMPUS:  'I SMELL A WUMPUS'" */
210         puts(" WUMPUS:  'I SMELL A WUMPUS'");
211         /* 565 PRINT " BAT   :  'BATS NEARBY'" */
212         puts(" BAT   :  'BATS NEARBY'");
213         /* 570 PRINT " PIT   :  'I FEEL A DRAFT'" */
214         puts(" PIT   :  'I FEEL A DRAFT'");
215         /* 575 PRINT */
216         puts("");
217         /* 580 RETURN */
218 }
219
220 void check_hazards() {
221         /* 585 REM *** PRINT LOCATION & HAZARD WARNINGS *** */
222         /* 590 PRINT                                                    */
223         (void)puts("");
224
225         /* 595 FOR J=2 TO 6 */
226         /* 600 FOR K=1 TO 3 */
227         /* 605 IF S(L(1),K)<>L(J) THEN 640 */
228         /* 610 ON J-1 GOTO 615,625,625,635,635                          */
229         /* 615 PRINT "I SMELL A WUMPUS!" */
230         /* 620 GOTO 640                                                 */
231         /* 625 PRINT "I FEEL A DRAFT"                                   */
232         /* 630 GOTO 640                                                 */
233         /* 635 PRINT "BATS NEARBY!" */
234         /* 640 NEXT K                                                   */
235         /* 645 NEXT J                                                   */
236         for (j = WUMPUS; j < LOCS; j++) {
237                 for (k = 0; k < 3; k++) {
238                         if (cave[loc[YOU]][k] != loc[j]) {
239                                 continue;
240                         }
241
242                         if (j == WUMPUS) {
243                                 (void)puts("I SMELL A WUMPUS!");
244                         } else if (j == PIT1 || j == PIT2) {
245                                 (void)puts("I FEEL A DRAFT");
246                         } else if (j == BATS1 || j == BATS2) {
247                                 (void)puts("BATS NEARBY!");
248                         }
249                 }
250         }
251
252         /* 650 PRINT "YOU ARE IN ROOM "L(1) */
253         (void)printf("YOU ARE IN ROOM %d\n", loc[YOU] + 1);
254
255         /* 655 PRINT "TUNNELS LEAD TO "S(L,1);S(L,2);S(L,3) */
256         (void)printf("TUNNELS LEAD TO %d %d %d\n", cave[loc[YOU]][0] + 1,
257                      cave[loc[YOU]][1] + 1, cave[loc[YOU]][2] + 1);
258
259         /* 660 PRINT                                                    */
260         (void)puts("");
261
262         /* 665 RETURN                                                   */
263 }
264
265 int move_or_shoot() {
266         int c;
267
268         /* 670 REM *** CHOOSE OPTION *** */
269
270 badin:
271         /* 675 PRINT "SHOOT OR MOVE (S-M)"; */
272         /* 680 INPUT I$                                                 */
273         c = getlet("SHOOT OR MOVE (S-M)");
274
275         /* 685 IF I$<>"S" THEN 700 */
276         /* 690 O=1 */
277         /* 695 RETURN                                                   */
278         /* 700 IF I$<>"M" THEN 675 */
279         /* 705 O=2 */
280         /* 710 RETURN                                                   */
281         if (c == 'S') {
282                 return (1);
283         } else if (c == 'M') {
284                 return (0);
285         } else {
286                 goto badin;
287         }
288 }
289
290 void shoot() {
291         extern void check_shot(), move_wumpus();
292         int j9;
293
294         /* 715 REM *** ARROW ROUTINE *** */
295         /* 720 F=0 */
296         finished = NOT;
297
298         /* 725 REM *** PATH OF ARROW *** */
299 badrange:
300         /* 735 PRINT "NO. OF ROOMS (1-5)"; */
301         /* 740 INPUT J9                                                 */
302         j9 = getnum("NO. OF ROOMS (1-5)");
303
304         /* 745 IF J9<1 THEN 735                                         */
305         /* 750 IF J9>5 THEN 735                                         */
306         if (j9 < 1 || j9 > 5) {
307                 goto badrange;
308         }
309
310         /* 755 FOR K=1 TO J9                                            */
311         for (k = 0; k < j9; k++) {
312                 /* 760 PRINT "ROOM #"; */
313                 /* 765 INPUT P(K) */
314                 path[k] = getnum("ROOM #") - 1;
315
316                 /* 770 IF K<=2 THEN 790 */
317                 if (k <= 1) {
318                         continue;
319                 }
320
321                 /* 775 IF P(K)<>P(K-2) THEN 790 */
322                 if (path[k] != path[k - 2]) {
323                         continue;
324                 }
325
326                 /* 780 PRINT "ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM"
327                  */
328                 (void)puts("ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM");
329                 /* 785 GOTO 760 */
330                 k--;
331
332                 /* 790 NEXT K */
333         }
334
335         /* 795 REM *** SHOOT ARROW ***                                  */
336         /* 800 L=L(1)                                                   */
337         scratchloc = loc[YOU];
338
339         /* 805 FOR K=1 TO J9                                            */
340         for (k = 0; k < j9; k++) {
341                 int k1;
342
343 #ifdef DEBUG
344                 (void)printf("Location is %d, looking for tunnel to room %d\n",
345                              scratchloc + 1, path[k] + 1);
346 #endif
347
348                 /* 810 FOR K1=1 TO 3 */
349                 for (k1 = 0; k1 < 3; k1++) {
350                         /* 815 IF S(L,K1)=P(K) THEN 895 */
351                         if (cave[scratchloc][k1] == path[k]) {
352                                 /*
353                                  * This is the only bit of the translation I'm
354                                  * not sure about.  It requires the trajectory
355                                  * of the arrow to be a path.  Without it, all
356                                  * rooms on the trajectory would be required by
357                                  * the above to be adjacent to the player,
358                                  * making for a trivial game --- just move to
359                                  * where you smell a wumpus and shoot into all
360                                  * adjacent passages! However, I can't find an
361                                  * equivalent in the BASIC.
362                                  */
363                                 scratchloc = path[k];
364
365 #ifdef DEBUG
366                                 (void)printf("Found tunnel to room %d\n",
367                                              scratchloc + 1);
368 #endif
369
370                                 /* this simulates logic at 895 in the BASIC code
371                                  */
372                                 check_shot();
373                                 if (finished != NOT) {
374                                         return;
375                                 }
376                                 goto nextpath;
377                         }
378                         /* 820 NEXT K1 */
379                 }
380
381                 /* 825 REM *** NO TUNNEL FOR ARROW *** */
382                 /* 830 L=S(L,FNB(1)) */
383                 scratchloc = cave[scratchloc][FNB()];
384
385 #ifdef DEBUG
386                 (void)printf("No tunnel for room %d, new location is %d\n",
387                              path[k] + 1, scratchloc + 1);
388 #endif
389
390                 /* 835 GOTO 900 */
391                 check_shot();
392                 if (finished != NOT) {
393                         return;
394                 }
395
396         /* 840 NEXT K                                                   */
397         nextpath:;
398         }
399
400         if (finished == NOT) {
401                 /* 845 PRINT "MISSED" */
402                 (void)puts("MISSED");
403
404                 /* 850 L=L(1) */
405                 scratchloc = loc[YOU];
406
407                 /* 855 REM *** MOVE WUMPUS *** */
408                 /* 860 GOSUB 935 */
409                 move_wumpus();
410
411                 /* 865 REM *** AMMO CHECK *** */
412                 /* 870 A=A-1 */
413                 /* 875 IF A>0 THEN 885 */
414                 /* 880 F=-1 */
415                 if (--arrows <= 0) {
416                         finished = LOSE;
417                 }
418         }
419
420         /* 885 RETURN                                                   */
421 }
422
423 void check_shot() {
424         /* 890 REM *** SEE IF ARROW IS AT L(1) OR AT L(2) */
425         /* 895 L=P(K)                                                   */
426
427         /* 900 IF L<>L(2) THEN 920 */
428         /* 905 PRINT "AHA! YOU GOT THE WUMPUS!"                         */
429         /* 910 F=1 */
430         /* 915 RETURN                                                   */
431         if (scratchloc == loc[WUMPUS]) {
432                 (void)puts("AHA! YOU GOT THE WUMPUS!");
433                 finished = WIN;
434         }
435
436         /* 920 IF L<>L(1) THEN 840 */
437         /* 925 PRINT "OUCH! ARROW GOT YOU!" */
438         /* 930 GOTO 880                                                 */
439         else if (scratchloc == loc[YOU]) {
440                 (void)puts("OUCH! ARROW GOT YOU!");
441                 finished = LOSE;
442         }
443 }
444
445 void move_wumpus() {
446         /* 935 REM *** MOVE WUMPUS ROUTINE ***                          */
447         /* 940 K=FNC(0)                                                 */
448         k = FNC();
449
450         /* 945 IF K=4 THEN 955                                          */
451         /* 950 L(2)=S(L(2),K)                                           */
452         if (k < 3) {
453                 loc[WUMPUS] = cave[loc[WUMPUS]][k];
454         }
455
456 #ifdef DEBUG
457         (void)printf("Wumpus location is now room %d\n", loc[WUMPUS] + 1);
458 #endif
459
460         /* 955 IF L(2)<>L THEN 970 */
461         if (loc[WUMPUS] != loc[YOU]) {
462                 return;
463         }
464
465         /* 960 PRINT "TSK TSK TSK - WUMPUS GOT YOU!"                    */
466         (void)puts("TSK TSK TSK - WUMPUS GOT YOU!");
467
468         /* 965 F=-1 */
469         finished = LOSE;
470
471         /* 970 RETURN                                                   */
472 }
473
474 void move() {
475         /* 975 REM *** MOVE ROUTINE ***                                 */
476         /* 980 F=0 */
477         finished = NOT;
478
479 badmove:
480         /* 985 PRINT "WHERE TO"; */
481         /* 990 INPUT L                                                  */
482         scratchloc = getnum("WHERE TO");
483
484         /* 995 IF L<1 THEN 985                                          */
485         /* 1000 IF L>20 THEN 985 */
486         if (scratchloc < 1 || scratchloc > 20) {
487                 goto badmove;
488         }
489         scratchloc--;
490
491         /* 1005 FOR K=1 TO 3                                            */
492         for (k = 0; k < 3; k++) {
493                 /* 1010 REM *** CHECK IF LEGAL MOVE *** */
494                 /* 1015 IF S(L(1),K)=L THEN 1045 */
495                 if (cave[loc[YOU]][k] == scratchloc) {
496                         goto goodmove;
497                 }
498
499                 /* 1020 NEXT K */
500         }
501
502         /* 1025 IF L=L(1) THEN 1045 */
503         if (scratchloc != loc[YOU]) {
504                 /* 1030 PRINT "NOT POSSIBLE -"; */
505                 (void)puts("NOT POSSIBLE -");
506
507                 /* 1035 GOTO 985 */
508                 goto badmove;
509         }
510
511 goodmove:
512         /* 1040 REM *** CHECK FOR HAZARDS ***                           */
513         /* 1045 L(1)=L                                                  */
514         loc[YOU] = scratchloc;
515
516         if (scratchloc == loc[WUMPUS]) {
517                 /* 1050 REM *** WUMPUS *** */
518                 /* 1055 IF L<>L(2) THEN 1090 */
519                 /* 1060 PRINT "... OOPS! BUMPED A WUMPUS!" */
520                 /* 1065 REM *** MOVE WUMPUS *** */
521                 /* 1070 GOSUB 940 */
522                 /* 1075 IF F=0 THEN 1090 */
523                 /* 1080 RETURN */
524                 (void)puts("... OOPS! BUMPED A WUMPUS!");
525                 move_wumpus();
526                 if (finished < 0) {
527                         return;
528                 }
529                 /* Fall through since Wumpus could have been in a pit or bat
530                  * room */
531         }
532         if (scratchloc == loc[PIT1] || scratchloc == loc[PIT2]) {
533                 /* 1085 REM *** PIT *** */
534                 /* 1090 IF L=L(3) THEN 1100 */
535                 /* 1095 IF L<>L(4) THEN 1120 */
536                 /* 1100 PRINT "YYYYIIIIEEEE . . . FELL IN PIT" */
537                 /* 1105 F=-1 */
538                 /* 1110 RETURN */
539                 (void)puts("YYYYIIIIEEEE . . . FELL IN PIT");
540                 finished = LOSE;
541                 return;
542         }
543         if (scratchloc == loc[BATS1] || scratchloc == loc[BATS2]) {
544                 /* 1115 REM *** BATS *** */
545                 /* 1120 IF L=L(5) THEN 1130 */
546                 /* 1125 IF L<>L(6) THEN 1145 */
547                 /* 1130 PRINT "ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!"
548                  */
549                 /* 1135 L=FNA(1) */
550                 /* 1140 GOTO 1045 */
551                 /* 1145 RETURN */
552                 /* 1150 END */
553                 (void)puts("ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!");
554                 scratchloc = loc[YOU] = FNA();
555                 goto goodmove;
556         }
557 }
558
559 int main(argc, argv)
560 int argc;
561 char *argv[];
562 {
563         int c;
564
565         if (argc >= 2 && strcmp(argv[1], "-s") == 0) {
566                 srand(atoi(argv[2]));
567         } else {
568                 srand((int)time((long *)0));
569         }
570
571         /* 15 PRINT "INSTRUCTIONS (Y-N)"; */
572         /* 20 INPUT I$                                                  */
573         c = getlet("INSTRUCTIONS (Y-N)");
574
575         /* 25 IF I$="N" THEN 35                                         */
576         /* 30 GOSUB 375                                                 */
577         /* 35 GOTO 80                                                   */
578         if (c == 'Y')
579                 print_instructions();
580
581         /* 150 REM *** LOCATE L ARRAY ITEMS ***                         */
582         /* 155 REM *** 1-YOU, 2-WUMPUS, 3&4-PITS, 5&6-BATS ***          */
583         /* 160 DIM L(6)                                                 */
584         /* 165 DIM M(6)                                                 */
585 badlocs:
586         /* 170 FOR J=1 TO 6 */
587         /* 175 L(J)=FNA(0) */
588         /* 180 M(J)=L(J) */
589         /* 185 NEXT J                                                   */
590         for (j = 0; j < LOCS; j++) {
591                 loc[j] = save[j] = FNA();
592         }
593
594         /* 190 REM *** CHECK FOR CROSSOVERS (IE L(1)=L(2), ETC) ***
595          */
596         /* 195 FOR J=1 TO 6 */
597         /* 200 FOR K=1 TO 6 */
598         /* 205 IF J=K THEN 215                                          */
599         /* 210 IF L(J)=L(K) THEN 170                                    */
600         /* 215 NEXT K                                                   */
601         /* 220 NEXT J                                                   */
602         for (j = 0; j < LOCS; j++) {
603                 for (k = 0; k < LOCS; k++) {
604                         if (j == k) {
605                                 continue;
606                         } else if (loc[j] == loc[k]) {
607                                 goto badlocs;
608                         }
609                 }
610         }
611
612         /* 225 REM *** SET NO. OF ARROWS ***                            */
613 newgame:
614         /* 230 A=5 */
615         /* 235 L=L(1)                                                   */
616         arrows = 5;
617         scratchloc = loc[YOU];
618
619         /* 240 REM *** RUN THE GAME ***                                 */
620         /* 245 PRINT "HUNT THE WUMPUS"                                  */
621         (void)puts("HUNT THE WUMPUS");
622
623 #ifdef DEBUG
624         (void)printf("Wumpus is at %d, pits at %d & %d, bats at %d & %d\n",
625                      loc[WUMPUS] + 1, loc[PIT1] + 1, loc[PIT2] + 1,
626                      loc[BATS1] + 1, loc[BATS2] + 1);
627 #endif
628
629 nextmove:
630         /* 250 REM *** HAZARD WARNING AND LOCATION ***                  */
631         /* 255 GOSUB 585 */
632         check_hazards();
633
634         /* 260 REM *** MOVE OR SHOOT *** */
635         /* 265 GOSUB 670 */
636         /* 270 ON O GOTO 280,300 */
637         if (move_or_shoot()) {
638                 /* 275 REM *** SHOOT *** */
639                 /* 280 GOSUB 715 */
640                 shoot();
641
642                 /* 285 IF F=0 THEN 255 */
643                 if (finished == NOT) {
644                         goto nextmove;
645                 }
646
647                 /* 290 GOTO 310 */
648         } else {
649                 /* 295 REM *** MOVE *** */
650                 /* 300 GOSUB 975 */
651                 move();
652
653                 /* 305 IF F=0 THEN 255 */
654                 if (finished == NOT) {
655                         goto nextmove;
656                 }
657         }
658
659         /* 310 IF F>0 THEN 335                                          */
660         if (finished == LOSE) {
661                 /* 315 REM *** LOSE *** */
662                 /* 320 PRINT "HA HA HA - YOU LOSE!" */
663                 /* 325 GOTO 340 */
664                 (void)puts("HA HA HA - YOU LOSE!");
665         } else {
666                 /* 330 REM *** WIN *** */
667                 /* 335 PRINT "HEE HEE HEE - THE WUMPUS'LL GET YOU NEXT TIME!!"
668                  */
669                 (void)puts("HEE HEE HEE - THE WUMPUS'LL GET YOU NEXT TIME!!");
670         }
671
672         /* 340 FOR J=1 TO 6 */
673         /* 345 L(J)=M(J) */
674         /* 350 NEXT J                                                   */
675         for (j = YOU; j < LOCS; j++) {
676                 loc[j] = save[j];
677         }
678
679         /* 355 PRINT "SAME SETUP (Y-N)"; */
680         /* 360 INPUT I$                                                 */
681         c = getlet("SAME SETUP (Y-N)");
682
683         /* 365 IF I$<>"Y"THEN 170 */
684         /* 370 GOTO 230                                                 */
685         if (c != 'Y') {
686                 goto badlocs;
687         } else {
688                 goto newgame;
689         }
690 }
691
692 /* wumpus.c ends here */