|
|
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: / Lastdead[], Gameprog[], Messfile[] ! 852: / ! 853: / GLOBAL OUTPUTS: Player ! 854: / ! 855: / DESCRIPTION: ! 856: / Kill off current player. ! 857: / Handle rings, and multiple lives. ! 858: / Print an appropriate message. ! 859: / Update scoreboard, lastdead, and let other players know about ! 860: / the demise of their comrade. ! 861: / ! 862: /************************************************************************/ ! 863: ! 864: death(how) ! 865: char *how; ! 866: { ! 867: FILE *fp; /* for updating various files */ ! 868: int ch; /* input */ ! 869: static char *deathmesg[] = ! 870: /* add more messages here, if desired */ ! 871: { ! 872: "You have been wounded beyond repair. ", ! 873: "You have been disemboweled. ", ! 874: "You've been mashed, mauled, and spit upon. (You're dead.)\n", ! 875: "You died! ", ! 876: "You're a complete failure -- you've died!!\n", ! 877: "You have been dealt a fatal blow! " ! 878: }; ! 879: ! 880: clear(); ! 881: ! 882: if (strcmp(how, "Stupidity") != 0) ! 883: { ! 884: if (Player.p_level > 9999.0) ! 885: /* old age */ ! 886: addstr("Characters must be retired upon reaching level 10000. Sorry."); ! 887: else if (Player.p_lives > 0) ! 888: /* extra lives */ ! 889: { ! 890: addstr("You should be more cautious. You've been killed.\n"); ! 891: printw("You only have %d more chance(s).\n", --Player.p_lives); ! 892: more(3); ! 893: Player.p_energy = Player.p_maxenergy; ! 894: return; ! 895: } ! 896: else if (Player.p_specialtype == SC_VALAR) ! 897: { ! 898: addstr("You had your chances, but Valar aren't totally\n"); ! 899: addstr("immortal. You are now left to wither and die . . .\n"); ! 900: more(3); ! 901: Player.p_brains = Player.p_level / 25.0; ! 902: Player.p_energy = Player.p_maxenergy /= 5.0; ! 903: Player.p_quksilver = Player.p_sword = 0.0; ! 904: Player.p_specialtype = SC_COUNCIL; ! 905: return; ! 906: } ! 907: else if (Player.p_ring.ring_inuse && ! 908: (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG)) ! 909: /* good ring in use - saved from death */ ! 910: { ! 911: mvaddstr(4, 0, "Your ring saved you from death!\n"); ! 912: refresh(); ! 913: Player.p_ring.ring_type = R_NONE; ! 914: Player.p_energy = Player.p_maxenergy / 12.0 + 1.0; ! 915: if (Player.p_crowns > 0) ! 916: --Player.p_crowns; ! 917: return; ! 918: } ! 919: else if (Player.p_ring.ring_type == R_BAD ! 920: || Player.p_ring.ring_type == R_SPOILED) ! 921: /* bad ring in possession; name idiot after player */ ! 922: { ! 923: mvaddstr(4, 0, ! 924: "Your ring has taken control of you and turned you into a monster!\n"); ! 925: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0); ! 926: fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp); ! 927: strcpy(Curmonster.m_name, Player.p_name); ! 928: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0); ! 929: fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp); ! 930: fflush(Monstfp); ! 931: } ! 932: } ! 933: ! 934: enterscore(); /* update score board */ ! 935: ! 936: /* put info in last dead file */ ! 937: fp = fopen(Lastdead, "w"); ! 938: fprintf(fp,"%s (%s, run by %s, level %.0f, killed by %s)", ! 939: Player.p_name, descrtype(&Player, TRUE), ! 940: Player.p_login, Player.p_level, how); ! 941: fclose(fp); ! 942: ! 943: /* let other players know */ ! 944: fp = fopen(Messfile, "w"); ! 945: fprintf(fp, "%s was killed by %s.", Player.p_name, how); ! 946: fclose(fp); ! 947: ! 948: freerecord(&Player, Fileloc); ! 949: ! 950: clear(); ! 951: move(10, 0); ! 952: addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]); ! 953: addstr("Care to give it another try ? "); ! 954: ch = getanswer("NY", FALSE); ! 955: ! 956: if (ch == 'Y') ! 957: { ! 958: cleanup(FALSE); ! 959: execl(Gameprog, "phantasia", "-s", (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, Goldfile[] ! 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(Goldfile, "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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.