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