|
|
1.1 root 1: /*
2: * misc.c Phantasia miscellaneous support routines
3: */
4:
5: #include "include.h"
6:
7: /************************************************************************
8: /
9: / FUNCTION NAME: movelevel()
10: /
11: / FUNCTION: move player to new level
12: /
13: / AUTHOR: E. A. Estes, 12/4/85
14: /
15: / ARGUMENTS: none
16: /
17: / RETURN VALUE: none
18: /
19: / MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
20: /
21: / GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
22: /
23: / GLOBAL OUTPUTS: Player, Changed
24: /
25: / DESCRIPTION:
26: / Use lookup table to increment important statistics when
27: / progressing to new experience level.
28: / Players are rested to maximum as a bonus for making a new
29: / level.
30: / Check for council of wise, and being too big to be king.
31: /
32: /************************************************************************/
33:
34: movelevel()
35: {
36: register struct charstats *statptr; /* for pointing into Stattable */
37: double new; /* new level */
38: double inc; /* increment between new and old levels */
39:
40: Changed = TRUE;
41:
42: if (Player.p_type == C_EXPER)
43: /* roll a type to use for increment */
44: statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
45: else
46: statptr = Statptr;
47:
48: new = explevel(Player.p_experience);
49: inc = new - Player.p_level;
50: Player.p_level = new;
51:
52: /* add increments to statistics */
53: Player.p_strength += statptr->c_strength.increase * inc;
54: Player.p_mana += statptr->c_mana.increase * inc;
55: Player.p_brains += statptr->c_brains.increase * inc;
56: Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
57: Player.p_maxenergy += statptr->c_energy.increase * inc;
58:
59: /* rest to maximum upon reaching new level */
60: Player.p_energy = Player.p_maxenergy + Player.p_shield;
61:
62: if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
63: /* no longer able to be king -- turn crowns into cash */
64: {
65: Player.p_gold += ((double) Player.p_crowns) * 5000.0;
66: Player.p_crowns = 0;
67: }
68:
69: if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
70: /* make a member of the council */
71: {
72: mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
73: addstr("Good Luck on your search for the Holy Grail.\n");
74:
75: Player.p_specialtype = SC_COUNCIL;
76:
77: /* no rings for council and above */
78: Player.p_ring.ring_type = R_NONE;
79: Player.p_ring.ring_duration = 0;
80:
81: Player.p_lives = 3; /* three extra lives */
82: }
83:
84: if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
85: death("Old age");
86: }
87: /**/
88: /************************************************************************
89: /
90: / FUNCTION NAME: descrlocation()
91: /
92: / FUNCTION: return a formatted description of location
93: /
94: / AUTHOR: E. A. Estes, 12/4/85
95: /
96: / ARGUMENTS:
97: / struct player playerp - pointer to player structure
98: / bool shortflag - set if short form is desired
99: /
100: / RETURN VALUE: pointer to string containing result
101: /
102: / MODULES CALLED: fabs(), floor(), sprintf(), distance()
103: /
104: / GLOBAL INPUTS: Databuf[]
105: /
106: / GLOBAL OUTPUTS: none
107: /
108: / DESCRIPTION:
109: / Look at coordinates and return an appropriately formatted
110: / string.
111: /
112: /************************************************************************/
113:
114: char *
115: descrlocation(playerp, shortflag)
116: struct player *playerp;
117: bool shortflag;
118: {
119: double circle; /* corresponding circle for coordinates */
120: register int quadrant; /* quandrant of grid */
121: register char *label; /* pointer to place name */
122: static char *nametable[4][4] = /* names of places */
123: {
124: "Anorien", "Ithilien", "Rohan", "Lorien",
125: "Gondor", "Mordor", "Dunland", "Rovanion",
126: "South Gondor", "Khand", "Eriador", "The Iron Hills",
127: "Far Harad", "Near Harad", "The Northern Waste", "Rhun"
128: };
129:
130: if (playerp->p_specialtype == SC_VALAR)
131: return(" is in Valhala");
132: else if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0)
133: {
134: if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
135: label = "The Point of No Return";
136: else
137: label = "The Ashen Mountains";
138: }
139: else if (circle >= 55)
140: label = "Morannon";
141: else if (circle >= 35)
142: label = "Kennaquahair";
143: else if (circle >= 20)
144: label = "The Dead Marshes";
145: else if (circle >= 9)
146: label = "The Outer Waste";
147: else if (circle >= 5)
148: label = "The Moors Adventurous";
149: else
150: {
151: if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
152: label = "The Lord's Chamber";
153: else
154: {
155: /* this expression is split to prevent compiler loop with some compilers */
156: quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
157: quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
158: label = nametable[((int) circle) - 1][quadrant];
159: }
160: }
161:
162: if (shortflag)
163: sprintf(Databuf, "%.29s", label);
164: else
165: sprintf(Databuf, " is in %s (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
166:
167: return(Databuf);
168: }
169: /**/
170: /************************************************************************
171: /
172: / FUNCTION NAME: tradingpost()
173: /
174: / FUNCTION: do trading post stuff
175: /
176: / AUTHOR: E. A. Estes, 12/4/85
177: /
178: / ARGUMENTS: none
179: /
180: / RETURN VALUE: none
181: /
182: / MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
183: / sleep(), floor(), wmove(), drandom(), wclear(), printw(),
184: / altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
185: / wclrtoeol(), wclrtobot()
186: /
187: / GLOBAL INPUTS: Menu[], Circle, Player, *stdscr, Fileloc, Nobetter[]
188: /
189: / GLOBAL OUTPUTS: Player
190: /
191: / DESCRIPTION:
192: / Different trading posts have different items.
193: / Merchants cannot be cheated, but they can be dishonest
194: / themselves.
195: /
196: / Shields, swords, and quicksilver are not cumulative. This is
197: / one major area of complaint, but there are two reasons for this:
198: / 1) It becomes MUCH too easy to make very large versions
199: / of these items.
200: / 2) In the real world, one cannot simply weld two swords
201: / together to make a bigger one.
202: /
203: / At one time, it was possible to sell old weapons at half the purchase
204: / price. This resulted in huge amounts of gold floating around,
205: / and the game lost much of its challenge.
206: /
207: / Also, purchasing gems defeats the whole purpose of gold. Gold
208: / is small change for lower level players. They really shouldn't
209: / be able to accumulate more than enough gold for a small sword or
210: / a few books. Higher level players shouldn't even bother to pick
211: / up gold, except maybe to buy mana once in a while.
212: /
213: /************************************************************************/
214:
215: tradingpost()
216: {
217: double numitems; /* number of items to purchase */
218: double cost; /* cost of purchase */
219: double blessingcost; /* cost of blessing */
220: int ch; /* input */
221: register int size; /* size of the trading post */
222: register int loop; /* loop counter */
223: int cheat = 0; /* number of times player has tried to cheat */
224: bool dishonest = FALSE;/* set when merchant is dishonest */
225:
226: Player.p_status = S_TRADING;
227: writerecord(&Player, Fileloc);
228:
229: clear();
230: addstr("You are at a trading post. All purchases must be made with gold.");
231:
232: size = sqrt(fabs(Player.p_x / 100)) + 1;
233: size = MIN(7, size);
234:
235: /* set up cost of blessing */
236: blessingcost = 1000.0 * (Player.p_level + 5.0);
237:
238: /* print Menu */
239: move(7, 0);
240: for (loop = 0; loop < size; ++loop)
241: /* print Menu */
242: {
243: if (loop == 6)
244: cost = blessingcost;
245: else
246: cost = Menu[loop].cost;
247: printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
248: }
249:
250: mvprintw(5, 0, "L:Leave P:Purchase S:Sell Gems ? ");
251:
252: for (;;)
253: {
254: adjuststats(); /* truncate any bad values */
255:
256: /* print some important statistics */
257: mvprintw(1, 0, "Gold: %9.0f Gems: %9.0f Level: %6.0f Charms: %6d\n",
258: Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
259: printw("Shield: %9.0f Sword: %9.0f Quicksilver:%3.0f Blessed: %s\n",
260: Player.p_shield, Player.p_sword, Player.p_quksilver,
261: (Player.p_blessing ? " True" : "False"));
262: printw("Brains: %9.0f Mana: %9.0f", Player.p_brains, Player.p_mana);
263:
264: move(5, 36);
265: ch = getanswer("LPS", FALSE);
266: move(15, 0);
267: clrtobot();
268: switch(ch)
269: {
270: case 'L': /* leave */
271: case '\n':
272: altercoordinates(0.0, 0.0, A_NEAR);
273: return;
274:
275: case 'P': /* make purchase */
276: mvaddstr(15, 0, "What what would you like to buy ? ");
277: ch = getanswer(" 1234567", FALSE);
278: move(15, 0);
279: clrtoeol();
280:
281: if (ch - '0' > size)
282: addstr("Sorry, this merchant doesn't have that.");
283: else
284: switch (ch)
285: {
286: case '1':
287: printw("Mana is one per %.0f gold piece. How many do you want (%.0f max) ? ",
288: Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
289: cost = (numitems = floor(infloat())) * Menu[0].cost;
290:
291: if (cost > Player.p_gold || numitems < 0)
292: ++cheat;
293: else
294: {
295: cheat = 0;
296: Player.p_gold -= cost;
297: if (drandom() < 0.02)
298: dishonest = TRUE;
299: else
300: Player.p_mana += numitems;
301: }
302: break;
303:
304: case '2':
305: printw("Shields are %.0f per +1. How many do you want (%.0f max) ? ",
306: Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
307: cost = (numitems = floor(infloat())) * Menu[1].cost;
308:
309: if (numitems == 0.0)
310: break;
311: else if (cost > Player.p_gold || numitems < 0)
312: ++cheat;
313: else if (numitems < Player.p_shield)
314: NOBETTER();
315: else
316: {
317: cheat = 0;
318: Player.p_gold -= cost;
319: if (drandom() < 0.02)
320: dishonest = TRUE;
321: else
322: Player.p_shield = numitems;
323: }
324: break;
325:
326: case '3':
327: printw("A book costs %.0f gp. How many do you want (%.0f max) ? ",
328: Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
329: cost = (numitems = floor(infloat())) * Menu[2].cost;
330:
331: if (cost > Player.p_gold || numitems < 0)
332: ++cheat;
333: else
334: {
335: cheat = 0;
336: Player.p_gold -= cost;
337: if (drandom() < 0.02)
338: dishonest = TRUE;
339: else if (drandom() * numitems > Player.p_level / 10.0
340: && numitems != 1)
341: {
342: printw("\nYou blew your mind!\n");
343: Player.p_brains /= 5;
344: }
345: else
346: {
347: Player.p_brains += floor(numitems) * ROLL(20, 8);
348: }
349: }
350: break;
351:
352: case '4':
353: printw("Swords are %.0f gp per +1. How many + do you want (%.0f max) ? ",
354: Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
355: cost = (numitems = floor(infloat())) * Menu[3].cost;
356:
357: if (numitems == 0.0)
358: break;
359: else if (cost > Player.p_gold || numitems < 0)
360: ++cheat;
361: else if (numitems < Player.p_sword)
362: NOBETTER();
363: else
364: {
365: cheat = 0;
366: Player.p_gold -= cost;
367: if (drandom() < 0.02)
368: dishonest = TRUE;
369: else
370: Player.p_sword = numitems;
371: }
372: break;
373:
374: case '5':
375: printw("A charm costs %.0f gp. How many do you want (%.0f max) ? ",
376: Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
377: cost = (numitems = floor(infloat())) * Menu[4].cost;
378:
379: if (cost > Player.p_gold || numitems < 0)
380: ++cheat;
381: else
382: {
383: cheat = 0;
384: Player.p_gold -= cost;
385: if (drandom() < 0.02)
386: dishonest = TRUE;
387: else
388: Player.p_charms += numitems;
389: }
390: break;
391:
392: case '6':
393: printw("Quicksilver is %.0f gp per +1. How many + do you want (%.0f max) ? ",
394: Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
395: cost = (numitems = floor(infloat())) * Menu[5].cost;
396:
397: if (numitems == 0.0)
398: break;
399: else if (cost > Player.p_gold || numitems < 0)
400: ++cheat;
401: else if (numitems < Player.p_quksilver)
402: NOBETTER();
403: else
404: {
405: cheat = 0;
406: Player.p_gold -= cost;
407: if (drandom() < 0.02)
408: dishonest = TRUE;
409: else
410: Player.p_quksilver = numitems;
411: }
412: break;
413:
414: case '7':
415: if (Player.p_blessing)
416: {
417: addstr("You already have a blessing.");
418: break;
419: }
420:
421: printw("A blessing requires a %.0f gp donation. Still want one ? ", blessingcost);
422: ch = getanswer("NY", FALSE);
423:
424: if (ch == 'Y')
425: if (Player.p_gold < blessingcost)
426: ++cheat;
427: else
428: {
429: cheat = 0;
430: Player.p_gold -= blessingcost;
431: if (drandom() < 0.02)
432: dishonest = TRUE;
433: else
434: Player.p_blessing = TRUE;
435: }
436: break;
437: }
438: break;
439:
440: case 'S': /* sell gems */
441: mvprintw(15, 0, "A gem is worth %.0f gp. How many do you want to sell (%.0f max) ? ",
442: (double) N_GEMVALUE, Player.p_gems);
443: numitems = floor(infloat());
444:
445: if (numitems > Player.p_gems || numitems < 0)
446: ++cheat;
447: else
448: {
449: cheat = 0;
450: Player.p_gems -= numitems;
451: Player.p_gold += numitems * N_GEMVALUE;
452: }
453: }
454:
455: if (cheat == 1)
456: mvaddstr(17, 0, "Come on, merchants aren't stupid. Stop cheating.\n");
457: else if (cheat == 2)
458: {
459: mvaddstr(17, 0, "You had your chance. This merchant happens to be\n");
460: printw("a %.0f level magic user, and you made %s mad!\n",
461: ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her");
462: altercoordinates(0.0, 0.0, A_FAR);
463: Player.p_energy /= 2.0;
464: ++Player.p_sin;
465: more(23);
466: return;
467: }
468: else if (dishonest)
469: {
470: mvaddstr(17, 0, "The merchant stole your money!");
471: refresh();
472: altercoordinates(Player.p_x - Player.p_x / 10.0,
473: Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
474: sleep(2);
475: return;
476: }
477: }
478: }
479: /**/
480: /************************************************************************
481: /
482: / FUNCTION NAME: displaystats()
483: /
484: / FUNCTION: print out important player statistics
485: /
486: / AUTHOR: E. A. Estes, 12/4/85
487: /
488: / ARGUMENTS: none
489: /
490: / RETURN VALUE: none
491: /
492: / MODULES CALLED: descrstatus(), descrlocation(), mvprintw()
493: /
494: / GLOBAL INPUTS: Users, Player
495: /
496: / GLOBAL OUTPUTS: none
497: /
498: / DESCRIPTION:
499: / Important player statistics are printed on the screen.
500: /
501: /************************************************************************/
502:
503: displaystats()
504: {
505: mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
506: mvprintw(1, 0, "Level :%7.0f Energy :%9.0f(%9.0f) Mana :%9.0f Users:%3d\n",
507: Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
508: Player.p_mana, Users);
509: mvprintw(2, 0, "Quick :%3.0f(%3.0f) Strength:%9.0f(%9.0f) Gold :%9.0f %s\n",
510: Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
511: Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
512: }
513: /**/
514: /************************************************************************
515: /
516: / FUNCTION NAME: allstatslist()
517: /
518: / FUNCTION: show player items
519: /
520: / AUTHOR: E. A. Estes, 12/4/85
521: /
522: / ARGUMENTS: none
523: /
524: / RETURN VALUE: none
525: /
526: / MODULES CALLED: mvprintw(), descrtype()
527: /
528: / GLOBAL INPUTS: Player
529: /
530: / GLOBAL OUTPUTS: none
531: /
532: / DESCRIPTION:
533: / Print out some player statistics of lesser importance.
534: /
535: /************************************************************************/
536:
537: allstatslist()
538: {
539: static char *flags[] = /* to print value of some bools */
540: {
541: "False",
542: " True"
543: };
544:
545: mvprintw( 8, 0, "Type: %s\n", descrtype(&Player, FALSE));
546:
547: mvprintw(10, 0, "Experience: %9.0f", Player.p_experience);
548: mvprintw(11, 0, "Brains : %9.0f", Player.p_brains);
549: mvprintw(12, 0, "Magic Lvl : %9.0f", Player.p_magiclvl);
550: mvprintw(13, 0, "Sin : %9.5f", Player.p_sin);
551: mvprintw(14, 0, "Poison : %9.5f", Player.p_poison);
552: mvprintw(15, 0, "Gems : %9.0f", Player.p_gems);
553: mvprintw(16, 0, "Age : %9d", Player.p_age);
554: mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
555: mvprintw(11, 40, "Amulets : %9d", Player.p_amulets);
556: mvprintw(12, 40, "Charms : %9d", Player.p_charms);
557: mvprintw(13, 40, "Crowns : %9d", Player.p_crowns);
558: mvprintw(14, 40, "Shield : %9.0f", Player.p_shield);
559: mvprintw(15, 40, "Sword : %9.0f", Player.p_sword);
560: mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
561:
562: mvprintw(18, 0, "Blessing: %s Ring: %s Virgin: %s Palantir: %s",
563: flags[Player.p_blessing], flags[Player.p_ring.ring_type != R_NONE],
564: flags[Player.p_virgin], flags[Player.p_palantir]);
565: }
566: /**/
567: /************************************************************************
568: /
569: / FUNCTION NAME: descrtype()
570: /
571: / FUNCTION: return a string specifying player type
572: /
573: / AUTHOR: E. A. Estes, 12/4/85
574: /
575: / ARGUMENTS:
576: / struct player playerp - pointer to structure for player
577: / bool shortflag - set if short form is desired
578: /
579: / RETURN VALUE: pointer to string describing player type
580: /
581: / MODULES CALLED: strcpy()
582: /
583: / GLOBAL INPUTS: Databuf[]
584: /
585: / GLOBAL OUTPUTS: Databuf[]
586: /
587: / DESCRIPTION:
588: / Return a string describing the player type.
589: / King, council, valar, supercedes other types.
590: / The first character of the string is '*' if the player
591: / has a crown.
592: / If 'shortflag' is TRUE, return a 3 character string.
593: /
594: /************************************************************************/
595:
596: char *
597: descrtype(playerp, shortflag)
598: struct player *playerp;
599: bool shortflag;
600: {
601: register int type; /* for caluculating result subscript */
602: static char *results[] = /* description table */
603: {
604: " Magic User", " MU",
605: " Fighter", " F ",
606: " Elf", " E ",
607: " Dwarf", " D ",
608: " Halfling", " H ",
609: " Experimento", " EX",
610: " Super", " S ",
611: " King", " K ",
612: " Council of Wise", " CW",
613: " Ex-Valar", " EV",
614: " Valar", " V ",
615: " ? ", " ? "
616: };
617:
618: type = playerp->p_type;
619:
620: switch (playerp->p_specialtype)
621: {
622: case SC_NONE:
623: type = playerp->p_type;
624: break;
625:
626: case SC_KING:
627: type = 7;
628: break;
629:
630: case SC_COUNCIL:
631: type = 8;
632: break;
633:
634: case SC_EXVALAR:
635: type = 9;
636: break;
637:
638: case SC_VALAR:
639: type = 10;
640: break;
641: }
642:
643: type *= 2; /* calculate offset */
644:
645: if (type > 20)
646: /* error */
647: type = 22;
648:
649: if (shortflag)
650: /* use short descriptions */
651: ++type;
652:
653: if (playerp->p_crowns > 0)
654: {
655: strcpy(Databuf, results[type]);
656: Databuf[0] = '*';
657: return(Databuf);
658: }
659: else
660: return(results[type]);
661: }
662: /**/
663: /************************************************************************
664: /
665: / FUNCTION NAME: findname()
666: /
667: / FUNCTION: find location in player file of given name
668: /
669: / AUTHOR: E. A. Estes, 12/4/85
670: /
671: / ARGUMENTS:
672: / char *name - name of character to look for
673: / struct player *playerp - pointer of structure to fill
674: /
675: / RETURN VALUE: location of player if found, -1 otherwise
676: /
677: / MODULES CALLED: fread(), fseek(), strcmp()
678: /
679: / GLOBAL INPUTS: Wizard, *Playersfp
680: /
681: / GLOBAL OUTPUTS: none
682: /
683: / DESCRIPTION:
684: / Search the player file for the player of the given name.
685: / If player is found, fill structure with player data.
686: /
687: /************************************************************************/
688:
689: long
690: findname(name, playerp)
691: register char *name;
692: register struct player *playerp;
693: {
694: long loc = 0; /* location in the file */
695:
696: fseek(Playersfp, 0L, 0);
697: while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
698: {
699: if (strcmp(playerp->p_name, name) == 0)
700: {
701: if (playerp->p_status != S_NOTUSED || Wizard)
702: /* found it */
703: return(loc);
704: }
705: loc += SZ_PLAYERSTRUCT;
706: }
707:
708: return(-1);
709: }
710: /**/
711: /************************************************************************
712: /
713: / FUNCTION NAME: allocrecord()
714: /
715: / FUNCTION: find space in the player file for a new character
716: /
717: / AUTHOR: E. A. Estes, 12/4/85
718: /
719: / ARGUMENTS: none
720: /
721: / RETURN VALUE: location of free space in file
722: /
723: / MODULES CALLED: initplayer(), writerecord(), fread(), fseek()
724: /
725: / GLOBAL INPUTS: Other, *Playersfp
726: /
727: / GLOBAL OUTPUTS: Player
728: /
729: / DESCRIPTION:
730: / Search the player file for an unused entry. If none are found,
731: / make one at the end of the file.
732: /
733: /************************************************************************/
734:
735: long
736: allocrecord()
737: {
738: long loc = 0L; /* location in file */
739:
740: fseek(Playersfp, 0L, 0);
741: while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
742: {
743: if (Other.p_status == S_NOTUSED)
744: /* found an empty record */
745: return(loc);
746: else
747: loc += SZ_PLAYERSTRUCT;
748: }
749:
750: /* make a new record */
751: initplayer(&Other);
752: Player.p_status = S_OFF;
753: writerecord(&Other, loc);
754:
755: return(loc);
756: }
757: /**/
758: /************************************************************************
759: /
760: / FUNCTION NAME: freerecord()
761: /
762: / FUNCTION: free up a record on the player file
763: /
764: / AUTHOR: E. A. Estes, 2/7/86
765: /
766: / ARGUMENTS:
767: / struct player playerp - pointer to structure to free
768: / long loc - location in file to free
769: /
770: / RETURN VALUE: none
771: /
772: / MODULES CALLED: writerecord()
773: /
774: / GLOBAL INPUTS: none
775: /
776: / GLOBAL OUTPUTS: none
777: /
778: / DESCRIPTION:
779: / Mark structure as not used, and update player file.
780: /
781: /************************************************************************/
782:
783: freerecord(playerp, loc)
784: struct player *playerp;
785: long loc;
786: {
787: playerp->p_name[0] = CH_MARKDELETE;
788: playerp->p_status = S_NOTUSED;
789: writerecord(playerp, loc);
790: }
791: /**/
792: /************************************************************************
793: /
794: / FUNCTION NAME: leavegame()
795: /
796: / FUNCTION: leave game
797: /
798: / AUTHOR: E. A. Estes, 12/4/85
799: /
800: / ARGUMENTS: none
801: /
802: / RETURN VALUE: none
803: /
804: / MODULES CALLED: freerecord(), writerecord(), cleanup()
805: /
806: / GLOBAL INPUTS: Player, Fileloc
807: /
808: / GLOBAL OUTPUTS: Player
809: /
810: / DESCRIPTION:
811: / Mark player as inactive, and cleanup.
812: / Do not save players below level 1.
813: /
814: /************************************************************************/
815:
816: leavegame()
817: {
818:
819: if (Player.p_level < 1.0)
820: /* delete character */
821: freerecord(&Player, Fileloc);
822: else
823: {
824: Player.p_status = S_OFF;
825: writerecord(&Player, Fileloc);
826: }
827:
828: cleanup(TRUE);
829: /*NOTREACHED*/
830: }
831: /**/
832: /************************************************************************
833: /
834: / FUNCTION NAME: death()
835: /
836: / FUNCTION: death routine
837: /
838: / AUTHOR: E. A. Estes, 12/4/85
839: /
840: / ARGUMENTS:
841: / char *how - pointer to string describing cause of death
842: /
843: / RETURN VALUE: none
844: /
845: / MODULES CALLED: freerecord(), enterscore(), more(), exit(), fread(),
846: / fseek(), execl(), fopen(), floor(), wmove(), drandom(), wclear(), strcmp(),
847: / fwrite(), fflush(), printw(), strcpy(), fclose(), waddstr(), cleanup(),
848: / fprintf(), wrefresh(), getanswer(), descrtype()
849: /
850: / GLOBAL INPUTS: Curmonster, Wizard, Player, *stdscr, Fileloc, *Monstfp
851: /
852: / GLOBAL OUTPUTS: Player
853: /
854: / DESCRIPTION:
855: / Kill off current player.
856: / Handle rings, and multiple lives.
857: / Print an appropriate message.
858: / Update scoreboard, lastdead, and let other players know about
859: / the demise of their comrade.
860: /
861: /************************************************************************/
862:
863: death(how)
864: char *how;
865: {
866: FILE *fp; /* for updating various files */
867: int ch; /* input */
868: static char *deathmesg[] =
869: /* add more messages here, if desired */
870: {
871: "You have been wounded beyond repair. ",
872: "You have been disemboweled. ",
873: "You've been mashed, mauled, and spit upon. (You're dead.)\n",
874: "You died! ",
875: "You're a complete failure -- you've died!!\n",
876: "You have been dealt a fatal blow! "
877: };
878:
879: clear();
880:
881: if (strcmp(how, "Stupidity") != 0)
882: {
883: if (Player.p_level > 9999.0)
884: /* old age */
885: addstr("Characters must be retired upon reaching level 10000. Sorry.");
886: else if (Player.p_lives > 0)
887: /* extra lives */
888: {
889: addstr("You should be more cautious. You've been killed.\n");
890: printw("You only have %d more chance(s).\n", --Player.p_lives);
891: more(3);
892: Player.p_energy = Player.p_maxenergy;
893: return;
894: }
895: else if (Player.p_specialtype == SC_VALAR)
896: {
897: addstr("You had your chances, but Valar aren't totally\n");
898: addstr("immortal. You are now left to wither and die . . .\n");
899: more(3);
900: Player.p_brains = Player.p_level / 25.0;
901: Player.p_energy = Player.p_maxenergy /= 5.0;
902: Player.p_quksilver = Player.p_sword = 0.0;
903: Player.p_specialtype = SC_COUNCIL;
904: return;
905: }
906: else if (Player.p_ring.ring_inuse &&
907: (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
908: /* good ring in use - saved from death */
909: {
910: mvaddstr(4, 0, "Your ring saved you from death!\n");
911: refresh();
912: Player.p_ring.ring_type = R_NONE;
913: Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
914: if (Player.p_crowns > 0)
915: --Player.p_crowns;
916: return;
917: }
918: else if (Player.p_ring.ring_type == R_BAD
919: || Player.p_ring.ring_type == R_SPOILED)
920: /* bad ring in possession; name idiot after player */
921: {
922: mvaddstr(4, 0,
923: "Your ring has taken control of you and turned you into a monster!\n");
924: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
925: fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
926: strcpy(Curmonster.m_name, Player.p_name);
927: fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
928: fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
929: fflush(Monstfp);
930: }
931: }
932:
933: enterscore(); /* update score board */
934:
935: /* put info in last dead file */
936: fp = fopen(_PATH_LASTDEAD, "w");
937: fprintf(fp,"%s (%s, run by %s, level %.0f, killed by %s)",
938: Player.p_name, descrtype(&Player, TRUE),
939: Player.p_login, Player.p_level, how);
940: fclose(fp);
941:
942: /* let other players know */
943: fp = fopen(_PATH_MESS, "w");
944: fprintf(fp, "%s was killed by %s.", Player.p_name, how);
945: fclose(fp);
946:
947: freerecord(&Player, Fileloc);
948:
949: clear();
950: move(10, 0);
951: addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
952: addstr("Care to give it another try ? ");
953: ch = getanswer("NY", FALSE);
954:
955: if (ch == 'Y')
956: {
957: cleanup(FALSE);
958: execl(_PATH_GAMEPROG, "phantasia", "-s",
959: (Wizard ? "-S": (char *) NULL), 0);
960: exit(0);
961: /*NOTREACHED*/
962: }
963:
964: cleanup(TRUE);
965: /*NOTREACHED*/
966: }
967: /**/
968: /************************************************************************
969: /
970: / FUNCTION NAME: writerecord()
971: /
972: / FUNCTION: update structure in player file
973: /
974: / AUTHOR: E. A. Estes, 12/4/85
975: /
976: / ARGUMENTS:
977: / struct player *playerp - pointer to structure to write out
978: / long place - location in file to updata
979: /
980: / RETURN VALUE: none
981: /
982: / MODULES CALLED: fseek(), fwrite(), fflush()
983: /
984: / GLOBAL INPUTS: *Playersfp
985: /
986: / GLOBAL OUTPUTS: none
987: /
988: / DESCRIPTION:
989: / Update location in player file with given structure.
990: /
991: /************************************************************************/
992:
993: writerecord(playerp, place)
994: register struct player *playerp;
995: long place;
996: {
997: fseek(Playersfp, place, 0);
998: fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
999: fflush(Playersfp);
1000: }
1001: /**/
1002: /************************************************************************
1003: /
1004: / FUNCTION NAME: explevel()
1005: /
1006: / FUNCTION: calculate level based upon experience
1007: /
1008: / AUTHOR: E. A. Estes, 12/4/85
1009: /
1010: / ARGUMENTS:
1011: / double experience - experience to calculate experience level from
1012: /
1013: / RETURN VALUE: experience level
1014: /
1015: / MODULES CALLED: pow(), floor()
1016: /
1017: / GLOBAL INPUTS: none
1018: /
1019: / GLOBAL OUTPUTS: none
1020: /
1021: / DESCRIPTION:
1022: / Experience level is a geometric progression. This has been finely
1023: / tuned over the years, and probably should not be changed.
1024: /
1025: /************************************************************************/
1026:
1027: double
1028: explevel(experience)
1029: double experience;
1030: {
1031: if (experience < 1.1e7)
1032: return(floor(pow((experience / 1000.0), 0.4875)));
1033: else
1034: return(floor(pow((experience / 1250.0), 0.4865)));
1035: }
1036: /**/
1037: /************************************************************************
1038: /
1039: / FUNCTION NAME: truncstring()
1040: /
1041: / FUNCTION: truncate trailing blanks off a string
1042: /
1043: / AUTHOR: E. A. Estes, 12/4/85
1044: /
1045: / ARGUMENTS:
1046: / char *string - pointer to null terminated string
1047: /
1048: / RETURN VALUE: none
1049: /
1050: / MODULES CALLED: strlen()
1051: /
1052: / GLOBAL INPUTS: none
1053: /
1054: / GLOBAL OUTPUTS: none
1055: /
1056: / DESCRIPTION:
1057: / Put nul characters in place of spaces at the end of the string.
1058: /
1059: /************************************************************************/
1060:
1061: truncstring(string)
1062: register char *string;
1063: {
1064: register int length; /* length of string */
1065:
1066: length = strlen(string);
1067: while (string[--length] == ' ')
1068: string[length] = '\0';
1069: }
1070: /**/
1071: /************************************************************************
1072: /
1073: / FUNCTION NAME: altercoordinates()
1074: /
1075: / FUNCTION: Alter x, y coordinates and set/check location flags
1076: /
1077: / AUTHOR: E. A. Estes, 12/16/85
1078: /
1079: / ARGUMENTS:
1080: / double xnew, ynew - new x, y coordinates
1081: / int operation - operation to perform with coordinates
1082: /
1083: / RETURN VALUE: none
1084: /
1085: / MODULES CALLED: fabs(), floor(), drandom(), distance()
1086: /
1087: / GLOBAL INPUTS: Circle, Beyond, Player
1088: /
1089: / GLOBAL OUTPUTS: Marsh, Circle, Beyond, Throne, Player, Changed
1090: /
1091: / DESCRIPTION:
1092: / This module is called whenever the player's coordinates are altered.
1093: / If the player is beyond the point of no return, he/she is forced
1094: / to stay there.
1095: /
1096: /************************************************************************/
1097:
1098: altercoordinates(xnew, ynew, operation)
1099: double xnew;
1100: double ynew;
1101: int operation;
1102: {
1103: switch (operation)
1104: {
1105: case A_FORCED: /* move with no checks */
1106: break;
1107:
1108: case A_NEAR: /* pick random coordinates near */
1109: xnew = Player.p_x + ROLL(1.0, 5.0);
1110: ynew = Player.p_y - ROLL(1.0, 5.0);
1111: /* fall through for check */
1112:
1113: case A_SPECIFIC: /* just move player */
1114: if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
1115: /*
1116: * cannot move back from point of no return
1117: * pick the largest coordinate to remain unchanged
1118: */
1119: {
1120: if (fabs(xnew) > fabs(ynew))
1121: xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
1122: else
1123: ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
1124: }
1125: break;
1126:
1127: case A_FAR: /* pick random coordinates far */
1128: xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
1129: ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
1130: break;
1131: }
1132:
1133: /* now set location flags and adjust coordinates */
1134: Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
1135:
1136: /* set up flags based upon location */
1137: Throne = Marsh = Beyond = FALSE;
1138:
1139: if (Player.p_x == 0.0 && Player.p_y == 0.0)
1140: Throne = TRUE;
1141: else if (Circle < 35 && Circle >= 20)
1142: Marsh = TRUE;
1143: else if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
1144: Beyond = TRUE;
1145:
1146: Changed = TRUE;
1147: }
1148: /**/
1149: /************************************************************************
1150: /
1151: / FUNCTION NAME: readrecord()
1152: /
1153: / FUNCTION: read a player structure from file
1154: /
1155: / AUTHOR: E. A. Estes, 12/4/85
1156: /
1157: / ARGUMENTS:
1158: / struct player *playerp - pointer to structure to fill
1159: / int loc - location of record to read
1160: /
1161: / RETURN VALUE: none
1162: /
1163: / MODULES CALLED: fread(), fseek()
1164: /
1165: / GLOBAL INPUTS: *Playersfp
1166: /
1167: / GLOBAL OUTPUTS: none
1168: /
1169: / DESCRIPTION:
1170: / Read structure information from player file.
1171: /
1172: /************************************************************************/
1173:
1174: readrecord(playerp, loc)
1175: register struct player *playerp;
1176: long loc;
1177: {
1178: fseek(Playersfp, loc, 0);
1179: fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
1180: }
1181: /**/
1182: /************************************************************************
1183: /
1184: / FUNCTION NAME: adjuststats()
1185: /
1186: / FUNCTION: adjust player statistics
1187: /
1188: / AUTHOR: E. A. Estes, 12/4/85
1189: /
1190: / ARGUMENTS: none
1191: /
1192: / RETURN VALUE: none
1193: /
1194: / MODULES CALLED: death(), floor(), drandom(), explevel(), movelevel()
1195: /
1196: / GLOBAL INPUTS: Player, *Statptr
1197: /
1198: / GLOBAL OUTPUTS: Circle, Player, Timeout
1199: /
1200: / DESCRIPTION:
1201: / Handle adjustment and maximums on various player characteristics.
1202: /
1203: /************************************************************************/
1204:
1205: adjuststats()
1206: {
1207: double dtemp; /* for temporary calculations */
1208:
1209: if (explevel(Player.p_experience) > Player.p_level)
1210: /* move one or more levels */
1211: {
1212: movelevel();
1213: if (Player.p_level > 5.0)
1214: Timeout = TRUE;
1215: }
1216:
1217: if (Player.p_specialtype == SC_VALAR)
1218: /* valar */
1219: Circle = Player.p_level / 5.0;
1220:
1221: /* calculate effective quickness */
1222: dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
1223: - Player.p_level;;
1224: dtemp = MAX(0.0, dtemp); /* gold slows player down */
1225: Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
1226:
1227: /* calculate effective strength */
1228: if (Player.p_poison > 0.0)
1229: /* poison makes player weaker */
1230: {
1231: dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
1232: dtemp = MAX(0.1, dtemp);
1233: }
1234: else
1235: dtemp = 1.0;
1236: Player.p_might = dtemp * Player.p_strength + Player.p_sword;
1237:
1238: /* insure that important things are within limits */
1239: Player.p_quksilver = MIN(99.0, Player.p_quksilver);
1240: Player.p_mana = MIN(Player.p_mana,
1241: Player.p_level * Statptr->c_maxmana + 1000.0);
1242: Player.p_brains = MIN(Player.p_brains,
1243: Player.p_level * Statptr->c_maxbrains + 200.0);
1244: Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
1245:
1246: /*
1247: * some implementations have problems with floating point compare
1248: * we work around it with this stuff
1249: */
1250: Player.p_gold = floor(Player.p_gold) + 0.1;
1251: Player.p_gems = floor(Player.p_gems) + 0.1;
1252: Player.p_mana = floor(Player.p_mana) + 0.1;
1253:
1254: if (Player.p_ring.ring_type != R_NONE)
1255: /* do ring things */
1256: {
1257: /* rest to max */
1258: Player.p_energy = Player.p_maxenergy + Player.p_shield;
1259:
1260: if (Player.p_ring.ring_duration <= 0)
1261: /* clean up expired rings */
1262: switch (Player.p_ring.ring_type)
1263: {
1264: case R_BAD: /* ring drives player crazy */
1265: Player.p_ring.ring_type = R_SPOILED;
1266: Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
1267: break;
1268:
1269: case R_NAZREG: /* ring disappears */
1270: Player.p_ring.ring_type = R_NONE;
1271: break;
1272:
1273: case R_SPOILED: /* ring kills player */
1274: death("A cursed ring");
1275: break;
1276:
1277: case R_DLREG: /* this ring doesn't expire */
1278: Player.p_ring.ring_duration = 0;
1279: break;
1280: }
1281: }
1282:
1283: if (Player.p_age / N_AGE > Player.p_degenerated)
1284: /* age player slightly */
1285: {
1286: ++Player.p_degenerated;
1287: if (Player.p_quickness > 23.0)
1288: Player.p_quickness *= 0.99;
1289: Player.p_strength *= 0.97;
1290: Player.p_brains *= 0.95;
1291: Player.p_magiclvl *= 0.97;
1292: Player.p_maxenergy *= 0.95;
1293: Player.p_quksilver *= 0.95;
1294: Player.p_sword *= 0.93;
1295: Player.p_shield *= 0.93;
1296: }
1297: }
1298: /**/
1299: /************************************************************************
1300: /
1301: / FUNCTION NAME: initplayer()
1302: /
1303: / FUNCTION: initialize a character
1304: /
1305: / AUTHOR: E. A. Estes, 12/4/85
1306: /
1307: / ARGUMENTS:
1308: / struct player *playerp - pointer to structure to init
1309: /
1310: / RETURN VALUE: none
1311: /
1312: / MODULES CALLED: floor(), drandom()
1313: /
1314: / GLOBAL INPUTS: none
1315: /
1316: / GLOBAL OUTPUTS: none
1317: /
1318: / DESCRIPTION:
1319: / Put a bunch of default values in the given structure.
1320: /
1321: /************************************************************************/
1322:
1323: initplayer(playerp)
1324: register struct player *playerp;
1325: {
1326: playerp->p_experience =
1327: playerp->p_level =
1328: playerp->p_strength =
1329: playerp->p_sword =
1330: playerp->p_might =
1331: playerp->p_energy =
1332: playerp->p_maxenergy =
1333: playerp->p_shield =
1334: playerp->p_quickness =
1335: playerp->p_quksilver =
1336: playerp->p_speed =
1337: playerp->p_magiclvl =
1338: playerp->p_mana =
1339: playerp->p_brains =
1340: playerp->p_poison =
1341: playerp->p_gems =
1342: playerp->p_sin =
1343: playerp->p_1scratch =
1344: playerp->p_2scratch = 0.0;
1345:
1346: playerp->p_gold = ROLL(50.0, 75.0) + 0.1; /* give some gold */
1347:
1348: playerp->p_x = ROLL(-125.0, 251.0);
1349: playerp->p_y = ROLL(-125.0, 251.0); /* give random x, y */
1350:
1351: /* clear ring */
1352: playerp->p_ring.ring_type = R_NONE;
1353: playerp->p_ring.ring_duration = 0;
1354: playerp->p_ring.ring_inuse = FALSE;
1355:
1356: playerp->p_age = 0L;
1357:
1358: playerp->p_degenerated = 1; /* don't degenerate initially */
1359:
1360: playerp->p_type = C_FIGHTER; /* default */
1361: playerp->p_specialtype = SC_NONE;
1362: playerp->p_lives =
1363: playerp->p_crowns =
1364: playerp->p_charms =
1365: playerp->p_amulets =
1366: playerp->p_holywater =
1367: playerp->p_lastused = 0;
1368: playerp->p_status = S_NOTUSED;
1369: playerp->p_tampered = T_OFF;
1370: playerp->p_istat = I_OFF;
1371:
1372: playerp->p_palantir =
1373: playerp->p_blessing =
1374: playerp->p_virgin =
1375: playerp->p_blindness = FALSE;
1376:
1377: playerp->p_name[0] =
1378: playerp->p_password[0] =
1379: playerp->p_login[0] = '\0';
1380: }
1381: /**/
1382: /************************************************************************
1383: /
1384: / FUNCTION NAME: readmessage()
1385: /
1386: / FUNCTION: read message from other players
1387: /
1388: / AUTHOR: E. A. Estes, 12/4/85
1389: /
1390: / ARGUMENTS: none
1391: /
1392: / RETURN VALUE: none
1393: /
1394: / MODULES CALLED: fseek(), fgets(), wmove(), waddstr(), wclrtoeol()
1395: /
1396: / GLOBAL INPUTS: *stdscr, Databuf[], *Messagefp
1397: /
1398: / GLOBAL OUTPUTS: none
1399: /
1400: / DESCRIPTION:
1401: / If there is a message from other players, print it.
1402: /
1403: /************************************************************************/
1404:
1405: readmessage()
1406: {
1407: move(3, 0);
1408: clrtoeol();
1409: fseek(Messagefp, 0L, 0);
1410: if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
1411: addstr(Databuf);
1412: }
1413: /**/
1414: /************************************************************************
1415: /
1416: / FUNCTION NAME: error()
1417: /
1418: / FUNCTION: process evironment error
1419: /
1420: / AUTHOR: E. A. Estes, 12/4/85
1421: /
1422: / ARGUMENTS:
1423: / char *whichfile - pointer to name of file which caused error
1424: /
1425: / RETURN VALUE: none
1426: /
1427: / MODULES CALLED: wclear(), cleanup()
1428: /
1429: / GLOBAL INPUTS: errno, *stdscr, printw(), printf(), Windows
1430: /
1431: / GLOBAL OUTPUTS: none
1432: /
1433: / DESCRIPTION:
1434: / Print message about offending file, and exit.
1435: /
1436: /************************************************************************/
1437:
1438: error(whichfile)
1439: char *whichfile;
1440: {
1441: extern int errno;
1442: extern printw(), printf();
1443: int (*funcp)();
1444:
1445: if (Windows)
1446: {
1447: funcp = printw;
1448: clear();
1449: }
1450: else
1451: funcp = printf;
1452:
1453: (*funcp)("An unrecoverable error has occurred reading %s. (errno = %d)\n", whichfile, errno);
1454: (*funcp)("Please run 'setup' to determine the problem.\n");
1455: cleanup(TRUE);
1456: /*NOTREACHED*/
1457: }
1458: /**/
1459: /************************************************************************
1460: /
1461: / FUNCTION NAME: distance()
1462: /
1463: / FUNCTION: calculate distance between two points
1464: /
1465: / AUTHOR: E. A. Estes, 12/4/85
1466: /
1467: / ARGUMENTS:
1468: / double x1, y1 - x, y coordinates of first point
1469: / double x2, y2 - x, y coordinates of second point
1470: /
1471: / RETURN VALUE: distance between the two points
1472: /
1473: / MODULES CALLED: sqrt()
1474: /
1475: / GLOBAL INPUTS: none
1476: /
1477: / GLOBAL OUTPUTS: none
1478: /
1479: / DESCRIPTION:
1480: / This function is provided because someone's hypot() library function
1481: / fails if x1 == x2 && y1 == y2.
1482: /
1483: /************************************************************************/
1484:
1485: double
1486: distance(x1, x2, y1, y2)
1487: double x1, x2, y1, y2;
1488: {
1489: double deltax, deltay;
1490:
1491: deltax = x1 - x2;
1492: deltay = y1 - y2;
1493: return(sqrt(deltax * deltax + deltay * deltay));
1494: }
1495:
1496: /**/
1497: /************************************************************************
1498: /
1499: / FUNCTION NAME: ill_sig()
1500: /
1501: / FUNCTION: exit upon trapping an illegal signal
1502: /
1503: / AUTHOR: E. A. Estes, 12/4/85
1504: /
1505: / ARGUMENTS:
1506: / int whichsig - signal which occured to cause jump to here
1507: /
1508: / RETURN VALUE: none
1509: /
1510: / MODULES CALLED: wclear(), printw(), cleanup()
1511: /
1512: / GLOBAL INPUTS: *stdscr
1513: /
1514: / GLOBAL OUTPUTS: none
1515: /
1516: / DESCRIPTION:
1517: / When an illegal signal is caught, print a message, and cleanup.
1518: /
1519: /************************************************************************/
1520:
1521: ill_sig(whichsig)
1522: int whichsig;
1523: {
1524: clear();
1525: if (!(whichsig == SIGINT || whichsig == SIGQUIT))
1526: printw("Error: caught signal # %d.\n", whichsig);
1527: cleanup(TRUE);
1528: /*NOTREACHED*/
1529: }
1530: /**/
1531: /************************************************************************
1532: /
1533: / FUNCTION NAME: descrstatus()
1534: /
1535: / FUNCTION: return a string describing the player status
1536: /
1537: / AUTHOR: E. A. Estes, 3/3/86
1538: /
1539: / ARGUMENTS:
1540: / struct player playerp - pointer to player structure to describe
1541: /
1542: / RETURN VALUE: string describing player's status
1543: /
1544: / MODULES CALLED: none
1545: /
1546: / GLOBAL INPUTS: none
1547: /
1548: / GLOBAL OUTPUTS: none
1549: /
1550: / DESCRIPTION:
1551: / Return verbal description of player status.
1552: / If player status is S_PLAYING, check for low energy and blindness.
1553: /
1554: /************************************************************************/
1555:
1556: char *
1557: descrstatus(playerp)
1558: register struct player *playerp;
1559: {
1560: switch (playerp->p_status)
1561: {
1562: case S_PLAYING:
1563: if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
1564: return("Low Energy");
1565: else if (playerp->p_blindness)
1566: return("Blind");
1567: else
1568: return("In game");
1569:
1570: case S_CLOAKED:
1571: return("Cloaked");
1572:
1573: case S_INBATTLE:
1574: return("In Battle");
1575:
1576: case S_MONSTER:
1577: return("Encounter");
1578:
1579: case S_TRADING:
1580: return("Trading");
1581:
1582: case S_OFF:
1583: return("Off");
1584:
1585: case S_HUNGUP:
1586: return("Hung up");
1587:
1588: default:
1589: return("");
1590: }
1591: }
1592: /**/
1593: /************************************************************************
1594: /
1595: / FUNCTION NAME: drandom()
1596: /
1597: / FUNCTION: return a random floating point number from 0.0 < 1.0
1598: /
1599: / AUTHOR: E. A. Estes, 2/7/86
1600: /
1601: / ARGUMENTS: none
1602: /
1603: / RETURN VALUE: none
1604: /
1605: / MODULES CALLED: random()
1606: /
1607: / GLOBAL INPUTS: none
1608: /
1609: / GLOBAL OUTPUTS: none
1610: /
1611: / DESCRIPTION:
1612: / Convert random integer from library routine into a floating
1613: / point number, and divide by the largest possible random number.
1614: / We mask large integers with 32767 to handle sites that return
1615: / 31 bit random integers.
1616: /
1617: /************************************************************************/
1618:
1619: double
1620: drandom()
1621: {
1622: if (sizeof(int) != 2)
1623: /* use only low bits */
1624: return((double) (random() & 0x7fff) / 32768.0);
1625: else
1626: return((double) random() / 32768.0);
1627: }
1628: /**/
1629: /************************************************************************
1630: /
1631: / FUNCTION NAME: collecttaxes()
1632: /
1633: / FUNCTION: collect taxes from current player
1634: /
1635: / AUTHOR: E. A. Estes, 2/7/86
1636: /
1637: / ARGUMENTS:
1638: / double gold - amount of gold to tax
1639: / double gems - amount of gems to tax
1640: /
1641: / RETURN VALUE: none
1642: /
1643: / MODULES CALLED: fread(), fseek(), fopen(), floor(), fwrite(), fclose()
1644: /
1645: / GLOBAL INPUTS: Player
1646: /
1647: / GLOBAL OUTPUTS: Player
1648: /
1649: / DESCRIPTION:
1650: / Pay taxes on gold and gems. If the player does not have enough
1651: / gold to pay taxes on the added gems, convert some gems to gold.
1652: / Add taxes to tax data base; add remaining gold and gems to
1653: / player's cache.
1654: /
1655: /************************************************************************/
1656:
1657: collecttaxes(gold, gems)
1658: double gold;
1659: double gems;
1660: {
1661: FILE *fp; /* to update Goldfile */
1662: double dtemp; /* for temporary calculations */
1663: double taxes; /* tax liability */
1664:
1665: /* add to cache */
1666: Player.p_gold += gold;
1667: Player.p_gems += gems;
1668:
1669: /* calculate tax liability */
1670: taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
1671:
1672: if (Player.p_gold < taxes)
1673: /* not enough gold to pay taxes, must convert some gems to gold */
1674: {
1675: dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to convert */
1676:
1677: if (Player.p_gems >= dtemp)
1678: /* player has enough to convert */
1679: {
1680: Player.p_gems -= dtemp;
1681: Player.p_gold += dtemp * N_GEMVALUE;
1682: }
1683: else
1684: /* take everything; this should never happen */
1685: {
1686: Player.p_gold += Player.p_gems * N_GEMVALUE;
1687: Player.p_gems = 0.0;
1688: taxes = Player.p_gold;
1689: }
1690: }
1691:
1692: Player.p_gold -= taxes;
1693:
1694: if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
1695: /* update taxes */
1696: {
1697: dtemp = 0.0;
1698: fread((char *) &dtemp, sizeof(double), 1, fp);
1699: dtemp += floor(taxes);
1700: fseek(fp, 0L, 0);
1701: fwrite((char *) &dtemp, sizeof(double), 1, fp);
1702: fclose(fp);
1703: }
1704: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.