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