1 /*        $NetBSD: interplayer.c,v 1.12 2009/08/31 08:27:16 dholland Exp $      */
2 
3 /*
4  * interplayer.c - player to player routines for Phantasia
5  */
6 
7 #include <math.h>
8 #include <setjmp.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 
13 #include "macros.h"
14 #include "phantdefs.h"
15 #include "phantstruct.h"
16 #include "phantglobs.h"
17 #include "pathnames.h"
18 
19 #undef bool
20 #include <curses.h>
21 
22 static long allocvoid(void);
23 static void battleplayer(long);
24 static void myturn(void);
25 static void tampered(int, double, double);
26 
27 void
checkbattle(void)28 checkbattle(void)
29 {
30           long    foeloc = 0L;          /* location in file of person to fight */
31 
32           Users = 0;
33           fseek(Playersfp, 0L, SEEK_SET);
34 
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 */
41                     {
42                               ++Users;
43 
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 */
55                               {
56                                         battleplayer(foeloc);
57                                         return;
58                               }
59                     }
60                     foeloc += SZ_PLAYERSTRUCT;
61           }
62 }
63 
64 static void
battleplayer(long foeplace)65 battleplayer(long foeplace)
66 {
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 */
72 
73           Lines = 8;
74           Luckout = FALSE;
75           mvaddstr(4, 0, "Preparing for battle!\n");
76           refresh();
77 
78 #ifdef SYS5
79           flushinp();
80 #endif
81 
82           /* set up variables, file, etc. */
83           Player.p_status = S_INBATTLE;
84           Shield = Player.p_energy;
85 
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;
91 
92           readrecord(&Other, foeplace);
93           if (fabs(Player.p_level - Other.p_level) > 20.0)
94                     /* see if players are greatly mismatched */
95           {
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;
100           }
101           writerecord(&Player, Fileloc);          /* write out all our info */
102 
103           if (Player.p_blindness)
104                     Enemyname = "someone";
105           else
106                     Enemyname = Other.p_name;
107 
108           mvprintw(6, 0, "You have encountered %s   Level: %.0f\n", Enemyname, Other.p_level);
109           refresh();
110 
111           for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
112                     /* wait for foe to respond */
113           {
114                     readrecord(&Other, foeplace);
115                     sleep(1);
116           }
117 
118           if (Other.p_status != S_INBATTLE)
119                     /* foe did not respond */
120           {
121                     mvprintw(5, 0, "%s is not responding.\n", Enemyname);
122                     goto LEAVE;
123           }
124           /* else, we are ready to battle */
125 
126           move(4, 0);
127           clrtoeol();
128 
129           /*
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)
134          */
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 */
148                                         {
149                                                   printw("You can't fight %s yet.", Enemyname);
150                                                   goto LEAVE;
151                                         }
152 
153           for (;;) {
154                     displaystats();
155                     readmessage();
156                     mvprintw(1, 26, "%20.0f", Shield);      /* overprint energy */
157 
158                     if (!Foestrikes)
159                               /* take action against foe */
160                               myturn();
161                     else
162                               /* wait for foe to take action */
163                     {
164                               mvaddstr(4, 0, "Waiting...\n");
165                               clrtoeol();
166                               refresh();
167 
168                               for (loop = 0; loop < 20; ++loop)
169                                         /* wait for foe to act */
170                               {
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 */
178                                         {
179                                                   sleep(1);
180                                                   addch('.');
181                                                   refresh();
182                                         }
183                               }
184 
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 */
197                               {
198                                         switch (Other.p_istat) {
199                                         case I_RAN:         /* foe ran away */
200                                                   mvprintw(Lines++, 0, "%s ran away!", Enemyname);
201                                                   break;
202 
203                                         case I_STUCK:       /* foe tried to run, but
204                                                              * couldn't */
205                                                   mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
206                                                   break;
207 
208                                         case I_BLEWIT:      /* foe tried to luckout, but
209                                                              * didn't */
210                                                   mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
211                                                   break;
212 
213                                         default:
214                                                   dtemp = Other.p_1scratch - oldhits;
215                                                   mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
216                                                   Shield -= dtemp;
217                                                   break;
218                                         }
219 
220                                         oldhits = Other.p_1scratch;   /* keep track of old
221                                                                                  * hits */
222 
223                                         if (Other.p_tampered != oldtampered)
224                                                   /* p_tampered changes to relinquish
225                                                    * turn */
226                                         {
227                                                   oldtampered = Other.p_tampered;
228                                                   Foestrikes = FALSE;
229                                         }
230                               }
231                     }
232 
233                     /* decide what happens next */
234                     refresh();
235                     if (Lines > LINES - 2) {
236                               more(Lines);
237                               move(Lines = 8, 0);
238                               clrtobot();
239                     }
240                     if (Other.p_istat == I_KILLED || Shield < 0.0)
241                               /* we died */
242                     {
243                               Shield = -2.0;      /* insure this value is negative */
244                               break;
245                     }
246                     if (Player.p_istat == I_KILLED)
247                               /* we killed foe; award treasre */
248                     {
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;
265                                         }
266                               }
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;
273           }
274 
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 */
281 
282           more(Lines);                  /* pause */
283 
284           move(4, 0);
285           clrtobot();                   /* clear bottom area of screen */
286 
287           if (Player.p_energy < 0.0)
288                     /* we are dead */
289                     death("Interterminal battle");
290 }
291 
292 static void
myturn(void)293 myturn(void)
294 {
295           double  dtemp;                /* for temporary calculations */
296           int     ch;                   /* input */
297 
298           mvaddstr(7, 0, "1:Fight  2:Run Away!  3:Power Blast  ");
299           if (Luckout)
300                     clrtoeol();
301           else
302                     addstr("4:Luckout  ");
303 
304           ch = inputoption();
305           move(Lines = 8, 0);
306           clrtobot();
307 
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;
317 
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;
327                     }
328                     break;
329 
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;
336 
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;
344                               }
345 
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;
351                     }
352                     break;
353           }
354 
355           refresh();
356           Player.p_1scratch = floor(Player.p_1scratch);     /* clean up any mess */
357 
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 */
363                     {
364                               ++Player.p_tampered;
365                               Foestrikes = TRUE;
366                     }
367           writerecord(&Player, Fileloc);          /* let foe know what we did */
368 }
369 
370 void
checktampered(void)371 checktampered(void)
372 {
373           long    loc = 0L;   /* location in energy void file */
374 
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 */
382                     {
383                               if (loc > 0L)
384                                         /* not the holy grail; inactivate energy void */
385                               {
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;
396 
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);
401 }
402 
403 static void
tampered(int what,double arg1,double arg2)404 tampered(int what, double arg1, double arg2)
405 {
406           long    loc;                  /* location in file of other players */
407 
408           Changed = TRUE;
409           move(4, 0);
410 
411           Player.p_tampered = T_OFF;    /* no longer tampered with */
412 
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;
421 
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');
430                     }
431                     break;
432 
433           case T_BESTOW:
434                     printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
435                     Player.p_gold += arg1;
436                     break;
437 
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 */
449                     }
450                     break;
451 
452           case T_VAPORIZED:
453                     addstr("You have been vaporized!\n");
454                     more(7);
455                     death("Vaporization");
456                     break;
457 
458           case T_MONSTER:
459                     addstr("The Valar zapped you with a monster!\n");
460                     more(7);
461                     encounter((int) arg1);
462                     return;
463 
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;
473 
474           case T_RELOCATE:
475                     addstr("You've been relocated. . .\n");
476                     altercoordinates(arg1, arg2, A_FORCED);
477                     break;
478 
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;
484 
485           case T_EXVALAR:
486                     addstr("You are no longer Valar!\n");
487                     Player.p_specialtype = SC_COUNCIL;
488                     break;
489 
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 */
494                     {
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);
507 
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;
518 
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 */
532                                                             {
533                                                                       Other.p_tampered = T_EXVALAR;
534                                                                       writerecord(&Other, loc);
535                                                                       break;
536                                                             } else
537                                                                       loc += SZ_PLAYERSTRUCT;
538                                         }
539                               }
540 
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;
547           }
548           refresh();
549           sleep(2);
550 }
551 
552 void
userlist(phbool ingameflag)553 userlist(phbool ingameflag)
554 {
555           int     numusers = 0;         /* number of users on file */
556 
557           if (ingameflag && Player.p_blindness) {
558                     mvaddstr(8, 0, "You cannot see anyone.\n");
559                     return;
560           }
561           fseek(Playersfp, 0L, SEEK_SET);
562           mvaddstr(8, 0,
563               "Name                         X         Y    Lvl Type Login    Status\n");
564 
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 */
570                     {
571                               if (!Wizard)
572                                         /* wizard can see everything on file */
573                                         continue;
574                     }
575                     ++numusers;
576 
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));
599 
600                     printw("%6.0f %s  %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
601                         Other.p_login, descrstatus(&Other));
602 
603                     if ((numusers % (LINES - 10)) == 0) {
604                               more(LINES - 1);
605                               move(9, 0);
606                               clrtobot();
607                     }
608           }
609 
610           printw("Total players on file = %d\n", numusers);
611           refresh();
612 }
613 
614 void
throneroom(void)615 throneroom(void)
616 {
617           FILE   *fp;                   /* to clear energy voids */
618           long    loc = 0L;   /* location of old king in player file */
619 
620           if (Player.p_specialtype < SC_KING)
621                     /* not already king -- assumes crown */
622           {
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 */
627                               {
628                                         if (Other.p_status != S_OFF)
629                                                   /* old king is playing */
630                                         {
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 */
638                                         {
639                                                   Other.p_specialtype = SC_NONE;
640                                                   if (Other.p_crowns)
641                                                             --Other.p_crowns;
642                                                   writerecord(&Other, loc);
643                                                   break;
644                                         }
645                               } else
646                                         loc += SZ_PLAYERSTRUCT;
647 
648                     /* make player new king */
649                     Changed = TRUE;
650                     Player.p_specialtype = SC_KING;
651                     mvaddstr(4, 0, "You have become king!\n");
652 
653                     /* let everyone else know */
654                     fp = fopen(_PATH_MESS, "w");
655                     fprintf(fp, "All hail the new king!");
656                     fclose(fp);
657 
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);
664           }
665           mvaddstr(6, 0, "0:Decree  ");
666 }
667 
668 void
dotampered(void)669 dotampered(void)
670 {
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 */
677 
678           move(6, 0);
679           clrtoeol();
680           if (Player.p_specialtype < SC_COUNCIL && !Wizard)
681                     /* king options */
682           {
683                     addstr("1:Transport  2:Curse  3:Energy Void  4:Bestow  5:Collect Taxes  ");
684 
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;
694 
695                     case '2': /* curse another */
696                               tamper = T_CURSED;
697                               option = "curse";
698                               break;
699 
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");
713                               }
714                               return;
715 
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;
723                               }
724                               /* adjust gold after we are sure it will be given to
725                                * someone */
726                               option = "give gold to";
727                               break;
728 
729                     case '5': /* collect accumulated taxes */
730                               if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
731                                         /* collect taxes */
732                               {
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);
739                               }
740                               mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
741                               Player.p_gold += floor(temp1);
742                               return;
743 
744                     default:
745                               return;
746                     }
747                     /* end of king options */
748           } else
749                     /* council of wise, valar, wizard options */
750           {
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  ");
758 
759                     ch = getanswer(" ", TRUE);
760                     if (!Wizard) {
761                               if (ch > '2' && Player.p_specialtype != SC_VALAR) {
762                                         ILLCMD();
763                                         return;
764                               }
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;
770                     }
771                     switch (ch) {
772                     case '1': /* heal another */
773                               tamper = T_HEAL;
774                               option = "heal";
775                               break;
776 
777                     case '2': /* seek grail */
778                               if (Player.p_palantir)
779                                         /* need a palantir to seek */
780                               {
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;
790 
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;
798 
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;
806 
807                     case '5': /* bless a player */
808                               tamper = T_BLESSED;
809                               option = "bless";
810                               break;
811 
812                     case '6': /* kill off a player */
813                               if (Wizard) {
814                                         tamper = T_VAPORIZED;
815                                         option = "vaporize";
816                                         break;
817                               } else
818                                         return;
819 
820                     default:
821                               return;
822                     }
823 
824                     /* adjust age after we are sure intervention will be done */
825                     /* end of valar, etc. options */
826           }
827 
828           for (;;)
829                     /* prompt for player to affect */
830           {
831                     mvprintw(4, 0, "Who do you want to %s ? ", option);
832                     getstring(Databuf, SZ_DATABUF);
833                     truncstring(Databuf);
834 
835                     if (Databuf[0] == '\0')
836                               userlist(TRUE);
837                     else
838                               break;
839           }
840 
841           if (strcmp(Player.p_name, Databuf) != 0)
842                     /* name other than self */
843           {
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");
864                                         }
865                                         return;
866                               }
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");
873 }
874 
875 void
writevoid(struct energyvoid * vp,long loc)876 writevoid(struct energyvoid *vp, long loc)
877 {
878 
879           fseek(Energyvoidfp, loc, SEEK_SET);
880           fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
881           fflush(Energyvoidfp);
882           fseek(Energyvoidfp, 0L, SEEK_SET);
883 }
884 
885 static long
allocvoid(void)886 allocvoid(void)
887 {
888           long    loc = 0L;   /* location of new energy void */
889 
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;
896 
897           return (loc);
898 }
899