Annotation of 43BSDReno/games/phantasia/misc.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * misc.c  Phantasia miscellaneous support routines
        !             3:  */
        !             4: 
        !             5: #include "include.h"
        !             6: 
        !             7: /************************************************************************
        !             8: /
        !             9: / FUNCTION NAME: movelevel()
        !            10: /
        !            11: / FUNCTION: move player to new level
        !            12: /
        !            13: / AUTHOR: E. A. Estes, 12/4/85
        !            14: /
        !            15: / ARGUMENTS: none
        !            16: /
        !            17: / RETURN VALUE: none
        !            18: /
        !            19: / MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
        !            20: /
        !            21: / GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
        !            22: /
        !            23: / GLOBAL OUTPUTS: Player, Changed
        !            24: /
        !            25: / DESCRIPTION:
        !            26: /      Use lookup table to increment important statistics when
        !            27: /      progressing to new experience level.
        !            28: /      Players are rested to maximum as a bonus for making a new
        !            29: /      level.
        !            30: /      Check for council of wise, and being too big to be king.
        !            31: /
        !            32: /************************************************************************/
        !            33: 
        !            34: movelevel()
        !            35: {
        !            36: register struct charstats      *statptr;       /* for pointing into Stattable */
        !            37: double new;                    /* new level */
        !            38: double inc;                    /* increment between new and old levels */
        !            39: 
        !            40:     Changed = TRUE;
        !            41: 
        !            42:     if (Player.p_type == C_EXPER)
        !            43:        /* roll a type to use for increment */
        !            44:        statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
        !            45:     else
        !            46:        statptr = Statptr;
        !            47: 
        !            48:     new = explevel(Player.p_experience);
        !            49:     inc = new - Player.p_level;
        !            50:     Player.p_level = new;
        !            51: 
        !            52:     /* add increments to statistics */
        !            53:     Player.p_strength += statptr->c_strength.increase * inc;
        !            54:     Player.p_mana += statptr->c_mana.increase * inc;
        !            55:     Player.p_brains += statptr->c_brains.increase * inc;
        !            56:     Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
        !            57:     Player.p_maxenergy += statptr->c_energy.increase * inc;
        !            58: 
        !            59:     /* rest to maximum upon reaching new level */
        !            60:     Player.p_energy = Player.p_maxenergy + Player.p_shield;
        !            61: 
        !            62:     if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
        !            63:        /* no longer able to be king -- turn crowns into cash */
        !            64:        {
        !            65:        Player.p_gold += ((double) Player.p_crowns) * 5000.0;
        !            66:        Player.p_crowns = 0;
        !            67:        }
        !            68: 
        !            69:     if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
        !            70:        /* make a member of the council */
        !            71:        {
        !            72:        mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
        !            73:        addstr("Good Luck on your search for the Holy Grail.\n");
        !            74: 
        !            75:        Player.p_specialtype = SC_COUNCIL;
        !            76: 
        !            77:        /* no rings for council and above */
        !            78:        Player.p_ring.ring_type = R_NONE;
        !            79:        Player.p_ring.ring_duration = 0;
        !            80: 
        !            81:        Player.p_lives = 3;             /* three extra lives */
        !            82:        }
        !            83: 
        !            84:     if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
        !            85:        death("Old age");
        !            86: }
        !            87: /**/
        !            88: /************************************************************************
        !            89: /
        !            90: / FUNCTION NAME: descrlocation()
        !            91: /
        !            92: / FUNCTION: return a formatted description of location
        !            93: /
        !            94: / AUTHOR: E. A. Estes, 12/4/85
        !            95: /
        !            96: / ARGUMENTS:
        !            97: /      struct player playerp - pointer to player structure
        !            98: /      bool shortflag - set if short form is desired
        !            99: /
        !           100: / RETURN VALUE: pointer to string containing result
        !           101: /
        !           102: / MODULES CALLED: fabs(), floor(), sprintf(), distance()
        !           103: /
        !           104: / GLOBAL INPUTS: Databuf[]
        !           105: /
        !           106: / GLOBAL OUTPUTS: none
        !           107: /
        !           108: / DESCRIPTION:
        !           109: /      Look at coordinates and return an appropriately formatted
        !           110: /      string.
        !           111: /
        !           112: /************************************************************************/
        !           113: 
        !           114: char   *
        !           115: descrlocation(playerp, shortflag)
        !           116: struct player  *playerp;
        !           117: bool   shortflag;
        !           118: {
        !           119: double circle;                 /* corresponding circle for coordinates */
        !           120: register int   quadrant;       /* quandrant of grid */
        !           121: register char  *label;         /* pointer to place name */
        !           122: static char    *nametable[4][4] =   /* names of places */
        !           123:        {
        !           124:        "Anorien",      "Ithilien",     "Rohan",        "Lorien",
        !           125:        "Gondor",       "Mordor",       "Dunland",      "Rovanion",
        !           126:        "South Gondor", "Khand",        "Eriador",      "The Iron Hills",
        !           127:        "Far Harad",    "Near Harad",   "The Northern Waste", "Rhun"
        !           128:        };
        !           129: 
        !           130:     if (playerp->p_specialtype == SC_VALAR)
        !           131:        return(" is in Valhala");
        !           132:     else if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0)
        !           133:        {
        !           134:        if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
        !           135:            label = "The Point of No Return";
        !           136:        else
        !           137:            label = "The Ashen Mountains";
        !           138:        }
        !           139:     else if (circle >= 55)
        !           140:        label = "Morannon";
        !           141:     else if (circle >= 35)
        !           142:        label = "Kennaquahair";
        !           143:     else if (circle >= 20)
        !           144:        label = "The Dead Marshes";
        !           145:     else if (circle >= 9)
        !           146:        label = "The Outer Waste";
        !           147:     else if (circle >= 5)
        !           148:        label = "The Moors Adventurous";
        !           149:     else
        !           150:        {
        !           151:        if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
        !           152:            label = "The Lord's Chamber";
        !           153:        else
        !           154:            {
        !           155:            /* this expression is split to prevent compiler loop with some compilers */
        !           156:            quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
        !           157:            quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
        !           158:            label = nametable[((int) circle) - 1][quadrant];
        !           159:            }
        !           160:        }
        !           161: 
        !           162:     if (shortflag)
        !           163:        sprintf(Databuf, "%.29s", label);
        !           164:     else
        !           165:        sprintf(Databuf, " is in %s  (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
        !           166: 
        !           167:     return(Databuf);
        !           168: }
        !           169: /**/
        !           170: /************************************************************************
        !           171: /
        !           172: / FUNCTION NAME: tradingpost()
        !           173: /
        !           174: / FUNCTION: do trading post stuff
        !           175: /
        !           176: / AUTHOR: E. A. Estes, 12/4/85
        !           177: /
        !           178: / ARGUMENTS: none
        !           179: /
        !           180: / RETURN VALUE: none
        !           181: /
        !           182: / MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(), 
        !           183: /      sleep(), floor(), wmove(), drandom(), wclear(), printw(), 
        !           184: /      altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(), 
        !           185: /      wclrtoeol(), wclrtobot()
        !           186: /
        !           187: / GLOBAL INPUTS: Menu[], Circle, Player, *stdscr, Fileloc, Nobetter[]
        !           188: /
        !           189: / GLOBAL OUTPUTS: Player
        !           190: /
        !           191: / DESCRIPTION:
        !           192: /      Different trading posts have different items.
        !           193: /      Merchants cannot be cheated, but they can be dishonest
        !           194: /      themselves.
        !           195: /
        !           196: /      Shields, swords, and quicksilver are not cumulative.  This is
        !           197: /      one major area of complaint, but there are two reasons for this:
        !           198: /              1) It becomes MUCH too easy to make very large versions
        !           199: /                 of these items.
        !           200: /              2) In the real world, one cannot simply weld two swords
        !           201: /                 together to make a bigger one.
        !           202: /
        !           203: /      At one time, it was possible to sell old weapons at half the purchase
        !           204: /      price.  This resulted in huge amounts of gold floating around,
        !           205: /      and the game lost much of its challenge.
        !           206: /
        !           207: /      Also, purchasing gems defeats the whole purpose of gold.  Gold
        !           208: /      is small change for lower level players.  They really shouldn't
        !           209: /      be able to accumulate more than enough gold for a small sword or
        !           210: /      a few books.  Higher level players shouldn't even bother to pick
        !           211: /      up gold, except maybe to buy mana once in a while.
        !           212: /
        !           213: /************************************************************************/
        !           214: 
        !           215: tradingpost()
        !           216: {
        !           217: double numitems;       /* number of items to purchase */
        !           218: double cost;           /* cost of purchase */
        !           219: double blessingcost;   /* cost of blessing */
        !           220: int    ch;             /* input */
        !           221: register int   size;   /* size of the trading post */
        !           222: register int   loop;   /* loop counter */
        !           223: int    cheat = 0;      /* number of times player has tried to cheat */
        !           224: bool   dishonest = FALSE;/* set when merchant is dishonest */
        !           225: 
        !           226:     Player.p_status = S_TRADING;
        !           227:     writerecord(&Player, Fileloc);
        !           228: 
        !           229:     clear();
        !           230:     addstr("You are at a trading post. All purchases must be made with gold.");
        !           231: 
        !           232:     size = sqrt(fabs(Player.p_x / 100)) + 1;
        !           233:     size = MIN(7, size);
        !           234: 
        !           235:     /* set up cost of blessing */
        !           236:     blessingcost = 1000.0 * (Player.p_level + 5.0);
        !           237: 
        !           238:     /* print Menu */
        !           239:     move(7, 0);
        !           240:     for (loop = 0; loop < size; ++loop)
        !           241:        /* print Menu */
        !           242:        {
        !           243:        if (loop == 6)
        !           244:            cost = blessingcost;
        !           245:        else
        !           246:            cost = Menu[loop].cost;
        !           247:        printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
        !           248:        }
        !           249: 
        !           250:     mvprintw(5, 0, "L:Leave  P:Purchase  S:Sell Gems ? ");
        !           251: 
        !           252:     for (;;)
        !           253:        {
        !           254:        adjuststats();  /* truncate any bad values */
        !           255: 
        !           256:        /* print some important statistics */
        !           257:        mvprintw(1, 0, "Gold:   %9.0f  Gems:  %9.0f  Level:   %6.0f  Charms: %6d\n",
        !           258:            Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
        !           259:        printw("Shield: %9.0f  Sword: %9.0f  Quicksilver:%3.0f  Blessed: %s\n",
        !           260:            Player.p_shield, Player.p_sword, Player.p_quksilver,
        !           261:            (Player.p_blessing ? " True" : "False"));
        !           262:        printw("Brains: %9.0f  Mana:  %9.0f", Player.p_brains, Player.p_mana);
        !           263: 
        !           264:        move(5, 36);
        !           265:        ch = getanswer("LPS", FALSE);
        !           266:        move(15, 0);
        !           267:        clrtobot();
        !           268:        switch(ch)
        !           269:            {
        !           270:            case 'L':           /* leave */
        !           271:            case '\n':
        !           272:                altercoordinates(0.0, 0.0, A_NEAR);
        !           273:                return;
        !           274: 
        !           275:            case 'P':           /* make purchase */
        !           276:                mvaddstr(15, 0, "What what would you like to buy ? ");
        !           277:                ch = getanswer(" 1234567", FALSE);
        !           278:                move(15, 0);
        !           279:                clrtoeol();
        !           280: 
        !           281:                if (ch - '0' > size)
        !           282:                    addstr("Sorry, this merchant doesn't have that.");
        !           283:                else
        !           284:                    switch (ch)
        !           285:                        {
        !           286:                        case '1':
        !           287:                            printw("Mana is one per %.0f gold piece.  How many do you want (%.0f max) ? ",
        !           288:                                Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
        !           289:                            cost = (numitems = floor(infloat())) * Menu[0].cost;
        !           290: 
        !           291:                            if (cost > Player.p_gold || numitems < 0)
        !           292:                                ++cheat;
        !           293:                            else
        !           294:                                {
        !           295:                                cheat = 0;
        !           296:                                Player.p_gold -= cost;
        !           297:                                if (drandom() < 0.02)
        !           298:                                    dishonest = TRUE;
        !           299:                                else
        !           300:                                    Player.p_mana += numitems;
        !           301:                                }
        !           302:                            break;
        !           303: 
        !           304:                        case '2':
        !           305:                            printw("Shields are %.0f per +1.  How many do you want (%.0f max) ? ",
        !           306:                                Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
        !           307:                            cost = (numitems = floor(infloat())) * Menu[1].cost;
        !           308: 
        !           309:                            if (numitems == 0.0)
        !           310:                                break;
        !           311:                            else if (cost > Player.p_gold || numitems < 0)
        !           312:                                ++cheat;
        !           313:                            else if (numitems < Player.p_shield)
        !           314:                                NOBETTER();
        !           315:                            else
        !           316:                                {
        !           317:                                cheat = 0;
        !           318:                                Player.p_gold -= cost;
        !           319:                                if (drandom() < 0.02)
        !           320:                                    dishonest = TRUE;
        !           321:                                else
        !           322:                                    Player.p_shield = numitems;
        !           323:                                }
        !           324:                            break;
        !           325: 
        !           326:                        case '3':
        !           327:                            printw("A book costs %.0f gp.  How many do you want (%.0f max) ? ",
        !           328:                                Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
        !           329:                            cost = (numitems = floor(infloat())) * Menu[2].cost;
        !           330: 
        !           331:                            if (cost > Player.p_gold || numitems < 0)
        !           332:                                ++cheat;
        !           333:                            else
        !           334:                                {
        !           335:                                cheat = 0;
        !           336:                                Player.p_gold -= cost;
        !           337:                                if (drandom() < 0.02)
        !           338:                                    dishonest = TRUE;
        !           339:                                else if (drandom() * numitems > Player.p_level / 10.0
        !           340:                                    && numitems != 1)
        !           341:                                    {
        !           342:                                    printw("\nYou blew your mind!\n");
        !           343:                                    Player.p_brains /= 5;
        !           344:                                    }
        !           345:                                else
        !           346:                                    {
        !           347:                                    Player.p_brains += floor(numitems) * ROLL(20, 8);
        !           348:                                    }
        !           349:                                }
        !           350:                            break;
        !           351: 
        !           352:                        case '4':
        !           353:                            printw("Swords are %.0f gp per +1.  How many + do you want (%.0f max) ? ",
        !           354:                                Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
        !           355:                            cost = (numitems = floor(infloat())) * Menu[3].cost;
        !           356: 
        !           357:                            if (numitems == 0.0)
        !           358:                                break;
        !           359:                            else if (cost > Player.p_gold || numitems < 0)
        !           360:                                ++cheat;
        !           361:                            else if (numitems < Player.p_sword)
        !           362:                                NOBETTER();
        !           363:                            else
        !           364:                                {
        !           365:                                cheat = 0;
        !           366:                                Player.p_gold -= cost;
        !           367:                                if (drandom() < 0.02)
        !           368:                                    dishonest = TRUE;
        !           369:                                else
        !           370:                                    Player.p_sword = numitems;
        !           371:                                }
        !           372:                            break;
        !           373: 
        !           374:                        case '5':
        !           375:                            printw("A charm costs %.0f gp.  How many do you want (%.0f max) ? ",
        !           376:                                Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
        !           377:                            cost = (numitems = floor(infloat())) * Menu[4].cost;
        !           378: 
        !           379:                            if (cost > Player.p_gold || numitems < 0)
        !           380:                                ++cheat;
        !           381:                            else
        !           382:                                {
        !           383:                                cheat = 0;
        !           384:                                Player.p_gold -= cost;
        !           385:                                if (drandom() < 0.02)
        !           386:                                    dishonest = TRUE;
        !           387:                                else
        !           388:                                    Player.p_charms += numitems;
        !           389:                                }
        !           390:                            break;
        !           391: 
        !           392:                        case '6':
        !           393:                            printw("Quicksilver is %.0f gp per +1.  How many + do you want (%.0f max) ? ",
        !           394:                                Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
        !           395:                            cost = (numitems = floor(infloat())) * Menu[5].cost;
        !           396: 
        !           397:                            if (numitems == 0.0)
        !           398:                                break;
        !           399:                            else if (cost > Player.p_gold || numitems < 0)
        !           400:                                ++cheat;
        !           401:                            else if (numitems < Player.p_quksilver)
        !           402:                                NOBETTER();
        !           403:                            else
        !           404:                                {
        !           405:                                cheat = 0;
        !           406:                                Player.p_gold -= cost;
        !           407:                                if (drandom() < 0.02)
        !           408:                                    dishonest = TRUE;
        !           409:                                else
        !           410:                                    Player.p_quksilver = numitems;
        !           411:                                }
        !           412:                            break;
        !           413: 
        !           414:                        case '7':
        !           415:                            if (Player.p_blessing)
        !           416:                                {
        !           417:                                addstr("You already have a blessing.");
        !           418:                                break;
        !           419:                                }
        !           420: 
        !           421:                            printw("A blessing requires a %.0f gp donation.  Still want one ? ", blessingcost);
        !           422:                            ch = getanswer("NY", FALSE);
        !           423: 
        !           424:                            if (ch == 'Y')
        !           425:                                if (Player.p_gold < blessingcost)
        !           426:                                    ++cheat;
        !           427:                                else
        !           428:                                    {
        !           429:                                    cheat = 0;
        !           430:                                    Player.p_gold -= blessingcost;
        !           431:                                    if (drandom() < 0.02)
        !           432:                                        dishonest = TRUE;
        !           433:                                    else
        !           434:                                        Player.p_blessing = TRUE;
        !           435:                                    }
        !           436:                            break;
        !           437:                        }
        !           438:            break;
        !           439: 
        !           440:            case 'S':           /* sell gems */
        !           441:                mvprintw(15, 0, "A gem is worth %.0f gp.  How many do you want to sell (%.0f max) ? ",
        !           442:                    (double) N_GEMVALUE, Player.p_gems);
        !           443:                numitems = floor(infloat());
        !           444: 
        !           445:                if (numitems > Player.p_gems || numitems < 0)
        !           446:                    ++cheat;
        !           447:                else
        !           448:                    {
        !           449:                    cheat = 0;
        !           450:                    Player.p_gems -= numitems;
        !           451:                    Player.p_gold += numitems * N_GEMVALUE;
        !           452:                    }
        !           453:            }
        !           454: 
        !           455:        if (cheat == 1)
        !           456:            mvaddstr(17, 0, "Come on, merchants aren't stupid.  Stop cheating.\n");
        !           457:        else if (cheat == 2)
        !           458:            {
        !           459:            mvaddstr(17, 0, "You had your chance.  This merchant happens to be\n");
        !           460:            printw("a %.0f level magic user, and you made %s mad!\n",
        !           461:                ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her");
        !           462:            altercoordinates(0.0, 0.0, A_FAR);
        !           463:            Player.p_energy /= 2.0;
        !           464:            ++Player.p_sin;
        !           465:            more(23);
        !           466:            return;
        !           467:            }
        !           468:        else if (dishonest)
        !           469:            {
        !           470:            mvaddstr(17, 0, "The merchant stole your money!");
        !           471:            refresh();
        !           472:            altercoordinates(Player.p_x - Player.p_x / 10.0,
        !           473:                Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
        !           474:            sleep(2);
        !           475:            return;
        !           476:            }
        !           477:        }
        !           478: }
        !           479: /**/
        !           480: /************************************************************************
        !           481: /
        !           482: / FUNCTION NAME: displaystats()
        !           483: /
        !           484: / FUNCTION: print out important player statistics
        !           485: /
        !           486: / AUTHOR: E. A. Estes, 12/4/85
        !           487: /
        !           488: / ARGUMENTS: none
        !           489: /
        !           490: / RETURN VALUE: none
        !           491: /
        !           492: / MODULES CALLED: descrstatus(), descrlocation(), mvprintw()
        !           493: /
        !           494: / GLOBAL INPUTS: Users, Player
        !           495: /
        !           496: / GLOBAL OUTPUTS: none
        !           497: /
        !           498: / DESCRIPTION:
        !           499: /      Important player statistics are printed on the screen.
        !           500: /
        !           501: /************************************************************************/
        !           502: 
        !           503: displaystats()
        !           504: {
        !           505:     mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
        !           506:     mvprintw(1, 0, "Level :%7.0f   Energy  :%9.0f(%9.0f)  Mana :%9.0f  Users:%3d\n",
        !           507:        Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
        !           508:        Player.p_mana, Users);
        !           509:     mvprintw(2, 0, "Quick :%3.0f(%3.0f)  Strength:%9.0f(%9.0f)  Gold :%9.0f  %s\n",
        !           510:        Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
        !           511:        Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
        !           512: }
        !           513: /**/
        !           514: /************************************************************************
        !           515: /
        !           516: / FUNCTION NAME: allstatslist()
        !           517: /
        !           518: / FUNCTION: show player items
        !           519: /
        !           520: / AUTHOR: E. A. Estes, 12/4/85
        !           521: /
        !           522: / ARGUMENTS: none
        !           523: /
        !           524: / RETURN VALUE: none
        !           525: /
        !           526: / MODULES CALLED: mvprintw(), descrtype()
        !           527: /
        !           528: / GLOBAL INPUTS: Player
        !           529: /
        !           530: / GLOBAL OUTPUTS: none
        !           531: /
        !           532: / DESCRIPTION:
        !           533: /      Print out some player statistics of lesser importance.
        !           534: /
        !           535: /************************************************************************/
        !           536: 
        !           537: allstatslist()
        !           538: {
        !           539: static char    *flags[] =      /* to print value of some bools */
        !           540:            {
        !           541:            "False", 
        !           542:            " True"
        !           543:            };
        !           544: 
        !           545:     mvprintw( 8,  0, "Type: %s\n",  descrtype(&Player,  FALSE));
        !           546: 
        !           547:     mvprintw(10,  0, "Experience: %9.0f", Player.p_experience);
        !           548:     mvprintw(11,  0, "Brains    : %9.0f", Player.p_brains);
        !           549:     mvprintw(12,  0, "Magic Lvl : %9.0f", Player.p_magiclvl);
        !           550:     mvprintw(13,  0, "Sin       : %9.5f", Player.p_sin);
        !           551:     mvprintw(14,  0, "Poison    : %9.5f", Player.p_poison);
        !           552:     mvprintw(15,  0, "Gems      : %9.0f", Player.p_gems);
        !           553:     mvprintw(16,  0, "Age       : %9d", Player.p_age);
        !           554:     mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
        !           555:     mvprintw(11, 40, "Amulets   : %9d", Player.p_amulets);
        !           556:     mvprintw(12, 40, "Charms    : %9d", Player.p_charms);
        !           557:     mvprintw(13, 40, "Crowns    : %9d", Player.p_crowns);
        !           558:     mvprintw(14, 40, "Shield    : %9.0f", Player.p_shield);
        !           559:     mvprintw(15, 40, "Sword     : %9.0f", Player.p_sword);
        !           560:     mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
        !           561: 
        !           562:     mvprintw(18,  0, "Blessing: %s   Ring: %s   Virgin: %s   Palantir: %s", 
        !           563:        flags[Player.p_blessing], flags[Player.p_ring.ring_type != R_NONE], 
        !           564:        flags[Player.p_virgin], flags[Player.p_palantir]);
        !           565: }
        !           566: /**/
        !           567: /************************************************************************
        !           568: /
        !           569: / FUNCTION NAME: descrtype()
        !           570: /
        !           571: / FUNCTION: return a string specifying player type
        !           572: /
        !           573: / AUTHOR: E. A. Estes, 12/4/85
        !           574: /
        !           575: / ARGUMENTS:
        !           576: /      struct player playerp - pointer to structure for player
        !           577: /      bool shortflag - set if short form is desired
        !           578: /
        !           579: / RETURN VALUE: pointer to string describing player type
        !           580: /
        !           581: / MODULES CALLED: strcpy()
        !           582: /
        !           583: / GLOBAL INPUTS: Databuf[]
        !           584: /
        !           585: / GLOBAL OUTPUTS: Databuf[]
        !           586: /
        !           587: / DESCRIPTION:
        !           588: /      Return a string describing the player type.
        !           589: /      King, council, valar, supercedes other types.
        !           590: /      The first character of the string is '*' if the player
        !           591: /      has a crown.
        !           592: /      If 'shortflag' is TRUE, return a 3 character string.
        !           593: /
        !           594: /************************************************************************/
        !           595: 
        !           596: char   *
        !           597: descrtype(playerp, shortflag)
        !           598: struct player *playerp;
        !           599: bool   shortflag;
        !           600: {
        !           601: register int type;     /* for caluculating result subscript */
        !           602: static char    *results[] =    /* description table */
        !           603:                        {
        !           604:                        " Magic User", " MU",
        !           605:                        " Fighter", " F ",
        !           606:                        " Elf", " E ",
        !           607:                        " Dwarf", " D ",
        !           608:                        " Halfling", " H ",
        !           609:                        " Experimento", " EX",
        !           610:                        " Super", " S ",
        !           611:                        " King", " K ",
        !           612:                        " Council of Wise", " CW",
        !           613:                        " Ex-Valar", " EV",
        !           614:                        " Valar", " V ",
        !           615:                        " ? ", " ? "
        !           616:                        };
        !           617: 
        !           618:     type = playerp->p_type;
        !           619: 
        !           620:     switch (playerp->p_specialtype)
        !           621:        {
        !           622:        case SC_NONE:
        !           623:            type = playerp->p_type;
        !           624:            break;
        !           625: 
        !           626:        case SC_KING:
        !           627:            type = 7;
        !           628:            break;
        !           629: 
        !           630:        case SC_COUNCIL:
        !           631:            type = 8;
        !           632:            break;
        !           633: 
        !           634:        case SC_EXVALAR:
        !           635:            type = 9;
        !           636:            break;
        !           637: 
        !           638:        case SC_VALAR:
        !           639:            type = 10;
        !           640:            break;
        !           641:        }
        !           642: 
        !           643:     type *= 2;         /* calculate offset */
        !           644: 
        !           645:     if (type > 20)
        !           646:        /* error */
        !           647:        type = 22;
        !           648: 
        !           649:     if (shortflag)
        !           650:        /* use short descriptions */
        !           651:        ++type;
        !           652: 
        !           653:     if (playerp->p_crowns > 0)
        !           654:        {
        !           655:        strcpy(Databuf, results[type]);
        !           656:        Databuf[0] = '*';
        !           657:        return(Databuf);
        !           658:        }
        !           659:     else
        !           660:        return(results[type]);
        !           661: }
        !           662: /**/
        !           663: /************************************************************************
        !           664: /
        !           665: / FUNCTION NAME: findname()
        !           666: /
        !           667: / FUNCTION: find location in player file of given name
        !           668: /
        !           669: / AUTHOR: E. A. Estes, 12/4/85
        !           670: /
        !           671: / ARGUMENTS:
        !           672: /      char *name - name of character to look for
        !           673: /      struct player *playerp - pointer of structure to fill
        !           674: /
        !           675: / RETURN VALUE: location of player if found, -1 otherwise
        !           676: /
        !           677: / MODULES CALLED: fread(), fseek(), strcmp()
        !           678: /
        !           679: / GLOBAL INPUTS: Wizard, *Playersfp
        !           680: /
        !           681: / GLOBAL OUTPUTS: none
        !           682: /
        !           683: / DESCRIPTION:
        !           684: /      Search the player file for the player of the given name.
        !           685: /      If player is found, fill structure with player data.
        !           686: /
        !           687: /************************************************************************/
        !           688: 
        !           689: long
        !           690: findname(name, playerp)
        !           691: register char  *name;
        !           692: register struct player *playerp;
        !           693: {
        !           694: long   loc = 0;                        /* location in the file */
        !           695: 
        !           696:     fseek(Playersfp, 0L, 0);
        !           697:     while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
        !           698:        {
        !           699:        if (strcmp(playerp->p_name, name) == 0)
        !           700:            {
        !           701:            if (playerp->p_status != S_NOTUSED || Wizard)
        !           702:                /* found it */
        !           703:                return(loc);
        !           704:            }
        !           705:        loc += SZ_PLAYERSTRUCT;
        !           706:        }
        !           707: 
        !           708:     return(-1);
        !           709: }
        !           710: /**/
        !           711: /************************************************************************
        !           712: /
        !           713: / FUNCTION NAME: allocrecord()
        !           714: /
        !           715: / FUNCTION: find space in the player file for a new character
        !           716: /
        !           717: / AUTHOR: E. A. Estes, 12/4/85
        !           718: /
        !           719: / ARGUMENTS: none
        !           720: /
        !           721: / RETURN VALUE: location of free space in file
        !           722: /
        !           723: / MODULES CALLED: initplayer(), writerecord(), fread(), fseek()
        !           724: /
        !           725: / GLOBAL INPUTS: Other, *Playersfp
        !           726: /
        !           727: / GLOBAL OUTPUTS: Player
        !           728: /
        !           729: / DESCRIPTION:
        !           730: /      Search the player file for an unused entry.  If none are found,
        !           731: /      make one at the end of the file.
        !           732: /
        !           733: /************************************************************************/
        !           734: 
        !           735: long
        !           736: allocrecord()
        !           737: {
        !           738: long   loc = 0L;               /* location in file */
        !           739: 
        !           740:     fseek(Playersfp, 0L, 0);
        !           741:     while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
        !           742:        {
        !           743:        if (Other.p_status == S_NOTUSED)
        !           744:            /* found an empty record */
        !           745:            return(loc);
        !           746:        else
        !           747:            loc += SZ_PLAYERSTRUCT;
        !           748:        }
        !           749: 
        !           750:     /* make a new record */
        !           751:     initplayer(&Other);
        !           752:     Player.p_status = S_OFF;
        !           753:     writerecord(&Other, loc);
        !           754: 
        !           755:     return(loc);
        !           756: }
        !           757: /**/
        !           758: /************************************************************************
        !           759: /
        !           760: / FUNCTION NAME: freerecord()
        !           761: /
        !           762: / FUNCTION: free up a record on the player file
        !           763: /
        !           764: / AUTHOR: E. A. Estes, 2/7/86
        !           765: /
        !           766: / ARGUMENTS:
        !           767: /      struct player playerp - pointer to structure to free
        !           768: /      long loc - location in file to free
        !           769: /
        !           770: / RETURN VALUE: none
        !           771: /
        !           772: / MODULES CALLED: writerecord()
        !           773: /
        !           774: / GLOBAL INPUTS: none
        !           775: /
        !           776: / GLOBAL OUTPUTS: none
        !           777: /
        !           778: / DESCRIPTION:
        !           779: /      Mark structure as not used, and update player file.
        !           780: /
        !           781: /************************************************************************/
        !           782: 
        !           783: freerecord(playerp, loc)
        !           784: struct player  *playerp;
        !           785: long   loc;
        !           786: {
        !           787:     playerp->p_name[0] = CH_MARKDELETE;
        !           788:     playerp->p_status = S_NOTUSED;
        !           789:     writerecord(playerp, loc);
        !           790: }
        !           791: /**/
        !           792: /************************************************************************
        !           793: /
        !           794: / FUNCTION NAME: leavegame()
        !           795: /
        !           796: / FUNCTION: leave game
        !           797: /
        !           798: / AUTHOR: E. A. Estes, 12/4/85
        !           799: /
        !           800: / ARGUMENTS: none
        !           801: /
        !           802: / RETURN VALUE: none
        !           803: /
        !           804: / MODULES CALLED: freerecord(), writerecord(), cleanup()
        !           805: /
        !           806: / GLOBAL INPUTS: Player, Fileloc
        !           807: /
        !           808: / GLOBAL OUTPUTS: Player
        !           809: /
        !           810: / DESCRIPTION:
        !           811: /      Mark player as inactive, and cleanup.
        !           812: /      Do not save players below level 1.
        !           813: /
        !           814: /************************************************************************/
        !           815: 
        !           816: leavegame()
        !           817: {
        !           818: 
        !           819:     if (Player.p_level < 1.0)
        !           820:        /* delete character */
        !           821:        freerecord(&Player, Fileloc);
        !           822:     else
        !           823:        {
        !           824:        Player.p_status = S_OFF;
        !           825:        writerecord(&Player, Fileloc);
        !           826:        }
        !           827: 
        !           828:     cleanup(TRUE);
        !           829:     /*NOTREACHED*/
        !           830: }
        !           831: /**/
        !           832: /************************************************************************
        !           833: /
        !           834: / FUNCTION NAME: death()
        !           835: /
        !           836: / FUNCTION: death routine
        !           837: /
        !           838: / AUTHOR: E. A. Estes, 12/4/85
        !           839: /
        !           840: / ARGUMENTS:
        !           841: /      char *how - pointer to string describing cause of death
        !           842: /
        !           843: / RETURN VALUE: none
        !           844: /
        !           845: / MODULES CALLED: freerecord(), enterscore(), more(), exit(), fread(), 
        !           846: /      fseek(), execl(), fopen(), floor(), wmove(), drandom(), wclear(), strcmp(), 
        !           847: /      fwrite(), fflush(), printw(), strcpy(), fclose(), waddstr(), cleanup(), 
        !           848: /      fprintf(), wrefresh(), getanswer(), descrtype()
        !           849: /
        !           850: / GLOBAL INPUTS: Curmonster, Wizard, Player, *stdscr, Fileloc, *Monstfp
        !           851: /
        !           852: / GLOBAL OUTPUTS: Player
        !           853: /
        !           854: / DESCRIPTION:
        !           855: /      Kill off current player.
        !           856: /      Handle rings, and multiple lives.
        !           857: /      Print an appropriate message.
        !           858: /      Update scoreboard, lastdead, and let other players know about
        !           859: /      the demise of their comrade.
        !           860: /
        !           861: /************************************************************************/
        !           862: 
        !           863: death(how)
        !           864: char   *how;
        !           865: {
        !           866: FILE   *fp;            /* for updating various files */
        !           867: int    ch;             /* input */
        !           868: static char    *deathmesg[] =
        !           869:        /* add more messages here, if desired */
        !           870:        {
        !           871:        "You have been wounded beyond repair.  ",
        !           872:        "You have been disemboweled.  ",
        !           873:        "You've been mashed, mauled, and spit upon.  (You're dead.)\n",
        !           874:        "You died!  ",
        !           875:        "You're a complete failure -- you've died!!\n",
        !           876:        "You have been dealt a fatal blow!  "
        !           877:        };
        !           878: 
        !           879:     clear();
        !           880: 
        !           881:     if (strcmp(how, "Stupidity") != 0)
        !           882:        {
        !           883:        if (Player.p_level > 9999.0)
        !           884:            /* old age */
        !           885:            addstr("Characters must be retired upon reaching level 10000.  Sorry.");
        !           886:        else if (Player.p_lives > 0)
        !           887:            /* extra lives */
        !           888:            {
        !           889:            addstr("You should be more cautious.  You've been killed.\n");
        !           890:            printw("You only have %d more chance(s).\n", --Player.p_lives);
        !           891:            more(3);
        !           892:            Player.p_energy = Player.p_maxenergy;
        !           893:            return;
        !           894:            }
        !           895:        else if (Player.p_specialtype == SC_VALAR)
        !           896:            {
        !           897:            addstr("You had your chances, but Valar aren't totally\n");
        !           898:            addstr("immortal.  You are now left to wither and die . . .\n");
        !           899:            more(3);
        !           900:            Player.p_brains = Player.p_level / 25.0;
        !           901:            Player.p_energy = Player.p_maxenergy /= 5.0;
        !           902:            Player.p_quksilver = Player.p_sword = 0.0;
        !           903:            Player.p_specialtype = SC_COUNCIL;
        !           904:            return;
        !           905:            }
        !           906:        else if (Player.p_ring.ring_inuse &&
        !           907:            (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
        !           908:            /* good ring in use - saved from death */
        !           909:            {
        !           910:            mvaddstr(4, 0, "Your ring saved you from death!\n");
        !           911:            refresh();
        !           912:            Player.p_ring.ring_type = R_NONE;
        !           913:            Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
        !           914:            if (Player.p_crowns > 0)
        !           915:                --Player.p_crowns;
        !           916:            return;
        !           917:            }
        !           918:        else if (Player.p_ring.ring_type == R_BAD
        !           919:            || Player.p_ring.ring_type == R_SPOILED)
        !           920:            /* bad ring in possession; name idiot after player */
        !           921:            {
        !           922:            mvaddstr(4, 0,
        !           923:                "Your ring has taken control of you and turned you into a monster!\n");
        !           924:            fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
        !           925:            fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
        !           926:            strcpy(Curmonster.m_name, Player.p_name);
        !           927:            fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
        !           928:            fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
        !           929:            fflush(Monstfp);
        !           930:            }
        !           931:        }
        !           932: 
        !           933:     enterscore();              /* update score board */
        !           934: 
        !           935:     /* put info in last dead file */
        !           936:     fp = fopen(_PATH_LASTDEAD, "w");
        !           937:     fprintf(fp,"%s (%s, run by %s, level %.0f, killed by %s)",
        !           938:        Player.p_name, descrtype(&Player, TRUE),
        !           939:        Player.p_login, Player.p_level, how);
        !           940:     fclose(fp);
        !           941: 
        !           942:     /* let other players know */
        !           943:     fp = fopen(_PATH_MESS, "w");
        !           944:     fprintf(fp, "%s was killed by %s.", Player.p_name, how);
        !           945:     fclose(fp);
        !           946: 
        !           947:     freerecord(&Player, Fileloc);
        !           948: 
        !           949:     clear();
        !           950:     move(10, 0);
        !           951:     addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
        !           952:     addstr("Care to give it another try ? ");
        !           953:     ch = getanswer("NY", FALSE);
        !           954: 
        !           955:     if (ch == 'Y')
        !           956:        {
        !           957:        cleanup(FALSE);
        !           958:        execl(_PATH_GAMEPROG, "phantasia", "-s",
        !           959:            (Wizard ? "-S": (char *) NULL), 0);
        !           960:        exit(0);
        !           961:        /*NOTREACHED*/
        !           962:        }
        !           963: 
        !           964:     cleanup(TRUE);
        !           965:     /*NOTREACHED*/
        !           966: }
        !           967: /**/
        !           968: /************************************************************************
        !           969: /
        !           970: / FUNCTION NAME: writerecord()
        !           971: /
        !           972: / FUNCTION: update structure in player file
        !           973: /
        !           974: / AUTHOR: E. A. Estes, 12/4/85
        !           975: /
        !           976: / ARGUMENTS:
        !           977: /      struct player *playerp - pointer to structure to write out
        !           978: /      long place - location in file to updata
        !           979: /
        !           980: / RETURN VALUE: none
        !           981: /
        !           982: / MODULES CALLED: fseek(), fwrite(), fflush()
        !           983: /
        !           984: / GLOBAL INPUTS: *Playersfp
        !           985: /
        !           986: / GLOBAL OUTPUTS: none
        !           987: /
        !           988: / DESCRIPTION:
        !           989: /      Update location in player file with given structure.
        !           990: /
        !           991: /************************************************************************/
        !           992: 
        !           993: writerecord(playerp, place)
        !           994: register struct player *playerp;
        !           995: long   place;
        !           996: {
        !           997:     fseek(Playersfp, place, 0);
        !           998:     fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
        !           999:     fflush(Playersfp);
        !          1000: }
        !          1001: /**/
        !          1002: /************************************************************************
        !          1003: /
        !          1004: / FUNCTION NAME: explevel()
        !          1005: /
        !          1006: / FUNCTION: calculate level based upon experience
        !          1007: /
        !          1008: / AUTHOR: E. A. Estes, 12/4/85
        !          1009: /
        !          1010: / ARGUMENTS:
        !          1011: /      double experience - experience to calculate experience level from
        !          1012: /
        !          1013: / RETURN VALUE: experience level
        !          1014: /
        !          1015: / MODULES CALLED: pow(), floor()
        !          1016: /
        !          1017: / GLOBAL INPUTS: none
        !          1018: /
        !          1019: / GLOBAL OUTPUTS: none
        !          1020: /
        !          1021: / DESCRIPTION: 
        !          1022: /      Experience level is a geometric progression.  This has been finely
        !          1023: /      tuned over the years, and probably should not be changed.
        !          1024: /
        !          1025: /************************************************************************/
        !          1026: 
        !          1027: double
        !          1028: explevel(experience)
        !          1029: double experience;
        !          1030: {
        !          1031:     if (experience < 1.1e7)
        !          1032:        return(floor(pow((experience / 1000.0), 0.4875)));
        !          1033:     else
        !          1034:        return(floor(pow((experience / 1250.0), 0.4865)));
        !          1035: }
        !          1036: /**/
        !          1037: /************************************************************************
        !          1038: /
        !          1039: / FUNCTION NAME: truncstring()
        !          1040: /
        !          1041: / FUNCTION: truncate trailing blanks off a string
        !          1042: /
        !          1043: / AUTHOR: E. A. Estes, 12/4/85
        !          1044: /
        !          1045: / ARGUMENTS: 
        !          1046: /      char *string - pointer to null terminated string
        !          1047: /
        !          1048: / RETURN VALUE: none
        !          1049: /
        !          1050: / MODULES CALLED: strlen()
        !          1051: /
        !          1052: / GLOBAL INPUTS: none
        !          1053: /
        !          1054: / GLOBAL OUTPUTS: none
        !          1055: /
        !          1056: / DESCRIPTION: 
        !          1057: /      Put nul characters in place of spaces at the end of the string.
        !          1058: /
        !          1059: /************************************************************************/
        !          1060: 
        !          1061: truncstring(string)
        !          1062: register char  *string;
        !          1063: {
        !          1064: register int   length;         /* length of string */
        !          1065: 
        !          1066:     length = strlen(string);
        !          1067:     while (string[--length] == ' ')
        !          1068:        string[length] = '\0';
        !          1069: }
        !          1070: /**/
        !          1071: /************************************************************************
        !          1072: /
        !          1073: / FUNCTION NAME: altercoordinates()
        !          1074: /
        !          1075: / FUNCTION: Alter x, y coordinates and set/check location flags
        !          1076: /
        !          1077: / AUTHOR: E. A. Estes, 12/16/85
        !          1078: /
        !          1079: / ARGUMENTS: 
        !          1080: /      double xnew, ynew - new x, y coordinates
        !          1081: /      int operation - operation to perform with coordinates
        !          1082: /
        !          1083: / RETURN VALUE: none
        !          1084: /
        !          1085: / MODULES CALLED: fabs(), floor(), drandom(), distance()
        !          1086: /
        !          1087: / GLOBAL INPUTS: Circle, Beyond, Player
        !          1088: /
        !          1089: / GLOBAL OUTPUTS: Marsh, Circle, Beyond, Throne, Player, Changed
        !          1090: /
        !          1091: / DESCRIPTION: 
        !          1092: /      This module is called whenever the player's coordinates are altered.
        !          1093: /      If the player is beyond the point of no return, he/she is forced
        !          1094: /      to stay there.
        !          1095: /
        !          1096: /************************************************************************/
        !          1097: 
        !          1098: altercoordinates(xnew, ynew, operation)
        !          1099: double xnew;
        !          1100: double ynew;
        !          1101: int    operation;
        !          1102: {
        !          1103:     switch (operation)
        !          1104:        {
        !          1105:        case A_FORCED:  /* move with no checks */
        !          1106:            break;
        !          1107: 
        !          1108:        case A_NEAR:    /* pick random coordinates near */
        !          1109:            xnew = Player.p_x + ROLL(1.0, 5.0);
        !          1110:            ynew = Player.p_y - ROLL(1.0, 5.0);
        !          1111:            /* fall through for check */
        !          1112: 
        !          1113:        case A_SPECIFIC:        /* just move player */
        !          1114:            if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
        !          1115:                /*
        !          1116:                 * cannot move back from point of no return
        !          1117:                 * pick the largest coordinate to remain unchanged
        !          1118:                 */
        !          1119:                {
        !          1120:                if (fabs(xnew) > fabs(ynew))
        !          1121:                    xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
        !          1122:                else
        !          1123:                    ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
        !          1124:                }
        !          1125:            break;
        !          1126: 
        !          1127:        case A_FAR:     /* pick random coordinates far */
        !          1128:            xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
        !          1129:            ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
        !          1130:            break;
        !          1131:        }
        !          1132:     
        !          1133:     /* now set location flags and adjust coordinates */
        !          1134:     Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
        !          1135: 
        !          1136:     /* set up flags based upon location */
        !          1137:     Throne = Marsh = Beyond = FALSE;
        !          1138: 
        !          1139:     if (Player.p_x == 0.0 && Player.p_y == 0.0)
        !          1140:        Throne = TRUE;
        !          1141:     else if (Circle < 35 && Circle >= 20)
        !          1142:        Marsh = TRUE;
        !          1143:     else if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
        !          1144:        Beyond = TRUE;
        !          1145: 
        !          1146:     Changed = TRUE;
        !          1147: }
        !          1148: /**/
        !          1149: /************************************************************************
        !          1150: /
        !          1151: / FUNCTION NAME: readrecord()
        !          1152: /
        !          1153: / FUNCTION: read a player structure from file
        !          1154: /
        !          1155: / AUTHOR: E. A. Estes, 12/4/85
        !          1156: /
        !          1157: / ARGUMENTS:
        !          1158: /      struct player *playerp - pointer to structure to fill
        !          1159: /      int loc - location of record to read
        !          1160: /
        !          1161: / RETURN VALUE: none
        !          1162: /
        !          1163: / MODULES CALLED: fread(), fseek()
        !          1164: /
        !          1165: / GLOBAL INPUTS: *Playersfp
        !          1166: /
        !          1167: / GLOBAL OUTPUTS: none
        !          1168: /
        !          1169: / DESCRIPTION:
        !          1170: /      Read structure information from player file.
        !          1171: /
        !          1172: /************************************************************************/
        !          1173: 
        !          1174: readrecord(playerp, loc)
        !          1175: register struct player *playerp;
        !          1176: long   loc;
        !          1177: {
        !          1178:     fseek(Playersfp, loc, 0);
        !          1179:     fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
        !          1180: }
        !          1181: /**/
        !          1182: /************************************************************************
        !          1183: /
        !          1184: / FUNCTION NAME: adjuststats()
        !          1185: /
        !          1186: / FUNCTION: adjust player statistics
        !          1187: /
        !          1188: / AUTHOR: E. A. Estes, 12/4/85
        !          1189: /
        !          1190: / ARGUMENTS: none
        !          1191: /
        !          1192: / RETURN VALUE: none
        !          1193: /
        !          1194: / MODULES CALLED: death(), floor(), drandom(), explevel(), movelevel()
        !          1195: /
        !          1196: / GLOBAL INPUTS: Player, *Statptr
        !          1197: /
        !          1198: / GLOBAL OUTPUTS: Circle, Player, Timeout
        !          1199: /
        !          1200: / DESCRIPTION:
        !          1201: /      Handle adjustment and maximums on various player characteristics.
        !          1202: /
        !          1203: /************************************************************************/
        !          1204: 
        !          1205: adjuststats()
        !          1206: {
        !          1207: double dtemp;                          /* for temporary calculations */
        !          1208: 
        !          1209:     if (explevel(Player.p_experience) > Player.p_level)
        !          1210:        /* move one or more levels */
        !          1211:        {
        !          1212:        movelevel();
        !          1213:        if (Player.p_level > 5.0)
        !          1214:            Timeout = TRUE;
        !          1215:        }
        !          1216: 
        !          1217:     if (Player.p_specialtype == SC_VALAR)
        !          1218:        /* valar */
        !          1219:        Circle = Player.p_level / 5.0;
        !          1220: 
        !          1221:     /* calculate effective quickness */
        !          1222:     dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
        !          1223:        - Player.p_level;;
        !          1224:     dtemp = MAX(0.0, dtemp);           /* gold slows player down */
        !          1225:     Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
        !          1226: 
        !          1227:     /* calculate effective strength */
        !          1228:     if (Player.p_poison > 0.0)
        !          1229:        /* poison makes player weaker */
        !          1230:        {
        !          1231:        dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
        !          1232:        dtemp = MAX(0.1, dtemp);
        !          1233:        }
        !          1234:     else
        !          1235:        dtemp = 1.0;
        !          1236:     Player.p_might = dtemp *  Player.p_strength + Player.p_sword;
        !          1237: 
        !          1238:     /* insure that important things are within limits */
        !          1239:     Player.p_quksilver = MIN(99.0, Player.p_quksilver);
        !          1240:     Player.p_mana = MIN(Player.p_mana,
        !          1241:        Player.p_level * Statptr->c_maxmana + 1000.0);
        !          1242:     Player.p_brains = MIN(Player.p_brains,
        !          1243:        Player.p_level * Statptr->c_maxbrains + 200.0);
        !          1244:     Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
        !          1245: 
        !          1246:     /*
        !          1247:      * some implementations have problems with floating point compare
        !          1248:      * we work around it with this stuff
        !          1249:      */
        !          1250:     Player.p_gold = floor(Player.p_gold) + 0.1;
        !          1251:     Player.p_gems = floor(Player.p_gems) + 0.1;
        !          1252:     Player.p_mana = floor(Player.p_mana) + 0.1;
        !          1253: 
        !          1254:     if (Player.p_ring.ring_type != R_NONE)
        !          1255:        /* do ring things */
        !          1256:        {
        !          1257:        /* rest to max */
        !          1258:        Player.p_energy = Player.p_maxenergy + Player.p_shield;
        !          1259: 
        !          1260:         if (Player.p_ring.ring_duration <= 0)
        !          1261:            /* clean up expired rings */
        !          1262:            switch (Player.p_ring.ring_type)
        !          1263:                {
        !          1264:                case R_BAD:     /* ring drives player crazy */
        !          1265:                    Player.p_ring.ring_type = R_SPOILED;
        !          1266:                    Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
        !          1267:                    break;
        !          1268: 
        !          1269:                case R_NAZREG:  /* ring disappears */
        !          1270:                    Player.p_ring.ring_type = R_NONE;
        !          1271:                    break;
        !          1272: 
        !          1273:                case R_SPOILED: /* ring kills player */
        !          1274:                    death("A cursed ring");
        !          1275:                    break;
        !          1276: 
        !          1277:                case R_DLREG:   /* this ring doesn't expire */
        !          1278:                    Player.p_ring.ring_duration = 0;
        !          1279:                    break;
        !          1280:                }
        !          1281:        }
        !          1282: 
        !          1283:     if (Player.p_age / N_AGE > Player.p_degenerated)
        !          1284:        /* age player slightly */
        !          1285:        {
        !          1286:        ++Player.p_degenerated;
        !          1287:        if (Player.p_quickness > 23.0)
        !          1288:            Player.p_quickness *= 0.99;
        !          1289:        Player.p_strength *= 0.97;
        !          1290:        Player.p_brains *= 0.95;
        !          1291:        Player.p_magiclvl *= 0.97;
        !          1292:        Player.p_maxenergy *= 0.95;
        !          1293:        Player.p_quksilver *= 0.95;
        !          1294:        Player.p_sword *= 0.93;
        !          1295:        Player.p_shield *= 0.93;
        !          1296:        }
        !          1297: }
        !          1298: /**/
        !          1299: /************************************************************************
        !          1300: /
        !          1301: / FUNCTION NAME: initplayer()
        !          1302: /
        !          1303: / FUNCTION: initialize a character
        !          1304: /
        !          1305: / AUTHOR: E. A. Estes, 12/4/85
        !          1306: /
        !          1307: / ARGUMENTS:
        !          1308: /      struct player *playerp - pointer to structure to init
        !          1309: /
        !          1310: / RETURN VALUE: none
        !          1311: /
        !          1312: / MODULES CALLED: floor(), drandom()
        !          1313: /
        !          1314: / GLOBAL INPUTS: none
        !          1315: /
        !          1316: / GLOBAL OUTPUTS: none
        !          1317: /
        !          1318: / DESCRIPTION:
        !          1319: /      Put a bunch of default values in the given structure.
        !          1320: /
        !          1321: /************************************************************************/
        !          1322: 
        !          1323: initplayer(playerp)
        !          1324: register struct  player   *playerp;
        !          1325: {
        !          1326:     playerp->p_experience =
        !          1327:     playerp->p_level =
        !          1328:     playerp->p_strength =
        !          1329:     playerp->p_sword =
        !          1330:     playerp->p_might =
        !          1331:     playerp->p_energy =
        !          1332:     playerp->p_maxenergy =
        !          1333:     playerp->p_shield =
        !          1334:     playerp->p_quickness =
        !          1335:     playerp->p_quksilver =
        !          1336:     playerp->p_speed =
        !          1337:     playerp->p_magiclvl =
        !          1338:     playerp->p_mana =
        !          1339:     playerp->p_brains =
        !          1340:     playerp->p_poison =
        !          1341:     playerp->p_gems =
        !          1342:     playerp->p_sin =
        !          1343:     playerp->p_1scratch =
        !          1344:     playerp->p_2scratch = 0.0;
        !          1345: 
        !          1346:     playerp->p_gold = ROLL(50.0, 75.0) + 0.1;  /* give some gold */
        !          1347: 
        !          1348:     playerp->p_x = ROLL(-125.0, 251.0);
        !          1349:     playerp->p_y = ROLL(-125.0, 251.0);                /* give random x, y */
        !          1350: 
        !          1351:     /* clear ring */
        !          1352:     playerp->p_ring.ring_type = R_NONE;
        !          1353:     playerp->p_ring.ring_duration = 0;
        !          1354:     playerp->p_ring.ring_inuse = FALSE;
        !          1355: 
        !          1356:     playerp->p_age = 0L;
        !          1357: 
        !          1358:     playerp->p_degenerated = 1;                        /* don't degenerate initially */
        !          1359: 
        !          1360:     playerp->p_type = C_FIGHTER;               /* default */
        !          1361:     playerp->p_specialtype = SC_NONE;
        !          1362:     playerp->p_lives =
        !          1363:     playerp->p_crowns = 
        !          1364:     playerp->p_charms =
        !          1365:     playerp->p_amulets =
        !          1366:     playerp->p_holywater =
        !          1367:     playerp->p_lastused = 0;
        !          1368:     playerp->p_status = S_NOTUSED;
        !          1369:     playerp->p_tampered = T_OFF;
        !          1370:     playerp->p_istat = I_OFF;
        !          1371: 
        !          1372:     playerp->p_palantir =
        !          1373:     playerp->p_blessing =
        !          1374:     playerp->p_virgin =
        !          1375:     playerp->p_blindness = FALSE;
        !          1376: 
        !          1377:     playerp->p_name[0] =
        !          1378:     playerp->p_password[0] =
        !          1379:     playerp->p_login[0] = '\0';
        !          1380: }
        !          1381: /**/
        !          1382: /************************************************************************
        !          1383: /
        !          1384: / FUNCTION NAME: readmessage()
        !          1385: /
        !          1386: / FUNCTION: read message from other players
        !          1387: /
        !          1388: / AUTHOR: E. A. Estes, 12/4/85
        !          1389: /
        !          1390: / ARGUMENTS: none
        !          1391: /
        !          1392: / RETURN VALUE: none
        !          1393: /
        !          1394: / MODULES CALLED: fseek(), fgets(), wmove(), waddstr(), wclrtoeol()
        !          1395: /
        !          1396: / GLOBAL INPUTS: *stdscr, Databuf[], *Messagefp
        !          1397: /
        !          1398: / GLOBAL OUTPUTS: none
        !          1399: /
        !          1400: / DESCRIPTION:
        !          1401: /      If there is a message from other players, print it.
        !          1402: /
        !          1403: /************************************************************************/
        !          1404: 
        !          1405: readmessage()
        !          1406: {
        !          1407:     move(3, 0);
        !          1408:     clrtoeol();
        !          1409:     fseek(Messagefp, 0L, 0);
        !          1410:     if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
        !          1411:        addstr(Databuf);
        !          1412: }
        !          1413: /**/
        !          1414: /************************************************************************
        !          1415: /
        !          1416: / FUNCTION NAME: error()
        !          1417: /
        !          1418: / FUNCTION: process evironment error
        !          1419: /
        !          1420: / AUTHOR: E. A. Estes, 12/4/85
        !          1421: /
        !          1422: / ARGUMENTS:
        !          1423: /      char *whichfile - pointer to name of file which caused error
        !          1424: /
        !          1425: / RETURN VALUE: none
        !          1426: /
        !          1427: / MODULES CALLED: wclear(), cleanup()
        !          1428: /
        !          1429: / GLOBAL INPUTS: errno, *stdscr, printw(), printf(), Windows
        !          1430: /
        !          1431: / GLOBAL OUTPUTS: none
        !          1432: /
        !          1433: / DESCRIPTION:
        !          1434: /      Print message about offending file, and exit.
        !          1435: /
        !          1436: /************************************************************************/
        !          1437: 
        !          1438: error(whichfile)
        !          1439: char   *whichfile;
        !          1440: {
        !          1441: extern int errno;
        !          1442: extern printw(), printf();
        !          1443: int    (*funcp)();
        !          1444: 
        !          1445:     if (Windows)
        !          1446:        {
        !          1447:        funcp = printw;
        !          1448:        clear();
        !          1449:        }
        !          1450:     else
        !          1451:        funcp = printf;
        !          1452: 
        !          1453:     (*funcp)("An unrecoverable error has occurred reading %s.  (errno = %d)\n", whichfile, errno);
        !          1454:     (*funcp)("Please run 'setup' to determine the problem.\n");
        !          1455:     cleanup(TRUE);
        !          1456:     /*NOTREACHED*/
        !          1457: }
        !          1458: /**/
        !          1459: /************************************************************************
        !          1460: /
        !          1461: / FUNCTION NAME: distance()
        !          1462: /
        !          1463: / FUNCTION: calculate distance between two points
        !          1464: /
        !          1465: / AUTHOR: E. A. Estes, 12/4/85
        !          1466: /
        !          1467: / ARGUMENTS: 
        !          1468: /      double x1, y1 - x, y coordinates of first point
        !          1469: /      double x2, y2 - x, y coordinates of second point
        !          1470: /
        !          1471: / RETURN VALUE: distance between the two points
        !          1472: /
        !          1473: / MODULES CALLED: sqrt()
        !          1474: /
        !          1475: / GLOBAL INPUTS: none
        !          1476: /
        !          1477: / GLOBAL OUTPUTS: none
        !          1478: /
        !          1479: / DESCRIPTION:
        !          1480: /      This function is provided because someone's hypot() library function
        !          1481: /      fails if x1 == x2 && y1 == y2.
        !          1482: /
        !          1483: /************************************************************************/
        !          1484: 
        !          1485: double
        !          1486: distance(x1, x2, y1, y2)
        !          1487: double x1, x2, y1, y2;
        !          1488: {
        !          1489: double deltax, deltay;
        !          1490: 
        !          1491:     deltax = x1 - x2;
        !          1492:     deltay = y1 - y2;
        !          1493:     return(sqrt(deltax * deltax + deltay * deltay));
        !          1494: }
        !          1495: 
        !          1496: /**/
        !          1497: /************************************************************************
        !          1498: /
        !          1499: / FUNCTION NAME: ill_sig()
        !          1500: /
        !          1501: / FUNCTION: exit upon trapping an illegal signal
        !          1502: /
        !          1503: / AUTHOR: E. A. Estes, 12/4/85
        !          1504: /
        !          1505: / ARGUMENTS:
        !          1506: /      int whichsig - signal which occured to cause jump to here
        !          1507: /
        !          1508: / RETURN VALUE: none
        !          1509: /
        !          1510: / MODULES CALLED: wclear(), printw(), cleanup()
        !          1511: /
        !          1512: / GLOBAL INPUTS: *stdscr
        !          1513: /
        !          1514: / GLOBAL OUTPUTS: none
        !          1515: /
        !          1516: / DESCRIPTION:
        !          1517: /      When an illegal signal is caught, print a message, and cleanup.
        !          1518: /
        !          1519: /************************************************************************/
        !          1520: 
        !          1521: ill_sig(whichsig)
        !          1522: int whichsig;
        !          1523: {
        !          1524:     clear();
        !          1525:     if (!(whichsig == SIGINT || whichsig == SIGQUIT))
        !          1526:        printw("Error: caught signal # %d.\n", whichsig);
        !          1527:     cleanup(TRUE);
        !          1528:     /*NOTREACHED*/
        !          1529: }
        !          1530: /**/
        !          1531: /************************************************************************
        !          1532: /
        !          1533: / FUNCTION NAME: descrstatus()
        !          1534: /
        !          1535: / FUNCTION: return a string describing the player status
        !          1536: /
        !          1537: / AUTHOR: E. A. Estes, 3/3/86
        !          1538: /
        !          1539: / ARGUMENTS:
        !          1540: /      struct player playerp - pointer to player structure to describe
        !          1541: /
        !          1542: / RETURN VALUE: string describing player's status
        !          1543: /
        !          1544: / MODULES CALLED: none
        !          1545: /
        !          1546: / GLOBAL INPUTS: none
        !          1547: /
        !          1548: / GLOBAL OUTPUTS: none
        !          1549: /
        !          1550: / DESCRIPTION:
        !          1551: /      Return verbal description of player status.
        !          1552: /      If player status is S_PLAYING, check for low energy and blindness.
        !          1553: /
        !          1554: /************************************************************************/
        !          1555: 
        !          1556: char   *
        !          1557: descrstatus(playerp)
        !          1558: register struct player *playerp;
        !          1559: {
        !          1560:     switch (playerp->p_status)
        !          1561:        {
        !          1562:        case S_PLAYING:
        !          1563:            if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
        !          1564:                return("Low Energy");
        !          1565:            else if (playerp->p_blindness)
        !          1566:                return("Blind");
        !          1567:            else
        !          1568:                return("In game");
        !          1569: 
        !          1570:        case S_CLOAKED:
        !          1571:            return("Cloaked");
        !          1572: 
        !          1573:        case S_INBATTLE:
        !          1574:            return("In Battle");
        !          1575: 
        !          1576:        case S_MONSTER:
        !          1577:            return("Encounter");
        !          1578: 
        !          1579:        case S_TRADING:
        !          1580:            return("Trading");
        !          1581: 
        !          1582:        case S_OFF:
        !          1583:            return("Off");
        !          1584: 
        !          1585:        case S_HUNGUP:
        !          1586:            return("Hung up");
        !          1587: 
        !          1588:        default:
        !          1589:            return("");
        !          1590:        }
        !          1591: }
        !          1592: /**/
        !          1593: /************************************************************************
        !          1594: /
        !          1595: / FUNCTION NAME: drandom()
        !          1596: /
        !          1597: / FUNCTION: return a random floating point number from 0.0 < 1.0
        !          1598: /
        !          1599: / AUTHOR: E. A. Estes, 2/7/86
        !          1600: /
        !          1601: / ARGUMENTS: none
        !          1602: /
        !          1603: / RETURN VALUE: none
        !          1604: /
        !          1605: / MODULES CALLED: random()
        !          1606: /
        !          1607: / GLOBAL INPUTS: none
        !          1608: /
        !          1609: / GLOBAL OUTPUTS: none
        !          1610: /
        !          1611: / DESCRIPTION:
        !          1612: /      Convert random integer from library routine into a floating
        !          1613: /      point number, and divide by the largest possible random number.
        !          1614: /      We mask large integers with 32767 to handle sites that return
        !          1615: /      31 bit random integers.
        !          1616: /
        !          1617: /************************************************************************/
        !          1618: 
        !          1619: double
        !          1620: drandom()
        !          1621: {
        !          1622:     if (sizeof(int) != 2)
        !          1623:        /* use only low bits */
        !          1624:        return((double) (random() & 0x7fff) / 32768.0);
        !          1625:     else
        !          1626:        return((double) random() / 32768.0);
        !          1627: }
        !          1628: /**/
        !          1629: /************************************************************************
        !          1630: /
        !          1631: / FUNCTION NAME: collecttaxes()
        !          1632: /
        !          1633: / FUNCTION: collect taxes from current player
        !          1634: /
        !          1635: / AUTHOR: E. A. Estes, 2/7/86
        !          1636: /
        !          1637: / ARGUMENTS:
        !          1638: /      double gold - amount of gold to tax
        !          1639: /      double gems - amount of gems to tax
        !          1640: /
        !          1641: / RETURN VALUE: none
        !          1642: /
        !          1643: / MODULES CALLED: fread(), fseek(), fopen(), floor(), fwrite(), fclose()
        !          1644: /
        !          1645: / GLOBAL INPUTS: Player
        !          1646: /
        !          1647: / GLOBAL OUTPUTS: Player
        !          1648: /
        !          1649: / DESCRIPTION:
        !          1650: /      Pay taxes on gold and gems.  If the player does not have enough
        !          1651: /      gold to pay taxes on the added gems, convert some gems to gold.
        !          1652: /      Add taxes to tax data base; add remaining gold and gems to
        !          1653: /      player's cache.
        !          1654: /
        !          1655: /************************************************************************/
        !          1656: 
        !          1657: collecttaxes(gold, gems)
        !          1658: double gold;
        !          1659: double gems;
        !          1660: {
        !          1661: FILE   *fp;            /* to update Goldfile */
        !          1662: double dtemp;          /* for temporary calculations */
        !          1663: double taxes;          /* tax liability */
        !          1664: 
        !          1665:     /* add to cache */
        !          1666:     Player.p_gold += gold;
        !          1667:     Player.p_gems += gems;
        !          1668: 
        !          1669:     /* calculate tax liability */
        !          1670:     taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
        !          1671: 
        !          1672:     if (Player.p_gold < taxes)
        !          1673:        /* not enough gold to pay taxes, must convert some gems to gold */
        !          1674:        {
        !          1675:        dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to convert */
        !          1676: 
        !          1677:        if (Player.p_gems >= dtemp)
        !          1678:            /* player has enough to convert */
        !          1679:            {
        !          1680:            Player.p_gems -= dtemp;
        !          1681:            Player.p_gold += dtemp * N_GEMVALUE;
        !          1682:            }
        !          1683:        else
        !          1684:            /* take everything; this should never happen */
        !          1685:            {
        !          1686:            Player.p_gold += Player.p_gems * N_GEMVALUE;
        !          1687:            Player.p_gems = 0.0;
        !          1688:            taxes = Player.p_gold;
        !          1689:            }
        !          1690:        }
        !          1691: 
        !          1692:     Player.p_gold -= taxes;
        !          1693: 
        !          1694:     if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
        !          1695:        /* update taxes */
        !          1696:        {
        !          1697:        dtemp = 0.0;
        !          1698:        fread((char *) &dtemp, sizeof(double), 1, fp);
        !          1699:        dtemp += floor(taxes);
        !          1700:        fseek(fp, 0L, 0);
        !          1701:        fwrite((char *) &dtemp, sizeof(double), 1, fp);
        !          1702:        fclose(fp);
        !          1703:        }
        !          1704: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.