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