/* UNIX ANGBAND Version 5.0 main.c: initialization, main() function and main loop Copyright (c) 1989 James E. Wilson, Robert A. Koeneke This software may be copied and distributed for educational, research, and not for profit purposes provided that this copyright and statement are included in all such copies. */ /* Original copyright message follows. */ /* ANGBAND Version 4.8 COPYRIGHT (c) Robert Alan Koeneke */ /* */ /* I lovingly dedicate this game to hackers and adventurers */ /* everywhere... */ /* */ /* */ /* Designer and Programmer : Robert Alan Koeneke */ /* University of Oklahoma */ /* */ /* Assistant Programmers : Jimmey Wayne Todd */ /* University of Oklahoma */ /* */ /* Gary D. McAdoo */ /* University of Oklahoma */ /* */ /* UNIX Port : James E. Wilson */ /* UC Berkeley */ /* wilson@ernie.Berkeley.EDU */ /* ucbvax!ucbernie!wilson */ /* */ /* MSDOS Port : Don Kneller */ /* 1349 - 10th ave */ /* San Francisco, CA 94122 */ /* kneller@cgl.ucsf.EDU */ /* ...ucbvax!ucsfcgl!kneller */ /* kneller@ucsf-cgl.BITNET */ /* */ /* BRUCE ANGBAND : Christopher Stuart */ /* Monash University */ /* Melbourne, Victoria, AUSTRALIA */ /* cjs@moncsbruce.oz */ /* */ /* ANGBAND may be copied and modified freely as long as the above */ /* credits are retained. No one who-so-ever may sell or market */ /* this software in any form without the expressed written consent */ /* of the author Robert Alan Koeneke. */ /* */ #include /* include before constant, because param.h defines NULL incorrectly */ #ifndef USG #include #include #include #include #endif #include "constant.h" #include "config.h" #include "types.h" #include "externs.h" #ifdef USG #include #else #include #endif #ifdef ultrix #include #endif #include #ifndef ibm032 #include #endif #if defined(ultrix) || defined(USG) void perror(); #endif #ifdef USG void exit(); #endif /* Lets do all prototypes correctly.... -CWS */ #ifndef NO_LINT_ARGS #ifdef __STDC__ static int d_check(char *); #else static int d_check(); #endif static void init_m_level(); static void init_t_level(); static void char_inven_init(); #endif #if (COST_ADJ != 100) static void price_adjust(); #endif int unfelt = TRUE; int be_nasty = FALSE; int rating = 0; int peek = FALSE; int player_uid; int quests[MAX_QUESTS]; creature_type ghost; /* Unique artifact weapon flags, even though some are in the wrong place!*/ int32 GROND, RINGIL, AEGLOS, ARUNRUTH, MORMEGIL, ANGRIST, GURTHANG, CALRIS, ANDURIL, STING, ORCRIST, GLAMDRING, DURIN, AULE, THUNDERFIST, BLOODSPIKE, DOOMCALLER, NARTHANC, NIMTHANC, DETHANC, GILETTAR, RILIA, BELANGIL, BALLI, LOTHARANG, FIRESTAR, ERIRIL, CUBRAGOL, BARD, COLLUIN, HOLCOLLETH, TOTILA, PAIN, ELVAGIL, AGLARANG, EORLINGAS, BARUKKHELED, WRATH, HARADEKKET, MUNDWINE, GONDRICAM, ZARCUTHRA, CARETH, FORASGIL, CRISDURIAN, COLANNON, HITHLOMIR, THALKETTOTH, ARVEDUI, THRANDUIL, THENGEL, HAMMERHAND, CELEBORN, THROR, MAEDHROS, OLORIN, ANGUIREL, OROME, EONWE, THEODEN, ULMO, OSONDIR, TURMIL, TIL, DEATHWREAKER, AVAVIR, TARATOL; /* Unique artifact armor flags */ int32 DOR_LOMIN, NENYA, NARYA, VILYA, BELEGENNON, FEANOR, ISILDUR, SOULKEEPER, FINGOLFIN, ANARION, POWER, PHIAL, BELEG, DAL, PAURHACH, PAURNIMMEN, PAURAEGEN, PAURNEN, CAMMITHRIM, CAMBELEG, INGWE, CARLAMMAS, HOLHENNETH, AEGLIN, CAMLOST, NIMLOTH, NAR, BERUTHIEL, GORLIM, ELENDIL, THORIN, CELEGORM, THRAIN, GONDOR, THINGOL, THORONGIL, LUTHIEN, TUOR, ROHAN, TULKAS, NECKLACE, BARAHIR, CASPANION, RAZORBACK, BLADETURNER; /* Initialize, restore, and get the ball rolling. -RAK- */ int main(argc, argv) int argc; char *argv[]; { int generate, i; int result=FALSE, FIDDLE=FALSE; #ifndef __MINT__ FILE *fp; #endif int new_game = FALSE; int force_rogue_like = FALSE; int force_keys_to = FALSE; #ifndef __MINT__ char temphost[MAXHOSTNAMELEN+1], thishost[MAXHOSTNAMELEN+1], discard[120]; #endif char string[80]; struct rlimit rlp; #if !defined(MSDOS) && !defined(HPUX) /* Disable core dumps */ getrlimit(RLIMIT_CORE,&rlp); rlp.rlim_cur=0; setrlimit(RLIMIT_CORE,&rlp); #endif /* default command set defined in config.h file */ rogue_like_commands = ROGUE_LIKE; strcpy(py.misc.name, "\0"); #ifndef MSDOS #ifndef SET_UID (void) umask(0); #endif #endif #ifdef SECURE Authenticate(); #endif #ifdef MSDOS /* -CFT */ msdos_init(); /* set up some screen stuff + get cnf file */ #endif #ifdef NEW_FILEPATHS /* This looks like a good spot to check for our files. - [cjh] */ get_file_paths(); #endif /* call this routine to grab a file pointer to the highscore file */ /* and prepare things to relinquish setuid privileges */ init_scorefile(); /* Call this routine to grab a file pointer to the log files and start the backup process before relinquishing setuid privileges */ init_files(); #ifndef MSDOS if ((player_uid = getuid()) < 0) { perror("Can't set permissions correctly! Getuid call failed.\n"); exit(0); } user_name(py.misc.name, player_uid); #else user_name(py.misc.name); #endif #if defined(SET_UID) && !defined(SECURE) if (setuid(geteuid()) != 0) { perror("Can't set permissions correctly! Setuid call failed.\n"); exit(0); } #endif #ifdef ANNOY if (player_uid == ANNOY) be_nasty=TRUE; else be_nasty=FALSE; #else be_nasty=FALSE; #endif #if !defined(MSDOS) && !defined(__MINT__) (void)gethostname(thishost, (sizeof thishost) - 1); /* get host */ if ((fp=my_tfopen(ANGBAND_LOAD, "r")) == NULL) { perror("Can't get load-check.\n"); exit(0); } do { if (fscanf(fp, "%s%d", temphost, &LOAD) == EOF) { LOAD=100; break; } if (temphost[0]=='#') (void)fgets(discard, (sizeof discard)-1, fp); /* Comment */ } while (strcmp(temphost,thishost) && strcmp(temphost,"localhost")); /* Until we've found ourselves */ fclose(fp); #endif /* use curses */ init_curses(); /* check for user interface option */ for (--argc, ++argv; argc > 0 && argv[0][0] == '-'; --argc, ++argv) switch (argv[0][1]) { case 'A': case 'a': if (is_wizard(player_uid)) peek=TRUE; else goto usage; break; case 'N': case 'n': new_game = TRUE; break; case 'O': case 'o': /* rogue_like_commands may be set in get_char(), so delay this until after read savefile if any */ force_rogue_like = TRUE; force_keys_to = FALSE; break; case 'R': case 'r': force_rogue_like = TRUE; force_keys_to = TRUE; break; case 'S': case 's': init_curses(); if (isdigit((int)argv[0][2])) display_scores(0, atoi(&argv[0][2])); else display_scores(0, 10); exit_game(); case 'D': case 'd': if (!is_wizard(player_uid)) goto usage; if (isdigit((int)argv[0][2])) delete_entry(atoi(&argv[0][2])); else display_scores(0, 10); exit_game(); case 'F': case 'f': if (is_wizard(player_uid) || to_be_wizard) FIDDLE=TRUE; else goto usage; break; case 'W': case 'w': if (is_wizard(player_uid)) to_be_wizard = TRUE; else goto usage; #ifndef MSDOS if (isdigit((int)argv[0][2])) player_uid = atoi(&argv[0][2]); #endif break; case 'u': case 'U': if (argv[0][2]) { strcpy(py.misc.name, &argv[0][2]); d_check(py.misc.name); NO_SAVE=TRUE; } else { goto usage; } break; default: usage: if (is_wizard(player_uid)) { #ifdef MSDOS puts("Usage: angband [-afnorw] [-s] [-d] "); #else puts("Usage: angband [-afnor] [-s] [-u] [-w] [-d]"); #endif puts(" a Activate \"peek\" mode"); puts(" d Delete high score number "); puts(" f Enter \"fiddle\" mode"); puts(" n Start a new character"); puts(" o Use original command set"); puts(" r Use the \"rogue-like\" command set"); puts(" s Show high scores. Show scores, or first 10"); #ifdef MSDOS puts(" w Start in wizard mode"); puts(" Play with savefile named "); #else puts(" w Start in wizard mode, as uid number "); puts(" u Play with character named "); #endif puts("Each option must be listed separately (ie '-r -n', not '-rn')"); } else { #ifdef MSDOS puts("Usage: angband [-nor] [-s] "); #else puts("Usage: angband [-nor] [-s] [-u]"); #endif puts(" n Start a new character"); puts(" o Use original command set"); puts(" r Use the \"rogue-like\" command set"); puts(" s Show high scores. Show scores, or first 10"); #ifdef MSDOS puts(" Play with savefile named "); #else puts(" u Play with character named "); #endif puts("Each option must be listed separately (ie '-r -n', not '-rn')"); } exit(1); } /* catch those nasty signals */ /* must come after init_curses as some of the signal handlers use curses */ init_signals(); /* Check operating hours */ /* If not wizard No_Control_Y */ read_times(); /* Some necessary initializations */ /* all made into constants or initialized in variables.c */ #if (COST_ADJ != 100) price_adjust(); #endif /* Grab a random seed from the clock */ init_seeds(); /* Init monster and treasure levels for allocate */ init_m_level(); init_t_level(); /* Init the store inventories */ store_init(); #ifndef MAC /* On Mac, if -n is passed, no savefile is used */ /* If -n is not passed, the calling routine will know savefile name, hence, this code is not necessary */ #endif (void) sprintf(savefile, "%s/%d%s", ANGBAND_SAV, player_uid, py.misc.name); /* This restoration of a saved character may get ONLY the monster memory. In this case, get_char returns false. It may also resurrect a dead character (if you are the wizard). In this case, it returns true, but also sets the parameter "generate" to true, as it does not recover any cave details. */ if (FIDDLE) { if (get_char(&generate)) save_char(); exit_game(); } result = get_char(&generate); /* enter wizard mode before showing the character display, but must wait until after get_char in case it was just a resurrection */ if (to_be_wizard) if (!enter_wiz_mode()) exit_game(); if ((new_game == FALSE) && result) { change_name(); /* could be restoring a dead character after a signal or HANGUP */ if (py.misc.chp < 0) death = TRUE; } else { /* Create character */ /* Unique Weapons, Armour and Rings */ GROND=0; RINGIL=0; AEGLOS=0; ARUNRUTH=0; MORMEGIL=0; ANGRIST=0; GURTHANG=0; CALRIS=0; ANDURIL=0; STING=0; ORCRIST=0; GLAMDRING=0; DURIN=0; AULE=0; THUNDERFIST=0; BLOODSPIKE=0; DOOMCALLER=0; NARTHANC=0; NIMTHANC=0; DETHANC=0; GILETTAR=0; RILIA=0; BELANGIL=0; BALLI=0; LOTHARANG=0; FIRESTAR=0; ERIRIL=0; CUBRAGOL=0; BARD=0; COLLUIN=0; HOLCOLLETH=0; TOTILA=0; PAIN=0; ELVAGIL=0; AGLARANG=0; EORLINGAS=0; BARUKKHELED=0; WRATH=0; HARADEKKET=0; MUNDWINE=0; GONDRICAM=0; ZARCUTHRA=0; CARETH=0; FORASGIL=0; CRISDURIAN=0; COLANNON=0; HITHLOMIR=0; THALKETTOTH=0; ARVEDUI=0; THRANDUIL=0; THENGEL=0; HAMMERHAND=0; CELEGORM=0; THROR=0; MAEDHROS=0; OLORIN=0; ANGUIREL=0; OROME=0; EONWE=0; THEODEN=0; ULMO=0; OSONDIR=0; TURMIL=0; TIL=0; DEATHWREAKER=0; AVAVIR=0; TARATOL=0; DOR_LOMIN=0; BELEGENNON=0; FEANOR=0; ISILDUR=0; SOULKEEPER=0; FINGOLFIN=0; ANARION=0; BELEG=0; DAL=0; PAURHACH=0; PAURNIMMEN=0; PAURAEGEN=0; PAURNEN=0; CAMMITHRIM=0; CAMBELEG=0; HOLHENNETH=0; AEGLIN=0; CAMLOST=0; NIMLOTH=0; NAR=0; BERUTHIEL=0; GORLIM=0; THORIN=0; CELEBORN=0; GONDOR=0; THINGOL=0; THORONGIL=0; LUTHIEN=0; TUOR=0; ROHAN=0; CASPANION=0; RAZORBACK=0; BLADETURNER=0; NARYA=0; NENYA=0; VILYA=0; POWER=0; PHIAL=0; INGWE=0; CARLAMMAS=0; TULKAS=0; NECKLACE=0; BARAHIR=0; ELENDIL=0; THRAIN=0; for (i=0; i