]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - games/phantasia/interplayer.c
This commit was generated by cvs2svn to compensate for changes in r41220,
[FreeBSD/FreeBSD.git] / games / phantasia / interplayer.c
1 /*
2  * interplayer.c - player to player routines for Phantasia
3  */
4
5 #include <string.h>
6 #include "include.h"
7
8 /************************************************************************
9 /
10 / FUNCTION NAME: checkbattle()
11 /
12 / FUNCTION: check to see if current player should battle another
13 /
14 / AUTHOR: E. A. Estes, 12/4/85
15 /
16 / ARGUMENTS: none
17 /
18 / RETURN VALUE: none
19 /
20 / MODULES CALLED: battleplayer(), fread(), fseek()
21 /
22 / GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
23 /
24 / GLOBAL OUTPUTS: Users
25 /
26 / DESCRIPTION:
27 /       Seach player file for a foe at the same coordinates as the
28 /       current player.
29 /       Also update user count.
30 /
31 *************************************************************************/
32
33 checkbattle()
34 {
35 long    foeloc = 0L;            /* location in file of person to fight */
36
37     Users = 0;
38     fseek(Playersfp, 0L, 0);
39
40     while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
41         {
42         if (Other.p_status != S_OFF
43             && Other.p_status != S_NOTUSED
44             && Other.p_status != S_HUNGUP
45             && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
46             /* player is on and not a cloaked valar */
47             {
48             ++Users;
49
50             if (Player.p_x == Other.p_x
51                 && Player.p_y == Other.p_y
52                 /* same coordinates */
53                 && foeloc != Fileloc
54                 /* not self */
55                 && Player.p_status == S_PLAYING
56                 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
57                 /* both are playing */
58                 && Other.p_specialtype != SC_VALAR
59                 && Player.p_specialtype != SC_VALAR)
60                 /* neither is valar */
61                 {
62                 battleplayer(foeloc);
63                 return;
64                 }
65             }
66         foeloc += SZ_PLAYERSTRUCT;
67         }
68 }
69 /*\f*/
70 /************************************************************************
71 /
72 / FUNCTION NAME: battleplayer()
73 /
74 / FUNCTION: inter-terminal battle with another player
75 /
76 / AUTHOR: E. A. Estes, 2/15/86
77 /
78 / ARGUMENTS:
79 /       long foeplace - location in player file of person to battle
80 /
81 / RETURN VALUE: none
82 /
83 / MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(),
84 /       displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(),
85 /       myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(),
86 /       getanswer(), wclrtoeol(), wclrtobot()
87 /
88 / GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr,
89 /       Fileloc, *Enemyname
90 /
91 / GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
92 /
93 / DESCRIPTION:
94 /       Inter-terminal battle is a very fragile and slightly klugy thing.
95 /       At any time, one player is master and the other is slave.
96 /       We pick who is master first by speed and level.  After that,
97 /       the slave waits for the master to relinquish its turn, and
98 /       the slave becomes master, and so on.
99 /
100 /       The items in the player structure which control the handshake are:
101 /           p_tampered:
102 /               master increments this to relinquish control
103 /           p_istat:
104 /               master sets this to specify particular action
105 /           p_1scratch:
106 /               set to total damage inflicted so far; changes to indicate action
107 /
108 *************************************************************************/
109
110 battleplayer(foeplace)
111 long    foeplace;
112 {
113 double  dtemp;          /* for temporary calculations */
114 double  oldhits = 0.0;  /* previous damage inflicted by foe */
115 register int    loop;   /* for timing out */
116 int     ch;             /* input */
117 short   oldtampered;    /* old value of foe's p_tampered */
118
119     Lines = 8;
120     Luckout = FALSE;
121     mvaddstr(4, 0, "Preparing for battle!\n");
122     refresh();
123
124 #ifdef SYS5
125     flushinp();
126 #endif
127
128     /* set up variables, file, etc. */
129     Player.p_status = S_INBATTLE;
130     Shield = Player.p_energy;
131
132     /* if p_tampered is not 0, someone else may try to change it (king, etc.) */
133     Player.p_tampered = oldtampered = 1;
134     Player.p_1scratch = 0.0;
135     Player.p_istat = I_OFF;
136
137     readrecord(&Other, foeplace);
138     if (fabs(Player.p_level - Other.p_level) > 20.0)
139         /* see if players are greatly mismatched */
140         {
141         dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
142         if (dtemp < -0.5)
143             /* foe outweighs this one */
144             Player.p_speed *= 2.0;
145         }
146
147     writerecord(&Player, Fileloc);              /* write out all our info */
148
149     if (Player.p_blindness)
150         Enemyname = "someone";
151     else
152         Enemyname = Other.p_name;
153
154     mvprintw(6, 0, "You have encountered %s   Level: %.0f\n", Enemyname, Other.p_level);
155     refresh();
156
157     for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
158         /* wait for foe to respond */
159         {
160         readrecord(&Other, foeplace);
161         sleep(1);
162         }
163
164     if (Other.p_status != S_INBATTLE)
165         /* foe did not respond */
166         {
167         mvprintw(5, 0, "%s is not responding.\n", Enemyname);
168         goto LEAVE;
169         }
170     /* else, we are ready to battle */
171
172     move(4, 0);
173     clrtoeol();
174
175     /*
176      * determine who is first master
177      * if neither player is faster, check level
178      * if neither level is greater, battle is not allowed
179      * (this should never happen, but we have to handle it)
180      */
181     if (Player.p_speed > Other.p_speed)
182         Foestrikes = FALSE;
183     else if (Other.p_speed > Player.p_speed)
184         Foestrikes = TRUE;
185     else if (Player.p_level > Other.p_level)
186         Foestrikes = FALSE;
187     else if (Other.p_level > Player.p_level)
188         Foestrikes = TRUE;
189     else
190         /* no one is faster */
191         {
192         printw("You can't fight %s yet.", Enemyname);
193         goto LEAVE;
194         }
195
196     for (;;)
197         {
198         displaystats();
199         readmessage();
200         mvprintw(1, 26, "%20.0f", Shield);      /* overprint energy */
201
202         if (!Foestrikes)
203             /* take action against foe */
204             myturn();
205         else
206             /* wait for foe to take action */
207             {
208             mvaddstr(4, 0, "Waiting...\n");
209             clrtoeol();
210             refresh();
211
212             for (loop = 0; loop < 20; ++loop)
213                 /* wait for foe to act */
214                 {
215                 readrecord(&Other, foeplace);
216                 if (Other.p_1scratch != oldhits)
217                     /* p_1scratch changes to indicate action */
218                     break;
219                 else
220                     /* wait and try again */
221                     {
222                     sleep(1);
223                     addch('.');
224                     refresh();
225                     }
226                 }
227
228             if (Other.p_1scratch == oldhits)
229                 {
230                 /* timeout */
231                 mvaddstr(22, 0, "Timeout: waiting for response.  Do you want to wait ? ");
232                 ch = getanswer("NY", FALSE);
233                 move(22, 0);
234                 clrtobot();
235                 if (ch == 'Y')
236                     continue;
237                 else
238                     break;
239                 }
240             else
241                 /* foe took action */
242                 {
243                 switch (Other.p_istat)
244                     {
245                     case I_RAN:         /* foe ran away */
246                         mvprintw(Lines++, 0, "%s ran away!", Enemyname);
247                         break;
248
249                     case I_STUCK:       /* foe tried to run, but couldn't */
250                         mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
251                         break;
252
253                     case I_BLEWIT:      /* foe tried to luckout, but didn't */
254                         mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
255                         break;
256
257                     default:
258                         dtemp = Other.p_1scratch - oldhits;
259                         mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
260                         Shield -= dtemp;
261                         break;
262                     }
263
264                 oldhits = Other.p_1scratch;     /* keep track of old hits */
265
266                 if (Other.p_tampered != oldtampered)
267                     /* p_tampered changes to relinquish turn */
268                     {
269                     oldtampered = Other.p_tampered;
270                     Foestrikes = FALSE;
271                     }
272                 }
273             }
274
275         /* decide what happens next */
276         refresh();
277         if (Lines > LINES - 2)
278             {
279             more(Lines);
280             move(Lines = 8, 0);
281             clrtobot();
282             }
283
284         if (Other.p_istat == I_KILLED || Shield < 0.0)
285             /* we died */
286             {
287             Shield = -2.0;              /* insure this value is negative */
288             break;
289             }
290
291         if (Player.p_istat == I_KILLED)
292             /* we killed foe; award treasre */
293             {
294             mvprintw(Lines++, 0, "You killed %s!", Enemyname);
295             Player.p_experience += Other.p_experience;
296             Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
297             Player.p_amulets += Other.p_amulets;
298             Player.p_charms += Other.p_charms;
299             collecttaxes(Other.p_gold, Other.p_gems);
300             Player.p_sword = MAX(Player.p_sword, Other.p_sword);
301             Player.p_shield = MAX(Player.p_shield, Other.p_shield);
302             Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
303             if (Other.p_virgin && !Player.p_virgin)
304                 {
305                 mvaddstr(Lines++, 0, "You have rescued a virgin.  Will you be honorable ? ");
306                 if ((ch = getanswer("YN", FALSE)) == 'Y')
307                     Player.p_virgin = TRUE;
308                 else
309                     {
310                     ++Player.p_sin;
311                     Player.p_experience += 8000.0;
312                     }
313                 }
314             sleep(3);                   /* give other person time to die */
315             break;
316             }
317         else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
318             /* either player ran away */
319             break;
320         }
321
322 LEAVE:
323     /* clean up things and leave */
324     writerecord(&Player, Fileloc);      /* update a final time */
325     altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
326     Player.p_energy = Shield;           /* set energy to actual value */
327     Player.p_tampered = T_OFF;          /* clear p_tampered */
328
329     more(Lines);                        /* pause */
330
331     move(4, 0);
332     clrtobot();                         /* clear bottom area of screen */
333
334     if (Player.p_energy < 0.0)
335         /* we are dead */
336         death("Interterminal battle");
337 }
338 /*\f*/
339 /************************************************************************
340 /
341 / FUNCTION NAME: myturn()
342 /
343 / FUNCTION: process players action against foe in battle
344 /
345 / AUTHOR: E. A. Estes, 2/7/86
346 /
347 / ARGUMENTS: none
348 /
349 / RETURN VALUE: none
350 /
351 / MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), drandom(),
352 /       waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot()
353 /
354 / GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout,
355 /       *Enemyname
356 /
357 / GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
358 /
359 / DESCRIPTION:
360 /       Take action action against foe, and decide who is master
361 /       for next iteration.
362 /
363 *************************************************************************/
364
365 myturn()
366 {
367 double  dtemp;          /* for temporary calculations */
368 int     ch;             /* input */
369
370     mvaddstr(7, 0, "1:Fight  2:Run Away!  3:Power Blast  ");
371     if (Luckout)
372         clrtoeol();
373     else
374         addstr("4:Luckout  ");
375
376     ch = inputoption();
377     move(Lines = 8, 0);
378     clrtobot();
379
380     switch (ch)
381         {
382         default:        /* fight */
383             dtemp = ROLL(2.0, Player.p_might);
384 HIT:
385             mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
386             Player.p_sin += 0.5;
387             Player.p_1scratch += dtemp;
388             Player.p_istat = I_OFF;
389             break;
390
391         case '2':       /* run away */
392             Player.p_1scratch -= 1.0;   /* change this to indicate action */
393             if (drandom() > 0.25)
394                 {
395                 mvaddstr(Lines++, 0, "You got away!");
396                 Player.p_istat = I_RAN;
397                 }
398             else
399                 {
400                 mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
401                 Player.p_istat = I_STUCK;
402                 }
403             break;
404
405         case '3':       /* power blast */
406             dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
407             Player.p_mana -= dtemp;
408             dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
409             mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
410             goto HIT;
411
412         case '4':       /* luckout */
413             if (Luckout || drandom() > 0.1)
414                 {
415                 if (Luckout)
416                     mvaddstr(Lines++, 0, "You already tried that!");
417                 else
418                     {
419                     mvaddstr(Lines++, 0, "Not this time . . .");
420                     Luckout = TRUE;
421                     }
422
423                 Player.p_1scratch -= 1.0;
424                 Player.p_istat = I_BLEWIT;
425                 }
426             else
427                 {
428                 mvaddstr(Lines++, 0, "You just lucked out!");
429                 Player.p_1scratch = Other.p_energy * 1.1;
430                 }
431             break;
432         }
433
434     refresh();
435     Player.p_1scratch = floor(Player.p_1scratch);       /* clean up any mess */
436
437     if (Player.p_1scratch > Other.p_energy)
438         Player.p_istat = I_KILLED;
439     else if (drandom() * Player.p_speed < drandom() * Other.p_speed)
440         /* relinquish control */
441         {
442         ++Player.p_tampered;
443         Foestrikes = TRUE;
444         }
445
446     writerecord(&Player, Fileloc);                      /* let foe know what we did */
447 }
448 /*\f*/
449 /************************************************************************
450 /
451 / FUNCTION NAME: checktampered()
452 /
453 / FUNCTION: check if current player has been tampered with
454 /
455 / AUTHOR: E. A. Estes, 12/4/85
456 /
457 / ARGUMENTS: none
458 /
459 / RETURN VALUE: none
460 /
461 / MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid()
462 /
463 / GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
464 /
465 / GLOBAL OUTPUTS: Enrgyvoid
466 /
467 / DESCRIPTION:
468 /       Check for energy voids, holy grail, and tampering by other
469 /       players.
470 /
471 *************************************************************************/
472
473 checktampered()
474 {
475 long    loc = 0L;               /* location in energy void file */
476
477     /* first check for energy voids */
478     fseek(Energyvoidfp, 0L, 0);
479     while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
480         if (Enrgyvoid.ev_active
481             && Enrgyvoid.ev_x == Player.p_x
482             && Enrgyvoid.ev_y == Player.p_y)
483             /* sitting on one */
484             {
485             if (loc > 0L)
486                 /* not the holy grail; inactivate energy void */
487                 {
488                 Enrgyvoid.ev_active = FALSE;
489                 writevoid(&Enrgyvoid, loc);
490                 tampered(T_NRGVOID, 0.0, 0.0);
491                 }
492             else if (Player.p_status != S_CLOAKED)
493                 /* holy grail */
494                 tampered(T_GRAIL, 0.0, 0.0);
495             break;
496             }
497         else
498             loc += SZ_VOIDSTRUCT;
499
500     /* now check for other things */
501     readrecord(&Other, Fileloc);
502     if (Other.p_tampered != T_OFF)
503         tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
504 }
505 /*\f*/
506 /************************************************************************
507 /
508 / FUNCTION NAME: tampered()
509 /
510 / FUNCTION: take care of tampering by other players
511 /
512 / AUTHOR: E. A. Estes, 12/4/85
513 /
514 / ARGUMENTS:
515 /       int what - what type of tampering
516 /       double arg1, arg2 - rest of tampering info
517 /
518 / RETURN VALUE: none
519 /
520 / MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(),
521 /       floor(), wmove(), waddch(), drandom(), printw(), altercoordinates(),
522 /       waddstr(), wrefresh(), encounter(), writevoid()
523 /
524 / GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
525 /
526 / GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
527 /
528 / DESCRIPTION:
529 /       Take care of energy voids, holy grail, decree and intervention
530 /       action on current player.
531 /
532 *************************************************************************/
533
534 tampered(what, arg1, arg2)
535 int     what;
536 double  arg1;
537 double  arg2;
538 {
539 long    loc;                    /* location in file of other players */
540
541     Changed = TRUE;
542     move(4,0);
543
544     Player.p_tampered = T_OFF;  /* no longer tampered with */
545
546     switch (what)
547         {
548         case T_NRGVOID:
549             addstr("You've hit an energy void !\n");
550             Player.p_mana /= 3.0;
551             Player.p_energy /= 2.0;
552             Player.p_gold = floor(Player.p_gold/1.25) + 0.1;
553             altercoordinates(0.0, 0.0, A_NEAR);
554             break;
555
556         case T_TRANSPORT:
557             addstr("The king transported you !  ");
558             if (Player.p_charms > 0)
559                 {
560                 addstr("But your charm saved you. . .\n");
561                 --Player.p_charms;
562                 }
563             else
564                 {
565                 altercoordinates(0.0, 0.0, A_FAR);
566                 addch('\n');
567                 }
568             break;
569
570         case T_BESTOW:
571             printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
572             Player.p_gold += arg1;
573             break;
574
575         case T_CURSED:
576             addstr("You've been cursed !  ");
577             if (Player.p_blessing)
578                 {
579                 addstr("But your blessing saved you. . .\n");
580                 Player.p_blessing = FALSE;
581                 }
582             else
583                 {
584                 addch('\n');
585                 Player.p_poison += 2.0;
586                 Player.p_energy = 10.0;
587                 Player.p_maxenergy  *= 0.95;
588                 Player.p_status = S_PLAYING;    /* no longer cloaked */
589                 }
590             break;
591
592         case T_VAPORIZED:
593             addstr("You have been vaporized!\n");
594             more(7);
595             death("Vaporization");
596             break;
597
598         case T_MONSTER:
599             addstr("The Valar zapped you with a monster!\n");
600             more(7);
601             encounter((int) arg1);
602             return;
603
604         case T_BLESSED:
605             addstr("The Valar has blessed you!\n");
606             Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
607             Player.p_mana += 500.0;
608             Player.p_strength += 0.5;
609             Player.p_brains += 0.5;
610             Player.p_magiclvl += 0.5;
611             Player.p_poison = MIN(0.5, Player.p_poison);
612             break;
613
614         case T_RELOCATE:
615             addstr("You've been relocated. . .\n");
616             altercoordinates(arg1, arg2, A_FORCED);
617             break;
618
619         case T_HEAL:
620             addstr("You've been healed!\n");
621             Player.p_poison -=  0.25;
622             Player.p_energy = Player.p_maxenergy + Player.p_shield;
623             break;
624
625         case T_EXVALAR:
626             addstr("You are no longer Valar!\n");
627             Player.p_specialtype = SC_COUNCIL;
628             break;
629
630         case T_GRAIL:
631             addstr("You have found The Holy Grail!!\n");
632             if (Player.p_specialtype < SC_COUNCIL)
633                 /* must be council of wise to behold grail */
634                 {
635                 addstr("However, you are not experienced enough to behold it.\n");
636                 Player.p_sin *= Player.p_sin;
637                 Player.p_mana +=  1000;
638                 }
639             else if (Player.p_specialtype == SC_VALAR
640                 || Player.p_specialtype == SC_EXVALAR)
641                 {
642                 addstr("You have made it to the position of Valar once already.\n");
643                 addstr("The Grail is of no more use to you now.\n");
644                 }
645             else
646                 {
647                 addstr("It is now time to see if you are worthy to behold it. . .\n");
648                 refresh();
649                 sleep(4);
650
651                 if (drandom() / 2.0 < Player.p_sin)
652                     {
653                     addstr("You have failed!\n");
654                     Player.p_strength =
655                     Player.p_mana =
656                     Player.p_energy =
657                     Player.p_maxenergy =
658                     Player.p_magiclvl =
659                     Player.p_brains =
660                     Player.p_experience =
661                     Player.p_quickness = 1.0;
662
663                     altercoordinates(1.0, 1.0, A_FORCED);
664                     Player.p_level = 0.0;
665                     }
666                 else
667                     {
668                     addstr("You made to position of Valar!\n");
669                     Player.p_specialtype = SC_VALAR;
670                     Player.p_lives = 5;
671                     fseek(Playersfp, 0L, 0);
672                     loc = 0L;
673                     while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
674                         /* search for existing valar */
675                         if (Other.p_specialtype == SC_VALAR
676                             && Other.p_status != S_NOTUSED)
677                             /* found old valar */
678                             {
679                             Other.p_tampered = T_EXVALAR;
680                             writerecord(&Other, loc);
681                             break;
682                             }
683                         else
684                             loc += SZ_PLAYERSTRUCT;
685                     }
686                 }
687
688             /* move grail to new location */
689             Enrgyvoid.ev_active = TRUE;
690             Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
691             Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
692             writevoid(&Enrgyvoid, 0L);
693             break;
694         }
695     refresh();
696     sleep(2);
697 }
698 /*\f*/
699 /************************************************************************
700 /
701 / FUNCTION NAME: userlist()
702 /
703 / FUNCTION: print list of players and locations
704 /
705 / AUTHOR: E. A. Estes, 2/28/86
706 /
707 / ARGUMENTS:
708 /       bool ingameflag - set if called while playing
709 /
710 / RETURN VALUE: none
711 /
712 / MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(),
713 /       floor(), wmove(), printw(), waddstr(), distance(), wrefresh(),
714 /       descrtype(), wclrtobot()
715 /
716 / GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
717 /
718 / GLOBAL OUTPUTS: none
719 /
720 / DESCRIPTION:
721 /       We can only see the coordinate of those closer to the origin
722 /       from us.
723 /       Kings and council of the wise can see and can be seen by everyone.
724 /       Palantirs are good for seeing everyone; and the valar can use
725 /       one to see through a 'cloak' spell.
726 /       The valar has no coordinates, and is completely invisible if
727 /       cloaked.
728 /
729 *************************************************************************/
730
731 userlist(ingameflag)
732 bool    ingameflag;
733 {
734 register int    numusers = 0;   /* number of users on file */
735
736     if (ingameflag && Player.p_blindness)
737         {
738         mvaddstr(8, 0, "You cannot see anyone.\n");
739         return;
740         }
741
742     fseek(Playersfp, 0L, 0);
743     mvaddstr(8, 0,
744         "Name                         X         Y    Lvl Type Login    Status\n");
745
746     while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
747         {
748         if (Other.p_status == S_NOTUSED
749             /* record is unused */
750             || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
751             /* cloaked valar */
752             {
753             if (!Wizard)
754                 /* wizard can see everything on file */
755                 continue;
756             }
757
758             ++numusers;
759
760             if (ingameflag &&
761                 /* must be playing for the rest of these conditions */
762                 (Player.p_specialtype >= SC_KING
763                 /* kings and higher can see others */
764                 || Other.p_specialtype >= SC_KING
765                 /* kings and higher can be seen by others */
766                 || Circle >= CIRCLE(Other.p_x, Other.p_y)
767                 /* those nearer the origin can be seen */
768                 || Player.p_palantir)
769                 /* palantir enables one to see others */
770                 && (Other.p_status != S_CLOAKED
771                     || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
772                 /* not cloaked; valar can see through cloak with a palantir */
773                 && Other.p_specialtype != SC_VALAR)
774                 /* not a valar */
775                 /* coordinates should be printed */
776                 printw("%-20s  %8.0f  %8.0f ",
777                     Other.p_name, Other.p_x, Other.p_y);
778             else
779                 /* cannot see player's coordinates */
780                 printw("%-20s %19.19s ",
781                     Other.p_name, descrlocation(&Other, TRUE));
782
783         printw("%6.0f %s  %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
784             Other.p_login, descrstatus(&Other));
785
786         if ((numusers % (LINES - 10)) == 0)
787             {
788             more(LINES - 1);
789             move(9, 0);
790             clrtobot();
791             }
792         }
793
794     printw("Total players on file = %d\n", numusers);
795     refresh();
796 }
797 /*\f*/
798 /************************************************************************
799 /
800 / FUNCTION NAME: throneroom()
801 /
802 / FUNCTION: king stuff upon entering throne
803 /
804 / AUTHOR: E. A. Estes, 12/16/85
805 /
806 / ARGUMENTS: none
807 /
808 / RETURN VALUE: none
809 /
810 / MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(),
811 /       fwrite(), altercoordinates(), waddstr(), fprintf()
812 /
813 / GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr,
814 /       Enrgyvoid, *Playersfp
815 /
816 / GLOBAL OUTPUTS: Other, Player, Changed
817 /
818 / DESCRIPTION:
819 /       If player is not already king, make him/her so if the old king
820 /       is not playing.
821 /       Clear energy voids with new king.
822 /       Print 'decree' prompt.
823 /
824 *************************************************************************/
825
826 throneroom()
827 {
828 FILE    *fp;                    /* to clear energy voids */
829 long    loc = 0L;               /* location of old king in player file */
830
831     if (Player.p_specialtype < SC_KING)
832         /* not already king -- assumes crown */
833         {
834         fseek(Playersfp, 0L, 0);
835         while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
836             if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
837                 /* found old king */
838                 {
839                 if (Other.p_status != S_OFF)
840                     /* old king is playing */
841                     {
842                     mvaddstr( 4, 0, "The king is playing, so you cannot steal his throne\n");
843                     altercoordinates(0.0, 0.0, A_NEAR);
844                     move(6, 0);
845                     return;
846                     }
847                 else
848                     /* old king is not playing - remove him/her */
849                     {
850                     Other.p_specialtype = SC_NONE;
851                     if (Other.p_crowns)
852                         --Other.p_crowns;
853                     writerecord(&Other, loc);
854                     break;
855                     }
856                 }
857             else
858                 loc += SZ_PLAYERSTRUCT;
859
860         /* make player new king */
861         Changed = TRUE;
862         Player.p_specialtype = SC_KING;
863         mvaddstr(4, 0, "You have become king!\n");
864
865         /* let everyone else know */
866         fp = fopen(_PATH_MESS, "w");
867         fprintf(fp, "All hail the new king!");
868         fclose(fp);
869
870         /* clear all energy voids; retain location of holy grail */
871         fseek(Energyvoidfp, 0L, 0);
872         fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
873         fp = fopen(_PATH_VOID, "w");
874         fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
875         fclose(fp);
876         }
877
878     mvaddstr(6, 0, "0:Decree  ");
879 }
880 /*\f*/
881 /************************************************************************
882 /
883 / FUNCTION NAME: dotampered()
884 /
885 / FUNCTION: king and valar special options
886 /
887 / AUTHOR: E. A. Estes, 2/28/86
888 /
889 / ARGUMENTS: none
890 /
891 / RETURN VALUE: none
892 /
893 / MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(),
894 /       floor(), wmove(), drandom(), fclose(), fwrite(), sscanf(), strcmp(),
895 /       infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(),
896 /       allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid()
897 /
898 / GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr,
899 /       Databuf[], Enrgyvoid
900 /
901 / GLOBAL OUTPUTS: Other, Player, Enrgyvoid
902 /
903 / DESCRIPTION:
904 /       Tamper with other players.  Handle king/valar specific options.
905 /
906 *************************************************************************/
907
908 dotampered()
909 {
910 short   tamper;                 /* value for tampering with other players */
911 char    *option;                        /* pointer to option description */
912 double  temp1 = 0.0, temp2 = 0.0;       /* other tampering values */
913 int     ch;                             /* input */
914 long    loc;                            /* location in energy void file */
915 FILE    *fp;                            /* for opening gold file */
916
917     move(6, 0);
918     clrtoeol();
919     if (Player.p_specialtype < SC_COUNCIL && !Wizard)
920         /* king options */
921         {
922         addstr("1:Transport  2:Curse  3:Energy Void  4:Bestow  5:Collect Taxes  ");
923
924         ch = getanswer(" ", TRUE);
925         move(6, 0);
926         clrtoeol();
927         move(4, 0);
928         switch (ch)
929             {
930             case '1':   /* transport someone */
931                 tamper = T_TRANSPORT;
932                 option = "transport";
933                 break;
934
935             case '2':   /* curse another */
936                 tamper = T_CURSED;
937                 option = "curse";
938                 break;
939
940             case '3':   /* create energy void */
941                 if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT)
942                     /* can only have 20 void active at once */
943                     mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
944                 else
945                     {
946                     addstr("Enter the X Y coordinates of void ? ");
947                     getstring(Databuf, SZ_DATABUF);
948                     sscanf(Databuf, "%lf %lf", &temp1, &temp2);
949                     Enrgyvoid.ev_x = floor(temp1);
950                     Enrgyvoid.ev_y = floor(temp2);
951                     Enrgyvoid.ev_active = TRUE;
952                     writevoid(&Enrgyvoid, loc);
953                     mvaddstr(5, 0, "It is done.\n");
954                     }
955                 return;
956
957             case '4':   /* bestow gold to subject */
958                 tamper = T_BESTOW;
959                 addstr("How much gold to bestow ? ");
960                 temp1 = infloat();
961                 if (temp1 > Player.p_gold || temp1 < 0)
962                     {
963                     mvaddstr(5, 0, "You don't have that !\n");
964                     return;
965                     }
966
967                 /* adjust gold after we are sure it will be given to someone */
968                 option = "give gold to";
969                 break;
970
971             case '5':   /* collect accumulated taxes */
972                 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
973                     /* collect taxes */
974                     {
975                     fread((char *) &temp1, sizeof(double), 1, fp);
976                     fseek(fp, 0L, 0);
977                     /* clear out value */
978                     temp2 = 0.0;
979                     fwrite((char *) &temp2, sizeof(double), 1, fp);
980                     fclose(fp);
981                     }
982
983                 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
984                 Player.p_gold += floor(temp1);
985                 return;
986
987             default:
988                 return;
989             }
990         /* end of king options */
991         }
992     else
993         /* council of wise, valar, wizard options */
994         {
995         addstr("1:Heal  ");
996         if (Player.p_palantir || Wizard)
997             addstr("2:Seek Grail  ");
998         if (Player.p_specialtype == SC_VALAR || Wizard)
999             addstr("3:Throw Monster  4:Relocate  5:Bless  ");
1000         if (Wizard)
1001             addstr("6:Vaporize  ");
1002
1003         ch = getanswer(" ", TRUE);
1004         if (!Wizard)
1005             {
1006             if (ch > '2' && Player.p_specialtype != SC_VALAR)
1007                 {
1008                 ILLCMD();
1009                 return;
1010                 }
1011
1012             if (Player.p_mana < MM_INTERVENE)
1013                 {
1014                 mvaddstr(5, 0, "No mana left.\n");
1015                 return;
1016                 }
1017             else
1018                 Player.p_mana -= MM_INTERVENE;
1019             }
1020
1021         switch (ch)
1022             {
1023             case '1':   /* heal another */
1024                 tamper = T_HEAL;
1025                 option = "heal";
1026                 break;
1027
1028             case '2':   /* seek grail */
1029                 if (Player.p_palantir)
1030                     /* need a palantir to seek */
1031                     {
1032                     fseek(Energyvoidfp, 0L, 0);
1033                     fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
1034                     temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
1035                     temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0);  /* add some error */
1036                     mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
1037                     }
1038                 else
1039                     /* no palantir */
1040                     mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
1041                 return;
1042
1043             case '3':   /* lob monster at someone */
1044                 mvaddstr(4, 0, "Which monster [0-99] ? ");
1045                 temp1 = infloat();
1046                 temp1 = MAX(0.0, MIN(99.0, temp1));
1047                 tamper = T_MONSTER;
1048                 option = "throw a monster at";
1049                 break;
1050
1051             case '4':   /* move another player */
1052                 mvaddstr(4, 0, "New X Y coordinates ? ");
1053                 getstring(Databuf, SZ_DATABUF);
1054                 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
1055                 tamper = T_RELOCATE;
1056                 option = "relocate";
1057                 break;
1058
1059             case '5':   /* bless a player */
1060                 tamper = T_BLESSED;
1061                 option = "bless";
1062                 break;
1063
1064             case '6':   /* kill off a player */
1065                 if (Wizard)
1066                     {
1067                     tamper = T_VAPORIZED;
1068                     option = "vaporize";
1069                     break;
1070                     }
1071                 else
1072                     return;
1073
1074             default:
1075                 return;
1076             }
1077
1078         /* adjust age after we are sure intervention will be done */
1079         /* end of valar, etc. options */
1080         }
1081
1082     for (;;)
1083         /* prompt for player to affect */
1084         {
1085         mvprintw(4, 0, "Who do you want to %s ? ", option);
1086         getstring(Databuf, SZ_DATABUF);
1087         truncstring(Databuf);
1088
1089         if (Databuf[0] == '\0')
1090             userlist(TRUE);
1091         else
1092             break;
1093         }
1094
1095     if (strcmp(Player.p_name, Databuf) != 0)
1096         /* name other than self */
1097         {
1098         if ((loc = findname(Databuf, &Other)) >= 0L)
1099             {
1100             if (Other.p_tampered != T_OFF)
1101                 {
1102                 mvaddstr(5, 0, "That person has something pending already.\n");
1103                 return;
1104                 }
1105             else
1106                 {
1107                 if (tamper == T_RELOCATE
1108                     && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
1109                     && !Wizard)
1110                     mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
1111                 else
1112                     {
1113                     if (tamper == T_BESTOW) Player.p_gold -= floor(temp1);
1114                     if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
1115                         tamper == T_RELOCATE || tamper == T_BLESSED))
1116                                 Player.p_age += N_AGE;  /* age penalty */
1117                     Other.p_tampered = tamper;
1118                     Other.p_1scratch = floor(temp1);
1119                     Other.p_2scratch = floor(temp2);
1120                     writerecord(&Other, loc);
1121                     mvaddstr(5, 0, "It is done.\n");
1122                     }
1123                 return;
1124                 }
1125             }
1126         else
1127             /* player not found */
1128             mvaddstr(5, 0, "There is no one by that name.\n");
1129         }
1130     else
1131         /* self */
1132         mvaddstr(5, 0, "You may not do it to yourself!\n");
1133 }
1134 /*\f*/
1135 /************************************************************************
1136 /
1137 / FUNCTION NAME: writevoid()
1138 /
1139 / FUNCTION: update energy void entry in energy void file
1140 /
1141 / AUTHOR: E. A. Estes, 12/4/85
1142 /
1143 / ARGUMENTS:
1144 /       struct energyvoid *vp - pointer to structure to write to file
1145 /       long loc - location in file to update
1146 /
1147 / RETURN VALUE: none
1148 /
1149 / MODULES CALLED: fseek(), fwrite(), fflush()
1150 /
1151 / GLOBAL INPUTS: *Energyvoidfp
1152 /
1153 / GLOBAL OUTPUTS: none
1154 /
1155 / DESCRIPTION:
1156 /       Write out energy void structure at specified location.
1157 /
1158 *************************************************************************/
1159
1160 writevoid(vp, loc)
1161 register struct energyvoid      *vp;
1162 long    loc;
1163 {
1164
1165     fseek(Energyvoidfp, loc, 0);
1166     fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
1167     fflush(Energyvoidfp);
1168     fseek(Energyvoidfp, 0L, 0);
1169 }
1170 /*\f*/
1171 /************************************************************************
1172 /
1173 / FUNCTION NAME: allocvoid()
1174 /
1175 / FUNCTION: allocate space for a new energy void
1176 /
1177 / AUTHOR: E. A. Estes, 12/4/85
1178 /
1179 / ARGUMENTS: none
1180 /
1181 / RETURN VALUE: location of new energy void space
1182 /
1183 / MODULES CALLED: fread(), fseek()
1184 /
1185 / GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
1186 /
1187 / GLOBAL OUTPUTS: none
1188 /
1189 / DESCRIPTION:
1190 /       Search energy void file for an inactive entry and return its
1191 /       location.
1192 /       If no inactive ones are found, return one more than last location.
1193 /
1194 *************************************************************************/
1195
1196 long
1197 allocvoid()
1198 {
1199 long    loc = 0L;               /* location of new energy void */
1200
1201     fseek(Energyvoidfp, 0L, 0);
1202     while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
1203         if (Enrgyvoid.ev_active)
1204             loc += SZ_VOIDSTRUCT;
1205         else
1206             break;
1207
1208     return(loc);
1209 }