[BACK]Return to main.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / arogue5

Annotation of early-roguelike/arogue5/main.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:  * Rogue
                      3:  *
                      4:  * Advanced Rogue
                      5:  * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
                      6:  * All rights reserved.
                      7:  *
                      8:  * Based on "Rogue: Exploring the Dungeons of Doom"
                      9:  * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     10:  * All rights reserved.
                     11:  *
                     12:  * See the file LICENSE.TXT for full copyright and licensing information.
                     13:  */
                     14:
                     15: #include "curses.h"
                     16: #include <stdlib.h>
                     17: #include <string.h>
                     18: #include <fcntl.h>
                     19: #include <sys/stat.h>
                     20: #include <limits.h>
                     21: #include <signal.h>
                     22: #include <time.h>
                     23: #include <errno.h>
                     24: #include "mach_dep.h"
                     25: #include "network.h"
                     26: #include "rogue.h"
                     27:
                     28: #ifdef CHECKTIME
                     29: static int num_checks;         /* times we've gone over in checkout() */
                     30: #endif
                     31:
                     32: /*
                     33:  * fruits that you get at startup
                     34:  */
                     35: static char *funfruit[] = {
                     36:        "candleberry",  "caprifig",     "dewberry",     "elderberry",
                     37:        "gooseberry",   "guanabana",    "hagberry",     "ilama",
                     38:        "imbu",         "jaboticaba",   "jujube",       "litchi",
                     39:        "mombin",       "pitanga",      "prickly pear", "rambutan",
                     40:        "sapodilla",    "soursop",      "sweetsop",     "whortleberry",
                     41:        "jellybean",    "apple",        "strawberry",   "blueberry",
                     42:        "peach",        "banana"
                     43: };
                     44: #define NFRUIT (sizeof(funfruit) / sizeof (char *))
                     45:
                     46: void open_records(void);
                     47: bool holiday(void);
                     48:
                     49: int
                     50: main(int argc, char *argv[], char *envp[])
                     51: {
                     52:     register char *env;
                     53:     char *roguedir;
                     54:
                     55:     roguedir = md_getroguedir();
                     56:     md_init();
                     57:
                     58:     /*
                     59:      * get home and options from environment
                     60:      */
                     61:     strncpy(home,md_gethomedir(),LINELEN);
                     62:
                     63: #ifdef SAVEDIR
                     64:     if (argc >= 3 && !strcmp(argv[1], "-n")) {
                     65:         use_savedir = TRUE;
                     66:         strncpy(whoami, argv[2], LINELEN);
                     67:         whoami[LINELEN - 1] = '\0';
                     68:         if (snprintf(file_name, 256, "%s/%d-%s.ar5sav", SAVEDIR,
                     69:                      md_getuid(), whoami) >= 256)
                     70:         {
                     71:             /* The name is too long */
                     72:             use_savedir = FALSE;
                     73:         }
                     74:     }
                     75: #endif
                     76:     /* Get default save file */
                     77:     if (!use_savedir) {
                     78:         strcpy(file_name, home);
                     79:         strcat(file_name, "arogue58.sav");
                     80:     }
                     81:
                     82: #ifdef SCOREFILE
                     83:     strncpy(score_file, SCOREFILE, LINELEN);
                     84:     score_file[LINELEN - 1] = '\0';
                     85: #else
                     86:     /* Get default score file */
                     87:     strcpy(score_file, roguedir);
                     88:
                     89:     if (*score_file)
                     90:         strcat(score_file,"/");
                     91:
                     92:     strcat(score_file, "arogue58.scr");
                     93: #endif
                     94:
                     95:     if ((env = getenv("ROGUEOPTS")) != NULL)
                     96:        parse_opts(env);
                     97:
                     98:     if (!use_savedir && whoami[0] == '\0')
                     99:         strucpy(whoami, md_getusername(), strlen(md_getusername()));
                    100:
                    101:     if (env == NULL || fruit[0] == '\0') {
                    102:        md_srand(md_random_seed());
                    103:        strcpy(fruit, funfruit[rnd(NFRUIT)]);
                    104:     }
                    105:
                    106:     open_records();
                    107:     if (!use_savedir)
                    108:         md_normaluser();
                    109:
                    110:     /*
                    111:      * check for print-score option
                    112:      */
                    113:     if (argc == 2 && strcmp(argv[1], "-s") == 0)
                    114:     {
                    115:        waswizard = TRUE;
                    116:        score(0, SCOREIT, 0);
                    117:        exit(0);
                    118:     }
                    119:
                    120: #ifdef NUMNET
                    121:     /*
                    122:      * Check for a network update
                    123:      */
                    124:     if (argc == 2 && strcmp(argv[1], "-u") == 0) {
                    125:        int errcheck, errors = 0;
                    126:        unsigned long amount;
                    127:        short monster;
                    128:
                    129:        /* Read in the amount and monster values to pass to score */
                    130:        amount = netread(&errcheck, sizeof(unsigned long), stdin);
                    131:        if (errcheck) errors++;
                    132:
                    133:        monster = (short) netread(&errcheck, sizeof(short), stdin);
                    134:        if (errcheck) errors++;
                    135:
                    136:        /* Now do the update if there were no errors */
                    137:        if (errors) exit(1);
                    138:        else {
                    139:            score(amount, UPDATE, monster);
                    140:            exit(0);
                    141:        }
                    142:     }
                    143: #endif
                    144:
                    145: #ifdef WIZARD
                    146:     /*
                    147:      * Check to see if he is a wizard
                    148:      */
                    149:     if (argc >= 2 && argv[1][0] == '\0')
                    150:        if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "Si")) == 0)
                    151:        {
                    152:            printf("Hail Mighty Wizard\n");
                    153:            wizard = TRUE;
                    154:            argv++;
                    155:            argc--;
                    156:        }
                    157: #endif
                    158:
                    159: #if MAXLOAD|MAXUSERS
                    160:     if (too_much() && !wizard && !author())
                    161:     {
                    162:        printf("Sorry, %s, but the system is too loaded now.\n", whoami);
                    163:        printf("Try again later.  Meanwhile, why not enjoy a%s %s?\n",
                    164:            vowelstr(fruit), fruit);
                    165:        exit(1);
                    166:     }
                    167: #endif
                    168:     if (use_savedir)
                    169:     {
                    170:         /* Try to restore from file_name first. */
                    171:         if (!restore(file_name, envp))
                    172:             exit(1);
                    173:         /* If restore() returns true, there is no such saved game.
                    174:            So start a new one. */
                    175:     }
                    176:     else if (argc == 2)
                    177:        if (!restore(argv[1], envp)) /* Note: restore will never return */
                    178:            exit(1);
                    179:     dnum = (wizard && getenv("SEED") != NULL ?
                    180:        atoi(getenv("SEED")) :
                    181:        md_random_seed());
                    182:     if (wizard)
                    183:        printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum);
                    184:     else
                    185:        printf("Hello %s, just a moment while I dig the dungeon...\n", whoami);
                    186:     fflush(stdout);
                    187:     seed = dnum;
                    188:     md_srand(seed);
                    189:
                    190:     init_things();                     /* Set up probabilities of things */
                    191:     init_colors();                     /* Set up colors of potions */
                    192:     init_stones();                     /* Set up stone settings of rings */
                    193:     init_materials();                  /* Set up materials of wands */
                    194:     initscr();                         /* Start up cursor package */
                    195:     init_names();                      /* Set up names of scrolls */
                    196:     init_misc();                       /* Set up miscellaneous magic */
                    197:     if (LINES < 24 || COLS < 80) {
                    198:        printf("\nERROR: screen size to small for rogue\n");
                    199:        byebye(-1);
                    200:     }
                    201:
                    202:     if (!use_savedir) {
                    203:         if ((*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
                    204:         {
                    205:             echo();
                    206:             mvaddstr(23,2,"Rogue's Name? ");
                    207:             wgetnstr(stdscr,whoami,LINELEN);
                    208:             noecho();
                    209:         }
                    210:
                    211:         if (*whoami == '\0')
                    212:             strcpy(whoami,"Rodney");
                    213:     }
                    214:
                    215:     setup();
                    216:     /*
                    217:      * Set up windows
                    218:      */
                    219:     cw = newwin(LINES, COLS, 0, 0);
                    220:     mw = newwin(LINES, COLS, 0, 0);
                    221:     hw = newwin(LINES, COLS, 0, 0);
                    222:     msgw = newwin(4, COLS, 0, 0);
                    223:     keypad(cw,1);
                    224:     keypad(msgw,1);
                    225:
                    226:     init_player();                     /* Roll up the rogue */
                    227:     waswizard = wizard;
                    228:     new_level(NORMLEV);                        /* Draw current level */
                    229:     /*
                    230:      * Start up daemons and fuses
                    231:      */
                    232:     start_daemon(doctor, &player, AFTER);
                    233:     fuse(swander, 0, WANDERTIME, AFTER);
                    234:     start_daemon(stomach, 0, AFTER);
                    235:     start_daemon(runners, 0, AFTER);
                    236:     if (player.t_ctype == C_THIEF)
                    237:        start_daemon(trap_look, 0, AFTER);
                    238:
                    239:     /* Choose a quest item */
                    240:     quest_item = rnd(MAXRELIC);
                    241:     msg("You have been quested to retrieve the %s....",
                    242:        rel_magic[quest_item].mi_name);
                    243:     mpos = 0;
                    244:     playit();
                    245: }
                    246:
                    247: void
                    248: reopen_score(void)
                    249: {
                    250:     if (scoreboard != NULL)
                    251:         fclose(scoreboard);
                    252:     scoreboard = fopen(score_file, "r+");
                    253:     if (scoreboard == NULL && errno == ENOENT) {
                    254:         scoreboard = fopen(score_file, "w+");
                    255:     }
                    256: }
                    257:
                    258:
                    259: void
                    260: open_records(void)
                    261: {
                    262:     if (scoreboard == NULL)
                    263:         reopen_score();
                    264: #ifdef LOGFILE
                    265:     if (logfile == NULL)
                    266:         logfile = fopen(LOGFILE, "a");
                    267: #endif
                    268:     return;
                    269: }
                    270:
                    271: /*
                    272:  * endit:
                    273:  *     Exit the program abnormally.
                    274:  */
                    275: void
                    276: endit(int sig)
                    277: {
                    278:     NOOP(sig);
                    279:
                    280:     fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
                    281: }
                    282:
                    283: /*
                    284:  * fatal:
                    285:  *     Exit the program, printing a message.
                    286:  */
                    287:
                    288: void
                    289: fatal(char *s)
                    290: {
                    291:     clear();
                    292:     move(LINES-2, 0);
                    293:     printw("%s", s);
                    294:     draw(stdscr);
                    295:     endwin();
                    296:     printf("\n");      /* So the cursor doesn't stop at the end of the line */
                    297:     exit(0);
                    298: }
                    299:
                    300: /*
                    301:  * rnd:
                    302:  *     Pick a very random number.
                    303:  */
                    304:
                    305: int
                    306: rnd(int range)
                    307: {
                    308:     return(range == 0 ? 0 : md_rand() % range);
                    309: }
                    310:
                    311: /*
                    312:  * roll:
                    313:  *     roll a number of dice
                    314:  */
                    315:
                    316: int
                    317: roll(int number, int sides)
                    318: {
                    319:     register int dtotal = 0;
                    320:
                    321:     while(number--)
                    322:        dtotal += rnd(sides)+1;
                    323:     return dtotal;
                    324: }
                    325: # ifdef SIGTSTP
                    326: /*
                    327:  * handle stop and start signals
                    328:  */
                    329: void
                    330: tstp(int a)
                    331: {
                    332:     mvcur(0, COLS - 1, LINES - 1, 0);
                    333:     endwin();
                    334:     fflush(stdout);
                    335:     kill(0, SIGTSTP);
                    336:     signal(SIGTSTP, tstp);
                    337:     raw();
                    338:     noecho();
                    339:     keypad(cw,1);
                    340:     clearok(curscr, TRUE);
                    341:     touchwin(cw);
                    342:     draw(cw);
                    343:     md_flushinp();
                    344: }
                    345: # endif
                    346:
                    347: void
                    348: setup(void)
                    349: {
                    350: #ifdef CHECKTIME
                    351:     void  checkout();
                    352: #endif
                    353:
                    354: #ifndef DUMP
                    355: #ifdef SIGHUP
                    356:     signal(SIGHUP, auto_save);
                    357: #endif
                    358:     signal(SIGILL, bugkill);
                    359: #ifdef SIGTRAP
                    360:     signal(SIGTRAP, bugkill);
                    361: #endif
                    362: #ifdef SIGIOT
                    363:     signal(SIGIOT, bugkill);
                    364: #endif
                    365: #if 0
                    366:     signal(SIGEMT, bugkill);
                    367:     signal(SIGFPE, bugkill);
                    368:     signal(SIGBUS, bugkill);
                    369:     signal(SIGSEGV, bugkill);
                    370:     signal(SIGSYS, bugkill);
                    371:     signal(SIGPIPE, bugkill);
                    372: #endif
                    373:     signal(SIGTERM, auto_save);
                    374: #endif
                    375:
                    376:     signal(SIGINT, quit);
                    377: #ifndef DUMP
                    378: #ifdef SIGQUIT
                    379:     signal(SIGQUIT, endit);
                    380: #endif
                    381: #endif
                    382: #ifdef SIGTSTP
                    383:     signal(SIGTSTP, tstp);
                    384: #endif
                    385: #ifdef CHECKTIME
                    386:     if (!author())
                    387:     {
                    388:        signal(SIGALRM, checkout);
                    389:        alarm(CHECKTIME * 60);
                    390:        num_checks = 0;
                    391:     }
                    392: #endif
                    393:     nonl();
                    394:     crmode();                          /* Cbreak mode */
                    395:     noecho();                          /* Echo off */
                    396: }
                    397:
                    398: /*
                    399:  * playit:
                    400:  *     The main loop of the program.  Loop until the game is over,
                    401:  * refreshing things and looking at the proper times.
                    402:  */
                    403:
                    404: void
                    405: playit(void)
                    406: {
                    407:     register char *opts;
                    408:
                    409:
                    410:     /*
                    411:      * parse environment declaration of options
                    412:      */
                    413:     if ((opts = getenv("ROGUEOPTS")) != NULL)
                    414:        parse_opts(opts);
                    415:
                    416:
                    417:     player.t_oldpos = hero;
                    418:     oldrp = roomin(&hero);
                    419:     after = TRUE;
                    420:     while (playing)
                    421:        command();                      /* Command execution */
                    422:     endit(0);
                    423: }
                    424:
                    425: #if MAXLOAD|MAXUSERS
                    426: /*
                    427:  * see if the system is being used too much for this game
                    428:  */
                    429: bool
                    430: too_much(void)
                    431: {
                    432: #ifdef MAXLOAD
                    433:        double avec[3];
                    434: #endif
                    435:
                    436: #ifdef MAXLOAD
                    437:        loadav(avec);
                    438:        return (avec[2] > (MAXLOAD / 10.0));
                    439: #else
                    440:        return (ucount() > MAXUSERS);
                    441: #endif
                    442: }
                    443: #endif
                    444:
                    445: /*
                    446:  * author:
                    447:  *     See if a user is an author of the program
                    448:  */
                    449: bool
                    450: author(void)
                    451: {
                    452:        switch (md_getuid()) {
                    453: #if AUTHOR
                    454:                case AUTHOR:
                    455: #endif
                    456:                case 0:
                    457:                        return TRUE;
                    458:                default:
                    459:                        return FALSE;
                    460:        }
                    461: }
                    462:
                    463:
                    464: #ifdef CHECKTIME
                    465: /*
                    466:  * checkout()'s version of msg.  If we are in the middle of a shell, do a
                    467:  * printf instead of a msg to avoid the refresh.
                    468:  */
                    469: void
                    470: chmsg(char *fmt, int arg)
                    471: {
                    472:        if (in_shell) {
                    473:                printf(fmt, arg);
                    474:                putchar('\n');
                    475:                fflush(stdout);
                    476:        }
                    477:        else
                    478:                msg(fmt, arg);
                    479: }
                    480:
                    481: void
                    482: checkout(void)
                    483: {
                    484:        static char *msgs[] = {
                    485:        "The system is too loaded for games. Please leave in %d minutes",
                    486:        "Please save your game.  You have %d minutes",
                    487:        "This is your last chance. You had better leave in %d minutes",
                    488:        };
                    489:        int checktime;
                    490:
                    491:        signal(SIGALRM, checkout);
                    492:        if (!holiday() && !author()) {
                    493:            wclear(cw);
                    494:            mvwaddstr(cw, LINES / 2, 0,
                    495:                "Game time is over. Your game is being saved.\n\n");
                    496:            draw(cw);
                    497:            auto_save();                /* NO RETURN */
                    498:        }
                    499:        if (too_much()) {
                    500:            if (num_checks >= 3)
                    501:                fatal("You didn't listen, so now you are DEAD !!\n");
                    502:            checktime = CHECKTIME / (num_checks + 1);
                    503:                chmsg(msgs[num_checks++], checktime);
                    504:                alarm(checktime * 60);
                    505:        }
                    506:        else {
                    507:            if (num_checks) {
                    508:                chmsg("The load has dropped. You have a reprieve.");
                    509:                num_checks = 0;
                    510:            }
                    511:            alarm(CHECKTIME * 60);
                    512:        }
                    513: }
                    514: #endif
                    515:
                    516: #ifdef LOADAV
                    517:
                    518: #include <nlist.h>
                    519:
                    520: struct nlist avenrun =
                    521: {
                    522:        "_avenrun"
                    523: };
                    524:
                    525: void
                    526: loadav(double *avg)
                    527: {
                    528:        reg int kmem;
                    529:
                    530:        if ((kmem = open("/dev/kmem", 0)) < 0)
                    531:                goto bad;
                    532:        nlist(NAMELIST, &avenrun);
                    533:        if (avenrun.n_type == 0) {
                    534: bad:
                    535:                avg[0] = avg[1] = avg[2] = 0.0;
                    536:                return;
                    537:        }
                    538:        lseek(kmem, (long) avenrun.n_value, 0);
                    539:        read(kmem, avg, 3 * sizeof (double));
                    540: }
                    541: #endif
                    542:
                    543: #ifdef UCOUNT
                    544: /*
                    545:  * ucount:
                    546:  *     Count the number of people on the system
                    547:  */
                    548: #include <sys/types.h>
                    549: #include <utmp.h>
                    550: struct utmp buf;
                    551: int
                    552: ucount(void)
                    553: {
                    554:        reg struct utmp *up;
                    555:        reg FILE *utmp;
                    556:        reg int count;
                    557:
                    558:        if ((utmp = fopen(UTMP, "r")) == NULL)
                    559:            return 0;
                    560:
                    561:        up = &buf;
                    562:        count = 0;
                    563:        while (fread(up, 1, sizeof (*up), utmp) > 0)
                    564:                if (buf.ut_type == USER_PROCESS)
                    565:                        count++;
                    566:        fclose(utmp);
                    567:        return count;
                    568: }
                    569: #endif
                    570:
                    571: /*
                    572:  * holiday:
                    573:  *     Returns TRUE when it is a good time to play rogue
                    574:  */
                    575: bool
                    576: holiday(void)
                    577: {
                    578:        time_t now;
                    579:        struct tm *localtime();
                    580:        reg struct tm *ntime;
                    581:
                    582:        time(&now);                     /* get the current time */
                    583:        ntime = localtime(&now);
                    584:        if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
                    585:                return TRUE;            /* OK on Sat & Sun */
                    586:        if(ntime->tm_hour < 8 || ntime->tm_hour >= 17)
                    587:                return TRUE;            /* OK before 8AM & after 5PM */
                    588:        if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350)
                    589:                return TRUE;            /* OK during Christmas */
                    590: #if 0 /* not for now */
                    591:        if (access("/usr/tmp/.ryes",0) == 0)
                    592:            return TRUE;                /* if author permission */
                    593: #endif
                    594:
                    595:        return FALSE;                   /* All other times are bad */
                    596: }

CVSweb