]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - phantasia/interplayer.c
don't use char values for functions that can return -1; chars are not always
[bsdgames-darwin.git] / phantasia / interplayer.c
1 /* $NetBSD: interplayer.c,v 1.10 2009/05/25 23:08:45 dholland Exp $ */
2
3 /*
4 * interplayer.c - player to player routines for Phantasia
5 */
6
7 #include "include.h"
8 #undef bool
9 #include <curses.h>
10
11 void
12 checkbattle(void)
13 {
14 long foeloc = 0L; /* location in file of person to fight */
15
16 Users = 0;
17 fseek(Playersfp, 0L, SEEK_SET);
18
19 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
20 if (Other.p_status != S_OFF
21 && Other.p_status != S_NOTUSED
22 && Other.p_status != S_HUNGUP
23 && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
24 /* player is on and not a cloaked valar */
25 {
26 ++Users;
27
28 if (Player.p_x == Other.p_x
29 && Player.p_y == Other.p_y
30 /* same coordinates */
31 && foeloc != Fileloc
32 /* not self */
33 && Player.p_status == S_PLAYING
34 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
35 /* both are playing */
36 && Other.p_specialtype != SC_VALAR
37 && Player.p_specialtype != SC_VALAR)
38 /* neither is valar */
39 {
40 battleplayer(foeloc);
41 return;
42 }
43 }
44 foeloc += SZ_PLAYERSTRUCT;
45 }
46 }
47
48 void
49 battleplayer(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(void)
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(void)
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(int what, double arg1, double arg2)
389 {
390 long loc; /* location in file of other players */
391
392 Changed = TRUE;
393 move(4, 0);
394
395 Player.p_tampered = T_OFF; /* no longer tampered with */
396
397 switch (what) {
398 case T_NRGVOID:
399 addstr("You've hit an energy void !\n");
400 Player.p_mana /= 3.0;
401 Player.p_energy /= 2.0;
402 Player.p_gold = floor(Player.p_gold / 1.25) + 0.1;
403 altercoordinates(0.0, 0.0, A_NEAR);
404 break;
405
406 case T_TRANSPORT:
407 addstr("The king transported you ! ");
408 if (Player.p_charms > 0) {
409 addstr("But your charm saved you. . .\n");
410 --Player.p_charms;
411 } else {
412 altercoordinates(0.0, 0.0, A_FAR);
413 addch('\n');
414 }
415 break;
416
417 case T_BESTOW:
418 printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
419 Player.p_gold += arg1;
420 break;
421
422 case T_CURSED:
423 addstr("You've been cursed ! ");
424 if (Player.p_blessing) {
425 addstr("But your blessing saved you. . .\n");
426 Player.p_blessing = FALSE;
427 } else {
428 addch('\n');
429 Player.p_poison += 2.0;
430 Player.p_energy = 10.0;
431 Player.p_maxenergy *= 0.95;
432 Player.p_status = S_PLAYING; /* no longer cloaked */
433 }
434 break;
435
436 case T_VAPORIZED:
437 addstr("You have been vaporized!\n");
438 more(7);
439 death("Vaporization");
440 break;
441
442 case T_MONSTER:
443 addstr("The Valar zapped you with a monster!\n");
444 more(7);
445 encounter((int) arg1);
446 return;
447
448 case T_BLESSED:
449 addstr("The Valar has blessed you!\n");
450 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
451 Player.p_mana += 500.0;
452 Player.p_strength += 0.5;
453 Player.p_brains += 0.5;
454 Player.p_magiclvl += 0.5;
455 Player.p_poison = MIN(0.5, Player.p_poison);
456 break;
457
458 case T_RELOCATE:
459 addstr("You've been relocated. . .\n");
460 altercoordinates(arg1, arg2, A_FORCED);
461 break;
462
463 case T_HEAL:
464 addstr("You've been healed!\n");
465 Player.p_poison -= 0.25;
466 Player.p_energy = Player.p_maxenergy + Player.p_shield;
467 break;
468
469 case T_EXVALAR:
470 addstr("You are no longer Valar!\n");
471 Player.p_specialtype = SC_COUNCIL;
472 break;
473
474 case T_GRAIL:
475 addstr("You have found The Holy Grail!!\n");
476 if (Player.p_specialtype < SC_COUNCIL)
477 /* must be council of wise to behold grail */
478 {
479 addstr("However, you are not experienced enough to behold it.\n");
480 Player.p_sin *= Player.p_sin;
481 Player.p_mana += 1000;
482 } else
483 if (Player.p_specialtype == SC_VALAR
484 || Player.p_specialtype == SC_EXVALAR) {
485 addstr("You have made it to the position of Valar once already.\n");
486 addstr("The Grail is of no more use to you now.\n");
487 } else {
488 addstr("It is now time to see if you are worthy to behold it. . .\n");
489 refresh();
490 sleep(4);
491
492 if (drandom() / 2.0 < Player.p_sin) {
493 addstr("You have failed!\n");
494 Player.p_strength =
495 Player.p_mana =
496 Player.p_energy =
497 Player.p_maxenergy =
498 Player.p_magiclvl =
499 Player.p_brains =
500 Player.p_experience =
501 Player.p_quickness = 1.0;
502
503 altercoordinates(1.0, 1.0, A_FORCED);
504 Player.p_level = 0.0;
505 } else {
506 addstr("You made to position of Valar!\n");
507 Player.p_specialtype = SC_VALAR;
508 Player.p_lives = 5;
509 fseek(Playersfp, 0L, SEEK_SET);
510 loc = 0L;
511 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
512 /* search for existing valar */
513 if (Other.p_specialtype == SC_VALAR
514 && Other.p_status != S_NOTUSED)
515 /* found old valar */
516 {
517 Other.p_tampered = T_EXVALAR;
518 writerecord(&Other, loc);
519 break;
520 } else
521 loc += SZ_PLAYERSTRUCT;
522 }
523 }
524
525 /* move grail to new location */
526 Enrgyvoid.ev_active = TRUE;
527 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
528 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
529 writevoid(&Enrgyvoid, 0L);
530 break;
531 }
532 refresh();
533 sleep(2);
534 }
535
536 void
537 userlist(phbool ingameflag)
538 {
539 int numusers = 0; /* number of users on file */
540
541 if (ingameflag && Player.p_blindness) {
542 mvaddstr(8, 0, "You cannot see anyone.\n");
543 return;
544 }
545 fseek(Playersfp, 0L, SEEK_SET);
546 mvaddstr(8, 0,
547 "Name X Y Lvl Type Login Status\n");
548
549 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
550 if (Other.p_status == S_NOTUSED
551 /* record is unused */
552 || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
553 /* cloaked valar */
554 {
555 if (!Wizard)
556 /* wizard can see everything on file */
557 continue;
558 }
559 ++numusers;
560
561 if (ingameflag &&
562 /* must be playing for the rest of these conditions */
563 (Player.p_specialtype >= SC_KING
564 /* kings and higher can see others */
565 || Other.p_specialtype >= SC_KING
566 /* kings and higher can be seen by others */
567 || Circle >= CIRCLE(Other.p_x, Other.p_y)
568 /* those nearer the origin can be seen */
569 || Player.p_palantir)
570 /* palantir enables one to see others */
571 && (Other.p_status != S_CLOAKED
572 || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
573 /* not cloaked; valar can see through cloak with a palantir */
574 && Other.p_specialtype != SC_VALAR)
575 /* not a valar */
576 /* coordinates should be printed */
577 printw("%-20s %8.0f %8.0f ",
578 Other.p_name, Other.p_x, Other.p_y);
579 else
580 /* cannot see player's coordinates */
581 printw("%-20s %19.19s ",
582 Other.p_name, descrlocation(&Other, TRUE));
583
584 printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
585 Other.p_login, descrstatus(&Other));
586
587 if ((numusers % (LINES - 10)) == 0) {
588 more(LINES - 1);
589 move(9, 0);
590 clrtobot();
591 }
592 }
593
594 printw("Total players on file = %d\n", numusers);
595 refresh();
596 }
597
598 void
599 throneroom(void)
600 {
601 FILE *fp; /* to clear energy voids */
602 long loc = 0L; /* location of old king in player file */
603
604 if (Player.p_specialtype < SC_KING)
605 /* not already king -- assumes crown */
606 {
607 fseek(Playersfp, 0L, SEEK_SET);
608 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
609 if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
610 /* found old king */
611 {
612 if (Other.p_status != S_OFF)
613 /* old king is playing */
614 {
615 mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n");
616 altercoordinates(0.0, 0.0, A_NEAR);
617 move(6, 0);
618 return;
619 } else
620 /* old king is not playing - remove
621 * him/her */
622 {
623 Other.p_specialtype = SC_NONE;
624 if (Other.p_crowns)
625 --Other.p_crowns;
626 writerecord(&Other, loc);
627 break;
628 }
629 } else
630 loc += SZ_PLAYERSTRUCT;
631
632 /* make player new king */
633 Changed = TRUE;
634 Player.p_specialtype = SC_KING;
635 mvaddstr(4, 0, "You have become king!\n");
636
637 /* let everyone else know */
638 fp = fopen(_PATH_MESS, "w");
639 fprintf(fp, "All hail the new king!");
640 fclose(fp);
641
642 /* clear all energy voids; retain location of holy grail */
643 fseek(Energyvoidfp, 0L, SEEK_SET);
644 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
645 fp = fopen(_PATH_VOID, "w");
646 fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
647 fclose(fp);
648 }
649 mvaddstr(6, 0, "0:Decree ");
650 }
651
652 void
653 dotampered(void)
654 {
655 short tamper; /* value for tampering with other players */
656 const char *option; /* pointer to option description */
657 double temp1 = 0.0, temp2 = 0.0; /* other tampering values */
658 int ch; /* input */
659 long loc; /* location in energy void file */
660 FILE *fp; /* for opening gold file */
661
662 move(6, 0);
663 clrtoeol();
664 if (Player.p_specialtype < SC_COUNCIL && !Wizard)
665 /* king options */
666 {
667 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
668
669 ch = getanswer(" ", TRUE);
670 move(6, 0);
671 clrtoeol();
672 move(4, 0);
673 switch (ch) {
674 case '1': /* transport someone */
675 tamper = T_TRANSPORT;
676 option = "transport";
677 break;
678
679 case '2': /* curse another */
680 tamper = T_CURSED;
681 option = "curse";
682 break;
683
684 case '3': /* create energy void */
685 if ((loc = allocvoid()) > 20L * (long)SZ_VOIDSTRUCT)
686 /* can only have 20 void active at once */
687 mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
688 else {
689 addstr("Enter the X Y coordinates of void ? ");
690 getstring(Databuf, SZ_DATABUF);
691 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
692 Enrgyvoid.ev_x = floor(temp1);
693 Enrgyvoid.ev_y = floor(temp2);
694 Enrgyvoid.ev_active = TRUE;
695 writevoid(&Enrgyvoid, loc);
696 mvaddstr(5, 0, "It is done.\n");
697 }
698 return;
699
700 case '4': /* bestow gold to subject */
701 tamper = T_BESTOW;
702 addstr("How much gold to bestow ? ");
703 temp1 = infloat();
704 if (temp1 > Player.p_gold || temp1 < 0) {
705 mvaddstr(5, 0, "You don't have that !\n");
706 return;
707 }
708 /* adjust gold after we are sure it will be given to
709 * someone */
710 option = "give gold to";
711 break;
712
713 case '5': /* collect accumulated taxes */
714 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
715 /* collect taxes */
716 {
717 fread((char *) &temp1, sizeof(double), 1, fp);
718 fseek(fp, 0L, SEEK_SET);
719 /* clear out value */
720 temp2 = 0.0;
721 fwrite((char *) &temp2, sizeof(double), 1, fp);
722 fclose(fp);
723 }
724 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
725 Player.p_gold += floor(temp1);
726 return;
727
728 default:
729 return;
730 }
731 /* end of king options */
732 } else
733 /* council of wise, valar, wizard options */
734 {
735 addstr("1:Heal ");
736 if (Player.p_palantir || Wizard)
737 addstr("2:Seek Grail ");
738 if (Player.p_specialtype == SC_VALAR || Wizard)
739 addstr("3:Throw Monster 4:Relocate 5:Bless ");
740 if (Wizard)
741 addstr("6:Vaporize ");
742
743 ch = getanswer(" ", TRUE);
744 if (!Wizard) {
745 if (ch > '2' && Player.p_specialtype != SC_VALAR) {
746 ILLCMD();
747 return;
748 }
749 if (Player.p_mana < MM_INTERVENE) {
750 mvaddstr(5, 0, "No mana left.\n");
751 return;
752 } else
753 Player.p_mana -= MM_INTERVENE;
754 }
755 switch (ch) {
756 case '1': /* heal another */
757 tamper = T_HEAL;
758 option = "heal";
759 break;
760
761 case '2': /* seek grail */
762 if (Player.p_palantir)
763 /* need a palantir to seek */
764 {
765 fseek(Energyvoidfp, 0L, SEEK_SET);
766 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
767 temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
768 temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
769 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
770 } else
771 /* no palantir */
772 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
773 return;
774
775 case '3': /* lob monster at someone */
776 mvaddstr(4, 0, "Which monster [0-99] ? ");
777 temp1 = infloat();
778 temp1 = MAX(0.0, MIN(99.0, temp1));
779 tamper = T_MONSTER;
780 option = "throw a monster at";
781 break;
782
783 case '4': /* move another player */
784 mvaddstr(4, 0, "New X Y coordinates ? ");
785 getstring(Databuf, SZ_DATABUF);
786 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
787 tamper = T_RELOCATE;
788 option = "relocate";
789 break;
790
791 case '5': /* bless a player */
792 tamper = T_BLESSED;
793 option = "bless";
794 break;
795
796 case '6': /* kill off a player */
797 if (Wizard) {
798 tamper = T_VAPORIZED;
799 option = "vaporize";
800 break;
801 } else
802 return;
803
804 default:
805 return;
806 }
807
808 /* adjust age after we are sure intervention will be done */
809 /* end of valar, etc. options */
810 }
811
812 for (;;)
813 /* prompt for player to affect */
814 {
815 mvprintw(4, 0, "Who do you want to %s ? ", option);
816 getstring(Databuf, SZ_DATABUF);
817 truncstring(Databuf);
818
819 if (Databuf[0] == '\0')
820 userlist(TRUE);
821 else
822 break;
823 }
824
825 if (strcmp(Player.p_name, Databuf) != 0)
826 /* name other than self */
827 {
828 if ((loc = findname(Databuf, &Other)) >= 0L) {
829 if (Other.p_tampered != T_OFF) {
830 mvaddstr(5, 0, "That person has something pending already.\n");
831 return;
832 } else {
833 if (tamper == T_RELOCATE
834 && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
835 && !Wizard)
836 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
837 else {
838 if (tamper == T_BESTOW)
839 Player.p_gold -= floor(temp1);
840 if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
841 tamper == T_RELOCATE || tamper == T_BLESSED))
842 Player.p_age += N_AGE; /* age penalty */
843 Other.p_tampered = tamper;
844 Other.p_1scratch = floor(temp1);
845 Other.p_2scratch = floor(temp2);
846 writerecord(&Other, loc);
847 mvaddstr(5, 0, "It is done.\n");
848 }
849 return;
850 }
851 } else
852 /* player not found */
853 mvaddstr(5, 0, "There is no one by that name.\n");
854 } else
855 /* self */
856 mvaddstr(5, 0, "You may not do it to yourself!\n");
857 }
858
859 void
860 writevoid(struct energyvoid *vp, long loc)
861 {
862
863 fseek(Energyvoidfp, loc, SEEK_SET);
864 fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
865 fflush(Energyvoidfp);
866 fseek(Energyvoidfp, 0L, SEEK_SET);
867 }
868
869 long
870 allocvoid(void)
871 {
872 long loc = 0L; /* location of new energy void */
873
874 fseek(Energyvoidfp, 0L, SEEK_SET);
875 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
876 if (Enrgyvoid.ev_active)
877 loc += SZ_VOIDSTRUCT;
878 else
879 break;
880
881 return (loc);
882 }