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