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