Install input{,-event-types}.h to /usr/include/compat/linux too.
[dragonfly.git] / games / phantasia / interplayer.c
blob2b16c75a1da8e773ad6e282f84f32ab1713b0745
1 /* $NetBSD: interplayer.c,v 1.12 2009/08/31 08:27:16 dholland Exp $ */
3 /*
4 * interplayer.c - player to player routines for Phantasia
5 */
7 #include <string.h>
8 #include "include.h"
11 static size_t allocvoid(void);
12 static void battleplayer(long);
13 static void myturn(void);
14 static void tampered(int, double, double);
15 static void writevoid(struct energyvoid *, long);
18 * FUNCTION: check to see if current player should battle another
20 * GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
22 * GLOBAL OUTPUTS: Users
24 * DESCRIPTION:
25 * Seach player file for a foe at the same coordinates as the
26 * current player.
27 * Also update user count.
30 void
31 checkbattle(void)
33 long foeloc = 0L; /* location in file of person to fight */
35 Users = 0;
36 fseek(Playersfp, 0L, SEEK_SET);
38 while (fread((char *)&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
39 if (Other.p_status != S_OFF
40 && Other.p_status != S_NOTUSED
41 && Other.p_status != S_HUNGUP
42 && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR)) {
43 /* player is on and not a cloaked valar */
44 ++Users;
46 if (Player.p_x == Other.p_x
47 && Player.p_y == Other.p_y
48 /* same coordinates */
49 && foeloc != Fileloc
50 /* not self */
51 && Player.p_status == S_PLAYING
52 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
53 /* both are playing */
54 && Other.p_specialtype != SC_VALAR
55 && Player.p_specialtype != SC_VALAR) {
56 /* neither is valar */
57 battleplayer(foeloc);
58 return;
61 foeloc += SZ_PLAYERSTRUCT;
66 * FUNCTION: inter-terminal battle with another player
68 * ARGUMENTS:
69 * long foeplace - location in player file of person to battle
71 * GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr,
72 * Fileloc, *Enemyname
74 * GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
76 * DESCRIPTION:
77 * Inter-terminal battle is a very fragile and slightly klugy thing.
78 * At any time, one player is master and the other is slave.
79 * We pick who is master first by speed and level. After that,
80 * the slave waits for the master to relinquish its turn, and
81 * the slave becomes master, and so on.
83 * The items in the player structure which control the handshake are:
84 * p_tampered:
85 * master increments this to relinquish control
86 * p_istat:
87 * master sets this to specify particular action
88 * p_1scratch:
89 * set to total damage inflicted so far; changes to indicate action
92 static void
93 battleplayer(long foeplace)
95 double dtemp; /* for temporary calculations */
96 double oldhits = 0.0; /* previous damage inflicted by foe */
97 int loop; /* for timing out */
98 int ch; /* input */
99 short oldtampered; /* old value of foe's p_tampered */
101 Lines = 8;
102 Luckout = FALSE;
103 mvaddstr(4, 0, "Preparing for battle!\n");
104 refresh();
106 #ifdef SYS5
107 flushinp();
108 #endif
110 /* set up variables, file, etc. */
111 Player.p_status = S_INBATTLE;
112 Shield = Player.p_energy;
114 /* if p_tampered is not 0, someone else may try to change it (king, etc.) */
115 Player.p_tampered = oldtampered = 1;
116 Player.p_1scratch = 0.0;
117 Player.p_istat = I_OFF;
119 readrecord(&Other, foeplace);
120 if (fabs(Player.p_level - Other.p_level) > 20.0) {
121 /* see if players are greatly mismatched */
122 dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
123 if (dtemp < -0.5)
124 /* foe outweighs this one */
125 Player.p_speed *= 2.0;
127 writerecord(&Player, Fileloc); /* write out all our info */
129 if (Player.p_blindness)
130 Enemyname = "someone";
131 else
132 Enemyname = Other.p_name;
134 mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level);
135 refresh();
137 for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop) {
138 /* wait for foe to respond */
139 readrecord(&Other, foeplace);
140 sleep(1);
143 if (Other.p_status != S_INBATTLE) {
144 /* foe did not respond */
145 mvprintw(5, 0, "%s is not responding.\n", Enemyname);
146 goto LEAVE;
148 /* else, we are ready to battle */
150 move(4, 0);
151 clrtoeol();
154 * determine who is first master
155 * if neither player is faster, check level
156 * if neither level is greater, battle is not allowed
157 * (this should never happen, but we have to handle it)
159 if (Player.p_speed > Other.p_speed)
160 Foestrikes = FALSE;
161 else if (Other.p_speed > Player.p_speed)
162 Foestrikes = TRUE;
163 else if (Player.p_level > Other.p_level)
164 Foestrikes = FALSE;
165 else if (Other.p_level > Player.p_level)
166 Foestrikes = TRUE;
167 else {
168 /* no one is faster */
169 printw("You can't fight %s yet.", Enemyname);
170 goto LEAVE;
173 for (;;) {
174 displaystats();
175 readmessage();
176 mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */
178 if (!Foestrikes)
179 /* take action against foe */
180 myturn();
181 else {
182 /* wait for foe to take action */
183 mvaddstr(4, 0, "Waiting...\n");
184 clrtoeol();
185 refresh();
187 for (loop = 0; loop < 20; ++loop) {
188 /* wait for foe to act */
189 readrecord(&Other, foeplace);
190 if (Other.p_1scratch != oldhits)
191 /* p_1scratch changes to indicate action */
192 break;
193 else {
194 /* wait and try again */
195 sleep(1);
196 addch('.');
197 refresh();
201 if (Other.p_1scratch == oldhits) {
202 /* timeout */
203 mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
204 ch = getanswer("NY", FALSE);
205 move(22, 0);
206 clrtobot();
207 if (ch == 'Y')
208 continue;
209 else
210 break;
211 } else {
212 /* foe took action */
213 switch (Other.p_istat) {
214 case I_RAN: /* foe ran away */
215 mvprintw(Lines++, 0, "%s ran away!", Enemyname);
216 break;
218 case I_STUCK: /* foe tried to run, but couldn't */
219 mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
220 break;
222 case I_BLEWIT: /* foe tried to luckout, but didn't */
223 mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
224 break;
226 default:
227 dtemp = Other.p_1scratch - oldhits;
228 mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
229 Shield -= dtemp;
230 break;
233 oldhits = Other.p_1scratch; /* keep track of old hits */
235 if (Other.p_tampered != oldtampered) {
236 /* p_tampered changes to relinquish turn */
237 oldtampered = Other.p_tampered;
238 Foestrikes = FALSE;
243 /* decide what happens next */
244 refresh();
245 if (Lines > LINES - 2) {
246 more(Lines);
247 move(Lines = 8, 0);
248 clrtobot();
251 if (Other.p_istat == I_KILLED || Shield < 0.0) {
252 /* we died */
253 Shield = -2.0; /* insure this value is negative */
254 break;
257 if (Player.p_istat == I_KILLED) {
258 /* we killed foe; award treasre */
259 mvprintw(Lines++, 0, "You killed %s!", Enemyname);
260 Player.p_experience += Other.p_experience;
261 Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
262 Player.p_amulets += Other.p_amulets;
263 Player.p_charms += Other.p_charms;
264 collecttaxes(Other.p_gold, Other.p_gems);
265 Player.p_sword = MAX(Player.p_sword, Other.p_sword);
266 Player.p_shield = MAX(Player.p_shield, Other.p_shield);
267 Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
268 if (Other.p_virgin && !Player.p_virgin) {
269 mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? ");
270 if ((ch = getanswer("YN", FALSE)) == 'Y')
271 Player.p_virgin = TRUE;
272 else {
273 ++Player.p_sin;
274 Player.p_experience += 8000.0;
277 sleep(3); /* give other person time to die */
278 break;
279 } else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
280 /* either player ran away */
281 break;
284 LEAVE:
285 /* clean up things and leave */
286 writerecord(&Player, Fileloc); /* update a final time */
287 altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
288 Player.p_energy = Shield; /* set energy to actual value */
289 Player.p_tampered = T_OFF; /* clear p_tampered */
291 more(Lines); /* pause */
293 move(4, 0);
294 clrtobot(); /* clear bottom area of screen */
296 if (Player.p_energy < 0.0)
297 /* we are dead */
298 death("Interterminal battle");
302 * FUNCTION: process players action against foe in battle
304 * GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout,
305 * *Enemyname
307 * GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
309 * DESCRIPTION:
310 * Take action action against foe, and decide who is master
311 * for next iteration.
314 static void
315 myturn(void)
317 double dtemp; /* for temporary calculations */
318 int ch; /* input */
320 mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
321 if (Luckout)
322 clrtoeol();
323 else
324 addstr("4:Luckout ");
326 ch = inputoption();
327 move(Lines = 8, 0);
328 clrtobot();
330 switch (ch) {
331 default: /* fight */
332 dtemp = ROLL(2.0, Player.p_might);
333 HIT:
334 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
335 Player.p_sin += 0.5;
336 Player.p_1scratch += dtemp;
337 Player.p_istat = I_OFF;
338 break;
340 case '2': /* run away */
341 /* change this to indicate action */
342 Player.p_1scratch -= 1.0;
343 if (drandom() > 0.25) {
344 mvaddstr(Lines++, 0, "You got away!");
345 Player.p_istat = I_RAN;
346 } else {
347 mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
348 Player.p_istat = I_STUCK;
350 break;
352 case '3': /* power blast */
353 dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
354 Player.p_mana -= dtemp;
355 dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
356 mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
357 goto HIT;
359 case '4': /* luckout */
360 if (Luckout || drandom() > 0.1) {
361 if (Luckout)
362 mvaddstr(Lines++, 0, "You already tried that!");
363 else {
364 mvaddstr(Lines++, 0, "Not this time . . .");
365 Luckout = TRUE;
368 Player.p_1scratch -= 1.0;
369 Player.p_istat = I_BLEWIT;
370 } else {
371 mvaddstr(Lines++, 0, "You just lucked out!");
372 Player.p_1scratch = Other.p_energy * 1.1;
374 break;
377 refresh();
378 Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */
380 if (Player.p_1scratch > Other.p_energy)
381 Player.p_istat = I_KILLED;
382 else if (drandom() * Player.p_speed < drandom() * Other.p_speed) {
383 /* relinquish control */
384 ++Player.p_tampered;
385 Foestrikes = TRUE;
388 writerecord(&Player, Fileloc); /* let foe know what we did */
392 * FUNCTION: check if current player has been tampered with
394 * GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
396 * GLOBAL OUTPUTS: Enrgyvoid
398 * DESCRIPTION:
399 * Check for energy voids, holy grail, and tampering by other
400 * players.
403 void
404 checktampered(void)
406 long loc = 0L; /* location in energy void file */
408 /* first check for energy voids */
409 fseek(Energyvoidfp, 0L, SEEK_SET);
410 while (fread((char *)&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
411 if (Enrgyvoid.ev_active
412 && Enrgyvoid.ev_x == Player.p_x
413 && Enrgyvoid.ev_y == Player.p_y) {
414 /* sitting on one */
415 if (loc > 0L) {
416 /* not the holy grail; inactivate energy void */
417 Enrgyvoid.ev_active = FALSE;
418 writevoid(&Enrgyvoid, loc);
419 tampered(T_NRGVOID, 0.0, 0.0);
420 } else if (Player.p_status != S_CLOAKED)
421 /* holy grail */
422 tampered(T_GRAIL, 0.0, 0.0);
423 break;
424 } else
425 loc += SZ_VOIDSTRUCT;
427 /* now check for other things */
428 readrecord(&Other, Fileloc);
429 if (Other.p_tampered != T_OFF)
430 tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
434 * FUNCTION: take care of tampering by other players
436 * ARGUMENTS:
437 * int what - what type of tampering
438 * double arg1, arg2 - rest of tampering info
440 * GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
442 * GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
444 * DESCRIPTION:
445 * Take care of energy voids, holy grail, decree and intervention
446 * action on current player.
449 static void
450 tampered(int what, double arg1, double arg2)
452 long loc; /* location in file of other players */
454 Changed = TRUE;
455 move(4, 0);
457 Player.p_tampered = T_OFF; /* no longer tampered with */
459 switch (what) {
460 case T_NRGVOID:
461 addstr("You've hit an energy void !\n");
462 Player.p_mana /= 3.0;
463 Player.p_energy /= 2.0;
464 Player.p_gold = floor(Player.p_gold / 1.25) + 0.1;
465 altercoordinates(0.0, 0.0, A_NEAR);
466 break;
468 case T_TRANSPORT:
469 addstr("The king transported you ! ");
470 if (Player.p_charms > 0) {
471 addstr("But your charm saved you. . .\n");
472 --Player.p_charms;
473 } else {
474 altercoordinates(0.0, 0.0, A_FAR);
475 addch('\n');
477 break;
479 case T_BESTOW:
480 printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
481 Player.p_gold += arg1;
482 break;
484 case T_CURSED:
485 addstr("You've been cursed ! ");
486 if (Player.p_blessing) {
487 addstr("But your blessing saved you. . .\n");
488 Player.p_blessing = FALSE;
489 } else {
490 addch('\n');
491 Player.p_poison += 2.0;
492 Player.p_energy = 10.0;
493 Player.p_maxenergy *= 0.95;
494 Player.p_status = S_PLAYING; /* no longer cloaked */
496 break;
498 case T_VAPORIZED:
499 addstr("You have been vaporized!\n");
500 more(7);
501 death("Vaporization");
502 break;
504 case T_MONSTER:
505 addstr("The Valar zapped you with a monster!\n");
506 more(7);
507 encounter((int)arg1);
508 return;
510 case T_BLESSED:
511 addstr("The Valar has blessed you!\n");
512 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
513 Player.p_mana += 500.0;
514 Player.p_strength += 0.5;
515 Player.p_brains += 0.5;
516 Player.p_magiclvl += 0.5;
517 Player.p_poison = MIN(0.5, Player.p_poison);
518 break;
520 case T_RELOCATE:
521 addstr("You've been relocated. . .\n");
522 altercoordinates(arg1, arg2, A_FORCED);
523 break;
525 case T_HEAL:
526 addstr("You've been healed!\n");
527 Player.p_poison -= 0.25;
528 Player.p_energy = Player.p_maxenergy + Player.p_shield;
529 break;
531 case T_EXVALAR:
532 addstr("You are no longer Valar!\n");
533 Player.p_specialtype = SC_COUNCIL;
534 break;
536 case T_GRAIL:
537 addstr("You have found The Holy Grail!!\n");
538 if (Player.p_specialtype < SC_COUNCIL) {
539 /* must be council of wise to behold grail */
540 addstr("However, you are not experienced enough to behold it.\n");
541 Player.p_sin *= Player.p_sin;
542 Player.p_mana += 1000;
543 } else if (Player.p_specialtype == SC_VALAR ||
544 Player.p_specialtype == SC_EXVALAR) {
545 addstr("You have made it to the position of Valar once already.\n");
546 addstr("The Grail is of no more use to you now.\n");
547 } else {
548 addstr("It is now time to see if you are worthy to behold it. . .\n");
549 refresh();
550 sleep(4);
552 if (drandom() / 2.0 < Player.p_sin) {
553 addstr("You have failed!\n");
554 Player.p_strength =
555 Player.p_mana =
556 Player.p_energy =
557 Player.p_maxenergy =
558 Player.p_magiclvl =
559 Player.p_brains =
560 Player.p_experience =
561 Player.p_quickness = 1.0;
563 altercoordinates(1.0, 1.0, A_FORCED);
564 Player.p_level = 0.0;
565 } else {
566 addstr("You made to position of Valar!\n");
567 Player.p_specialtype = SC_VALAR;
568 Player.p_lives = 5;
569 fseek(Playersfp, 0L, SEEK_SET);
570 loc = 0L;
571 while (fread((char *)&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
572 /* search for existing valar */
573 if (Other.p_specialtype == SC_VALAR &&
574 Other.p_status != S_NOTUSED) {
575 /* found old valar */
576 Other.p_tampered = T_EXVALAR;
577 writerecord(&Other, loc);
578 break;
579 } else
580 loc += SZ_PLAYERSTRUCT;
584 /* move grail to new location */
585 Enrgyvoid.ev_active = TRUE;
586 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
587 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
588 writevoid(&Enrgyvoid, 0L);
589 break;
591 refresh();
592 sleep(2);
596 * FUNCTION: print list of players and locations
598 * ARGUMENTS:
599 * bool ingameflag - set if called while playing
601 * GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
603 * DESCRIPTION:
604 * We can only see the coordinate of those closer to the origin
605 * from us.
606 * Kings and council of the wise can see and can be seen by everyone.
607 * Palantirs are good for seeing everyone; and the valar can use
608 * one to see through a 'cloak' spell.
609 * The valar has no coordinates, and is completely invisible if
610 * cloaked.
613 void
614 userlist(bool ingameflag)
616 int numusers = 0; /* number of users on file */
618 if (ingameflag && Player.p_blindness) {
619 mvaddstr(8, 0, "You cannot see anyone.\n");
620 return;
623 fseek(Playersfp, 0L, SEEK_SET);
624 mvaddstr(8, 0,
625 "Name X Y Lvl Type Login Status\n");
627 while (fread((char *)&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
628 if (Other.p_status == S_NOTUSED
629 /* record is unused */
630 || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED)) {
631 /* cloaked valar */
632 if (!Wizard)
633 /* wizard can see everything on file */
634 continue;
637 ++numusers;
639 if (ingameflag &&
640 /* must be playing for the rest of these conditions */
641 (Player.p_specialtype >= SC_KING
642 /* kings and higher can see others */
643 || Other.p_specialtype >= SC_KING
644 /* kings and higher can be seen by others */
645 || Circle >= CIRCLE(Other.p_x, Other.p_y)
646 /* those nearer the origin can be seen */
647 || Player.p_palantir)
648 /* palantir enables one to see others */
649 && (Other.p_status != S_CLOAKED
650 || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
651 /* not cloaked; valar can see through cloak with a palantir */
652 && Other.p_specialtype != SC_VALAR)
653 /* not a valar */
654 /* coordinates should be printed */
655 printw("%-20s %8.0f %8.0f ",
656 Other.p_name, Other.p_x, Other.p_y);
657 else
658 /* cannot see player's coordinates */
659 printw("%-20s %19.19s ",
660 Other.p_name, descrlocation(&Other, TRUE));
662 printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
663 Other.p_login, descrstatus(&Other));
665 if ((numusers % (LINES - 10)) == 0) {
666 more(LINES - 1);
667 move(9, 0);
668 clrtobot();
672 printw("Total players on file = %d\n", numusers);
673 refresh();
677 * FUNCTION: king stuff upon entering throne
679 * GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr,
680 * Enrgyvoid, *Playersfp
682 * GLOBAL OUTPUTS: Other, Player, Changed
684 * DESCRIPTION:
685 * If player is not already king, make him/her so if the old king
686 * is not playing.
687 * Clear energy voids with new king.
688 * Print 'decree' prompt.
691 void
692 throneroom(void)
694 FILE *fp; /* to clear energy voids */
695 long loc = 0L; /* location of old king in player file */
697 if (Player.p_specialtype < SC_KING) {
698 /* not already king -- assumes crown */
699 fseek(Playersfp, 0L, SEEK_SET);
700 while (fread((char *)&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
701 if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED) {
702 /* found old king */
703 if (Other.p_status != S_OFF) {
704 /* old king is playing */
705 mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n");
706 altercoordinates(0.0, 0.0, A_NEAR);
707 move(6, 0);
708 return;
709 } else {
710 /* old king is not playing - remove him/her */
711 Other.p_specialtype = SC_NONE;
712 if (Other.p_crowns)
713 --Other.p_crowns;
714 writerecord(&Other, loc);
715 break;
717 } else
718 loc += SZ_PLAYERSTRUCT;
720 /* make player new king */
721 Changed = TRUE;
722 Player.p_specialtype = SC_KING;
723 mvaddstr(4, 0, "You have become king!\n");
725 /* let everyone else know */
726 fp = fopen(_PATH_MESS, "w");
727 fprintf(fp, "All hail the new king!");
728 fclose(fp);
730 /* clear all energy voids; retain location of holy grail */
731 fseek(Energyvoidfp, 0L, SEEK_SET);
732 fread((char *)&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
733 fp = fopen(_PATH_VOID, "w");
734 fwrite((char *)&Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
735 fclose(fp);
738 mvaddstr(6, 0, "0:Decree ");
742 * FUNCTION: king and valar special options
744 * GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr,
745 * Databuf[], Enrgyvoid
747 * GLOBAL OUTPUTS: Other, Player, Enrgyvoid
749 * DESCRIPTION:
750 * Tamper with other players. Handle king/valar specific options.
753 void
754 dotampered(void)
756 short tamper; /* value for tampering with other players */
757 const char *option; /* pointer to option description */
758 double temp1 = 0.0, temp2 = 0.0; /* other tampering values */
759 int ch; /* input */
760 long loc; /* location in energy void file */
761 FILE *fp; /* for opening gold file */
763 move(6, 0);
764 clrtoeol();
765 if (Player.p_specialtype < SC_COUNCIL && !Wizard) {
766 /* king options */
767 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
769 ch = getanswer(" ", TRUE);
770 move(6, 0);
771 clrtoeol();
772 move(4, 0);
773 switch (ch) {
774 case '1': /* transport someone */
775 tamper = T_TRANSPORT;
776 option = "transport";
777 break;
779 case '2': /* curse another */
780 tamper = T_CURSED;
781 option = "curse";
782 break;
784 case '3': /* create energy void */
785 if ((loc = allocvoid()) > 20L * (long)SZ_VOIDSTRUCT)
786 /* can only have 20 void active at once */
787 mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
788 else {
789 addstr("Enter the X Y coordinates of void ? ");
790 getstring(Databuf, SZ_DATABUF);
791 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
792 Enrgyvoid.ev_x = floor(temp1);
793 Enrgyvoid.ev_y = floor(temp2);
794 Enrgyvoid.ev_active = TRUE;
795 writevoid(&Enrgyvoid, loc);
796 mvaddstr(5, 0, "It is done.\n");
798 return;
800 case '4': /* bestow gold to subject */
801 tamper = T_BESTOW;
802 addstr("How much gold to bestow ? ");
803 temp1 = infloat();
804 if (temp1 > Player.p_gold || temp1 < 0) {
805 mvaddstr(5, 0, "You don't have that !\n");
806 return;
809 /* adjust gold after we are sure it will be given to someone */
810 option = "give gold to";
811 break;
813 case '5': /* collect accumulated taxes */
814 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL) {
815 /* collect taxes */
816 fread((char *)&temp1, sizeof(double), 1, fp);
817 fseek(fp, 0L, SEEK_SET);
818 /* clear out value */
819 temp2 = 0.0;
820 fwrite((char *)&temp2, sizeof(double), 1, fp);
821 fclose(fp);
824 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
825 Player.p_gold += floor(temp1);
826 return;
828 default:
829 return;
831 /* end of king options */
832 } else {
833 /* council of wise, valar, wizard options */
834 addstr("1:Heal ");
835 if (Player.p_palantir || Wizard)
836 addstr("2:Seek Grail ");
837 if (Player.p_specialtype == SC_VALAR || Wizard)
838 addstr("3:Throw Monster 4:Relocate 5:Bless ");
839 if (Wizard)
840 addstr("6:Vaporize ");
842 ch = getanswer(" ", TRUE);
843 if (!Wizard) {
844 if (ch > '2' && Player.p_specialtype != SC_VALAR) {
845 ILLCMD();
846 return;
849 if (Player.p_mana < MM_INTERVENE) {
850 mvaddstr(5, 0, "No mana left.\n");
851 return;
852 } else
853 Player.p_mana -= MM_INTERVENE;
856 switch (ch) {
857 case '1': /* heal another */
858 tamper = T_HEAL;
859 option = "heal";
860 break;
862 case '2': /* seek grail */
863 if (Player.p_palantir) {
864 /* need a palantir to seek */
865 fseek(Energyvoidfp, 0L, SEEK_SET);
866 fread((char *)&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
867 temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
868 temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
869 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
870 } else
871 /* no palantir */
872 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
873 return;
875 case '3': /* lob monster at someone */
876 mvaddstr(4, 0, "Which monster [0-99] ? ");
877 temp1 = infloat();
878 temp1 = MAX(0.0, MIN(99.0, temp1));
879 tamper = T_MONSTER;
880 option = "throw a monster at";
881 break;
883 case '4': /* move another player */
884 mvaddstr(4, 0, "New X Y coordinates ? ");
885 getstring(Databuf, SZ_DATABUF);
886 sscanf(Databuf, "%lf %lf", &temp1, &temp2);
887 tamper = T_RELOCATE;
888 option = "relocate";
889 break;
891 case '5': /* bless a player */
892 tamper = T_BLESSED;
893 option = "bless";
894 break;
896 case '6': /* kill off a player */
897 if (Wizard) {
898 tamper = T_VAPORIZED;
899 option = "vaporize";
900 break;
901 } else
902 return;
904 default:
905 return;
908 /* adjust age after we are sure intervention will be done */
909 /* end of valar, etc. options */
912 for (;;) {
913 /* prompt for player to affect */
914 mvprintw(4, 0, "Who do you want to %s ? ", option);
915 getstring(Databuf, SZ_DATABUF);
916 truncstring(Databuf);
918 if (Databuf[0] == '\0')
919 userlist(TRUE);
920 else
921 break;
924 if (strcmp(Player.p_name, Databuf) != 0) {
925 /* name other than self */
926 if ((loc = findname(Databuf, &Other)) >= 0L) {
927 if (Other.p_tampered != T_OFF) {
928 mvaddstr(5, 0, "That person has something pending already.\n");
929 return;
930 } else {
931 if (tamper == T_RELOCATE
932 && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
933 && !Wizard)
934 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
935 else {
936 if (tamper == T_BESTOW)
937 Player.p_gold -= floor(temp1);
938 if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
939 tamper == T_RELOCATE || tamper == T_BLESSED))
940 Player.p_age += N_AGE; /* age penalty */
941 Other.p_tampered = tamper;
942 Other.p_1scratch = floor(temp1);
943 Other.p_2scratch = floor(temp2);
944 writerecord(&Other, loc);
945 mvaddstr(5, 0, "It is done.\n");
947 return;
949 } else
950 /* player not found */
951 mvaddstr(5, 0, "There is no one by that name.\n");
952 } else
953 /* self */
954 mvaddstr(5, 0, "You may not do it to yourself!\n");
958 * FUNCTION: update energy void entry in energy void file
960 * ARGUMENTS:
961 * struct energyvoid *vp - pointer to structure to write to file
962 * long loc - location in file to update
964 * GLOBAL INPUTS: *Energyvoidfp
966 * DESCRIPTION:
967 * Write out energy void structure at specified location.
970 static void
971 writevoid(struct energyvoid *vp, long loc)
973 fseek(Energyvoidfp, loc, SEEK_SET);
974 fwrite((char *)vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
975 fflush(Energyvoidfp);
976 fseek(Energyvoidfp, 0L, SEEK_SET);
980 * FUNCTION: allocate space for a new energy void
982 * RETURN VALUE: location of new energy void space
984 * GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
986 * DESCRIPTION:
987 * Search energy void file for an inactive entry and return its
988 * location.
989 * If no inactive ones are found, return one more than last location.
992 static size_t
993 allocvoid(void)
995 size_t loc = 0; /* location of new energy void */
997 fseek(Energyvoidfp, 0L, SEEK_SET);
998 while (fread((char *)&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
999 if (Enrgyvoid.ev_active)
1000 loc += SZ_VOIDSTRUCT;
1001 else
1002 break;
1004 return (loc);