1: /*
   2:  * Phantasia 3.2 -- Interterminal fantasy game
   3:  *
   4:  * Edward A. Estes
   5:  * AT&T Teletype Corp., September 4, 1984
   6:  */
   7: 
   8: /*
   9:  * This is the program which drives the whole mess.  Hopefully, you will be
  10:  * able to wade throught the garbage if you have to fix something.
  11:  * several undocumented items exist.  The program checks uid and sets the
  12:  * boolean flag 'su' (super user) if the person is allowed special powers.
  13:  * The 'su' may execute any of the valar/council options.  Also,
  14:  * a 'vaporize' option exists to kill anybody at will.  The 'su' can select
  15:  * character type 7, which starts out with the maximum possible in each
  16:  * category.  (The resulting character is an experimento.)  The 'su' may
  17:  * also change the stats of other characters with the -x option.
  18:  */
  19: 
  20: /*
  21:  * The program allocates as much file space as it needs to store characters,
  22:  * so the possibility exists for the character file to grow without bound.
  23:  * The file is purged upon normal entry to try to avoid that problem.
  24:  * A similar problem exists for energy voids.  To alleviate the problem here,
  25:  * the void file is cleared with every new king.
  26:  */
  27: 
  28: /*
  29:  * The support functions are split between various files with no apparent
  30:  * order.  Use of 'ctags' is recommended to find a particular function.
  31:  */
  32: 
  33: /*
  34:  * Put one line of text into the file 'motd' for announcements, etc.
  35:  */
  36: 
  37: /*
  38:  * If ENEMY is defined, a list of restricted login names is checked
  39:  * in the file 'enemy'.  These names are listed, one per line, with
  40:  * no trailing blanks.
  41:  */
  42: 
  43: #include "phant.h"
  44: 
  45: double  strength, speed;
  46: bool    beyond, marsh, throne, valhala, changed, fghting, su, wmhl;
  47: int fileloc, users;
  48: jmp_buf fightenv, mainenv;
  49: long    secs;
  50: /*
  51:  * worm hole map -- This table is carefully set up so that one can always
  52:  * return the way he/she came by inverting the initial path.
  53:  */
  54: struct  worm_hole   w_h[] =
  55:     {
  56:     0,0,0,0,    35,22,2,0,  2,2,0,1,    59,34,64,0,
  57:     54,47,0,60, 50,62,0,56, 19,31,25,0, 0,35,41,41,
  58:     0,46,40,23, 24,0,29,30, 44,57,56,0, 0,44,39,40,
  59:     61,41,0,42, 32,0,17,18, 57,0,63,64, 0,33,26,34,
  60:     48,0,54,55, 28,23,22,13,    63,25,13,19,    34,6,18,20,
  61:     27,26,19,21,    15,27,20,27,    1,28,34,17, 17,29,8,24,
  62:     29,9,23,25, 18,30,24,6, 20,32,27,15,    21,20,21,26,
  63:     22,17,46,29,    23,24,28,9, 25,38,9,31, 6,39,30,32,
  64:     26,13,31,33,    15,40,32,35,    3,19,15,22, 7,1,33,36,
  65:     37,37,35,37,    36,36,36,38,    30,42,37,39,    31,43,38,11,
  66:     33,45,11,8, 12,48,7,7,  38,49,12,43,    39,51,42,44,
  67:     11,10,43,45,    40,52,44,46,    8,53,45,28, 4,54,51,48,
  68:     41,16,47,49,    42,55,48,50,    62,5,49,51, 43,56,50,47,
  69:     45,58,53,53,    46,59,52,52,    47,4,55,16, 49,61,16,54,
  70:     51,63,5,10, 10,14,59,58,    52,64,57,59,    53,3,58,57,
  71:     60,60,4,61, 55,12,60,62,    5,50,61,63, 56,18,62,14,
  72:     58,33,14,3
  73:     };
  74: 
  75: main(argc,argv)             /* Phantasia main routine */
  76: int argc;
  77: char    *argv[];
  78: {
  79: struct  stats   charac;
  80: char    aline[200], *login = NULL;
  81: double  x = 0.0, y = 0.0;
  82: int ch, ch2;
  83: reg int loop, temp;
  84: FILE    *fp;
  85: bool    shrt = FALSE, examine = FALSE, header = FALSE;
  86: 
  87:     if ((login = getlogin()) == NULL)
  88:         login = getpwuid(getuid())->pw_name;
  89: #ifdef ENEMY
  90:     /* check hit list of restricted accounts */
  91:     if ((fp = fopen(enemyfile, "r")) != NULL)
  92:         {
  93:         char    enemy[20];
  94: 
  95:         while (fscanf(fp, "%s", enemy) != EOF)
  96:             if (!strcmp(login,enemy))
  97:                 {
  98:                 printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", login);
  99:                 printf ("Mail comments to %s.\n", WIZARD);
 100:                 exit (0);
 101:                 }
 102:         fclose (fp);
 103:         }
 104: #endif
 105:     setbuf(stdin, (char *) NULL);   /* this may or may not be necessary */
 106:     su = (getuid() == UID);
 107:     fghting = FALSE;
 108:     users = 0;
 109:     if (argc > 1 && (*++argv)[0] == '-')
 110:         switch ((*argv)[1])
 111:             {
 112:             case 'h':       /* help */
 113:                 printhelp();
 114:                 exit(0);
 115:                 /*NOTREACHED*/
 116:             case 's':       /* short */
 117:                 shrt = TRUE;
 118:                 break;
 119:             case 'x':       /* examine */
 120:                 examine = TRUE;
 121:                 break;
 122:             case 'H':       /* Header */
 123:                 header = TRUE;
 124:                 break;
 125:             case 'm':       /* monsters */
 126:                 printmonster();
 127:                 exit(0);
 128:                 /*NOTREACHED*/
 129:             case 'a':       /* all users */
 130:                 showusers();
 131:                 exit(0);
 132:                 /*NOTREACHED*/
 133:             case 'p':       /* purge old players */
 134:                 purge();
 135:                 exit(0);
 136:                 /*NOTREACHED*/
 137:             }
 138:     if (!isatty(0)) /* don't let non-tty's play */
 139:         exit(0);
 140:     init1();    /* set up for screen stuff */
 141:     if (examine)
 142:         {
 143:         cstat();
 144:         exit1();
 145:         /*NOTREACHED*/
 146:         }
 147:     if (!shrt)
 148:         {
 149:         titlestuff();
 150:         purge();    /* clean up old characters */
 151:         }
 152:     if (header)
 153:         {
 154:         exit1();
 155:         /*NOTREACHED*/
 156:         }
 157: #ifdef OK_TO_PLAY
 158:     if (!ok_to_play())
 159:         {
 160:         mvaddstr(23,27,"Sorry, you can't play now.\n");
 161:         exit1();
 162:         /*NOTREACHED*/
 163:         }
 164: #endif
 165:     mvaddstr(23,24,"Do you have a character to run? ");
 166:     ch = rgetch();
 167:     if (toupper(ch) == 'Y')
 168:         fileloc = findchar(&charac);
 169:     else
 170:         {
 171:         initchar(&charac);
 172:         clear();
 173:         mvaddstr(5,21,"Which type of character do you want:");
 174:         mvaddstr(10,4,"1:Magic User  2:Fighter  3:Elf  4:Dwarf  5:Halfling  6:Experimento  ? ");
 175:         ch = rgetch();
 176:         do
 177:             {
 178:             genchar(&charac,ch);
 179:             mvprintw(15,14,"Strength:  %2.0f  Manna      : %3.0f  Quickness   :  %2d",
 180:                 charac.str,charac.man,charac.quk);
 181:             mvprintw(16,14,"Brains  :  %2.0f  Magic Level:  %2.0f  Energy Level:  %2.0f",
 182:                 charac.brn,charac.mag,charac.nrg);
 183:             if (charac.typ != 6)
 184:                 {
 185:                 mvaddstr(17,14,"Type '1' to keep >");
 186:                 ch2 = rgetch();
 187:                 }
 188:             else
 189:                 break;
 190:             }
 191:         while (ch2 != '1');
 192:         if (charac.typ == 6)
 193:             {
 194:             mvaddstr(19,0,"Enter the X Y coordinates of your experimento ? ");
 195:             getstring(aline,80);
 196:             sscanf(aline,"%F %F",&x,&y);
 197:             charac.x = (abs(x) > 1.2e+6) ? sgn(x)*1.2e+6 : floor(x);
 198:             charac.y = (abs(y) > 1.2e+6) ? sgn(y)*1.2e+6 : floor(y);
 199:             }
 200:         do
 201:             {
 202:             mvaddstr(20,0,"Give your character a name [up to 20 characters] ?  ");
 203:             getstring(aline,80);
 204:             strncpy(charac.name,aline,20);
 205:             charac.name[20] = '\0';
 206:             }
 207:         while (findname(charac.name));
 208:         putchar('\n');
 209:         fflush(stdout);
 210:         nocrmode();
 211:         do
 212:             {
 213:             strcpy(charac.pswd,getpass("Give your character a password [up to 8 characters] ? "));
 214:             putchar('\n');
 215:             strcpy(aline,getpass("One more time to verify ? "));
 216:             }
 217:         while (strcmp(charac.pswd,aline));
 218:         fileloc = findspace();
 219:         }
 220:     crmode();
 221:     if (charac.status)
 222:         {
 223:         clear();
 224:         addstr("Your character did not exit normally last time.\n");
 225:         addstr("If you think you have good cause to have you character saved,\n");
 226:         printw("you may quit and mail your reason to '%s'.\n",WIZARD);
 227:         addstr("Do you want to quit ? ");
 228:         ch = rgetch();
 229:         if (toupper(ch) == 'Y')
 230:             {
 231:             charac.quk = -100;
 232:             leave(&charac);
 233:             /*NOTREACHED*/
 234:             }
 235:         death(&charac);
 236:         }
 237:     charac.status = PLAYING;
 238:     strcpy(charac.login,login);
 239:     time(&secs);
 240:     charac.lastused = localtime(&secs)->tm_yday;
 241:     update(&charac,fileloc);
 242:     clear();
 243: #ifdef  BSD41
 244:     sigset(SIGINT,interrupt);
 245: #endif
 246: #ifdef  BSD42
 247:     signal(SIGINT,interrupt,-1);
 248: #endif
 249: #ifdef  USG3
 250:     signal(SIGINT,interrupt);
 251: #endif
 252: #ifdef  USG5
 253:     signal(SIGINT,interrupt);
 254: #endif
 255: 
 256: /* all set for now */
 257: 
 258: TOP:    switch (setjmp(mainenv))
 259:         {
 260:         case QUIT:
 261: #ifdef  BSD41
 262:             sigrelse(SIGINT);
 263: #endif
 264: #ifdef  BSD42
 265:             signal(SIGINT,interrupt,-1);
 266: #endif
 267: #ifdef  USG3
 268:             signal(SIGINT,interrupt);
 269: #endif
 270: #ifdef  USG5
 271:             signal(SIGINT,interrupt);
 272: #endif
 273:             leave(&charac);
 274:             /*NOTREACHED*/
 275:         case DIE:
 276: #ifdef  BSD41
 277:             sigrelse(SIGINT);
 278: #endif
 279: #ifdef  BSD42
 280:             signal(SIGINT,interrupt,-1);
 281: #endif
 282: #ifdef  USG3
 283:             signal(SIGINT,interrupt);
 284: #endif
 285: #ifdef  USG5
 286:             signal(SIGINT,interrupt);
 287: #endif
 288:             death(&charac);
 289:             break;
 290:         }
 291: #ifdef OK_TO_PLAY
 292:     if (!ok_to_play())
 293:         {
 294:         mvaddstr(6,0,"Whoops!  Can't play now.\n");
 295:         leave(&charac);
 296:         /*NOTREACHED*/
 297:         }
 298: #endif
 299:     fghting = FALSE;
 300:     adjuststats(&charac);
 301:     if (throne && !charac.crn && (charac.typ < 10 || charac.typ > 20))
 302:         {
 303:         mvaddstr(6,0,"You're not allowed in the Lord's Chamber without a crown.\n");
 304:         changed = TRUE;
 305:         charac.x = charac.y = 10;
 306:         }
 307:     if (charac.status != CLOAKED && abs(charac.x) == abs(charac.y)
 308:          && floor(sqrt(fabs(charac.x/100.0))) == sqrt(fabs(charac.x/100.0)) && !throne)
 309:         {
 310:         trade(&charac);
 311:         clear();
 312:         }
 313:     checktampered(&charac);
 314:     checkinterm(&charac);
 315:     if (charac.nrg < 0 || (charac.lvl >= 10000 && charac.typ != 99))
 316:         death(&charac);
 317:     neatstuff(&charac);
 318:     if (changed)
 319:         {
 320:         update(&charac,fileloc);
 321:         changed = FALSE;
 322:         goto TOP;
 323:         }
 324:     move(5,0);
 325:     clrtoeol();
 326:     fp = fopen(messfile,"r");
 327:     if (fgets(aline,160,fp))
 328:         addstr(aline);
 329:     fclose(fp);
 330:     printstats(&charac);
 331:     move(3,0);
 332:     clrtoeol();
 333:     if (!wmhl)
 334:         {
 335:         if (throne)
 336:             kingstuff(&charac);
 337:         addstr("1:Move  2:Players  3:Talk  4:Stats  5:Quit  ");
 338:         if (charac.lvl >= 5 && charac.mag >= 15)
 339:             addstr("6:Cloak  ");
 340:         if (charac.lvl >= 10 && charac.mag >= 25)
 341:             addstr("7:Teleport  ");
 342:         if (charac.typ > 20)
 343:             addstr("8:Intervention");
 344:         ch = gch(charac.rng.type);
 345:         clrtoeol();
 346:         move(6,0);
 347:         clrtobot();
 348:         if (charac.typ == 99 && (ch == '1' || ch == '7'))
 349:             ch = ' ';
 350:         switch (ch2 = toupper(ch))
 351:             {
 352:             case 'N':
 353:                 charac.y += maxmove;
 354:                 break;
 355:             case 'S':
 356:                 charac.y -= maxmove;
 357:                 break;
 358:             case 'E':
 359:                 charac.x += maxmove;
 360:                 break;
 361:             case 'W':
 362:                 charac.x -= maxmove;
 363:                 break;
 364:             default:    /* rest */
 365:                 if (charac.status == CLOAKED)
 366:                     if (charac.man > 3.0)
 367:                         charac.man -= 3;
 368:                     else
 369:                         {
 370:                         charac.status = PLAYING;
 371:                         changed = TRUE;
 372:                         }
 373:                 else
 374:                     {
 375:                     charac.man += circ(charac.x,charac.y)/3+0.5;
 376:                     charac.man += charac.lvl/5+0.5;
 377:                     }
 378:                 rndattack();
 379:                 break;
 380:             case '1':   /* move */
 381:                 for (loop = 3; loop; --loop)
 382:                     {
 383:                     mvaddstr(5,0,"X Y Coordinates ? ");
 384:                     getstring(aline,80);
 385:                     if (sscanf(aline,"%F %F",&x,&y) < 2)
 386:                         ;
 387:                     else
 388:                         if (hypot((double) charac.x - x, (double) charac.y - y) > maxmove)
 389:                             illmove();
 390:                         else
 391:                             {
 392:                             charac.x = x;
 393:                             charac.y = y;
 394:                             break;
 395:                             }
 396:                     }
 397:                 break;
 398:             case '2':   /* players */
 399:                 printplayers(&charac);
 400:                 break;
 401:             case '3':   /* message */
 402:                 talk(charac.name);
 403:                 break;
 404:             case '4':   /* stats */
 405:                 showall(&charac);
 406:                 break;
 407:             case '5':   /* good-bye */
 408:                 leave(&charac);
 409:                 /*NOTREACHED*/
 410:             case '6':   /* cloak */
 411:                 if (charac.lvl < 5 || charac.mag < 15)
 412:                     illcmd();
 413:                 else if (charac.status == CLOAKED)
 414:                     charac.status = PLAYING;
 415:                 else if (charac.man < 35)
 416:                     {
 417:                     mvaddstr(6,0,"No power left.\n");
 418:                     refresh();
 419:                     }
 420:                 else
 421:                     {
 422:                     changed = TRUE;
 423:                     charac.man -= 35;
 424:                     charac.status = CLOAKED;
 425:                     }
 426:                 break;
 427:             case '7':   /* teleport */
 428:                 if (charac.lvl < 10 || charac.mag < 25)
 429:                     illcmd();
 430:                 else
 431:                     for (loop = 3; loop; --loop)
 432:                         {
 433:                         mvaddstr(5,0,"X Y Coordinates ? ");
 434:                         getstring(aline,80);
 435:                         if (sscanf(aline,"%F %F",&x,&y) == 2)
 436:                             if ((temp = hypot(charac.x-x,charac.y-y))
 437:                                     > (charac.lvl+charac.mag)*5+((charac.typ > 20) ? 1e+6 : 0)
 438:                                     && !throne)
 439:                                 illmove();
 440:                             else if ((temp = (temp/75+1)*20) > charac.man && !throne)
 441:                                 mvaddstr(6,0,"Not enough power for that distance.\n");
 442:                             else
 443:                                 {
 444:                                 charac.x = x;
 445:                                 charac.y = y;
 446:                                 if (!throne)
 447:                                     charac.man -= temp;
 448:                                 break;
 449:                                 }
 450:                         }
 451:                 break;
 452:             case '9':   /* monster */
 453:                 if (throne)
 454:                     mvaddstr(6,0,"No monsters in the chamber!\n");
 455:                 else if (charac.typ != 99)
 456:                     {
 457:                     charac.status = PLAYING;
 458:                     changed = TRUE;
 459:                     charac.sin += 1e-6;
 460:                     fight(&charac,-1);
 461:                     }
 462:                 break;
 463:             case '0':   /* decree */
 464:                 if (su || charac.typ > 10 && charac.typ < 20 && throne)
 465:                     decree(&charac);
 466:                 else
 467:                     illcmd();
 468:                 break;
 469:             case '8':   /* intervention */
 470:                 if (su || charac.typ > 20)
 471:                     valarstuff(&charac);
 472:                 else
 473:                     illcmd();
 474:                 break;
 475:             case '\014':    /* redo screen */
 476:                 clear();
 477:             }
 478:         if (ch2 == 'E' || ch2 == 'W' || ch2 == 'N' || ch2 == 'S'
 479:             || ch2 == '1' || ch2 == '7')
 480:             {
 481:             checkmov(&charac);
 482:             rndattack();
 483:             changed = TRUE;
 484:             }
 485:         }
 486:     else
 487:         {
 488:         addstr("F:Forward  B:Back  R:Right  L:Left  Q:Quit  T:Talk  P:Players  S:Stats  ");
 489:         ch = rgetch();
 490:         move(6,0);
 491:         clrtobot();
 492:         switch (toupper(ch))
 493:             {
 494:             default:
 495:                 if (charac.status == CLOAKED)
 496:                     if (charac.man > 3.0)
 497:                         charac.man -= 3;
 498:                     else
 499:                         {
 500:                         charac.status = PLAYING;
 501:                         changed = TRUE;
 502:                         }
 503:                 else
 504:                     charac.man += charac.lvl/5+0.5;
 505:                 break;
 506:             case 'F':
 507:                 temp = (int) w_h[charac.wormhole].f;
 508:                 goto CHKMOVE;
 509:             case 'B':
 510:                 temp = (int) w_h[charac.wormhole].b;
 511:                 goto CHKMOVE;
 512:             case 'R':
 513:                 temp = (int) w_h[charac.wormhole].r;
 514:                 goto CHKMOVE;
 515:             case 'L':
 516:                 temp = (int) w_h[charac.wormhole].l;
 517:                 goto CHKMOVE;
 518:             case 'Q':
 519:                 leave(&charac);
 520:                 /*NOTREACHED*/
 521:             case 'T':
 522:                 talk(charac.name);
 523:                 break;
 524:             case 'P':
 525:                 printplayers(&charac);
 526:                 break;
 527:             case 'S':
 528:                 showall(&charac);
 529:                 break;
 530:             case '\014':    /* redo screen */
 531:                 clear();
 532:             }
 533:         goto TOP;
 534: CHKMOVE:    if (!temp)
 535:                 {
 536:                 charac.y = 0.0;
 537:                 charac.x = pow(-1.0,(double) charac.wormhole) * charac.wormhole * 400 - 1.0;
 538:                 charac.wormhole = 0;
 539:                 changed = TRUE;
 540:                 }
 541:             else
 542:                 charac.wormhole = temp;
 543:         }
 544:     goto TOP;
 545: }
 546: 
 547: /*
 548:  * This function is provided to allow one to restrict access to the game.
 549:  * Tailor this routine as appropriate.
 550:  */
 551: 
 552: #ifdef  OK_TO_PLAY
 553: #include <sys/types.h>
 554: #include <utmp.h>   /* used for counting users on system */
 555: 
 556: bool    ok_to_play()        /* return FALSE if playing is not allowed at this time */
 557: {
 558: #define MAXUSERS    8   /* max. number of people on system */
 559: reg struct  tm  *tp;
 560: reg int numusers = 0;
 561: FILE    *fp;
 562: long    now;
 563: struct  utmp    ubuf;
 564: 
 565:     if (su)
 566:         return (TRUE);
 567:     /* check time of day */
 568:     time(&now);
 569:     if (((tp = localtime(&now))->tm_hour > 8 && tp->tm_hour < 12)   /* 8-noon */
 570:         || (tp->tm_hour > 13 && tp->tm_hour < 16))      /* 1-4 pm */
 571:         return (FALSE);
 572:     /* check # of users */
 573:     fp = fopen(_PATH_UTMP,"r");
 574:     while (fread((char *) &ubuf,sizeof(ubuf),1,fp))
 575: #ifdef  USG5
 576:         if (ubuf.ut_type == USER_PROCESS)
 577: #else
 578:     if (*ubuf.ut_name)
 579: #endif
 580:             ++numusers;
 581:     fclose(fp);
 582:     if (numusers > MAXUSERS)
 583:         return (FALSE);
 584:     return (TRUE);
 585: }
 586: #endif

Defined functions

main defined in line 75; never used
ok_to_play defined in line 556; used 3 times

Defined variables

fightenv defined in line 48; never used
fileloc defined in line 47; used 4 times
mainenv defined in line 48; used 1 times
secs defined in line 49; used 2 times
speed defined in line 45; never used
strength defined in line 45; never used
users defined in line 47; used 1 times
w_h defined in line 54; used 4 times

Defined macros

MAXUSERS defined in line 558; used 1 times
Last modified: 1996-11-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5465
Valid CSS Valid XHTML 1.0 Strict