Make this compile with gcc40: rename variables so that they don't collide
[dragonfly.git] / games / phantasia / interplayer.c
CommitLineData
984263bc
MD
1/*
2 * interplayer.c - player to player routines for Phantasia
3 *
4 * $FreeBSD: src/games/phantasia/interplayer.c,v 1.6 1999/11/16 02:57:33 billf Exp $
1de703da 5 * $DragonFly: src/games/phantasia/interplayer.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
984263bc
MD
6 */
7
8#include <string.h>
9#include "include.h"
10
11/************************************************************************
12/
13/ FUNCTION NAME: checkbattle()
14/
15/ FUNCTION: check to see if current player should battle another
16/
17/ AUTHOR: E. A. Estes, 12/4/85
18/
19/ ARGUMENTS: none
20/
21/ RETURN VALUE: none
22/
23/ MODULES CALLED: battleplayer(), fread(), fseek()
24/
25/ GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
26/
27/ GLOBAL OUTPUTS: Users
28/
29/ DESCRIPTION:
30/ Seach player file for a foe at the same coordinates as the
31/ current player.
32/ Also update user count.
33/
34*************************************************************************/
35
36checkbattle()
37{
38long foeloc = 0L; /* location in file of person to fight */
39
40 Users = 0;
41 fseek(Playersfp, 0L, 0);
42
43 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
44 {
45 if (Other.p_status != S_OFF
46 && Other.p_status != S_NOTUSED
47 && Other.p_status != S_HUNGUP
48 && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
49 /* player is on and not a cloaked valar */
50 {
51 ++Users;
52
53 if (Player.p_x == Other.p_x
54 && Player.p_y == Other.p_y
55 /* same coordinates */
56 && foeloc != Fileloc
57 /* not self */
58 && Player.p_status == S_PLAYING
59 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
60 /* both are playing */
61 && Other.p_specialtype != SC_VALAR
62 && Player.p_specialtype != SC_VALAR)
63 /* neither is valar */
64 {
65 battleplayer(foeloc);
66 return;
67 }
68 }
69 foeloc += SZ_PLAYERSTRUCT;
70 }
71}
72/*\f*/
73/************************************************************************
74/
75/ FUNCTION NAME: battleplayer()
76/
77/ FUNCTION: inter-terminal battle with another player
78/
79/ AUTHOR: E. A. Estes, 2/15/86
80/
81/ ARGUMENTS:
82/ long foeplace - location in player file of person to battle
83/
84/ RETURN VALUE: none
85/
86/ MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(),
87/ displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(),
88/ myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(),
89/ getanswer(), wclrtoeol(), wclrtobot()
90/
91/ GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr,
92/ Fileloc, *Enemyname
93/
94/ GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
95/
96/ DESCRIPTION:
97/ Inter-terminal battle is a very fragile and slightly klugy thing.
98/ At any time, one player is master and the other is slave.
99/ We pick who is master first by speed and level. After that,
100/ the slave waits for the master to relinquish its turn, and
101/ the slave becomes master, and so on.
102/
103/ The items in the player structure which control the handshake are:
104/ p_tampered:
105/ master increments this to relinquish control
106/ p_istat:
107/ master sets this to specify particular action
108/ p_1scratch:
109/ set to total damage inflicted so far; changes to indicate action
110/
111*************************************************************************/
112
113battleplayer(foeplace)
114long foeplace;
115{
116double dtemp; /* for temporary calculations */
117double oldhits = 0.0; /* previous damage inflicted by foe */
118int loop; /* for timing out */
119int ch; /* input */
120short oldtampered; /* old value of foe's p_tampered */
121
122 Lines = 8;
123 Luckout = FALSE;
124 mvaddstr(4, 0, "Preparing for battle!\n");
125 refresh();
126
127#ifdef SYS5
128 flushinp();
129#endif
130
131 /* set up variables, file, etc. */
132 Player.p_status = S_INBATTLE;
133 Shield = Player.p_energy;
134
135 /* if p_tampered is not 0, someone else may try to change it (king, etc.) */
136 Player.p_tampered = oldtampered = 1;
137 Player.p_1scratch = 0.0;
138 Player.p_istat = I_OFF;
139
140 readrecord(&Other, foeplace);
141 if (fabs(Player.p_level - Other.p_level) > 20.0)
142 /* see if players are greatly mismatched */
143 {
144 dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
145 if (dtemp < -0.5)
146 /* foe outweighs this one */
147 Player.p_speed *= 2.0;
148 }
149
150 writerecord(&Player, Fileloc); /* write out all our info */
151
152 if (Player.p_blindness)
153 Enemyname = "someone";
154 else
155 Enemyname = Other.p_name;
156
157 mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level);
158 refresh();
159
160 for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
161 /* wait for foe to respond */
162 {
163 readrecord(&Other, foeplace);
164 sleep(1);
165 }
166
167 if (Other.p_status != S_INBATTLE)
168 /* foe did not respond */
169 {
170 mvprintw(5, 0, "%s is not responding.\n", Enemyname);
171 goto LEAVE;
172 }
173 /* else, we are ready to battle */
174
175 move(4, 0);
176 clrtoeol();
177
178 /*
179 * determine who is first master
180 * if neither player is faster, check level
181 * if neither level is greater, battle is not allowed
182 * (this should never happen, but we have to handle it)
183 */
184 if (Player.p_speed > Other.p_speed)
185 Foestrikes = FALSE;
186 else if (Other.p_speed > Player.p_speed)
187 Foestrikes = TRUE;
188 else if (Player.p_level > Other.p_level)
189 Foestrikes = FALSE;
190 else if (Other.p_level > Player.p_level)
191 Foestrikes = TRUE;
192 else
193 /* no one is faster */
194 {
195 printw("You can't fight %s yet.", Enemyname);
196 goto LEAVE;
197 }
198
199 for (;;)
200 {
201 displaystats();
202 readmessage();
203 mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */
204
205 if (!Foestrikes)
206 /* take action against foe */
207 myturn();
208 else
209 /* wait for foe to take action */
210 {
211 mvaddstr(4, 0, "Waiting...\n");
212 clrtoeol();
213 refresh();
214
215 for (loop = 0; loop < 20; ++loop)
216 /* wait for foe to act */
217 {
218 readrecord(&Other, foeplace);
219 if (Other.p_1scratch != oldhits)
220 /* p_1scratch changes to indicate action */
221 break;
222 else
223 /* wait and try again */
224 {
225 sleep(1);
226 addch('.');
227 refresh();
228 }
229 }
230
231 if (Other.p_1scratch == oldhits)
232 {
233 /* timeout */
234 mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
235 ch = getanswer("NY", FALSE);
236 move(22, 0);
237 clrtobot();
238 if (ch == 'Y')
239 continue;
240 else
241 break;
242 }
243 else
244 /* foe took action */
245 {
246 switch (Other.p_istat)
247 {
248 case I_RAN: /* foe ran away */
249 mvprintw(Lines++, 0, "%s ran away!", Enemyname);
250 break;
251
252 case I_STUCK: /* foe tried to run, but couldn't */
253 mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
254 break;
255
256 case I_BLEWIT: /* foe tried to luckout, but didn't */
257 mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
258 break;
259
260 default:
261 dtemp = Other.p_1scratch - oldhits;
262 mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
263 Shield -= dtemp;
264 break;
265 }
266
267 oldhits = Other.p_1scratch; /* keep track of old hits */
268
269 if (Other.p_tampered != oldtampered)
270 /* p_tampered changes to relinquish turn */
271 {
272 oldtampered = Other.p_tampered;
273 Foestrikes = FALSE;
274 }
275 }
276 }
277
278 /* decide what happens next */
279 refresh();
280 if (Lines > LINES - 2)
281 {
282 more(Lines);
283 move(Lines = 8, 0);
284 clrtobot();
285 }
286
287 if (Other.p_istat == I_KILLED || Shield < 0.0)
288 /* we died */
289 {
290 Shield = -2.0; /* insure this value is negative */
291 break;
292 }
293
294 if (Player.p_istat == I_KILLED)
295 /* we killed foe; award treasre */
296 {
297 mvprintw(Lines++, 0, "You killed %s!", Enemyname);
298 Player.p_experience += Other.p_experience;
299 Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
300 Player.p_amulets += Other.p_amulets;
301 Player.p_charms += Other.p_charms;
302 collecttaxes(Other.p_gold, Other.p_gems);
303 Player.p_sword = MAX(Player.p_sword, Other.p_sword);
304 Player.p_shield = MAX(Player.p_shield, Other.p_shield);
305 Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
306 if (Other.p_virgin && !Player.p_virgin)
307 {
308 mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? ");
309 if ((ch = getanswer("YN", FALSE)) == 'Y')
310 Player.p_virgin = TRUE;
311 else
312 {
313 ++Player.p_sin;
314 Player.p_experience += 8000.0;
315 }
316 }
317 sleep(3); /* give other person time to die */
318 break;
319 }
320 else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
321 /* either player ran away */
322 break;
323 }
324
325LEAVE:
326 /* clean up things and leave */
327 writerecord(&Player, Fileloc); /* update a final time */
328 altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
329 Player.p_energy = Shield; /* set energy to actual value */
330 Player.p_tampered = T_OFF; /* clear p_tampered */
331
332 more(Lines); /* pause */
333
334 move(4, 0);
335 clrtobot(); /* clear bottom area of screen */
336
337 if (Player.p_energy < 0.0)
338 /* we are dead */
339 death("Interterminal battle");
340}
341/*\f*/
342/************************************************************************
343/
344/ FUNCTION NAME: myturn()
345/
346/ FUNCTION: process players action against foe in battle
347/
348/ AUTHOR: E. A. Estes, 2/7/86
349/
350/ ARGUMENTS: none
351/
352/ RETURN VALUE: none
353/
354/ MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), drandom(),
355/ waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot()
356/
357/ GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout,
358/ *Enemyname
359/
360/ GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
361/
362/ DESCRIPTION:
363/ Take action action against foe, and decide who is master
364/ for next iteration.
365/
366*************************************************************************/
367
368myturn()
369{
370double dtemp; /* for temporary calculations */
371int ch; /* input */
372
373 mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
374 if (Luckout)
375 clrtoeol();
376 else
377 addstr("4:Luckout ");
378
379 ch = inputoption();
380 move(Lines = 8, 0);
381 clrtobot();
382
383 switch (ch)
384 {
385 default: /* fight */
386 dtemp = ROLL(2.0, Player.p_might);
387HIT:
388 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
389 Player.p_sin += 0.5;
390 Player.p_1scratch += dtemp;
391 Player.p_istat = I_OFF;
392 break;
393
394 case '2': /* run away */
395 Player.p_1scratch -= 1.0; /* change this to indicate action */
396 if (drandom() > 0.25)
397 {
398 mvaddstr(Lines++, 0, "You got away!");
399 Player.p_istat = I_RAN;
400 }
401 else
402 {
403 mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
404 Player.p_istat = I_STUCK;
405 }
406 break;
407
408 case '3': /* power blast */
409 dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
410 Player.p_mana -= dtemp;
411 dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
412 mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
413 goto HIT;
414
415 case '4': /* luckout */
416 if (Luckout || drandom() > 0.1)
417 {
418 if (Luckout)
419 mvaddstr(Lines++, 0, "You already tried that!");
420 else
421 {
422 mvaddstr(Lines++, 0, "Not this time . . .");
423 Luckout = TRUE;
424 }
425
426 Player.p_1scratch -= 1.0;
427 Player.p_istat = I_BLEWIT;
428 }
429 else
430 {
431 mvaddstr(Lines++, 0, "You just lucked out!");
432 Player.p_1scratch = Other.p_energy * 1.1;
433 }
434 break;
435 }
436
437 refresh();
438 Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */
439
440 if (Player.p_1scratch > Other.p_energy)
441 Player.p_istat = I_KILLED;
442 else if (drandom() * Player.p_speed < drandom() * Other.p_speed)
443 /* relinquish control */
444 {
445 ++Player.p_tampered;
446 Foestrikes = TRUE;
447 }
448
449 writerecord(&Player, Fileloc); /* let foe know what we did */
450}
451/*\f*/
452/************************************************************************
453/
454/ FUNCTION NAME: checktampered()
455/
456/ FUNCTION: check if current player has been tampered with
457/
458/ AUTHOR: E. A. Estes, 12/4/85
459/
460/ ARGUMENTS: none
461/
462/ RETURN VALUE: none
463/
464/ MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid()
465/
466/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
467/
468/ GLOBAL OUTPUTS: Enrgyvoid
469/
470/ DESCRIPTION:
471/ Check for energy voids, holy grail, and tampering by other
472/ players.
473/
474*************************************************************************/
475
476checktampered()
477{
478long loc = 0L; /* location in energy void file */
479
480 /* first check for energy voids */
481 fseek(Energyvoidfp, 0L, 0);
482 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
483 if (Enrgyvoid.ev_active
484 && Enrgyvoid.ev_x == Player.p_x
485 && Enrgyvoid.ev_y == Player.p_y)
486 /* sitting on one */
487 {
488 if (loc > 0L)
489 /* not the holy grail; inactivate energy void */
490 {
491 Enrgyvoid.ev_active = FALSE;
492 writevoid(&Enrgyvoid, loc);
493 tampered(T_NRGVOID, 0.0, 0.0);
494 }
495 else if (Player.p_status != S_CLOAKED)
496 /* holy grail */
497 tampered(T_GRAIL, 0.0, 0.0);
498 break;
499 }
500 else
501 loc += SZ_VOIDSTRUCT;
502
503 /* now check for other things */
504 readrecord(&Other, Fileloc);
505 if (Other.p_tampered != T_OFF)
506 tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
507}
508/*\f*/
509/************************************************************************
510/
511/ FUNCTION NAME: tampered()
512/
513/ FUNCTION: take care of tampering by other players
514/
515/ AUTHOR: E. A. Estes, 12/4/85
516/
517/ ARGUMENTS:
518/ int what - what type of tampering
519/ double arg1, arg2 - rest of tampering info
520/
521/ RETURN VALUE: none
522/
523/ MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(),
524/ floor(), wmove(), waddch(), drandom(), printw(), altercoordinates(),
525/ waddstr(), wrefresh(), encounter(), writevoid()
526/
527/ GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
528/
529/ GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
530/
531/ DESCRIPTION:
532/ Take care of energy voids, holy grail, decree and intervention
533/ action on current player.
534/
535*************************************************************************/
536
537tampered(what, arg1, arg2)
538int what;
539double arg1;
540double arg2;
541{
542long loc; /* location in file of other players */
543
544 Changed = TRUE;
545 move(4,0);
546
547 Player.p_tampered = T_OFF; /* no longer tampered with */
548
549 switch (what)
550 {
551 case T_NRGVOID:
552 addstr("You've hit an energy void !\n");
553 Player.p_mana /= 3.0;
554 Player.p_energy /= 2.0;
555 Player.p_gold = floor(Player.p_gold/1.25) + 0.1;
556 altercoordinates(0.0, 0.0, A_NEAR);
557 break;
558
559 case T_TRANSPORT:
560 addstr("The king transported you ! ");
561 if (Player.p_charms > 0)
562 {
563 addstr("But your charm saved you. . .\n");
564 --Player.p_charms;
565 }
566 else
567 {
568 altercoordinates(0.0, 0.0, A_FAR);
569 addch('\n');
570 }
571 break;
572
573 case T_BESTOW:
574 printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
575 Player.p_gold += arg1;
576 break;
577
578 case T_CURSED:
579 addstr("You've been cursed ! ");
580 if (Player.p_blessing)
581 {
582 addstr("But your blessing saved you. . .\n");
583 Player.p_blessing = FALSE;
584 }
585 else
586 {
587 addch('\n');
588 Player.p_poison += 2.0;
589 Player.p_energy = 10.0;
590 Player.p_maxenergy *= 0.95;
591 Player.p_status = S_PLAYING; /* no longer cloaked */
592 }
593 break;
594
595 case T_VAPORIZED:
596 addstr("You have been vaporized!\n");
597 more(7);
598 death("Vaporization");
599 break;
600
601 case T_MONSTER:
602 addstr("The Valar zapped you with a monster!\n");
603 more(7);
604 encounter((int) arg1);
605 return;
606
607 case T_BLESSED:
608 addstr("The Valar has blessed you!\n");
609 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
610 Player.p_mana += 500.0;
611 Player.p_strength += 0.5;
612 Player.p_brains += 0.5;
613 Player.p_magiclvl += 0.5;
614 Player.p_poison = MIN(0.5, Player.p_poison);
615 break;
616
617 case T_RELOCATE:
618 addstr("You've been relocated. . .\n");
619 altercoordinates(arg1, arg2, A_FORCED);
620 break;
621
622 case T_HEAL:
623 addstr("You've been healed!\n");
624 Player.p_poison -= 0.25;
625 Player.p_energy = Player.p_maxenergy + Player.p_shield;
626 break;
627
628 case T_EXVALAR:
629 addstr("You are no longer Valar!\n");
630 Player.p_specialtype = SC_COUNCIL;
631 break;
632
633 case T_GRAIL:
634 addstr("You have found The Holy Grail!!\n");
635 if (Player.p_specialtype < SC_COUNCIL)
636 /* must be council of wise to behold grail */
637 {
638 addstr("However, you are not experienced enough to behold it.\n");
639 Player.p_sin *= Player.p_sin;
640 Player.p_mana += 1000;
641 }
642 else if (Player.p_specialtype == SC_VALAR
643 || Player.p_specialtype == SC_EXVALAR)
644 {
645 addstr("You have made it to the position of Valar once already.\n");
646 addstr("The Grail is of no more use to you now.\n");
647 }
648 else
649 {
650 addstr("It is now time to see if you are worthy to behold it. . .\n");
651 refresh();
652 sleep(4);
653
654 if (drandom() / 2.0 < Player.p_sin)
655 {
656 addstr("You have failed!\n");
657 Player.p_strength =
658 Player.p_mana =
659 Player.p_energy =
660 Player.p_maxenergy =
661 Player.p_magiclvl =
662 Player.p_brains =
663 Player.p_experience =
664 Player.p_quickness = 1.0;
665
666 altercoordinates(1.0, 1.0, A_FORCED);
667 Player.p_level = 0.0;
668 }
669 else
670 {
671 addstr("You made to position of Valar!\n");
672 Player.p_specialtype = SC_VALAR;
673 Player.p_lives = 5;
674 fseek(Playersfp, 0L, 0);
675 loc = 0L;
676 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
677 /* search for existing valar */
678 if (Other.p_specialtype == SC_VALAR
679 && Other.p_status != S_NOTUSED)
680 /* found old valar */
681 {
682 Other.p_tampered = T_EXVALAR;
683 writerecord(&Other, loc);
684 break;
685 }
686 else
687 loc += SZ_PLAYERSTRUCT;
688 }
689 }
690
691 /* move grail to new location */
692 Enrgyvoid.ev_active = TRUE;
693 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
694 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
695 writevoid(&Enrgyvoid, 0L);
696 break;
697 }
698 refresh();
699 sleep(2);
700}
701/*\f*/
702/************************************************************************
703/
704/ FUNCTION NAME: userlist()
705/
706/ FUNCTION: print list of players and locations
707/
708/ AUTHOR: E. A. Estes, 2/28/86
709/
710/ ARGUMENTS:
711/ bool ingameflag - set if called while playing
712/
713/ RETURN VALUE: none
714/
715/ MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(),
716/ floor(), wmove(), printw(), waddstr(), distance(), wrefresh(),
717/ descrtype(), wclrtobot()
718/
719/ GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
720/
721/ GLOBAL OUTPUTS: none
722/
723/ DESCRIPTION:
724/ We can only see the coordinate of those closer to the origin
725/ from us.
726/ Kings and council of the wise can see and can be seen by everyone.
727/ Palantirs are good for seeing everyone; and the valar can use
728/ one to see through a 'cloak' spell.
729/ The valar has no coordinates, and is completely invisible if
730/ cloaked.
731/
732*************************************************************************/
733
734userlist(ingameflag)
735bool ingameflag;
736{
737int numusers = 0; /* number of users on file */
738
739 if (ingameflag && Player.p_blindness)
740 {
741 mvaddstr(8, 0, "You cannot see anyone.\n");
742 return;
743 }
744
745 fseek(Playersfp, 0L, 0);
746 mvaddstr(8, 0,
747 "Name X Y Lvl Type Login Status\n");
748
749 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
750 {
751 if (Other.p_status == S_NOTUSED
752 /* record is unused */
753 || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
754 /* cloaked valar */
755 {
756 if (!Wizard)
757 /* wizard can see everything on file */
758 continue;
759 }
760
761 ++numusers;
762
763 if (ingameflag &&
764 /* must be playing for the rest of these conditions */
765 (Player.p_specialtype >= SC_KING
766 /* kings and higher can see others */
767 || Other.p_specialtype >= SC_KING
768 /* kings and higher can be seen by others */
769 || Circle >= CIRCLE(Other.p_x, Other.p_y)
770 /* those nearer the origin can be seen */
771 || Player.p_palantir)
772 /* palantir enables one to see others */
773 && (Other.p_status != S_CLOAKED
774 || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
775 /* not cloaked; valar can see through cloak with a palantir */
776 && Other.p_specialtype != SC_VALAR)
777 /* not a valar */
778 /* coordinates should be printed */
779 printw("%-20s %8.0f %8.0f ",
780 Other.p_name, Other.p_x, Other.p_y);
781 else
782 /* cannot see player's coordinates */
783 printw("%-20s %19.19s ",
784 Other.p_name, descrlocation(&Other, TRUE));
785
786 printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
787 Other.p_login, descrstatus(&Other));
788
789 if ((numusers % (LINES - 10)) == 0)
790 {
791 more(LINES - 1);
792 move(9, 0);
793 clrtobot();
794 }
795 }
796
797 printw("Total players on file = %d\n", numusers);
798 refresh();
799}
800/*\f*/
801/************************************************************************
802/
803/ FUNCTION NAME: throneroom()
804/
805/ FUNCTION: king stuff upon entering throne
806/
807/ AUTHOR: E. A. Estes, 12/16/85
808/
809/ ARGUMENTS: none
810/
811/ RETURN VALUE: none
812/
813/ MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(),
814/ fwrite(), altercoordinates(), waddstr(), fprintf()
815/
816/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr,
817/ Enrgyvoid, *Playersfp
818/
819/ GLOBAL OUTPUTS: Other, Player, Changed
820/
821/ DESCRIPTION:
822/ If player is not already king, make him/her so if the old king
823/ is not playing.
824/ Clear energy voids with new king.
825/ Print 'decree' prompt.
826/
827*************************************************************************/
828
829throneroom()
830{
831FILE *fp; /* to clear energy voids */
832long loc = 0L; /* location of old king in player file */
833
834 if (Player.p_specialtype < SC_KING)
835 /* not already king -- assumes crown */
836 {
837 fseek(Playersfp, 0L, 0);
838 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
839 if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
840 /* found old king */
841 {
842 if (Other.p_status != S_OFF)
843 /* old king is playing */
844 {
845 mvaddstr( 4, 0, "The king is playing, so you cannot steal his throne\n");
846 altercoordinates(0.0, 0.0, A_NEAR);
847 move(6, 0);
848 return;
849 }
850 else
851 /* old king is not playing - remove him/her */
852 {
853 Other.p_specialtype = SC_NONE;
854 if (Other.p_crowns)
855 --Other.p_crowns;
856 writerecord(&Other, loc);
857 break;
858 }
859 }
860 else
861 loc += SZ_PLAYERSTRUCT;
862
863 /* make player new king */
864 Changed = TRUE;
865 Player.p_specialtype = SC_KING;
866 mvaddstr(4, 0, "You have become king!\n");
867
868 /* let everyone else know */
869 fp = fopen(_PATH_MESS, "w");
870 fprintf(fp, "All hail the new king!");
871 fclose(fp);
872
873 /* clear all energy voids; retain location of holy grail */
874 fseek(Energyvoidfp, 0L, 0);
875 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
876 fp = fopen(_PATH_VOID, "w");
877 fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
878 fclose(fp);
879 }
880
881 mvaddstr(6, 0, "0:Decree ");
882}
883/*\f*/
884/************************************************************************
885/
886/ FUNCTION NAME: dotampered()
887/
888/ FUNCTION: king and valar special options
889/
890/ AUTHOR: E. A. Estes, 2/28/86
891/
892/ ARGUMENTS: none
893/
894/ RETURN VALUE: none
895/
896/ MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(),
897/ floor(), wmove(), drandom(), fclose(), fwrite(), sscanf(), strcmp(),
898/ infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(),
899/ allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid()
900/
901/ GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr,
902/ Databuf[], Enrgyvoid
903/
904/ GLOBAL OUTPUTS: Other, Player, Enrgyvoid
905/
906/ DESCRIPTION:
907/ Tamper with other players. Handle king/valar specific options.
908/
909*************************************************************************/
910
911dotampered()
912{
913short tamper; /* value for tampering with other players */
914char *option; /* pointer to option description */
915double temp1 = 0.0, temp2 = 0.0; /* other tampering values */
916int ch; /* input */
917long loc; /* location in energy void file */
918FILE *fp; /* for opening gold file */
919
920 move(6, 0);
921 clrtoeol();
922 if (Player.p_specialtype < SC_COUNCIL && !Wizard)
923 /* king options */
924 {
925 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
926
927 ch = getanswer(" ", TRUE);
928 move(6, 0);
929 clrtoeol();
930 move(4, 0);
931 switch (ch)
932 {
933 case '1': /* transport someone */
934 tamper = T_TRANSPORT;
935 option = "transport";
936 break;
937
938 case '2': /* curse another */
939 tamper = T_CURSED;
940 option = "curse";
941 break;
942
943 case '3': /* create energy void */
944 if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT)
945 /* can only have 20 void active at once */
946 mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
947 else
948 {
949 addstr("Enter the X Y coordinates of void ? ");
950 getstring(Databuf, SZ_DATABUF);
951 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
952 Enrgyvoid.ev_x = floor(temp1);
953 Enrgyvoid.ev_y = floor(temp2);
954 Enrgyvoid.ev_active = TRUE;
955 writevoid(&Enrgyvoid, loc);
956 mvaddstr(5, 0, "It is done.\n");
957 }
958 return;
959
960 case '4': /* bestow gold to subject */
961 tamper = T_BESTOW;
962 addstr("How much gold to bestow ? ");
963 temp1 = infloat();
964 if (temp1 > Player.p_gold || temp1 < 0)
965 {
966 mvaddstr(5, 0, "You don't have that !\n");
967 return;
968 }
969
970 /* adjust gold after we are sure it will be given to someone */
971 option = "give gold to";
972 break;
973
974 case '5': /* collect accumulated taxes */
975 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
976 /* collect taxes */
977 {
978 fread((char *) &temp1, sizeof(double), 1, fp);
979 fseek(fp, 0L, 0);
980 /* clear out value */
981 temp2 = 0.0;
982 fwrite((char *) &temp2, sizeof(double), 1, fp);
983 fclose(fp);
984 }
985
986 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
987 Player.p_gold += floor(temp1);
988 return;
989
990 default:
991 return;
992 }
993 /* end of king options */
994 }
995 else
996 /* council of wise, valar, wizard options */
997 {
998 addstr("1:Heal ");
999 if (Player.p_palantir || Wizard)
1000 addstr("2:Seek Grail ");
1001 if (Player.p_specialtype == SC_VALAR || Wizard)
1002 addstr("3:Throw Monster 4:Relocate 5:Bless ");
1003 if (Wizard)
1004 addstr("6:Vaporize ");
1005
1006 ch = getanswer(" ", TRUE);
1007 if (!Wizard)
1008 {
1009 if (ch > '2' && Player.p_specialtype != SC_VALAR)
1010 {
1011 ILLCMD();
1012 return;
1013 }
1014
1015 if (Player.p_mana < MM_INTERVENE)
1016 {
1017 mvaddstr(5, 0, "No mana left.\n");
1018 return;
1019 }
1020 else
1021 Player.p_mana -= MM_INTERVENE;
1022 }
1023
1024 switch (ch)
1025 {
1026 case '1': /* heal another */
1027 tamper = T_HEAL;
1028 option = "heal";
1029 break;
1030
1031 case '2': /* seek grail */
1032 if (Player.p_palantir)
1033 /* need a palantir to seek */
1034 {
1035 fseek(Energyvoidfp, 0L, 0);
1036 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
1037 temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
1038 temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
1039 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
1040 }
1041 else
1042 /* no palantir */
1043 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
1044 return;
1045
1046 case '3': /* lob monster at someone */
1047 mvaddstr(4, 0, "Which monster [0-99] ? ");
1048 temp1 = infloat();
1049 temp1 = MAX(0.0, MIN(99.0, temp1));
1050 tamper = T_MONSTER;
1051 option = "throw a monster at";
1052 break;
1053
1054 case '4': /* move another player */
1055 mvaddstr(4, 0, "New X Y coordinates ? ");
1056 getstring(Databuf, SZ_DATABUF);
1057 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
1058 tamper = T_RELOCATE;
1059 option = "relocate";
1060 break;
1061
1062 case '5': /* bless a player */
1063 tamper = T_BLESSED;
1064 option = "bless";
1065 break;
1066
1067 case '6': /* kill off a player */
1068 if (Wizard)
1069 {
1070 tamper = T_VAPORIZED;
1071 option = "vaporize";
1072 break;
1073 }
1074 else
1075 return;
1076
1077 default:
1078 return;
1079 }
1080
1081 /* adjust age after we are sure intervention will be done */
1082 /* end of valar, etc. options */
1083 }
1084
1085 for (;;)
1086 /* prompt for player to affect */
1087 {
1088 mvprintw(4, 0, "Who do you want to %s ? ", option);
1089 getstring(Databuf, SZ_DATABUF);
1090 truncstring(Databuf);
1091
1092 if (Databuf[0] == '\0')
1093 userlist(TRUE);
1094 else
1095 break;
1096 }
1097
1098 if (strcmp(Player.p_name, Databuf) != 0)
1099 /* name other than self */
1100 {
1101 if ((loc = findname(Databuf, &Other)) >= 0L)
1102 {
1103 if (Other.p_tampered != T_OFF)
1104 {
1105 mvaddstr(5, 0, "That person has something pending already.\n");
1106 return;
1107 }
1108 else
1109 {
1110 if (tamper == T_RELOCATE
1111 && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
1112 && !Wizard)
1113 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
1114 else
1115 {
1116 if (tamper == T_BESTOW) Player.p_gold -= floor(temp1);
1117 if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
1118 tamper == T_RELOCATE || tamper == T_BLESSED))
1119 Player.p_age += N_AGE; /* age penalty */
1120 Other.p_tampered = tamper;
1121 Other.p_1scratch = floor(temp1);
1122 Other.p_2scratch = floor(temp2);
1123 writerecord(&Other, loc);
1124 mvaddstr(5, 0, "It is done.\n");
1125 }
1126 return;
1127 }
1128 }
1129 else
1130 /* player not found */
1131 mvaddstr(5, 0, "There is no one by that name.\n");
1132 }
1133 else
1134 /* self */
1135 mvaddstr(5, 0, "You may not do it to yourself!\n");
1136}
1137/*\f*/
1138/************************************************************************
1139/
1140/ FUNCTION NAME: writevoid()
1141/
1142/ FUNCTION: update energy void entry in energy void file
1143/
1144/ AUTHOR: E. A. Estes, 12/4/85
1145/
1146/ ARGUMENTS:
1147/ struct energyvoid *vp - pointer to structure to write to file
1148/ long loc - location in file to update
1149/
1150/ RETURN VALUE: none
1151/
1152/ MODULES CALLED: fseek(), fwrite(), fflush()
1153/
1154/ GLOBAL INPUTS: *Energyvoidfp
1155/
1156/ GLOBAL OUTPUTS: none
1157/
1158/ DESCRIPTION:
1159/ Write out energy void structure at specified location.
1160/
1161*************************************************************************/
1162
1163writevoid(vp, loc)
1164struct energyvoid *vp;
1165long loc;
1166{
1167
1168 fseek(Energyvoidfp, loc, 0);
1169 fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
1170 fflush(Energyvoidfp);
1171 fseek(Energyvoidfp, 0L, 0);
1172}
1173/*\f*/
1174/************************************************************************
1175/
1176/ FUNCTION NAME: allocvoid()
1177/
1178/ FUNCTION: allocate space for a new energy void
1179/
1180/ AUTHOR: E. A. Estes, 12/4/85
1181/
1182/ ARGUMENTS: none
1183/
1184/ RETURN VALUE: location of new energy void space
1185/
1186/ MODULES CALLED: fread(), fseek()
1187/
1188/ GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
1189/
1190/ GLOBAL OUTPUTS: none
1191/
1192/ DESCRIPTION:
1193/ Search energy void file for an inactive entry and return its
1194/ location.
1195/ If no inactive ones are found, return one more than last location.
1196/
1197*************************************************************************/
1198
1199long
1200allocvoid()
1201{
1202long loc = 0L; /* location of new energy void */
1203
1204 fseek(Energyvoidfp, 0L, 0);
1205 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
1206 if (Enrgyvoid.ev_active)
1207 loc += SZ_VOIDSTRUCT;
1208 else
1209 break;
1210
1211 return(loc);
1212}