(linenum→info "unix/slp.c:2238")

bsd-games/2.17/phantasia/misc.c

    1: /*      $NetBSD: misc.c,v 1.14 2005/02/15 12:58:21 jsm Exp $ */
    2: 
    3: /*
    4:  * misc.c  Phantasia miscellaneous support routines
    5:  */
    6: 
    7: #include "include.h"
    8: #undef bool
    9: #include <curses.h>
   10: 
   11: 
   12: void
   13: movelevel()
   14: {
   15:         const struct charstats *statptr; /* for pointing into Stattable */
   16:         double  new;           /* new level */
   17:         double  inc;           /* increment between new and old levels */
   18: 
   19:         Changed = TRUE;
   20: 
   21:         if (Player.p_type == C_EXPER)
   22:                 /* roll a type to use for increment */
   23:                 statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
   24:         else
   25:                 statptr = Statptr;
   26: 
   27:         new = explevel(Player.p_experience);
   28:         inc = new - Player.p_level;
   29:         Player.p_level = new;
   30: 
   31:         /* add increments to statistics */
   32:         Player.p_strength += statptr->c_strength.increase * inc;
   33:         Player.p_mana += statptr->c_mana.increase * inc;
   34:         Player.p_brains += statptr->c_brains.increase * inc;
   35:         Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
   36:         Player.p_maxenergy += statptr->c_energy.increase * inc;
   37: 
   38:         /* rest to maximum upon reaching new level */
   39:         Player.p_energy = Player.p_maxenergy + Player.p_shield;
   40: 
   41:         if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
   42:                 /* no longer able to be king -- turn crowns into cash */
   43:         {
   44:                 Player.p_gold += ((double) Player.p_crowns) * 5000.0;
   45:                 Player.p_crowns = 0;
   46:         }
   47:         if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
   48:                 /* make a member of the council */
   49:         {
   50:                 mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
   51:                 addstr("Good Luck on your search for the Holy Grail.\n");
   52: 
   53:                 Player.p_specialtype = SC_COUNCIL;
   54: 
   55:                 /* no rings for council and above */
   56:                 Player.p_ring.ring_type = R_NONE;
   57:                 Player.p_ring.ring_duration = 0;
   58: 
   59:                 Player.p_lives = 3;   /* three extra lives */
   60:         }
   61:         if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
   62:                 death("Old age");
   63: }
   64: 
   65: const char   *
   66: descrlocation(playerp, shortflag)
   67:         struct player *playerp;
   68:         phbool  shortflag;
   69: {
   70:         double  circle;                /* corresponding circle for coordinates */
   71:         int     quadrant;      /* quandrant of grid */
   72:         const char   *label;   /* pointer to place name */
   73:         static const char *const nametable[4][4] =     /* names of places */
   74:         {
   75:                 {"Anorien", "Ithilien", "Rohan", "Lorien"},
   76:                 {"Gondor", "Mordor", "Dunland", "Rovanion"},
   77:                 {"South Gondor", "Khand", "Eriador", "The Iron Hills"},
   78:                 {"Far Harad", "Near Harad", "The Northern Waste", "Rhun"}
   79:         };
   80: 
   81:         if (playerp->p_specialtype == SC_VALAR)
   82:                 return (" is in Valhala");
   83:         else
   84:                 if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0) {
   85:                         if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
   86:                                 label = "The Point of No Return";
   87:                         else
   88:                                 label = "The Ashen Mountains";
   89:                 } else
   90:                         if (circle >= 55)
   91:                                 label = "Morannon";
   92:                         else
   93:                                 if (circle >= 35)
   94:                                         label = "Kennaquahair";
   95:                                 else
   96:                                         if (circle >= 20)
   97:                                                 label = "The Dead Marshes";
   98:                                         else
   99:                                                 if (circle >= 9)
  100:                                                         label = "The Outer Waste";
  101:                                                 else
  102:                                                         if (circle >= 5)
  103:                                                                 label = "The Moors Adventurous";
  104:                                                         else {
  105:                                                                 if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
  106:                                                                         label = "The Lord's Chamber";
  107:                                                                 else {
  108:                                                                         /* this
  109:                                                                          * 
  110:                                                                          * expr
  111:                                                                          * essi
  112:                                                                          * on
  113:                                                                          * is
  114:                                                                          * spli
  115:                                                                          * t
  116:                                                                          * to
  117:                                                                          * prev
  118:                                                                          * ent
  119:                                                                          * comp
  120:                                                                          * iler
  121:                                                                          * 
  122:                                                                          * loop
  123:                                                                          * 
  124:                                                                          * with
  125:                                                                          * 
  126:                                                                          * some
  127:                                                                          * 
  128:                                                                          * comp
  129:                                                                          * iler
  130:                                                                          * s */
  131:                                                                         quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
  132:                                                                         quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
  133:                                                                         label = nametable[((int) circle) - 1][quadrant];
  134:                                                                 }
  135:                                                         }
  136: 
  137:         if (shortflag)
  138:                 sprintf(Databuf, "%.29s", label);
  139:         else
  140:                 sprintf(Databuf, " is in %s  (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
  141: 
  142:         return (Databuf);
  143: }
  144: 
  145: void
  146: tradingpost()
  147: {
  148:         double  numitems;      /* number of items to purchase */
  149:         double  cost;          /* cost of purchase */
  150:         double  blessingcost;  /* cost of blessing */
  151:         int     ch;            /* input */
  152:         int     size;          /* size of the trading post */
  153:         int     loop;          /* loop counter */
  154:         int     cheat = 0;     /* number of times player has tried to cheat */
  155:         bool    dishonest = FALSE;     /* set when merchant is dishonest */
  156: 
  157:         Player.p_status = S_TRADING;
  158:         writerecord(&Player, Fileloc);
  159: 
  160:         clear();
  161:         addstr("You are at a trading post. All purchases must be made with gold.");
  162: 
  163:         size = sqrt(fabs(Player.p_x / 100)) + 1;
  164:         size = MIN(7, size);
  165: 
  166:         /* set up cost of blessing */
  167:         blessingcost = 1000.0 * (Player.p_level + 5.0);
  168: 
  169:         /* print Menu */
  170:         move(7, 0);
  171:         for (loop = 0; loop < size; ++loop)
  172:                 /* print Menu */
  173:         {
  174:                 if (loop == 6)
  175:                         cost = blessingcost;
  176:                 else
  177:                         cost = Menu[loop].cost;
  178:                 printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
  179:         }
  180: 
  181:         mvprintw(5, 0, "L:Leave  P:Purchase  S:Sell Gems ? ");
  182: 
  183:         for (;;) {
  184:                 adjuststats();        /* truncate any bad values */
  185: 
  186:                 /* print some important statistics */
  187:                 mvprintw(1, 0, "Gold:   %9.0f  Gems:  %9.0f  Level:   %6.0f  Charms: %6d\n",
  188:                     Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
  189:                 printw("Shield: %9.0f  Sword: %9.0f  Quicksilver:%3.0f  Blessed: %s\n",
  190:                     Player.p_shield, Player.p_sword, Player.p_quksilver,
  191:                     (Player.p_blessing ? " True" : "False"));
  192:                 printw("Brains: %9.0f  Mana:  %9.0f", Player.p_brains, Player.p_mana);
  193: 
  194:                 move(5, 36);
  195:                 ch = getanswer("LPS", FALSE);
  196:                 move(15, 0);
  197:                 clrtobot();
  198:                 switch (ch) {
  199:                 case 'L':     /* leave */
  200:                 case '\n':
  201:                         altercoordinates(0.0, 0.0, A_NEAR);
  202:                         return;
  203: 
  204:                 case 'P':     /* make purchase */
  205:                         mvaddstr(15, 0, "What what would you like to buy ? ");
  206:                         ch = getanswer(" 1234567", FALSE);
  207:                         move(15, 0);
  208:                         clrtoeol();
  209: 
  210:                         if (ch - '0' > size)
  211:                                 addstr("Sorry, this merchant doesn't have that.");
  212:                         else
  213:                                 switch (ch) {
  214:                                 case '1':
  215:                                         printw("Mana is one per %.0f gold piece.  How many do you want (%.0f max) ? ",
  216:                                             Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
  217:                                         cost = (numitems = floor(infloat())) * Menu[0].cost;
  218: 
  219:                                         if (cost > Player.p_gold || numitems < 0)
  220:                                                 ++cheat;
  221:                                         else {
  222:                                                 cheat = 0;
  223:                                                 Player.p_gold -= cost;
  224:                                                 if (drandom() < 0.02)
  225:                                                         dishonest = TRUE;
  226:                                                 else
  227:                                                         Player.p_mana += numitems;
  228:                                         }
  229:                                         break;
  230: 
  231:                                 case '2':
  232:                                         printw("Shields are %.0f per +1.  How many do you want (%.0f max) ? ",
  233:                                             Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
  234:                                         cost = (numitems = floor(infloat())) * Menu[1].cost;
  235: 
  236:                                         if (numitems == 0.0)
  237:                                                 break;
  238:                                         else
  239:                                                 if (cost > Player.p_gold || numitems < 0)
  240:                                                         ++cheat;
  241:                                                 else
  242:                                                         if (numitems < Player.p_shield)
  243:                                                                 NOBETTER();
  244:                                                         else {
  245:                                                                 cheat = 0;
  246:                                                                 Player.p_gold -= cost;
  247:                                                                 if (drandom() < 0.02)
  248:                                                                         dishonest = TRUE;
  249:                                                                 else
  250:                                                                         Player.p_shield = numitems;
  251:                                                         }
  252:                                         break;
  253: 
  254:                                 case '3':
  255:                                         printw("A book costs %.0f gp.  How many do you want (%.0f max) ? ",
  256:                                             Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
  257:                                         cost = (numitems = floor(infloat())) * Menu[2].cost;
  258: 
  259:                                         if (cost > Player.p_gold || numitems < 0)
  260:                                                 ++cheat;
  261:                                         else {
  262:                                                 cheat = 0;
  263:                                                 Player.p_gold -= cost;
  264:                                                 if (drandom() < 0.02)
  265:                                                         dishonest = TRUE;
  266:                                                 else
  267:                                                         if (drandom() * numitems > Player.p_level / 10.0
  268:                                                             && numitems != 1) {
  269:                                                                 printw("\nYou blew your mind!\n");
  270:                                                                 Player.p_brains /= 5;
  271:                                                         } else {
  272:                                                                 Player.p_brains += floor(numitems) * ROLL(20, 8);
  273:                                                         }
  274:                                         }
  275:                                         break;
  276: 
  277:                                 case '4':
  278:                                         printw("Swords are %.0f gp per +1.  How many + do you want (%.0f max) ? ",
  279:                                             Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
  280:                                         cost = (numitems = floor(infloat())) * Menu[3].cost;
  281: 
  282:                                         if (numitems == 0.0)
  283:                                                 break;
  284:                                         else
  285:                                                 if (cost > Player.p_gold || numitems < 0)
  286:                                                         ++cheat;
  287:                                                 else
  288:                                                         if (numitems < Player.p_sword)
  289:                                                                 NOBETTER();
  290:                                                         else {
  291:                                                                 cheat = 0;
  292:                                                                 Player.p_gold -= cost;
  293:                                                                 if (drandom() < 0.02)
  294:                                                                         dishonest = TRUE;
  295:                                                                 else
  296:                                                                         Player.p_sword = numitems;
  297:                                                         }
  298:                                         break;
  299: 
  300:                                 case '5':
  301:                                         printw("A charm costs %.0f gp.  How many do you want (%.0f max) ? ",
  302:                                             Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
  303:                                         cost = (numitems = floor(infloat())) * Menu[4].cost;
  304: 
  305:                                         if (cost > Player.p_gold || numitems < 0)
  306:                                                 ++cheat;
  307:                                         else {
  308:                                                 cheat = 0;
  309:                                                 Player.p_gold -= cost;
  310:                                                 if (drandom() < 0.02)
  311:                                                         dishonest = TRUE;
  312:                                                 else
  313:                                                         Player.p_charms += numitems;
  314:                                         }
  315:                                         break;
  316: 
  317:                                 case '6':
  318:                                         printw("Quicksilver is %.0f gp per +1.  How many + do you want (%.0f max) ? ",
  319:                                             Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
  320:                                         cost = (numitems = floor(infloat())) * Menu[5].cost;
  321: 
  322:                                         if (numitems == 0.0)
  323:                                                 break;
  324:                                         else
  325:                                                 if (cost > Player.p_gold || numitems < 0)
  326:                                                         ++cheat;
  327:                                                 else
  328:                                                         if (numitems < Player.p_quksilver)
  329:                                                                 NOBETTER();
  330:                                                         else {
  331:                                                                 cheat = 0;
  332:                                                                 Player.p_gold -= cost;
  333:                                                                 if (drandom() < 0.02)
  334:                                                                         dishonest = TRUE;
  335:                                                                 else
  336:                                                                         Player.p_quksilver = numitems;
  337:                                                         }
  338:                                         break;
  339: 
  340:                                 case '7':
  341:                                         if (Player.p_blessing) {
  342:                                                 addstr("You already have a blessing.");
  343:                                                 break;
  344:                                         }
  345:                                         printw("A blessing requires a %.0f gp donation.  Still want one ? ", blessingcost);
  346:                                         ch = getanswer("NY", FALSE);
  347: 
  348:                                         if (ch == 'Y') {
  349:                                                 if (Player.p_gold < blessingcost)
  350:                                                         ++cheat;
  351:                                                 else {
  352:                                                         cheat = 0;
  353:                                                         Player.p_gold -= blessingcost;
  354:                                                         if (drandom() < 0.02)
  355:                                                                 dishonest = TRUE;
  356:                                                         else
  357:                                                                 Player.p_blessing = TRUE;
  358:                                                 }
  359:                                         }
  360:                                         break;
  361:                                 }
  362:                         break;
  363: 
  364:                 case 'S':     /* sell gems */
  365:                         mvprintw(15, 0, "A gem is worth %.0f gp.  How many do you want to sell (%.0f max) ? ",
  366:                             (double) N_GEMVALUE, Player.p_gems);
  367:                         numitems = floor(infloat());
  368: 
  369:                         if (numitems > Player.p_gems || numitems < 0)
  370:                                 ++cheat;
  371:                         else {
  372:                                 cheat = 0;
  373:                                 Player.p_gems -= numitems;
  374:                                 Player.p_gold += numitems * N_GEMVALUE;
  375:                         }
  376:                 }
  377: 
  378:                 if (cheat == 1)
  379:                         mvaddstr(17, 0, "Come on, merchants aren't stupid.  Stop cheating.\n");
  380:                 else
  381:                         if (cheat == 2) {
  382:                                 mvaddstr(17, 0, "You had your chance.  This merchant happens to be\n");
  383:                                 printw("a %.0f level magic user, and you made %s mad!\n",
  384:                                     ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her");
  385:                                 altercoordinates(0.0, 0.0, A_FAR);
  386:                                 Player.p_energy /= 2.0;
  387:                                 ++Player.p_sin;
  388:                                 more(23);
  389:                                 return;
  390:                         } else
  391:                                 if (dishonest) {
  392:                                         mvaddstr(17, 0, "The merchant stole your money!");
  393:                                         refresh();
  394:                                         altercoordinates(Player.p_x - Player.p_x / 10.0,
  395:                                             Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
  396:                                         sleep(2);
  397:                                         return;
  398:                                 }
  399:         }
  400: }
  401: 
  402: void
  403: displaystats()
  404: {
  405:         mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
  406:         mvprintw(1, 0, "Level :%7.0f   Energy  :%9.0f(%9.0f)  Mana :%9.0f  Users:%3d\n",
  407:             Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
  408:             Player.p_mana, Users);
  409:         mvprintw(2, 0, "Quick :%3.0f(%3.0f)  Strength:%9.0f(%9.0f)  Gold :%9.0f  %s\n",
  410:             Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
  411:             Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
  412: }
  413: 
  414: void
  415: allstatslist()
  416: {
  417:         static const char *const flags[] = /* to print value of some bools */
  418:         {
  419:                 "False",
  420:                 " True"
  421:         };
  422: 
  423:         mvprintw(8, 0, "Type: %s\n", descrtype(&Player, FALSE));
  424: 
  425:         mvprintw(10, 0, "Experience: %9.0f", Player.p_experience);
  426:         mvprintw(11, 0, "Brains    : %9.0f", Player.p_brains);
  427:         mvprintw(12, 0, "Magic Lvl : %9.0f", Player.p_magiclvl);
  428:         mvprintw(13, 0, "Sin       : %9.5f", Player.p_sin);
  429:         mvprintw(14, 0, "Poison    : %9.5f", Player.p_poison);
  430:         mvprintw(15, 0, "Gems      : %9.0f", Player.p_gems);
  431:         mvprintw(16, 0, "Age       : %9ld", Player.p_age);
  432:         mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
  433:         mvprintw(11, 40, "Amulets   : %9d", Player.p_amulets);
  434:         mvprintw(12, 40, "Charms    : %9d", Player.p_charms);
  435:         mvprintw(13, 40, "Crowns    : %9d", Player.p_crowns);
  436:         mvprintw(14, 40, "Shield    : %9.0f", Player.p_shield);
  437:         mvprintw(15, 40, "Sword     : %9.0f", Player.p_sword);
  438:         mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
  439: 
  440:         mvprintw(18, 0, "Blessing: %s   Ring: %s   Virgin: %s   Palantir: %s",
  441:             flags[(int)Player.p_blessing],
  442:             flags[Player.p_ring.ring_type != R_NONE],
  443:             flags[(int)Player.p_virgin],
  444:             flags[(int)Player.p_palantir]);
  445: }
  446: 
  447: const char   *
  448: descrtype(playerp, shortflag)
  449:         struct player *playerp;
  450:         phbool  shortflag;
  451: {
  452:         int     type;          /* for caluculating result subscript */
  453:         static const char *const results[] =/* description table */
  454:         {
  455:                 " Magic User", " MU",
  456:                 " Fighter", " F ",
  457:                 " Elf", " E ",
  458:                 " Dwarf", " D ",
  459:                 " Halfling", " H ",
  460:                 " Experimento", " EX",
  461:                 " Super", " S ",
  462:                 " King", " K ",
  463:                 " Council of Wise", " CW",
  464:                 " Ex-Valar", " EV",
  465:                 " Valar", " V ",
  466:                 " ? ", " ? "
  467:         };
  468: 
  469:         type = playerp->p_type;
  470: 
  471:         switch (playerp->p_specialtype) {
  472:         case SC_NONE:
  473:                 type = playerp->p_type;
  474:                 break;
  475: 
  476:         case SC_KING:
  477:                 type = 7;
  478:                 break;
  479: 
  480:         case SC_COUNCIL:
  481:                 type = 8;
  482:                 break;
  483: 
  484:         case SC_EXVALAR:
  485:                 type = 9;
  486:                 break;
  487: 
  488:         case SC_VALAR:
  489:                 type = 10;
  490:                 break;
  491:         }
  492: 
  493:         type *= 2;             /* calculate offset */
  494: 
  495:         if (type > 20)
  496:                 /* error */
  497:                 type = 22;
  498: 
  499:         if (shortflag)
  500:                 /* use short descriptions */
  501:                 ++type;
  502: 
  503:         if (playerp->p_crowns > 0) {
  504:                 strcpy(Databuf, results[type]);
  505:                 Databuf[0] = '*';
  506:                 return (Databuf);
  507:         } else
  508:                 return (results[type]);
  509: }
  510: 
  511: long
  512: findname(name, playerp)
  513:         const char   *name;
  514:         struct player *p