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