Annotation of src/games/phantasia/misc.c, Revision 1.5
1.5 ! jsm 1: /* $NetBSD: misc.c,v 1.4 1998/08/30 09:19:39 veego Exp $ */
1.2 cgd 2:
1.1 jtc 3: /*
4: * misc.c Phantasia miscellaneous support routines
5: */
6:
7: #include "include.h"
8:
9:
1.3 lukem 10: void
1.1 jtc 11: movelevel()
12: {
1.5 ! jsm 13: const struct charstats *statptr; /* for pointing into Stattable */
1.3 lukem 14: double new; /* new level */
15: double inc; /* increment between new and old levels */
16:
17: Changed = TRUE;
18:
19: if (Player.p_type == C_EXPER)
20: /* roll a type to use for increment */
21: statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
22: else
23: statptr = Statptr;
1.1 jtc 24:
1.3 lukem 25: new = explevel(Player.p_experience);
26: inc = new - Player.p_level;
27: Player.p_level = new;
28:
29: /* add increments to statistics */
30: Player.p_strength += statptr->c_strength.increase * inc;
31: Player.p_mana += statptr->c_mana.increase * inc;
32: Player.p_brains += statptr->c_brains.increase * inc;
33: Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
34: Player.p_maxenergy += statptr->c_energy.increase * inc;
1.1 jtc 35:
1.3 lukem 36: /* rest to maximum upon reaching new level */
37: Player.p_energy = Player.p_maxenergy + Player.p_shield;
38:
39: if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
40: /* no longer able to be king -- turn crowns into cash */
1.1 jtc 41: {
1.3 lukem 42: Player.p_gold += ((double) Player.p_crowns) * 5000.0;
43: Player.p_crowns = 0;
1.1 jtc 44: }
1.3 lukem 45: if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
46: /* make a member of the council */
1.1 jtc 47: {
1.3 lukem 48: mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
49: addstr("Good Luck on your search for the Holy Grail.\n");
1.1 jtc 50:
1.3 lukem 51: Player.p_specialtype = SC_COUNCIL;
1.1 jtc 52:
1.3 lukem 53: /* no rings for council and above */
54: Player.p_ring.ring_type = R_NONE;
55: Player.p_ring.ring_duration = 0;
1.1 jtc 56:
1.3 lukem 57: Player.p_lives = 3; /* three extra lives */
1.1 jtc 58: }
1.3 lukem 59: if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
60: death("Old age");
1.1 jtc 61: }
62:
1.5 ! jsm 63: const char *
1.1 jtc 64: descrlocation(playerp, shortflag)
1.3 lukem 65: struct player *playerp;
66: bool 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.1 jtc 144: tradingpost()
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.1 jtc 401: displaystats()
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.1 jtc 413: allstatslist()
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);
429: mvprintw(16, 0, "Age : %9d", Player.p_age);
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.1 jtc 446: descrtype(playerp, shortflag)
1.3 lukem 447: struct player *playerp;
448: bool shortflag;
1.1 jtc 449: {
1.3 lukem 450: int type; /* for caluculating result subscript */
1.5 ! jsm 451: static const char *const results[] =/* description table */
1.3 lukem 452: {
453: " Magic User", " MU",
454: " Fighter", " F ",
455: " Elf", " E ",
456: " Dwarf", " D ",
457: " Halfling", " H ",
458: " Experimento", " EX",
459: " Super", " S ",
460: " King", " K ",
461: " Council of Wise", " CW",
462: " Ex-Valar", " EV",
463: " Valar", " V ",
464: " ? ", " ? "
465: };
1.1 jtc 466:
1.3 lukem 467: type = playerp->p_type;
1.1 jtc 468:
1.3 lukem 469: switch (playerp->p_specialtype) {
1.1 jtc 470: case SC_NONE:
1.3 lukem 471: type = playerp->p_type;
472: break;
1.1 jtc 473:
474: case SC_KING:
1.3 lukem 475: type = 7;
476: break;
1.1 jtc 477:
478: case SC_COUNCIL:
1.3 lukem 479: type = 8;
480: break;
1.1 jtc 481:
482: case SC_EXVALAR:
1.3 lukem 483: type = 9;
484: break;
1.1 jtc 485:
486: case SC_VALAR:
1.3 lukem 487: type = 10;
488: break;
1.1 jtc 489: }
490:
1.3 lukem 491: type *= 2; /* calculate offset */
1.1 jtc 492:
1.3 lukem 493: if (type > 20)
494: /* error */
495: type = 22;
496:
497: if (shortflag)
498: /* use short descriptions */
499: ++type;
500:
501: if (playerp->p_crowns > 0) {
502: strcpy(Databuf, results[type]);
503: Databuf[0] = '*';
504: return (Databuf);
505: } else
506: return (results[type]);
1.1 jtc 507: }
508:
509: long
510: findname(name, playerp)
1.5 ! jsm 511: const char *name;
1.3 lukem 512: struct player *playerp;
1.1 jtc 513: {
1.3 lukem 514: long loc = 0; /* location in the file */
1.1 jtc 515:
1.3 lukem 516: fseek(Playersfp, 0L, 0);
517: while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
518: if (strcmp(playerp->p_name, name) == 0) {
519: if (playerp->p_status != S_NOTUSED || Wizard)
520: /* found it */
521: return (loc);
522: }
523: loc += SZ_PLAYERSTRUCT;
1.1 jtc 524: }
525:
1.3 lukem 526: return (-1);
1.1 jtc 527: }
528:
529: long
530: allocrecord()
531: {
1.3 lukem 532: long loc = 0L; /* location in file */
1.1 jtc 533:
1.3 lukem 534: fseek(Playersfp, 0L, 0);
535: while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
536: if (Other.p_status == S_NOTUSED)
537: /* found an empty record */
538: return (loc);
539: else
540: loc += SZ_PLAYERSTRUCT;
1.1 jtc 541: }
542:
1.3 lukem 543: /* make a new record */
544: initplayer(&Other);
545: Player.p_status = S_OFF;
546: writerecord(&Other, loc);
1.1 jtc 547:
1.3 lukem 548: return (loc);
549: }
550:
551: void
1.1 jtc 552: freerecord(playerp, loc)
1.3 lukem 553: struct player *playerp;
554: long loc;
1.1 jtc 555: {
1.3 lukem 556: playerp->p_name[0] = CH_MARKDELETE;
557: playerp->p_status = S_NOTUSED;
558: writerecord(playerp, loc);
559: }
1.1 jtc 560:
1.3 lukem 561: void
1.1 jtc 562: leavegame()
563: {
564:
1.3 lukem 565: if (Player.p_level < 1.0)
566: /* delete character */
567: freerecord(&Player, Fileloc);
568: else {
569: Player.p_status = S_OFF;
570: writerecord(&Player, Fileloc);
1.1 jtc 571: }
572:
1.3 lukem 573: cleanup(TRUE);
574: /* NOTREACHED */
1.1 jtc 575: }
576:
1.3 lukem 577: void
1.1 jtc 578: death(how)
1.5 ! jsm 579: const char *how;
1.1 jtc 580: {
1.3 lukem 581: FILE *fp; /* for updating various files */
582: int ch; /* input */
1.5 ! jsm 583: static const char *const deathmesg[] =
1.1 jtc 584: /* add more messages here, if desired */
585: {
1.3 lukem 586: "You have been wounded beyond repair. ",
587: "You have been disemboweled. ",
588: "You've been mashed, mauled, and spit upon. (You're dead.)\n",
589: "You died! ",
590: "You're a complete failure -- you've died!!\n",
591: "You have been dealt a fatal blow! "
1.1 jtc 592: };
593:
1.3 lukem 594: clear();
1.1 jtc 595:
1.3 lukem 596: if (strcmp(how, "Stupidity") != 0) {
597: if (Player.p_level > 9999.0)
598: /* old age */
599: addstr("Characters must be retired upon reaching level 10000. Sorry.");
600: else
601: if (Player.p_lives > 0)
602: /* extra lives */
603: {
604: addstr("You should be more cautious. You've been killed.\n");
605: printw("You only have %d more chance(s).\n", --Player.p_lives);
606: more(3);
607: Player.p_energy = Player.p_maxenergy;
608: return;
609: } else
610: if (Player.p_specialtype == SC_VALAR) {
611: addstr("You had your chances, but Valar aren't totally\n");
612: addstr("immortal. You are now left to wither and die . . .\n");
613: more(3);
614: Player.p_brains = Player.p_level / 25.0;
615: Player.p_energy = Player.p_maxenergy /= 5.0;
616: Player.p_quksilver = Player.p_sword = 0.0;
617: Player.p_specialtype = SC_COUNCIL;
618: return;
619: } else
620: if (Player.p_ring.ring_inuse &&
621: (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
622: /* good ring in use - saved
623: * from death */
624: {
625: mvaddstr(4, 0, "Your ring saved you from death!\n");
626: refresh();
627: Player.p_ring.ring_type = R_NONE;
628: Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
629: if (Player.p_crowns > 0)
630: --Player.p_crowns;
631: return;
632: } else
633: if (Player.p_ring.ring_type == R_BAD
634: || Player.p_ring.ring_type == R_SPOILED)
635: /* bad ring in
636: * possession; name
637: * idiot after player */
638: {
639: mvaddstr(4, 0,
640: "Your ring has taken control of you and turned you into a monster!\n");
641: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
642: fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
643: strcpy(Curmonster.m_name, Player.p_name);
644: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
645: fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
646: fflush(Monstfp);
647: }
648: }
649: enterscore(); /* update score board */
650:
651: /* put info in last dead file */
652: fp = fopen(_PATH_LASTDEAD, "w");
653: fprintf(fp, "%s (%s, run by %s, level %.0f, killed by %s)",
654: Player.p_name, descrtype(&Player, TRUE),
655: Player.p_login, Player.p_level, how);
656: fclose(fp);
1.1 jtc 657:
1.3 lukem 658: /* let other players know */
659: fp = fopen(_PATH_MESS, "w");
660: fprintf(fp, "%s was killed by %s.", Player.p_name, how);
661: fclose(fp);
1.1 jtc 662:
1.3 lukem 663: freerecord(&Player, Fileloc);
1.1 jtc 664:
1.3 lukem 665: clear();
666: move(10, 0);
667: addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
668: addstr("Care to give it another try ? ");
669: ch = getanswer("NY", FALSE);
670:
671: if (ch == 'Y') {
672: cleanup(FALSE);
673: execl(_PATH_GAMEPROG, "phantasia", "-s",
674: (Wizard ? "-S" : (char *) NULL), 0);
675: exit(0);
676: /* NOTREACHED */
1.1 jtc 677: }
1.3 lukem 678: cleanup(TRUE);
679: /* NOTREACHED */
1.1 jtc 680: }
681:
1.3 lukem 682: void
1.1 jtc 683: writerecord(playerp, place)
1.3 lukem 684: struct player *playerp;
685: long place;
1.1 jtc 686: {
1.3 lukem 687: fseek(Playersfp, place, 0);
688: fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
689: fflush(Playersfp);
690: }
1.1 jtc 691:
692: double
693: explevel(experience)
1.3 lukem 694: double experience;
1.1 jtc 695: {
1.3 lukem 696: if (experience < 1.1e7)
697: return (floor(pow((experience / 1000.0), 0.4875)));
698: else
699: return (floor(pow((experience / 1250.0), 0.4865)));
700: }
1.1 jtc 701:
1.3 lukem 702: void
1.1 jtc 703: truncstring(string)
1.3 lukem 704: char *string;
1.1 jtc 705: {
1.3 lukem 706: int length; /* length of string */
1.1 jtc 707:
1.3 lukem 708: length = strlen(string);
709: while (string[--length] == ' ')
710: string[length] = '\0';
711: }
1.1 jtc 712:
1.3 lukem 713: void
1.1 jtc 714: altercoordinates(xnew, ynew, operation)
1.3 lukem 715: double xnew;
716: double ynew;
717: int operation;
718: {
719: switch (operation) {
720: case A_FORCED: /* move with no checks */
721: break;
722:
723: case A_NEAR: /* pick random coordinates near */
724: xnew = Player.p_x + ROLL(1.0, 5.0);
725: ynew = Player.p_y - ROLL(1.0, 5.0);
726: /* fall through for check */
1.1 jtc 727:
728: case A_SPECIFIC: /* just move player */
1.3 lukem 729: if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
730: /*
731: * cannot move back from point of no return
732: * pick the largest coordinate to remain unchanged
733: */
1.1 jtc 734: {
1.3 lukem 735: if (fabs(xnew) > fabs(ynew))
736: xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
737: else
738: ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
1.1 jtc 739: }
1.3 lukem 740: break;
1.1 jtc 741:
1.3 lukem 742: case A_FAR: /* pick random coordinates far */
743: xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
744: ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
745: break;
1.1 jtc 746: }
747:
1.3 lukem 748: /* now set location flags and adjust coordinates */
749: Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
750:
751: /* set up flags based upon location */
752: Throne = Marsh = Beyond = FALSE;
753:
754: if (Player.p_x == 0.0 && Player.p_y == 0.0)
755: Throne = TRUE;
756: else
757: if (Circle < 35 && Circle >= 20)
758: Marsh = TRUE;
759: else
760: if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
761: Beyond = TRUE;
762:
763: Changed = TRUE;
764: }
765:
766: void
1.1 jtc 767: readrecord(playerp, loc)
1.3 lukem 768: struct player *playerp;
769: long loc;
1.1 jtc 770: {
1.3 lukem 771: fseek(Playersfp, loc, 0);
772: fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
1.1 jtc 773: }
774:
1.3 lukem 775: void
1.1 jtc 776: adjuststats()
777: {
1.3 lukem 778: double dtemp; /* for temporary calculations */
1.1 jtc 779:
1.3 lukem 780: if (explevel(Player.p_experience) > Player.p_level)
781: /* move one or more levels */
1.1 jtc 782: {
1.3 lukem 783: movelevel();
784: if (Player.p_level > 5.0)
785: Timeout = TRUE;
786: }
787: if (Player.p_specialtype == SC_VALAR)
788: /* valar */
789: Circle = Player.p_level / 5.0;
790:
791: /* calculate effective quickness */
792: dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
793: - Player.p_level;;
794: dtemp = MAX(0.0, dtemp);/* gold slows player down */
795: Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
796:
797: /* calculate effective strength */
798: if (Player.p_poison > 0.0)
799: /* poison makes player weaker */
800: {
801: dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
802: dtemp = MAX(0.1, dtemp);
803: } else
804: dtemp = 1.0;
805: Player.p_might = dtemp * Player.p_strength + Player.p_sword;
806:
807: /* insure that important things are within limits */
808: Player.p_quksilver = MIN(99.0, Player.p_quksilver);
809: Player.p_mana = MIN(Player.p_mana,
810: Player.p_level * Statptr->c_maxmana + 1000.0);
811: Player.p_brains = MIN(Player.p_brains,
812: Player.p_level * Statptr->c_maxbrains + 200.0);
813: Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
814:
815: /*
816: * some implementations have problems with floating point compare
817: * we work around it with this stuff
818: */
819: Player.p_gold = floor(Player.p_gold) + 0.1;
820: Player.p_gems = floor(Player.p_gems) + 0.1;
821: Player.p_mana = floor(Player.p_mana) + 0.1;
822:
823: if (Player.p_ring.ring_type != R_NONE)
824: /* do ring things */
825: {
826: /* rest to max */
827: Player.p_energy = Player.p_maxenergy + Player.p_shield;
828:
829: if (Player.p_ring.ring_duration <= 0)
830: /* clean up expired rings */
831: switch (Player.p_ring.ring_type) {
832: case R_BAD: /* ring drives player crazy */
833: Player.p_ring.ring_type = R_SPOILED;
834: Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
835: break;
1.1 jtc 836:
1.3 lukem 837: case R_NAZREG: /* ring disappears */
838: Player.p_ring.ring_type = R_NONE;
839: break;
1.1 jtc 840:
1.3 lukem 841: case R_SPOILED: /* ring kills player */
842: death("A cursed ring");
843: break;
1.1 jtc 844:
1.3 lukem 845: case R_DLREG: /* this ring doesn't expire */
846: Player.p_ring.ring_duration = 0;
847: break;
848: }
1.1 jtc 849: }
1.3 lukem 850: if (Player.p_age / N_AGE > Player.p_degenerated)
851: /* age player slightly */
1.1 jtc 852: {
1.3 lukem 853: ++Player.p_degenerated;
854: if (Player.p_quickness > 23.0)
855: Player.p_quickness *= 0.99;
856: Player.p_strength *= 0.97;
857: Player.p_brains *= 0.95;
858: Player.p_magiclvl *= 0.97;
859: Player.p_maxenergy *= 0.95;
860: Player.p_quksilver *= 0.95;
861: Player.p_sword *= 0.93;
862: Player.p_shield *= 0.93;
1.1 jtc 863: }
864: }
865:
1.3 lukem 866: void
1.1 jtc 867: initplayer(playerp)
1.3 lukem 868: struct player *playerp;
1.1 jtc 869: {
1.3 lukem 870: playerp->p_experience =
871: playerp->p_level =
872: playerp->p_strength =
873: playerp->p_sword =
874: playerp->p_might =
875: playerp->p_energy =
876: playerp->p_maxenergy =
877: playerp->p_shield =
878: playerp->p_quickness =
879: playerp->p_quksilver =
880: playerp->p_speed =
881: playerp->p_magiclvl =
882: playerp->p_mana =
883: playerp->p_brains =
884: playerp->p_poison =
885: playerp->p_gems =
886: playerp->p_sin =
887: playerp->p_1scratch =
888: playerp->p_2scratch = 0.0;
889:
890: playerp->p_gold = ROLL(50.0, 75.0) + 0.1; /* give some gold */
891:
892: playerp->p_x = ROLL(-125.0, 251.0);
893: playerp->p_y = ROLL(-125.0, 251.0); /* give random x, y */
894:
895: /* clear ring */
896: playerp->p_ring.ring_type = R_NONE;
897: playerp->p_ring.ring_duration = 0;
898: playerp->p_ring.ring_inuse = FALSE;
899:
900: playerp->p_age = 0L;
901:
902: playerp->p_degenerated = 1; /* don't degenerate initially */
903:
904: playerp->p_type = C_FIGHTER; /* default */
905: playerp->p_specialtype = SC_NONE;
906: playerp->p_lives =
907: playerp->p_crowns =
908: playerp->p_charms =
909: playerp->p_amulets =
910: playerp->p_holywater =
911: playerp->p_lastused = 0;
912: playerp->p_status = S_NOTUSED;
913: playerp->p_tampered = T_OFF;
914: playerp->p_istat = I_OFF;
915:
916: playerp->p_palantir =
917: playerp->p_blessing =
918: playerp->p_virgin =
919: playerp->p_blindness = FALSE;
920:
921: playerp->p_name[0] =
922: playerp->p_password[0] =
923: playerp->p_login[0] = '\0';
924: }
1.1 jtc 925:
1.3 lukem 926: void
1.1 jtc 927: readmessage()
928: {
1.3 lukem 929: move(3, 0);
930: clrtoeol();
931: fseek(Messagefp, 0L, 0);
932: if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
933: addstr(Databuf);
934: }
1.1 jtc 935:
1.3 lukem 936: void
1.1 jtc 937: error(whichfile)
1.5 ! jsm 938: const char *whichfile;
1.1 jtc 939: {
1.3 lukem 940: int (*funcp) __P((const char *,...));
1.1 jtc 941:
1.3 lukem 942: if (Windows) {
943: funcp = printw;
944: clear();
945: } else
946: funcp = printf;
947:
948: (*funcp) ("An unrecoverable error has occurred reading %s. (errno = %d)\n", whichfile, errno);
949: (*funcp) ("Please run 'setup' to determine the problem.\n");
950: cleanup(TRUE);
951: /* NOTREACHED */
952: }
1.1 jtc 953:
954: double
955: distance(x1, x2, y1, y2)
1.3 lukem 956: double x1, x2, y1, y2;
1.1 jtc 957: {
1.3 lukem 958: double deltax, deltay;
1.1 jtc 959:
1.3 lukem 960: deltax = x1 - x2;
961: deltay = y1 - y2;
962: return (sqrt(deltax * deltax + deltay * deltay));
963: }
1.1 jtc 964:
1.3 lukem 965: void
1.1 jtc 966: ill_sig(whichsig)
1.3 lukem 967: int whichsig;
1.1 jtc 968: {
1.3 lukem 969: clear();
970: if (!(whichsig == SIGINT || whichsig == SIGQUIT))
971: printw("Error: caught signal # %d.\n", whichsig);
972: cleanup(TRUE);
973: /* NOTREACHED */
974: }
1.1 jtc 975:
1.5 ! jsm 976: const char *
1.1 jtc 977: descrstatus(playerp)
1.3 lukem 978: struct player *playerp;
1.1 jtc 979: {
1.3 lukem 980: switch (playerp->p_status) {
1.1 jtc 981: case S_PLAYING:
1.3 lukem 982: if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
983: return ("Low Energy");
984: else
985: if (playerp->p_blindness)
986: return ("Blind");
987: else
988: return ("In game");
1.1 jtc 989:
990: case S_CLOAKED:
1.3 lukem 991: return ("Cloaked");
1.1 jtc 992:
993: case S_INBATTLE:
1.3 lukem 994: return ("In Battle");
1.1 jtc 995:
996: case S_MONSTER:
1.3 lukem 997: return ("Encounter");
1.1 jtc 998:
999: case S_TRADING:
1.3 lukem 1000: return ("Trading");
1.1 jtc 1001:
1002: case S_OFF:
1.3 lukem 1003: return ("Off");
1.1 jtc 1004:
1005: case S_HUNGUP:
1.3 lukem 1006: return ("Hung up");
1.1 jtc 1007:
1008: default:
1.3 lukem 1009: return ("");
1.1 jtc 1010: }
1011: }
1012:
1013: double
1014: drandom()
1015: {
1.3 lukem 1016: if (sizeof(int) != 2)
1017: /* use only low bits */
1018: return ((double) (random() & 0x7fff) / 32768.0);
1019: else
1020: return ((double) random() / 32768.0);
1021: }
1.1 jtc 1022:
1.3 lukem 1023: void
1.1 jtc 1024: collecttaxes(gold, gems)
1.3 lukem 1025: double gold;
1026: double gems;
1.1 jtc 1027: {
1.3 lukem 1028: FILE *fp; /* to update Goldfile */
1029: double dtemp; /* for temporary calculations */
1030: double taxes; /* tax liability */
1031:
1032: /* add to cache */
1033: Player.p_gold += gold;
1034: Player.p_gems += gems;
1.1 jtc 1035:
1.3 lukem 1036: /* calculate tax liability */
1037: taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
1.1 jtc 1038:
1.3 lukem 1039: if (Player.p_gold < taxes)
1040: /* not enough gold to pay taxes, must convert some gems to
1041: * gold */
1.1 jtc 1042: {
1.3 lukem 1043: dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to
1044: * convert */
1.1 jtc 1045:
1.3 lukem 1046: if (Player.p_gems >= dtemp)
1047: /* player has enough to convert */
1048: {
1049: Player.p_gems -= dtemp;
1050: Player.p_gold += dtemp * N_GEMVALUE;
1051: } else
1052: /* take everything; this should never happen */
1053: {
1054: Player.p_gold += Player.p_gems * N_GEMVALUE;
1055: Player.p_gems = 0.0;
1056: taxes = Player.p_gold;
1057: }
1.1 jtc 1058: }
1.3 lukem 1059: Player.p_gold -= taxes;
1.1 jtc 1060:
1.3 lukem 1061: if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
1062: /* update taxes */
1.1 jtc 1063: {
1.3 lukem 1064: dtemp = 0.0;
1065: fread((char *) &dtemp, sizeof(double), 1, fp);
1066: dtemp += floor(taxes);
1067: fseek(fp, 0L, 0);
1068: fwrite((char *) &dtemp, sizeof(double), 1, fp);
1069: fclose(fp);
1.1 jtc 1070: }
1071: }
CVSweb <webmaster@jp.NetBSD.org>