📄 wump.c
字号:
/* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Dave Taylor, of Intuitive Systems. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)wump.c 8.1 (Berkeley) 5/31/93";#endif /* not lint *//* * A very new version of the age old favorite Hunt-The-Wumpus game that has * been a part of the BSD distribution of Unix for longer than us old folk * would care to remember. */#include <sys/types.h>#include <sys/file.h>#include <stdio.h>#include "pathnames.h"/* some defines to spec out what our wumpus cave should look like */#define MAX_ARROW_SHOT_DISTANCE 6 /* +1 for '0' stopper */#define MAX_LINKS_IN_ROOM 25 /* a complex cave */#define MAX_ROOMS_IN_CAVE 250#define ROOMS_IN_CAVE 20#define MIN_ROOMS_IN_CAVE 10#define LINKS_IN_ROOM 3#define NUMBER_OF_ARROWS 5#define PIT_COUNT 3#define BAT_COUNT 3#define EASY 1 /* levels of play */#define HARD 2/* some macro definitions for cleaner output */#define plural(n) (n == 1 ? "" : "s")/* simple cave data structure; +1 so we can index from '1' not '0' */struct room_record { int tunnel[MAX_LINKS_IN_ROOM]; int has_a_pit, has_a_bat;} cave[MAX_ROOMS_IN_CAVE+1];/* * global variables so we can keep track of where the player is, how * many arrows they still have, where el wumpo is, and so on... */int player_loc = -1; /* player location */int wumpus_loc = -1; /* The Bad Guy location */int level = EASY; /* level of play */int arrows_left; /* arrows unshot */#ifdef DEBUGint debug = 0;#endifint pit_num = PIT_COUNT; /* # pits in cave */int bat_num = BAT_COUNT; /* # bats */int room_num = ROOMS_IN_CAVE; /* # rooms in cave */int link_num = LINKS_IN_ROOM; /* links per room */int arrow_num = NUMBER_OF_ARROWS; /* arrow inventory */char answer[20]; /* user input */main(argc, argv) int argc; char **argv;{ extern char *optarg; int c;#ifdef DEBUG while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != EOF)#else while ((c = getopt(argc, argv, "a:b:hp:r:t:")) != EOF)#endif switch (c) { case 'a': arrow_num = atoi(optarg); break; case 'b': bat_num = atoi(optarg); break;#ifdef DEBUG case 'd': debug = 1; break;#endif case 'h': level = HARD; break; case 'p': pit_num = atoi(optarg); break; case 'r': room_num = atoi(optarg); if (room_num < MIN_ROOMS_IN_CAVE) { (void)fprintf(stderr, "No self-respecting wumpus would live in such a small cave!\n"); exit(1); } if (room_num > MAX_ROOMS_IN_CAVE) { (void)fprintf(stderr, "Even wumpii can't furnish caves that large!\n"); exit(1); } break; case 't': link_num = atoi(optarg); if (link_num < 2) { (void)fprintf(stderr, "Wumpii like extra doors in their caves!\n"); exit(1); } break; case '?': default: usage(); } if (link_num > MAX_LINKS_IN_ROOM || link_num > room_num - (room_num / 4)) { (void)fprintf(stderr,"Too many tunnels! The cave collapsed!\n(Fortunately, the wumpus escaped!)\n"); exit(1); } if (level == HARD) { bat_num += ((random() % (room_num / 2)) + 1); pit_num += ((random() % (room_num / 2)) + 1); } if (bat_num > room_num / 2) { (void)fprintf(stderr,"The wumpus refused to enter the cave, claiming it was too crowded!\n"); exit(1); } if (pit_num > room_num / 2) { (void)fprintf(stderr,"The wumpus refused to enter the cave, claiming it was too dangerous!\n"); exit(1); } instructions(); cave_init(); /* and we're OFF! da dum, da dum, da dum, da dum... */ (void)printf("\nYou're in a cave with %d rooms and %d tunnels leading from each room.\n\There are %d bat%s and %d pit%s scattered throughout the cave, and your\n\quiver holds %d custom super anti-evil Wumpus arrows. Good luck.\n", room_num, link_num, bat_num, plural(bat_num), pit_num, plural(pit_num), arrow_num); for (;;) { initialize_things_in_cave(); arrows_left = arrow_num; do { display_room_stats(); (void)printf("Move or shoot? (m-s) "); (void)fflush(stdout); if (!fgets(answer, sizeof(answer), stdin)) break; } while (!take_action()); if (!getans("\nCare to play another game? (y-n) ")) exit(0); if (getans("In the same cave? (y-n) ")) clear_things_in_cave(); else cave_init(); } /* NOTREACHED */}display_room_stats(){ register int i; /* * Routine will explain what's going on with the current room, as well * as describe whether there are pits, bats, & wumpii nearby. It's * all pretty mindless, really. */ (void)printf("\nYou are in room %d of the cave, and have %d arrow%s left.\n", player_loc, arrows_left, plural(arrows_left)); if (bats_nearby()) (void)printf("*rustle* *rustle* (must be bats nearby)\n"); if (pit_nearby()) (void)printf("*whoosh* (I feel a draft from some pits).\n"); if (wump_nearby()) (void)printf("*sniff* (I can smell the evil Wumpus nearby!)\n"); (void)printf("There are tunnels to rooms %d, ", cave[player_loc].tunnel[0]); for (i = 1; i < link_num - 1; i++) if (cave[player_loc].tunnel[i] <= room_num) (void)printf("%d, ", cave[player_loc].tunnel[i]); (void)printf("and %d.\n", cave[player_loc].tunnel[link_num - 1]);}take_action(){ /* * Do the action specified by the player, either 'm'ove, 's'hoot * or something exceptionally bizarre and strange! Returns 1 * iff the player died during this turn, otherwise returns 0. */ switch (*answer) { case 'M': case 'm': /* move */ return(move_to(answer + 1)); case 'S': case 's': /* shoot */ return(shoot(answer + 1)); case 'Q': case 'q': case 'x': exit(0); case '\n': return(0); } if (random() % 15 == 1) (void)printf("Que pasa?\n"); else (void)printf("I don't understand!\n"); return(0);}move_to(room_number) char *room_number;{ int i, just_moved_by_bats, next_room, tunnel_available; /* * This is responsible for moving the player into another room in the * cave as per their directions. If room_number is a null string, * then we'll prompt the user for the next room to go into. Once * we've moved into the room, we'll check for things like bats, pits, * and so on. This routine returns 1 if something occurs that kills * the player and 0 otherwise... */ tunnel_available = just_moved_by_bats = 0; next_room = atoi(room_number); /* crap for magic tunnels */ if (next_room == room_num + 1 && cave[player_loc].tunnel[link_num-1] != next_room) ++next_room; while (next_room < 1 || next_room > room_num + 1) { if (next_room < 0 && next_room != -1)(void)printf("Sorry, but we're constrained to a semi-Euclidean cave!\n"); if (next_room > room_num + 1)(void)printf("What? The cave surely isn't quite that big!\n"); if (next_room == room_num + 1 && cave[player_loc].tunnel[link_num-1] != next_room) { (void)printf("What? The cave isn't that big!\n"); ++next_room; } (void)printf("To which room do you wish to move? "); (void)fflush(stdout); if (!fgets(answer, sizeof(answer), stdin)) return(1); next_room = atoi(answer); } /* now let's see if we can move to that room or not */ tunnel_available = 0; for (i = 0; i < link_num; i++) if (cave[player_loc].tunnel[i] == next_room) tunnel_available = 1; if (!tunnel_available) { (void)printf("*Oof!* (You hit the wall)\n"); if (random() % 6 == 1) {(void)printf("Your colorful comments awaken the wumpus!\n"); move_wump(); if (wumpus_loc == player_loc) { wump_kill(); return(1); } } return(0); } /* now let's move into that room and check it out for dangers */ if (next_room == room_num + 1) jump(next_room = (random() % room_num) + 1); player_loc = next_room; for (;;) { if (next_room == wumpus_loc) { /* uh oh... */ wump_kill(); return(1); } if (cave[next_room].has_a_pit) if (random() % 12 < 2) { pit_survive(); return(0); } else { pit_kill(); return(1); } if (cave[next_room].has_a_bat) { (void)printf("*flap* *flap* *flap* (humongous bats pick you up and move you%s!)\n", just_moved_by_bats ? " again": ""); next_room = player_loc = (random() % room_num) + 1; just_moved_by_bats = 1; } else break; } return(0);}shoot(room_list) char *room_list;{ int chance, next, roomcnt; int j, arrow_location, link, ok; char *p, *strtok(); /* * Implement shooting arrows. Arrows are shot by the player indicating * a space-separated list of rooms that the arrow should pass through; * if any of the rooms they specify are not accessible via tunnel from * the room the arrow is in, it will instead fly randomly into another * room. If the player hits the wumpus, this routine will indicate * such. If it misses, this routine will *move* the wumpus one room. * If it's the last arrow, the player then dies... Returns 1 if the * player has won or died, 0 if nothing has happened. */ arrow_location = player_loc; for (roomcnt = 1;; ++roomcnt, room_list = NULL) { if (!(p = strtok(room_list, " \t\n"))) if (roomcnt == 1) { (void)printf( "The arrow falls to the ground at your feet!\n"); return(0); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -