Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / games / phantasia / interplayer.c
blob10c8c1d421125abba7cd26cbd153c744777ff89b
1 /* $NetBSD: interplayer.c,v 1.11 2009/08/12 08:21:41 dholland Exp $ */
3 /*
4 * interplayer.c - player to player routines for Phantasia
5 */
7 #include <math.h>
8 #include <setjmp.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
13 #include "macros.h"
14 #include "phantdefs.h"
15 #include "phantstruct.h"
16 #include "phantglobs.h"
17 #include "pathnames.h"
19 #undef bool
20 #include <curses.h>
22 static long allocvoid(void);
23 static void battleplayer(long);
24 static void myturn(void);
25 static void tampered(int, double, double);
27 void
28 checkbattle(void)
30 long foeloc = 0L; /* location in file of person to fight */
32 Users = 0;
33 fseek(Playersfp, 0L, SEEK_SET);
35 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
36 if (Other.p_status != S_OFF
37 && Other.p_status != S_NOTUSED
38 && Other.p_status != S_HUNGUP
39 && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
40 /* player is on and not a cloaked valar */
42 ++Users;
44 if (Player.p_x == Other.p_x
45 && Player.p_y == Other.p_y
46 /* same coordinates */
47 && foeloc != Fileloc
48 /* not self */
49 && Player.p_status == S_PLAYING
50 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
51 /* both are playing */
52 && Other.p_specialtype != SC_VALAR
53 && Player.p_specialtype != SC_VALAR)
54 /* neither is valar */
56 battleplayer(foeloc);
57 return;
60 foeloc += SZ_PLAYERSTRUCT;
64 static void
65 battleplayer(long foeplace)
67 double dtemp; /* for temporary calculations */
68 double oldhits = 0.0; /* previous damage inflicted by foe */
69 int loop; /* for timing out */
70 int ch; /* input */
71 short oldtampered; /* old value of foe's p_tampered */
73 Lines = 8;
74 Luckout = FALSE;
75 mvaddstr(4, 0, "Preparing for battle!\n");
76 refresh();
78 #ifdef SYS5
79 flushinp();
80 #endif
82 /* set up variables, file, etc. */
83 Player.p_status = S_INBATTLE;
84 Shield = Player.p_energy;
86 /* if p_tampered is not 0, someone else may try to change it (king,
87 * etc.) */
88 Player.p_tampered = oldtampered = 1;
89 Player.p_1scratch = 0.0;
90 Player.p_istat = I_OFF;
92 readrecord(&Other, foeplace);
93 if (fabs(Player.p_level - Other.p_level) > 20.0)
94 /* see if players are greatly mismatched */
96 dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
97 if (dtemp < -0.5)
98 /* foe outweighs this one */
99 Player.p_speed *= 2.0;
101 writerecord(&Player, Fileloc); /* write out all our info */
103 if (Player.p_blindness)
104 Enemyname = "someone";
105 else
106 Enemyname = Other.p_name;
108 mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level);
109 refresh();
111 for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
112 /* wait for foe to respond */
114 readrecord(&Other, foeplace);
115 sleep(1);
118 if (Other.p_status != S_INBATTLE)
119 /* foe did not respond */
121 mvprintw(5, 0, "%s is not responding.\n", Enemyname);
122 goto LEAVE;
124 /* else, we are ready to battle */
126 move(4, 0);
127 clrtoeol();
130 * determine who is first master
131 * if neither player is faster, check level
132 * if neither level is greater, battle is not allowed
133 * (this should never happen, but we have to handle it)
135 if (Player.p_speed > Other.p_speed)
136 Foestrikes = FALSE;
137 else
138 if (Other.p_speed > Player.p_speed)
139 Foestrikes = TRUE;
140 else
141 if (Player.p_level > Other.p_level)
142 Foestrikes = FALSE;
143 else
144 if (Other.p_level > Player.p_level)
145 Foestrikes = TRUE;
146 else
147 /* no one is faster */
149 printw("You can't fight %s yet.", Enemyname);
150 goto LEAVE;
153 for (;;) {
154 displaystats();
155 readmessage();
156 mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */
158 if (!Foestrikes)
159 /* take action against foe */
160 myturn();
161 else
162 /* wait for foe to take action */
164 mvaddstr(4, 0, "Waiting...\n");
165 clrtoeol();
166 refresh();
168 for (loop = 0; loop < 20; ++loop)
169 /* wait for foe to act */
171 readrecord(&Other, foeplace);
172 if (Other.p_1scratch != oldhits)
173 /* p_1scratch changes to indicate
174 * action */
175 break;
176 else
177 /* wait and try again */
179 sleep(1);
180 addch('.');
181 refresh();
185 if (Other.p_1scratch == oldhits) {
186 /* timeout */
187 mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
188 ch = getanswer("NY", FALSE);
189 move(22, 0);
190 clrtobot();
191 if (ch == 'Y')
192 continue;
193 else
194 break;
195 } else
196 /* foe took action */
198 switch (Other.p_istat) {
199 case I_RAN: /* foe ran away */
200 mvprintw(Lines++, 0, "%s ran away!", Enemyname);
201 break;
203 case I_STUCK: /* foe tried to run, but
204 * couldn't */
205 mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
206 break;
208 case I_BLEWIT: /* foe tried to luckout, but
209 * didn't */
210 mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
211 break;
213 default:
214 dtemp = Other.p_1scratch - oldhits;
215 mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
216 Shield -= dtemp;
217 break;
220 oldhits = Other.p_1scratch; /* keep track of old
221 * hits */
223 if (Other.p_tampered != oldtampered)
224 /* p_tampered changes to relinquish
225 * turn */
227 oldtampered = Other.p_tampered;
228 Foestrikes = FALSE;
233 /* decide what happens next */
234 refresh();
235 if (Lines > LINES - 2) {
236 more(Lines);
237 move(Lines = 8, 0);
238 clrtobot();
240 if (Other.p_istat == I_KILLED || Shield < 0.0)
241 /* we died */
243 Shield = -2.0; /* insure this value is negative */
244 break;
246 if (Player.p_istat == I_KILLED)
247 /* we killed foe; award treasre */
249 mvprintw(Lines++, 0, "You killed %s!", Enemyname);
250 Player.p_experience += Other.p_experience;
251 Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
252 Player.p_amulets += Other.p_amulets;
253 Player.p_charms += Other.p_charms;
254 collecttaxes(Other.p_gold, Other.p_gems);
255 Player.p_sword = MAX(Player.p_sword, Other.p_sword);
256 Player.p_shield = MAX(Player.p_shield, Other.p_shield);
257 Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
258 if (Other.p_virgin && !Player.p_virgin) {
259 mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? ");
260 if ((ch = getanswer("YN", FALSE)) == 'Y')
261 Player.p_virgin = TRUE;
262 else {
263 ++Player.p_sin;
264 Player.p_experience += 8000.0;
267 sleep(3); /* give other person time to die */
268 break;
269 } else
270 if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
271 /* either player ran away */
272 break;
275 LEAVE:
276 /* clean up things and leave */
277 writerecord(&Player, Fileloc); /* update a final time */
278 altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
279 Player.p_energy = Shield; /* set energy to actual value */
280 Player.p_tampered = T_OFF; /* clear p_tampered */
282 more(Lines); /* pause */
284 move(4, 0);
285 clrtobot(); /* clear bottom area of screen */
287 if (Player.p_energy < 0.0)
288 /* we are dead */
289 death("Interterminal battle");
292 static void
293 myturn(void)
295 double dtemp; /* for temporary calculations */
296 int ch; /* input */
298 mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
299 if (Luckout)
300 clrtoeol();
301 else
302 addstr("4:Luckout ");
304 ch = inputoption();
305 move(Lines = 8, 0);
306 clrtobot();
308 switch (ch) {
309 default: /* fight */
310 dtemp = ROLL(2.0, Player.p_might);
311 HIT:
312 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
313 Player.p_sin += 0.5;
314 Player.p_1scratch += dtemp;
315 Player.p_istat = I_OFF;
316 break;
318 case '2': /* run away */
319 Player.p_1scratch -= 1.0; /* change this to indicate
320 * action */
321 if (drandom() > 0.25) {
322 mvaddstr(Lines++, 0, "You got away!");
323 Player.p_istat = I_RAN;
324 } else {
325 mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
326 Player.p_istat = I_STUCK;
328 break;
330 case '3': /* power blast */
331 dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
332 Player.p_mana -= dtemp;
333 dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
334 mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
335 goto HIT;
337 case '4': /* luckout */
338 if (Luckout || drandom() > 0.1) {
339 if (Luckout)
340 mvaddstr(Lines++, 0, "You already tried that!");
341 else {
342 mvaddstr(Lines++, 0, "Not this time . . .");
343 Luckout = TRUE;
346 Player.p_1scratch -= 1.0;
347 Player.p_istat = I_BLEWIT;
348 } else {
349 mvaddstr(Lines++, 0, "You just lucked out!");
350 Player.p_1scratch = Other.p_energy * 1.1;
352 break;
355 refresh();
356 Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */
358 if (Player.p_1scratch > Other.p_energy)
359 Player.p_istat = I_KILLED;
360 else
361 if (drandom() * Player.p_speed < drandom() * Other.p_speed)
362 /* relinquish control */
364 ++Player.p_tampered;
365 Foestrikes = TRUE;
367 writerecord(&Player, Fileloc); /* let foe know what we did */
370 void
371 checktampered(void)
373 long loc = 0L; /* location in energy void file */
375 /* first check for energy voids */
376 fseek(Energyvoidfp, 0L, SEEK_SET);
377 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
378 if (Enrgyvoid.ev_active
379 && Enrgyvoid.ev_x == Player.p_x
380 && Enrgyvoid.ev_y == Player.p_y)
381 /* sitting on one */
383 if (loc > 0L)
384 /* not the holy grail; inactivate energy void */
386 Enrgyvoid.ev_active = FALSE;
387 writevoid(&Enrgyvoid, loc);
388 tampered(T_NRGVOID, 0.0, 0.0);
389 } else
390 if (Player.p_status != S_CLOAKED)
391 /* holy grail */
392 tampered(T_GRAIL, 0.0, 0.0);
393 break;
394 } else
395 loc += SZ_VOIDSTRUCT;
397 /* now check for other things */
398 readrecord(&Other, Fileloc);
399 if (Other.p_tampered != T_OFF)
400 tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
403 static void
404 tampered(int what, double arg1, double arg2)
406 long loc; /* location in file of other players */
408 Changed = TRUE;
409 move(4, 0);
411 Player.p_tampered = T_OFF; /* no longer tampered with */
413 switch (what) {
414 case T_NRGVOID:
415 addstr("You've hit an energy void !\n");
416 Player.p_mana /= 3.0;
417 Player.p_energy /= 2.0;
418 Player.p_gold = floor(Player.p_gold / 1.25) + 0.1;
419 altercoordinates(0.0, 0.0, A_NEAR);
420 break;
422 case T_TRANSPORT:
423 addstr("The king transported you ! ");
424 if (Player.p_charms > 0) {
425 addstr("But your charm saved you. . .\n");
426 --Player.p_charms;
427 } else {
428 altercoordinates(0.0, 0.0, A_FAR);
429 addch('\n');
431 break;
433 case T_BESTOW:
434 printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
435 Player.p_gold += arg1;
436 break;
438 case T_CURSED:
439 addstr("You've been cursed ! ");
440 if (Player.p_blessing) {
441 addstr("But your blessing saved you. . .\n");
442 Player.p_blessing = FALSE;
443 } else {
444 addch('\n');
445 Player.p_poison += 2.0;
446 Player.p_energy = 10.0;
447 Player.p_maxenergy *= 0.95;
448 Player.p_status = S_PLAYING; /* no longer cloaked */
450 break;
452 case T_VAPORIZED:
453 addstr("You have been vaporized!\n");
454 more(7);
455 death("Vaporization");
456 break;
458 case T_MONSTER:
459 addstr("The Valar zapped you with a monster!\n");
460 more(7);
461 encounter((int) arg1);
462 return;
464 case T_BLESSED:
465 addstr("The Valar has blessed you!\n");
466 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
467 Player.p_mana += 500.0;
468 Player.p_strength += 0.5;
469 Player.p_brains += 0.5;
470 Player.p_magiclvl += 0.5;
471 Player.p_poison = MIN(0.5, Player.p_poison);
472 break;
474 case T_RELOCATE:
475 addstr("You've been relocated. . .\n");
476 altercoordinates(arg1, arg2, A_FORCED);
477 break;
479 case T_HEAL:
480 addstr("You've been healed!\n");
481 Player.p_poison -= 0.25;
482 Player.p_energy = Player.p_maxenergy + Player.p_shield;
483 break;
485 case T_EXVALAR:
486 addstr("You are no longer Valar!\n");
487 Player.p_specialtype = SC_COUNCIL;
488 break;
490 case T_GRAIL:
491 addstr("You have found The Holy Grail!!\n");
492 if (Player.p_specialtype < SC_COUNCIL)
493 /* must be council of wise to behold grail */
495 addstr("However, you are not experienced enough to behold it.\n");
496 Player.p_sin *= Player.p_sin;
497 Player.p_mana += 1000;
498 } else
499 if (Player.p_specialtype == SC_VALAR
500 || Player.p_specialtype == SC_EXVALAR) {
501 addstr("You have made it to the position of Valar once already.\n");
502 addstr("The Grail is of no more use to you now.\n");
503 } else {
504 addstr("It is now time to see if you are worthy to behold it. . .\n");
505 refresh();
506 sleep(4);
508 if (drandom() / 2.0 < Player.p_sin) {
509 addstr("You have failed!\n");
510 Player.p_strength =
511 Player.p_mana =
512 Player.p_energy =
513 Player.p_maxenergy =
514 Player.p_magiclvl =
515 Player.p_brains =
516 Player.p_experience =
517 Player.p_quickness = 1.0;
519 altercoordinates(1.0, 1.0, A_FORCED);
520 Player.p_level = 0.0;
521 } else {
522 addstr("You made to position of Valar!\n");
523 Player.p_specialtype = SC_VALAR;
524 Player.p_lives = 5;
525 fseek(Playersfp, 0L, SEEK_SET);
526 loc = 0L;
527 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
528 /* search for existing valar */
529 if (Other.p_specialtype == SC_VALAR
530 && Other.p_status != S_NOTUSED)
531 /* found old valar */
533 Other.p_tampered = T_EXVALAR;
534 writerecord(&Other, loc);
535 break;
536 } else
537 loc += SZ_PLAYERSTRUCT;
541 /* move grail to new location */
542 Enrgyvoid.ev_active = TRUE;
543 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
544 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
545 writevoid(&Enrgyvoid, 0L);
546 break;
548 refresh();
549 sleep(2);
552 void
553 userlist(phbool ingameflag)
555 int numusers = 0; /* number of users on file */
557 if (ingameflag && Player.p_blindness) {
558 mvaddstr(8, 0, "You cannot see anyone.\n");
559 return;
561 fseek(Playersfp, 0L, SEEK_SET);
562 mvaddstr(8, 0,
563 "Name X Y Lvl Type Login Status\n");
565 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
566 if (Other.p_status == S_NOTUSED
567 /* record is unused */
568 || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
569 /* cloaked valar */
571 if (!Wizard)
572 /* wizard can see everything on file */
573 continue;
575 ++numusers;
577 if (ingameflag &&
578 /* must be playing for the rest of these conditions */
579 (Player.p_specialtype >= SC_KING
580 /* kings and higher can see others */
581 || Other.p_specialtype >= SC_KING
582 /* kings and higher can be seen by others */
583 || Circle >= CIRCLE(Other.p_x, Other.p_y)
584 /* those nearer the origin can be seen */
585 || Player.p_palantir)
586 /* palantir enables one to see others */
587 && (Other.p_status != S_CLOAKED
588 || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
589 /* not cloaked; valar can see through cloak with a palantir */
590 && Other.p_specialtype != SC_VALAR)
591 /* not a valar */
592 /* coordinates should be printed */
593 printw("%-20s %8.0f %8.0f ",
594 Other.p_name, Other.p_x, Other.p_y);
595 else
596 /* cannot see player's coordinates */
597 printw("%-20s %19.19s ",
598 Other.p_name, descrlocation(&Other, TRUE));
600 printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
601 Other.p_login, descrstatus(&Other));
603 if ((numusers % (LINES - 10)) == 0) {
604 more(LINES - 1);
605 move(9, 0);
606 clrtobot();
610 printw("Total players on file = %d\n", numusers);
611 refresh();
614 void
615 throneroom(void)
617 FILE *fp; /* to clear energy voids */
618 long loc = 0L; /* location of old king in player file */
620 if (Player.p_specialtype < SC_KING)
621 /* not already king -- assumes crown */
623 fseek(Playersfp, 0L, SEEK_SET);
624 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
625 if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
626 /* found old king */
628 if (Other.p_status != S_OFF)
629 /* old king is playing */
631 mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n");
632 altercoordinates(0.0, 0.0, A_NEAR);
633 move(6, 0);
634 return;
635 } else
636 /* old king is not playing - remove
637 * him/her */
639 Other.p_specialtype = SC_NONE;
640 if (Other.p_crowns)
641 --Other.p_crowns;
642 writerecord(&Other, loc);
643 break;
645 } else
646 loc += SZ_PLAYERSTRUCT;
648 /* make player new king */
649 Changed = TRUE;
650 Player.p_specialtype = SC_KING;
651 mvaddstr(4, 0, "You have become king!\n");
653 /* let everyone else know */
654 fp = fopen(_PATH_MESS, "w");
655 fprintf(fp, "All hail the new king!");
656 fclose(fp);
658 /* clear all energy voids; retain location of holy grail */
659 fseek(Energyvoidfp, 0L, SEEK_SET);
660 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
661 fp = fopen(_PATH_VOID, "w");
662 fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
663 fclose(fp);
665 mvaddstr(6, 0, "0:Decree ");
668 void
669 dotampered(void)
671 short tamper; /* value for tampering with other players */
672 const char *option; /* pointer to option description */
673 double temp1 = 0.0, temp2 = 0.0; /* other tampering values */
674 int ch; /* input */
675 long loc; /* location in energy void file */
676 FILE *fp; /* for opening gold file */
678 move(6, 0);
679 clrtoeol();
680 if (Player.p_specialtype < SC_COUNCIL && !Wizard)
681 /* king options */
683 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
685 ch = getanswer(" ", TRUE);
686 move(6, 0);
687 clrtoeol();
688 move(4, 0);
689 switch (ch) {
690 case '1': /* transport someone */
691 tamper = T_TRANSPORT;
692 option = "transport";
693 break;
695 case '2': /* curse another */
696 tamper = T_CURSED;
697 option = "curse";
698 break;
700 case '3': /* create energy void */
701 if ((loc = allocvoid()) > 20L * (long)SZ_VOIDSTRUCT)
702 /* can only have 20 void active at once */
703 mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
704 else {
705 addstr("Enter the X Y coordinates of void ? ");
706 getstring(Databuf, SZ_DATABUF);
707 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
708 Enrgyvoid.ev_x = floor(temp1);
709 Enrgyvoid.ev_y = floor(temp2);
710 Enrgyvoid.ev_active = TRUE;
711 writevoid(&Enrgyvoid, loc);
712 mvaddstr(5, 0, "It is done.\n");
714 return;
716 case '4': /* bestow gold to subject */
717 tamper = T_BESTOW;
718 addstr("How much gold to bestow ? ");
719 temp1 = infloat();
720 if (temp1 > Player.p_gold || temp1 < 0) {
721 mvaddstr(5, 0, "You don't have that !\n");
722 return;
724 /* adjust gold after we are sure it will be given to
725 * someone */
726 option = "give gold to";
727 break;
729 case '5': /* collect accumulated taxes */
730 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
731 /* collect taxes */
733 fread((char *) &temp1, sizeof(double), 1, fp);
734 fseek(fp, 0L, SEEK_SET);
735 /* clear out value */
736 temp2 = 0.0;
737 fwrite((char *) &temp2, sizeof(double), 1, fp);
738 fclose(fp);
740 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
741 Player.p_gold += floor(temp1);
742 return;
744 default:
745 return;
747 /* end of king options */
748 } else
749 /* council of wise, valar, wizard options */
751 addstr("1:Heal ");
752 if (Player.p_palantir || Wizard)
753 addstr("2:Seek Grail ");
754 if (Player.p_specialtype == SC_VALAR || Wizard)
755 addstr("3:Throw Monster 4:Relocate 5:Bless ");
756 if (Wizard)
757 addstr("6:Vaporize ");
759 ch = getanswer(" ", TRUE);
760 if (!Wizard) {
761 if (ch > '2' && Player.p_specialtype != SC_VALAR) {
762 ILLCMD();
763 return;
765 if (Player.p_mana < MM_INTERVENE) {
766 mvaddstr(5, 0, "No mana left.\n");
767 return;
768 } else
769 Player.p_mana -= MM_INTERVENE;
771 switch (ch) {
772 case '1': /* heal another */
773 tamper = T_HEAL;
774 option = "heal";
775 break;
777 case '2': /* seek grail */
778 if (Player.p_palantir)
779 /* need a palantir to seek */
781 fseek(Energyvoidfp, 0L, SEEK_SET);
782 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
783 temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
784 temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
785 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
786 } else
787 /* no palantir */
788 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
789 return;
791 case '3': /* lob monster at someone */
792 mvaddstr(4, 0, "Which monster [0-99] ? ");
793 temp1 = infloat();
794 temp1 = MAX(0.0, MIN(99.0, temp1));
795 tamper = T_MONSTER;
796 option = "throw a monster at";
797 break;
799 case '4': /* move another player */
800 mvaddstr(4, 0, "New X Y coordinates ? ");
801 getstring(Databuf, SZ_DATABUF);
802 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
803 tamper = T_RELOCATE;
804 option = "relocate";
805 break;
807 case '5': /* bless a player */
808 tamper = T_BLESSED;
809 option = "bless";
810 break;
812 case '6': /* kill off a player */
813 if (Wizard) {
814 tamper = T_VAPORIZED;
815 option = "vaporize";
816 break;
817 } else
818 return;
820 default:
821 return;
824 /* adjust age after we are sure intervention will be done */
825 /* end of valar, etc. options */
828 for (;;)
829 /* prompt for player to affect */
831 mvprintw(4, 0, "Who do you want to %s ? ", option);
832 getstring(Databuf, SZ_DATABUF);
833 truncstring(Databuf);
835 if (Databuf[0] == '\0')
836 userlist(TRUE);
837 else
838 break;
841 if (strcmp(Player.p_name, Databuf) != 0)
842 /* name other than self */
844 if ((loc = findname(Databuf, &Other)) >= 0L) {
845 if (Other.p_tampered != T_OFF) {
846 mvaddstr(5, 0, "That person has something pending already.\n");
847 return;
848 } else {
849 if (tamper == T_RELOCATE
850 && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
851 && !Wizard)
852 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
853 else {
854 if (tamper == T_BESTOW)
855 Player.p_gold -= floor(temp1);
856 if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
857 tamper == T_RELOCATE || tamper == T_BLESSED))
858 Player.p_age += N_AGE; /* age penalty */
859 Other.p_tampered = tamper;
860 Other.p_1scratch = floor(temp1);
861 Other.p_2scratch = floor(temp2);
862 writerecord(&Other, loc);
863 mvaddstr(5, 0, "It is done.\n");
865 return;
867 } else
868 /* player not found */
869 mvaddstr(5, 0, "There is no one by that name.\n");
870 } else
871 /* self */
872 mvaddstr(5, 0, "You may not do it to yourself!\n");
875 void
876 writevoid(struct energyvoid *vp, long loc)
879 fseek(Energyvoidfp, loc, SEEK_SET);
880 fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
881 fflush(Energyvoidfp);
882 fseek(Energyvoidfp, 0L, SEEK_SET);
885 static long
886 allocvoid(void)
888 long loc = 0L; /* location of new energy void */
890 fseek(Energyvoidfp, 0L, SEEK_SET);
891 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
892 if (Enrgyvoid.ev_active)
893 loc += SZ_VOIDSTRUCT;
894 else
895 break;
897 return (loc);