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