Annotation of src/games/phantasia/misc.c, Revision 1.16
1.16 ! dholland 1: /* $NetBSD: misc.c,v 1.15 2008/01/28 06:20:15 dholland Exp $ */
1.2 cgd 2:
1.1 jtc 3: /*
4: * misc.c Phantasia miscellaneous support routines
5: */
6:
7: #include "include.h"
1.12 he 8: #undef bool
1.11 ross 9: #include <curses.h>
1.1 jtc 10:
11:
1.3 lukem 12: void
1.16 ! dholland 13: movelevel(void)
1.1 jtc 14: {
1.5 jsm 15: const struct charstats *statptr; /* for pointing into Stattable */
1.3 lukem 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;
1.1 jtc 26:
1.3 lukem 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;
1.1 jtc 37:
1.3 lukem 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 */
1.1 jtc 43: {
1.3 lukem 44: Player.p_gold += ((double) Player.p_crowns) * 5000.0;
45: Player.p_crowns = 0;
1.1 jtc 46: }
1.3 lukem 47: if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
48: /* make a member of the council */
1.1 jtc 49: {
1.3 lukem 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");
1.1 jtc 52:
1.3 lukem 53: Player.p_specialtype = SC_COUNCIL;
1.1 jtc 54:
1.3 lukem 55: /* no rings for council and above */
56: Player.p_ring.ring_type = R_NONE;
57: Player.p_ring.ring_duration = 0;
1.1 jtc 58:
1.3 lukem 59: Player.p_lives = 3; /* three extra lives */
1.1 jtc 60: }
1.3 lukem 61: if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
62: death("Old age");
1.1 jtc 63: }
64:
1.5 jsm 65: const char *
1.16 ! dholland 66: descrlocation(struct player *playerp, phbool shortflag)
1.1 jtc 67: {
1.3 lukem 68: double circle; /* corresponding circle for coordinates */
69: int quadrant; /* quandrant of grid */
1.5 jsm 70: const char *label; /* pointer to place name */
71: static const char *const nametable[4][4] = /* names of places */
1.3 lukem 72: {
73: {"Anorien", "Ithilien", "Rohan", "Lorien"},
74: {"Gondor", "Mordor", "Dunland", "Rovanion"},
75: {"South Gondor", "Khand", "Eriador", "The Iron Hills"},
76: {"Far Harad", "Near Harad", "The Northern Waste", "Rhun"}
1.1 jtc 77: };
78:
1.3 lukem 79: if (playerp->p_specialtype == SC_VALAR)
80: return (" is in Valhala");
1.1 jtc 81: else
1.3 lukem 82: if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0) {
83: if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
84: label = "The Point of No Return";
85: else
86: label = "The Ashen Mountains";
87: } else
88: if (circle >= 55)
89: label = "Morannon";
90: else
91: if (circle >= 35)
92: label = "Kennaquahair";
93: else
94: if (circle >= 20)
95: label = "The Dead Marshes";
96: else
97: if (circle >= 9)
98: label = "The Outer Waste";
99: else
100: if (circle >= 5)
101: label = "The Moors Adventurous";
102: else {
103: if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
104: label = "The Lord's Chamber";
105: else {
106: /* this
107: *
108: * expr
109: * essi
110: * on
111: * is
112: * spli
113: * t
114: * to
115: * prev
116: * ent
117: * comp
118: * iler
119: *
120: * loop
121: *
122: * with
123: *
124: * some
125: *
126: * comp
127: * iler
128: * s */
129: quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
130: quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
131: label = nametable[((int) circle) - 1][quadrant];
132: }
133: }
134:
135: if (shortflag)
136: sprintf(Databuf, "%.29s", label);
1.1 jtc 137: else
1.3 lukem 138: sprintf(Databuf, " is in %s (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
1.1 jtc 139:
1.3 lukem 140: return (Databuf);
141: }
1.1 jtc 142:
1.3 lukem 143: void
1.16 ! dholland 144: tradingpost(void)
1.1 jtc 145: {
1.3 lukem 146: double numitems; /* number of items to purchase */
147: double cost; /* cost of purchase */
148: double blessingcost; /* cost of blessing */
149: int ch; /* input */
150: int size; /* size of the trading post */
151: int loop; /* loop counter */
152: int cheat = 0; /* number of times player has tried to cheat */
153: bool dishonest = FALSE; /* set when merchant is dishonest */
1.1 jtc 154:
1.3 lukem 155: Player.p_status = S_TRADING;
156: writerecord(&Player, Fileloc);
1.1 jtc 157:
1.3 lukem 158: clear();
159: addstr("You are at a trading post. All purchases must be made with gold.");
160:
161: size = sqrt(fabs(Player.p_x / 100)) + 1;
162: size = MIN(7, size);
1.1 jtc 163:
1.3 lukem 164: /* set up cost of blessing */
165: blessingcost = 1000.0 * (Player.p_level + 5.0);
1.1 jtc 166:
1.3 lukem 167: /* print Menu */
168: move(7, 0);
169: for (loop = 0; loop < size; ++loop)
170: /* print Menu */
171: {
172: if (loop == 6)
173: cost = blessingcost;
1.1 jtc 174: else
1.3 lukem 175: cost = Menu[loop].cost;
176: printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
177: }
1.1 jtc 178:
1.3 lukem 179: mvprintw(5, 0, "L:Leave P:Purchase S:Sell Gems ? ");
1.1 jtc 180:
1.3 lukem 181: for (;;) {
182: adjuststats(); /* truncate any bad values */
1.1 jtc 183:
1.3 lukem 184: /* print some important statistics */
185: mvprintw(1, 0, "Gold: %9.0f Gems: %9.0f Level: %6.0f Charms: %6d\n",
186: Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
187: printw("Shield: %9.0f Sword: %9.0f Quicksilver:%3.0f Blessed: %s\n",
188: Player.p_shield, Player.p_sword, Player.p_quksilver,
189: (Player.p_blessing ? " True" : "False"));
190: printw("Brains: %9.0f Mana: %9.0f", Player.p_brains, Player.p_mana);
1.1 jtc 191:
1.3 lukem 192: move(5, 36);
193: ch = getanswer("LPS", FALSE);
194: move(15, 0);
195: clrtobot();
196: switch (ch) {
197: case 'L': /* leave */
198: case '\n':
199: altercoordinates(0.0, 0.0, A_NEAR);
200: return;
201:
202: case 'P': /* make purchase */
203: mvaddstr(15, 0, "What what would you like to buy ? ");
204: ch = getanswer(" 1234567", FALSE);
205: move(15, 0);
206: clrtoeol();
207:
208: if (ch - '0' > size)
209: addstr("Sorry, this merchant doesn't have that.");
210: else
211: switch (ch) {
212: case '1':
213: printw("Mana is one per %.0f gold piece. How many do you want (%.0f max) ? ",
214: Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
215: cost = (numitems = floor(infloat())) * Menu[0].cost;
216:
217: if (cost > Player.p_gold || numitems < 0)
218: ++cheat;
219: else {
220: cheat = 0;
221: Player.p_gold -= cost;
222: if (drandom() < 0.02)
223: dishonest = TRUE;
224: else
225: Player.p_mana += numitems;
226: }
227: break;
228:
229: case '2':
230: printw("Shields are %.0f per +1. How many do you want (%.0f max) ? ",
231: Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
232: cost = (numitems = floor(infloat())) * Menu[1].cost;
233:
234: if (numitems == 0.0)
235: break;
236: else
237: if (cost > Player.p_gold || numitems < 0)
238: ++cheat;
239: else
240: if (numitems < Player.p_shield)
241: NOBETTER();
242: else {
243: cheat = 0;
244: Player.p_gold -= cost;
245: if (drandom() < 0.02)
246: dishonest = TRUE;
247: else
248: Player.p_shield = numitems;
249: }
250: break;
251:
252: case '3':
253: printw("A book costs %.0f gp. How many do you want (%.0f max) ? ",
254: Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
255: cost = (numitems = floor(infloat())) * Menu[2].cost;
256:
257: if (cost > Player.p_gold || numitems < 0)
258: ++cheat;
259: else {
260: cheat = 0;
261: Player.p_gold -= cost;
262: if (drandom() < 0.02)
263: dishonest = TRUE;
264: else
265: if (drandom() * numitems > Player.p_level / 10.0
266: && numitems != 1) {
267: printw("\nYou blew your mind!\n");
268: Player.p_brains /= 5;
269: } else {
270: Player.p_brains += floor(numitems) * ROLL(20, 8);
271: }
272: }
273: break;
274:
275: case '4':
276: printw("Swords are %.0f gp per +1. How many + do you want (%.0f max) ? ",
277: Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
278: cost = (numitems = floor(infloat())) * Menu[3].cost;
279:
280: if (numitems == 0.0)
281: break;
282: else
283: if (cost > Player.p_gold || numitems < 0)
284: ++cheat;
285: else
286: if (numitems < Player.p_sword)
287: NOBETTER();
288: else {
289: cheat = 0;
290: Player.p_gold -= cost;
291: if (drandom() < 0.02)
292: dishonest = TRUE;
293: else
294: Player.p_sword = numitems;
295: }
296: break;
297:
298: case '5':
299: printw("A charm costs %.0f gp. How many do you want (%.0f max) ? ",
300: Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
301: cost = (numitems = floor(infloat())) * Menu[4].cost;
302:
303: if (cost > Player.p_gold || numitems < 0)
304: ++cheat;
305: else {
306: cheat = 0;
307: Player.p_gold -= cost;
308: if (drandom() < 0.02)
309: dishonest = TRUE;
310: else
311: Player.p_charms += numitems;
312: }
313: break;
314:
315: case '6':
316: printw("Quicksilver is %.0f gp per +1. How many + do you want (%.0f max) ? ",
317: Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
318: cost = (numitems = floor(infloat())) * Menu[5].cost;
319:
320: if (numitems == 0.0)
321: break;
322: else
323: if (cost > Player.p_gold || numitems < 0)
324: ++cheat;
325: else
326: if (numitems < Player.p_quksilver)
327: NOBETTER();
328: else {
329: cheat = 0;
330: Player.p_gold -= cost;
331: if (drandom() < 0.02)
332: dishonest = TRUE;
333: else
334: Player.p_quksilver = numitems;
335: }
336: break;
337:
338: case '7':
339: if (Player.p_blessing) {
340: addstr("You already have a blessing.");
341: break;
342: }
343: printw("A blessing requires a %.0f gp donation. Still want one ? ", blessingcost);
344: ch = getanswer("NY", FALSE);
345:
1.4 veego 346: if (ch == 'Y') {
1.3 lukem 347: if (Player.p_gold < blessingcost)
348: ++cheat;
349: else {
350: cheat = 0;
351: Player.p_gold -= blessingcost;
352: if (drandom() < 0.02)
353: dishonest = TRUE;
354: else
355: Player.p_blessing = TRUE;
356: }
1.4 veego 357: }
1.3 lukem 358: break;
1.1 jtc 359: }
1.3 lukem 360: break;
1.1 jtc 361:
1.3 lukem 362: case 'S': /* sell gems */
363: mvprintw(15, 0, "A gem is worth %.0f gp. How many do you want to sell (%.0f max) ? ",
364: (double) N_GEMVALUE, Player.p_gems);
365: numitems = floor(infloat());
1.1 jtc 366:
1.3 lukem 367: if (numitems > Player.p_gems || numitems < 0)
1.1 jtc 368: ++cheat;
1.3 lukem 369: else {
1.1 jtc 370: cheat = 0;
1.3 lukem 371: Player.p_gems -= numitems;
372: Player.p_gold += numitems * N_GEMVALUE;
1.1 jtc 373: }
1.3 lukem 374: }
1.1 jtc 375:
1.3 lukem 376: if (cheat == 1)
377: mvaddstr(17, 0, "Come on, merchants aren't stupid. Stop cheating.\n");
1.1 jtc 378: else
1.3 lukem 379: if (cheat == 2) {
380: mvaddstr(17, 0, "You had your chance. This merchant happens to be\n");
381: printw("a %.0f level magic user, and you made %s mad!\n",
382: ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her");
383: altercoordinates(0.0, 0.0, A_FAR);
384: Player.p_energy /= 2.0;
385: ++Player.p_sin;
386: more(23);
387: return;
388: } else
389: if (dishonest) {
390: mvaddstr(17, 0, "The merchant stole your money!");
391: refresh();
392: altercoordinates(Player.p_x - Player.p_x / 10.0,
393: Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
394: sleep(2);
395: return;
396: }
1.1 jtc 397: }
398: }
399:
1.3 lukem 400: void
1.16 ! dholland 401: displaystats(void)
1.1 jtc 402: {
1.3 lukem 403: mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
404: mvprintw(1, 0, "Level :%7.0f Energy :%9.0f(%9.0f) Mana :%9.0f Users:%3d\n",
405: Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
406: Player.p_mana, Users);
407: mvprintw(2, 0, "Quick :%3.0f(%3.0f) Strength:%9.0f(%9.0f) Gold :%9.0f %s\n",
408: Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
409: Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
410: }
1.1 jtc 411:
1.3 lukem 412: void
1.16 ! dholland 413: allstatslist(void)
1.1 jtc 414: {
1.5 jsm 415: static const char *const flags[] = /* to print value of some bools */
1.3 lukem 416: {
417: "False",
418: " True"
419: };
420:
421: mvprintw(8, 0, "Type: %s\n", descrtype(&Player, FALSE));
1.1 jtc 422:
1.3 lukem 423: mvprintw(10, 0, "Experience: %9.0f", Player.p_experience);
424: mvprintw(11, 0, "Brains : %9.0f", Player.p_brains);
425: mvprintw(12, 0, "Magic Lvl : %9.0f", Player.p_magiclvl);
426: mvprintw(13, 0, "Sin : %9.5f", Player.p_sin);
427: mvprintw(14, 0, "Poison : %9.5f", Player.p_poison);
428: mvprintw(15, 0, "Gems : %9.0f", Player.p_gems);
1.7 jdc 429: mvprintw(16, 0, "Age : %9ld", Player.p_age);
1.3 lukem 430: mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
431: mvprintw(11, 40, "Amulets : %9d", Player.p_amulets);
432: mvprintw(12, 40, "Charms : %9d", Player.p_charms);
433: mvprintw(13, 40, "Crowns : %9d", Player.p_crowns);
434: mvprintw(14, 40, "Shield : %9.0f", Player.p_shield);
435: mvprintw(15, 40, "Sword : %9.0f", Player.p_sword);
436: mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
437:
438: mvprintw(18, 0, "Blessing: %s Ring: %s Virgin: %s Palantir: %s",
439: flags[(int)Player.p_blessing],
440: flags[Player.p_ring.ring_type != R_NONE],
441: flags[(int)Player.p_virgin],
442: flags[(int)Player.p_palantir]);
443: }
444:
1.5 jsm 445: const char *
1.16 ! dholland 446: descrtype(struct player *playerp, phbool shortflag)
1.1 jtc 447: {
1.3 lukem 448: int type; /* for caluculating result subscript */
1.5 jsm 449: static const char *const results[] =/* description table */
1.3 lukem 450: {
451: " Magic User", " MU",
452: " Fighter", " F ",
453: " Elf", " E ",
454: " Dwarf", " D ",
455: " Halfling", " H ",
456: " Experimento", " EX",
457: " Super", " S ",
458: " King", " K ",
459: " Council of Wise", " CW",
460: " Ex-Valar", " EV",
461: " Valar", " V ",
462: " ? ", " ? "
463: };
1.1 jtc 464:
1.3 lukem 465: type = playerp->p_type;
1.1 jtc 466:
1.3 lukem 467: switch (playerp->p_specialtype) {
1.1 jtc 468: case SC_NONE:
1.3 lukem 469: type = playerp->p_type;
470: break;
1.1 jtc 471:
472: case SC_KING:
1.3 lukem 473: type = 7;
474: break;
1.1 jtc 475:
476: case SC_COUNCIL:
1.3 lukem 477: type = 8;
478: break;
1.1 jtc 479:
480: case SC_EXVALAR:
1.3 lukem 481: type = 9;
482: break;
1.1 jtc 483:
484: case SC_VALAR:
1.3 lukem 485: type = 10;
486: break;
1.1 jtc 487: }
488:
1.3 lukem 489: type *= 2; /* calculate offset */
1.1 jtc 490:
1.3 lukem 491: if (type > 20)
492: /* error */
493: type = 22;
494:
495: if (shortflag)
496: /* use short descriptions */
497: ++type;
498:
499: if (playerp->p_crowns > 0) {
500: strcpy(Databuf, results[type]);
501: Databuf[0] = '*';
502: return (Databuf);
503: } else
504: return (results[type]);
1.1 jtc 505: }
506:
507: long
1.16 ! dholland 508: findname(const char *name, struct player *playerp)
1.1 jtc 509: {
1.3 lukem 510: long loc = 0; /* location in the file */
1.1 jtc 511:
1.6 jsm 512: fseek(Playersfp, 0L, SEEK_SET);
1.3 lukem 513: while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
514: if (strcmp(playerp->p_name, name) == 0) {
515: if (playerp->p_status != S_NOTUSED || Wizard)
516: /* found it */
517: return (loc);
518: }
519: loc += SZ_PLAYERSTRUCT;
1.1 jtc 520: }
521:
1.3 lukem 522: return (-1);
1.1 jtc 523: }
524:
525: long
1.16 ! dholland 526: allocrecord(void)
1.1 jtc 527: {
1.3 lukem 528: long loc = 0L; /* location in file */
1.1 jtc 529:
1.6 jsm 530: fseek(Playersfp, 0L, SEEK_SET);
1.3 lukem 531: while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
532: if (Other.p_status == S_NOTUSED)
533: /* found an empty record */
534: return (loc);
535: else
536: loc += SZ_PLAYERSTRUCT;
1.1 jtc 537: }
538:
1.3 lukem 539: /* make a new record */
540: initplayer(&Other);
541: Player.p_status = S_OFF;
542: writerecord(&Other, loc);
1.1 jtc 543:
1.3 lukem 544: return (loc);
545: }
546:
547: void
1.16 ! dholland 548: freerecord(struct player *playerp, long loc)
1.1 jtc 549: {
1.3 lukem 550: playerp->p_name[0] = CH_MARKDELETE;
551: playerp->p_status = S_NOTUSED;
552: writerecord(playerp, loc);
553: }
1.1 jtc 554:
1.3 lukem 555: void
1.16 ! dholland 556: leavegame(void)
1.1 jtc 557: {
558:
1.3 lukem 559: if (Player.p_level < 1.0)
560: /* delete character */
561: freerecord(&Player, Fileloc);
562: else {
563: Player.p_status = S_OFF;
564: writerecord(&Player, Fileloc);
1.1 jtc 565: }
566:
1.3 lukem 567: cleanup(TRUE);
568: /* NOTREACHED */
1.1 jtc 569: }
570:
1.3 lukem 571: void
1.16 ! dholland 572: death(const char *how)
1.1 jtc 573: {
1.3 lukem 574: FILE *fp; /* for updating various files */
575: int ch; /* input */
1.5 jsm 576: static const char *const deathmesg[] =
1.1 jtc 577: /* add more messages here, if desired */
578: {
1.3 lukem 579: "You have been wounded beyond repair. ",
580: "You have been disemboweled. ",
581: "You've been mashed, mauled, and spit upon. (You're dead.)\n",
582: "You died! ",
583: "You're a complete failure -- you've died!!\n",
584: "You have been dealt a fatal blow! "
1.1 jtc 585: };
586:
1.3 lukem 587: clear();
1.1 jtc 588:
1.3 lukem 589: if (strcmp(how, "Stupidity") != 0) {
590: if (Player.p_level > 9999.0)
591: /* old age */
592: addstr("Characters must be retired upon reaching level 10000. Sorry.");
593: else
594: if (Player.p_lives > 0)
595: /* extra lives */
596: {
597: addstr("You should be more cautious. You've been killed.\n");
598: printw("You only have %d more chance(s).\n", --Player.p_lives);
599: more(3);
600: Player.p_energy = Player.p_maxenergy;
601: return;
602: } else
603: if (Player.p_specialtype == SC_VALAR) {
604: addstr("You had your chances, but Valar aren't totally\n");
605: addstr("immortal. You are now left to wither and die . . .\n");
606: more(3);
607: Player.p_brains = Player.p_level / 25.0;
608: Player.p_energy = Player.p_maxenergy /= 5.0;
609: Player.p_quksilver = Player.p_sword = 0.0;
610: Player.p_specialtype = SC_COUNCIL;
611: return;
612: } else
613: if (Player.p_ring.ring_inuse &&
614: (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
615: /* good ring in use - saved
616: * from death */
617: {
618: mvaddstr(4, 0, "Your ring saved you from death!\n");
619: refresh();
620: Player.p_ring.ring_type = R_NONE;
621: Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
622: if (Player.p_crowns > 0)
623: --Player.p_crowns;
624: return;
625: } else
626: if (Player.p_ring.ring_type == R_BAD
627: || Player.p_ring.ring_type == R_SPOILED)
628: /* bad ring in
629: * possession; name
630: * idiot after player */
631: {
632: mvaddstr(4, 0,
633: "Your ring has taken control of you and turned you into a monster!\n");
1.6 jsm 634: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, SEEK_SET);
1.3 lukem 635: fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
636: strcpy(Curmonster.m_name, Player.p_name);
1.6 jsm 637: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, SEEK_SET);
1.3 lukem 638: fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
639: fflush(Monstfp);
640: }
641: }
642: enterscore(); /* update score board */
643:
644: /* put info in last dead file */
645: fp = fopen(_PATH_LASTDEAD, "w");
646: fprintf(fp, "%s (%s, run by %s, level %.0f, killed by %s)",
647: Player.p_name, descrtype(&Player, TRUE),
648: Player.p_login, Player.p_level, how);
649: fclose(fp);
1.1 jtc 650:
1.3 lukem 651: /* let other players know */
652: fp = fopen(_PATH_MESS, "w");
653: fprintf(fp, "%s was killed by %s.", Player.p_name, how);
654: fclose(fp);
1.1 jtc 655:
1.3 lukem 656: freerecord(&Player, Fileloc);
1.1 jtc 657:
1.3 lukem 658: clear();
659: move(10, 0);
660: addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
661: addstr("Care to give it another try ? ");
662: ch = getanswer("NY", FALSE);
663:
664: if (ch == 'Y') {
665: cleanup(FALSE);
666: execl(_PATH_GAMEPROG, "phantasia", "-s",
1.13 jsm 667: (Wizard ? "-S" : (char *) NULL), (char *) NULL);
1.3 lukem 668: exit(0);
669: /* NOTREACHED */
1.1 jtc 670: }
1.3 lukem 671: cleanup(TRUE);
672: /* NOTREACHED */
1.1 jtc 673: }
674:
1.3 lukem 675: void
1.16 ! dholland 676: writerecord(struct player *playerp, long place)
1.1 jtc 677: {
1.6 jsm 678: fseek(Playersfp, place, SEEK_SET);
1.3 lukem 679: fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
680: fflush(Playersfp);
681: }
1.1 jtc 682:
683: double
1.16 ! dholland 684: explevel(double experience)
1.1 jtc 685: {
1.3 lukem 686: if (experience < 1.1e7)
687: return (floor(pow((experience / 1000.0), 0.4875)));
688: else
689: return (floor(pow((experience / 1250.0), 0.4865)));
690: }
1.1 jtc 691:
1.3 lukem 692: void
1.16 ! dholland 693: truncstring(char *string)
1.1 jtc 694: {
1.3 lukem 695: int length; /* length of string */
1.1 jtc 696:
1.3 lukem 697: length = strlen(string);
698: while (string[--length] == ' ')
699: string[length] = '\0';
700: }
1.1 jtc 701:
1.3 lukem 702: void
1.16 ! dholland 703: altercoordinates(double xnew, double ynew, int operation)
1.3 lukem 704: {
705: switch (operation) {
706: case A_FORCED: /* move with no checks */
707: break;
708:
709: case A_NEAR: /* pick random coordinates near */
710: xnew = Player.p_x + ROLL(1.0, 5.0);
711: ynew = Player.p_y - ROLL(1.0, 5.0);
712: /* fall through for check */
1.1 jtc 713:
714: case A_SPECIFIC: /* just move player */
1.3 lukem 715: if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
716: /*
717: * cannot move back from point of no return
718: * pick the largest coordinate to remain unchanged
719: */
1.1 jtc 720: {
1.3 lukem 721: if (fabs(xnew) > fabs(ynew))
722: xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
723: else
724: ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
1.1 jtc 725: }
1.3 lukem 726: break;
1.1 jtc 727:
1.3 lukem 728: case A_FAR: /* pick random coordinates far */
729: xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
730: ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
731: break;
1.1 jtc 732: }
733:
1.3 lukem 734: /* now set location flags and adjust coordinates */
735: Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
736:
737: /* set up flags based upon location */
738: Throne = Marsh = Beyond = FALSE;
739:
740: if (Player.p_x == 0.0 && Player.p_y == 0.0)
741: Throne = TRUE;
742: else
743: if (Circle < 35 && Circle >= 20)
744: Marsh = TRUE;
745: else
746: if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
747: Beyond = TRUE;
748:
749: Changed = TRUE;
750: }
751:
752: void
1.16 ! dholland 753: readrecord(struct player *playerp, long loc)
1.1 jtc 754: {
1.6 jsm 755: fseek(Playersfp, loc, SEEK_SET);
1.3 lukem 756: fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
1.1 jtc 757: }
758:
1.3 lukem 759: void
1.16 ! dholland 760: adjuststats(void)
1.1 jtc 761: {
1.3 lukem 762: double dtemp; /* for temporary calculations */
1.1 jtc 763:
1.3 lukem 764: if (explevel(Player.p_experience) > Player.p_level)
765: /* move one or more levels */
1.1 jtc 766: {
1.3 lukem 767: movelevel();
768: if (Player.p_level > 5.0)
769: Timeout = TRUE;
770: }
771: if (Player.p_specialtype == SC_VALAR)
772: /* valar */
773: Circle = Player.p_level / 5.0;
774:
775: /* calculate effective quickness */
776: dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
1.8 simonb 777: - Player.p_level;
1.3 lukem 778: dtemp = MAX(0.0, dtemp);/* gold slows player down */
779: Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
780:
781: /* calculate effective strength */
782: if (Player.p_poison > 0.0)
783: /* poison makes player weaker */
784: {
785: dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
786: dtemp = MAX(0.1, dtemp);
787: } else
788: dtemp = 1.0;
789: Player.p_might = dtemp * Player.p_strength + Player.p_sword;
790:
791: /* insure that important things are within limits */
792: Player.p_quksilver = MIN(99.0, Player.p_quksilver);
793: Player.p_mana = MIN(Player.p_mana,
794: Player.p_level * Statptr->c_maxmana + 1000.0);
795: Player.p_brains = MIN(Player.p_brains,
796: Player.p_level * Statptr->c_maxbrains + 200.0);
797: Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
798:
799: /*
800: * some implementations have problems with floating point compare
801: * we work around it with this stuff
802: */
803: Player.p_gold = floor(Player.p_gold) + 0.1;
804: Player.p_gems = floor(Player.p_gems) + 0.1;
805: Player.p_mana = floor(Player.p_mana) + 0.1;
806:
807: if (Player.p_ring.ring_type != R_NONE)
808: /* do ring things */
809: {
810: /* rest to max */
811: Player.p_energy = Player.p_maxenergy + Player.p_shield;
812:
813: if (Player.p_ring.ring_duration <= 0)
814: /* clean up expired rings */
815: switch (Player.p_ring.ring_type) {
816: case R_BAD: /* ring drives player crazy */
817: Player.p_ring.ring_type = R_SPOILED;
818: Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
819: break;
1.1 jtc 820:
1.3 lukem 821: case R_NAZREG: /* ring disappears */
822: Player.p_ring.ring_type = R_NONE;
823: break;
1.1 jtc 824:
1.3 lukem 825: case R_SPOILED: /* ring kills player */
826: death("A cursed ring");
827: break;
1.1 jtc 828:
1.3 lukem 829: case R_DLREG: /* this ring doesn't expire */
830: Player.p_ring.ring_duration = 0;
831: break;
832: }
1.1 jtc 833: }
1.3 lukem 834: if (Player.p_age / N_AGE > Player.p_degenerated)
835: /* age player slightly */
1.1 jtc 836: {
1.3 lukem 837: ++Player.p_degenerated;
838: if (Player.p_quickness > 23.0)
839: Player.p_quickness *= 0.99;
840: Player.p_strength *= 0.97;
841: Player.p_brains *= 0.95;
842: Player.p_magiclvl *= 0.97;
843: Player.p_maxenergy *= 0.95;
844: Player.p_quksilver *= 0.95;
845: Player.p_sword *= 0.93;
846: Player.p_shield *= 0.93;
1.1 jtc 847: }
848: }
849:
1.3 lukem 850: void
1.16 ! dholland 851: initplayer(struct player *playerp)
1.1 jtc 852: {
1.3 lukem 853: playerp->p_experience =
854: playerp->p_level =
855: playerp->p_strength =
856: playerp->p_sword =
857: playerp->p_might =
858: playerp->p_energy =
859: playerp->p_maxenergy =
860: playerp->p_shield =
861: playerp->p_quickness =
862: playerp->p_quksilver =
863: playerp->p_speed =
864: playerp->p_magiclvl =
865: playerp->p_mana =
866: playerp->p_brains =
867: playerp->p_poison =
868: playerp->p_gems =
869: playerp->p_sin =
870: playerp->p_1scratch =
871: playerp->p_2scratch = 0.0;
872:
873: playerp->p_gold = ROLL(50.0, 75.0) + 0.1; /* give some gold */
874:
875: playerp->p_x = ROLL(-125.0, 251.0);
876: playerp->p_y = ROLL(-125.0, 251.0); /* give random x, y */
877:
878: /* clear ring */
879: playerp->p_ring.ring_type = R_NONE;
880: playerp->p_ring.ring_duration = 0;
881: playerp->p_ring.ring_inuse = FALSE;
882:
883: playerp->p_age = 0L;
884:
885: playerp->p_degenerated = 1; /* don't degenerate initially */
886:
887: playerp->p_type = C_FIGHTER; /* default */
888: playerp->p_specialtype = SC_NONE;
889: playerp->p_lives =
890: playerp->p_crowns =
891: playerp->p_charms =
892: playerp->p_amulets =
893: playerp->p_holywater =
894: playerp->p_lastused = 0;
895: playerp->p_status = S_NOTUSED;
896: playerp->p_tampered = T_OFF;
897: playerp->p_istat = I_OFF;
898:
899: playerp->p_palantir =
900: playerp->p_blessing =
901: playerp->p_virgin =
902: playerp->p_blindness = FALSE;
903:
904: playerp->p_name[0] =
905: playerp->p_password[0] =
906: playerp->p_login[0] = '\0';
907: }
1.1 jtc 908:
1.3 lukem 909: void
1.16 ! dholland 910: readmessage(void)
1.1 jtc 911: {
1.3 lukem 912: move(3, 0);
913: clrtoeol();
1.6 jsm 914: fseek(Messagefp, 0L, SEEK_SET);
1.3 lukem 915: if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
916: addstr(Databuf);
917: }
1.1 jtc 918:
1.3 lukem 919: void
1.16 ! dholland 920: error(const char *whichfile)
1.1 jtc 921: {
1.9 wiz 922: int (*funcp)(const char *,...);
1.1 jtc 923:
1.3 lukem 924: if (Windows) {
925: funcp = printw;
926: clear();
927: } else
928: funcp = printf;
929:
1.10 jsm 930: (*funcp) ("An unrecoverable error has occurred reading %s. (%s)\n", whichfile, strerror(errno));
1.3 lukem 931: (*funcp) ("Please run 'setup' to determine the problem.\n");
932: cleanup(TRUE);
933: /* NOTREACHED */
934: }
1.1 jtc 935:
936: double
1.16 ! dholland 937: distance(double x_1, double x_2, double y_1, double y_2)
1.1 jtc 938: {
1.3 lukem 939: double deltax, deltay;
1.1 jtc 940:
1.15 dholland 941: deltax = x_1 - x_2;
942: deltay = y_1 - y_2;
1.3 lukem 943: return (sqrt(deltax * deltax + deltay * deltay));
944: }
1.1 jtc 945:
1.3 lukem 946: void
1.16 ! dholland 947: ill_sig(int whichsig)
1.1 jtc 948: {
1.3 lukem 949: clear();
950: if (!(whichsig == SIGINT || whichsig == SIGQUIT))
951: printw("Error: caught signal # %d.\n", whichsig);
952: cleanup(TRUE);
953: /* NOTREACHED */
954: }
1.1 jtc 955:
1.5 jsm 956: const char *
1.16 ! dholland 957: descrstatus(struct player *playerp)
1.1 jtc 958: {
1.3 lukem 959: switch (playerp->p_status) {
1.1 jtc 960: case S_PLAYING:
1.3 lukem 961: if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
962: return ("Low Energy");
963: else
964: if (playerp->p_blindness)
965: return ("Blind");
966: else
967: return ("In game");
1.1 jtc 968:
969: case S_CLOAKED:
1.3 lukem 970: return ("Cloaked");
1.1 jtc 971:
972: case S_INBATTLE:
1.3 lukem 973: return ("In Battle");
1.1 jtc 974:
975: case S_MONSTER:
1.3 lukem 976: return ("Encounter");
1.1 jtc 977:
978: case S_TRADING:
1.3 lukem 979: return ("Trading");
1.1 jtc 980:
981: case S_OFF:
1.3 lukem 982: return ("Off");
1.1 jtc 983:
984: case S_HUNGUP:
1.3 lukem 985: return ("Hung up");
1.1 jtc 986:
987: default:
1.3 lukem 988: return ("");
1.1 jtc 989: }
990: }
991:
992: double
1.16 ! dholland 993: drandom(void)
1.1 jtc 994: {
1.3 lukem 995: if (sizeof(int) != 2)
996: /* use only low bits */
997: return ((double) (random() & 0x7fff) / 32768.0);
998: else
999: return ((double) random() / 32768.0);
1000: }
1.1 jtc 1001:
1.3 lukem 1002: void
1.16 ! dholland 1003: collecttaxes(double gold, double gems)
1.1 jtc 1004: {
1.3 lukem 1005: FILE *fp; /* to update Goldfile */
1006: double dtemp; /* for temporary calculations */
1007: double taxes; /* tax liability */
1008:
1009: /* add to cache */
1010: Player.p_gold += gold;
1011: Player.p_gems += gems;
1.1 jtc 1012:
1.3 lukem 1013: /* calculate tax liability */
1014: taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
1.1 jtc 1015:
1.3 lukem 1016: if (Player.p_gold < taxes)
1017: /* not enough gold to pay taxes, must convert some gems to
1018: * gold */
1.1 jtc 1019: {
1.3 lukem 1020: dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to
1021: * convert */
1.1 jtc 1022:
1.3 lukem 1023: if (Player.p_gems >= dtemp)
1024: /* player has enough to convert */
1025: {
1026: Player.p_gems -= dtemp;
1027: Player.p_gold += dtemp * N_GEMVALUE;
1028: } else
1029: /* take everything; this should never happen */
1030: {
1031: Player.p_gold += Player.p_gems * N_GEMVALUE;
1032: Player.p_gems = 0.0;
1033: taxes = Player.p_gold;
1034: }
1.1 jtc 1035: }
1.3 lukem 1036: Player.p_gold -= taxes;
1.1 jtc 1037:
1.3 lukem 1038: if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
1039: /* update taxes */
1.1 jtc 1040: {
1.3 lukem 1041: dtemp = 0.0;
1042: fread((char *) &dtemp, sizeof(double), 1, fp);
1043: dtemp += floor(taxes);
1.6 jsm 1044: fseek(fp, 0L, SEEK_SET);
1.3 lukem 1045: fwrite((char *) &dtemp, sizeof(double), 1, fp);
1046: fclose(fp);
1.1 jtc 1047: }
1048: }
CVSweb <webmaster@jp.NetBSD.org>